|
@@ -1968,26 +1968,50 @@ static bool flow_is_multicast_only(struct ib_flow_attr *ib_attr)
|
|
|
is_multicast_ether_addr(eth_spec->val.dst_mac);
|
|
|
}
|
|
|
|
|
|
-static bool is_valid_attr(const struct ib_flow_attr *flow_attr)
|
|
|
+static bool is_valid_ethertype(const struct ib_flow_attr *flow_attr,
|
|
|
+ bool check_inner)
|
|
|
{
|
|
|
union ib_flow_spec *ib_spec = (union ib_flow_spec *)(flow_attr + 1);
|
|
|
- bool has_ipv4_spec = false;
|
|
|
- bool eth_type_ipv4 = true;
|
|
|
+ int inner_bit = check_inner ? IB_FLOW_SPEC_INNER : 0;
|
|
|
+ bool ipv4_spec_valid, ipv6_spec_valid;
|
|
|
+ unsigned int ip_spec_type = 0;
|
|
|
+ bool has_ethertype = false;
|
|
|
unsigned int spec_index;
|
|
|
+ bool mask_valid = true;
|
|
|
+ u16 eth_type = 0;
|
|
|
+ bool type_valid;
|
|
|
|
|
|
/* Validate that ethertype is correct */
|
|
|
for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) {
|
|
|
- if (ib_spec->type == IB_FLOW_SPEC_ETH &&
|
|
|
+ if ((ib_spec->type == (IB_FLOW_SPEC_ETH | inner_bit)) &&
|
|
|
ib_spec->eth.mask.ether_type) {
|
|
|
- if (!((ib_spec->eth.mask.ether_type == htons(0xffff)) &&
|
|
|
- ib_spec->eth.val.ether_type == htons(ETH_P_IP)))
|
|
|
- eth_type_ipv4 = false;
|
|
|
- } else if (ib_spec->type == IB_FLOW_SPEC_IPV4) {
|
|
|
- has_ipv4_spec = true;
|
|
|
+ mask_valid = (ib_spec->eth.mask.ether_type ==
|
|
|
+ htons(0xffff));
|
|
|
+ has_ethertype = true;
|
|
|
+ eth_type = ntohs(ib_spec->eth.val.ether_type);
|
|
|
+ } else if ((ib_spec->type == (IB_FLOW_SPEC_IPV4 | inner_bit)) ||
|
|
|
+ (ib_spec->type == (IB_FLOW_SPEC_IPV6 | inner_bit))) {
|
|
|
+ ip_spec_type = ib_spec->type;
|
|
|
}
|
|
|
ib_spec = (void *)ib_spec + ib_spec->size;
|
|
|
}
|
|
|
- return !has_ipv4_spec || eth_type_ipv4;
|
|
|
+
|
|
|
+ type_valid = (!has_ethertype) || (!ip_spec_type);
|
|
|
+ if (!type_valid && mask_valid) {
|
|
|
+ ipv4_spec_valid = (eth_type == ETH_P_IP) &&
|
|
|
+ (ip_spec_type == (IB_FLOW_SPEC_IPV4 | inner_bit));
|
|
|
+ ipv6_spec_valid = (eth_type == ETH_P_IPV6) &&
|
|
|
+ (ip_spec_type == (IB_FLOW_SPEC_IPV6 | inner_bit));
|
|
|
+ type_valid = ipv4_spec_valid || ipv6_spec_valid;
|
|
|
+ }
|
|
|
+
|
|
|
+ return type_valid;
|
|
|
+}
|
|
|
+
|
|
|
+static bool is_valid_attr(const struct ib_flow_attr *flow_attr)
|
|
|
+{
|
|
|
+ return is_valid_ethertype(flow_attr, false) &&
|
|
|
+ is_valid_ethertype(flow_attr, true);
|
|
|
}
|
|
|
|
|
|
static void put_flow_table(struct mlx5_ib_dev *dev,
|