Commit 163e5292 authored by Paolo Abeni's avatar Paolo Abeni Committed by David S. Miller

veth: implement ndo_set_rx_headroom

The rx headroom for veth dev is the peer device needed_headroom.
Avoid ping-pong updates setting the private flag IFF_PHONY_HEADROOM.

This avoids skb head reallocation when forwarding from a veth dev
towards a device adding some kind of encapsulation.

When transmitting frames below the MTU size towards a vxlan device,
this gives about 10% performance speed-up when OVS is used to connect
the veth and the vxlan device and a little more when using a
plain Linux bridge.
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent eaea34b2
...@@ -35,6 +35,7 @@ struct pcpu_vstats { ...@@ -35,6 +35,7 @@ struct pcpu_vstats {
struct veth_priv { struct veth_priv {
struct net_device __rcu *peer; struct net_device __rcu *peer;
atomic64_t dropped; atomic64_t dropped;
unsigned requested_headroom;
}; };
/* /*
...@@ -271,6 +272,29 @@ static int veth_get_iflink(const struct net_device *dev) ...@@ -271,6 +272,29 @@ static int veth_get_iflink(const struct net_device *dev)
return iflink; return iflink;
} }
static void veth_set_rx_headroom(struct net_device *dev, int new_hr)
{
struct veth_priv *peer_priv, *priv = netdev_priv(dev);
struct net_device *peer;
if (new_hr < 0)
new_hr = 0;
rcu_read_lock();
peer = rcu_dereference(priv->peer);
if (unlikely(!peer))
goto out;
peer_priv = netdev_priv(peer);
priv->requested_headroom = new_hr;
new_hr = max(priv->requested_headroom, peer_priv->requested_headroom);
dev->needed_headroom = new_hr;
peer->needed_headroom = new_hr;
out:
rcu_read_unlock();
}
static const struct net_device_ops veth_netdev_ops = { static const struct net_device_ops veth_netdev_ops = {
.ndo_init = veth_dev_init, .ndo_init = veth_dev_init,
.ndo_open = veth_open, .ndo_open = veth_open,
...@@ -285,6 +309,7 @@ static const struct net_device_ops veth_netdev_ops = { ...@@ -285,6 +309,7 @@ static const struct net_device_ops veth_netdev_ops = {
#endif #endif
.ndo_get_iflink = veth_get_iflink, .ndo_get_iflink = veth_get_iflink,
.ndo_features_check = passthru_features_check, .ndo_features_check = passthru_features_check,
.ndo_set_rx_headroom = veth_set_rx_headroom,
}; };
#define VETH_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \ #define VETH_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \
...@@ -301,6 +326,7 @@ static void veth_setup(struct net_device *dev) ...@@ -301,6 +326,7 @@ static void veth_setup(struct net_device *dev)
dev->priv_flags &= ~IFF_TX_SKB_SHARING; dev->priv_flags &= ~IFF_TX_SKB_SHARING;
dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
dev->priv_flags |= IFF_NO_QUEUE; dev->priv_flags |= IFF_NO_QUEUE;
dev->priv_flags |= IFF_PHONY_HEADROOM;
dev->netdev_ops = &veth_netdev_ops; dev->netdev_ops = &veth_netdev_ops;
dev->ethtool_ops = &veth_ethtool_ops; dev->ethtool_ops = &veth_ethtool_ops;
......
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