Message ID | c0a1543fe7608640f2dd1f37f8fe5978f30536d1.1411249633.git.hannes@stressinduktion.org |
---|---|
State | Superseded, archived |
Delegated to: | David Miller |
Headers | show |
Hannes Frederic Sowa wrote: > fib6_flush_trees is still a very costly operation but now is only called > by xfrm code when a policy changes or ipv6 addresses are added/removed. > > fib6_flush_tree must walk all ipv6 routing tables and modify fn_sernum, > so all sockets relookup their dst_entries. Use a NULL callback, so we > only walk the nodes without looking at the rt6_infos. > > Cc: Eric Dumazet <eric.dumazet@gmail.com> > Cc: Vlad Yasevich <vyasevich@gmail.com> > Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com> > Cc: Martin Lau <kafai@fb.com> > Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> > --- > include/net/net_namespace.h | 14 +++----------- > include/net/netns/ipv6.h | 1 - > net/ipv6/addrconf_core.c | 6 ++++++ > net/ipv6/af_inet6.c | 1 - > net/ipv6/ip6_fib.c | 21 +++++++++++++++++---- > net/ipv6/route.c | 4 ---- > 6 files changed, 26 insertions(+), 21 deletions(-) > > diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h > index 361d260..61aad36 100644 > --- a/include/net/net_namespace.h > +++ b/include/net/net_namespace.h > @@ -353,21 +353,13 @@ static inline void rt_genid_bump_ipv4(struct net *net) > } > > #if IS_ENABLED(CONFIG_IPV6) > -static inline int rt_genid_ipv6(struct net *net) > -{ > - return atomic_read(&net->ipv6.rt_genid); > -} > - > +extern void (*__fib6_flush_trees)(struct net *); > static inline void rt_genid_bump_ipv6(struct net *net) > { > - atomic_inc(&net->ipv6.rt_genid); > + if (__fib6_flush_trees) > + __fib6_flush_trees(net); > } > #else Now it does not "bump" the genid anymore. Why not to change the function name to reflect the fact? --yoshfuji -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Sun, Sep 21, 2014, at 04:21, YOSHIFUJI Hideaki wrote: > Now it does not "bump" the genid anymore. Why not to change the > function name to reflect the fact? I first named the new function fib6_flush_trees but then realized this function itself gets called by rt_genid_bump_all, so I left the name. I'll append a patch to generalize those names, because it should not matter for ipv4 or ipv6 how it is ensured that sockets drop their cached dst_entries. Thanks, Hannes -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 361d260..61aad36 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -353,21 +353,13 @@ static inline void rt_genid_bump_ipv4(struct net *net) } #if IS_ENABLED(CONFIG_IPV6) -static inline int rt_genid_ipv6(struct net *net) -{ - return atomic_read(&net->ipv6.rt_genid); -} - +extern void (*__fib6_flush_trees)(struct net *); static inline void rt_genid_bump_ipv6(struct net *net) { - atomic_inc(&net->ipv6.rt_genid); + if (__fib6_flush_trees) + __fib6_flush_trees(net); } #else -static inline int rt_genid_ipv6(struct net *net) -{ - return 0; -} - static inline void rt_genid_bump_ipv6(struct net *net) { } diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h index eade27a..3291ba6 100644 --- a/include/net/netns/ipv6.h +++ b/include/net/netns/ipv6.h @@ -76,7 +76,6 @@ struct netns_ipv6 { #endif #endif atomic_t dev_addr_genid; - atomic_t rt_genid; }; #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c index e696045..8b2d99a 100644 --- a/net/ipv6/addrconf_core.c +++ b/net/ipv6/addrconf_core.c @@ -10,6 +10,12 @@ #define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) +/* if ipv6 module registers this function is used by xfrm to force + * all sockets to relookup their nodes - this is fairly expensive + */ +void (*__fib6_flush_trees)(struct net *); +EXPORT_SYMBOL(__fib6_flush_trees); + static inline unsigned int ipv6_addr_scope2type(unsigned int scope) { switch (scope) { diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index e4865a3..2189d2d 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -766,7 +766,6 @@ static int __net_init inet6_net_init(struct net *net) net->ipv6.sysctl.icmpv6_time = 1*HZ; net->ipv6.sysctl.flowlabel_consistency = 1; net->ipv6.sysctl.auto_flowlabels = 0; - atomic_set(&net->ipv6.rt_genid, 0); err = ipv6_init_mibs(net); if (err) diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 8db8b1c..0fe9241 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -1574,8 +1574,9 @@ static void fib6_clean_tree(struct net *net, struct fib6_node *root, fib6_walk(&c.w); } -void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg), - void *arg) +void __fib6_clean_all(struct net *net, + int (*func)(struct rt6_info *, void *arg), + u32 sernum, void *arg) { struct fib6_table *table; struct hlist_head *head; @@ -1587,14 +1588,24 @@ void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg), hlist_for_each_entry_rcu(table, head, tb6_hlist) { write_lock_bh(&table->tb6_lock); fib6_clean_tree(net, &table->tb6_root, - func, false, FIB6_NO_SERNUM_CHANGE, - arg); + func, false, sernum, arg); write_unlock_bh(&table->tb6_lock); } } rcu_read_unlock(); } +void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg), + void *arg) +{ + __fib6_clean_all(net, func, FIB6_NO_SERNUM_CHANGE, arg); +} + +static void fib6_flush_trees(struct net *net) +{ + __fib6_clean_all(net, NULL, fib6_new_sernum(), NULL); +} + static int fib6_prune_clone(struct rt6_info *rt, void *arg) { if (rt->rt6i_flags & RTF_CACHE) { @@ -1793,6 +1804,8 @@ int __init fib6_init(void) NULL); if (ret) goto out_unregister_subsys; + + __fib6_flush_trees = fib6_flush_trees; out: return ret; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index f74b041..a318dd89 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, memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); - rt->rt6i_genid = rt_genid_ipv6(net); INIT_LIST_HEAD(&rt->rt6i_siblings); } return rt; @@ -1096,9 +1095,6 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) * DST_OBSOLETE_FORCE_CHK which forces validation calls down * into this function always. */ - if (rt->rt6i_genid != rt_genid_ipv6(dev_net(rt->dst.dev))) - return NULL; - if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie)) return NULL;
fib6_flush_trees is still a very costly operation but now is only called by xfrm code when a policy changes or ipv6 addresses are added/removed. fib6_flush_tree must walk all ipv6 routing tables and modify fn_sernum, so all sockets relookup their dst_entries. Use a NULL callback, so we only walk the nodes without looking at the rt6_infos. Cc: Eric Dumazet <eric.dumazet@gmail.com> Cc: Vlad Yasevich <vyasevich@gmail.com> Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com> Cc: Martin Lau <kafai@fb.com> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> --- include/net/net_namespace.h | 14 +++----------- include/net/netns/ipv6.h | 1 - net/ipv6/addrconf_core.c | 6 ++++++ net/ipv6/af_inet6.c | 1 - net/ipv6/ip6_fib.c | 21 +++++++++++++++++---- net/ipv6/route.c | 4 ---- 6 files changed, 26 insertions(+), 21 deletions(-)