Add Nicira vendor extension action NXAST_DEC_TTL_CNT_IDS.
[sliver-openvswitch.git] / lib / ofp-parse.c
index 6236e50..e5f5ea0 100644 (file)
@@ -278,6 +278,41 @@ parse_controller(struct ofpbuf *b, char *arg)
     }
 }
 
+static void
+parse_dec_ttl(struct ofpbuf *b, char *arg)
+{
+    struct ofpact_cnt_ids *ids;
+
+    ids = ofpact_put_DEC_TTL(b);
+
+    if (*arg == '\0') {
+        uint16_t id = 0;
+
+        ids->ofpact.compat = OFPUTIL_NXAST_DEC_TTL;
+        ofpbuf_put(b, &id, sizeof id);
+        ids = b->l2;
+        ids->n_controllers++;
+    } else {
+        char *cntr;
+
+        ids->ofpact.compat = OFPUTIL_NXAST_DEC_TTL_CNT_IDS;
+        for (cntr = strtok_r(arg, ", ", &arg); cntr != NULL;
+             cntr = strtok_r(NULL, ", ", &arg)) {
+            uint16_t id = atoi(cntr);
+
+            ofpbuf_put(b, &id, sizeof id);
+            ids = b->l2;
+            ids->n_controllers++;
+        }
+        if (!ids->n_controllers) {
+            ovs_fatal(0, "dec_ttl_cnt_ids: expected at least one controller "
+                      "id.");
+        }
+
+    }
+    ofpact_update_len(b, &ids->ofpact);
+}
+
 static void
 parse_named_action(enum ofputil_action_code code, const struct flow *flow,
                    char *arg, struct ofpbuf *ofpacts)
@@ -293,10 +328,12 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
         NOT_REACHED();
 
     case OFPUTIL_OFPAT10_OUTPUT:
+    case OFPUTIL_OFPAT11_OUTPUT:
         parse_output(arg, ofpacts);
         break;
 
     case OFPUTIL_OFPAT10_SET_VLAN_VID:
