When encoding MPLS information in ODP flow key data use encap() for encap for frames. This seems to be in keeping with datapath/README.
before: eth(...), eth_type(0x8847), mpls(...), encap(ip(...), tcp(...)) after: eth(...), eth_type(0x8847), mpls(...), ip(...), tcp(...) Suggested by Ben Pfaff Signed-off-by: Simon Horman <ho...@verge.net.au> --- v2.19 * Initial post --- lib/odp-util.c | 38 ++++++++++++++++++++++++++++++-------- tests/ofproto-dpif.at | 4 ++-- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/lib/odp-util.c b/lib/odp-util.c index f3f66b7..5966c15 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -1801,10 +1801,14 @@ parse_l2_5_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1], const struct nlattr *key, size_t key_len) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + enum odp_key_fitness fitness, mpls_fitness = 0; ovs_be16 dl_type; /* Parse MPLS label stack entry */ if (eth_type_mpls(flow->dl_type)) { + const struct nlattr *encap + = (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ENCAP) + ? attrs[OVS_KEY_ATTR_ENCAP] : NULL); /* Calculate fitness of outer attributes. */ expected_attrs |= (UINT64_C(1) << OVS_KEY_ATTR_MPLS); @@ -1815,12 +1819,27 @@ parse_l2_5_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1], flow->mpls_lse = nl_attr_get_be32(attrs[OVS_KEY_ATTR_MPLS]); flow->mpls_depth++; - if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IPV4)) { - flow->encap_dl_type = htons(ETH_TYPE_IP); - } else if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IPV6)) { - flow->encap_dl_type = htons(ETH_TYPE_IPV6); - } else if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ARP)) { - flow->encap_dl_type = htons(ETH_TYPE_ARP); + /* Encap may not be present if nothing is known about the + * encapsulated frame */ + if (encap) { + expected_attrs |= (UINT64_C(1) << OVS_KEY_ATTR_ENCAP); + mpls_fitness = check_expectations(present_attrs, out_of_range_attr, + expected_attrs, key, key_len); + + /* Now parse the encapsulated attributes. */ + if (!parse_flow_nlattrs(nl_attr_get(encap), nl_attr_get_size(encap), + attrs, &present_attrs, &out_of_range_attr)) { + return ODP_FIT_ERROR; + } + expected_attrs = 0; + + if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IPV4)) { + flow->encap_dl_type = htons(ETH_TYPE_IP); + } else if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IPV6)) { + flow->encap_dl_type = htons(ETH_TYPE_IPV6); + } else if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ARP)) { + flow->encap_dl_type = htons(ETH_TYPE_ARP); + } } } @@ -1939,8 +1958,11 @@ parse_l2_5_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1], } } - return check_expectations(present_attrs, out_of_range_attr, expected_attrs, - key, key_len); + fitness = check_expectations(present_attrs, out_of_range_attr, + expected_attrs, key, key_len); + + /* The overall fitness is the worse of the outer and inner attributes. */ + return MAX(fitness, mpls_fitness); } /* Parse 802.1Q header then encapsulated L3 attributes. */ diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index 8f11b82..15069bd 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -359,7 +359,7 @@ dnl Modified MPLS actions. AT_CHECK([ovs-ofctl monitor br0 65534 -P nxm --detach --pidfile 2> ofctl_monitor.log]) for i in 1 2 3; do - ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:55:55:55:55:55,dst=50:54:00:00:00:07),eth_type(0x8847),mpls(label=100,tc=7,ttl=64,bos=1),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no)' + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:55:55:55:55:55,dst=50:54:00:00:00:07),eth_type(0x8847),mpls(label=100,tc=7,ttl=64,bos=1),encap(ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))' done OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) @@ -398,7 +398,7 @@ dnl Modified MPLS pop action. AT_CHECK([ovs-ofctl monitor br0 65534 -P nxm --detach --pidfile 2> ofctl_monitor.log]) for i in 1 2 3; do - ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=60:66:66:66:66:66,dst=50:54:00:00:00:07),eth_type(0x8847),mpls(label=10,tc=3,ttl=100,bos=1),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no)' + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=60:66:66:66:66:66,dst=50:54:00:00:00:07),eth_type(0x8847),mpls(label=10,tc=3,ttl=100,bos=1),encap(ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))' done OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev