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

Reply via email to