ofpacts_check() now stores the nw_proto field from flow to port number
set actions, so that we later remember which protocol they relate to.
This is needed for an accurate tranlation to OF 1.2+ set field action.

Simplify some of the ofp-actions interface.

Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com>
---
 lib/ofp-actions.c     |  235 +++++++++++++++++++++++++++++++++++++++----------
 lib/ofp-actions.h     |   18 ++--
 lib/ofp-util.c        |   49 ++++++-----
 lib/ofp-util.h        |    3 +-
 ofproto/ofproto.c     |    5 +-
 tests/ovs-ofctl.at    |   12 ++-
 utilities/ovs-ofctl.c |   10 ++-
 7 files changed, 248 insertions(+), 84 deletions(-)

diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index 8c9dd8c..0963874 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -1524,7 +1524,7 @@ exit:
 
 /* May modify flow->dl_type, caller must restore it. */
 static enum ofperr
-ofpact_check__(const struct ofpact *a, struct flow *flow, ofp_port_t max_ports,
+ofpact_check__(struct ofpact *a, struct flow *flow, ofp_port_t max_ports,
                uint8_t table_id)
 {
     const struct ofpact_enqueue *enqueue;
@@ -1562,12 +1562,28 @@ ofpact_check__(const struct ofpact *a, struct flow 
*flow, ofp_port_t max_ports,
     case OFPACT_SET_IPV4_SRC:
     case OFPACT_SET_IPV4_DST:
     case OFPACT_SET_IPV4_DSCP:
-    case OFPACT_SET_L4_SRC_PORT:
-    case OFPACT_SET_L4_DST_PORT:
     case OFPACT_SET_IP_ECN:
     case OFPACT_SET_IP_TTL:
         return 0;
 
+    case OFPACT_SET_L4_SRC_PORT:
+        /* Note on which transport protocol the port numbers are set.
+         * This allows this set action to be converted to an OF1.2 set field
+         * action. */
+        if (is_ip_any(flow)) {
+            ofpact_get_SET_L4_SRC_PORT(a)->ip_proto = flow->nw_proto;
+        }
+        return 0;
+
+    case OFPACT_SET_L4_DST_PORT:
+        /* Note on which transport protocol the port numbers are set.
+         * This allows this set action to be converted to an OF1.2 set field
+         * action. */
+        if (is_ip_any(flow)) {
+            ofpact_get_SET_L4_DST_PORT(a)->ip_proto = flow->nw_proto;
+        }
+        return 0;
+
     case OFPACT_REG_MOVE:
         return nxm_reg_move_check(ofpact_get_REG_MOVE(a), flow);
 
@@ -1658,12 +1674,14 @@ ofpact_check__(const struct ofpact *a, struct flow 
*flow, ofp_port_t max_ports,
  * appropriate for a packet with the prerequisites satisfied by 'flow' in a
  * switch with no more than 'max_ports' ports.
  *
+ * May annotate ofpacts with information gathered from the 'flow'.
+ *
  * May temporarily modify 'flow', but restores the changes before returning. */
 enum ofperr
-ofpacts_check(const struct ofpact ofpacts[], size_t ofpacts_len,
+ofpacts_check(struct ofpact ofpacts[], size_t ofpacts_len,
               struct flow *flow, ofp_port_t max_ports, uint8_t table_id)
 {
-    const struct ofpact *a;
+    struct ofpact *a;
     ovs_be16 dl_type = flow->dl_type;
     enum ofperr error = 0;
 
@@ -1871,10 +1889,6 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf 
*out)
         nxm_reg_load_to_nxast(ofpact_get_REG_LOAD(a), out);
         break;
 
-    case OFPACT_SET_FIELD:
-        ofputil_set_field_to_openflow(ofpact_get_SET_FIELD(a), out);
-        break;
-
     case OFPACT_STACK_PUSH:
         nxm_stack_push_to_nxast(ofpact_get_STACK_PUSH(a), out);
         break;
@@ -1971,6 +1985,7 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf 
*out)
     case OFPACT_CLEAR_ACTIONS:
     case OFPACT_GOTO_TABLE:
     case OFPACT_METER:
+    case OFPACT_SET_FIELD:
         NOT_REACHED();
     }
 }
@@ -2071,12 +2086,15 @@ ofpact_to_openflow10(const struct ofpact *a, struct 
ofpbuf *out)
     case OFPACT_GROUP:
         break;
 
+    case OFPACT_SET_FIELD:
+        ofputil_set_field_to_openflow(ofpact_get_SET_FIELD(a), out);
+        break;
+
     case OFPACT_CONTROLLER:
     case OFPACT_OUTPUT_REG:
     case OFPACT_BUNDLE:
     case OFPACT_REG_MOVE:
     case OFPACT_REG_LOAD:
-    case OFPACT_SET_FIELD:
     case OFPACT_STACK_PUSH:
     case OFPACT_STACK_POP:
     case OFPACT_DEC_TTL:
@@ -2101,20 +2119,6 @@ ofpact_to_openflow10(const struct ofpact *a, struct 
ofpbuf *out)
         break;
     }
 }
