Skip to content

Commit 0c1d70a

Browse files
Paolo Abenidavem330
authored andcommitted
net: use dst_cache for vxlan device
In case of UDP traffic with datagram length below MTU this give about 3% performance increase when tunneling over ipv4 and about 70% when tunneling over ipv6. Signed-off-by: Paolo Abeni <pabeni@redhat.com> Suggested-and-acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent e09acdd commit 0c1d70a

File tree

2 files changed

+48
-8
lines changed

2 files changed

+48
-8
lines changed

drivers/net/vxlan.c

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,8 @@ static int vxlan_fdb_replace(struct vxlan_fdb *f,
480480
rd = list_first_entry_or_null(&f->remotes, struct vxlan_rdst, list);
481481
if (!rd)
482482
return 0;
483+
484+
dst_cache_reset(&rd->dst_cache);
483485
rd->remote_ip = *ip;
484486
rd->remote_port = port;
485487
rd->remote_vni = vni;
@@ -501,6 +503,12 @@ static int vxlan_fdb_append(struct vxlan_fdb *f,
501503
rd = kmalloc(sizeof(*rd), GFP_ATOMIC);
502504
if (rd == NULL)
503505
return -ENOBUFS;
506+
507+
if (dst_cache_init(&rd->dst_cache, GFP_ATOMIC)) {
508+
kfree(rd);
509+
return -ENOBUFS;
510+
}
511+
504512
rd->remote_ip = *ip;
505513
rd->remote_port = port;
506514
rd->remote_vni = vni;
@@ -749,8 +757,10 @@ static void vxlan_fdb_free(struct rcu_head *head)
749757
struct vxlan_fdb *f = container_of(head, struct vxlan_fdb, rcu);
750758
struct vxlan_rdst *rd, *nd;
751759

752-
list_for_each_entry_safe(rd, nd, &f->remotes, list)
760+
list_for_each_entry_safe(rd, nd, &f->remotes, list) {
761+
dst_cache_destroy(&rd->dst_cache);
753762
kfree(rd);
763+
}
754764
kfree(f);
755765
}
756766

@@ -1754,11 +1764,24 @@ static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst,
17541764

17551765
static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan,
17561766
struct sk_buff *skb, int oif, u8 tos,
1757-
__be32 daddr, __be32 *saddr)
1767+
__be32 daddr, __be32 *saddr,
1768+
struct dst_cache *dst_cache,
1769+
struct ip_tunnel_info *info)
17581770
{
17591771
struct rtable *rt = NULL;
1772+
bool use_cache = false;
17601773
struct flowi4 fl4;
17611774

1775+
/* when the ip_tunnel_info is availble, the tos used for lookup is
1776+
* packet independent, so we can use the cache
1777+
*/
1778+
if (dst_cache && !skb->mark && (!tos || info)) {
1779+
use_cache = true;
1780+
rt = dst_cache_get_ip4(dst_cache, saddr);
1781+
if (rt)
1782+
return rt;
1783+
}
1784+
17621785
memset(&fl4, 0, sizeof(fl4));
17631786
fl4.flowi4_oif = oif;
17641787
fl4.flowi4_tos = RT_TOS(tos);
@@ -1768,21 +1791,33 @@ static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan,
17681791
fl4.saddr = vxlan->cfg.saddr.sin.sin_addr.s_addr;
17691792

17701793
rt = ip_route_output_key(vxlan->net, &fl4);
1771-
if (!IS_ERR(rt))
1794+
if (!IS_ERR(rt)) {
17721795
*saddr = fl4.saddr;
1796+
if (use_cache)
1797+
dst_cache_set_ip4(dst_cache, &rt->dst, fl4.saddr);
1798+
}
17731799
return rt;
17741800
}
17751801

17761802
#if IS_ENABLED(CONFIG_IPV6)
17771803
static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
17781804
struct sk_buff *skb, int oif,
17791805
const struct in6_addr *daddr,
1780-
struct in6_addr *saddr)
1806+
struct in6_addr *saddr,
1807+
struct dst_cache *dst_cache)
17811808
{
1809+
bool use_cache = false;
17821810
struct dst_entry *ndst;
17831811
struct flowi6 fl6;
17841812
int err;
17851813

1814+
if (dst_cache && !skb->mark) {
1815+
use_cache = true;
1816+
ndst = dst_cache_get_ip6(dst_cache, saddr);
1817+
if (ndst)
1818+
return ndst;
1819+
}
1820+
17861821
memset(&fl6, 0, sizeof(fl6));
17871822
fl6.flowi6_oif = oif;
17881823
fl6.daddr = *daddr;
@@ -1797,6 +1832,8 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
17971832
return ERR_PTR(err);
17981833

17991834
*saddr = fl6.saddr;
1835+
if (use_cache)
1836+
dst_cache_set_ip6(dst_cache, ndst, saddr);
18001837
return ndst;
18011838
}
18021839
#endif
@@ -1938,7 +1975,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
19381975

19391976
rt = vxlan_get_route(vxlan, skb,
19401977
rdst ? rdst->remote_ifindex : 0, tos,
1941-
dst->sin.sin_addr.s_addr, &saddr);
1978+
dst->sin.sin_addr.s_addr, &saddr,
1979+
rdst ? &rdst->dst_cache : NULL, info);
19421980
if (IS_ERR(rt)) {
19431981
netdev_dbg(dev, "no route to %pI4\n",
19441982
&dst->sin.sin_addr.s_addr);
@@ -1990,7 +2028,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
19902028

19912029
ndst = vxlan6_get_route(vxlan, skb,
19922030
rdst ? rdst->remote_ifindex : 0,
1993-
&dst->sin6.sin6_addr, &saddr);
2031+
&dst->sin6.sin6_addr, &saddr,
2032+
rdst ? &rdst->dst_cache : NULL);
19942033
if (IS_ERR(ndst)) {
19952034
netdev_dbg(dev, "no route to %pI6\n",
19962035
&dst->sin6.sin6_addr);
@@ -2331,7 +2370,7 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
23312370
return -EINVAL;
23322371
rt = vxlan_get_route(vxlan, skb, 0, info->key.tos,
23332372
info->key.u.ipv4.dst,
2334-
&info->key.u.ipv4.src);
2373+
&info->key.u.ipv4.src, NULL, info);
23352374
if (IS_ERR(rt))
23362375
return PTR_ERR(rt);
23372376
ip_rt_put(rt);
@@ -2343,7 +2382,7 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
23432382
return -EINVAL;
23442383
ndst = vxlan6_get_route(vxlan, skb, 0,
23452384
&info->key.u.ipv6.dst,
2346-
&info->key.u.ipv6.src);
2385+
&info->key.u.ipv6.src, NULL);
23472386
if (IS_ERR(ndst))
23482387
return PTR_ERR(ndst);
23492388
dst_release(ndst);

include/net/vxlan.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ struct vxlan_rdst {
148148
u32 remote_ifindex;
149149
struct list_head list;
150150
struct rcu_head rcu;
151+
struct dst_cache dst_cache;
151152
};
152153

153154
struct vxlan_config {

0 commit comments

Comments
 (0)