Skip to content

Commit b5063cb

Browse files
shifty91anguy11
authored andcommitted
igc: Check VLAN TCI mask
Currently the driver accepts VLAN TCI steering rules regardless of the configured mask. And things might fail silently or with confusing error messages to the user. There are two ways to handle the VLAN TCI mask: 1. Match on the PCP field using a VLAN prio filter 2. Match on complete TCI field using a flex filter Therefore, add checks and code for that. For instance the following rule is invalid and will be converted into a VLAN prio rule which is not correct: |root@host:~# ethtool -N enp3s0 flow-type ether vlan 0x0001 m 0xf000 \ | action 1 |Added rule with ID 61 |root@host:~# ethtool --show-ntuple enp3s0 |4 RX rings available |Total 1 rules | |Filter: 61 | Flow Type: Raw Ethernet | Src MAC addr: 00:00:00:00:00:00 mask: FF:FF:FF:FF:FF:FF | Dest MAC addr: 00:00:00:00:00:00 mask: FF:FF:FF:FF:FF:FF | Ethertype: 0x0 mask: 0xFFFF | VLAN EtherType: 0x0 mask: 0xffff | VLAN: 0x1 mask: 0x1fff | User-defined: 0x0 mask: 0xffffffffffffffff | Action: Direct to queue 1 After: |root@host:~# ethtool -N enp3s0 flow-type ether vlan 0x0001 m 0xf000 \ | action 1 |rmgr: Cannot insert RX class rule: Operation not supported Fixes: 7991487 ("igc: Allow for Flex Filters to be installed") Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de> Acked-by: Vinicius Costa Gomes <vinicius.gomes@intel.com> Reviewed-by: Simon Horman <horms@kernel.org> Tested-by: Naama Meir <naamax.meir@linux.intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
1 parent 088464a commit b5063cb

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

drivers/net/ethernet/intel/igc/igc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,7 @@ struct igc_nfc_filter {
568568
u16 etype;
569569
__be16 vlan_etype;
570570
u16 vlan_tci;
571+
u16 vlan_tci_mask;
571572
u8 src_addr[ETH_ALEN];
572573
u8 dst_addr[ETH_ALEN];
573574
u8 user_data[8];

drivers/net/ethernet/intel/igc/igc_ethtool.c

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,7 @@ static int igc_ethtool_set_coalesce(struct net_device *netdev,
958958
}
959959

960960
#define ETHER_TYPE_FULL_MASK ((__force __be16)~0)
961+
#define VLAN_TCI_FULL_MASK ((__force __be16)~0)
961962
static int igc_ethtool_get_nfc_rule(struct igc_adapter *adapter,
962963
struct ethtool_rxnfc *cmd)
963964
{
@@ -989,7 +990,7 @@ static int igc_ethtool_get_nfc_rule(struct igc_adapter *adapter,
989990
if (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) {
990991
fsp->flow_type |= FLOW_EXT;
991992
fsp->h_ext.vlan_tci = htons(rule->filter.vlan_tci);
992-
fsp->m_ext.vlan_tci = htons(VLAN_PRIO_MASK);
993+
fsp->m_ext.vlan_tci = htons(rule->filter.vlan_tci_mask);
993994
}
994995

995996
if (rule->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR) {
@@ -1224,6 +1225,7 @@ static void igc_ethtool_init_nfc_rule(struct igc_nfc_rule *rule,
12241225

12251226
if ((fsp->flow_type & FLOW_EXT) && fsp->m_ext.vlan_tci) {
12261227
rule->filter.vlan_tci = ntohs(fsp->h_ext.vlan_tci);
1228+
rule->filter.vlan_tci_mask = ntohs(fsp->m_ext.vlan_tci);
12271229
rule->filter.match_flags |= IGC_FILTER_FLAG_VLAN_TCI;
12281230
}
12291231

@@ -1261,11 +1263,19 @@ static void igc_ethtool_init_nfc_rule(struct igc_nfc_rule *rule,
12611263
memcpy(rule->filter.user_mask, fsp->m_ext.data, sizeof(fsp->m_ext.data));
12621264
}
12631265

1264-
/* When multiple filter options or user data or vlan etype is set, use a
1265-
* flex filter.
1266+
/* The i225/i226 has various different filters. Flex filters provide a
1267+
* way to match up to the first 128 bytes of a packet. Use them for:
1268+
* a) For specific user data
1269+
* b) For VLAN EtherType
1270+
* c) For full TCI match
1271+
* d) Or in case multiple filter criteria are set
1272+
*
1273+
* Otherwise, use the simple MAC, VLAN PRIO or EtherType filters.
12661274
*/
12671275
if ((rule->filter.match_flags & IGC_FILTER_FLAG_USER_DATA) ||
12681276
(rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_ETYPE) ||
1277+
((rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) &&
1278+
rule->filter.vlan_tci_mask == ntohs(VLAN_TCI_FULL_MASK)) ||
12691279
(rule->filter.match_flags & (rule->filter.match_flags - 1)))
12701280
rule->flex = true;
12711281
else
@@ -1335,6 +1345,18 @@ static int igc_ethtool_add_nfc_rule(struct igc_adapter *adapter,
13351345
return -EINVAL;
13361346
}
13371347

1348+
/* There are two ways to match the VLAN TCI:
1349+
* 1. Match on PCP field and use vlan prio filter for it
1350+
* 2. Match on complete TCI field and use flex filter for it
1351+
*/
1352+
if ((fsp->flow_type & FLOW_EXT) &&
1353+
fsp->m_ext.vlan_tci &&
1354+
fsp->m_ext.vlan_tci != htons(VLAN_PRIO_MASK) &&
1355+
fsp->m_ext.vlan_tci != VLAN_TCI_FULL_MASK) {
1356+
netdev_dbg(netdev, "VLAN mask not supported\n");
1357+
return -EOPNOTSUPP;
1358+
}
1359+
13381360
if (fsp->location >= IGC_MAX_RXNFC_RULES) {
13391361
netdev_dbg(netdev, "Invalid location\n");
13401362
return -EINVAL;

0 commit comments

Comments
 (0)