Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com> --- lib/ofp-actions.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/ofp-actions.h | 3 +- tests/ovs-ofctl.at | 12 ++++- 3 files changed, 153 insertions(+), 3 deletions(-)
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index 09a98bf..eef4c16 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -1888,12 +1888,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: @@ -2653,9 +2668,135 @@ 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; + /* Set-Field on OXM_OF_VLAN_VID must have OFPVID_PRESENT set. */ + value.be16 = htons(ofpact_get_SET_VLAN_VID(a)->vlan_vid + | OFPVID12_PRESENT); + 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; /* RFC: 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; /* RFC: 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 a7d5618..d503149 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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev