Commit 1cf844c7 authored by David Ahern's avatar David Ahern Committed by David S. Miller

ipv6: Make fib6_nh optional at the end of fib6_info

Move fib6_nh to the end of fib6_info and make it an array of
size 0. Pass a flag to fib6_info_alloc indicating if the
allocation needs to add space for a fib6_nh.

The current code path always has a fib6_nh allocated with a
fib6_info; with nexthop objects they will be separate.
Signed-off-by: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cc5c073a
...@@ -2886,7 +2886,7 @@ mlxsw_sp_nexthop6_group_cmp(const struct mlxsw_sp_nexthop_group *nh_grp, ...@@ -2886,7 +2886,7 @@ mlxsw_sp_nexthop6_group_cmp(const struct mlxsw_sp_nexthop_group *nh_grp,
return false; return false;
list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) { list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
struct fib6_nh *fib6_nh = &mlxsw_sp_rt6->rt->fib6_nh; struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
struct in6_addr *gw; struct in6_addr *gw;
int ifindex, weight; int ifindex, weight;
...@@ -2958,7 +2958,7 @@ mlxsw_sp_nexthop6_group_hash(struct mlxsw_sp_fib6_entry *fib6_entry, u32 seed) ...@@ -2958,7 +2958,7 @@ mlxsw_sp_nexthop6_group_hash(struct mlxsw_sp_fib6_entry *fib6_entry, u32 seed)
struct net_device *dev; struct net_device *dev;
list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) { list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
dev = mlxsw_sp_rt6->rt->fib6_nh.fib_nh_dev; dev = mlxsw_sp_rt6->rt->fib6_nh->fib_nh_dev;
val ^= dev->ifindex; val ^= dev->ifindex;
} }
...@@ -3960,9 +3960,9 @@ mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group *nh_grp, ...@@ -3960,9 +3960,9 @@ mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group *nh_grp,
struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i]; struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i];
struct fib6_info *rt = mlxsw_sp_rt6->rt; struct fib6_info *rt = mlxsw_sp_rt6->rt;
if (nh->rif && nh->rif->dev == rt->fib6_nh.fib_nh_dev && if (nh->rif && nh->rif->dev == rt->fib6_nh->fib_nh_dev &&
ipv6_addr_equal((const struct in6_addr *) &nh->gw_addr, ipv6_addr_equal((const struct in6_addr *) &nh->gw_addr,
&rt->fib6_nh.fib_nh_gw6)) &rt->fib6_nh->fib_nh_gw6))
return nh; return nh;
continue; continue;
} }
...@@ -4022,13 +4022,13 @@ mlxsw_sp_fib6_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry) ...@@ -4022,13 +4022,13 @@ mlxsw_sp_fib6_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL || if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL ||
fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE) { fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE) {
list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6, list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6,
list)->rt->fib6_nh.fib_nh_flags |= RTNH_F_OFFLOAD; list)->rt->fib6_nh->fib_nh_flags |= RTNH_F_OFFLOAD;
return; return;
} }
list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) { list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group; struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
struct fib6_nh *fib6_nh = &mlxsw_sp_rt6->rt->fib6_nh; struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
struct mlxsw_sp_nexthop *nh; struct mlxsw_sp_nexthop *nh;
nh = mlxsw_sp_rt6_nexthop(nh_grp, mlxsw_sp_rt6); nh = mlxsw_sp_rt6_nexthop(nh_grp, mlxsw_sp_rt6);
...@@ -4050,7 +4050,7 @@ mlxsw_sp_fib6_entry_offload_unset(struct mlxsw_sp_fib_entry *fib_entry) ...@@ -4050,7 +4050,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) { list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
struct fib6_info *rt = mlxsw_sp_rt6->rt; struct fib6_info *rt = mlxsw_sp_rt6->rt;
rt->fib6_nh.fib_nh_flags &= ~RTNH_F_OFFLOAD; rt->fib6_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
} }
} }
...@@ -4928,7 +4928,8 @@ static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6 *mlxsw_sp_rt6) ...@@ -4928,7 +4928,8 @@ static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
static bool mlxsw_sp_fib6_rt_can_mp(const struct fib6_info *rt) static bool mlxsw_sp_fib6_rt_can_mp(const struct fib6_info *rt)
{ {
/* RTF_CACHE routes are ignored */ /* RTF_CACHE routes are ignored */
return !(rt->fib6_flags & RTF_ADDRCONF) && rt->fib6_nh.fib_nh_gw_family; return !(rt->fib6_flags & RTF_ADDRCONF) &&
rt->fib6_nh->fib_nh_gw_family;
} }
static struct fib6_info * static struct fib6_info *
...@@ -4987,8 +4988,8 @@ static bool mlxsw_sp_nexthop6_ipip_type(const struct mlxsw_sp *mlxsw_sp, ...@@ -4987,8 +4988,8 @@ static bool mlxsw_sp_nexthop6_ipip_type(const struct mlxsw_sp *mlxsw_sp,
const struct fib6_info *rt, const struct fib6_info *rt,
enum mlxsw_sp_ipip_type *ret) enum mlxsw_sp_ipip_type *ret)
{ {
return rt->fib6_nh.fib_nh_dev && return rt->fib6_nh->fib_nh_dev &&
mlxsw_sp_netdev_ipip_type(mlxsw_sp, rt->fib6_nh.fib_nh_dev, ret); mlxsw_sp_netdev_ipip_type(mlxsw_sp, rt->fib6_nh->fib_nh_dev, ret);
} }
static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp *mlxsw_sp,
...@@ -4998,7 +4999,7 @@ static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp *mlxsw_sp, ...@@ -4998,7 +4999,7 @@ static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp *mlxsw_sp,
{ {
const struct mlxsw_sp_ipip_ops *ipip_ops; const struct mlxsw_sp_ipip_ops *ipip_ops;
struct mlxsw_sp_ipip_entry *ipip_entry; struct mlxsw_sp_ipip_entry *ipip_entry;
struct net_device *dev = rt->fib6_nh.fib_nh_dev; struct net_device *dev = rt->fib6_nh->fib_nh_dev;
struct mlxsw_sp_rif *rif; struct mlxsw_sp_rif *rif;
int err; int err;
...@@ -5041,11 +5042,11 @@ static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp, ...@@ -5041,11 +5042,11 @@ static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_nexthop *nh, struct mlxsw_sp_nexthop *nh,
const struct fib6_info *rt) const struct fib6_info *rt)
{ {
struct net_device *dev = rt->fib6_nh.fib_nh_dev; struct net_device *dev = rt->fib6_nh->fib_nh_dev;
nh->nh_grp = nh_grp; nh->nh_grp = nh_grp;
nh->nh_weight = rt->fib6_nh.fib_nh_weight; nh->nh_weight = rt->fib6_nh->fib_nh_weight;
memcpy(&nh->gw_addr, &rt->fib6_nh.fib_nh_gw6, sizeof(nh->gw_addr)); memcpy(&nh->gw_addr, &rt->fib6_nh->fib_nh_gw6, sizeof(nh->gw_addr));
mlxsw_sp_nexthop_counter_alloc(mlxsw_sp, nh); mlxsw_sp_nexthop_counter_alloc(mlxsw_sp, nh);
list_add_tail(&nh->router_list_node, &mlxsw_sp->router->nexthop_list); list_add_tail(&nh->router_list_node, &mlxsw_sp->router->nexthop_list);
...@@ -5068,7 +5069,7 @@ static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp *mlxsw_sp, ...@@ -5068,7 +5069,7 @@ static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp *mlxsw_sp,
static bool mlxsw_sp_rt6_is_gateway(const struct mlxsw_sp *mlxsw_sp, static bool mlxsw_sp_rt6_is_gateway(const struct mlxsw_sp *mlxsw_sp,
const struct fib6_info *rt) const struct fib6_info *rt)
{ {
return rt->fib6_nh.fib_nh_gw_family || return rt->fib6_nh->fib_nh_gw_family ||
mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, NULL); mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, NULL);
} }
......
...@@ -169,8 +169,8 @@ struct fib6_info { ...@@ -169,8 +169,8 @@ struct fib6_info {
fib6_destroying:1, fib6_destroying:1,
unused:3; unused:3;
struct fib6_nh fib6_nh;
struct rcu_head rcu; struct rcu_head rcu;
struct fib6_nh fib6_nh[0];
}; };
struct rt6_info { struct rt6_info {
...@@ -280,7 +280,7 @@ static inline void ip6_rt_put(struct rt6_info *rt) ...@@ -280,7 +280,7 @@ static inline void ip6_rt_put(struct rt6_info *rt)
dst_release(&rt->dst); dst_release(&rt->dst);
} }
struct fib6_info *fib6_info_alloc(gfp_t gfp_flags); struct fib6_info *fib6_info_alloc(gfp_t gfp_flags, bool with_fib6_nh);
void fib6_info_destroy_rcu(struct rcu_head *head); void fib6_info_destroy_rcu(struct rcu_head *head);
static inline void fib6_info_hold(struct fib6_info *f6i) static inline void fib6_info_hold(struct fib6_info *f6i)
...@@ -443,7 +443,7 @@ void rt6_get_prefsrc(const struct rt6_info *rt, struct in6_addr *addr) ...@@ -443,7 +443,7 @@ void rt6_get_prefsrc(const struct rt6_info *rt, struct in6_addr *addr)
static inline struct net_device *fib6_info_nh_dev(const struct fib6_info *f6i) static inline struct net_device *fib6_info_nh_dev(const struct fib6_info *f6i)
{ {
return f6i->fib6_nh.fib_nh_dev; return f6i->fib6_nh->fib_nh_dev;
} }
int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh, int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
......
...@@ -70,7 +70,7 @@ static inline bool rt6_qualify_for_ecmp(const struct fib6_info *f6i) ...@@ -70,7 +70,7 @@ static inline bool rt6_qualify_for_ecmp(const struct fib6_info *f6i)
{ {
/* the RTF_ADDRCONF flag filters out RA's */ /* the RTF_ADDRCONF flag filters out RA's */
return !(f6i->fib6_flags & RTF_ADDRCONF) && return !(f6i->fib6_flags & RTF_ADDRCONF) &&
f6i->fib6_nh.fib_nh_gw_family; f6i->fib6_nh->fib_nh_gw_family;
} }
void ip6_route_input(struct sk_buff *skb); void ip6_route_input(struct sk_buff *skb);
...@@ -275,7 +275,7 @@ static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt, ...@@ -275,7 +275,7 @@ static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt,
static inline bool rt6_duplicate_nexthop(struct fib6_info *a, struct fib6_info *b) static inline bool rt6_duplicate_nexthop(struct fib6_info *a, struct fib6_info *b)
{ {
struct fib6_nh *nha = &a->fib6_nh, *nhb = &b->fib6_nh; struct fib6_nh *nha = a->fib6_nh, *nhb = b->fib6_nh;
return nha->fib_nh_dev == nhb->fib_nh_dev && return nha->fib_nh_dev == nhb->fib_nh_dev &&
ipv6_addr_equal(&nha->fib_nh_gw6, &nhb->fib_nh_gw6) && ipv6_addr_equal(&nha->fib_nh_gw6, &nhb->fib_nh_gw6) &&
......
...@@ -2421,9 +2421,9 @@ static struct fib6_info *addrconf_get_prefix_route(const struct in6_addr *pfx, ...@@ -2421,9 +2421,9 @@ static struct fib6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
goto out; goto out;
for_each_fib6_node_rt_rcu(fn) { for_each_fib6_node_rt_rcu(fn) {
if (rt->fib6_nh.fib_nh_dev->ifindex != dev->ifindex) if (rt->fib6_nh->fib_nh_dev->ifindex != dev->ifindex)
continue; continue;
if (no_gw && rt->fib6_nh.fib_nh_gw_family) if (no_gw && rt->fib6_nh->fib_nh_gw_family)
continue; continue;
if ((rt->fib6_flags & flags) != flags) if ((rt->fib6_flags & flags) != flags)
continue; continue;
...@@ -6341,7 +6341,7 @@ void addrconf_disable_policy_idev(struct inet6_dev *idev, int val) ...@@ -6341,7 +6341,7 @@ void addrconf_disable_policy_idev(struct inet6_dev *idev, int val)
list_for_each_entry(ifa, &idev->addr_list, if_list) { list_for_each_entry(ifa, &idev->addr_list, if_list) {
spin_lock(&ifa->lock); spin_lock(&ifa->lock);
if (ifa->rt) { if (ifa->rt) {
struct fib6_nh *nh = &ifa->rt->fib6_nh; struct fib6_nh *nh = ifa->rt->fib6_nh;
int cpu; int cpu;
rcu_read_lock(); rcu_read_lock();
......
...@@ -147,11 +147,15 @@ static __be32 addr_bit_set(const void *token, int fn_bit) ...@@ -147,11 +147,15 @@ static __be32 addr_bit_set(const void *token, int fn_bit)
addr[fn_bit >> 5]; addr[fn_bit >> 5];
} }
struct fib6_info *fib6_info_alloc(gfp_t gfp_flags) struct fib6_info *fib6_info_alloc(gfp_t gfp_flags, bool with_fib6_nh)
{ {
struct fib6_info *f6i; struct fib6_info *f6i;
size_t sz = sizeof(*f6i);
f6i = kzalloc(sizeof(*f6i), gfp_flags); if (with_fib6_nh)
sz += sizeof(struct fib6_nh);
f6i = kzalloc(sz, gfp_flags);
if (!f6i) if (!f6i)
return NULL; return NULL;
...@@ -167,7 +171,7 @@ void fib6_info_destroy_rcu(struct rcu_head *head) ...@@ -167,7 +171,7 @@ void fib6_info_destroy_rcu(struct rcu_head *head)
WARN_ON(f6i->fib6_node); WARN_ON(f6i->fib6_node);
fib6_nh_release(&f6i->fib6_nh); fib6_nh_release(f6i->fib6_nh);
ip_fib_metrics_put(f6i->fib6_metrics); ip_fib_metrics_put(f6i->fib6_metrics);
kfree(f6i); kfree(f6i);
} }
...@@ -912,7 +916,7 @@ static void fib6_drop_pcpu_from(struct fib6_info *f6i, ...@@ -912,7 +916,7 @@ static void fib6_drop_pcpu_from(struct fib6_info *f6i,
f6i->fib6_destroying = 1; f6i->fib6_destroying = 1;
mb(); /* paired with the cmpxchg() in rt6_make_pcpu_route() */ mb(); /* paired with the cmpxchg() in rt6_make_pcpu_route() */
fib6_nh = &f6i->fib6_nh; fib6_nh = f6i->fib6_nh;
__fib6_drop_pcpu_from(fib6_nh, f6i, table); __fib6_drop_pcpu_from(fib6_nh, f6i, table);
} }
...@@ -2301,14 +2305,14 @@ static int ipv6_route_seq_show(struct seq_file *seq, void *v) ...@@ -2301,14 +2305,14 @@ static int ipv6_route_seq_show(struct seq_file *seq, void *v)
#else #else
seq_puts(seq, "00000000000000000000000000000000 00 "); seq_puts(seq, "00000000000000000000000000000000 00 ");
#endif #endif
if (rt->fib6_nh.fib_nh_gw_family) { if (rt->fib6_nh->fib_nh_gw_family) {
flags |= RTF_GATEWAY; flags |= RTF_GATEWAY;
seq_printf(seq, "%pi6", &rt->fib6_nh.fib_nh_gw6); seq_printf(seq, "%pi6", &rt->fib6_nh->fib_nh_gw6);
} else { } else {
seq_puts(seq, "00000000000000000000000000000000"); seq_puts(seq, "00000000000000000000000000000000");
} }
dev = rt->fib6_nh.fib_nh_dev; dev = rt->fib6_nh->fib_nh_dev;
seq_printf(seq, " %08x %08x %08x %08x %8s\n", seq_printf(seq, " %08x %08x %08x %08x %8s\n",
rt->fib6_metric, refcount_read(&rt->fib6_ref), 0, rt->fib6_metric, refcount_read(&rt->fib6_ref), 0,
flags, dev ? dev->name : ""); flags, dev ? dev->name : "");
......
...@@ -1293,8 +1293,8 @@ static void ndisc_router_discovery(struct sk_buff *skb) ...@@ -1293,8 +1293,8 @@ static void ndisc_router_discovery(struct sk_buff *skb)
rt = rt6_get_dflt_router(net, &ipv6_hdr(skb)->saddr, skb->dev); rt = rt6_get_dflt_router(net, &ipv6_hdr(skb)->saddr, skb->dev);
if (rt) { if (rt) {
neigh = ip6_neigh_lookup(&rt->fib6_nh.fib_nh_gw6, neigh = ip6_neigh_lookup(&rt->fib6_nh->fib_nh_gw6,
rt->fib6_nh.fib_nh_dev, NULL, rt->fib6_nh->fib_nh_dev, NULL,
&ipv6_hdr(skb)->saddr); &ipv6_hdr(skb)->saddr);
if (!neigh) { if (!neigh) {
ND_PRINTK(0, err, ND_PRINTK(0, err,
...@@ -1323,8 +1323,8 @@ static void ndisc_router_discovery(struct sk_buff *skb) ...@@ -1323,8 +1323,8 @@ static void ndisc_router_discovery(struct sk_buff *skb)
return; return;
} }
neigh = ip6_neigh_lookup(&rt->fib6_nh.fib_nh_gw6, neigh = ip6_neigh_lookup(&rt->fib6_nh->fib_nh_gw6,
rt->fib6_nh.fib_nh_dev, NULL, rt->fib6_nh->fib_nh_dev, NULL,
&ipv6_hdr(skb)->saddr); &ipv6_hdr(skb)->saddr);
if (!neigh) { if (!neigh) {
ND_PRINTK(0, err, ND_PRINTK(0, err,
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment