[ovs-dev] [PATCH v3 09/11] lib/ofp-actions: Deprecated actions as set fields.

Jarno Rajahalme jrajahalme at nicira.com
Wed Oct 23 19:53:04 UTC 2013


Signed-off-by: Jarno Rajahalme <jrajahalme at nicira.com>
---
 lib/ofp-actions.c  |  139 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/ofp-actions.h  |    3 +-
 tests/ovs-ofctl.at |   12 ++++-
 3 files changed, 151 insertions(+), 3 deletions(-)

diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index c9027f2..1ec6888 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -1874,12 +1874,27 @@ ofpact_check__(struct ofpact *a, struct flow *flow, ofp_port_t max_ports,
         return 0;
 
     case OFPACT_SET_L4_SRC_PORT:
+        if (!is_ip_any(flow) ||
+            (flow->nw_proto != IPPROTO_TCP && flow->nw_proto != IPPROTO_UDP
+             && flow->nw_proto != IPPROTO_SCTP)) {
+            goto inconsistent;
+        }
+        /* 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. */
+        ofpact_get_SET_L4_SRC_PORT(a)->flow_ip_proto = flow->nw_proto;
+        return 0;
+
     case OFPACT_SET_L4_DST_PORT:
         if (!is_ip_any(flow) ||
             (flow->nw_proto != IPPROTO_TCP && flow->nw_proto != IPPROTO_UDP
              && flow->nw_proto != IPPROTO_SCTP)) {
             goto inconsistent;
         }
+        /* 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. */
+        ofpact_get_SET_L4_DST_PORT(a)->flow_ip_proto = flow->nw_proto;
         return 0;
 
     case OFPACT_REG_MOVE:
@@ -2637,9 +2652,133 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out)
     }
 }
 
+/* Output deprecated set actions as set_field actions. */
 static void
 ofpact_to_openflow12(const struct ofpact *a, struct ofpbuf *out)
 {
+    enum mf_field_id field;
+    union mf_value value;
+    struct ofpact_l4_port *l4port;
+    uint8_t proto;
+
+    /*
+     * Convert actions deprecated in OpenFlow 1.2 to Set Field actions,
+     * if possible.
+     */
+    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_IP_DSCP:
+    case OFPACT_SET_IP_ECN:
+    case OFPACT_SET_L4_SRC_PORT:
+    case OFPACT_SET_L4_DST_PORT:
+    case OFPACT_SET_TUNNEL:  /* Convert to a set_field, too. */
+
+        switch ((int)a->type) {
+
+        case OFPACT_SET_VLAN_VID:
+            if (!ofpact_get_SET_VLAN_VID(a)->flow_has_vlan &&
+                ofpact_get_SET_VLAN_VID(a)->push_vlan_if_needed) {
+                ofputil_put_OFPAT11_PUSH_VLAN(out)->ethertype
+                    = htons(ETH_TYPE_VLAN_8021Q);
+            }
+            field = MFF_VLAN_VID;
+            value.be16 = htons(ofpact_get_SET_VLAN_VID(a)->vlan_vid);
+            break;
+
+        case OFPACT_SET_VLAN_PCP:
+            if (!ofpact_get_SET_VLAN_PCP(a)->flow_has_vlan &&
+                ofpact_get_SET_VLAN_PCP(a)->push_vlan_if_needed) {
+                ofputil_put_OFPAT11_PUSH_VLAN(out)->ethertype
+                    = htons(ETH_TYPE_VLAN_8021Q);
+            }
+            field = MFF_VLAN_PCP;
+            value.u8 = ofpact_get_SET_VLAN_PCP(a)->vlan_pcp;
+            break;
+
+        case OFPACT_SET_ETH_SRC:
+            field = MFF_ETH_SRC;
+            memcpy(value.mac, ofpact_get_SET_ETH_SRC(a)->mac, ETH_ADDR_LEN);
+            break;
+
+        case OFPACT_SET_ETH_DST:
+            field = MFF_ETH_DST;
+            memcpy(value.mac, ofpact_get_SET_ETH_DST(a)->mac, ETH_ADDR_LEN);
+            break;
+
+        case OFPACT_SET_IPV4_SRC:
+            field = MFF_IPV4_SRC;
+            value.be32 = ofpact_get_SET_IPV4_SRC(a)->ipv4;
+            break;
+
+        case OFPACT_SET_IPV4_DST:
+            field = MFF_IPV4_DST;
+            value.be32 = ofpact_get_SET_IPV4_DST(a)->ipv4;
+            break;
+
+        case OFPACT_SET_IP_DSCP:
+            field = MFF_IP_DSCP_SHIFTED; /* OXM_OF_IP_DSCP */
+            value.u8 = ofpact_get_SET_IP_DSCP(a)->dscp >> 2;
+            break;
+
+        case OFPACT_SET_IP_ECN:
+            field = MFF_IP_ECN;
+            value.u8 = ofpact_get_SET_IP_ECN(a)->ecn;
+            break;
+
+        case OFPACT_SET_L4_SRC_PORT:
+            /* We keep track of IP protocol while translating actions to be
+             * able to translate to the proper OXM type.
+             * If the IP protocol type is unknown, the translation cannot
+             * be performed and we will send the action using the original
+             * action type. */
+            l4port = ofpact_get_SET_L4_SRC_PORT(a);
+            proto = l4port->flow_ip_proto;
+            field = proto == IPPROTO_TCP ? MFF_TCP_SRC
+                : proto == IPPROTO_UDP ? MFF_UDP_SRC
+                : proto == IPPROTO_SCTP ? MFF_SCTP_SRC
+                : MFF_N_IDS; /* Unknown, IP proto, do not translate. */
+            value.be16 = htons(l4port->port);
+            break;
+
+        case OFPACT_SET_L4_DST_PORT:
+            l4port = ofpact_get_SET_L4_DST_PORT(a);
+            proto = l4port->flow_ip_proto;
+            field = proto == IPPROTO_TCP ? MFF_TCP_DST
+                : proto == IPPROTO_UDP ? MFF_UDP_DST
+                : proto == IPPROTO_SCTP ? MFF_SCTP_DST
+                : MFF_N_IDS; /* Unknown, IP proto, do not translate. */
+            value.be16 = htons(l4port->port);
+            break;
+
+        case OFPACT_SET_TUNNEL:
+            field = MFF_TUN_ID;
+            value.be64 = htonll(ofpact_get_SET_TUNNEL(a)->tun_id);
+            break;
+
+        default:
+            field = MFF_N_IDS;
+        }
+
+        /* Put the action out as a set field action, if possible. */
+        if (field < MFF_N_IDS) {
+            uint64_t ofpacts_stub[128 / 8];
+            struct ofpbuf sf_act;
+            struct ofpact_set_field *sf;
+
+            ofpbuf_use_stub(&sf_act, ofpacts_stub, sizeof ofpacts_stub);
+            sf = ofpact_put_SET_FIELD(&sf_act);
+            sf->field = field;
+            memcpy(&sf->value, &value, mf_from_id(field)->n_bytes);
+            set_field_to_ofast(sf, out);
+            return;
+        }
+    }
+
     ofpact_to_openflow11(a, out);
 }
 
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index d25d772..41579ce 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -331,7 +331,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  flow_ip_proto;     /* IP proto from corresponding match, or 0 */
 };
 
 /* OFPACT_REG_MOVE.
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index b62afec..54cdb2e 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=pop_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,mod_nw_ttl:1,set_field:4->ip_dscp,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)
 ]])
-- 
1.7.10.4




More information about the dev mailing list