Actions may provide information to allow further decoding of a flow. This allows decoding of encapsulated frames.
For example: In the case of MPLS, L3 and L4 information may not initially be decoded from the frame as the ethernet type of the frame is an MPLS type and no information is known about the type of the inner frame. However, the type of the inner frame may be provided by an mpls_pop action in which case L3 and L4 information may be decoded providing a finer grained match than is otherwise possible. A subsequent patch will introduce code to set flow->encap_dl_type which will activate this change. Signed-off-by: Simon Horman <ho...@verge.net.au> --- v2.19 * As suggested by Ben Pfaff - Remove encap_dl_type parameter from odp_flow_key_from_flow() - Use encap for mpls in ODP flow key data. after: eth(...), eth_type(0x8847), mpls(...), encap(ip(...), tcp(...)) before: eth(...), eth_type(0x8847), mpls(...), ip(...), tcp(...) * Coding style fix for actions_allow_l3_extraction(). Use {} in conjunction with if statements. * Enhance actions_allow_l3_extraction to return when the first MPLS_PUSH action with a non-MPLS ether type is found rather than when the first MPLS_PUSH action is found. * Remove actions_allow_l3_extraction() and obtain encap_dl_type from xlate_actions() instead. * Removed non-odp_flow_key_from_flow portions. These are now present in ofproto: Allow richer matches based on actions(). * Rename patch from "actions: Allow secondary decoding of a flow" to "actions: odp_flow_key_from_flow: Allow of encapsulated frames" v2.18 * Update odp_flow_key_from_flow() to use dl_type_is_ip_any() wrapper. As odp_flow_key_from_flow() is paramatised over encap_dl_type this seems to be a good approach. v2.17 * Rebase v2.13 - v2.16 * No change v2.12 * As suggested by Jarno Rajahalme - Use flow->encap_dl_type instead of of obtaining the value by scanning the actions. v2.11 * First post --- lib/odp-util.c | 47 ++++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/lib/odp-util.c b/lib/odp-util.c index 5966c15..a6002db 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -1506,7 +1506,8 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow, uint32_t odp_in_port) { struct ovs_key_ethernet *eth_key; - size_t encap; + size_t encap_vlan = 0, encap_mpls = 0; + ovs_be16 dl_type = flow_innermost_dl_type(flow); if (flow->skb_priority) { nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, flow->skb_priority); @@ -1534,12 +1535,10 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow, if (flow->vlan_tci != htons(0) || flow->dl_type == htons(ETH_TYPE_VLAN)) { nl_msg_put_be16(buf, OVS_KEY_ATTR_ETHERTYPE, htons(ETH_TYPE_VLAN)); nl_msg_put_be16(buf, OVS_KEY_ATTR_VLAN, flow->vlan_tci); - encap = nl_msg_start_nested(buf, OVS_KEY_ATTR_ENCAP); + encap_vlan = nl_msg_start_nested(buf, OVS_KEY_ATTR_ENCAP); if (flow->vlan_tci == htons(0)) { goto unencap; } - } else { - encap = 0; } if (ntohs(flow->dl_type) < ETH_TYPE_MIN) { @@ -1548,7 +1547,18 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow, nl_msg_put_be16(buf, OVS_KEY_ATTR_ETHERTYPE, flow->dl_type); - if (flow->dl_type == htons(ETH_TYPE_IP)) { + if (flow->mpls_depth) { + struct ovs_key_mpls *mpls_key; + + mpls_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_MPLS, + sizeof *mpls_key); + mpls_key->mpls_top_lse = flow->mpls_lse; + if (flow->encap_dl_type) { + encap_mpls = nl_msg_start_nested(buf, OVS_KEY_ATTR_ENCAP); + } + } + + if (dl_type == htons(ETH_TYPE_IP)) { struct ovs_key_ipv4 *ipv4_key; ipv4_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_IPV4, @@ -1559,7 +1569,7 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow, ipv4_key->ipv4_tos = flow->nw_tos; ipv4_key->ipv4_ttl = flow->nw_ttl; ipv4_key->ipv4_frag = ovs_to_odp_frag(flow->nw_frag); - } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) { + } else if (dl_type == htons(ETH_TYPE_IPV6)) { struct ovs_key_ipv6 *ipv6_key; ipv6_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_IPV6, @@ -1571,8 +1581,8 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow, ipv6_key->ipv6_tclass = flow->nw_tos; ipv6_key->ipv6_hlimit = flow->nw_ttl; ipv6_key->ipv6_frag = ovs_to_odp_frag(flow->nw_frag); - } else if (flow->dl_type == htons(ETH_TYPE_ARP) || - flow->dl_type == htons(ETH_TYPE_RARP)) { + } else if (dl_type == htons(ETH_TYPE_ARP) || + dl_type == htons(ETH_TYPE_RARP)) { struct ovs_key_arp *arp_key; arp_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_ARP, @@ -1585,15 +1595,7 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow, memcpy(arp_key->arp_tha, flow->arp_tha, ETH_ADDR_LEN); } - if (flow->mpls_depth) { - struct ovs_key_mpls *mpls_key; - - mpls_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_MPLS, - sizeof *mpls_key); - mpls_key->mpls_top_lse = flow->mpls_lse; - } - - if (is_ip_any(flow) && !(flow->nw_frag & FLOW_NW_FRAG_LATER)) { + if (dl_type_is_ip_any(dl_type) && !(flow->nw_frag & FLOW_NW_FRAG_LATER)) { if (flow->nw_proto == IPPROTO_TCP) { struct ovs_key_tcp *tcp_key; @@ -1608,7 +1610,7 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow, sizeof *udp_key); udp_key->udp_src = flow->tp_src; udp_key->udp_dst = flow->tp_dst; - } else if (flow->dl_type == htons(ETH_TYPE_IP) + } else if (dl_type == htons(ETH_TYPE_IP) && flow->nw_proto == IPPROTO_ICMP) { struct ovs_key_icmp *icmp_key; @@ -1616,7 +1618,7 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow, sizeof *icmp_key); icmp_key->icmp_type = ntohs(flow->tp_src); icmp_key->icmp_code = ntohs(flow->tp_dst); - } else if (flow->dl_type == htons(ETH_TYPE_IPV6) + } else if (dl_type == htons(ETH_TYPE_IPV6) && flow->nw_proto == IPPROTO_ICMPV6) { struct ovs_key_icmpv6 *icmpv6_key; @@ -1640,8 +1642,11 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow, } unencap: - if (encap) { - nl_msg_end_nested(buf, encap); + if (encap_mpls) { + nl_msg_end_nested(buf, encap_mpls); + } + if (encap_vlan) { + nl_msg_end_nested(buf, encap_vlan); } } -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev