Skip to content

Commit 1d4c8c2

Browse files
jpirkodavem330
authored andcommitted
neigh: restore old behaviour of default parms values
Previously inet devices were only constructed when addresses are added. Therefore the default neigh parms values they get are the ones at the time of these operations. Now that we're creating inet devices earlier, this changes the behaviour of default neigh parms values in an incompatible way (see bug #8519). This patch creates a compromise by setting the default values at the same point as before but only for those that have not been explicitly set by the user since the inet device's creation. Introduced by: commit 8030f54 Author: Herbert Xu <[email protected]> Date: Thu Feb 22 01:53:47 2007 +0900 [IPV4] devinet: Register inetdev earlier. Signed-off-by: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 73af614 commit 1d4c8c2

File tree

5 files changed

+92
-6
lines changed

5 files changed

+92
-6
lines changed

include/linux/inetdevice.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,13 @@ static inline struct in_device *__in_dev_get_rtnl(const struct net_device *dev)
220220
return rtnl_dereference(dev->ip_ptr);
221221
}
222222

223+
static inline struct neigh_parms *__in_dev_arp_parms_get_rcu(const struct net_device *dev)
224+
{
225+
struct in_device *in_dev = __in_dev_get_rcu(dev);
226+
227+
return in_dev ? in_dev->arp_parms : NULL;
228+
}
229+
223230
void in_dev_finish_destroy(struct in_device *idev);
224231

225232
static inline void in_dev_put(struct in_device *idev)

include/net/neighbour.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <linux/skbuff.h>
2222
#include <linux/rcupdate.h>
2323
#include <linux/seq_file.h>
24+
#include <linux/bitmap.h>
2425

2526
#include <linux/err.h>
2627
#include <linux/sysctl.h>
@@ -81,16 +82,28 @@ struct neigh_parms {
8182

8283
int reachable_time;
8384
int data[NEIGH_VAR_DATA_MAX];
85+
DECLARE_BITMAP(data_state, NEIGH_VAR_DATA_MAX);
8486
};
8587

8688
static inline void neigh_var_set(struct neigh_parms *p, int index, int val)
8789
{
90+
set_bit(index, p->data_state);
8891
p->data[index] = val;
8992
}
9093

9194
#define NEIGH_VAR(p, attr) ((p)->data[NEIGH_VAR_ ## attr])
9295
#define NEIGH_VAR_SET(p, attr, val) neigh_var_set(p, NEIGH_VAR_ ## attr, val)
9396

97+
static inline void neigh_parms_data_state_setall(struct neigh_parms *p)
98+
{
99+
bitmap_fill(p->data_state, NEIGH_VAR_DATA_MAX);
100+
}
101+
102+
static inline void neigh_parms_data_state_cleanall(struct neigh_parms *p)
103+
{
104+
bitmap_zero(p->data_state, NEIGH_VAR_DATA_MAX);
105+
}
106+
94107
struct neigh_statistics {
95108
unsigned long allocs; /* number of allocated neighs */
96109
unsigned long destroys; /* number of destroyed neighs */

net/core/neighbour.c

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <linux/random.h>
3939
#include <linux/string.h>
4040
#include <linux/log2.h>
41+
#include <linux/inetdevice.h>
4142

4243
#define DEBUG
4344
#define NEIGH_DEBUG 1
@@ -1464,6 +1465,8 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
14641465
p->next = tbl->parms.next;
14651466
tbl->parms.next = p;
14661467
write_unlock_bh(&tbl->lock);
1468+
1469+
neigh_parms_data_state_cleanall(p);
14671470
}
14681471
return p;
14691472
}
@@ -2813,53 +2816,111 @@ static int proc_unres_qlen(struct ctl_table *ctl, int write,
28132816
return ret;
28142817
}
28152818

2819+
static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
2820+
int family)
2821+
{
2822+
if (family == AF_INET)
2823+
return __in_dev_arp_parms_get_rcu(dev);
2824+
return NULL;
2825+
}
2826+
2827+
static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
2828+
int index)
2829+
{
2830+
struct net_device *dev;
2831+
int family = neigh_parms_family(p);
2832+
2833+
rcu_read_lock();
2834+
for_each_netdev_rcu(net, dev) {
2835+
struct neigh_parms *dst_p =
2836+
neigh_get_dev_parms_rcu(dev, family);
2837+
2838+
if (dst_p && !test_bit(index, dst_p->data_state))
2839+
dst_p->data[index] = p->data[index];
2840+
}
2841+
rcu_read_unlock();
2842+
}
2843+
2844+
static void neigh_proc_update(struct ctl_table *ctl, int write)
2845+
{
2846+
struct net_device *dev = ctl->extra1;
2847+
struct neigh_parms *p = ctl->extra2;
2848+
struct net *net = p->net;
2849+
int index = (int *) ctl->data - p->data;
2850+
2851+
if (!write)
2852+
return;
2853+
2854+
set_bit(index, p->data_state);
2855+
if (!dev) /* NULL dev means this is default value */
2856+
neigh_copy_dflt_parms(net, p, index);
2857+
}
2858+
28162859
static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
28172860
void __user *buffer,
28182861
size_t *lenp, loff_t *ppos)
28192862
{
28202863
struct ctl_table tmp = *ctl;
2864+
int ret;
28212865

28222866
tmp.extra1 = &zero;
28232867
tmp.extra2 = &int_max;
28242868

2825-
return proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2869+
ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2870+
neigh_proc_update(ctl, write);
2871+
return ret;
28262872
}
28272873

28282874
int neigh_proc_dointvec(struct ctl_table *ctl, int write,
28292875
void __user *buffer, size_t *lenp, loff_t *ppos)
28302876
{
2831-
return proc_dointvec(ctl, write, buffer, lenp, ppos);
2877+
int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
2878+
2879+
neigh_proc_update(ctl, write);
2880+
return ret;
28322881
}
28332882
EXPORT_SYMBOL(neigh_proc_dointvec);
28342883

28352884
int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
28362885
void __user *buffer,
28372886
size_t *lenp, loff_t *ppos)
28382887
{
2839-
return proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
2888+
int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
2889+
2890+
neigh_proc_update(ctl, write);
2891+
return ret;
28402892
}
28412893
EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
28422894

28432895
static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
28442896
void __user *buffer,
28452897
size_t *lenp, loff_t *ppos)
28462898
{
2847-
return proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
2899+
int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
2900+
2901+
neigh_proc_update(ctl, write);
2902+
return ret;
28482903
}
28492904

28502905
int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
28512906
void __user *buffer,
28522907
size_t *lenp, loff_t *ppos)
28532908
{
2854-
return proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
2909+
int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
2910+
2911+
neigh_proc_update(ctl, write);
2912+
return ret;
28552913
}
28562914
EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
28572915

28582916
static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
28592917
void __user *buffer,
28602918
size_t *lenp, loff_t *ppos)
28612919
{
2862-
return proc_unres_qlen(ctl, write, buffer, lenp, ppos);
2920+
int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
2921+
2922+
neigh_proc_update(ctl, write);
2923+
return ret;
28632924
}
28642925

28652926
#define NEIGH_PARMS_DATA_OFFSET(index) \
@@ -2962,6 +3023,7 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
29623023
for (i = 0; i < ARRAY_SIZE(t->neigh_vars); i++) {
29633024
t->neigh_vars[i].data += (long) p;
29643025
t->neigh_vars[i].extra1 = dev;
3026+
t->neigh_vars[i].extra2 = p;
29653027
}
29663028

29673029
if (dev) {

net/ipv4/devinet.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)
500500
return -ENOBUFS;
501501
}
502502
ipv4_devconf_setall(in_dev);
503+
neigh_parms_data_state_setall(in_dev->arp_parms);
503504
if (ifa->ifa_dev != in_dev) {
504505
WARN_ON(ifa->ifa_dev);
505506
in_dev_hold(in_dev);
@@ -747,6 +748,7 @@ static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh,
747748
goto errout;
748749

749750
ipv4_devconf_setall(in_dev);
751+
neigh_parms_data_state_setall(in_dev->arp_parms);
750752
in_dev_hold(in_dev);
751753

752754
if (tb[IFA_ADDRESS] == NULL)

net/ipv4/ipmr.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ struct net_device *ipmr_new_tunnel(struct net *net, struct vifctl *v)
425425
goto failure;
426426

427427
ipv4_devconf_setall(in_dev);
428+
neigh_parms_data_state_setall(in_dev->arp_parms);
428429
IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0;
429430

430431
if (dev_open(dev))
@@ -517,6 +518,7 @@ static struct net_device *ipmr_reg_vif(struct net *net, struct mr_table *mrt)
517518
}
518519

519520
ipv4_devconf_setall(in_dev);
521+
neigh_parms_data_state_setall(in_dev->arp_parms);
520522
IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0;
521523
rcu_read_unlock();
522524

0 commit comments

Comments
 (0)