Implement IPFIX export
[sliver-openvswitch.git] / lib / ofp-parse.c
index d64d461..295c038 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"
@@ -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)
 {
@@ -378,6 +389,34 @@ parse_metadata(struct ofpbuf *b, char *arg)
     om->metadata = htonll(str_to_u64(arg));
 }
 
+static void
+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, const struct flow *flow,
                    char *arg, struct ofpbuf *ofpacts)
@@ -428,12 +467,17 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
     case OFPUTIL_OFPAT11_PUSH_VLAN:
         ethertype = str_to_u16(arg, "ethertype");
         if (ethertype != ETH_TYPE_VLAN_8021Q) {
-            /* TODO:XXXX ETH_TYPE_VLAN_8021AD case isn't supported */
+            /* XXX ETH_TYPE_VLAN_8021AD case isn't supported */
             ovs_fatal(0, "%s: not a valid VLAN ethertype", arg);
         }
         ofpact_put_PUSH_VLAN(ofpacts);
         break;
 
+    case OFPUTIL_OFPAT11_SET_QUEUE:
+        ofpact_put_SET_QUEUE(ofpacts)->queue_id = str_to_u32(arg);
+        break;
+
+
     case OFPUTIL_OFPAT10_SET_DL_SRC:
     case OFPUTIL_OFPAT11_SET_DL_SRC:
         str_to_mac(arg, ofpact_put_SET_ETH_SRC(ofpacts)->mac);
@@ -521,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;
@@ -550,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;
@@ -557,6 +607,29 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
     case OFPUTIL_NXAST_CONTROLLER:
         parse_controller(ofpacts, arg);
         break;
+
+    case OFPUTIL_OFPAT11_PUSH_MPLS:
+    case OFPUTIL_NXAST_PUSH_MPLS:
+        ofpact_put_PUSH_MPLS(ofpacts)->ethertype =
+            htons(str_to_u16(arg, "push_mpls"));
+        break;
+
+    case OFPUTIL_OFPAT11_POP_MPLS:
+    case OFPUTIL_NXAST_POP_MPLS:
+        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;
     }
 }
 
@@ -624,7 +697,7 @@ parse_named_instruction(enum ovs_instruction_type type,
         break;
 
     case OVSINST_OFPIT11_WRITE_ACTIONS:
-        /* TODO:XXX */
+        /* XXX */
         ovs_fatal(0, "instruction write-actions is not supported yet");
         break;
 
@@ -721,7 +794,9 @@ parse_protocol(const char *name, const struct protocol **p_out)
         { "tcp6", ETH_TYPE_IPV6, IPPROTO_TCP },
         { "udp6", ETH_TYPE_IPV6, IPPROTO_UDP },
         { "rarp", ETH_TYPE_RARP, 0},
-};
+        { "mpls", ETH_TYPE_MPLS, 0 },
+        { "mplsm", ETH_TYPE_MPLS_MCAST, 0 },
+    };
     const struct protocol *p;
 
     for (p = protocols; p < &protocols[ARRAY_SIZE(protocols)]; p++) {
@@ -909,7 +984,9 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
                 parse_field(mf_from_name(name), value, &fm->match);
             } else if (!strcmp(name, "duration")
                        || !strcmp(name, "n_packets")
-                       || !strcmp(name, "n_bytes")) {
+                       || !strcmp(name, "n_bytes")
+                       || !strcmp(name, "idle_age")
+                       || !strcmp(name, "hard_age")) {
                 /* Ignore these, so that users can feed the output of
                  * "ovs-ofctl dump-flows" back into commands that parse
                  * flows. */
@@ -1144,6 +1221,10 @@ parse_ofp_exact_flow(struct flow *flow, const char *s)
         }
     }
 
+    if (!flow->in_port) {
+        flow->in_port = OFPP_NONE;
+    }
+
 exit:
     free(copy);