Create specific types for ofp and odp port
[sliver-openvswitch.git] / lib / ofp-parse.c
index dd43577..1890050 100644 (file)
@@ -22,7 +22,6 @@
 #include <errno.h>
 #include <stdlib.h>
 
-#include "autopath.h"
 #include "bundle.h"
 #include "byte-order.h"
 #include "dynamic-string.h"
@@ -136,7 +135,7 @@ parse_enqueue(char *arg, struct ofpbuf *ofpacts)
     }
 
     enqueue = ofpact_put_ENQUEUE(ofpacts);
-    enqueue->port = str_to_u32(port);
+    enqueue->port = u16_to_ofp(str_to_u32(port));
     enqueue->queue = str_to_u32(queue);
 }
 
@@ -153,7 +152,7 @@ parse_output(char *arg, struct ofpbuf *ofpacts)
         struct ofpact_output *output;
 
         output = ofpact_put_OUTPUT(ofpacts);
-        output->port = str_to_u32(arg);
+        output->port = u16_to_ofp(str_to_u32(arg));
         output->max_len = output->port == OFPP_CONTROLLER ? UINT16_MAX : 0;
     }
 }
@@ -318,6 +317,18 @@ parse_dec_ttl(struct ofpbuf *b, char *arg)
     }
 }
 
+static void
+parse_set_mpls_ttl(struct ofpbuf *b, const char *arg)
+{
+    struct ofpact_mpls_ttl *mpls_ttl = ofpact_put_SET_MPLS_TTL(b);
+
+    if (*arg == '\0') {
+        ovs_fatal(0, "parse_set_mpls_ttl: expected ttl.");
+    }
+
+    mpls_ttl->ttl = atoi(arg);
+}
+
 static void
 set_field_parse(const char *arg, struct ofpbuf *ofpacts)
 {
@@ -379,7 +390,35 @@ parse_metadata(struct ofpbuf *b, char *arg)
 }
 
 static void
-parse_named_action(enum ofputil_action_code code, const struct flow *flow,
+parse_sample(struct ofpbuf *b, char *arg)
+{
+    struct ofpact_sample *os = ofpact_put_SAMPLE(b);
+    char *key, *value;
+
+    while (ofputil_parse_key_value(&arg, &key, &value)) {
+        if (!strcmp(key, "probability")) {
+            os->probability = str_to_u16(value, "probability");
+            if (os->probability == 0) {
+                ovs_fatal(0, "invalid probability value \"%s\"", value);
+            }
+        } else if (!strcmp(key, "collector_set_id")) {
+            os->collector_set_id = str_to_u32(value);
+        } else if (!strcmp(key, "obs_domain_id")) {
+            os->obs_domain_id = str_to_u32(value);
+        } else if (!strcmp(key, "obs_point_id")) {
+            os->obs_point_id = str_to_u32(value);
+        } else {
+            ovs_fatal(0, "invalid key \"%s\" in \"sample\" argument",
+                      key);
+        }
+    }
+    if (os->probability == 0) {
+        ovs_fatal(0, "non-zero \"probability\" must be specified on sample");
+    }
+}
+
+static void
+parse_named_action(enum ofputil_action_code code,
                    char *arg, struct ofpbuf *ofpacts)
 {
     struct ofpact_tunnel *tunnel;
@@ -526,10 +565,6 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
         multipath_parse(ofpact_put_MULTIPATH(ofpacts), arg);
         break;
 
-    case OFPUTIL_NXAST_AUTOPATH__DEPRECATED:
-        autopath_parse(ofpact_put_AUTOPATH(ofpacts), arg);
-        break;
-
     case OFPUTIL_NXAST_BUNDLE:
         bundle_parse(arg, ofpacts);
         break;
@@ -544,7 +579,7 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
         NOT_REACHED();
 
     case OFPUTIL_NXAST_LEARN:
-        learn_parse(arg, flow, ofpacts);
+        learn_parse(arg, ofpacts);
         break;
 
     case OFPUTIL_NXAST_EXIT:
@@ -555,6 +590,16 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
         parse_dec_ttl(ofpacts, arg);
         break;
 
+    case OFPUTIL_NXAST_SET_MPLS_TTL:
+    case OFPUTIL_OFPAT11_SET_MPLS_TTL:
+        parse_set_mpls_ttl(ofpacts, arg);
+        break;
+
+    case OFPUTIL_OFPAT11_DEC_MPLS_TTL:
+    case OFPUTIL_NXAST_DEC_MPLS_TTL:
+        ofpact_put_DEC_MPLS_TTL(ofpacts);
+        break;
+
     case OFPUTIL_NXAST_FIN_TIMEOUT:
         parse_fin_timeout(ofpacts, arg);
         break;
@@ -574,16 +619,27 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
         ofpact_put_POP_MPLS(ofpacts)->ethertype =
             htons(str_to_u16(arg, "pop_mpls"));
         break;
+
+    case OFPUTIL_NXAST_STACK_PUSH:
+        nxm_parse_stack_action(ofpact_put_STACK_PUSH(ofpacts), arg);
+        break;
+    case OFPUTIL_NXAST_STACK_POP:
+        nxm_parse_stack_action(ofpact_put_STACK_POP(ofpacts), arg);
+        break;
+
+    case OFPUTIL_NXAST_SAMPLE:
+        parse_sample(ofpacts, arg);
+        break;
     }
 }
 
 static bool
