[ovs-dev] [PATCH 3/9] Add OF11 set IP ECN action.

Jarno Rajahalme jrajahalme at nicira.com
Wed Oct 16 23:16:05 UTC 2013


Signed-off-by: Jarno Rajahalme <jrajahalme at nicira.com>
---
 lib/ofp-actions.c            |   24 ++++++++++++++++++++++++
 lib/ofp-actions.h            |    9 +++++++++
 lib/ofp-parse.c              |   14 +++++++++++++-
 lib/ofp-util.def             |    2 +-
 ofproto/ofproto-dpif-xlate.c |    8 ++++++++
 tests/ovs-ofctl.at           |   37 +++++++++++++++++++++++++++++++++++++
 utilities/ovs-ofctl.8.in     |    9 +++++++++
 7 files changed, 101 insertions(+), 2 deletions(-)

diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index 73a3291..ff691ee 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -44,6 +44,7 @@ union ofp_action {
     struct ofp_action_vlan_pcp vlan_pcp;
     struct ofp_action_nw_addr nw_addr;
     struct ofp_action_nw_tos nw_tos;
+    struct ofp11_action_nw_ecn nw_ecn;
     struct ofp_action_tp_port tp_port;
 };
 OFP_ASSERT(sizeof(union ofp_action) == 8);
@@ -833,6 +834,13 @@ ofpact_from_openflow11(const union ofp_action *a, struct ofpbuf *out)
         ofpact_put_SET_IPV4_DSCP(out)->dscp = a->nw_tos.nw_tos;
         break;
 
+    case OFPUTIL_OFPAT11_SET_NW_ECN:
+        if (a->nw_ecn.nw_ecn & ~IP_ECN_MASK) {
+            return OFPERR_OFPBAC_BAD_ARGUMENT;
+        }
+        ofpact_put_SET_IP_ECN(out)->ecn = a->nw_ecn.nw_ecn;
+        break;
+
     case OFPUTIL_OFPAT11_SET_TP_SRC:
         ofpact_put_SET_L4_SRC_PORT(out)->port = ntohs(a->tp_port.tp_port);
         break;
@@ -907,6 +915,7 @@ ofpact_is_set_action(const struct ofpact *a)
     case OFPACT_SET_IPV4_DSCP:
     case OFPACT_SET_IPV4_DST:
     case OFPACT_SET_IPV4_SRC:
+    case OFPACT_SET_IP_ECN:
     case OFPACT_SET_L4_DST_PORT:
     case OFPACT_SET_L4_SRC_PORT:
     case OFPACT_SET_MPLS_TTL:
@@ -968,6 +977,7 @@ ofpact_is_allowed_in_actions_set(const struct ofpact *a)
     case OFPACT_SET_IPV4_DSCP:
     case OFPACT_SET_IPV4_DST:
     case OFPACT_SET_IPV4_SRC:
+    case OFPACT_SET_IP_ECN:
     case OFPACT_SET_L4_DST_PORT:
     case OFPACT_SET_L4_SRC_PORT:
     case OFPACT_SET_MPLS_TTL:
@@ -1207,6 +1217,7 @@ ovs_instruction_type_from_ofpact_type(enum ofpact_type type)
     case OFPACT_SET_IPV4_SRC:
     case OFPACT_SET_IPV4_DST:
     case OFPACT_SET_IPV4_DSCP:
+    case OFPACT_SET_IP_ECN:
     case OFPACT_SET_L4_SRC_PORT:
     case OFPACT_SET_L4_DST_PORT:
     case OFPACT_REG_MOVE:
@@ -1499,6 +1510,7 @@ ofpact_check__(const struct ofpact *a, struct flow *flow, ofp_port_t max_ports,
     case OFPACT_SET_IPV4_DSCP:
     case OFPACT_SET_L4_SRC_PORT:
     case OFPACT_SET_L4_DST_PORT:
+    case OFPACT_SET_IP_ECN:
         return 0;
 
     case OFPACT_REG_MOVE:
@@ -1883,6 +1895,7 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out)
     case OFPACT_SET_IPV4_SRC:
     case OFPACT_SET_IPV4_DST:
     case OFPACT_SET_IPV4_DSCP:
