Commit e9350d44 authored by David S. Miller's avatar David S. Miller

Merge branch '1GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/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: default avatarDavid S. Miller <davem@davemloft.net>
parents c8ad0892 e086be9a
...@@ -491,6 +491,8 @@ ...@@ -491,6 +491,8 @@
* manageability enabled, allowing us room for 15 multicast addresses. * manageability enabled, allowing us room for 15 multicast addresses.
*/ */
#define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */ #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_RAL_MAC_ADDR_LEN 4
#define E1000_RAH_MAC_ADDR_LEN 2 #define E1000_RAH_MAC_ADDR_LEN 2
#define E1000_RAH_POOL_MASK 0x03FC0000 #define E1000_RAH_POOL_MASK 0x03FC0000
......
...@@ -442,6 +442,8 @@ struct hwmon_buff { ...@@ -442,6 +442,8 @@ struct hwmon_buff {
enum igb_filter_match_flags { enum igb_filter_match_flags {
IGB_FILTER_FLAG_ETHER_TYPE = 0x1, IGB_FILTER_FLAG_ETHER_TYPE = 0x1,
IGB_FILTER_FLAG_VLAN_TCI = 0x2, 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 #define IGB_MAX_RXNFC_FILTERS 16
...@@ -456,11 +458,14 @@ struct igb_nfc_input { ...@@ -456,11 +458,14 @@ struct igb_nfc_input {
u8 match_flags; u8 match_flags;
__be16 etype; __be16 etype;
__be16 vlan_tci; __be16 vlan_tci;
u8 src_addr[ETH_ALEN];
u8 dst_addr[ETH_ALEN];
}; };
struct igb_nfc_filter { struct igb_nfc_filter {
struct hlist_node nfc_node; struct hlist_node nfc_node;
struct igb_nfc_input filter; struct igb_nfc_input filter;
unsigned long cookie;
u16 etype_reg_index; u16 etype_reg_index;
u16 sw_idx; u16 sw_idx;
u16 action; u16 action;
...@@ -474,6 +479,8 @@ struct igb_mac_addr { ...@@ -474,6 +479,8 @@ struct igb_mac_addr {
#define IGB_MAC_STATE_DEFAULT 0x1 #define IGB_MAC_STATE_DEFAULT 0x1
#define IGB_MAC_STATE_IN_USE 0x2 #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 */ /* board specific private data structure */
struct igb_adapter { struct igb_adapter {
...@@ -598,6 +605,7 @@ struct igb_adapter { ...@@ -598,6 +605,7 @@ struct igb_adapter {
/* RX network flow classification support */ /* RX network flow classification support */
struct hlist_head nfc_filter_list; struct hlist_head nfc_filter_list;
struct hlist_head cls_flower_list;
unsigned int nfc_filter_count; unsigned int nfc_filter_count;
/* lock for RX network flow classification filter */ /* lock for RX network flow classification filter */
spinlock_t nfc_lock; spinlock_t nfc_lock;
...@@ -739,4 +747,9 @@ int igb_add_filter(struct igb_adapter *adapter, ...@@ -739,4 +747,9 @@ int igb_add_filter(struct igb_adapter *adapter,
int igb_erase_filter(struct igb_adapter *adapter, int igb_erase_filter(struct igb_adapter *adapter,
struct igb_nfc_filter *input); 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_ */ #endif /* _IGB_H_ */
...@@ -2495,6 +2495,23 @@ static int igb_get_ethtool_nfc_entry(struct igb_adapter *adapter, ...@@ -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->h_ext.vlan_tci = rule->filter.vlan_tci;
fsp->m_ext.vlan_tci = htons(VLAN_PRIO_MASK); 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 0;
} }
return -EINVAL; return -EINVAL;
...@@ -2768,14 +2785,41 @@ static int igb_rxnfc_write_vlan_prio_filter(struct igb_adapter *adapter, ...@@ -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) int igb_add_filter(struct igb_adapter *adapter, struct igb_nfc_filter *input)
{ {
struct e1000_hw *hw = &adapter->hw;
int err = -EINVAL; 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) { if (input->filter.match_flags & IGB_FILTER_FLAG_ETHER_TYPE) {
err = igb_rxnfc_write_etype_filter(adapter, input); err = igb_rxnfc_write_etype_filter(adapter, input);
if (err) if (err)
return 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) if (input->filter.match_flags & IGB_FILTER_FLAG_VLAN_TCI)
err = igb_rxnfc_write_vlan_prio_filter(adapter, input); err = igb_rxnfc_write_vlan_prio_filter(adapter, input);
...@@ -2824,6 +2868,15 @@ int igb_erase_filter(struct igb_adapter *adapter, struct igb_nfc_filter *input) ...@@ -2824,6 +2868,15 @@ int igb_erase_filter(struct igb_adapter *adapter, struct igb_nfc_filter *input)
igb_clear_vlan_prio_filter(adapter, igb_clear_vlan_prio_filter(adapter,
ntohs(input->filter.vlan_tci)); 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; return 0;
} }
...@@ -2865,7 +2918,7 @@ static int igb_update_ethtool_nfc_entry(struct igb_adapter *adapter, ...@@ -2865,7 +2918,7 @@ static int igb_update_ethtool_nfc_entry(struct igb_adapter *adapter,
/* add filter to the list */ /* add filter to the list */
if (parent) if (parent)
hlist_add_behind(&parent->nfc_node, &input->nfc_node); hlist_add_behind(&input->nfc_node, &parent->nfc_node);
else else
hlist_add_head(&input->nfc_node, &adapter->nfc_filter_list); hlist_add_head(&input->nfc_node, &adapter->nfc_filter_list);
...@@ -2905,10 +2958,6 @@ static int igb_add_ethtool_nfc_entry(struct igb_adapter *adapter, ...@@ -2905,10 +2958,6 @@ static int igb_add_ethtool_nfc_entry(struct igb_adapter *adapter,
if ((fsp->flow_type & ~FLOW_EXT) != ETHER_FLOW) if ((fsp->flow_type & ~FLOW_EXT) != ETHER_FLOW)
return -EINVAL; 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); input = kzalloc(sizeof(*input), GFP_KERNEL);
if (!input) if (!input)
return -ENOMEM; return -ENOMEM;
...@@ -2918,6 +2967,20 @@ static int igb_add_ethtool_nfc_entry(struct igb_adapter *adapter, ...@@ -2918,6 +2967,20 @@ static int igb_add_ethtool_nfc_entry(struct igb_adapter *adapter,
input->filter.match_flags = IGB_FILTER_FLAG_ETHER_TYPE; 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->flow_type & FLOW_EXT) && fsp->m_ext.vlan_tci) {
if (fsp->m_ext.vlan_tci != htons(VLAN_PRIO_MASK)) { if (fsp->m_ext.vlan_tci != htons(VLAN_PRIO_MASK)) {
err = -EINVAL; err = -EINVAL;
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment