diff options
author | Paolo Abeni <pabeni@redhat.com> | 2016-02-26 04:45:40 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-03-01 15:54:30 -0500 |
commit | eaea34b23c46bf17b4a5638be69ab3561854f34b (patch) | |
tree | 1a2182f40f905d60de941bda9513864eb22fe9ab | |
parent | 3a927bc7cf9d0fbe8f4a8189dd5f8440228f64e7 (diff) |
net/tun: implement ndo_set_rx_headroom
ndo_set_rx_headroom controls the align value used by tun devices to
allocate skbs on frame reception.
When the xmit device adds a large encapsulation, this avoids an skb
head reallocation on forwarding.
The measured improvement when forwarding towards a vxlan dev with
frame size below the egress device MTU is as follow:
vxlan over ipv6, bridged: +6%
vxlan over ipv6, ovs: +7%
In case of ipv4 tunnels there is no improvement, since the tun
device default alignment provides enough headroom to avoid the skb
head reallocation.
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/tun.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 88bb8cc3555b..afdf950617c3 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -187,6 +187,7 @@ struct tun_struct { | |||
187 | #define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \ | 187 | #define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \ |
188 | NETIF_F_TSO6|NETIF_F_UFO) | 188 | NETIF_F_TSO6|NETIF_F_UFO) |
189 | 189 | ||
190 | int align; | ||
190 | int vnet_hdr_sz; | 191 | int vnet_hdr_sz; |
191 | int sndbuf; | 192 | int sndbuf; |
192 | struct tap_filter txflt; | 193 | struct tap_filter txflt; |
@@ -934,6 +935,17 @@ static void tun_poll_controller(struct net_device *dev) | |||
934 | return; | 935 | return; |
935 | } | 936 | } |
936 | #endif | 937 | #endif |
938 | |||
939 | static void tun_set_headroom(struct net_device *dev, int new_hr) | ||
940 | { | ||
941 | struct tun_struct *tun = netdev_priv(dev); | ||
942 | |||
943 | if (new_hr < NET_SKB_PAD) | ||
944 | new_hr = NET_SKB_PAD; | ||
945 | |||
946 | tun->align = new_hr; | ||
947 | } | ||
948 | |||
937 | static const struct net_device_ops tun_netdev_ops = { | 949 | static const struct net_device_ops tun_netdev_ops = { |
938 | .ndo_uninit = tun_net_uninit, | 950 | .ndo_uninit = tun_net_uninit, |
939 | .ndo_open = tun_net_open, | 951 | .ndo_open = tun_net_open, |
@@ -945,6 +957,7 @@ static const struct net_device_ops tun_netdev_ops = { | |||
945 | #ifdef CONFIG_NET_POLL_CONTROLLER | 957 | #ifdef CONFIG_NET_POLL_CONTROLLER |
946 | .ndo_poll_controller = tun_poll_controller, | 958 | .ndo_poll_controller = tun_poll_controller, |
947 | #endif | 959 | #endif |
960 | .ndo_set_rx_headroom = tun_set_headroom, | ||
948 | }; | 961 | }; |
949 | 962 | ||
950 | static const struct net_device_ops tap_netdev_ops = { | 963 | static const struct net_device_ops tap_netdev_ops = { |
@@ -962,6 +975,7 @@ static const struct net_device_ops tap_netdev_ops = { | |||
962 | .ndo_poll_controller = tun_poll_controller, | 975 | .ndo_poll_controller = tun_poll_controller, |
963 | #endif | 976 | #endif |
964 | .ndo_features_check = passthru_features_check, | 977 | .ndo_features_check = passthru_features_check, |
978 | .ndo_set_rx_headroom = tun_set_headroom, | ||
965 | }; | 979 | }; |
966 | 980 | ||
967 | static void tun_flow_init(struct tun_struct *tun) | 981 | static void tun_flow_init(struct tun_struct *tun) |
@@ -1086,7 +1100,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1086 | struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; | 1100 | struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; |
1087 | struct sk_buff *skb; | 1101 | struct sk_buff *skb; |
1088 | size_t total_len = iov_iter_count(from); | 1102 | size_t total_len = iov_iter_count(from); |
1089 | size_t len = total_len, align = NET_SKB_PAD, linear; | 1103 | size_t len = total_len, align = tun->align, linear; |
1090 | struct virtio_net_hdr gso = { 0 }; | 1104 | struct virtio_net_hdr gso = { 0 }; |
1091 | int good_linear; | 1105 | int good_linear; |
1092 | int copylen; | 1106 | int copylen; |
@@ -1694,6 +1708,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
1694 | tun->txflt.count = 0; | 1708 | tun->txflt.count = 0; |
1695 | tun->vnet_hdr_sz = sizeof(struct virtio_net_hdr); | 1709 | tun->vnet_hdr_sz = sizeof(struct virtio_net_hdr); |
1696 | 1710 | ||
1711 | tun->align = NET_SKB_PAD; | ||
1697 | tun->filter_attached = false; | 1712 | tun->filter_attached = false; |
1698 | tun->sndbuf = tfile->socket.sk->sk_sndbuf; | 1713 | tun->sndbuf = tfile->socket.sk->sk_sndbuf; |
1699 | 1714 | ||