aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/ip6_fib.h5
-rw-r--r--include/net/net_namespace.h20
-rw-r--r--net/ipv6/addrconf.c3
-rw-r--r--net/ipv6/addrconf_core.c7
-rw-r--r--net/ipv6/ip6_fib.c20
-rw-r--r--net/ipv6/route.c4
6 files changed, 33 insertions, 26 deletions
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 9bcb220bd4ad..cf485f9aa563 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -114,16 +114,13 @@ struct rt6_info {
114 u32 rt6i_flags; 114 u32 rt6i_flags;
115 struct rt6key rt6i_src; 115 struct rt6key rt6i_src;
116 struct rt6key rt6i_prefsrc; 116 struct rt6key rt6i_prefsrc;
117 u32 rt6i_metric;
118 117
119 struct inet6_dev *rt6i_idev; 118 struct inet6_dev *rt6i_idev;
120 unsigned long _rt6i_peer; 119 unsigned long _rt6i_peer;
121 120
122 u32 rt6i_genid; 121 u32 rt6i_metric;
123
124 /* more non-fragment space at head required */ 122 /* more non-fragment space at head required */
125 unsigned short rt6i_nfheader_len; 123 unsigned short rt6i_nfheader_len;
126
127 u8 rt6i_protocol; 124 u8 rt6i_protocol;
128}; 125};
129 126
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 361d26077196..e0d64667a4b3 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -352,26 +352,12 @@ static inline void rt_genid_bump_ipv4(struct net *net)
352 atomic_inc(&net->ipv4.rt_genid); 352 atomic_inc(&net->ipv4.rt_genid);
353} 353}
354 354
355#if IS_ENABLED(CONFIG_IPV6) 355extern void (*__fib6_flush_trees)(struct net *net);
356static inline int rt_genid_ipv6(struct net *net)
357{
358 return atomic_read(&net->ipv6.rt_genid);
359}
360
361static inline void rt_genid_bump_ipv6(struct net *net)
362{
363 atomic_inc(&net->ipv6.rt_genid);
364}
365#else
366static inline int rt_genid_ipv6(struct net *net)
367{
368 return 0;
369}
370
371static inline void rt_genid_bump_ipv6(struct net *net) 356static inline void rt_genid_bump_ipv6(struct net *net)
372{ 357{
358 if (__fib6_flush_trees)
359 __fib6_flush_trees(net);
373} 360}
374#endif
375 361
376#if IS_ENABLED(CONFIG_IEEE802154_6LOWPAN) 362#if IS_ENABLED(CONFIG_IEEE802154_6LOWPAN)
377static inline struct netns_ieee802154_lowpan * 363static inline struct netns_ieee802154_lowpan *
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 3342ee64f2e3..3e118dfddd02 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4780,10 +4780,11 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
4780 4780
4781 if (ip6_del_rt(ifp->rt)) 4781 if (ip6_del_rt(ifp->rt))
4782 dst_free(&ifp->rt->dst); 4782 dst_free(&ifp->rt->dst);
4783
4784 rt_genid_bump_ipv6(net);
4783 break; 4785 break;
4784 } 4786 }
4785 atomic_inc(&net->ipv6.dev_addr_genid); 4787 atomic_inc(&net->ipv6.dev_addr_genid);
4786 rt_genid_bump_ipv6(net);
4787} 4788}
4788 4789
4789static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) 4790static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
index e6960457f625..98cc4cd570e2 100644
--- a/net/ipv6/addrconf_core.c
+++ b/net/ipv6/addrconf_core.c
@@ -8,6 +8,13 @@
8#include <net/addrconf.h> 8#include <net/addrconf.h>
9#include <net/ip.h> 9#include <net/ip.h>
10 10
11/* if ipv6 module registers this function is used by xfrm to force all
12 * sockets to relookup their nodes - this is fairly expensive, be
13 * careful
14 */
15void (*__fib6_flush_trees)(struct net *);
16EXPORT_SYMBOL(__fib6_flush_trees);
17
11#define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) 18#define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16)
12 19
13static inline unsigned int ipv6_addr_scope2type(unsigned int scope) 20static inline unsigned int ipv6_addr_scope2type(unsigned int scope)
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 76b7f5ee8f4c..97b9fa8de377 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1605,6 +1605,24 @@ static void fib6_prune_clones(struct net *net, struct fib6_node *fn)
1605 fib6_clean_tree(net, fn, fib6_prune_clone, 1, NULL); 1605 fib6_clean_tree(net, fn, fib6_prune_clone, 1, NULL);
1606} 1606}
1607 1607
1608static int fib6_update_sernum(struct rt6_info *rt, void *arg)
1609{
1610 __u32 sernum = *(__u32 *)arg;
1611
1612 if (rt->rt6i_node &&
1613 rt->rt6i_node->fn_sernum != sernum)
1614 rt->rt6i_node->fn_sernum = sernum;
1615
1616 return 0;
1617}
1618
1619static void fib6_flush_trees(struct net *net)
1620{
1621 __u32 new_sernum = fib6_new_sernum();
1622
1623 fib6_clean_all(net, fib6_update_sernum, &new_sernum);
1624}
1625
1608/* 1626/*
1609 * Garbage collection 1627 * Garbage collection
1610 */ 1628 */
@@ -1788,6 +1806,8 @@ int __init fib6_init(void)
1788 NULL); 1806 NULL);
1789 if (ret) 1807 if (ret)
1790 goto out_unregister_subsys; 1808 goto out_unregister_subsys;
1809
1810 __fib6_flush_trees = fib6_flush_trees;
1791out: 1811out:
1792 return ret; 1812 return ret;
1793 1813
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index f23fbd28a501..bafde82324c5 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -314,7 +314,6 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net,
314 314
315 memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); 315 memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
316 rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); 316 rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers);
317 rt->rt6i_genid = rt_genid_ipv6(net);
318 INIT_LIST_HEAD(&rt->rt6i_siblings); 317 INIT_LIST_HEAD(&rt->rt6i_siblings);
319 } 318 }
320 return rt; 319 return rt;
@@ -1098,9 +1097,6 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
1098 * DST_OBSOLETE_FORCE_CHK which forces validation calls down 1097 * DST_OBSOLETE_FORCE_CHK which forces validation calls down
1099 * into this function always. 1098 * into this function always.
1100 */ 1099 */
1101 if (rt->rt6i_genid != rt_genid_ipv6(dev_net(rt->dst.dev)))
1102 return NULL;
1103
1104 if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie)) 1100 if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie))
1105 return NULL; 1101 return NULL;
1106 1102