We will allocate per-netns neigh_table in net->neigh_tables[]. Let's replace &nd_tbl with nd_table(net). Signed-off-by: Kuniyuki Iwashima --- Cc: Saeed Mahameed Cc: Leon Romanovsky Cc: Tariq Toukan Cc: Mark Bloch Cc: Petr Machata Cc: Edward Cree Cc: Nikolay Aleksandrov Cc: Alexander Aring Cc: Stefan Schmidt Cc: Miquel Raynal --- .../mellanox/mlx5/core/en/rep/neigh.c | 7 +- .../mellanox/mlx5/core/en/tc_tun_encap.c | 2 +- .../ethernet/mellanox/mlxsw/spectrum_router.c | 13 ++- .../ethernet/mellanox/mlxsw/spectrum_span.c | 5 +- .../netronome/nfp/flower/tunnel_conf.c | 4 +- drivers/net/ethernet/sfc/tc_counters.c | 2 +- drivers/net/ethernet/sfc/tc_encap_actions.c | 2 +- drivers/net/vrf.c | 2 +- drivers/net/vxlan/vxlan_core.c | 6 +- include/net/ndisc.h | 11 ++- net/bridge/br_arp_nd_proxy.c | 2 +- net/ieee802154/6lowpan/tx.c | 3 +- net/ipv4/fib_semantics.c | 2 +- net/ipv6/addrconf.c | 17 ++-- net/ipv6/ip6_output.c | 4 +- net/ipv6/ndisc.c | 91 ++++++++++--------- net/ipv6/route.c | 18 ++-- 17 files changed, 112 insertions(+), 79 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/neigh.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/neigh.c index 9894a0527789..6a8d8aac7d16 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/neigh.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/neigh.c @@ -17,26 +17,27 @@ #include "fs_core.h" #include "diag/en_rep_tracepoint.h" -static unsigned long mlx5e_rep_ipv6_interval(void) +static unsigned long mlx5e_rep_ipv6_interval(struct net *net) { if (IS_ENABLED(CONFIG_IPV6) && ipv6_mod_enabled()) - return NEIGH_VAR(&nd_tbl.parms, DELAY_PROBE_TIME); + return NEIGH_VAR(&nd_table(net)->parms, DELAY_PROBE_TIME); return ~0UL; } static void mlx5e_rep_neigh_update_init_interval(struct mlx5e_rep_priv *rpriv) { - unsigned long ipv6_interval = mlx5e_rep_ipv6_interval(); struct net_device *netdev = rpriv->netdev; struct net *net = dev_net(netdev); unsigned long ipv4_interval; + unsigned long ipv6_interval; struct neigh_table *tbl; struct mlx5e_priv *priv; priv = netdev_priv(netdev); tbl = arp_table(net); ipv4_interval = NEIGH_VAR(&tbl->parms, DELAY_PROBE_TIME); + ipv6_interval = mlx5e_rep_ipv6_interval(net); rpriv->neigh_update.min_interval = min_t(unsigned long, ipv6_interval, ipv4_interval); mlx5_fc_update_sampling_interval(priv->mdev, rpriv->neigh_update.min_interval); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c index 33737a29ab97..67c12ca19d59 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c @@ -445,7 +445,7 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe) #if IS_ENABLED(CONFIG_IPV6) if (m_neigh->family != AF_INET) - tbl = &nd_tbl; + tbl = nd_table(net); else #endif tbl = arp_table(net); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index d2a840ce42e3..f4a435885ba4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -2403,7 +2403,7 @@ mlxsw_sp_router_neighs_update_interval_init(struct mlxsw_sp *mlxsw_sp) #if IS_ENABLED(CONFIG_IPV6) interval = min_t(unsigned long, NEIGH_VAR(&arp_table(net)->parms, DELAY_PROBE_TIME), - NEIGH_VAR(&nd_tbl.parms, DELAY_PROBE_TIME)); + NEIGH_VAR(&nd_table(net)->parms, DELAY_PROBE_TIME)); #else interval = NEIGH_VAR(&arp_table(net)->parms, DELAY_PROBE_TIME); #endif @@ -2449,6 +2449,8 @@ static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp, char *rauhtd_pl, int rec_index) { + struct net *net = mlxsw_sp_net(mlxsw_sp); + struct neigh_table *tbl; struct net_device *dev; struct neighbour *n; struct in6_addr dip; @@ -2462,8 +2464,9 @@ static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp, return; } + tbl = nd_table(net); dev = mlxsw_sp_rif_dev(mlxsw_sp->router->rifs[rif]); - n = neigh_lookup(&nd_tbl, &dip, dev); + n = neigh_lookup(tbl, &dip, dev); if (!n) return; @@ -3028,7 +3031,7 @@ static int mlxsw_sp_neigh_rif_made_sync(struct mlxsw_sp *mlxsw_sp, goto err_arp; #if IS_ENABLED(CONFIG_IPV6) - neigh_for_each(&nd_tbl, mlxsw_sp_neigh_rif_made_sync_each, &rms); + neigh_for_each(nd_table(net), mlxsw_sp_neigh_rif_made_sync_each, &rms); #endif if (rms.err) goto err_nd; @@ -5131,7 +5134,7 @@ mlxsw_sp_nexthop_obj_init(struct mlxsw_sp *mlxsw_sp, case AF_INET6: memcpy(&nh->gw_addr, &nh_obj->ipv6, sizeof(nh_obj->ipv6)); #if IS_ENABLED(CONFIG_IPV6) - nh->neigh_tbl = &nd_tbl; + nh->neigh_tbl = nd_table(net); #endif break; } @@ -6987,7 +6990,7 @@ static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp, nh->nh_weight = rt->fib6_nh->fib_nh_weight; memcpy(&nh->gw_addr, &rt->fib6_nh->fib_nh_gw6, sizeof(nh->gw_addr)); #if IS_ENABLED(CONFIG_IPV6) - nh->neigh_tbl = &nd_tbl; + nh->neigh_tbl = nd_table(mlxsw_sp_net(mlxsw_sp)); #endif err = mlxsw_sp_nexthop_counter_enable(mlxsw_sp, nh); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c index 2e8577b555ca..1cd8347c274d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c @@ -564,6 +564,7 @@ mlxsw_sp_span_entry_gretap6_parms(struct mlxsw_sp *mlxsw_sp, union mlxsw_sp_l3addr daddr = { .addr6 = tparm.raddr }; bool inherit_ttl = !tparm.hop_limit; union mlxsw_sp_l3addr gw = daddr; + struct neigh_table *tbl = NULL; struct net_device *l3edev; if (!(to_dev->flags & IFF_UP) || @@ -577,9 +578,11 @@ mlxsw_sp_span_entry_gretap6_parms(struct mlxsw_sp *mlxsw_sp, return mlxsw_sp_span_entry_unoffloadable(sparmsp); l3edev = mlxsw_sp_span_gretap6_route(to_dev, &saddr.addr6, &gw.addr6); + if (l3edev) + tbl = nd_table(dev_net(l3edev)); return mlxsw_sp_span_entry_tunnel_parms_common(l3edev, saddr, daddr, gw, tparm.hop_limit, - &nd_tbl, sparmsp); + tbl, sparmsp); } static int diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c index 551db6417405..d650d33e3709 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c +++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c @@ -253,6 +253,7 @@ void nfp_tunnel_keep_alive_v6(struct nfp_app *app, struct sk_buff *skb) #if IS_ENABLED(CONFIG_IPV6) struct nfp_tun_active_tuns_v6 *payload; struct net_device *netdev; + struct neigh_table *tbl; int count, i, pay_len; struct neighbour *n; void *ipv6_add; @@ -279,7 +280,8 @@ void nfp_tunnel_keep_alive_v6(struct nfp_app *app, struct sk_buff *skb) if (!netdev) continue; - n = neigh_lookup(&nd_tbl, ipv6_add, netdev); + tbl = nd_table(dev_net(netdev)); + n = neigh_lookup(tbl, ipv6_add, netdev); if (!n) continue; diff --git a/drivers/net/ethernet/sfc/tc_counters.c b/drivers/net/ethernet/sfc/tc_counters.c index f039836eaec8..793a562fc1f7 100644 --- a/drivers/net/ethernet/sfc/tc_counters.c +++ b/drivers/net/ethernet/sfc/tc_counters.c @@ -116,7 +116,7 @@ static void efx_tc_counter_work(struct work_struct *work) encap->neigh->egdev); else #if IS_ENABLED(CONFIG_IPV6) - n = neigh_lookup(&nd_tbl, + n = neigh_lookup(nd_table(net), &encap->neigh->dst_ip6, encap->neigh->egdev); #else diff --git a/drivers/net/ethernet/sfc/tc_encap_actions.c b/drivers/net/ethernet/sfc/tc_encap_actions.c index f75c87b166ea..152c4639ecc6 100644 --- a/drivers/net/ethernet/sfc/tc_encap_actions.c +++ b/drivers/net/ethernet/sfc/tc_encap_actions.c @@ -530,7 +530,7 @@ static int efx_neigh_event(struct efx_nic *efx, struct neighbour *n) if (n->tbl->family == AF_INET) { keysize = sizeof(keys.dst_ip); #if IS_ENABLED(CONFIG_IPV6) - } else if (n->tbl == &nd_tbl) { + } else if (n->tbl->family == AF_INET6) { ipv6 = true; keysize = sizeof(keys.dst_ip6); #endif diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index a0557a3a7026..50ec04cc0213 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -616,7 +616,7 @@ static int vrf_finish_output6(struct net *net, struct sock *sk, nexthop = rt6_nexthop(dst_rt6_info(dst), &ipv6_hdr(skb)->daddr); neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop); if (unlikely(!neigh)) - neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false); + neigh = __neigh_create(nd_table(net), nexthop, dst->dev, false); if (!IS_ERR(neigh)) { sock_confirm_neigh(skb, neigh); ret = neigh_output(neigh, skb, false); diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index 507bd145c364..f148a4b28d09 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -2048,7 +2048,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) ipv6_addr_is_multicast(&msg->target)) goto out; - n = neigh_lookup(&nd_tbl, &msg->target, dev); + n = neigh_lookup(nd_table(dev_net(dev)), &msg->target, dev); if (n) { struct vxlan_rdst *rdst = NULL; @@ -2143,8 +2143,10 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb) return false; if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr))) return false; + + tbl = nd_table(dev_net(dev)); pip6 = ipv6_hdr(skb); - n = neigh_lookup(&nd_tbl, &pip6->daddr, dev); + n = neigh_lookup(tbl, &pip6->daddr, dev); if (!n && (vxlan->cfg.flags & VXLAN_F_L3MISS)) { union vxlan_addr ipa = { .sin6.sin6_addr = pip6->daddr, diff --git a/include/net/ndisc.h b/include/net/ndisc.h index 84dba1376f98..5b7a36cbda16 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h @@ -363,7 +363,9 @@ static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, _ static inline struct neighbour *__ipv6_neigh_lookup_noref(struct net_device *dev, const void *pkey) { - return ___neigh_lookup_noref(&nd_tbl, neigh_key_eq128, ndisc_hashfn, pkey, dev); + struct neigh_table *tbl = nd_table(dev_net(dev)); + + return ___neigh_lookup_noref(tbl, neigh_key_eq128, ndisc_hashfn, pkey, dev); } static inline struct neighbour *__ipv6_neigh_lookup(struct net_device *dev, const void *pkey) @@ -397,8 +399,11 @@ static inline struct neighbour *ip_neigh_gw6(struct net_device *dev, struct neighbour *neigh; neigh = __ipv6_neigh_lookup_noref(dev, addr); - if (unlikely(!neigh)) - neigh = __neigh_create(&nd_tbl, addr, dev, false); + if (unlikely(!neigh)) { + struct neigh_table *tbl = nd_table(dev_net(dev)); + + neigh = __neigh_create(tbl, addr, dev, false); + } return neigh; #else diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c index e73c92284558..3b4cd709e70e 100644 --- a/net/bridge/br_arp_nd_proxy.c +++ b/net/bridge/br_arp_nd_proxy.c @@ -469,7 +469,7 @@ void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br, return; } - n = neigh_lookup(&nd_tbl, &msg->target, vlandev); + n = neigh_lookup(nd_table(dev_net(vlandev)), &msg->target, vlandev); if (n) { struct net_bridge_fdb_entry *f; diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c index 4df76ff50699..4f511476b992 100644 --- a/net/ieee802154/6lowpan/tx.c +++ b/net/ieee802154/6lowpan/tx.c @@ -58,8 +58,9 @@ int lowpan_header_create(struct sk_buff *skb, struct net_device *ldev, info->daddr.mode = IEEE802154_ADDR_SHORT; } else { __le16 short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC); + struct neigh_table *tbl = nd_table(dev_net(ldev)); - n = neigh_lookup(&nd_tbl, &hdr->daddr, ldev); + n = neigh_lookup(tbl, &hdr->daddr, ldev); if (n) { llneigh = lowpan_802154_neigh(neighbour_priv(n)); read_lock_bh(&n->lock); diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 6634e750f349..7cdd911b1203 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -586,7 +586,7 @@ static int fib_detect_death(struct fib_info *fi, int order, if (likely(nhc->nhc_gw_family == AF_INET)) n = neigh_lookup(arp_table(net), &nhc->nhc_gw.ipv4, nhc->nhc_dev); else if (IS_ENABLED(CONFIG_IPV6) && nhc->nhc_gw_family == AF_INET6) - n = neigh_lookup(&nd_tbl, &nhc->nhc_gw.ipv6, nhc->nhc_dev); + n = neigh_lookup(nd_table(net), &nhc->nhc_gw.ipv6, nhc->nhc_dev); else n = NULL; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f6fa2715b450..f3be7a8f996d 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -376,6 +376,8 @@ static int snmp6_alloc_dev(struct inet6_dev *idev) static struct inet6_dev *ipv6_add_dev(struct net_device *dev) { + struct net *net = dev_net(dev); + struct neigh_table *tbl; struct inet6_dev *ndev; int err = -ENOMEM; @@ -393,14 +395,15 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) ndev->dev = dev; INIT_LIST_HEAD(&ndev->addr_list); timer_setup(&ndev->rs_timer, addrconf_rs_timer, 0); - memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); + memcpy(&ndev->cnf, net->ipv6.devconf_dflt, sizeof(ndev->cnf)); if (ndev->cnf.stable_secret.initialized) ndev->cnf.addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY; + tbl = nd_table(net); ndev->cnf.mtu6 = dev->mtu; ndev->ra_mtu = 0; - ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl); + ndev->nd_parms = neigh_parms_alloc(dev, tbl); if (!ndev->nd_parms) { kfree(ndev); return ERR_PTR(err); @@ -413,7 +416,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) if (snmp6_alloc_dev(ndev) < 0) { netdev_dbg(dev, "%s: cannot allocate memory for statistics\n", __func__); - neigh_parms_release(&nd_tbl, ndev->nd_parms); + neigh_parms_release(tbl, ndev->nd_parms); netdev_put(dev, &ndev->dev_tracker); kfree(ndev); return ERR_PTR(err); @@ -481,7 +484,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) return ndev; err_release: - neigh_parms_release(&nd_tbl, ndev->nd_parms); + neigh_parms_release(tbl, ndev->nd_parms); ndev->dead = 1; in6_dev_finish_destroy(ndev); return ERR_PTR(err); @@ -4038,9 +4041,11 @@ static int addrconf_ifdown(struct net_device *dev, bool unregister) /* Last: Shot the device (if unregistered) */ if (unregister) { + struct neigh_table *tbl = nd_table(net); + addrconf_sysctl_unregister(idev); - neigh_parms_release(&nd_tbl, idev->nd_parms); - neigh_ifdown(&nd_tbl, dev); + neigh_parms_release(tbl, idev->nd_parms); + neigh_ifdown(tbl, dev); in6_dev_put(idev); } return 0; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 2c44e5ed6171..1ec32b3c0a7f 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -125,7 +125,7 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * if (IS_ERR_OR_NULL(neigh)) { if (unlikely(!neigh)) - neigh = __neigh_create(&nd_tbl, nexthop, dev, false); + neigh = __neigh_create(nd_table(net), nexthop, dev, false); if (IS_ERR(neigh)) { IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTNOROUTES); kfree_skb_reason(skb, SKB_DROP_REASON_NEIGH_CREATEFAIL); @@ -581,7 +581,7 @@ int ip6_forward(struct sk_buff *skb) /* XXX: idev->cnf.proxy_ndp? */ if (READ_ONCE(net->ipv6.devconf_all->proxy_ndp) && - pneigh_lookup(&nd_tbl, net, &hdr->daddr, skb->dev)) { + pneigh_lookup(nd_table(net), net, &hdr->daddr, skb->dev)) { int proxied = ip6_forward_proxy_check(skb); hdr = ipv6_hdr(skb); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 8e630b47c0b9..3a458b188595 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -766,10 +766,11 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) static int pndisc_is_router(const void *pkey, struct net_device *dev) { + struct net *net = dev_net(dev); struct pneigh_entry *n; int ret = -1; - n = pneigh_lookup(&nd_tbl, dev_net(dev), pkey, dev); + n = pneigh_lookup(nd_table(net), net, pkey, dev); if (n) ret = !!(READ_ONCE(n->flags) & NTF_ROUTER); @@ -787,19 +788,21 @@ void ndisc_update(const struct net_device *dev, struct neighbour *neigh, static enum skb_drop_reason ndisc_recv_ns(struct sk_buff *skb) { + u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) + + offsetof(struct nd_msg, opt)); struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; - u8 *lladdr = NULL; - u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) + - offsetof(struct nd_msg, opt)); - struct ndisc_options ndopts; struct net_device *dev = skb->dev; - struct inet6_ifaddr *ifp; + struct net *net = dev_net(dev); + int dad = ipv6_addr_any(saddr); struct inet6_dev *idev = NULL; + struct ndisc_options ndopts; + struct inet6_ifaddr *ifp; + struct neigh_table *tbl; struct neighbour *neigh; - int dad = ipv6_addr_any(saddr); int is_router = -1; + u8 *lladdr = NULL; SKB_DR(reason); u64 nonce = 0; bool inc; @@ -844,9 +847,10 @@ static enum skb_drop_reason ndisc_recv_ns(struct sk_buff *skb) if (ndopts.nd_opts_nonce && ndopts.nd_opts_nonce->nd_opt_len == 1) memcpy(&nonce, (u8 *)(ndopts.nd_opts_nonce + 1), 6); - inc = ipv6_addr_is_multicast(daddr); + tbl = nd_table(net); - ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1); + inc = ipv6_addr_is_multicast(daddr); + ifp = ipv6_get_ifaddr(net, &msg->target, dev, 1); if (ifp) { have_ifp: if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) { @@ -879,8 +883,6 @@ static enum skb_drop_reason ndisc_recv_ns(struct sk_buff *skb) idev = ifp->idev; } else { - struct net *net = dev_net(dev); - /* perhaps an address on the master device */ if (netif_is_l3_slave(dev)) { struct net_device *mdev; @@ -917,7 +919,7 @@ static enum skb_drop_reason ndisc_recv_ns(struct sk_buff *skb) */ struct sk_buff *n = skb_clone(skb, GFP_ATOMIC); if (n) - pneigh_enqueue(&nd_tbl, idev->nd_parms, n); + pneigh_enqueue(tbl, idev->nd_parms, n); goto out; } } else { @@ -936,15 +938,15 @@ static enum skb_drop_reason ndisc_recv_ns(struct sk_buff *skb) } if (inc) - NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_mcast); + NEIGH_CACHE_STAT_INC(tbl, rcv_probes_mcast); else - NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_ucast); + NEIGH_CACHE_STAT_INC(tbl, rcv_probes_ucast); /* * update / create cache entry * for the source address */ - neigh = __neigh_lookup(&nd_tbl, saddr, dev, + neigh = __neigh_lookup(tbl, saddr, dev, !inc || lladdr || !dev->addr_len); if (neigh) ndisc_update(dev, neigh, lladdr, NUD_STALE, @@ -986,17 +988,19 @@ static int accept_untracked_na(struct inet6_dev *idev, struct in6_addr *saddr) static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb) { - struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); - struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; - const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; - u8 *lladdr = NULL; u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) + offsetof(struct nd_msg, opt)); - struct ndisc_options ndopts; + struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); + const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; + struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; struct net_device *dev = skb->dev; - struct inet6_dev *idev = __in6_dev_get(dev); + struct net *net = dev_net(dev); + struct ndisc_options ndopts; struct inet6_ifaddr *ifp; + struct neigh_table *tbl; struct neighbour *neigh; + struct inet6_dev *idev; + u8 *lladdr = NULL; SKB_DR(reason); u8 new_state; @@ -1019,6 +1023,7 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb) * and thus should not be accepted. * drop_unsolicited_na takes precedence over accept_untracked_na */ + idev = __in6_dev_get(dev); if (!msg->icmph.icmp6_solicited && idev && READ_ONCE(idev->cnf.drop_unsolicited_na)) return reason; @@ -1033,7 +1038,7 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb) return reason; } } - ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1); + ifp = ipv6_get_ifaddr(net, &msg->target, dev, 1); if (ifp) { if (skb->pkt_type != PACKET_LOOPBACK && (ifp->flags & IFA_F_TENTATIVE)) { @@ -1057,7 +1062,8 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb) return reason; } - neigh = neigh_lookup(&nd_tbl, &msg->target, dev); + tbl = nd_table(net); + neigh = neigh_lookup(tbl, &msg->target, dev); /* RFC 9131 updates original Neighbour Discovery RFC 4861. * NAs with Target LL Address option without a corresponding @@ -1077,14 +1083,13 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb) new_state = msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE; if (!neigh && lladdr && idev && READ_ONCE(idev->cnf.forwarding)) { if (accept_untracked_na(idev, saddr)) { - neigh = neigh_create(&nd_tbl, &msg->target, dev); + neigh = neigh_create(tbl, &msg->target, dev); new_state = NUD_STALE; } } if (neigh && !IS_ERR(neigh)) { u8 old_flags = neigh->flags; - struct net *net = dev_net(dev); if (READ_ONCE(neigh->nud_state) & NUD_FAILED) goto out; @@ -1097,7 +1102,7 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb) if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) && READ_ONCE(net->ipv6.devconf_all->forwarding) && READ_ONCE(net->ipv6.devconf_all->proxy_ndp) && - pneigh_lookup(&nd_tbl, net, &msg->target, dev)) { + pneigh_lookup(tbl, net, &msg->target, dev)) { /* XXX: idev->cnf.proxy_ndp */ goto out; } @@ -1126,18 +1131,20 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb) static enum skb_drop_reason ndisc_recv_rs(struct sk_buff *skb) { struct rs_msg *rs_msg = (struct rs_msg *)skb_transport_header(skb); + const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; unsigned long ndoptlen = skb->len - sizeof(*rs_msg); + struct net_device *dev = skb->dev; + struct ndisc_options ndopts; + struct neigh_table *tbl; struct neighbour *neigh; struct inet6_dev *idev; - const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; - struct ndisc_options ndopts; u8 *lladdr = NULL; SKB_DR(reason); if (skb->len < sizeof(*rs_msg)) return SKB_DROP_REASON_PKT_TOO_SMALL; - idev = __in6_dev_get(skb->dev); + idev = __in6_dev_get(dev); if (!idev) { net_err_ratelimited("RS: can't find in6 device\n"); return reason; @@ -1155,19 +1162,19 @@ static enum skb_drop_reason ndisc_recv_rs(struct sk_buff *skb) goto out; /* Parse ND options */ - if (!ndisc_parse_options(skb->dev, rs_msg->opt, ndoptlen, &ndopts)) + if (!ndisc_parse_options(dev, rs_msg->opt, ndoptlen, &ndopts)) return SKB_DROP_REASON_IPV6_NDISC_BAD_OPTIONS; if (ndopts.nd_opts_src_lladdr) { - lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr, - skb->dev); + lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr, dev); if (!lladdr) goto out; } - neigh = __neigh_lookup(&nd_tbl, saddr, skb->dev, 1); + tbl = nd_table(dev_net(dev)); + neigh = __neigh_lookup(tbl, saddr, dev, 1); if (neigh) { - ndisc_update(skb->dev, neigh, lladdr, NUD_STALE, + ndisc_update(dev, neigh, lladdr, NUD_STALE, NEIGH_UPDATE_F_WEAK_OVERRIDE| NEIGH_UPDATE_F_OVERRIDE| NEIGH_UPDATE_F_OVERRIDE_ISROUTER, @@ -1231,6 +1238,7 @@ static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt) static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb) { struct ra_msg *ra_msg = (struct ra_msg *)skb_transport_header(skb); + struct net *net = dev_net(skb->dev); bool send_ifinfo_notify = false; struct neighbour *neigh = NULL; struct ndisc_options ndopts; @@ -1240,7 +1248,6 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb) u32 defrtr_usr_metric; unsigned int pref = 0; __u32 old_if_flags; - struct net *net; SKB_DR(reason); int lifetime; int optlen; @@ -1329,7 +1336,6 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb) /* Do not accept RA with source-addr found on local machine unless * accept_ra_from_local is set to true. */ - net = dev_net(in6_dev->dev); if (!READ_ONCE(in6_dev->cnf.accept_ra_from_local) && ipv6_chk_addr(net, &ipv6_hdr(skb)->saddr, in6_dev->dev, 0)) { net_dbg_ratelimited("RA from local address detected on dev: %s: default router ignored\n", @@ -1465,7 +1471,7 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb) */ if (!neigh) - neigh = __neigh_lookup(&nd_tbl, &ipv6_hdr(skb)->saddr, + neigh = __neigh_lookup(nd_table(net), &ipv6_hdr(skb)->saddr, skb->dev, 1); if (neigh) { u8 *lladdr = NULL; @@ -1858,12 +1864,15 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct netdev_notifier_change_info *change_info; struct net *net = dev_net(dev); + struct neigh_table *tbl; struct inet6_dev *idev; bool evict_nocarrier; + tbl = nd_table(net); + switch (event) { case NETDEV_CHANGEADDR: - neigh_changeaddr(&nd_tbl, dev); + neigh_changeaddr(tbl, dev); fib6_run_gc(0, net, false); fallthrough; case NETDEV_UP: @@ -1887,12 +1896,12 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, change_info = ptr; if (change_info->flags_changed & IFF_NOARP) - neigh_changeaddr(&nd_tbl, dev); + neigh_changeaddr(tbl, dev); if (evict_nocarrier && !netif_carrier_ok(dev)) - neigh_carrier_down(&nd_tbl, dev); + neigh_carrier_down(tbl, dev); break; case NETDEV_DOWN: - neigh_ifdown(&nd_tbl, dev); + neigh_ifdown(tbl, dev); fib6_run_gc(0, net, false); break; case NETDEV_NOTIFY_PEERS: diff --git a/net/ipv6/route.c b/net/ipv6/route.c index fc42d67e5822..88914f5a68f8 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -217,7 +217,7 @@ struct neighbour *ip6_neigh_lookup(const struct in6_addr *gw, if (n) return n; - n = neigh_create(&nd_tbl, daddr, dev); + n = neigh_create(nd_table(dev_net(dev)), daddr, dev); return IS_ERR(n) ? NULL : n; } @@ -4229,6 +4229,7 @@ static int ip6_route_del(struct fib6_config *cfg, static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb) { struct netevent_redirect netevent; + struct net_device *dev = skb->dev; struct rt6_info *rt, *nrt = NULL; struct fib6_result res = {}; struct ndisc_options ndopts; @@ -4262,7 +4263,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu return; } - in6_dev = __in6_dev_get(skb->dev); + in6_dev = __in6_dev_get(dev); if (!in6_dev) return; if (READ_ONCE(in6_dev->cnf.forwarding) || @@ -4274,15 +4275,14 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu * first-hop router for the specified ICMP Destination Address. */ - if (!ndisc_parse_options(skb->dev, msg->opt, optlen, &ndopts)) { + if (!ndisc_parse_options(dev, msg->opt, optlen, &ndopts)) { net_dbg_ratelimited("rt6_redirect: invalid ND options\n"); return; } lladdr = NULL; if (ndopts.nd_opts_tgt_lladdr) { - lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr, - skb->dev); + lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr, dev); if (!lladdr) { net_dbg_ratelimited("rt6_redirect: invalid link-layer address length\n"); return; @@ -4301,7 +4301,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu */ dst_confirm_neigh(&rt->dst, &ipv6_hdr(skb)->saddr); - neigh = __neigh_lookup(&nd_tbl, &msg->target, skb->dev, 1); + neigh = __neigh_lookup(nd_table(dev_net(dev)), &msg->target, dev, 1); if (!neigh) return; @@ -4309,7 +4309,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu * We have finally decided to accept it. */ - ndisc_update(skb->dev, neigh, lladdr, NUD_STALE, + ndisc_update(dev, neigh, lladdr, NUD_STALE, NEIGH_UPDATE_F_WEAK_OVERRIDE| NEIGH_UPDATE_F_OVERRIDE| (on_link ? 0 : (NEIGH_UPDATE_F_OVERRIDE_ISROUTER| @@ -5030,9 +5030,11 @@ void rt6_sync_down_dev(struct net_device *dev, unsigned long event) void rt6_disable_ip(struct net_device *dev, unsigned long event) { + struct net *net = dev_net(dev); + rt6_sync_down_dev(dev, event); rt6_uncached_list_flush_dev(dev); - neigh_ifdown(&nd_tbl, dev); + neigh_ifdown(nd_table(net), dev); } struct rt6_mtu_change_arg { -- 2.55.0.679.g6767b8d81c-goog