-
-/* Converts the 'ofpacts_len' bytes of ofpacts in 'ofpacts' into OpenFlow 1.0
- * actions in 'openflow', appending the actions to any existing data in
- * 'openflow'. */
-void
-ofpacts_put_openflow10(const struct ofpact ofpacts[], size_t ofpacts_len,
-                       struct ofpbuf *openflow)
-{
-    const struct ofpact *a;
-
-    OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
-        ofpact_to_openflow10(a, openflow);
-    }
-}
 
 /* Converting ofpacts to OpenFlow 1.1. */
 
@@ -2262,12 +2266,15 @@ ofpact_to_openflow11(const struct ofpact *a, struct 
ofpbuf *out)
             htonl(ofpact_get_GROUP(a)->group_id);
         break;
 
+    case OFPACT_SET_FIELD:
+        ofputil_set_field_to_openflow(ofpact_get_SET_FIELD(a), out);
+        break;
+
     case OFPACT_CONTROLLER:
     case OFPACT_OUTPUT_REG:
     case OFPACT_BUNDLE:
     case OFPACT_REG_MOVE:
     case OFPACT_REG_LOAD:
-    case OFPACT_SET_FIELD:
     case OFPACT_STACK_PUSH:
     case OFPACT_STACK_POP:
     case OFPACT_SET_TUNNEL:
@@ -2284,20 +2291,149 @@ ofpact_to_openflow11(const struct ofpact *a, struct 
ofpbuf *out)
     }
 }
 
