ofp-actions: Allow OF1.1+ actions to be variable-length.
[sliver-openvswitch.git] / lib / ofp-actions.c
index 210f4ce..8b85f4f 100644 (file)
@@ -282,8 +282,7 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code,
     switch (code) {
     case OFPUTIL_ACTION_INVALID:
 #define OFPAT10_ACTION(ENUM, STRUCT, NAME) case OFPUTIL_##ENUM:
-#define OFPAT11_ACTION(ENUM, STRUCT, NAME) case OFPUTIL_##ENUM:
-#define OFPAT12_ACTION(ENUM, STRUCT, NAME) case OFPUTIL_##ENUM:
+#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM:
 #include "ofp-util.def"
         NOT_REACHED();
 
@@ -397,8 +396,7 @@ ofpact_from_openflow10(const union ofp_action *a, struct ofpbuf *out)
 
     switch (code) {
     case OFPUTIL_ACTION_INVALID:
-#define OFPAT11_ACTION(ENUM, STRUCT, NAME) case OFPUTIL_##ENUM:
-#define OFPAT12_ACTION(ENUM, STRUCT, NAME) case OFPUTIL_##ENUM:
+#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM:
 #include "ofp-util.def"
         NOT_REACHED();
 
@@ -609,19 +607,24 @@ static enum ofperr
 decode_openflow11_action(const union ofp_action *a,
                          enum ofputil_action_code *code)
 {
+    uint16_t len;
+
     switch (a->type) {
     case CONSTANT_HTONS(OFPAT11_EXPERIMENTER):
         return decode_nxast_action(a, code);
 
-#define OFPAT11_ACTION(ENUM, STRUCT, NAME)                          \
-        case CONSTANT_HTONS(ENUM):                                  \
-            if (a->header.len == htons(sizeof(struct STRUCT))) {    \
-                *code = OFPUTIL_##ENUM;                             \
-                return 0;                                           \
-            } else {                                                \
-                return OFPERR_OFPBAC_BAD_LEN;                       \
-            }                                                       \
-            break;
+#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME)  \
+        case CONSTANT_HTONS(ENUM):                      \
+            len = ntohs(a->header.len);                 \
+            if (EXTENSIBLE                              \
+                ? len >= sizeof(struct STRUCT)          \
+                : len == sizeof(struct STRUCT)) {       \
+                *code = OFPUTIL_##ENUM;                 \
+                return 0;                               \
+            } else {                                    \
+                return OFPERR_OFPBAC_BAD_LEN;           \
+            }                                           \
+            NOT_REACHED();
 #include "ofp-util.def"
 
     default:
@@ -661,7 +664,6 @@ ofpact_from_openflow11(const union ofp_action *a, struct ofpbuf *out)
     switch (code) {
     case OFPUTIL_ACTION_INVALID:
 #define OFPAT10_ACTION(ENUM, STRUCT, NAME) case OFPUTIL_##ENUM:
-#define OFPAT12_ACTION(ENUM, STRUCT, NAME) case OFPUTIL_##ENUM:
 #include "ofp-util.def"
         NOT_REACHED();
 
@@ -716,6 +718,10 @@ ofpact_from_openflow11(const union ofp_action *a, struct ofpbuf *out)
         ofpact_put_SET_L4_DST_PORT(out)->port = ntohs(a->tp_port.tp_port);
         break;
 
+    case OFPUTIL_OFPAT12_SET_FIELD:
+        /* Not yet implemented. */
+        break;
+
 #define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM:
 #include "ofp-util.def"
         return ofpact_from_nxast(a, code, out);
@@ -1770,7 +1776,8 @@ ofpact_format(const struct ofpact *a, struct ds *s)
     case OFPACT_RESUBMIT:
         resubmit = ofpact_get_RESUBMIT(a);
         if (resubmit->in_port != OFPP_IN_PORT && resubmit->table_id == 255) {
-            ds_put_format(s, "resubmit:%"PRIu16, resubmit->in_port);
+            ds_put_cstr(s, "resubmit:");
+            ofputil_format_port(resubmit->in_port, s);
         } else {
             ds_put_format(s, "resubmit(");
             if (resubmit->in_port != OFPP_IN_PORT) {
@@ -1794,7 +1801,9 @@ ofpact_format(const struct ofpact *a, struct ds *s)
 
     case OFPACT_AUTOPATH:
         autopath = ofpact_get_AUTOPATH(a);
-        ds_put_format(s, "autopath(%u,", autopath->port);
+        ds_put_cstr(s, "autopath(");
+        ofputil_format_port(autopath->port, s);
+        ds_put_char(s, ',');
         mf_format_subfield(&autopath->dst, s);
         ds_put_char(s, ')');
         break;