diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/ip6_fib.c | 20 | ||||
-rw-r--r-- | net/ipv6/route.c | 20 |
2 files changed, 34 insertions, 6 deletions
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index e14d244c551f..9ba72d94d60f 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -47,6 +47,7 @@ struct fib6_cleaner { | |||
47 | int (*func)(struct fib6_info *, void *arg); | 47 | int (*func)(struct fib6_info *, void *arg); |
48 | int sernum; | 48 | int sernum; |
49 | void *arg; | 49 | void *arg; |
50 | bool skip_notify; | ||
50 | }; | 51 | }; |
51 | 52 | ||
52 | #ifdef CONFIG_IPV6_SUBTREES | 53 | #ifdef CONFIG_IPV6_SUBTREES |
@@ -1956,6 +1957,7 @@ static int fib6_clean_node(struct fib6_walker *w) | |||
1956 | struct fib6_cleaner *c = container_of(w, struct fib6_cleaner, w); | 1957 | struct fib6_cleaner *c = container_of(w, struct fib6_cleaner, w); |
1957 | struct nl_info info = { | 1958 | struct nl_info info = { |
1958 | .nl_net = c->net, | 1959 | .nl_net = c->net, |
1960 | .skip_notify = c->skip_notify, | ||
1959 | }; | 1961 | }; |
1960 | 1962 | ||
1961 | if (c->sernum != FIB6_NO_SERNUM_CHANGE && | 1963 | if (c->sernum != FIB6_NO_SERNUM_CHANGE && |
@@ -2007,7 +2009,7 @@ static int fib6_clean_node(struct fib6_walker *w) | |||
2007 | 2009 | ||
2008 | static void fib6_clean_tree(struct net *net, struct fib6_node *root, | 2010 | static void fib6_clean_tree(struct net *net, struct fib6_node *root, |
2009 | int (*func)(struct fib6_info *, void *arg), | 2011 | int (*func)(struct fib6_info *, void *arg), |
2010 | int sernum, void *arg) | 2012 | int sernum, void *arg, bool skip_notify) |
2011 | { | 2013 | { |
2012 | struct fib6_cleaner c; | 2014 | struct fib6_cleaner c; |
2013 | 2015 | ||
@@ -2019,13 +2021,14 @@ static void fib6_clean_tree(struct net *net, struct fib6_node *root, | |||
2019 | c.sernum = sernum; | 2021 | c.sernum = sernum; |
2020 | c.arg = arg; | 2022 | c.arg = arg; |
2021 | c.net = net; | 2023 | c.net = net; |
2024 | c.skip_notify = skip_notify; | ||
2022 | 2025 | ||
2023 | fib6_walk(net, &c.w); | 2026 | fib6_walk(net, &c.w); |
2024 | } | 2027 | } |
2025 | 2028 | ||
2026 | static void __fib6_clean_all(struct net *net, | 2029 | static void __fib6_clean_all(struct net *net, |
2027 | int (*func)(struct fib6_info *, void *), | 2030 | int (*func)(struct fib6_info *, void *), |
2028 | int sernum, void *arg) | 2031 | int sernum, void *arg, bool skip_notify) |
2029 | { | 2032 | { |
2030 | struct fib6_table *table; | 2033 | struct fib6_table *table; |
2031 | struct hlist_head *head; | 2034 | struct hlist_head *head; |
@@ -2037,7 +2040,7 @@ static void __fib6_clean_all(struct net *net, | |||
2037 | hlist_for_each_entry_rcu(table, head, tb6_hlist) { | 2040 | hlist_for_each_entry_rcu(table, head, tb6_hlist) { |
2038 | spin_lock_bh(&table->tb6_lock); | 2041 | spin_lock_bh(&table->tb6_lock); |
2039 | fib6_clean_tree(net, &table->tb6_root, | 2042 | fib6_clean_tree(net, &table->tb6_root, |
2040 | func, sernum, arg); | 2043 | func, sernum, arg, skip_notify); |
2041 | spin_unlock_bh(&table->tb6_lock); | 2044 | spin_unlock_bh(&table->tb6_lock); |
2042 | } | 2045 | } |
2043 | } | 2046 | } |
@@ -2047,14 +2050,21 @@ static void __fib6_clean_all(struct net *net, | |||
2047 | void fib6_clean_all(struct net *net, int (*func)(struct fib6_info *, void *), | 2050 | void fib6_clean_all(struct net *net, int (*func)(struct fib6_info *, void *), |
2048 | void *arg) | 2051 | void *arg) |
2049 | { | 2052 | { |
2050 | __fib6_clean_all(net, func, FIB6_NO_SERNUM_CHANGE, arg); | 2053 | __fib6_clean_all(net, func, FIB6_NO_SERNUM_CHANGE, arg, false); |
2054 | } | ||
2055 | |||
2056 | void fib6_clean_all_skip_notify(struct net *net, | ||
2057 | int (*func)(struct fib6_info *, void *), | ||
2058 | void *arg) | ||
2059 | { | ||
2060 | __fib6_clean_all(net, func, FIB6_NO_SERNUM_CHANGE, arg, true); | ||
2051 | } | 2061 | } |
2052 | 2062 | ||
2053 | static void fib6_flush_trees(struct net *net) | 2063 | static void fib6_flush_trees(struct net *net) |
2054 | { | 2064 | { |
2055 | int new_sernum = fib6_new_sernum(net); | 2065 | int new_sernum = fib6_new_sernum(net); |
2056 | 2066 | ||
2057 | __fib6_clean_all(net, NULL, new_sernum, NULL); | 2067 | __fib6_clean_all(net, NULL, new_sernum, NULL, false); |
2058 | } | 2068 | } |
2059 | 2069 | ||
2060 | /* | 2070 | /* |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index bf4cd647d8b8..f4e08b0689a8 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -4026,8 +4026,12 @@ void rt6_sync_down_dev(struct net_device *dev, unsigned long event) | |||
4026 | .event = event, | 4026 | .event = event, |
4027 | }, | 4027 | }, |
4028 | }; | 4028 | }; |
4029 | struct net *net = dev_net(dev); | ||
4029 | 4030 | ||
4030 | fib6_clean_all(dev_net(dev), fib6_ifdown, &arg); | 4031 | if (net->ipv6.sysctl.skip_notify_on_dev_down) |
4032 | fib6_clean_all_skip_notify(net, fib6_ifdown, &arg); | ||
4033 | else | ||
4034 | fib6_clean_all(net, fib6_ifdown, &arg); | ||
4031 | } | 4035 | } |
4032 | 4036 | ||
4033 | void rt6_disable_ip(struct net_device *dev, unsigned long event) | 4037 | void rt6_disable_ip(struct net_device *dev, unsigned long event) |
@@ -5031,6 +5035,9 @@ int ipv6_sysctl_rtcache_flush(struct ctl_table *ctl, int write, | |||
5031 | return 0; | 5035 | return 0; |
5032 | } | 5036 | } |
5033 | 5037 | ||
5038 | static int zero; | ||
5039 | static int one = 1; | ||
5040 | |||
5034 | static struct ctl_table ipv6_route_table_template[] = { | 5041 | static struct ctl_table ipv6_route_table_template[] = { |
5035 | { | 5042 | { |
5036 | .procname = "flush", | 5043 | .procname = "flush", |
@@ -5102,6 +5109,15 @@ static struct ctl_table ipv6_route_table_template[] = { | |||
5102 | .mode = 0644, | 5109 | .mode = 0644, |
5103 | .proc_handler = proc_dointvec_ms_jiffies, | 5110 | .proc_handler = proc_dointvec_ms_jiffies, |
5104 | }, | 5111 | }, |
5112 | { | ||
5113 | .procname = "skip_notify_on_dev_down", | ||
5114 | .data = &init_net.ipv6.sysctl.skip_notify_on_dev_down, | ||
5115 | .maxlen = sizeof(int), | ||
5116 | .mode = 0644, | ||
5117 | .proc_handler = proc_dointvec, | ||
5118 | .extra1 = &zero, | ||
5119 | .extra2 = &one, | ||
5120 | }, | ||
5105 | { } | 5121 | { } |
5106 | }; | 5122 | }; |
5107 | 5123 | ||
@@ -5125,6 +5141,7 @@ struct ctl_table * __net_init ipv6_route_sysctl_init(struct net *net) | |||
5125 | table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires; | 5141 | table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires; |
5126 | table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss; | 5142 | table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss; |
5127 | table[9].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; | 5143 | table[9].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; |
5144 | table[10].data = &net->ipv6.sysctl.skip_notify_on_dev_down; | ||
5128 | 5145 | ||
5129 | /* Don't export sysctls to unprivileged users */ | 5146 | /* Don't export sysctls to unprivileged users */ |
5130 | if (net->user_ns != &init_user_ns) | 5147 | if (net->user_ns != &init_user_ns) |
@@ -5189,6 +5206,7 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
5189 | net->ipv6.sysctl.ip6_rt_gc_elasticity = 9; | 5206 | net->ipv6.sysctl.ip6_rt_gc_elasticity = 9; |
5190 | net->ipv6.sysctl.ip6_rt_mtu_expires = 10*60*HZ; | 5207 | net->ipv6.sysctl.ip6_rt_mtu_expires = 10*60*HZ; |
5191 | net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40; | 5208 | net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40; |
5209 | net->ipv6.sysctl.skip_notify_on_dev_down = 0; | ||
5192 | 5210 | ||
5193 | net->ipv6.ip6_rt_gc_expire = 30*HZ; | 5211 | net->ipv6.ip6_rt_gc_expire = 30*HZ; |
5194 | 5212 | ||