mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-26 12:34:41 +08:00
neighbour: add RCU protection to neigh_tables[]
In order to remove RTNL protection from neightbl_dump_info() and neigh_dump_info() later, we need to add RCU protection to neigh_tables[]. Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
9fc31a9251
commit
f8f2eb9de6
@ -1771,7 +1771,7 @@ static void neigh_parms_destroy(struct neigh_parms *parms)
|
||||
|
||||
static struct lock_class_key neigh_table_proxy_queue_class;
|
||||
|
||||
static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
|
||||
static struct neigh_table __rcu *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
|
||||
|
||||
void neigh_table_init(int index, struct neigh_table *tbl)
|
||||
{
|
||||
@ -1828,13 +1828,19 @@ void neigh_table_init(int index, struct neigh_table *tbl)
|
||||
tbl->last_flush = now;
|
||||
tbl->last_rand = now + tbl->parms.reachable_time * 20;
|
||||
|
||||
neigh_tables[index] = tbl;
|
||||
rcu_assign_pointer(neigh_tables[index], tbl);
|
||||
}
|
||||
EXPORT_SYMBOL(neigh_table_init);
|
||||
|
||||
/*
|
||||
* Only called from ndisc_cleanup(), which means this is dead code
|
||||
* because we no longer can unload IPv6 module.
|
||||
*/
|
||||
int neigh_table_clear(int index, struct neigh_table *tbl)
|
||||
{
|
||||
neigh_tables[index] = NULL;
|
||||
RCU_INIT_POINTER(neigh_tables[index], NULL);
|
||||
synchronize_rcu();
|
||||
|
||||
/* It is not clean... Fix it to unload IPv6 module safely */
|
||||
cancel_delayed_work_sync(&tbl->managed_work);
|
||||
cancel_delayed_work_sync(&tbl->gc_work);
|
||||
@ -1866,10 +1872,10 @@ static struct neigh_table *neigh_find_table(int family)
|
||||
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
tbl = neigh_tables[NEIGH_ARP_TABLE];
|
||||
tbl = rcu_dereference_rtnl(neigh_tables[NEIGH_ARP_TABLE]);
|
||||
break;
|
||||
case AF_INET6:
|
||||
tbl = neigh_tables[NEIGH_ND_TABLE];
|
||||
tbl = rcu_dereference_rtnl(neigh_tables[NEIGH_ND_TABLE]);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2333,7 +2339,7 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
ndtmsg = nlmsg_data(nlh);
|
||||
|
||||
for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
|
||||
tbl = neigh_tables[tidx];
|
||||
tbl = rcu_dereference_rtnl(neigh_tables[tidx]);
|
||||
if (!tbl)
|
||||
continue;
|
||||
if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
|
||||
@ -2521,7 +2527,7 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
|
||||
struct neigh_parms *p;
|
||||
|
||||
tbl = neigh_tables[tidx];
|
||||
tbl = rcu_dereference_rtnl(neigh_tables[tidx]);
|
||||
if (!tbl)
|
||||
continue;
|
||||
|
||||
@ -2881,7 +2887,7 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
s_t = cb->args[0];
|
||||
|
||||
for (t = 0; t < NEIGH_NR_TABLES; t++) {
|
||||
tbl = neigh_tables[t];
|
||||
tbl = rcu_dereference_rtnl(neigh_tables[t]);
|
||||
|
||||
if (!tbl)
|
||||
continue;
|
||||
@ -3145,14 +3151,15 @@ int neigh_xmit(int index, struct net_device *dev,
|
||||
const void *addr, struct sk_buff *skb)
|
||||
{
|
||||
int err = -EAFNOSUPPORT;
|
||||
|
||||
if (likely(index < NEIGH_NR_TABLES)) {
|
||||
struct neigh_table *tbl;
|
||||
struct neighbour *neigh;
|
||||
|
||||
tbl = neigh_tables[index];
|
||||
if (!tbl)
|
||||
goto out;
|
||||
rcu_read_lock();
|
||||
tbl = rcu_dereference(neigh_tables[index]);
|
||||
if (!tbl)
|
||||
goto out_unlock;
|
||||
if (index == NEIGH_ARP_TABLE) {
|
||||
u32 key = *((u32 *)addr);
|
||||
|
||||
@ -3168,6 +3175,7 @@ int neigh_xmit(int index, struct net_device *dev,
|
||||
goto out_kfree_skb;
|
||||
}
|
||||
err = READ_ONCE(neigh->output)(neigh, skb);
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
else if (index == NEIGH_LINK_TABLE) {
|
||||
|
Loading…
Reference in New Issue
Block a user