+    case OFPUTIL_OFPAT11_SET_VLAN_VID:
         vid = str_to_u32(arg);
         if (vid & ~VLAN_VID_MASK) {
             ovs_fatal(0, "%s: not a valid VLAN VID", arg);
@@ -305,6 +342,7 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
         break;
 
     case OFPUTIL_OFPAT10_SET_VLAN_PCP:
+    case OFPUTIL_OFPAT11_SET_VLAN_PCP:
         pcp = str_to_u32(arg);
         if (pcp & ~7) {
             ovs_fatal(0, "%s: not a valid VLAN PCP", arg);
@@ -317,24 +355,29 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
         break;
 
     case OFPUTIL_OFPAT10_SET_DL_SRC:
+    case OFPUTIL_OFPAT11_SET_DL_SRC:
         str_to_mac(arg, ofpact_put_SET_ETH_SRC(ofpacts)->mac);
         break;
 
     case OFPUTIL_OFPAT10_SET_DL_DST:
+    case OFPUTIL_OFPAT11_SET_DL_DST:
         str_to_mac(arg, ofpact_put_SET_ETH_DST(ofpacts)->mac);
         break;
 
     case OFPUTIL_OFPAT10_SET_NW_SRC:
+    case OFPUTIL_OFPAT11_SET_NW_SRC:
         str_to_ip(arg, &ip);
         ofpact_put_SET_IPV4_SRC(ofpacts)->ipv4 = ip;
         break;
 
     case OFPUTIL_OFPAT10_SET_NW_DST:
+    case OFPUTIL_OFPAT11_SET_NW_DST:
         str_to_ip(arg, &ip);
         ofpact_put_SET_IPV4_DST(ofpacts)->ipv4 = ip;
         break;
 
     case OFPUTIL_OFPAT10_SET_NW_TOS:
+    case OFPUTIL_OFPAT11_SET_NW_TOS:
         tos = str_to_u32(arg);
         if (tos & ~IP_DSCP_MASK) {
             ovs_fatal(0, "%s: not a valid TOS", arg);
@@ -343,10 +386,12 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
         break;
 
     case OFPUTIL_OFPAT10_SET_TP_SRC:
+    case OFPUTIL_OFPAT11_SET_TP_SRC:
         ofpact_put_SET_L4_SRC_PORT(ofpacts)->port = str_to_u32(arg);
         break;
 
     case OFPUTIL_OFPAT10_SET_TP_DST:
+    case OFPUTIL_OFPAT11_SET_TP_DST:
         ofpact_put_SET_L4_DST_PORT(ofpacts)->port = str_to_u32(arg);
         break;
 
@@ -403,6 +448,7 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
 
     case OFPUTIL_NXAST_RESUBMIT_TABLE:
     case OFPUTIL_NXAST_OUTPUT_REG:
+    case OFPUTIL_NXAST_DEC_TTL_CNT_IDS:
         NOT_REACHED();
 
     case OFPUTIL_NXAST_LEARN:
@@ -414,7 +460,7 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
         break;
 
     case OFPUTIL_NXAST_DEC_TTL:
-        ofpact_put_DEC_TTL(ofpacts);
+        parse_dec_ttl(ofpacts, arg);
         break;
 
     case OFPUTIL_NXAST_FIN_TIMEOUT:
@@ -690,6 +736,68 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
     free(string);
 }
 
+/* Convert 'str_' (as described in the documentation for the "monitor" command
+ * in the ovs-ofctl man page) into 'fmr'. */
+void
+parse_flow_monitor_request(struct ofputil_flow_monitor_request *fmr,
+                           const char *str_)
+{
+    static uint32_t id;
+
+    char *string = xstrdup(str_);
+    char *save_ptr = NULL;
+    char *name;
+
+    fmr->id = id++;
+    fmr->flags = (NXFMF_INITIAL | NXFMF_ADD | NXFMF_DELETE | NXFMF_MODIFY
+                  | NXFMF_OWN | NXFMF_ACTIONS);
+    fmr->out_port = OFPP_NONE;
+    fmr->table_id = 0xff;
+    cls_rule_init_catchall(&fmr->match, 0);
+
+    for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
+         name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
+        const struct protocol *p;
+
+        if (!strcmp(name, "!initial")) {
+            fmr->flags &= ~NXFMF_INITIAL;
+        } else if (!strcmp(name, "!add")) {
+            fmr->flags &= ~NXFMF_ADD;
+        } else if (!strcmp(name, "!delete")) {
+            fmr->flags &= ~NXFMF_DELETE;
+        } else if (!strcmp(name, "!modify")) {
+            fmr->flags &= ~NXFMF_MODIFY;
+        } else if (!strcmp(name, "!actions")) {
+            fmr->flags &= ~NXFMF_ACTIONS;
+        } else if (!strcmp(name, "!own")) {
+            fmr->flags &= ~NXFMF_OWN;
+        } else if (parse_protocol(name, &p)) {
+            cls_rule_set_dl_type(&fmr->match, htons(p->dl_type));
+            if (p->nw_proto) {
+                cls_rule_set_nw_proto(&fmr->match, p->nw_proto);
+            }
+        } else {
+            char *value;
+
+            value = strtok_r(NULL, ", \t\r\n", &save_ptr);
+            if (!value) {
+                ovs_fatal(0, "%s: field %s missing value", str_, name);
+            }
+
+            if (!strcmp(name, "table")) {
+                fmr->table_id = str_to_table_id(value);
+            } else if (!strcmp(name, "out_port")) {
+                fmr->out_port = atoi(value);
+            } else if (mf_from_name(name)) {
+                parse_field(mf_from_name(name), value, &fmr->match);
+            } else {
+                ovs_fatal(0, "%s: unknown keyword %s", str_, name);
+            }
+        }
+    }
+    free(string);
+}
+
 /* Parses 's' as a set of OpenFlow actions and appends the actions to
  * 'actions'.
  *