summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/ip6_fib.c20
-rw-r--r--net/ipv6/route.c20
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
2008static void fib6_clean_tree(struct net *net, struct fib6_node *root, 2010static 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
2026static void __fib6_clean_all(struct net *net, 2029static 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,
2047void fib6_clean_all(struct net *net, int (*func)(struct fib6_info *, void *), 2050void 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
2056void 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
2053static void fib6_flush_trees(struct net *net) 2063static 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
4033void rt6_disable_ip(struct net_device *dev, unsigned long event) 4037void 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
5038static int zero;
5039static int one = 1;
5040
5034static struct ctl_table ipv6_route_table_template[] = { 5041static 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