-str_to_ofpact__(const struct flow *flow, char *pos, char *act, char *arg,
+str_to_ofpact__(char *pos, char *act, char *arg,
                 struct ofpbuf *ofpacts, int n_actions)
 {
     int code = ofputil_action_code_from_name(act);
     if (code >= 0) {
-        parse_named_action(code, flow, arg, ofpacts);
+        parse_named_action(code, arg, ofpacts);
     } else if (!strcasecmp(act, "drop")) {
         if (n_actions) {
             ovs_fatal(0, "Drop actions must not be preceded by other "
@@ -594,7 +650,7 @@ str_to_ofpact__(const struct flow *flow, char *pos, char *act, char *arg,
         }
         return false;
     } else {
-        uint16_t port;
+        ofp_port_t port;
         if (ofputil_port_from_string(act, &port)) {
             ofpact_put_OUTPUT(ofpacts)->port = port;
         } else {
@@ -606,7 +662,7 @@ str_to_ofpact__(const struct flow *flow, char *pos, char *act, char *arg,
 }
 
 static void
-str_to_ofpacts(const struct flow *flow, char *str, struct ofpbuf *ofpacts)
+str_to_ofpacts(char *str, struct ofpbuf *ofpacts)
 {
     char *pos, *act, *arg;
     enum ofperr error;
@@ -615,7 +671,7 @@ str_to_ofpacts(const struct flow *flow, char *str, struct ofpbuf *ofpacts)
     pos = str;
     n_actions = 0;
     while (ofputil_parse_key_value(&pos, &act, &arg)) {
-        if (!str_to_ofpact__(flow, pos, act, arg, ofpacts, n_actions)) {
+        if (!str_to_ofpact__(pos, act, arg, ofpacts, n_actions)) {
             break;
         }
         n_actions++;
@@ -673,7 +729,7 @@ parse_named_instruction(enum ovs_instruction_type type,
 }
 
 static void
-str_to_inst_ofpacts(const struct flow *flow, char *str, struct ofpbuf *ofpacts)
+str_to_inst_ofpacts(char *str, struct ofpbuf *ofpacts)
 {
     char *pos, *inst, *arg;
     int type;
@@ -685,7 +741,7 @@ str_to_inst_ofpacts(const struct flow *flow, char *str, struct ofpbuf *ofpacts)
     while (ofputil_parse_key_value(&pos, &inst, &arg)) {
         type = ofpact_instruction_type_from_name(inst);
         if (type < 0) {
-            if (!str_to_ofpact__(flow, pos, inst, arg, ofpacts, n_actions)) {
+            if (!str_to_ofpact__(pos, inst, arg, ofpacts, n_actions)) {
                 break;
             }
 
@@ -948,11 +1004,19 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
     }
     if (fields & F_ACTIONS) {
         struct ofpbuf ofpacts;
+        enum ofperr err;
 
         ofpbuf_init(&ofpacts, 32);
-        str_to_inst_ofpacts(&fm->match.flow, act_str, &ofpacts);
+        str_to_inst_ofpacts(act_str, &ofpacts);
         fm->ofpacts_len = ofpacts.size;
         fm->ofpacts = ofpbuf_steal_data(&ofpacts);
+
+        err = ofpacts_check(fm->ofpacts, fm->ofpacts_len, &fm->match.flow,
+                            OFPP_MAX);
+        if (err) {
+            exit(EXIT_FAILURE);
+        }
+
     } else {
         fm->ofpacts_len = 0;
         fm->ofpacts = NULL;
@@ -1012,7 +1076,7 @@ parse_flow_monitor_request(struct ofputil_flow_monitor_request *fmr,
             if (!strcmp(name, "table")) {
                 fmr->table_id = str_to_table_id(value);
             } else if (!strcmp(name, "out_port")) {
-                fmr->out_port = atoi(value);
+                fmr->out_port = u16_to_ofp(atoi(value));
             } else if (mf_from_name(name)) {
                 parse_field(mf_from_name(name), value, &fmr->match);
             } else {
@@ -1032,7 +1096,7 @@ void
 parse_ofpacts(const char *s_, struct ofpbuf *ofpacts)
 {
     char *s = xstrdup(s_);
-    str_to_ofpacts(NULL, s, ofpacts);
+    str_to_ofpacts(s, ofpacts);
     free(s);
 }
 
@@ -1165,8 +1229,8 @@ parse_ofp_exact_flow(struct flow *flow, const char *s)
         }
     }
 
-    if (!flow->in_port) {
-        flow->in_port = OFPP_NONE;
+    if (!flow->in_port.ofp_port) {
+        flow->in_port.ofp_port = OFPP_NONE;
     }
 
 exit: