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

Merge branch '10GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue

Jeff Kirsher says:

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

This series represents yet another phase of the macvlan cleanup Alex has
been working on.

The main goal of these changes is to make it so that we only support
offloading what we can actually offload and we don't break any existing
functionality. So for example we were claiming to advertise source mode
macvlan and we were doing nothing of the sort, so support for that has been
dropped.

The biggest change with this set is that broadcast/multicast replication is
no longer being supported in software. Alex dropped it as it leads to
scaling issues when a broadcast frame has to be replicated up to 64 times.

Beyond that this set goes through and optimized the time needed to bring up
and tear down the macvlan interfaces on ixgbe and provides a clean way for
us to disable the macvlan offload when needed.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6f5d2959 8315ef6f
...@@ -445,15 +445,14 @@ static void fm10k_type_trans(struct fm10k_ring *rx_ring, ...@@ -445,15 +445,14 @@ static void fm10k_type_trans(struct fm10k_ring *rx_ring,
l2_accel = NULL; l2_accel = NULL;
} }
skb->protocol = eth_type_trans(skb, dev);
/* Record Rx queue, or update macvlan statistics */ /* Record Rx queue, or update macvlan statistics */
if (!l2_accel) if (!l2_accel)
skb_record_rx_queue(skb, rx_ring->queue_index); skb_record_rx_queue(skb, rx_ring->queue_index);
else else
macvlan_count_rx(netdev_priv(dev), skb->len + ETH_HLEN, true, macvlan_count_rx(netdev_priv(dev), skb->len + ETH_HLEN, true,
(skb->pkt_type == PACKET_BROADCAST) || false);
(skb->pkt_type == PACKET_MULTICAST));
skb->protocol = eth_type_trans(skb, dev);
} }
/** /**
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "fm10k.h" #include "fm10k.h"
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <net/udp_tunnel.h> #include <net/udp_tunnel.h>
#include <linux/if_macvlan.h>
/** /**
* fm10k_setup_tx_resources - allocate Tx resources (Descriptors) * fm10k_setup_tx_resources - allocate Tx resources (Descriptors)
...@@ -1254,7 +1255,7 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface) ...@@ -1254,7 +1255,7 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface)
glort = l2_accel->dglort + 1 + i; glort = l2_accel->dglort + 1 + i;
hw->mac.ops.update_xcast_mode(hw, glort, hw->mac.ops.update_xcast_mode(hw, glort,
FM10K_XCAST_MODE_MULTI); FM10K_XCAST_MODE_NONE);
fm10k_queue_mac_request(interface, glort, fm10k_queue_mac_request(interface, glort,
sdev->dev_addr, sdev->dev_addr,
hw->mac.default_vid, true); hw->mac.default_vid, true);
...@@ -1449,6 +1450,13 @@ static void *fm10k_dfwd_add_station(struct net_device *dev, ...@@ -1449,6 +1450,13 @@ static void *fm10k_dfwd_add_station(struct net_device *dev,
int size = 0, i; int size = 0, i;
u16 glort; u16 glort;
/* The hardware supported by fm10k only filters on the destination MAC
* address. In order to avoid issues we only support offloading modes
* where the hardware can actually provide the functionality.
*/
if (!macvlan_supports_dest_filter(sdev))
return ERR_PTR(-EMEDIUMTYPE);
/* allocate l2 accel structure if it is not available */ /* allocate l2 accel structure if it is not available */
if (!l2_accel) { if (!l2_accel) {
/* verify there is enough free GLORTs to support l2_accel */ /* verify there is enough free GLORTs to support l2_accel */
...@@ -1515,7 +1523,7 @@ static void *fm10k_dfwd_add_station(struct net_device *dev, ...@@ -1515,7 +1523,7 @@ static void *fm10k_dfwd_add_station(struct net_device *dev,
if (fm10k_host_mbx_ready(interface)) { if (fm10k_host_mbx_ready(interface)) {
hw->mac.ops.update_xcast_mode(hw, glort, hw->mac.ops.update_xcast_mode(hw, glort,
FM10K_XCAST_MODE_MULTI); FM10K_XCAST_MODE_NONE);
fm10k_queue_mac_request(interface, glort, sdev->dev_addr, fm10k_queue_mac_request(interface, glort, sdev->dev_addr,
hw->mac.default_vid, true); hw->mac.default_vid, true);
} }
......
...@@ -305,7 +305,6 @@ enum ixgbe_ring_state_t { ...@@ -305,7 +305,6 @@ enum ixgbe_ring_state_t {
struct ixgbe_fwd_adapter { struct ixgbe_fwd_adapter {
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
struct net_device *netdev; struct net_device *netdev;
struct ixgbe_adapter *real_adapter;
unsigned int tx_base_queue; unsigned int tx_base_queue;
unsigned int rx_base_queue; unsigned int rx_base_queue;
int pool; int pool;
......
...@@ -266,7 +266,7 @@ int ixgbe_disable_sriov(struct ixgbe_adapter *adapter) ...@@ -266,7 +266,7 @@ int ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
#endif #endif
/* Disable VMDq flag so device will be set in VM mode */ /* Disable VMDq flag so device will be set in VM mode */
if (adapter->ring_feature[RING_F_VMDQ].limit == 1) { if (bitmap_weight(adapter->fwd_bitmask, adapter->num_rx_pools) == 1) {
adapter->flags &= ~IXGBE_FLAG_VMDQ_ENABLED; adapter->flags &= ~IXGBE_FLAG_VMDQ_ENABLED;
adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED; adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED;
rss = min_t(int, ixgbe_max_rss_indices(adapter), rss = min_t(int, ixgbe_max_rss_indices(adapter),
...@@ -312,7 +312,8 @@ static int ixgbe_pci_sriov_enable(struct pci_dev *dev, int num_vfs) ...@@ -312,7 +312,8 @@ static int ixgbe_pci_sriov_enable(struct pci_dev *dev, int num_vfs)
* other values out of range. * other values out of range.
*/ */
num_tc = adapter->hw_tcs; num_tc = adapter->hw_tcs;
num_rx_pools = adapter->num_rx_pools; num_rx_pools = bitmap_weight(adapter->fwd_bitmask,
adapter->num_rx_pools);
limit = (num_tc > 4) ? IXGBE_MAX_VFS_8TC : limit = (num_tc > 4) ? IXGBE_MAX_VFS_8TC :
(num_tc > 1) ? IXGBE_MAX_VFS_4TC : IXGBE_MAX_VFS_1TC; (num_tc > 1) ? IXGBE_MAX_VFS_4TC : IXGBE_MAX_VFS_1TC;
......
...@@ -514,6 +514,7 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -514,6 +514,7 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
const struct macvlan_dev *vlan = netdev_priv(dev); const struct macvlan_dev *vlan = netdev_priv(dev);
const struct macvlan_port *port = vlan->port; const struct macvlan_port *port = vlan->port;
const struct macvlan_dev *dest; const struct macvlan_dev *dest;
void *accel_priv = NULL;
if (vlan->mode == MACVLAN_MODE_BRIDGE) { if (vlan->mode == MACVLAN_MODE_BRIDGE) {
const struct ethhdr *eth = (void *)skb->data; const struct ethhdr *eth = (void *)skb->data;
...@@ -533,9 +534,14 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -533,9 +534,14 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
} }
} }
/* For packets that are non-multicast and not bridged we will pass
* the necessary information so that the lowerdev can distinguish
* the source of the packets via the accel_priv value.
*/
accel_priv = vlan->accel_priv;
xmit_world: xmit_world:
skb->dev = vlan->lowerdev; skb->dev = vlan->lowerdev;
return dev_queue_xmit(skb); return dev_queue_xmit_accel(skb, accel_priv);
} }
static inline netdev_tx_t macvlan_netpoll_send_skb(struct macvlan_dev *vlan, struct sk_buff *skb) static inline netdev_tx_t macvlan_netpoll_send_skb(struct macvlan_dev *vlan, struct sk_buff *skb)
...@@ -552,19 +558,14 @@ static inline netdev_tx_t macvlan_netpoll_send_skb(struct macvlan_dev *vlan, str ...@@ -552,19 +558,14 @@ static inline netdev_tx_t macvlan_netpoll_send_skb(struct macvlan_dev *vlan, str
static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb, static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
struct net_device *dev) struct net_device *dev)
{ {
struct macvlan_dev *vlan = netdev_priv(dev);
unsigned int len = skb->len; unsigned int len = skb->len;
int ret; int ret;
struct macvlan_dev *vlan = netdev_priv(dev);
if (unlikely(netpoll_tx_running(dev))) if (unlikely(netpoll_tx_running(dev)))
return macvlan_netpoll_send_skb(vlan, skb); return macvlan_netpoll_send_skb(vlan, skb);
if (vlan->fwd_priv) { ret = macvlan_queue_xmit(skb, dev);
skb->dev = vlan->lowerdev;
ret = dev_queue_xmit_accel(skb, vlan->fwd_priv);
} else {
ret = macvlan_queue_xmit(skb, dev);
}
if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) { if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
struct vlan_pcpu_stats *pcpu_stats; struct vlan_pcpu_stats *pcpu_stats;
...@@ -613,26 +614,27 @@ static int macvlan_open(struct net_device *dev) ...@@ -613,26 +614,27 @@ static int macvlan_open(struct net_device *dev)
goto hash_add; goto hash_add;
} }
if (lowerdev->features & NETIF_F_HW_L2FW_DOFFLOAD) {
vlan->fwd_priv =
lowerdev->netdev_ops->ndo_dfwd_add_station(lowerdev, dev);
/* If we get a NULL pointer back, or if we get an error
* then we should just fall through to the non accelerated path
*/
if (IS_ERR_OR_NULL(vlan->fwd_priv)) {
vlan->fwd_priv = NULL;
} else
return 0;
}
err = -EBUSY; err = -EBUSY;
if (macvlan_addr_busy(vlan->port, dev->dev_addr)) if (macvlan_addr_busy(vlan->port, dev->dev_addr))
goto out; goto out;
err = dev_uc_add(lowerdev, dev->dev_addr); /* Attempt to populate accel_priv which is used to offload the L2
if (err < 0) * forwarding requests for unicast packets.
goto out; */
if (lowerdev->features & NETIF_F_HW_L2FW_DOFFLOAD)
vlan->accel_priv =
lowerdev->netdev_ops->ndo_dfwd_add_station(lowerdev, dev);
/* If earlier attempt to offload failed, or accel_priv is not
* populated we must add the unicast address to the lower device.
*/
if (IS_ERR_OR_NULL(vlan->accel_priv)) {
vlan->accel_priv = NULL;
err = dev_uc_add(lowerdev, dev->dev_addr);
if (err < 0)
goto out;
}
if (dev->flags & IFF_ALLMULTI) { if (dev->flags & IFF_ALLMULTI) {
err = dev_set_allmulti(lowerdev, 1); err = dev_set_allmulti(lowerdev, 1);
if (err < 0) if (err < 0)
...@@ -653,13 +655,14 @@ static int macvlan_open(struct net_device *dev) ...@@ -653,13 +655,14 @@ static int macvlan_open(struct net_device *dev)
if (dev->flags & IFF_ALLMULTI) if (dev->flags & IFF_ALLMULTI)
dev_set_allmulti(lowerdev, -1); dev_set_allmulti(lowerdev, -1);
del_unicast: del_unicast:
dev_uc_del(lowerdev, dev->dev_addr); if (vlan->accel_priv) {
out:
if (vlan->fwd_priv) {
lowerdev->netdev_ops->ndo_dfwd_del_station(lowerdev, lowerdev->netdev_ops->ndo_dfwd_del_station(lowerdev,
vlan->fwd_priv); vlan->accel_priv);
vlan->fwd_priv = NULL; vlan->accel_priv = NULL;
} else {
dev_uc_del(lowerdev, dev->dev_addr);
} }
out:
return err; return err;
} }
...@@ -668,11 +671,10 @@ static int macvlan_stop(struct net_device *dev) ...@@ -668,11 +671,10 @@ static int macvlan_stop(struct net_device *dev)
struct macvlan_dev *vlan = netdev_priv(dev); struct macvlan_dev *vlan = netdev_priv(dev);
struct net_device *lowerdev = vlan->lowerdev; struct net_device *lowerdev = vlan->lowerdev;
if (vlan->fwd_priv) { if (vlan->accel_priv) {
lowerdev->netdev_ops->ndo_dfwd_del_station(lowerdev, lowerdev->netdev_ops->ndo_dfwd_del_station(lowerdev,
vlan->fwd_priv); vlan->accel_priv);
vlan->fwd_priv = NULL; vlan->accel_priv = NULL;
return 0;
} }
dev_uc_unsync(lowerdev, dev); dev_uc_unsync(lowerdev, dev);
......
...@@ -21,7 +21,7 @@ struct macvlan_dev { ...@@ -21,7 +21,7 @@ struct macvlan_dev {
struct hlist_node hlist; struct hlist_node hlist;
struct macvlan_port *port; struct macvlan_port *port;
struct net_device *lowerdev; struct net_device *lowerdev;
void *fwd_priv; void *accel_priv;
struct vlan_pcpu_stats __percpu *pcpu_stats; struct vlan_pcpu_stats __percpu *pcpu_stats;
DECLARE_BITMAP(mc_filter, MACVLAN_MC_FILTER_SZ); DECLARE_BITMAP(mc_filter, MACVLAN_MC_FILTER_SZ);
...@@ -61,10 +61,6 @@ extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev, ...@@ -61,10 +61,6 @@ extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[], struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
extern void macvlan_count_rx(const struct macvlan_dev *vlan,
unsigned int len, bool success,
bool multicast);
extern void macvlan_dellink(struct net_device *dev, struct list_head *head); extern void macvlan_dellink(struct net_device *dev, struct list_head *head);
extern int macvlan_link_register(struct rtnl_link_ops *ops); extern int macvlan_link_register(struct rtnl_link_ops *ops);
...@@ -86,4 +82,27 @@ macvlan_dev_real_dev(const struct net_device *dev) ...@@ -86,4 +82,27 @@ macvlan_dev_real_dev(const struct net_device *dev)
} }
#endif #endif
static inline void *macvlan_accel_priv(struct net_device *dev)
{
struct macvlan_dev *macvlan = netdev_priv(dev);
return macvlan->accel_priv;
}
static inline bool macvlan_supports_dest_filter(struct net_device *dev)
{
struct macvlan_dev *macvlan = netdev_priv(dev);
return macvlan->mode == MACVLAN_MODE_PRIVATE ||
macvlan->mode == MACVLAN_MODE_VEPA ||
macvlan->mode == MACVLAN_MODE_BRIDGE;
}
static inline int macvlan_release_l2fw_offload(struct net_device *dev)
{
struct macvlan_dev *macvlan = netdev_priv(dev);
macvlan->accel_priv = NULL;
return dev_uc_add(macvlan->lowerdev, dev->dev_addr);
}
#endif /* _LINUX_IF_MACVLAN_H */ #endif /* _LINUX_IF_MACVLAN_H */
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