-/* Converts the ofpacts in 'ofpacts' (terminated by OFPACT_END) into OpenFlow
- * 1.1 actions in 'openflow', appending the actions to any existing data in
+/* Output deprecated set actions as set_field actions. */
+static void
+ofpact_to_openflow12(const struct ofpact *a, struct ofpbuf *out)
+{
+    uint64_t ofpacts_stub[128 / 8];
+    struct ofpbuf sf_act;
+    enum mf_field_id field;
+    union mf_value mf_value;
+    void *value = &mf_value;
+    struct ofpact_set_field *sf;
+    struct ofpact_l4_port *l4port;
+    uint8_t proto;
+
+    switch ((int)a->type) {
+    case OFPACT_SET_VLAN_VID:
+    case OFPACT_SET_VLAN_PCP:
+    case OFPACT_SET_ETH_SRC:
+    case OFPACT_SET_ETH_DST:
+    case OFPACT_SET_IPV4_SRC:
+    case OFPACT_SET_IPV4_DST:
+    case OFPACT_SET_IPV4_DSCP:
+    case OFPACT_SET_IP_ECN:
+    case OFPACT_SET_IP_TTL:
+    case OFPACT_SET_L4_SRC_PORT:
+    case OFPACT_SET_L4_DST_PORT:
+        /* case OFPACT_SET_MPLS_LABEL: */
+        /* case OFPACT_SET_MPLS_TC: */
+    case OFPACT_SET_TUNNEL:  /* Convert to a set_field, too. */
+
+        switch ((int)a->type) {
+
+        case OFPACT_SET_VLAN_VID:
+            field = MFF_VLAN_VID;
+            mf_value.be16 = htons(ofpact_get_SET_VLAN_VID(a)->vlan_vid);
+            break;
+
+        case OFPACT_SET_VLAN_PCP:
+            field = MFF_VLAN_PCP;
+            value = &ofpact_get_SET_VLAN_PCP(a)->vlan_pcp;
+            break;
+
+        case OFPACT_SET_ETH_SRC:
+            field = MFF_ETH_SRC;
+            value = &ofpact_get_SET_ETH_SRC(a)->mac;
+            break;
+
+        case OFPACT_SET_ETH_DST:
+            field = MFF_ETH_DST;
+            value = &ofpact_get_SET_ETH_DST(a)->mac;
+            break;
+
+        case OFPACT_SET_IPV4_SRC:
+            field = MFF_IPV4_SRC;
+            value = &ofpact_get_SET_IPV4_SRC(a)->ipv4;
+            break;
+
+        case OFPACT_SET_IPV4_DST:
+            field = MFF_IPV4_DST;
+            value = &ofpact_get_SET_IPV4_DST(a)->ipv4;
+            break;
+
+        case OFPACT_SET_IPV4_DSCP:
+            field = MFF_IP_DSCP;
+            value = &ofpact_get_SET_IPV4_DSCP(a)->dscp;
+            break;
+
+        case OFPACT_SET_IP_ECN:
+            field = MFF_IP_ECN;
+            value = &ofpact_get_SET_IP_ECN(a)->ecn;
+            break;
+
+        case OFPACT_SET_IP_TTL:
+            field = MFF_IP_TTL;
+            value = &ofpact_get_SET_IP_TTL(a)->ttl;
+            break;
+
+        case OFPACT_SET_L4_SRC_PORT:
+            l4port = ofpact_get_SET_L4_SRC_PORT(a);
+            proto = l4port->ip_proto;
+            field = proto == IPPROTO_SCTP ? MFF_SCTP_SRC
+                : proto == IPPROTO_UDP ? MFF_UDP_SRC : MFF_TCP_SRC; /* XXX */
+            mf_value.be16 = htons(l4port->port);
+            break;
+
+        case OFPACT_SET_L4_DST_PORT:
+            l4port = ofpact_get_SET_L4_DST_PORT(a);
+            proto = l4port->ip_proto;
+            field = proto == IPPROTO_SCTP ? MFF_SCTP_DST
+                : proto == IPPROTO_UDP ? MFF_UDP_DST : MFF_TCP_DST; /* XXX */
+            mf_value.be16 = htons(l4port->port);
+            break;
+#if 0
+        case OFPACT_SET_MPLS_LABEL:
+            field = MFF_MPLS_LABEL;
+            mf_value.be32 = htonl(ofpact_get_SET_MPLS_LABEL(a)->label);
+            break;
+
+        case OFPACT_SET_MPLS_TC:
+            field = MFF_MPLS_TC;
+            value = &ofpact_get_SET_MPLS_LABEL(a)->tc;
+            break;
+#endif
+        case OFPACT_SET_TUNNEL:
+            field = MFF_TUN_ID;
+            mf_value.be64 = htonll(ofpact_get_SET_TUNNEL(a)->tun_id);
+            break;
+
+        default:
+            field = MFF_N_IDS;
+        }
+
+        /* Out the action out as a set field action. */
+        if (field < MFF_N_IDS) {
+            ofpbuf_use_stub(&sf_act, ofpacts_stub, sizeof ofpacts_stub);
+            sf = ofpact_set_field_from_be_value(mf_from_id(field), value,
+                                                &sf_act);
+            ofputil_set_field_to_openflow(sf, out);
+            return;
+        }
+    }
+
+    ofpact_to_openflow11(a, out);
+}
+
+/* Converts the 'ofpacts_len' bytes of ofpacts in 'ofpacts' into OpenFlow
+ * actions in 'openflow', appending the actions to any existing data in
  * 'openflow'. */
 size_t
-ofpacts_put_openflow11_actions(const struct ofpact ofpacts[],
-                               size_t ofpacts_len, struct ofpbuf *openflow)
+ofpacts_put_openflow_actions(const struct ofpact ofpacts[], size_t ofpacts_len,
+                             struct ofpbuf *openflow,
+                             enum ofp_version ofp_version)
 {
     const struct ofpact *a;
     size_t start_size = openflow->size;
 
+    void (*translate)(const struct ofpact *a, struct ofpbuf *out) =
+        (ofp_version == OFP10_VERSION) ? ofpact_to_openflow10 :
+        (ofp_version == OFP11_VERSION) ? ofpact_to_openflow11 :
+        ofpact_to_openflow12;
+
     OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
-        ofpact_to_openflow11(a, openflow);
+        translate(a, openflow);
     }
