From: Yunjian Wang <[email protected]>

A problem the userspace datapath failed to create a new datapath flow
when dealing with QinQ packets(the flow includeing ip,udp,etc). L2-L5
header should be considered before parsing the second 802.1Q header.

Fixes: f0fb825a3785 ("Add support for 802.1ad (QinQ tunneling)")
Signed-off-by: Yunjian Wang <[email protected]>
---
 lib/odp-util.c | 72 +++++++++++++++++++++++-----------------------------------
 1 file changed, 29 insertions(+), 43 deletions(-)

diff --git a/lib/odp-util.c b/lib/odp-util.c
index 1e8c5f1..089023b 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -6325,9 +6325,9 @@ parse_ethertype(const struct nlattr 
*attrs[OVS_KEY_ATTR_MAX + 1],
 static enum odp_key_fitness
 parse_l2_5_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
                   uint64_t present_attrs, int out_of_range_attr,
-                  uint64_t expected_attrs, struct flow *flow,
+                  uint64_t *expected_attrs, struct flow *flow,
                   const struct nlattr *key, size_t key_len,
-                  const struct flow *src_flow)
+                  const struct flow *src_flow, bool need_check)
 {
     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
     bool is_mask = src_flow != flow;
@@ -6337,7 +6337,7 @@ parse_l2_5_onward(const struct nlattr 
*attrs[OVS_KEY_ATTR_MAX + 1],
 
     if (eth_type_mpls(src_flow->dl_type)) {
         if (!is_mask || present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_MPLS)) {
-            expected_attrs |= (UINT64_C(1) << OVS_KEY_ATTR_MPLS);
+            *expected_attrs |= (UINT64_C(1) << OVS_KEY_ATTR_MPLS);
         }
         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_MPLS)) {
             size_t size = nl_attr_get_size(attrs[OVS_KEY_ATTR_MPLS]);
@@ -6378,7 +6378,7 @@ parse_l2_5_onward(const struct nlattr 
*attrs[OVS_KEY_ATTR_MAX + 1],
         goto done;
     } else if (src_flow->dl_type == htons(ETH_TYPE_IP)) {
         if (!is_mask) {
-            expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_IPV4;
+            *expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_IPV4;
         }
         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IPV4)) {
             const struct ovs_key_ipv4 *ipv4_key;
@@ -6396,7 +6396,7 @@ parse_l2_5_onward(const struct nlattr 
*attrs[OVS_KEY_ATTR_MAX + 1],
         }
     } else if (src_flow->dl_type == htons(ETH_TYPE_IPV6)) {
         if (!is_mask) {
-            expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_IPV6;
+            *expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_IPV6;
         }
         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IPV6)) {
             const struct ovs_key_ipv6 *ipv6_key;
@@ -6415,7 +6415,7 @@ parse_l2_5_onward(const struct nlattr 
*attrs[OVS_KEY_ATTR_MAX + 1],
     } else if (src_flow->dl_type == htons(ETH_TYPE_ARP) ||
                src_flow->dl_type == htons(ETH_TYPE_RARP)) {
         if (!is_mask) {
-            expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ARP;
+            *expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ARP;
         }
         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ARP)) {
             const struct ovs_key_arp *arp_key;
@@ -6433,18 +6433,6 @@ parse_l2_5_onward(const struct nlattr 
*attrs[OVS_KEY_ATTR_MAX + 1],
                 expected_bit = OVS_KEY_ATTR_ARP;
             }
         }
-    } else if (src_flow->dl_type == htons(ETH_TYPE_NSH)) {
-        if (!is_mask) {
-            expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_NSH;
-        }
-        if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_NSH)) {
-            odp_nsh_key_from_attr(attrs[OVS_KEY_ATTR_NSH], &flow->nsh, NULL);
-            if (is_mask) {
-                check_start = nl_attr_get(attrs[OVS_KEY_ATTR_NSH]);
-                check_len = nl_attr_get_size(attrs[OVS_KEY_ATTR_NSH]);
-                expected_bit = OVS_KEY_ATTR_NSH;
-            }
-        }
     } else {
         goto done;
     }
@@ -6453,7 +6441,7 @@ parse_l2_5_onward(const struct nlattr 
*attrs[OVS_KEY_ATTR_MAX + 1],
             flow->dl_type != htons(0xffff)) {
             return ODP_FIT_ERROR;
         } else {
-            expected_attrs |= UINT64_C(1) << expected_bit;
+            *expected_attrs |= UINT64_C(1) << expected_bit;
         }
     }
 