+    case OFPACT_SET_IP_ECN:
     case OFPACT_SET_L4_SRC_PORT:
     case OFPACT_SET_L4_DST_PORT:
     case OFPACT_WRITE_ACTIONS:
@@ -1997,6 +2010,7 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out)
     case OFPACT_STACK_PUSH:
     case OFPACT_STACK_POP:
     case OFPACT_DEC_TTL:
+    case OFPACT_SET_IP_ECN:
     case OFPACT_SET_MPLS_TTL:
     case OFPACT_DEC_MPLS_TTL:
     case OFPACT_SET_TUNNEL:
@@ -2118,6 +2132,11 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out)
             = ofpact_get_SET_IPV4_DSCP(a)->dscp;
         break;
 
+    case OFPACT_SET_IP_ECN:
+        ofputil_put_OFPAT11_SET_NW_ECN(out)->nw_ecn
+            = ofpact_get_SET_IP_ECN(a)->ecn;
+        break;
+
     case OFPACT_SET_L4_SRC_PORT:
         ofputil_put_OFPAT11_SET_TP_SRC(out)->tp_port
             = htons(ofpact_get_SET_L4_SRC_PORT(a)->port);
@@ -2322,6 +2341,7 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, ofp_port_t port)
     case OFPACT_SET_IPV4_SRC:
     case OFPACT_SET_IPV4_DST:
     case OFPACT_SET_IPV4_DSCP:
+    case OFPACT_SET_IP_ECN:
     case OFPACT_SET_L4_SRC_PORT:
     case OFPACT_SET_L4_DST_PORT:
     case OFPACT_REG_MOVE:
@@ -2583,6 +2603,10 @@ ofpact_format(const struct ofpact *a, struct ds *s)
         ds_put_format(s, "mod_nw_tos:%d", ofpact_get_SET_IPV4_DSCP(a)->dscp);
         break;
 
+    case OFPACT_SET_IP_ECN:
+        ds_put_format(s, "mod_nw_ecn:%d", ofpact_get_SET_IP_ECN(a)->ecn);
+        break;
+
     case OFPACT_SET_L4_SRC_PORT:
         ds_put_format(s, "mod_tp_src:%d", ofpact_get_SET_L4_SRC_PORT(a)->port);
         break;
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index 5996651..c1172ca 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -68,6 +68,7 @@
     DEFINE_OFPACT(SET_IPV4_SRC,    ofpact_ipv4,          ofpact)    \
     DEFINE_OFPACT(SET_IPV4_DST,    ofpact_ipv4,          ofpact)    \
     DEFINE_OFPACT(SET_IPV4_DSCP,   ofpact_dscp,          ofpact)    \
+    DEFINE_OFPACT(SET_IP_ECN,      ofpact_ecn,           ofpact)    \
     DEFINE_OFPACT(SET_L4_SRC_PORT, ofpact_l4_port,       ofpact)    \
     DEFINE_OFPACT(SET_L4_DST_PORT, ofpact_l4_port,       ofpact)    \
     DEFINE_OFPACT(REG_MOVE,        ofpact_reg_move,      ofpact)    \
@@ -293,6 +294,14 @@ struct ofpact_dscp {
     uint8_t dscp;               /* DSCP in high 6 bits, rest ignored. */
 };
 
