diff options
-rw-r--r-- | include/net/ip6_fib.h | 5 | ||||
-rw-r--r-- | include/net/net_namespace.h | 20 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 3 | ||||
-rw-r--r-- | net/ipv6/addrconf_core.c | 7 | ||||
-rw-r--r-- | net/ipv6/ip6_fib.c | 20 | ||||
-rw-r--r-- | net/ipv6/route.c | 4 |
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) | 355 | extern void (*__fib6_flush_trees)(struct net *net); |
356 | static inline int rt_genid_ipv6(struct net *net) | ||
357 | { | ||
358 | return atomic_read(&net->ipv6.rt_genid); | ||
359 | } | ||
360 | |||
361 | static inline void rt_genid_bump_ipv6(struct net *net) | ||
362 | { | ||
363 | atomic_inc(&net->ipv6.rt_genid); | ||
364 | } | ||
365 | #else | ||
366 | static inline int rt_genid_ipv6(struct net *net) | ||
367 | { | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static inline void rt_genid_bump_ipv6(struct net *net) | 356 | static 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) |
377 | static inline struct netns_ieee802154_lowpan * | 363 | static 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 | ||
4789 | static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | 4790 | static 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 | */ | ||
15 | void (*__fib6_flush_trees)(struct net *); | ||
16 | EXPORT_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 | ||
13 | static inline unsigned int ipv6_addr_scope2type(unsigned int scope) | 20 | static 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 | ||
1608 | static 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 | |||
1619 | static 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; | ||
1791 | out: | 1811 | out: |
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 | ||