ofp-actions: Implement writing to metadata field
[openvswitch] / lib / ofp-parse.c
index f8cbcc670d23a90c6fa983aa2bb8f7c71e580c25..33065aa17b11913c997e1c449f053015b75923dc 100644 (file)
@@ -360,6 +360,24 @@ set_field_parse(const char *arg, struct ofpbuf *ofpacts)
     free(orig);
 }
 
+static void
+parse_metadata(struct ofpbuf *b, char *arg)
+{
+    struct ofpact_metadata *om;
+    char *mask = strchr(arg, '/');
+
+    om = ofpact_put_WRITE_METADATA(b);
+
+    if (mask) {
+        *mask = '\0';
+        om->mask = htonll(str_to_u64(mask + 1));
+    } else {
+        om->mask = htonll(UINT64_MAX);
+    }
+
+    om->metadata = htonll(str_to_u64(arg));
+}
+
 static void
 parse_named_action(enum ofputil_action_code code, const struct flow *flow,
                    char *arg, struct ofpbuf *ofpacts)
@@ -465,6 +483,10 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
         tunnel->tun_id = str_to_u64(arg);
         break;
 
+    case OFPUTIL_NXAST_WRITE_METADATA:
+        parse_metadata(ofpacts, arg);
+        break;
+
     case OFPUTIL_NXAST_SET_QUEUE:
         ofpact_put_SET_QUEUE(ofpacts)->queue_id = str_to_u32(arg);
         break;
@@ -560,6 +582,7 @@ static void
 str_to_ofpacts(const struct flow *flow, char *str, struct ofpbuf *ofpacts)
 {
     char *pos, *act, *arg;
+    enum ofperr error;
     int n_actions;
 
     pos = str;
@@ -570,6 +593,12 @@ str_to_ofpacts(const struct flow *flow, char *str, struct ofpbuf *ofpacts)
         }
         n_actions++;
     }
+
+    error = ofpacts_verify(ofpacts->data, ofpacts->size);
+    if (error) {
+        ovs_fatal(0, "Incorrect action ordering");
+    }
+
     ofpact_pad(ofpacts);
 }
 
@@ -577,6 +606,8 @@ static void
 parse_named_instruction(enum ovs_instruction_type type,
                         char *arg, struct ofpbuf *ofpacts)
 {
+    enum ofperr error;
+
     switch (type) {
     case OVSINST_OFPIT11_APPLY_ACTIONS:
         NOT_REACHED();  /* This case is handled by str_to_inst_ofpacts() */
@@ -592,8 +623,7 @@ parse_named_instruction(enum ovs_instruction_type type,
         break;
 
     case OVSINST_OFPIT11_WRITE_METADATA:
-        /* TODO:XXX */
-        ovs_fatal(0, "instruction write-metadata is not supported yet");
+        parse_metadata(ofpacts, arg);
         break;
 
     case OVSINST_OFPIT11_GOTO_TABLE: {
@@ -606,6 +636,13 @@ parse_named_instruction(enum ovs_instruction_type type,
         break;
     }
     }
+
+    /* If write_metadata is specified as an action AND an instruction, ofpacts
+       could be invalid. */
+    error = ofpacts_verify(ofpacts->data, ofpacts->size);
+    if (error) {
+        ovs_fatal(0, "Incorrect instruction ordering");
+    }
 }
 
 static void