-
     return openflow->size - start_size;
 }
 
@@ -2316,12 +2452,15 @@ ofpacts_update_instruction_actions(struct ofpbuf 
*openflow, size_t ofs)
 }
 
 void
-ofpacts_put_openflow11_instructions(const struct ofpact ofpacts[],
-                                    size_t ofpacts_len,
-                                    struct ofpbuf *openflow)
+ofpacts_put_openflow_instructions(const struct ofpact ofpacts[],
+                                  size_t ofpacts_len,
+                                  struct ofpbuf *openflow,
+                                  enum ofp_version ofp_version)
 {
     const struct ofpact *a;
 
+    ovs_assert(ofp_version >= OFP11_VERSION);
+
     OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
         switch (ovs_instruction_type_from_ofpact_type(a->type)) {
         case OVSINST_OFPIT11_CLEAR_ACTIONS:
@@ -2347,15 +2486,16 @@ ofpacts_put_openflow11_instructions(const struct ofpact 
ofpacts[],
             break;
         }
 
-        case OVSINST_OFPIT13_METER: {
-            const struct ofpact_meter *om;
-            struct ofp13_instruction_meter *oim;
+        case OVSINST_OFPIT13_METER:
+            if (ofp_version >= OFP13_VERSION) {
+                const struct ofpact_meter *om;
+                struct ofp13_instruction_meter *oim;
 
-            om = ofpact_get_METER(a);
-            oim = instruction_put_OFPIT13_METER(openflow);
-            oim->meter_id = htonl(om->meter_id);
+                om = ofpact_get_METER(a);
+                oim = instruction_put_OFPIT13_METER(openflow);
+                oim->meter_id = htonl(om->meter_id);
+            }
             break;
-        }
 
         case OVSINST_OFPIT11_APPLY_ACTIONS: {
             const size_t ofs = openflow->size;
@@ -2370,7 +2510,11 @@ ofpacts_put_openflow11_instructions(const struct ofpact 
ofpacts[],
                     != OVSINST_OFPIT11_APPLY_ACTIONS) {
                     break;
                 }
-                ofpact_to_openflow11(action, openflow);
+                if (ofp_version == OFP11_VERSION) {
+                    ofpact_to_openflow11(action, openflow);
+                } else {
+                    ofpact_to_openflow12(action, openflow);
+                }
                 processed = action;
             }
             ofpacts_update_instruction_actions(openflow, ofs);
@@ -2384,9 +2528,9 @@ ofpacts_put_openflow11_instructions(const struct ofpact 
ofpacts[],
 
             on = ofpact_get_WRITE_ACTIONS(a);
             instruction_put_OFPIT11_WRITE_ACTIONS(openflow);
-            ofpacts_put_openflow11_actions(on->actions,
-                                           ofpact_nest_get_action_len(on),
-                                           openflow);
+            ofpacts_put_openflow_actions(on->actions,
+                                         ofpact_nest_get_action_len(on),
+                                         openflow, ofp_version);
             ofpacts_update_instruction_actions(openflow, ofs);
 
             break;
@@ -2394,6 +2538,7 @@ ofpacts_put_openflow11_instructions(const struct ofpact 
ofpacts[],
         }
     }
 }
+
 
 /* Returns true if 'action' outputs to 'port', false otherwise. */
 static bool
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index b97d14b..4e13472 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -320,7 +320,8 @@ struct ofpact_ip_ttl {
  * Used for OFPAT10_SET_TP_SRC, OFPAT10_SET_TP_DST. */
 struct ofpact_l4_port {
     struct ofpact ofpact;
-    uint16_t port;              /* TCP or UDP port number. */
+    uint16_t port;              /* TCP, UDP or SCTP port number. */
+    uint8_t  ip_proto;          /* IP proto from corresponding match, or 0 */
 };
 
 /* OFPACT_REG_MOVE.
@@ -601,19 +602,18 @@ enum ofperr ofpacts_pull_openflow11_actions(struct ofpbuf 
*openflow,
 enum ofperr ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow,
                                                  unsigned int instructions_len,
                                                  struct ofpbuf *ofpacts);
-enum ofperr ofpacts_check(const struct ofpact[], size_t ofpacts_len,
+enum ofperr ofpacts_check(struct ofpact[], size_t ofpacts_len,
                           struct flow *, ofp_port_t max_ports,
                           uint8_t table_id);
 enum ofperr ofpacts_verify(const struct ofpact ofpacts[], size_t ofpacts_len);
 
 /* Converting ofpacts to OpenFlow. */
-void ofpacts_put_openflow10(const struct ofpact[], size_t ofpacts_len,
-                            struct ofpbuf *openflow);
-size_t ofpacts_put_openflow11_actions(const struct ofpact[], size_t 
ofpacts_len,
-                                      struct ofpbuf *openflow);
-void ofpacts_put_openflow11_instructions(const struct ofpact[],
-                                         size_t ofpacts_len,
-                                         struct ofpbuf *openflow);
+size_t ofpacts_put_openflow_actions(const struct ofpact[], size_t ofpacts_len,
+                                    struct ofpbuf *openflow, enum ofp_version);
+void ofpacts_put_openflow_instructions(const struct ofpact[],
+                                       size_t ofpacts_len,
+                                       struct ofpbuf *openflow,
+                                       enum ofp_version ofp_version);
 
 /* Working with ofpacts. */
 bool ofpacts_output_to_port(const struct ofpact[], size_t ofpacts_len,
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 17642d2..ee701e9 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -2065,7 +2065,8 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm,
         ofm->out_group = htonl(fm->out_group);
         ofm->flags = raw_flags;
         ofputil_put_ofp11_match(msg, &fm->match, protocol);
-        ofpacts_put_openflow11_instructions(fm->ofpacts, fm->ofpacts_len, msg);
+        ofpacts_put_openflow_instructions(fm->ofpacts, fm->ofpacts_len, msg,
+                                          version);
         break;
     }
 
@@ -2085,7 +2086,8 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm,
         ofm->buffer_id = htonl(fm->buffer_id);
         ofm->out_port = htons(ofp_to_u16(fm->out_port));
         ofm->flags = raw_flags;
-        ofpacts_put_openflow10(fm->ofpacts, fm->ofpacts_len, msg);
+        ofpacts_put_openflow_actions(fm->ofpacts, fm->ofpacts_len, msg,
+                                     version);
         break;
     }
 
@@ -2108,7 +2110,8 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm,
         nfm->out_port = htons(ofp_to_u16(fm->out_port));
         nfm->flags = raw_flags;
         nfm->match_len = htons(match_len);
-        ofpacts_put_openflow10(fm->ofpacts, fm->ofpacts_len, msg);
+        ofpacts_put_openflow_actions(fm->ofpacts, fm->ofpacts_len, msg,
+                                     version);
         break;
     }
 
