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);
ofpact_put_SET_IP_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;
case OFPACT_SET_ETH_DST:
case OFPACT_SET_ETH_SRC:
case OFPACT_SET_IP_DSCP:
+ case OFPACT_SET_IP_ECN:
case OFPACT_SET_IPV4_DST:
case OFPACT_SET_IPV4_SRC:
case OFPACT_SET_L4_DST_PORT:
case OFPACT_SET_ETH_DST:
case OFPACT_SET_ETH_SRC:
case OFPACT_SET_IP_DSCP:
+ case OFPACT_SET_IP_ECN:
case OFPACT_SET_IPV4_DST:
case OFPACT_SET_IPV4_SRC:
case OFPACT_SET_L4_DST_PORT:
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_REG_MOVE:
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:
return 0;
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_WRITE_ACTIONS:
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:
= ofpact_get_SET_IP_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);
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_REG_MOVE:
ds_put_format(s, "mod_nw_tos:%d", ofpact_get_SET_IP_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;
DEFINE_OFPACT(SET_IPV4_SRC, ofpact_ipv4, ofpact) \
DEFINE_OFPACT(SET_IPV4_DST, ofpact_ipv4, ofpact) \
DEFINE_OFPACT(SET_IP_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) \
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. */
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) {
ofpact_put_SET_IP_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();
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")
}
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);
]])
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
Sets the DSCP bits in the IPv4 ToS/DSCP or IPv6 traffic class 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 or IPv6 traffic class 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 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
.IQ
\fBmod_nw_tos\fR
.IQ
+\fBmod_nw_ecn\fR
+.IQ
\fBmod_tp_dst\fR
.IQ
\fBmod_tp_src\fR