@@ -480,6 +480,8 @@ static int vxlan_fdb_replace(struct vxlan_fdb *f,
480
480
rd = list_first_entry_or_null (& f -> remotes , struct vxlan_rdst , list );
481
481
if (!rd )
482
482
return 0 ;
483
+
484
+ dst_cache_reset (& rd -> dst_cache );
483
485
rd -> remote_ip = * ip ;
484
486
rd -> remote_port = port ;
485
487
rd -> remote_vni = vni ;
@@ -501,6 +503,12 @@ static int vxlan_fdb_append(struct vxlan_fdb *f,
501
503
rd = kmalloc (sizeof (* rd ), GFP_ATOMIC );
502
504
if (rd == NULL )
503
505
return - ENOBUFS ;
506
+
507
+ if (dst_cache_init (& rd -> dst_cache , GFP_ATOMIC )) {
508
+ kfree (rd );
509
+ return - ENOBUFS ;
510
+ }
511
+
504
512
rd -> remote_ip = * ip ;
505
513
rd -> remote_port = port ;
506
514
rd -> remote_vni = vni ;
@@ -749,8 +757,10 @@ static void vxlan_fdb_free(struct rcu_head *head)
749
757
struct vxlan_fdb * f = container_of (head , struct vxlan_fdb , rcu );
750
758
struct vxlan_rdst * rd , * nd ;
751
759
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 );
753
762
kfree (rd );
763
+ }
754
764
kfree (f );
755
765
}
756
766
@@ -1754,11 +1764,24 @@ static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst,
1754
1764
1755
1765
static struct rtable * vxlan_get_route (struct vxlan_dev * vxlan ,
1756
1766
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 )
1758
1770
{
1759
1771
struct rtable * rt = NULL ;
1772
+ bool use_cache = false;
1760
1773
struct flowi4 fl4 ;
1761
1774
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
+
1762
1785
memset (& fl4 , 0 , sizeof (fl4 ));
1763
1786
fl4 .flowi4_oif = oif ;
1764
1787
fl4 .flowi4_tos = RT_TOS (tos );
@@ -1768,21 +1791,33 @@ static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan,
1768
1791
fl4 .saddr = vxlan -> cfg .saddr .sin .sin_addr .s_addr ;
1769
1792
1770
1793
rt = ip_route_output_key (vxlan -> net , & fl4 );
1771
- if (!IS_ERR (rt ))
1794
+ if (!IS_ERR (rt )) {
1772
1795
* saddr = fl4 .saddr ;
1796
+ if (use_cache )
1797
+ dst_cache_set_ip4 (dst_cache , & rt -> dst , fl4 .saddr );
1798
+ }
1773
1799
return rt ;
1774
1800
}
1775
1801
1776
1802
#if IS_ENABLED (CONFIG_IPV6 )
1777
1803
static struct dst_entry * vxlan6_get_route (struct vxlan_dev * vxlan ,
1778
1804
struct sk_buff * skb , int oif ,
1779
1805
const struct in6_addr * daddr ,
1780
- struct in6_addr * saddr )
1806
+ struct in6_addr * saddr ,
1807
+ struct dst_cache * dst_cache )
1781
1808
{
1809
+ bool use_cache = false;
1782
1810
struct dst_entry * ndst ;
1783
1811
struct flowi6 fl6 ;
1784
1812
int err ;
1785
1813
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
+
1786
1821
memset (& fl6 , 0 , sizeof (fl6 ));
1787
1822
fl6 .flowi6_oif = oif ;
1788
1823
fl6 .daddr = * daddr ;
@@ -1797,6 +1832,8 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
1797
1832
return ERR_PTR (err );
1798
1833
1799
1834
* saddr = fl6 .saddr ;
1835
+ if (use_cache )
1836
+ dst_cache_set_ip6 (dst_cache , ndst , saddr );
1800
1837
return ndst ;
1801
1838
}
1802
1839
#endif
@@ -1938,7 +1975,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
1938
1975
1939
1976
rt = vxlan_get_route (vxlan , skb ,
1940
1977
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 );
1942
1980
if (IS_ERR (rt )) {
1943
1981
netdev_dbg (dev , "no route to %pI4\n" ,
1944
1982
& dst -> sin .sin_addr .s_addr );
@@ -1990,7 +2028,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
1990
2028
1991
2029
ndst = vxlan6_get_route (vxlan , skb ,
1992
2030
rdst ? rdst -> remote_ifindex : 0 ,
1993
- & dst -> sin6 .sin6_addr , & saddr );
2031
+ & dst -> sin6 .sin6_addr , & saddr ,
2032
+ rdst ? & rdst -> dst_cache : NULL );
1994
2033
if (IS_ERR (ndst )) {
1995
2034
netdev_dbg (dev , "no route to %pI6\n" ,
1996
2035
& dst -> sin6 .sin6_addr );
@@ -2331,7 +2370,7 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
2331
2370
return - EINVAL ;
2332
2371
rt = vxlan_get_route (vxlan , skb , 0 , info -> key .tos ,
2333
2372
info -> key .u .ipv4 .dst ,
2334
- & info -> key .u .ipv4 .src );
2373
+ & info -> key .u .ipv4 .src , NULL , info );
2335
2374
if (IS_ERR (rt ))
2336
2375
return PTR_ERR (rt );
2337
2376
ip_rt_put (rt );
@@ -2343,7 +2382,7 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
2343
2382
return - EINVAL ;
2344
2383
ndst = vxlan6_get_route (vxlan , skb , 0 ,
2345
2384
& info -> key .u .ipv6 .dst ,
2346
- & info -> key .u .ipv6 .src );
2385
+ & info -> key .u .ipv6 .src , NULL );
2347
2386
if (IS_ERR (ndst ))
2348
2387
return PTR_ERR (ndst );
2349
2388
dst_release (ndst );
0 commit comments