+/* OFPACT_SET_IP_ECN.
+ *
+ * Used for OFPAT11_SET_NW_ECN. */
+struct ofpact_ecn {
+    struct ofpact ofpact;
+    uint8_t ecn;               /* ECN in low 2 bits, rest ignored. */
+};
+
 /* OFPACT_SET_L4_SRC_PORT, OFPACT_SET_L4_DST_PORT.
  *
  * Used for OFPAT10_SET_TP_SRC, OFPAT10_SET_TP_DST. */
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index f55eb3f..50a68c4 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -601,7 +601,7 @@ parse_named_action(enum ofputil_action_code code,
     char *error = NULL;
     uint16_t ethertype = 0;
     uint16_t vid = 0;
-    uint8_t tos = 0;
+    uint8_t tos = 0, ecn;
     uint8_t pcp = 0;
 
     switch (code) {
@@ -699,6 +699,18 @@ parse_named_action(enum ofputil_action_code code,
         ofpact_put_SET_IPV4_DSCP(ofpacts)->dscp = tos;
         break;
 
+    case OFPUTIL_OFPAT11_SET_NW_ECN:
+        error = str_to_u8(arg, "ECN", &ecn);
+        if (error) {
+            return error;
+        }
+
+        if (ecn & ~IP_ECN_MASK) {
+            return xasprintf("%s: not a valid ECN", arg);
+        }
+        ofpact_put_SET_IP_ECN(ofpacts)->ecn = ecn;
+        break;
+
     case OFPUTIL_OFPAT11_DEC_NW_TTL:
         NOT_REACHED();
 
diff --git a/lib/ofp-util.def b/lib/ofp-util.def
index f5eec73..eb75c2d 100644
--- a/lib/ofp-util.def
+++ b/lib/ofp-util.def
@@ -27,7 +27,7 @@ OFPAT11_ACTION(OFPAT11_SET_DL_DST,   ofp_action_dl_addr,  0, "mod_dl_dst")
 OFPAT11_ACTION(OFPAT11_SET_NW_SRC,   ofp_action_nw_addr,  0, "mod_nw_src")
 OFPAT11_ACTION(OFPAT11_SET_NW_DST,   ofp_action_nw_addr,  0, "mod_nw_dst")
 OFPAT11_ACTION(OFPAT11_SET_NW_TOS,   ofp_action_nw_tos,   0, "mod_nw_tos")
-//OFPAT11_ACTION(OFPAT11_SET_NW_ECN,   ofp11_action_nw_ecn, "0, mod_nw_ecn")
+OFPAT11_ACTION(OFPAT11_SET_NW_ECN,   ofp11_action_nw_ecn, 0, "mod_nw_ecn")
 OFPAT11_ACTION(OFPAT11_SET_TP_SRC,   ofp_action_tp_port,  0, "mod_tp_src")
 OFPAT11_ACTION(OFPAT11_SET_TP_DST,   ofp_action_tp_port,  0, "mod_tp_dst")
 OFPAT11_ACTION(OFPAT11_SET_MPLS_TTL, ofp11_action_mpls_ttl, 0, "set_mpls_ttl")
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 7371750..f0c8fde 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -2373,6 +2373,14 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
             }
             break;
 
+        case OFPACT_SET_IP_ECN:
+            if (is_ip_any(flow)) {
+                wc->masks.nw_tos |= IP_ECN_MASK;
+                flow->nw_tos &= ~IP_ECN_MASK;
+                flow->nw_tos |= ofpact_get_SET_IP_ECN(a)->ecn;
+            }
+            break;
+
         case OFPACT_SET_L4_SRC_PORT:
             if (is_ip_any(flow)) {
                 memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto);
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index cbd6aec..4550a8d 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -139,6 +139,43 @@ OFPT_FLOW_MOD: ADD actions=sample(probability=12345,collector_set_id=23456,obs_d
 ]])
 AT_CLEANUP
 
