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