Signed-off-by: Jarno Rajahalme <jrajaha...@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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev