diff options
author | Eric Dumazet <edumazet@google.com> | 2014-10-05 21:38:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-10-07 13:22:11 -0400 |
commit | 0287587884b15041203b3a362d485e1ab1f24445 (patch) | |
tree | 675ae57663c1ba3ee8768e65e7fb0e6d0259e04c /net/ipv4 | |
parent | fe971b95c22578456ff7198537827841c726d3f7 (diff) |
net: better IFF_XMIT_DST_RELEASE support
Testing xmit_more support with netperf and connected UDP sockets,
I found strange dst refcount false sharing.
Current handling of IFF_XMIT_DST_RELEASE is not optimal.
Dropping dst in validate_xmit_skb() is certainly too late in case
packet was queued by cpu X but dequeued by cpu Y
The logical point to take care of drop/force is in __dev_queue_xmit()
before even taking qdisc lock.
As Julian Anastasov pointed out, need for skb_dst() might come from some
packet schedulers or classifiers.
This patch adds new helper to cleanly express needs of various drivers
or qdiscs/classifiers.
Drivers that need skb_dst() in their ndo_start_xmit() should call
following helper in their setup instead of the prior :
dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
->
netif_keep_dst(dev);
Instead of using a single bit, we use two bits, one being
eventually rebuilt in bonding/team drivers.
The other one, is permanent and blocks IFF_XMIT_DST_RELEASE being
rebuilt in bonding/team. Eventually, we could add something
smarter later.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Julian Anastasov <ja@ssi.bg>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/ip_gre.c | 2 | ||||
-rw-r--r-- | net/ipv4/ip_vti.c | 2 | ||||
-rw-r--r-- | net/ipv4/ipip.c | 2 |
3 files changed, 3 insertions, 3 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 0485ef18d254..12055fdbe716 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -510,7 +510,7 @@ static int ipgre_tunnel_init(struct net_device *dev) | |||
510 | memcpy(dev->broadcast, &iph->daddr, 4); | 510 | memcpy(dev->broadcast, &iph->daddr, 4); |
511 | 511 | ||
512 | dev->flags = IFF_NOARP; | 512 | dev->flags = IFF_NOARP; |
513 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; | 513 | netif_keep_dst(dev); |
514 | dev->addr_len = 4; | 514 | dev->addr_len = 4; |
515 | 515 | ||
516 | if (iph->daddr) { | 516 | if (iph->daddr) { |
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index e453cb724a95..3e861011e4a3 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c | |||
@@ -364,7 +364,7 @@ static int vti_tunnel_init(struct net_device *dev) | |||
364 | dev->iflink = 0; | 364 | dev->iflink = 0; |
365 | dev->addr_len = 4; | 365 | dev->addr_len = 4; |
366 | dev->features |= NETIF_F_LLTX; | 366 | dev->features |= NETIF_F_LLTX; |
367 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; | 367 | netif_keep_dst(dev); |
368 | 368 | ||
369 | return ip_tunnel_init(dev); | 369 | return ip_tunnel_init(dev); |
370 | } | 370 | } |
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index ea88ab3102a8..37096d64730e 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -289,7 +289,7 @@ static void ipip_tunnel_setup(struct net_device *dev) | |||
289 | dev->iflink = 0; | 289 | dev->iflink = 0; |
290 | dev->addr_len = 4; | 290 | dev->addr_len = 4; |
291 | dev->features |= NETIF_F_LLTX; | 291 | dev->features |= NETIF_F_LLTX; |
292 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; | 292 | netif_keep_dst(dev); |
293 | 293 | ||
294 | dev->features |= IPIP_FEATURES; | 294 | dev->features |= IPIP_FEATURES; |
295 | dev->hw_features |= IPIP_FEATURES; | 295 | dev->hw_features |= IPIP_FEATURES; |