@@ -6463,7 +6451,7 @@ parse_l2_5_onward(const struct nlattr 
*attrs[OVS_KEY_ATTR_MAX + 1],
             src_flow->dl_type == htons(ETH_TYPE_IPV6))
         && !(src_flow->nw_frag & FLOW_NW_FRAG_LATER)) {
         if (!is_mask) {
-            expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_TCP;
+            *expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_TCP;
         }
         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_TCP)) {
             const union ovs_key_tp *tcp_key;
@@ -6473,7 +6461,7 @@ parse_l2_5_onward(const struct nlattr 
*attrs[OVS_KEY_ATTR_MAX + 1],
             expected_bit = OVS_KEY_ATTR_TCP;
         }
         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_TCP_FLAGS)) {
-            expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_TCP_FLAGS;
+            *expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_TCP_FLAGS;
             flow->tcp_flags = nl_attr_get_be16(attrs[OVS_KEY_ATTR_TCP_FLAGS]);
         }
     } else if (src_flow->nw_proto == IPPROTO_UDP
@@ -6481,7 +6469,7 @@ parse_l2_5_onward(const struct nlattr 
*attrs[OVS_KEY_ATTR_MAX + 1],
                    src_flow->dl_type == htons(ETH_TYPE_IPV6))
                && !(src_flow->nw_frag & FLOW_NW_FRAG_LATER)) {
         if (!is_mask) {
-            expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_UDP;
+            *expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_UDP;
         }
         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_UDP)) {
             const union ovs_key_tp *udp_key;
@@ -6495,7 +6483,7 @@ parse_l2_5_onward(const struct nlattr 
*attrs[OVS_KEY_ATTR_MAX + 1],
                    src_flow->dl_type == htons(ETH_TYPE_IPV6))
                && !(src_flow->nw_frag & FLOW_NW_FRAG_LATER)) {
         if (!is_mask) {
-            expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_SCTP;
+            *expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_SCTP;
         }
         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_SCTP)) {
             const union ovs_key_tp *sctp_key;
@@ -6508,7 +6496,7 @@ parse_l2_5_onward(const struct nlattr 
*attrs[OVS_KEY_ATTR_MAX + 1],
                && src_flow->dl_type == htons(ETH_TYPE_IP)
                && !(src_flow->nw_frag & FLOW_NW_FRAG_LATER)) {
         if (!is_mask) {
-            expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ICMP;
+            *expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ICMP;
         }
         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ICMP)) {
             const struct ovs_key_icmp *icmp_key;
@@ -6522,7 +6510,7 @@ parse_l2_5_onward(const struct nlattr 
*attrs[OVS_KEY_ATTR_MAX + 1],
                && src_flow->dl_type == htons(ETH_TYPE_IPV6)
                && !(src_flow->nw_frag & FLOW_NW_FRAG_LATER)) {
         if (!is_mask) {
-            expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ICMPV6;
+            *expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ICMPV6;
         }
         if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ICMPV6)) {
             const struct ovs_key_icmpv6 *icmpv6_key;
@@ -6533,7 +6521,7 @@ parse_l2_5_onward(const struct nlattr 
*attrs[OVS_KEY_ATTR_MAX + 1],
             expected_bit = OVS_KEY_ATTR_ICMPV6;
             if (is_nd(src_flow, NULL)) {
                 if (!is_mask) {
-                    expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ND;
+                    *expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ND;
                 }
                 if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ND)) {
                     const struct ovs_key_nd *nd_key;
@@ -6553,29 +6541,24 @@ parse_l2_5_onward(const struct nlattr 
*attrs[OVS_KEY_ATTR_MAX + 1],
                              flow->tp_dst != htons(0xff))) {
                             return ODP_FIT_ERROR;
                         } else {
-                            expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ND;
+                            *expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ND;
                         }
                     }
                 }
             }
         }
-    } else if (src_flow->nw_proto == IPPROTO_IGMP
-               && src_flow->dl_type == htons(ETH_TYPE_IP)) {
-        /* OVS userspace parses the IGMP type, code, and group, but its
-         * datapaths do not, so there is always missing information. */
-        return ODP_FIT_TOO_LITTLE;
     }
     if (is_mask && expected_bit != OVS_KEY_ATTR_UNSPEC) {
         if ((flow->tp_src || flow->tp_dst) && flow->nw_proto != 0xff) {
             return ODP_FIT_ERROR;
         } else {
-            expected_attrs |= UINT64_C(1) << expected_bit;
+            *expected_attrs |= UINT64_C(1) << expected_bit;
         }
     }
 
 done:
-    return check_expectations(present_attrs, out_of_range_attr, expected_attrs,
-                              key, key_len);
+    return need_check ? check_expectations(present_attrs, out_of_range_attr,
+                            *expected_attrs, key, key_len) : ODP_FIT_PERFECT;
 }
 
 /* Parse 802.1Q header then encapsulated L3 attributes. */
@@ -6658,16 +6641,18 @@ parse_8021q_onward(const struct nlattr 
*attrs[OVS_KEY_ATTR_MAX + 1],
                              flow, src_flow)) {
             return ODP_FIT_ERROR;
         }
-
+        encap_fitness = parse_l2_5_onward(attrs, present_attrs,
+                                          out_of_range_attr,
+                                          &expected_attrs,
+                                          flow, key, key_len,
+                                          src_flow, false);
+        if (encap_fitness != ODP_FIT_PERFECT) {
+            return encap_fitness;
+        }
         encaps++;
     }
 
-    encap_fitness = parse_l2_5_onward(attrs, present_attrs, out_of_range_attr,
-                                      expected_attrs, flow, key, key_len,
-                                      src_flow);
-
-    /* The overall fitness is the worse of the outer and inner attributes. */
-    return MAX(fitness, encap_fitness);
+    return ODP_FIT_PERFECT;
 }
 
 static enum odp_key_fitness
@@ -6820,7 +6805,8 @@ odp_flow_key_to_flow__(const struct nlattr *key, size_t 
key_len,
         }
     }
     return parse_l2_5_onward(attrs, present_attrs, out_of_range_attr,
-                             expected_attrs, flow, key, key_len, src_flow);
+                             &expected_attrs, flow, key, key_len,
+                             src_flow, true);
 }
 
 /* Converts the 'key_len' bytes of OVS_KEY_ATTR_* attributes in 'key' to a flow
-- 
1.8.3.1


_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to