ofp-parse: Fix padding parsing write-actions.
[sliver-openvswitch.git] / lib / ofp-parse.c
index a61beb9..2350de3 100644 (file)
@@ -38,9 +38,6 @@
 #include "packets.h"
 #include "socket-util.h"
 #include "vconn.h"
-#include "vlog.h"
-
-VLOG_DEFINE_THIS_MODULE(ofp_parse);
 
 /* Parses 'str' as an 8-bit unsigned integer into '*valuep'.
  *
@@ -544,7 +541,7 @@ parse_metadata(struct ofpbuf *b, char *arg)
             return error;
         }
     } else {
-        om->mask = htonll(UINT64_MAX);
+        om->mask = OVS_BE64_MAX;
     }
 
     return str_to_be64(arg, &om->metadata);
@@ -882,12 +879,11 @@ str_to_ofpact__(char *pos, char *act, char *arg,
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
 static char * WARN_UNUSED_RESULT
-str_to_ofpacts(char *str, struct ofpbuf *ofpacts,
-               enum ofputil_protocol *usable_protocols)
+str_to_ofpacts__(char *str, struct ofpbuf *ofpacts,
+                 enum ofputil_protocol *usable_protocols)
 {
     size_t orig_size = ofpacts->size;
     char *pos, *act, *arg;
-    enum ofperr error;
     int n_actions;
 
     pos = str;
@@ -902,13 +898,34 @@ str_to_ofpacts(char *str, struct ofpbuf *ofpacts,
         n_actions++;
     }
 
+    ofpact_pad(ofpacts);
+    return NULL;
+}
+
+
+/* Parses 'str' as a series of actions, and appends them to 'ofpacts'.
+ *
+ * Returns NULL if successful, otherwise a malloc()'d string describing the
+ * error.  The caller is responsible for freeing the returned string. */
+static char * WARN_UNUSED_RESULT
+str_to_ofpacts(char *str, struct ofpbuf *ofpacts,
+               enum ofputil_protocol *usable_protocols)
+{
+    size_t orig_size = ofpacts->size;
+    char *error_s;
+    enum ofperr error;
+
+    error_s = str_to_ofpacts__(str, ofpacts, usable_protocols);
+    if (error_s) {
+        return error_s;
+    }
+
     error = ofpacts_verify(ofpacts->data, ofpacts->size);
     if (error) {
         ofpacts->size = orig_size;
         return xstrdup("Incorrect action ordering");
     }
 
-    ofpact_pad(ofpacts);
     return NULL;
 }
 
@@ -932,10 +949,24 @@ parse_named_instruction(enum ovs_instruction_type type,
         NOT_REACHED();  /* This case is handled by str_to_inst_ofpacts() */
         break;
 
-    case OVSINST_OFPIT11_WRITE_ACTIONS:
-        /* XXX */
-        error_s = xstrdup("instruction write-actions is not supported yet");
+    case OVSINST_OFPIT11_WRITE_ACTIONS: {
+        struct ofpact_nest *on;
+        size_t ofs;
+
+        ofpact_pad(ofpacts);
+        ofs = ofpacts->size;
+        on = ofpact_put(ofpacts, OFPACT_WRITE_ACTIONS,
+                        offsetof(struct ofpact_nest, actions));
+        error_s = str_to_ofpacts__(arg, ofpacts, usable_protocols);
+
+        on = ofpbuf_at_assert(ofpacts, ofs, sizeof *on);
+        on->ofpact.len = ofpacts->size - ofs;
+
+        if (error_s) {
+            ofpacts->size = ofs;
+        }
         break;
+    }
 
     case OVSINST_OFPIT11_CLEAR_ACTIONS:
         ofpact_put_CLEAR_ACTIONS(ofpacts);
@@ -1149,7 +1180,7 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
     fm->cookie_mask = htonll(0);
     if (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT) {
         /* For modify, by default, don't update the cookie. */
-        fm->new_cookie = htonll(UINT64_MAX);
+        fm->new_cookie = OVS_BE64_MAX;
     } else{
         fm->new_cookie = htonll(0);
     }
@@ -1290,7 +1321,7 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
             *usable_protocols &= OFPUTIL_P_NXM_OXM_ANY;
         }
     }
-    if (!fm->cookie_mask && fm->new_cookie == htonll(UINT64_MAX)
+    if (!fm->cookie_mask && fm->new_cookie == OVS_BE64_MAX
         && (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT)) {
         /* On modifies without a mask, we are supposed to add a flow if
          * one does not exist.  If a cookie wasn't been specified, use a
@@ -1370,7 +1401,7 @@ parse_ofp_meter_mod_str__(struct ofputil_meter_mod *mm, char *string,
     char *name;
 
     /* Meters require at least OF 1.3. */
-    *usable_protocols &= OFPUTIL_P_OF13_UP;
+    *usable_protocols = OFPUTIL_P_OF13_UP;
 
     switch (command) {
     case -1: