net: Add layer 2 hardware acceleration operations for macvlan devices
Add a operations structure that allows a network interface to export the fact that it supports package forwarding in hardware between physical interfaces and other mac layer devices assigned to it (such as macvlans). This operaions structure can be used by virtual mac devices to bypass software switching so that forwarding can be done in hardware more efficiently. Signed-off-by: John Fastabend <john.r.fastabend@intel.com> Signed-off-by: Neil Horman <nhorman@tuxdriver.com> CC: Andy Gospodarek <andy@greyhouse.net> CC: "David S. Miller" <davem@davemloft.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
1ec4864b10
commit
a6cc0cfa72
@@ -297,7 +297,13 @@ netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
|
||||
int ret;
|
||||
const struct macvlan_dev *vlan = netdev_priv(dev);
|
||||
|
||||
ret = macvlan_queue_xmit(skb, dev);
|
||||
if (vlan->fwd_priv) {
|
||||
skb->dev = vlan->lowerdev;
|
||||
ret = dev_hard_start_xmit(skb, skb->dev, NULL, vlan->fwd_priv);
|
||||
} else {
|
||||
ret = macvlan_queue_xmit(skb, dev);
|
||||
}
|
||||
|
||||
if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
|
||||
struct macvlan_pcpu_stats *pcpu_stats;
|
||||
|
||||
@@ -347,6 +353,21 @@ static int macvlan_open(struct net_device *dev)
|
||||
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 {
|
||||
dev->features &= ~NETIF_F_LLTX;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
err = -EBUSY;
|
||||
if (macvlan_addr_busy(vlan->port, dev->dev_addr))
|
||||
goto out;
|
||||
@@ -367,6 +388,11 @@ hash_add:
|
||||
del_unicast:
|
||||
dev_uc_del(lowerdev, dev->dev_addr);
|
||||
out:
|
||||
if (vlan->fwd_priv) {
|
||||
lowerdev->netdev_ops->ndo_dfwd_del_station(lowerdev,
|
||||
vlan->fwd_priv);
|
||||
vlan->fwd_priv = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -375,6 +401,13 @@ static int macvlan_stop(struct net_device *dev)
|
||||
struct macvlan_dev *vlan = netdev_priv(dev);
|
||||
struct net_device *lowerdev = vlan->lowerdev;
|
||||
|
||||
if (vlan->fwd_priv) {
|
||||
lowerdev->netdev_ops->ndo_dfwd_del_station(lowerdev,
|
||||
vlan->fwd_priv);
|
||||
vlan->fwd_priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_uc_unsync(lowerdev, dev);
|
||||
dev_mc_unsync(lowerdev, dev);
|
||||
|
||||
@@ -833,6 +866,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
|
||||
if (err < 0)
|
||||
goto destroy_port;
|
||||
|
||||
dev->priv_flags |= IFF_MACVLAN;
|
||||
err = netdev_upper_dev_link(lowerdev, dev);
|
||||
if (err)
|
||||
goto destroy_port;
|
||||
|
Reference in New Issue
Block a user