Skip to content

Commit

Permalink
Merge branch '1GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/…
Browse files Browse the repository at this point in the history
…jkirsher/next-queue

Jeff Kirsher says:

====================
1GbE Intel Wired LAN Driver Updates 2018-04-25

This series enables some ethtool and tc-flower filters to be offloaded
to igb-based network controllers. This is useful when the system
configuration wants to steer kinds of traffic to a specific hardware
queue for i210 devices only.

The first two patch in the series are bug fixes.

The basis of this series is to export the internal API used to
configure address filters, so they can be used by ethtool, and
extending the functionality so an source address can be handled.

Then, we enable the tc-flower offloading implementation to re-use the
same infrastructure as ethtool, and storing them in the per-adapter
"nfc" (Network Filter Config?) list. But for consistency, for
destructive access they are separated, i.e. an filter added by
tc-flower can only be removed by tc-flower, but ethtool can read them
all.

Only support for VLAN Prio, Source and Destination MAC Address, and
Ethertype is enabled for now.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 26, 2018
2 parents c8ad089 + e086be9 commit e9350d4
Show file tree
Hide file tree
Showing 4 changed files with 439 additions and 15 deletions.
2 changes: 2 additions & 0 deletions drivers/net/ethernet/intel/igb/e1000_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,8 @@
* manageability enabled, allowing us room for 15 multicast addresses.
*/
#define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */
#define E1000_RAH_ASEL_SRC_ADDR 0x00010000
#define E1000_RAH_QSEL_ENABLE 0x10000000
#define E1000_RAL_MAC_ADDR_LEN 4
#define E1000_RAH_MAC_ADDR_LEN 2
#define E1000_RAH_POOL_MASK 0x03FC0000
Expand Down
13 changes: 13 additions & 0 deletions drivers/net/ethernet/intel/igb/igb.h
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,8 @@ struct hwmon_buff {
enum igb_filter_match_flags {
IGB_FILTER_FLAG_ETHER_TYPE = 0x1,
IGB_FILTER_FLAG_VLAN_TCI = 0x2,
IGB_FILTER_FLAG_SRC_MAC_ADDR = 0x4,
IGB_FILTER_FLAG_DST_MAC_ADDR = 0x8,
};

#define IGB_MAX_RXNFC_FILTERS 16
Expand All @@ -456,11 +458,14 @@ struct igb_nfc_input {
u8 match_flags;
__be16 etype;
__be16 vlan_tci;
u8 src_addr[ETH_ALEN];
u8 dst_addr[ETH_ALEN];
};

struct igb_nfc_filter {
struct hlist_node nfc_node;
struct igb_nfc_input filter;
unsigned long cookie;
u16 etype_reg_index;
u16 sw_idx;
u16 action;
Expand All @@ -474,6 +479,8 @@ struct igb_mac_addr {

#define IGB_MAC_STATE_DEFAULT 0x1
#define IGB_MAC_STATE_IN_USE 0x2
#define IGB_MAC_STATE_SRC_ADDR 0x4
#define IGB_MAC_STATE_QUEUE_STEERING 0x8

/* board specific private data structure */
struct igb_adapter {
Expand Down Expand Up @@ -598,6 +605,7 @@ struct igb_adapter {

/* RX network flow classification support */
struct hlist_head nfc_filter_list;
struct hlist_head cls_flower_list;
unsigned int nfc_filter_count;
/* lock for RX network flow classification filter */
spinlock_t nfc_lock;
Expand Down Expand Up @@ -739,4 +747,9 @@ int igb_add_filter(struct igb_adapter *adapter,
int igb_erase_filter(struct igb_adapter *adapter,
struct igb_nfc_filter *input);

int igb_add_mac_steering_filter(struct igb_adapter *adapter,
const u8 *addr, u8 queue, u8 flags);
int igb_del_mac_steering_filter(struct igb_adapter *adapter,
const u8 *addr, u8 queue, u8 flags);

#endif /* _IGB_H_ */
73 changes: 68 additions & 5 deletions drivers/net/ethernet/intel/igb/igb_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -2495,6 +2495,23 @@ static int igb_get_ethtool_nfc_entry(struct igb_adapter *adapter,
fsp->h_ext.vlan_tci = rule->filter.vlan_tci;
fsp->m_ext.vlan_tci = htons(VLAN_PRIO_MASK);
}
if (rule->filter.match_flags & IGB_FILTER_FLAG_DST_MAC_ADDR) {
ether_addr_copy(fsp->h_u.ether_spec.h_dest,
rule->filter.dst_addr);
/* As we only support matching by the full
* mask, return the mask to userspace
*/
eth_broadcast_addr(fsp->m_u.ether_spec.h_dest);
}
if (rule->filter.match_flags & IGB_FILTER_FLAG_SRC_MAC_ADDR) {
ether_addr_copy(fsp->h_u.ether_spec.h_source,
rule->filter.src_addr);
/* As we only support matching by the full
* mask, return the mask to userspace
*/
eth_broadcast_addr(fsp->m_u.ether_spec.h_source);
}

return 0;
}
return -EINVAL;
Expand Down Expand Up @@ -2768,14 +2785,41 @@ static int igb_rxnfc_write_vlan_prio_filter(struct igb_adapter *adapter,

int igb_add_filter(struct igb_adapter *adapter, struct igb_nfc_filter *input)
{
struct e1000_hw *hw = &adapter->hw;
int err = -EINVAL;

if (hw->mac.type == e1000_i210 &&
!(input->filter.match_flags & ~IGB_FILTER_FLAG_SRC_MAC_ADDR)) {
dev_err(&adapter->pdev->dev,
"i210 doesn't support flow classification rules specifying only source addresses.\n");
return -EOPNOTSUPP;
}

if (input->filter.match_flags & IGB_FILTER_FLAG_ETHER_TYPE) {
err = igb_rxnfc_write_etype_filter(adapter, input);
if (err)
return err;
}

if (input->filter.match_flags & IGB_FILTER_FLAG_DST_MAC_ADDR) {
err = igb_add_mac_steering_filter(adapter,
input->filter.dst_addr,
input->action, 0);
err = min_t(int, err, 0);
if (err)
return err;
}

if (input->filter.match_flags & IGB_FILTER_FLAG_SRC_MAC_ADDR) {
err = igb_add_mac_steering_filter(adapter,
input->filter.src_addr,
input->action,
IGB_MAC_STATE_SRC_ADDR);
err = min_t(int, err, 0);
if (err)
return err;
}

if (input->filter.match_flags & IGB_FILTER_FLAG_VLAN_TCI)
err = igb_rxnfc_write_vlan_prio_filter(adapter, input);

Expand Down Expand Up @@ -2824,6 +2868,15 @@ int igb_erase_filter(struct igb_adapter *adapter, struct igb_nfc_filter *input)
igb_clear_vlan_prio_filter(adapter,
ntohs(input->filter.vlan_tci));

if (input->filter.match_flags & IGB_FILTER_FLAG_SRC_MAC_ADDR)
igb_del_mac_steering_filter(adapter, input->filter.src_addr,
input->action,
IGB_MAC_STATE_SRC_ADDR);

if (input->filter.match_flags & IGB_FILTER_FLAG_DST_MAC_ADDR)
igb_del_mac_steering_filter(adapter, input->filter.dst_addr,
input->action, 0);

return 0;
}

Expand Down Expand Up @@ -2865,7 +2918,7 @@ static int igb_update_ethtool_nfc_entry(struct igb_adapter *adapter,

/* add filter to the list */
if (parent)
hlist_add_behind(&parent->nfc_node, &input->nfc_node);
hlist_add_behind(&input->nfc_node, &parent->nfc_node);
else
hlist_add_head(&input->nfc_node, &adapter->nfc_filter_list);

Expand Down Expand Up @@ -2905,10 +2958,6 @@ static int igb_add_ethtool_nfc_entry(struct igb_adapter *adapter,
if ((fsp->flow_type & ~FLOW_EXT) != ETHER_FLOW)
return -EINVAL;

if (fsp->m_u.ether_spec.h_proto != ETHER_TYPE_FULL_MASK &&
fsp->m_ext.vlan_tci != htons(VLAN_PRIO_MASK))
return -EINVAL;

input = kzalloc(sizeof(*input), GFP_KERNEL);
if (!input)
return -ENOMEM;
Expand All @@ -2918,6 +2967,20 @@ static int igb_add_ethtool_nfc_entry(struct igb_adapter *adapter,
input->filter.match_flags = IGB_FILTER_FLAG_ETHER_TYPE;
}

/* Only support matching addresses by the full mask */
if (is_broadcast_ether_addr(fsp->m_u.ether_spec.h_source)) {
input->filter.match_flags |= IGB_FILTER_FLAG_SRC_MAC_ADDR;
ether_addr_copy(input->filter.src_addr,
fsp->h_u.ether_spec.h_source);
}

/* Only support matching addresses by the full mask */
if (is_broadcast_ether_addr(fsp->m_u.ether_spec.h_dest)) {
input->filter.match_flags |= IGB_FILTER_FLAG_DST_MAC_ADDR;
ether_addr_copy(input->filter.dst_addr,
fsp->h_u.ether_spec.h_dest);
}

if ((fsp->flow_type & FLOW_EXT) && fsp->m_ext.vlan_tci) {
if (fsp->m_ext.vlan_tci != htons(VLAN_PRIO_MASK)) {
err = -EINVAL;
Expand Down
Loading

0 comments on commit e9350d4

Please sign in to comment.