summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Gospodarek <gospo@broadcom.com>2018-04-11 11:50:14 -0400
committerDavid S. Miller <davem@davemloft.net>2018-04-11 14:41:59 -0400
commite85a9be93cf144623a823a0a60e4eda6ee337aef (patch)
tree150b1d3d1c814b3052ca5eba03646a83b838230b
parent7991cb9cfbce1b60ac1cff819350b05de4d902e1 (diff)
bnxt_en: do not allow wildcard matches for L2 flows
Before this patch the following commands would succeed as far as the user was concerned: $ tc qdisc add dev p1p1 ingress $ tc filter add dev p1p1 parent ffff: protocol all \ flower skip_sw action drop $ tc filter add dev p1p1 parent ffff: protocol ipv4 \ flower skip_sw src_mac 00:02:00:00:00:01/44 action drop The current flow offload infrastructure used does not support wildcard matching for ethernet headers, so do not allow the second or third commands to succeed. If a user wants to drop traffic on that interface the protocol and MAC addresses need to be specified explicitly: $ tc qdisc add dev p1p1 ingress $ tc filter add dev p1p1 parent ffff: protocol arp \ flower skip_sw action drop $ tc filter add dev p1p1 parent ffff: protocol ipv4 \ flower skip_sw action drop ... $ tc filter add dev p1p1 parent ffff: protocol ipv4 \ flower skip_sw src_mac 00:02:00:00:00:01 action drop $ tc filter add dev p1p1 parent ffff: protocol ipv4 \ flower skip_sw src_mac 00:02:00:00:00:02 action drop ... There are also checks for VLAN parameters in this patch as other callers may wildcard those parameters even if tc does not. Using different flow infrastructure could allow this to work in the future for L2 flows, but for now it does not. Fixes: 2ae7408fedfe ("bnxt_en: bnxt: add TC flower filter offload support") Signed-off-by: Andy Gospodarek <gospo@broadcom.com> Signed-off-by: Michael Chan <michael.chan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
index 65c2cee35766..ac193408a418 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
@@ -377,6 +377,30 @@ static bool is_wildcard(void *mask, int len)
return true;
}
+static bool is_exactmatch(void *mask, int len)
+{
+ const u8 *p = mask;
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (p[i] != 0xff)
+ return false;
+
+ return true;
+}
+
+static bool bits_set(void *key, int len)
+{
+ const u8 *p = key;
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (p[i] != 0)
+ return true;
+
+ return false;
+}
+
static int bnxt_hwrm_cfa_flow_alloc(struct bnxt *bp, struct bnxt_tc_flow *flow,
__le16 ref_flow_handle,
__le32 tunnel_handle, __le16 *flow_handle)
@@ -764,6 +788,41 @@ static bool bnxt_tc_can_offload(struct bnxt *bp, struct bnxt_tc_flow *flow)
return false;
}
+ /* Currently source/dest MAC cannot be partial wildcard */
+ if (bits_set(&flow->l2_key.smac, sizeof(flow->l2_key.smac)) &&
+ !is_exactmatch(flow->l2_mask.smac, sizeof(flow->l2_mask.smac))) {
+ netdev_info(bp->dev, "Wildcard match unsupported for Source MAC\n");
+ return false;
+ }
+ if (bits_set(&flow->l2_key.dmac, sizeof(flow->l2_key.dmac)) &&
+ !is_exactmatch(&flow->l2_mask.dmac, sizeof(flow->l2_mask.dmac))) {
+ netdev_info(bp->dev, "Wildcard match unsupported for Dest MAC\n");
+ return false;
+ }
+
+ /* Currently VLAN fields cannot be partial wildcard */
+ if (bits_set(&flow->l2_key.inner_vlan_tci,
+ sizeof(flow->l2_key.inner_vlan_tci)) &&
+ !is_exactmatch(&flow->l2_mask.inner_vlan_tci,
+ sizeof(flow->l2_mask.inner_vlan_tci))) {
+ netdev_info(bp->dev, "Wildcard match unsupported for VLAN TCI\n");
+ return false;
+ }
+ if (bits_set(&flow->l2_key.inner_vlan_tpid,
+ sizeof(flow->l2_key.inner_vlan_tpid)) &&
+ !is_exactmatch(&flow->l2_mask.inner_vlan_tpid,
+ sizeof(flow->l2_mask.inner_vlan_tpid))) {
+ netdev_info(bp->dev, "Wildcard match unsupported for VLAN TPID\n");
+ return false;
+ }
+
+ /* Currently Ethertype must be set */
+ if (!is_exactmatch(&flow->l2_mask.ether_type,
+ sizeof(flow->l2_mask.ether_type))) {
+ netdev_info(bp->dev, "Wildcard match unsupported for Ethertype\n");
+ return false;
+ }
+
return true;
}