[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAEA6p_Dxm-BeKcNQEM_N7UGgSTJ6dtc=3wGHjqqzKW1tGG3jHg@mail.gmail.com>
Date: Mon, 26 Feb 2018 14:28:07 -0800
From: Wei Wang <weiwan@...gle.com>
To: David Ahern <dsahern@...il.com>
Cc: Linux Kernel Network Developers <netdev@...r.kernel.org>,
"David S . Miller" <davem@...emloft.net>,
Ido Schimmel <idosch@...sch.org>, roopa@...ulusnetworks.com,
Eric Dumazet <eric.dumazet@...il.com>,
Martin KaFai Lau <kafai@...com>,
Hideaki YOSHIFUJI <yoshfuji@...ux-ipv6.org>
Subject: Re: [PATCH RFC net-next 07/20] net/ipv6: Move nexthop data to fib6_nh
On Sun, Feb 25, 2018 at 11:47 AM, David Ahern <dsahern@...il.com> wrote:
> Introduce fib6_nh structure and move nexthop related data from
> rt6_info and rt6_info.dst to fib6_nh. References to dev, gateway or
> lwtstate from a FIB lookup perspective are converted to use fib6_nh;
> datapath references to dst version are left as is.
>
My understanding is that after your whole patch series, sibling routes
will still have their own fib6_info. Does it make sense to make this
fib6_nh as an array in fib6_info so that sibling routes will share
fib6_info but will have their own fib6_nh as a future improvement? It
matches ipv4 behavior. And I think it will make the sibling route
handling code easier?
> Signed-off-by: David Ahern <dsahern@...il.com>
> ---
> .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 32 ++--
> include/net/ip6_fib.h | 16 +-
> include/net/ip6_route.h | 6 +-
> net/ipv6/addrconf.c | 2 +-
> net/ipv6/ip6_fib.c | 6 +-
> net/ipv6/route.c | 164 ++++++++++++---------
> 6 files changed, 127 insertions(+), 99 deletions(-)
>
> diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
> index 05146970c19c..90d01df783b3 100644
> --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
> +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
> @@ -2700,9 +2700,9 @@ mlxsw_sp_nexthop6_group_cmp(const struct mlxsw_sp_nexthop_group *nh_grp,
> struct in6_addr *gw;
> int ifindex, weight;
>
> - ifindex = mlxsw_sp_rt6->rt->dst.dev->ifindex;
> - weight = mlxsw_sp_rt6->rt->rt6i_nh_weight;
> - gw = &mlxsw_sp_rt6->rt->rt6i_gateway;
> + ifindex = mlxsw_sp_rt6->rt->fib6_nh.nh_dev->ifindex;
> + weight = mlxsw_sp_rt6->rt->fib6_nh.nh_weight;
> + gw = &mlxsw_sp_rt6->rt->fib6_nh.nh_gw;
> if (!mlxsw_sp_nexthop6_group_has_nexthop(nh_grp, gw, ifindex,
> weight))
> return false;
> @@ -2768,7 +2768,7 @@ mlxsw_sp_nexthop6_group_hash(struct mlxsw_sp_fib6_entry *fib6_entry, u32 seed)
> struct net_device *dev;
>
> list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
> - dev = mlxsw_sp_rt6->rt->dst.dev;
> + dev = mlxsw_sp_rt6->rt->fib6_nh.nh_dev;
> val ^= dev->ifindex;
> }
>
> @@ -3766,9 +3766,9 @@ mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group *nh_grp,
> struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i];
> struct rt6_info *rt = mlxsw_sp_rt6->rt;
>
> - if (nh->rif && nh->rif->dev == rt->dst.dev &&
> + if (nh->rif && nh->rif->dev == rt->fib6_nh.nh_dev &&
> ipv6_addr_equal((const struct in6_addr *) &nh->gw_addr,
> - &rt->rt6i_gateway))
> + &rt->fib6_nh.nh_gw))
> return nh;
> continue;
> }
> @@ -3825,7 +3825,7 @@ mlxsw_sp_fib6_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
>
> if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL) {
> list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6,
> - list)->rt->rt6i_nh_flags |= RTNH_F_OFFLOAD;
> + list)->rt->fib6_nh.nh_flags |= RTNH_F_OFFLOAD;
> return;
> }
>
> @@ -3835,9 +3835,9 @@ mlxsw_sp_fib6_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
>
> nh = mlxsw_sp_rt6_nexthop(nh_grp, mlxsw_sp_rt6);
> if (nh && nh->offloaded)
> - mlxsw_sp_rt6->rt->rt6i_nh_flags |= RTNH_F_OFFLOAD;
> + mlxsw_sp_rt6->rt->fib6_nh.nh_flags |= RTNH_F_OFFLOAD;
> else
> - mlxsw_sp_rt6->rt->rt6i_nh_flags &= ~RTNH_F_OFFLOAD;
> + mlxsw_sp_rt6->rt->fib6_nh.nh_flags &= ~RTNH_F_OFFLOAD;
> }
> }
>
> @@ -3852,7 +3852,7 @@ mlxsw_sp_fib6_entry_offload_unset(struct mlxsw_sp_fib_entry *fib_entry)
> list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
> struct rt6_info *rt = mlxsw_sp_rt6->rt;
>
> - rt->rt6i_nh_flags &= ~RTNH_F_OFFLOAD;
> + rt->fib6_nh.nh_flags &= ~RTNH_F_OFFLOAD;
> }
> }
>
> @@ -4748,8 +4748,8 @@ static bool mlxsw_sp_nexthop6_ipip_type(const struct mlxsw_sp *mlxsw_sp,
> const struct rt6_info *rt,
> enum mlxsw_sp_ipip_type *ret)
> {
> - return rt->dst.dev &&
> - mlxsw_sp_netdev_ipip_type(mlxsw_sp, rt->dst.dev, ret);
> + return rt->fib6_nh.nh_dev &&
> + mlxsw_sp_netdev_ipip_type(mlxsw_sp, rt->fib6_nh.nh_dev, ret);
> }
>
> static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp *mlxsw_sp,
> @@ -4759,7 +4759,7 @@ static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp *mlxsw_sp,
> {
> const struct mlxsw_sp_ipip_ops *ipip_ops;
> struct mlxsw_sp_ipip_entry *ipip_entry;
> - struct net_device *dev = rt->dst.dev;
> + struct net_device *dev = rt->fib6_nh.nh_dev;
> struct mlxsw_sp_rif *rif;
> int err;
>
> @@ -4802,11 +4802,11 @@ static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp,
> struct mlxsw_sp_nexthop *nh,
> const struct rt6_info *rt)
> {
> - struct net_device *dev = rt->dst.dev;
> + struct net_device *dev = rt->fib6_nh.nh_dev;
>
> nh->nh_grp = nh_grp;
> - nh->nh_weight = rt->rt6i_nh_weight;
> - memcpy(&nh->gw_addr, &rt->rt6i_gateway, sizeof(nh->gw_addr));
> + nh->nh_weight = rt->fib6_nh.nh_weight;
> + memcpy(&nh->gw_addr, &rt->fib6_nh.nh_gw, sizeof(nh->gw_addr));
> mlxsw_sp_nexthop_counter_alloc(mlxsw_sp, nh);
>
> list_add_tail(&nh->router_list_node, &mlxsw_sp->router->nexthop_list);
> diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
> index 4badcf105bd9..7678ae3de44a 100644
> --- a/include/net/ip6_fib.h
> +++ b/include/net/ip6_fib.h
> @@ -127,6 +127,16 @@ struct rt6_exception {
> #define FIB6_EXCEPTION_BUCKET_SIZE (1 << FIB6_EXCEPTION_BUCKET_SIZE_SHIFT)
> #define FIB6_MAX_DEPTH 5
>
> +struct fib6_nh {
> + struct in6_addr nh_gw;
> + struct net_device *nh_dev;
> + struct lwtunnel_state *nh_lwtstate;
> +
> + unsigned int nh_flags;
> + atomic_t nh_upper_bound;
> + int nh_weight;
> +};
> +
> struct rt6_info {
> struct dst_entry dst;
> struct rt6_info __rcu *rt6_next;
> @@ -149,12 +159,9 @@ struct rt6_info {
> */
> struct list_head rt6i_siblings;
> unsigned int rt6i_nsiblings;
> - atomic_t rt6i_nh_upper_bound;
>
> atomic_t rt6i_ref;
>
> - unsigned int rt6i_nh_flags;
> -
> /* These are in a separate cache line. */
> struct rt6key rt6i_dst ____cacheline_aligned_in_smp;
> u32 rt6i_flags;
> @@ -171,13 +178,14 @@ struct rt6_info {
> u32 rt6i_metric;
> u32 rt6i_pmtu;
> /* more non-fragment space at head required */
> - int rt6i_nh_weight;
> unsigned short rt6i_nfheader_len;
> u8 rt6i_protocol;
> u8 fib6_type;
> u8 exception_bucket_flushed:1,
> should_flush:1,
> unused:6;
> +
> + struct fib6_nh fib6_nh;
> };
>
> #define for_each_fib6_node_rt_rcu(fn) \
> diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
> index ef0d8977e2d0..bd82ec4a57e6 100644
> --- a/include/net/ip6_route.h
> +++ b/include/net/ip6_route.h
> @@ -263,9 +263,9 @@ static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt,
>
> static inline bool rt6_duplicate_nexthop(struct rt6_info *a, struct rt6_info *b)
> {
> - return a->dst.dev == b->dst.dev &&
> + return a->fib6_nh.nh_dev == b->fib6_nh.nh_dev &&
> a->rt6i_idev == b->rt6i_idev &&
> - ipv6_addr_equal(&a->rt6i_gateway, &b->rt6i_gateway) &&
> - !lwtunnel_cmp_encap(a->dst.lwtstate, b->dst.lwtstate);
> + ipv6_addr_equal(&a->fib6_nh.nh_gw, &b->fib6_nh.nh_gw) &&
> + !lwtunnel_cmp_encap(a->fib6_nh.nh_lwtstate, b->fib6_nh.nh_lwtstate);
> }
> #endif
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index 82862d3f0295..eeecef2b83a4 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -2344,7 +2344,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
> goto out;
>
> for_each_fib6_node_rt_rcu(fn) {
> - if (rt->dst.dev->ifindex != dev->ifindex)
> + if (rt->fib6_nh.nh_dev->ifindex != dev->ifindex)
> continue;
> if ((rt->rt6i_flags & flags) != flags)
> continue;
> diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
> index 51d2d5a7ba89..134d86483f3c 100644
> --- a/net/ipv6/ip6_fib.c
> +++ b/net/ipv6/ip6_fib.c
> @@ -2213,6 +2213,7 @@ static int ipv6_route_seq_show(struct seq_file *seq, void *v)
> {
> struct rt6_info *rt = v;
> struct ipv6_route_iter *iter = seq->private;
> + const struct net_device *dev;
>
> seq_printf(seq, "%pi6 %02x ", &rt->rt6i_dst.addr, rt->rt6i_dst.plen);
>
> @@ -2222,14 +2223,15 @@ static int ipv6_route_seq_show(struct seq_file *seq, void *v)
> seq_puts(seq, "00000000000000000000000000000000 00 ");
> #endif
> if (rt->rt6i_flags & RTF_GATEWAY)
> - seq_printf(seq, "%pi6", &rt->rt6i_gateway);
> + seq_printf(seq, "%pi6", &rt->fib6_nh.nh_gw);
> else
> seq_puts(seq, "00000000000000000000000000000000");
>
> + dev = rt->fib6_nh.nh_dev;
> seq_printf(seq, " %08x %08x %08x %08x %8s\n",
> rt->rt6i_metric, atomic_read(&rt->dst.__refcnt),
> rt->dst.__use, rt->rt6i_flags,
> - rt->dst.dev ? rt->dst.dev->name : "");
> + dev ? dev->name : "");
> iter->w.leaf = NULL;
> return 0;
> }
> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> index 2de9af0bead1..ff809ee930c7 100644
> --- a/net/ipv6/route.c
> +++ b/net/ipv6/route.c
> @@ -464,12 +464,15 @@ static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
> if (!fl6->mp_hash)
> fl6->mp_hash = rt6_multipath_hash(fl6, NULL);
>
> - if (fl6->mp_hash <= atomic_read(&match->rt6i_nh_upper_bound))
> + if (fl6->mp_hash <= atomic_read(&match->fib6_nh.nh_upper_bound))
> return match;
>
> list_for_each_entry_safe(sibling, next_sibling, &match->rt6i_siblings,
> rt6i_siblings) {
> - if (fl6->mp_hash > atomic_read(&sibling->rt6i_nh_upper_bound))
> + int nh_upper_bound;
> +
> + nh_upper_bound = atomic_read(&sibling->fib6_nh.nh_upper_bound);
> + if (fl6->mp_hash > nh_upper_bound)
> continue;
> if (rt6_score_route(sibling, oif, strict) < 0)
> break;
> @@ -493,13 +496,14 @@ static inline struct rt6_info *rt6_device_match(struct net *net,
> struct rt6_info *local = NULL;
> struct rt6_info *sprt;
>
> - if (!oif && ipv6_addr_any(saddr) && !(rt->rt6i_nh_flags & RTNH_F_DEAD))
> + if (!oif && ipv6_addr_any(saddr) &&
> + !(rt->fib6_nh.nh_flags & RTNH_F_DEAD))
> return rt;
>
> for (sprt = rt; sprt; sprt = rcu_dereference(sprt->rt6_next)) {
> - struct net_device *dev = sprt->dst.dev;
> + const struct net_device *dev = sprt->fib6_nh.nh_dev;
>
> - if (sprt->rt6i_nh_flags & RTNH_F_DEAD)
> + if (sprt->fib6_nh.nh_flags & RTNH_F_DEAD)
> continue;
>
> if (oif) {
> @@ -531,7 +535,7 @@ static inline struct rt6_info *rt6_device_match(struct net *net,
> return net->ipv6.ip6_null_entry;
> }
>
> - return rt->rt6i_nh_flags & RTNH_F_DEAD ? net->ipv6.ip6_null_entry : rt;
> + return rt->fib6_nh.nh_flags & RTNH_F_DEAD ? net->ipv6.ip6_null_entry : rt;
> }
>
> #ifdef CONFIG_IPV6_ROUTER_PREF
> @@ -556,7 +560,10 @@ static void rt6_probe_deferred(struct work_struct *w)
> static void rt6_probe(struct rt6_info *rt)
> {
> struct __rt6_probe_work *work;
> + const struct in6_addr *nh_gw;
> struct neighbour *neigh;
> + struct net_device *dev;
> +
> /*
> * Okay, this does not seem to be appropriate
> * for now, however, we need to check if it
> @@ -567,8 +574,11 @@ static void rt6_probe(struct rt6_info *rt)
> */
> if (!rt || !(rt->rt6i_flags & RTF_GATEWAY))
> return;
> +
> + nh_gw = &rt->fib6_nh.nh_gw;
> + dev = rt->fib6_nh.nh_dev;
> rcu_read_lock_bh();
> - neigh = __ipv6_neigh_lookup_noref(rt->dst.dev, &rt->rt6i_gateway);
> + neigh = __ipv6_neigh_lookup_noref(dev, nh_gw);
> if (neigh) {
> if (neigh->nud_state & NUD_VALID)
> goto out;
> @@ -590,9 +600,9 @@ static void rt6_probe(struct rt6_info *rt)
>
> if (work) {
> INIT_WORK(&work->work, rt6_probe_deferred);
> - work->target = rt->rt6i_gateway;
> - dev_hold(rt->dst.dev);
> - work->dev = rt->dst.dev;
> + work->target = *nh_gw;
> + dev_hold(dev);
> + work->dev = dev;
> schedule_work(&work->work);
> }
>
> @@ -610,7 +620,8 @@ static inline void rt6_probe(struct rt6_info *rt)
> */
> static inline int rt6_check_dev(struct rt6_info *rt, int oif)
> {
> - struct net_device *dev = rt->dst.dev;
> + const struct net_device *dev = rt->fib6_nh.nh_dev;
> +
> if (!oif || dev->ifindex == oif)
> return 2;
> if ((dev->flags & IFF_LOOPBACK) &&
> @@ -621,15 +632,16 @@ static inline int rt6_check_dev(struct rt6_info *rt, int oif)
>
> static inline enum rt6_nud_state rt6_check_neigh(struct rt6_info *rt)
> {
> - struct neighbour *neigh;
> enum rt6_nud_state ret = RT6_NUD_FAIL_HARD;
> + struct neighbour *neigh;
>
> if (rt->rt6i_flags & RTF_NONEXTHOP ||
> !(rt->rt6i_flags & RTF_GATEWAY))
> return RT6_NUD_SUCCEED;
>
> rcu_read_lock_bh();
> - neigh = __ipv6_neigh_lookup_noref(rt->dst.dev, &rt->rt6i_gateway);
> + neigh = __ipv6_neigh_lookup_noref(rt->fib6_nh.nh_dev,
> + &rt->fib6_nh.nh_gw);
> if (neigh) {
> read_lock(&neigh->lock);
> if (neigh->nud_state & NUD_VALID)
> @@ -677,11 +689,11 @@ static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict,
> bool match_do_rr = false;
> struct inet6_dev *idev = rt->rt6i_idev;
>
> - if (rt->rt6i_nh_flags & RTNH_F_DEAD)
> + if (rt->fib6_nh.nh_flags & RTNH_F_DEAD)
> goto out;
>
> if (idev->cnf.ignore_routes_with_linkdown &&
> - rt->rt6i_nh_flags & RTNH_F_LINKDOWN &&
> + rt->fib6_nh.nh_flags & RTNH_F_LINKDOWN &&
> !(strict & RT6_LOOKUP_F_IGNORE_LINKSTATE))
> goto out;
>
> @@ -886,7 +898,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
> /* called with rcu_lock held */
> static struct net_device *ip6_rt_get_dev_rcu(struct rt6_info *rt)
> {
> - struct net_device *dev = rt->dst.dev;
> + struct net_device *dev = rt->fib6_nh.nh_dev;
>
> if (rt->rt6i_flags & (RTF_LOCAL | RTF_ANYCAST)) {
> /* for copies of local routes, dst->dev needs to be the
> @@ -926,7 +938,7 @@ static void ip6_rt_copy_init(struct rt6_info *rt, struct rt6_info *ort)
> if (rt->rt6i_idev)
> in6_dev_hold(rt->rt6i_idev);
> rt->dst.lastuse = jiffies;
> - rt->rt6i_gateway = ort->rt6i_gateway;
> + rt->rt6i_gateway = ort->fib6_nh.nh_gw;
> rt->rt6i_flags = ort->rt6i_flags;
> rt6_set_from(rt, ort);
> rt->rt6i_metric = ort->rt6i_metric;
> @@ -935,7 +947,7 @@ static void ip6_rt_copy_init(struct rt6_info *rt, struct rt6_info *ort)
> #endif
> rt->rt6i_prefsrc = ort->rt6i_prefsrc;
> rt->rt6i_table = ort->rt6i_table;
> - rt->dst.lwtstate = lwtstate_get(ort->dst.lwtstate);
> + rt->dst.lwtstate = lwtstate_get(ort->fib6_nh.nh_lwtstate);
> }
>
> static struct fib6_node* fib6_backtrack(struct fib6_node *fn,
> @@ -1300,7 +1312,7 @@ __rt6_find_exception_rcu(struct rt6_exception_bucket **bucket,
> static int rt6_insert_exception(struct rt6_info *nrt,
> struct rt6_info *ort)
> {
> - struct net *net = dev_net(ort->dst.dev);
> + struct net *net = dev_net(nrt->dst.dev);
> struct rt6_exception_bucket *bucket;
> struct in6_addr *src_key = NULL;
> struct rt6_exception *rt6_ex;
> @@ -2194,7 +2206,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
> fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
> restart:
> for_each_fib6_node_rt_rcu(fn) {
> - if (rt->rt6i_nh_flags & RTNH_F_DEAD)
> + if (rt->fib6_nh.nh_flags & RTNH_F_DEAD)
> continue;
> if (rt6_check_expired(rt))
> continue;
> @@ -2202,14 +2214,14 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
> break;
> if (!(rt->rt6i_flags & RTF_GATEWAY))
> continue;
> - if (fl6->flowi6_oif != rt->dst.dev->ifindex)
> + if (fl6->flowi6_oif != rt->fib6_nh.nh_dev->ifindex)
> continue;
> /* rt_cache's gateway might be different from its 'parent'
> * in the case of an ip redirect.
> * So we keep searching in the exception table if the gateway
> * is different.
> */
> - if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway)) {
> + if (!ipv6_addr_equal(&rdfl->gateway, &rt->fib6_nh.nh_gw)) {
> rt_cache = rt6_find_cached_rt(rt,
> &fl6->daddr,
> &fl6->saddr);
> @@ -2712,7 +2724,7 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
> &lwtstate, extack);
> if (err)
> goto out;
> - rt->dst.lwtstate = lwtstate_get(lwtstate);
> + rt->fib6_nh.nh_lwtstate = lwtstate_get(lwtstate);
> lwtunnel_set_redirect(&rt->dst);
> }
>
> @@ -2727,7 +2739,7 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
> #endif
>
> rt->rt6i_metric = cfg->fc_metric;
> - rt->rt6i_nh_weight = 1;
> + rt->fib6_nh.nh_weight = 1;
>
> rt->fib6_type = cfg->fc_type;
>
> @@ -2796,7 +2808,9 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
> NL_SET_ERR_MSG(extack, "Invalid gateway address");
> goto out;
> }
> - rt->rt6i_gateway = *gw_addr;
> + rt->fib6_nh.nh_gw = *gw_addr;
> +
> + rt->rt6i_gateway = rt->fib6_nh.nh_gw;
>
> if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) {
> /* IPv6 strictly inhibits using not link-local
> @@ -2861,9 +2875,9 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
> install_route:
> if (!(rt->rt6i_flags & (RTF_LOCAL | RTF_ANYCAST)) &&
> !netif_carrier_ok(dev))
> - rt->rt6i_nh_flags |= RTNH_F_LINKDOWN;
> - rt->rt6i_nh_flags |= (cfg->fc_flags & RTNH_F_ONLINK);
> - rt->dst.dev = dev;
> + rt->fib6_nh.nh_flags |= RTNH_F_LINKDOWN;
> + rt->fib6_nh.nh_flags |= (cfg->fc_flags & RTNH_F_ONLINK);
> + rt->fib6_nh.nh_dev = rt->dst.dev = dev;
> rt->rt6i_idev = idev;
> rt->rt6i_table = table;
>
> @@ -3022,11 +3036,11 @@ static int ip6_route_del(struct fib6_config *cfg,
> rt = rt_cache;
> }
> if (cfg->fc_ifindex &&
> - (!rt->dst.dev ||
> - rt->dst.dev->ifindex != cfg->fc_ifindex))
> + (!rt->fib6_nh.nh_dev ||
> + rt->fib6_nh.nh_dev->ifindex != cfg->fc_ifindex))
> continue;
> if (cfg->fc_flags & RTF_GATEWAY &&
> - !ipv6_addr_equal(&cfg->fc_gateway, &rt->rt6i_gateway))
> + !ipv6_addr_equal(&cfg->fc_gateway, &rt->fib6_nh.nh_gw))
> continue;
> if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric)
> continue;
> @@ -3188,11 +3202,11 @@ static struct rt6_info *rt6_get_route_info(struct net *net,
> goto out;
>
> for_each_fib6_node_rt_rcu(fn) {
> - if (rt->dst.dev->ifindex != ifindex)
> + if (rt->fib6_nh.nh_dev->ifindex != ifindex)
> continue;
> if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY))
> continue;
> - if (!ipv6_addr_equal(&rt->rt6i_gateway, gwaddr))
> + if (!ipv6_addr_equal(&rt->fib6_nh.nh_gw, gwaddr))
> continue;
> ip6_hold_safe(NULL, &rt, false);
> break;
> @@ -3249,9 +3263,9 @@ struct rt6_info *rt6_get_dflt_router(struct net *net,
>
> rcu_read_lock();
> for_each_fib6_node_rt_rcu(&table->tb6_root) {
> - if (dev == rt->dst.dev &&
> + if (dev == rt->fib6_nh.nh_dev &&
> ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) &&
> - ipv6_addr_equal(&rt->rt6i_gateway, addr))
> + ipv6_addr_equal(&rt->fib6_nh.nh_gw, addr))
> break;
> }
> if (rt)
> @@ -3477,6 +3491,8 @@ struct rt6_info *addrconf_dst_alloc(struct net *net,
> rt->rt6i_flags |= RTF_LOCAL;
> }
>
> + rt->fib6_nh.nh_gw = *addr;
> + rt->fib6_nh.nh_dev = dev;
> rt->rt6i_gateway = *addr;
> rt->rt6i_dst.addr = *addr;
> rt->rt6i_dst.plen = 128;
> @@ -3499,7 +3515,7 @@ static int fib6_remove_prefsrc(struct rt6_info *rt, void *arg)
> struct net *net = ((struct arg_dev_net_ip *)arg)->net;
> struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr;
>
> - if (((void *)rt->dst.dev == dev || !dev) &&
> + if (((void *)rt->fib6_nh.nh_dev == dev || !dev) &&
> rt != net->ipv6.ip6_null_entry &&
> ipv6_addr_equal(addr, &rt->rt6i_prefsrc.addr)) {
> spin_lock_bh(&rt6_exception_lock);
> @@ -3531,7 +3547,7 @@ static int fib6_clean_tohost(struct rt6_info *rt, void *arg)
> struct in6_addr *gateway = (struct in6_addr *)arg;
>
> if (((rt->rt6i_flags & RTF_RA_ROUTER) == RTF_RA_ROUTER) &&
> - ipv6_addr_equal(gateway, &rt->rt6i_gateway)) {
> + ipv6_addr_equal(gateway, &rt->fib6_nh.nh_gw)) {
> return -1;
> }
>
> @@ -3579,8 +3595,8 @@ static struct rt6_info *rt6_multipath_first_sibling(const struct rt6_info *rt)
>
> static bool rt6_is_dead(const struct rt6_info *rt)
> {
> - if (rt->rt6i_nh_flags & RTNH_F_DEAD ||
> - (rt->rt6i_nh_flags & RTNH_F_LINKDOWN &&
> + if (rt->fib6_nh.nh_flags & RTNH_F_DEAD ||
> + (rt->fib6_nh.nh_flags & RTNH_F_LINKDOWN &&
> rt->rt6i_idev->cnf.ignore_routes_with_linkdown))
> return true;
>
> @@ -3593,11 +3609,11 @@ static int rt6_multipath_total_weight(const struct rt6_info *rt)
> int total = 0;
>
> if (!rt6_is_dead(rt))
> - total += rt->rt6i_nh_weight;
> + total += rt->fib6_nh.nh_weight;
>
> list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings) {
> if (!rt6_is_dead(iter))
> - total += iter->rt6i_nh_weight;
> + total += iter->fib6_nh.nh_weight;
> }
>
> return total;
> @@ -3608,11 +3624,11 @@ static void rt6_upper_bound_set(struct rt6_info *rt, int *weight, int total)
> int upper_bound = -1;
>
> if (!rt6_is_dead(rt)) {
> - *weight += rt->rt6i_nh_weight;
> + *weight += rt->fib6_nh.nh_weight;
> upper_bound = DIV_ROUND_CLOSEST_ULL((u64) (*weight) << 31,
> total) - 1;
> }
> - atomic_set(&rt->rt6i_nh_upper_bound, upper_bound);
> + atomic_set(&rt->fib6_nh.nh_upper_bound, upper_bound);
> }
>
> static void rt6_multipath_upper_bound_set(struct rt6_info *rt, int total)
> @@ -3655,8 +3671,8 @@ static int fib6_ifup(struct rt6_info *rt, void *p_arg)
> const struct arg_netdev_event *arg = p_arg;
> struct net *net = dev_net(arg->dev);
>
> - if (rt != net->ipv6.ip6_null_entry && rt->dst.dev == arg->dev) {
> - rt->rt6i_nh_flags &= ~arg->nh_flags;
> + if (rt != net->ipv6.ip6_null_entry && rt->fib6_nh.nh_dev == arg->dev) {
> + rt->fib6_nh.nh_flags &= ~arg->nh_flags;
> fib6_update_sernum_upto_root(net, rt);
> rt6_multipath_rebalance(rt);
> }
> @@ -3684,10 +3700,10 @@ static bool rt6_multipath_uses_dev(const struct rt6_info *rt,
> {
> struct rt6_info *iter;
>
> - if (rt->dst.dev == dev)
> + if (rt->fib6_nh.nh_dev == dev)
> return true;
> list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings)
> - if (iter->dst.dev == dev)
> + if (iter->fib6_nh.nh_dev == dev)
> return true;
>
> return false;
> @@ -3708,11 +3724,12 @@ static unsigned int rt6_multipath_dead_count(const struct rt6_info *rt,
> struct rt6_info *iter;
> unsigned int dead = 0;
>
> - if (rt->dst.dev == down_dev || rt->rt6i_nh_flags & RTNH_F_DEAD)
> + if (rt->fib6_nh.nh_dev == down_dev ||
> + rt->fib6_nh.nh_flags & RTNH_F_DEAD)
> dead++;
> list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings)
> - if (iter->dst.dev == down_dev ||
> - iter->rt6i_nh_flags & RTNH_F_DEAD)
> + if (iter->fib6_nh.nh_dev == down_dev ||
> + iter->fib6_nh.nh_flags & RTNH_F_DEAD)
> dead++;
>
> return dead;
> @@ -3724,11 +3741,11 @@ static void rt6_multipath_nh_flags_set(struct rt6_info *rt,
> {
> struct rt6_info *iter;
>
> - if (rt->dst.dev == dev)
> - rt->rt6i_nh_flags |= nh_flags;
> + if (rt->fib6_nh.nh_dev == dev)
> + rt->fib6_nh.nh_flags |= nh_flags;
> list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings)
> - if (iter->dst.dev == dev)
> - iter->rt6i_nh_flags |= nh_flags;
> + if (iter->fib6_nh.nh_dev == dev)
> + iter->fib6_nh.nh_flags |= nh_flags;
> }
>
> /* called with write lock held for table with rt */
> @@ -3743,12 +3760,12 @@ static int fib6_ifdown(struct rt6_info *rt, void *p_arg)
>
> switch (arg->event) {
> case NETDEV_UNREGISTER:
> - return rt->dst.dev == dev ? -1 : 0;
> + return rt->fib6_nh.nh_dev == dev ? -1 : 0;
> case NETDEV_DOWN:
> if (rt->should_flush)
> return -1;
> if (!rt->rt6i_nsiblings)
> - return rt->dst.dev == dev ? -1 : 0;
> + return rt->fib6_nh.nh_dev == dev ? -1 : 0;
> if (rt6_multipath_uses_dev(rt, dev)) {
> unsigned int count;
>
> @@ -3764,10 +3781,10 @@ static int fib6_ifdown(struct rt6_info *rt, void *p_arg)
> }
> return -2;
> case NETDEV_CHANGE:
> - if (rt->dst.dev != dev ||
> + if (rt->fib6_nh.nh_dev != dev ||
> rt->rt6i_flags & (RTF_LOCAL | RTF_ANYCAST))
> break;
> - rt->rt6i_nh_flags |= RTNH_F_LINKDOWN;
> + rt->fib6_nh.nh_flags |= RTNH_F_LINKDOWN;
> rt6_multipath_rebalance(rt);
> break;
> }
> @@ -3828,7 +3845,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
> also have the lowest MTU, TOO BIG MESSAGE will be lead to
> PMTU discovery.
> */
> - if (rt->dst.dev == arg->dev &&
> + if (rt->fib6_nh.nh_dev == arg->dev &&
> dst_metric_raw(&rt->dst, RTAX_MTU) &&
> !dst_metric_locked(&rt->dst, RTAX_MTU)) {
> spin_lock_bh(&rt6_exception_lock);
> @@ -4116,7 +4133,7 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
> goto cleanup;
> }
>
> - rt->rt6i_nh_weight = rtnh->rtnh_hops + 1;
> + rt->fib6_nh.nh_weight = rtnh->rtnh_hops + 1;
>
> err = ip6_route_info_append(&rt6_nh_list, rt, &r_cfg);
> if (err) {
> @@ -4273,7 +4290,7 @@ static size_t rt6_nlmsg_size(struct rt6_info *rt)
> nexthop_len = nla_total_size(0) /* RTA_MULTIPATH */
> + NLA_ALIGN(sizeof(struct rtnexthop))
> + nla_total_size(16) /* RTA_GATEWAY */
> - + lwtunnel_get_encap_size(rt->dst.lwtstate);
> + + lwtunnel_get_encap_size(rt->fib6_nh.nh_lwtstate);
>
> nexthop_len *= rt->rt6i_nsiblings;
> }
> @@ -4291,38 +4308,38 @@ static size_t rt6_nlmsg_size(struct rt6_info *rt)
> + nla_total_size(sizeof(struct rta_cacheinfo))
> + nla_total_size(TCP_CA_NAME_MAX) /* RTAX_CC_ALGO */
> + nla_total_size(1) /* RTA_PREF */
> - + lwtunnel_get_encap_size(rt->dst.lwtstate)
> + + lwtunnel_get_encap_size(rt->fib6_nh.nh_lwtstate)
> + nexthop_len;
> }
>
> static int rt6_nexthop_info(struct sk_buff *skb, struct rt6_info *rt,
> unsigned int *flags, bool skip_oif)
> {
> - if (rt->rt6i_nh_flags & RTNH_F_DEAD)
> + if (rt->fib6_nh.nh_flags & RTNH_F_DEAD)
> *flags |= RTNH_F_DEAD;
>
> - if (rt->rt6i_nh_flags & RTNH_F_LINKDOWN) {
> + if (rt->fib6_nh.nh_flags & RTNH_F_LINKDOWN) {
> *flags |= RTNH_F_LINKDOWN;
> if (rt->rt6i_idev->cnf.ignore_routes_with_linkdown)
> *flags |= RTNH_F_DEAD;
> }
>
> if (rt->rt6i_flags & RTF_GATEWAY) {
> - if (nla_put_in6_addr(skb, RTA_GATEWAY, &rt->rt6i_gateway) < 0)
> + if (nla_put_in6_addr(skb, RTA_GATEWAY, &rt->fib6_nh.nh_gw) < 0)
> goto nla_put_failure;
> }
>
> - *flags |= (rt->rt6i_nh_flags & RTNH_F_ONLINK);
> - if (rt->rt6i_nh_flags & RTNH_F_OFFLOAD)
> + *flags |= (rt->fib6_nh.nh_flags & RTNH_F_ONLINK);
> + if (rt->fib6_nh.nh_flags & RTNH_F_OFFLOAD)
> *flags |= RTNH_F_OFFLOAD;
>
> /* not needed for multipath encoding b/c it has a rtnexthop struct */
> - if (!skip_oif && rt->dst.dev &&
> - nla_put_u32(skb, RTA_OIF, rt->dst.dev->ifindex))
> + if (!skip_oif && rt->fib6_nh.nh_dev &&
> + nla_put_u32(skb, RTA_OIF, rt->fib6_nh.nh_dev->ifindex))
> goto nla_put_failure;
>
> - if (rt->dst.lwtstate &&
> - lwtunnel_fill_encap(skb, rt->dst.lwtstate) < 0)
> + if (rt->fib6_nh.nh_lwtstate &&
> + lwtunnel_fill_encap(skb, rt->fib6_nh.nh_lwtstate) < 0)
> goto nla_put_failure;
>
> return 0;
> @@ -4334,6 +4351,7 @@ static int rt6_nexthop_info(struct sk_buff *skb, struct rt6_info *rt,
> /* add multipath next hop */
> static int rt6_add_nexthop(struct sk_buff *skb, struct rt6_info *rt)
> {
> + const struct net_device *dev = rt->fib6_nh.nh_dev;
> struct rtnexthop *rtnh;
> unsigned int flags = 0;
>
> @@ -4341,8 +4359,8 @@ static int rt6_add_nexthop(struct sk_buff *skb, struct rt6_info *rt)
> if (!rtnh)
> goto nla_put_failure;
>
> - rtnh->rtnh_hops = rt->rt6i_nh_weight - 1;
> - rtnh->rtnh_ifindex = rt->dst.dev ? rt->dst.dev->ifindex : 0;
> + rtnh->rtnh_hops = rt->fib6_nh.nh_weight - 1;
> + rtnh->rtnh_ifindex = dev ? dev->ifindex : 0;
>
> if (rt6_nexthop_info(skb, rt, &flags, true) < 0)
> goto nla_put_failure;
> --
> 2.11.0
>
Powered by blists - more mailing lists