+AT_SETUP([ovs-ofctl parse-flows (OpenFlow 1.1)])
+AT_DATA([flows.txt], [[
+# comment
+tcp,tp_src=123,out_port=5,actions=flood
+in_port=LOCAL dl_vlan=9 dl_src=00:0A:E4:25:6B:B0 actions=drop
+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=mod_nw_ecn:2,output:1
+cookie=0x123456789abcdef hard_timeout=10 priority=60000 actions=controller
+actions=note:41.42.43,note:00.01.02.03.04.05.06.07,note
+ip,actions=set_field:10.4.3.77->ip_src
+sctp actions=drop
+sctp actions=drop
+in_port=0 actions=resubmit:0
+actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+]])
+
+AT_CHECK([ovs-ofctl --protocols OpenFlow11 parse-flows flows.txt
+], [0], [stdout])
+AT_CHECK([[sed 's/ (xid=0x[0-9a-fA-F]*)//' stdout]], [0],
+[[usable protocols: any
+chosen protocol: OpenFlow11
+OFPT_FLOW_MOD (OF1.1): ADD table:255 tcp,tp_src=123 out_port:5 actions=FLOOD
+OFPT_FLOW_MOD (OF1.1): ADD table:255 in_port=LOCAL,dl_vlan=9,dl_src=00:0a:e4:25:6b:b0 actions=drop
+OFPT_FLOW_MOD (OF1.1): ADD table:255 udp,dl_vlan_pcp=7 idle:5 actions=strip_vlan,output:0
+OFPT_FLOW_MOD (OF1.1): ADD table:255 tcp,nw_src=192.168.0.3,tp_dst=80 actions=set_queue:37,output:1
+OFPT_FLOW_MOD (OF1.1): ADD table:255 udp,nw_src=192.168.0.3,tp_dst=53 actions=mod_nw_ecn:2,output:1
+OFPT_FLOW_MOD (OF1.1): ADD table:255 priority=60000 cookie:0x123456789abcdef hard:10 actions=CONTROLLER:65535
+OFPT_FLOW_MOD (OF1.1): ADD table:255 actions=note:41.42.43.00.00.00,note:00.01.02.03.04.05.06.07.00.00.00.00.00.00,note:00.00.00.00.00.00
+OFPT_FLOW_MOD (OF1.1): ADD table:255 ip actions=load:0xa04034d->NXM_OF_IP_SRC[]
+OFPT_FLOW_MOD (OF1.1): ADD table:255 sctp actions=drop
+OFPT_FLOW_MOD (OF1.1): ADD table:255 sctp actions=drop
+OFPT_FLOW_MOD (OF1.1): ADD table:255 in_port=0 actions=resubmit:0
+OFPT_FLOW_MOD (OF1.1): ADD table:255 actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+]])
+AT_CLEANUP
+
 AT_SETUP([ovs-ofctl parse-flows (OpenFlow 1.2)])
 AT_DATA([flows.txt], [[
 # comment
diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
index 0a2ddf6..4bad990 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -1099,6 +1099,13 @@ Sets the TCP or UDP or SCTP destination port to \fIport\fR.
 Sets the IPv4 ToS/DSCP field to \fItos\fR, which must be a multiple of
 4 between 0 and 255.  This action does not modify the two least
 significant bits of the ToS field (the ECN bits).
+.
+.IP \fBmod_nw_ecn\fB:\fIecn\fR
+Sets the ECN bits in the IPv4 ToS field to \fIecn\fR, which must be a
+value between 0 and 3, inclusive.  This action does not modify the six most
+significant bits of the ToS field (the DSCP bits).
+.IP
+Requires OpenFlow 1.1 or later.
 .RE
 .IP
 The following actions are Nicira vendor extensions that, as of this writing, are
@@ -1388,6 +1395,8 @@ the action set, the one written later replaces the earlier action:
 .IQ
 \fBmod_nw_tos\fR
 .IQ
+\fBmod_nw_ecn\fR
+.IQ
 \fBmod_tp_dst\fR
 .IQ
 \fBmod_tp_src\fR
-- 
1.7.10.4




More information about the dev mailing list