@@ -2498,16 +2501,16 @@ ofputil_append_flow_stats_reply(const struct 
ofputil_flow_stats *fs,
     struct ofpbuf *reply = ofpbuf_from_list(list_back(replies));
     size_t start_ofs = reply->size;
     enum ofpraw raw;
+    const struct ofp_header *oh = reply->data;
 
     ofpraw_decode_partial(&raw, reply->data, reply->size);
     if (raw == OFPRAW_OFPST11_FLOW_REPLY || raw == OFPRAW_OFPST13_FLOW_REPLY) {
-        const struct ofp_header *oh = reply->data;
         struct ofp11_flow_stats *ofs;
 
         ofpbuf_put_uninit(reply, sizeof *ofs);
         oxm_put_match(reply, &fs->match);
-        ofpacts_put_openflow11_instructions(fs->ofpacts, fs->ofpacts_len,
-                                            reply);
+        ofpacts_put_openflow_instructions(fs->ofpacts, fs->ofpacts_len, reply,
+                                          oh->version);
 
         ofs = ofpbuf_at_assert(reply, start_ofs, sizeof *ofs);
         ofs->length = htons(reply->size - start_ofs);
@@ -2531,8 +2534,8 @@ ofputil_append_flow_stats_reply(const struct 
ofputil_flow_stats *fs,
         struct ofp10_flow_stats *ofs;
 
         ofpbuf_put_uninit(reply, sizeof *ofs);
-        ofpacts_put_openflow10(fs->ofpacts, fs->ofpacts_len, reply);
-
+        ofpacts_put_openflow_actions(fs->ofpacts, fs->ofpacts_len, reply,
+                                     oh->version);
         ofs = ofpbuf_at_assert(reply, start_ofs, sizeof *ofs);
         ofs->length = htons(reply->size - start_ofs);
         ofs->table_id = fs->table_id;
@@ -2555,8 +2558,8 @@ ofputil_append_flow_stats_reply(const struct 
ofputil_flow_stats *fs,
 
         ofpbuf_put_uninit(reply, sizeof *nfs);
         match_len = nx_put_match(reply, &fs->match, 0, 0);
-        ofpacts_put_openflow10(fs->ofpacts, fs->ofpacts_len, reply);
-
+        ofpacts_put_openflow_actions(fs->ofpacts, fs->ofpacts_len, reply,
+                                     oh->version);
         nfs = ofpbuf_at_assert(reply, start_ofs, sizeof *nfs);
         nfs->length = htons(reply->size - start_ofs);
         nfs->table_id = fs->table_id;
@@ -4298,9 +4301,11 @@ ofputil_append_flow_update(const struct 
ofputil_flow_update *update,
     struct nx_flow_update_header *nfuh;
     struct ofpbuf *msg;
     size_t start_ofs;
+    struct ofp_header *oh;
 
     msg = ofpbuf_from_list(list_back(replies));
     start_ofs = msg->size;
+    oh = msg->l2;
 
     if (update->event == NXFME_ABBREV) {
         struct nx_flow_update_abbrev *nfua;
@@ -4313,8 +4318,8 @@ ofputil_append_flow_update(const struct 
ofputil_flow_update *update,
 
         ofpbuf_put_zeros(msg, sizeof *nfuf);
         match_len = nx_put_match(msg, update->match, htonll(0), htonll(0));
-        ofpacts_put_openflow10(update->ofpacts, update->ofpacts_len, msg);
-
+        ofpacts_put_openflow_actions(update->ofpacts, update->ofpacts_len, msg,
+                                     oh->version);
         nfuf = ofpbuf_at_assert(msg, start_ofs, sizeof *nfuf);
         nfuf->reason = htons(update->reason);
         nfuf->priority = htons(update->priority);
@@ -4353,7 +4358,8 @@ ofputil_encode_packet_out(const struct ofputil_packet_out 
*po,
         msg = ofpraw_alloc(OFPRAW_OFPT10_PACKET_OUT, OFP10_VERSION, size);
         ofpbuf_put_zeros(msg, sizeof *opo);
         actions_ofs = msg->size;
-        ofpacts_put_openflow10(po->ofpacts, po->ofpacts_len, msg);
+        ofpacts_put_openflow_actions(po->ofpacts, po->ofpacts_len, msg,
+                                     ofp_version);
 
         opo = msg->l3;
         opo->buffer_id = htonl(po->buffer_id);
@@ -4370,8 +4376,8 @@ ofputil_encode_packet_out(const struct ofputil_packet_out 
*po,
 
         msg = ofpraw_alloc(OFPRAW_OFPT11_PACKET_OUT, ofp_version, size);
         ofpbuf_put_zeros(msg, sizeof *opo);
-        len = ofpacts_put_openflow11_actions(po->ofpacts, po->ofpacts_len, 
msg);
-
+        len = ofpacts_put_openflow_actions(po->ofpacts, po->ofpacts_len, msg,
+                                           ofp_version);
         opo = msg->l3;
         opo->buffer_id = htonl(po->buffer_id);
         opo->in_port = ofputil_port_to_ofp11(po->in_port);
@@ -5641,7 +5647,8 @@ ofputil_decode_group_stats_reply(struct ofpbuf *msg,
 void
 ofputil_append_group_desc_reply(const struct ofputil_group_desc *gds,
                                 struct list *buckets,
-                                struct list *replies)
+                                struct list *replies,
+                                enum ofp_version ofp_version)
 {
     struct ofpbuf *reply = ofpbuf_from_list(list_back(replies));
     struct ofp11_group_desc_stats *ogds;
@@ -5656,9 +5663,8 @@ ofputil_append_group_desc_reply(const struct 
ofputil_group_desc *gds,
 
         start_ob = reply->size;
         ofpbuf_put_zeros(reply, sizeof *ob);
-        ofpacts_put_openflow11_actions(bucket->ofpacts,
-                                       bucket->ofpacts_len, reply);
-
+        ofpacts_put_openflow_actions(bucket->ofpacts, bucket->ofpacts_len,
+                                     reply, ofp_version);
         ob = ofpbuf_at_assert(reply, start_ob, sizeof *ob);
         ob->len = htons(reply->size - start_ob);
         ob->weight = htons(bucket->weight);
@@ -5815,8 +5821,9 @@ ofputil_encode_group_mod(enum ofp_version ofp_version,
             start_bucket = b->size;
             ofpbuf_put_uninit(b, sizeof *ob);
             if (bucket->ofpacts && bucket->ofpacts_len) {
-                ofpacts_put_openflow11_actions(bucket->ofpacts,
-                                bucket->ofpacts_len, b);
+                ofpacts_put_openflow_actions(bucket->ofpacts,
+                                             bucket->ofpacts_len, b,
+                                             ofp_version);
             }
             ob = ofpbuf_at_assert(b, start_bucket, sizeof *ob);
             ob->len = htons(b->size - start_bucket);;
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index f998e09..17d14c0 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -979,7 +979,8 @@ int ofputil_decode_group_desc_reply(struct 
ofputil_group_desc *,
 
 void ofputil_append_group_desc_reply(const struct ofputil_group_desc *,
                                      struct list *buckets,
-                                     struct list *replies);
+                                     struct list *replies,
+                                     enum ofp_version);
 struct ofpbuf *ofputil_encode_group_desc_request(enum ofp_version);
 
 void
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index fe004b5..ef81889 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -2799,7 +2799,7 @@ reject_slave_controller(struct ofconn *ofconn)
  */
 static enum ofperr
 ofproto_check_ofpacts(struct ofproto *ofproto,
-                      const struct ofpact ofpacts[], size_t ofpacts_len,
+                      struct ofpact ofpacts[], size_t ofpacts_len,
                       struct flow *flow, uint8_t table_id)
 {
     enum ofperr error;
@@ -5359,7 +5359,8 @@ handle_group_desc_stats_request(struct ofconn *ofconn,
     HMAP_FOR_EACH (group, hmap_node, &ofproto->groups) {
         gds.group_id = group->group_id;
         gds.type = group->type;
-        ofputil_append_group_desc_reply(&gds, &group->buckets, &replies);
+        ofputil_append_group_desc_reply(&gds, &group->buckets, &replies,
+                                        request->version);
     }
     ovs_rwlock_unlock(&ofproto->groups_rwlock);
 
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index 9ceb4a9..a196647 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -180,7 +180,7 @@ AT_SETUP([ovs-ofctl parse-flows (OpenFlow 1.2)])
 AT_DATA([flows.txt], [[
 # comment
 tcp,tp_src=123,actions=flood
-in_port=LOCAL dl_vlan=9 dl_src=00:0A:E4:25:6B:B0 actions=drop
+in_port=LOCAL dl_vlan=9 dl_src=00:0A:E4:25:6B:B0 
actions=mod_vlan_vid:7,mod_vlan_pcp:2
 udp dl_vlan_pcp=7 idle_timeout=5 actions=strip_vlan output:0
 tcp,nw_src=192.168.0.3,tp_dst=80 actions=set_queue:37,output:1
 udp,nw_src=192.168.0.3,tp_dst=53 actions=pop_queue,output:1
@@ -189,6 +189,10 @@ actions=note:41.42.43,note:00.01.02.03.04.05.06.07,note
 ipv6,actions=set_field:fe80:0123:4567:890a:a6ba:dbff:fefe:59fa->ipv6_src
 sctp actions=set_field:3334->sctp_src
 sctp actions=set_field:4445->sctp_dst
+tcp actions=mod_tp_dst:1234
+udp actions=mod_tp_src:1111
+ip 
actions=mod_nw_src:10.1.1.2,mod_nw_dst:192.168.10.1,mod_nw_ttl:1,mod_nw_tos:16,mod_nw_ecn:2
+in_port=0 actions=mod_dl_src:11:22:33:44:55:66,mod_dl_dst:10:20:30:40:50:60
 in_port=0 actions=resubmit:0
 
actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
@@ -199,7 +203,7 @@ AT_CHECK([[sed 's/ (xid=0x[0-9a-fA-F]*)//' stdout]], [0],
 [[usable protocols: NXM,OXM
 chosen protocol: OXM-OpenFlow12
 OFPT_FLOW_MOD (OF1.2): ADD table:255 tcp,tp_src=123 actions=FLOOD
-OFPT_FLOW_MOD (OF1.2): ADD table:255 
in_port=LOCAL,dl_vlan=9,dl_src=00:0a:e4:25:6b:b0 actions=drop
+OFPT_FLOW_MOD (OF1.2): ADD table:255 
in_port=LOCAL,dl_vlan=9,dl_src=00:0a:e4:25:6b:b0 
actions=set_field:7->vlan_vid,set_field:2->vlan_pcp
 OFPT_FLOW_MOD (OF1.2): ADD table:255 udp,dl_vlan_pcp=7 idle:5 
actions=strip_vlan,output:0
 OFPT_FLOW_MOD (OF1.2): ADD table:255 tcp,nw_src=192.168.0.3,tp_dst=80 
actions=set_queue:37,output:1
 OFPT_FLOW_MOD (OF1.2): ADD table:255 udp,nw_src=192.168.0.3,tp_dst=53 
actions=pop_queue,output:1
@@ -208,6 +212,10 @@ OFPT_FLOW_MOD (OF1.2): ADD table:255 
actions=note:41.42.43.00.00.00,note:00.01.0
 OFPT_FLOW_MOD (OF1.2): ADD table:255 ipv6 
actions=set_field:fe80:123:4567:890a:a6ba:dbff:fefe:59fa->ipv6_src
 OFPT_FLOW_MOD (OF1.2): ADD table:255 sctp actions=set_field:3334->sctp_src
 OFPT_FLOW_MOD (OF1.2): ADD table:255 sctp actions=set_field:4445->sctp_dst
+OFPT_FLOW_MOD (OF1.2): ADD table:255 tcp actions=set_field:1234->tcp_dst
+OFPT_FLOW_MOD (OF1.2): ADD table:255 udp actions=set_field:1111->udp_src
+OFPT_FLOW_MOD (OF1.2): ADD table:255 ip 
actions=set_field:10.1.1.2->ip_src,set_field:192.168.10.1->ip_dst,set_field:1->nw_ttl,set_field:16->nw_tos,set_field:2->nw_ecn
+OFPT_FLOW_MOD (OF1.2): ADD table:255 in_port=0 
actions=set_field:11:22:33:44:55:66->eth_src,set_field:10:20:30:40:50:60->eth_dst
 OFPT_FLOW_MOD (OF1.2): ADD table:255 in_port=0 actions=resubmit:0
 OFPT_FLOW_MOD (OF1.2): ADD table:255 
actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 2b89755..5ec8f11 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -2802,7 +2802,8 @@ ofctl_parse_ofp10_actions(int argc OVS_UNUSED, char 
*argv[] OVS_UNUSED)
 
         /* Convert back to ofp10 actions and print differences from input. */
         ofpbuf_init(&of10_out, 0);
-        ofpacts_put_openflow10(ofpacts.data, ofpacts.size, &of10_out);
+        ofpacts_put_openflow_actions(ofpacts.data, ofpacts.size, &of10_out,
+                                     OFP10_VERSION);
 
         print_differences("", of10_in.data, of10_in.size,
                           of10_out.data, of10_out.size);
@@ -2989,7 +2990,8 @@ ofctl_parse_ofp11_actions(int argc OVS_UNUSED, char 
*argv[] OVS_UNUSED)
 
         /* Convert back to ofp11 actions and print differences from input. */
         ofpbuf_init(&of11_out, 0);
-        ofpacts_put_openflow11_actions(ofpacts.data, ofpacts.size, &of11_out);
+        ofpacts_put_openflow_actions(ofpacts.data, ofpacts.size, &of11_out,
+                                     OFP11_VERSION);
 
         print_differences("", of11_in.data, of11_in.size,
                           of11_out.data, of11_out.size);
@@ -3066,8 +3068,8 @@ ofctl_parse_ofp11_instructions(int argc OVS_UNUSED, char 
*argv[] OVS_UNUSED)
         /* Convert back to ofp11 instructions and print differences from
          * input. */
         ofpbuf_init(&of11_out, 0);
-        ofpacts_put_openflow11_instructions(ofpacts.data, ofpacts.size,
-                                            &of11_out);
+        ofpacts_put_openflow_instructions(ofpacts.data, ofpacts.size,
+                                          &of11_out, OFP13_VERSION);
 
         print_differences("", of11_in.data, of11_in.size,
                           of11_out.data, of11_out.size);
-- 
1.7.10.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to