提交 3f4fe759 编写于 作者: D David S. Miller

Merge branch 'ipv6-followup-to-fib6_info-change'

David Ahern says:

====================
net/ipv6: followup to fib6_info change

Followup to fib change for IPv6.

First 2 patches rename fib6_info struct elements to match its name,
and rename addrconf_dst_alloc to match what it returns.

Patches 3-7 refactor the code to remove the need for fib6_idev reducing
fib6_info by another 8 bytes to 200 bytes.

Patch 8 fixes the gfp flags argument to addrconf_prefix_route in a
couple of places.
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
......@@ -4705,17 +4705,17 @@ static bool mlxsw_sp_fib6_rt_should_ignore(const struct fib6_info *rt)
* are trapped to the CPU, so no need to program specific routes
* for them.
*/
if (ipv6_addr_type(&rt->rt6i_dst.addr) & IPV6_ADDR_LINKLOCAL)
if (ipv6_addr_type(&rt->fib6_dst.addr) & IPV6_ADDR_LINKLOCAL)
return true;
/* Multicast routes aren't supported, so ignore them. Neighbour
* Discovery packets are specifically trapped.
*/
if (ipv6_addr_type(&rt->rt6i_dst.addr) & IPV6_ADDR_MULTICAST)
if (ipv6_addr_type(&rt->fib6_dst.addr) & IPV6_ADDR_MULTICAST)
return true;
/* Cloned routes are irrelevant in the forwarding path. */
if (rt->rt6i_flags & RTF_CACHE)
if (rt->fib6_flags & RTF_CACHE)
return true;
return false;
......@@ -4759,7 +4759,7 @@ 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)
{
/* RTF_CACHE routes are ignored */
return (rt->rt6i_flags & (RTF_GATEWAY | RTF_ADDRCONF)) == RTF_GATEWAY;
return (rt->fib6_flags & (RTF_GATEWAY | RTF_ADDRCONF)) == RTF_GATEWAY;
}
static struct fib6_info *
......@@ -4784,16 +4784,16 @@ mlxsw_sp_fib6_node_mp_entry_find(const struct mlxsw_sp_fib_node *fib_node,
/* RT6_TABLE_LOCAL and RT6_TABLE_MAIN share the same
* virtual router.
*/
if (rt->rt6i_table->tb6_id > nrt->rt6i_table->tb6_id)
if (rt->fib6_table->tb6_id > nrt->fib6_table->tb6_id)
continue;
if (rt->rt6i_table->tb6_id != nrt->rt6i_table->tb6_id)
if (rt->fib6_table->tb6_id != nrt->fib6_table->tb6_id)
break;
if (rt->rt6i_metric < nrt->rt6i_metric)
if (rt->fib6_metric < nrt->fib6_metric)
continue;
if (rt->rt6i_metric == nrt->rt6i_metric &&
if (rt->fib6_metric == nrt->fib6_metric &&
mlxsw_sp_fib6_rt_can_mp(rt))
return fib6_entry;
if (rt->rt6i_metric > nrt->rt6i_metric)
if (rt->fib6_metric > nrt->fib6_metric)
break;
}
......@@ -4899,7 +4899,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,
const struct fib6_info *rt)
{
return rt->rt6i_flags & RTF_GATEWAY ||
return rt->fib6_flags & RTF_GATEWAY ||
mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, NULL);
}
......@@ -5092,9 +5092,9 @@ static void mlxsw_sp_fib6_entry_type_set(struct mlxsw_sp *mlxsw_sp,
* local, which will cause them to be trapped with a lower
* priority than packets that need to be locally received.
*/
if (rt->rt6i_flags & (RTF_LOCAL | RTF_ANYCAST))
if (rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST))
fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
else if (rt->rt6i_flags & RTF_REJECT)
else if (rt->fib6_flags & RTF_REJECT)
fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
else if (mlxsw_sp_rt6_is_gateway(mlxsw_sp, rt))
fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_REMOTE;
......@@ -5175,18 +5175,18 @@ mlxsw_sp_fib6_node_entry_find(const struct mlxsw_sp_fib_node *fib_node,
list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
struct fib6_info *rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
if (rt->rt6i_table->tb6_id > nrt->rt6i_table->tb6_id)
if (rt->fib6_table->tb6_id > nrt->fib6_table->tb6_id)
continue;
if (rt->rt6i_table->tb6_id != nrt->rt6i_table->tb6_id)
if (rt->fib6_table->tb6_id != nrt->fib6_table->tb6_id)
break;
if (replace && rt->rt6i_metric == nrt->rt6i_metric) {
if (replace && rt->fib6_metric == nrt->fib6_metric) {
if (mlxsw_sp_fib6_rt_can_mp(rt) ==
mlxsw_sp_fib6_rt_can_mp(nrt))
return fib6_entry;
if (mlxsw_sp_fib6_rt_can_mp(nrt))
fallback = fallback ?: fib6_entry;
}
if (rt->rt6i_metric > nrt->rt6i_metric)
if (rt->fib6_metric > nrt->fib6_metric)
return fallback ?: fib6_entry;
}
......@@ -5215,7 +5215,7 @@ mlxsw_sp_fib6_node_list_insert(struct mlxsw_sp_fib6_entry *new6_entry,
list_for_each_entry(last, &fib_node->entry_list, common.list) {
struct fib6_info *rt = mlxsw_sp_fib6_entry_rt(last);
if (nrt->rt6i_table->tb6_id > rt->rt6i_table->tb6_id)
if (nrt->fib6_table->tb6_id > rt->fib6_table->tb6_id)
break;
fib6_entry = last;
}
......@@ -5275,22 +5275,22 @@ mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib *fib;
struct mlxsw_sp_vr *vr;
vr = mlxsw_sp_vr_find(mlxsw_sp, rt->rt6i_table->tb6_id);
vr = mlxsw_sp_vr_find(mlxsw_sp, rt->fib6_table->tb6_id);
if (!vr)
return NULL;
fib = mlxsw_sp_vr_fib(vr, MLXSW_SP_L3_PROTO_IPV6);
fib_node = mlxsw_sp_fib_node_lookup(fib, &rt->rt6i_dst.addr,
sizeof(rt->rt6i_dst.addr),
rt->rt6i_dst.plen);
fib_node = mlxsw_sp_fib_node_lookup(fib, &rt->fib6_dst.addr,
sizeof(rt->fib6_dst.addr),
rt->fib6_dst.plen);
if (!fib_node)
return NULL;
list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
struct fib6_info *iter_rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
if (rt->rt6i_table->tb6_id == iter_rt->rt6i_table->tb6_id &&
rt->rt6i_metric == iter_rt->rt6i_metric &&
if (rt->fib6_table->tb6_id == iter_rt->fib6_table->tb6_id &&
rt->fib6_metric == iter_rt->fib6_metric &&
mlxsw_sp_fib6_entry_rt_find(fib6_entry, rt))
return fib6_entry;
}
......@@ -5325,16 +5325,16 @@ static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
if (mlxsw_sp->router->aborted)
return 0;
if (rt->rt6i_src.plen)
if (rt->fib6_src.plen)
return -EINVAL;
if (mlxsw_sp_fib6_rt_should_ignore(rt))
return 0;
fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, rt->rt6i_table->tb6_id,
&rt->rt6i_dst.addr,
sizeof(rt->rt6i_dst.addr),
rt->rt6i_dst.plen,
fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, rt->fib6_table->tb6_id,
&rt->fib6_dst.addr,
sizeof(rt->fib6_dst.addr),
rt->fib6_dst.plen,
MLXSW_SP_L3_PROTO_IPV6);
if (IS_ERR(fib_node))
return PTR_ERR(fib_node);
......
......@@ -143,7 +143,6 @@ struct ipv6_ac_socklist {
struct ifacaddr6 {
struct in6_addr aca_addr;
struct inet6_dev *aca_idev;
struct fib6_info *aca_rt;
struct ifacaddr6 *aca_next;
int aca_users;
......
......@@ -134,34 +134,33 @@ struct fib6_nh {
};
struct fib6_info {
struct fib6_table *rt6i_table;
struct fib6_table *fib6_table;
struct fib6_info __rcu *rt6_next;
struct fib6_node __rcu *rt6i_node;
struct fib6_node __rcu *fib6_node;
/* Multipath routes:
* siblings is a list of fib6_info that have the the same metric/weight,
* destination, but not the same gateway. nsiblings is just a cache
* to speed up lookup.
*/
struct list_head rt6i_siblings;
unsigned int rt6i_nsiblings;
struct list_head fib6_siblings;
unsigned int fib6_nsiblings;
atomic_t rt6i_ref;
struct inet6_dev *rt6i_idev;
atomic_t fib6_ref;
unsigned long expires;
struct dst_metrics *fib6_metrics;
#define fib6_pmtu fib6_metrics->metrics[RTAX_MTU-1]
struct rt6key rt6i_dst;
u32 rt6i_flags;
struct rt6key rt6i_src;
struct rt6key rt6i_prefsrc;
struct rt6key fib6_dst;
u32 fib6_flags;
struct rt6key fib6_src;
struct rt6key fib6_prefsrc;
struct rt6_info * __percpu *rt6i_pcpu;
struct rt6_exception_bucket __rcu *rt6i_exception_bucket;
u32 rt6i_metric;
u8 rt6i_protocol;
u32 fib6_metric;
u8 fib6_protocol;
u8 fib6_type;
u8 exception_bucket_flushed:1,
should_flush:1,
......@@ -206,7 +205,7 @@ static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst)
static inline void fib6_clean_expires(struct fib6_info *f6i)
{
f6i->rt6i_flags &= ~RTF_EXPIRES;
f6i->fib6_flags &= ~RTF_EXPIRES;
f6i->expires = 0;
}
......@@ -214,12 +213,12 @@ static inline void fib6_set_expires(struct fib6_info *f6i,
unsigned long expires)
{
f6i->expires = expires;
f6i->rt6i_flags |= RTF_EXPIRES;
f6i->fib6_flags |= RTF_EXPIRES;
}
static inline bool fib6_check_expired(const struct fib6_info *f6i)
{
if (f6i->rt6i_flags & RTF_EXPIRES)
if (f6i->fib6_flags & RTF_EXPIRES)
return time_after(jiffies, f6i->expires);
return false;
}
......@@ -250,14 +249,14 @@ static inline void rt6_update_expires(struct rt6_info *rt0, int timeout)
* Return true if we can get cookie safely
* Return false if not
*/
static inline bool rt6_get_cookie_safe(const struct fib6_info *rt,
static inline bool rt6_get_cookie_safe(const struct fib6_info *f6i,
u32 *cookie)
{
struct fib6_node *fn;
bool status = false;
rcu_read_lock();
fn = rcu_dereference(rt->rt6i_node);
fn = rcu_dereference(f6i->fib6_node);
if (fn) {
*cookie = fn->fn_sernum;
......@@ -295,12 +294,12 @@ void fib6_info_destroy(struct fib6_info *f6i);
static inline void fib6_info_hold(struct fib6_info *f6i)
{
atomic_inc(&f6i->rt6i_ref);
atomic_inc(&f6i->fib6_ref);
}
static inline void fib6_info_release(struct fib6_info *f6i)
{
if (f6i && atomic_dec_and_test(&f6i->rt6i_ref))
if (f6i && atomic_dec_and_test(&f6i->fib6_ref))
fib6_info_destroy(f6i);
}
......@@ -410,6 +409,11 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt,
struct nl_info *info, struct netlink_ext_ack *extack);
int fib6_del(struct fib6_info *rt, struct nl_info *info);
static inline struct net_device *fib6_info_nh_dev(const struct fib6_info *f6i)
{
return f6i->fib6_nh.nh_dev;
}
void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info,
unsigned int flags);
......
......@@ -66,9 +66,9 @@ static inline bool rt6_need_strict(const struct in6_addr *daddr)
(IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK);
}
static inline bool rt6_qualify_for_ecmp(const struct fib6_info *rt)
static inline bool rt6_qualify_for_ecmp(const struct fib6_info *f6i)
{
return (rt->rt6i_flags & (RTF_GATEWAY|RTF_ADDRCONF|RTF_DYNAMIC)) ==
return (f6i->fib6_flags & (RTF_GATEWAY|RTF_ADDRCONF|RTF_DYNAMIC)) ==
RTF_GATEWAY;
}
......@@ -102,26 +102,27 @@ int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg);
int ip6_route_add(struct fib6_config *cfg, gfp_t gfp_flags,
struct netlink_ext_ack *extack);
int ip6_ins_rt(struct net *net, struct fib6_info *rt);
int ip6_del_rt(struct net *net, struct fib6_info *rt);
int ip6_ins_rt(struct net *net, struct fib6_info *f6i);
int ip6_del_rt(struct net *net, struct fib6_info *f6i);
void rt6_flush_exceptions(struct fib6_info *rt);
void rt6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args,
void rt6_flush_exceptions(struct fib6_info *f6i);
void rt6_age_exceptions(struct fib6_info *f6i, struct fib6_gc_args *gc_args,
unsigned long now);
static inline int ip6_route_get_saddr(struct net *net, struct fib6_info *rt,
static inline int ip6_route_get_saddr(struct net *net, struct fib6_info *f6i,
const struct in6_addr *daddr,
unsigned int prefs,
struct in6_addr *saddr)
{
struct inet6_dev *idev = rt ? rt->rt6i_idev : NULL;
int err = 0;
if (rt && rt->rt6i_prefsrc.plen)
*saddr = rt->rt6i_prefsrc.addr;
else
err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL,
daddr, prefs, saddr);
if (f6i && f6i->fib6_prefsrc.plen) {
*saddr = f6i->fib6_prefsrc.addr;
} else {
struct net_device *dev = f6i ? fib6_info_nh_dev(f6i) : NULL;
err = ipv6_dev_get_saddr(net, dev, daddr, prefs, saddr);
}
return err;
}
......@@ -136,7 +137,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, struct flowi6 *fl6);
void fib6_force_start_gc(struct net *net);
struct fib6_info *addrconf_dst_alloc(struct net *net, struct inet6_dev *idev,
struct fib6_info *addrconf_f6i_alloc(struct net *net, struct inet6_dev *idev,
const struct in6_addr *addr, bool anycast,
gfp_t gfp_flags);
......@@ -176,14 +177,14 @@ struct rt6_rtnl_dump_arg {
struct net *net;
};
int rt6_dump_route(struct fib6_info *rt, void *p_arg);
int rt6_dump_route(struct fib6_info *f6i, void *p_arg);
void rt6_mtu_change(struct net_device *dev, unsigned int mtu);
void rt6_remove_prefsrc(struct inet6_ifaddr *ifp);
void rt6_clean_tohost(struct net *net, struct in6_addr *gateway);
void rt6_sync_up(struct net_device *dev, unsigned int nh_flags);
void rt6_disable_ip(struct net_device *dev, unsigned long event);
void rt6_sync_down_dev(struct net_device *dev, unsigned long event);
void rt6_multipath_rebalance(struct fib6_info *rt);
void rt6_multipath_rebalance(struct fib6_info *f6i);
void rt6_uncached_list_add(struct rt6_info *rt);
void rt6_uncached_list_del(struct rt6_info *rt);
......@@ -274,7 +275,6 @@ 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)
{
return a->fib6_nh.nh_dev == b->fib6_nh.nh_dev &&
a->rt6i_idev == b->rt6i_idev &&
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);
}
......
......@@ -994,7 +994,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
gfp_t gfp_flags = can_block ? GFP_KERNEL : GFP_ATOMIC;
struct net *net = dev_net(idev->dev);
struct inet6_ifaddr *ifa = NULL;
struct fib6_info *rt = NULL;
struct fib6_info *f6i = NULL;
int err = 0;
int addr_type = ipv6_addr_type(addr);
......@@ -1036,16 +1036,16 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
goto out;
}
rt = addrconf_dst_alloc(net, idev, addr, false, gfp_flags);
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
rt = NULL;
f6i = addrconf_f6i_alloc(net, idev, addr, false, gfp_flags);
if (IS_ERR(f6i)) {
err = PTR_ERR(f6i);
f6i = NULL;
goto out;
}
if (net->ipv6.devconf_all->disable_policy ||
idev->cnf.disable_policy)
rt->dst_nopolicy = true;
f6i->dst_nopolicy = true;
neigh_parms_data_state_setall(idev->nd_parms);
......@@ -1067,7 +1067,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
ifa->cstamp = ifa->tstamp = jiffies;
ifa->tokenized = false;
ifa->rt = rt;
ifa->rt = f6i;
ifa->idev = idev;
in6_dev_hold(idev);
......@@ -1101,7 +1101,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
inet6addr_notifier_call_chain(NETDEV_UP, ifa);
out:
if (unlikely(err < 0)) {
fib6_info_release(rt);
fib6_info_release(f6i);
if (ifa) {
if (ifa->idev)
......@@ -1178,19 +1178,19 @@ check_cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long *expires)
static void
cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long expires, bool del_rt)
{
struct fib6_info *rt;
struct fib6_info *f6i;
rt = addrconf_get_prefix_route(&ifp->addr,
f6i = addrconf_get_prefix_route(&ifp->addr,
ifp->prefix_len,
ifp->idev->dev,
0, RTF_GATEWAY | RTF_DEFAULT);
if (rt) {
if (f6i) {
if (del_rt)
ip6_del_rt(dev_net(ifp->idev->dev), rt);
ip6_del_rt(dev_net(ifp->idev->dev), f6i);
else {
if (!(rt->rt6i_flags & RTF_EXPIRES))
fib6_set_expires(rt, expires);
fib6_info_release(rt);
if (!(f6i->fib6_flags & RTF_EXPIRES))
fib6_set_expires(f6i, expires);
fib6_info_release(f6i);
}
}
}
......@@ -2370,9 +2370,9 @@ static struct fib6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
for_each_fib6_node_rt_rcu(fn) {
if (rt->fib6_nh.nh_dev->ifindex != dev->ifindex)
continue;
if ((rt->rt6i_flags & flags) != flags)
if ((rt->fib6_flags & flags) != flags)
continue;
if ((rt->rt6i_flags & noflags) != 0)
if ((rt->fib6_flags & noflags) != 0)
continue;
fib6_info_hold(rt);
break;
......@@ -3245,7 +3245,7 @@ static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route)
addrconf_add_linklocal(idev, &addr, 0);
else if (prefix_route)
addrconf_prefix_route(&addr, 64, idev->dev,
0, 0, GFP_ATOMIC);
0, 0, GFP_KERNEL);
break;
case IN6_ADDR_GEN_MODE_NONE:
default:
......@@ -3341,22 +3341,22 @@ static int fixup_permanent_addr(struct net *net,
struct inet6_dev *idev,
struct inet6_ifaddr *ifp)
{
/* !rt6i_node means the host route was removed from the
/* !fib6_node means the host route was removed from the
* FIB, for example, if 'lo' device is taken down. In that
* case regenerate the host route.
*/
if (!ifp->rt || !ifp->rt->rt6i_node) {
struct fib6_info *rt, *prev;
if (!ifp->rt || !ifp->rt->fib6_node) {
struct fib6_info *f6i, *prev;
rt = addrconf_dst_alloc(net, idev, &ifp->addr, false,
GFP_ATOMIC);
if (IS_ERR(rt))
return PTR_ERR(rt);
f6i = addrconf_f6i_alloc(net, idev, &ifp->addr, false,
GFP_ATOMIC);
if (IS_ERR(f6i))
return PTR_ERR(f6i);
/* ifp->rt can be accessed outside of rtnl */
spin_lock(&ifp->lock);
prev = ifp->rt;
ifp->rt = rt;
ifp->rt = f6i;
spin_unlock(&ifp->lock);
fib6_info_release(prev);
......@@ -4817,9 +4817,10 @@ static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
u32 portid, u32 seq, int event, unsigned int flags)
{
struct net_device *dev = fib6_info_nh_dev(ifaca->aca_rt);
int ifindex = dev ? dev->ifindex : 1;
struct nlmsghdr *nlh;
u8 scope = RT_SCOPE_UNIVERSE;
int ifindex = ifaca->aca_idev->dev->ifindex;
if (ipv6_addr_scope(&ifaca->aca_addr) & IFA_SITE)
scope = RT_SCOPE_SITE;
......@@ -5612,14 +5613,14 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
* our DAD process, so we don't need
* to do it again
*/
if (!rcu_access_pointer(ifp->rt->rt6i_node))
if (!rcu_access_pointer(ifp->rt->fib6_node))
ip6_ins_rt(net, ifp->rt);
if (ifp->idev->cnf.forwarding)
addrconf_join_anycast(ifp);
if (!ipv6_addr_any(&ifp->peer_addr))
addrconf_prefix_route(&ifp->peer_addr, 128,
ifp->idev->dev, 0, 0,
GFP_KERNEL);
GFP_ATOMIC);
break;
case RTM_DELADDR:
if (ifp->idev->cnf.forwarding)
......
......@@ -212,16 +212,14 @@ static void aca_get(struct ifacaddr6 *aca)
static void aca_put(struct ifacaddr6 *ac)
{
if (refcount_dec_and_test(&ac->aca_refcnt)) {
in6_dev_put(ac->aca_idev);
fib6_info_release(ac->aca_rt);
kfree(ac);
}
}
static struct ifacaddr6 *aca_alloc(struct fib6_info *rt,
static struct ifacaddr6 *aca_alloc(struct fib6_info *f6i,
const struct in6_addr *addr)
{
struct inet6_dev *idev = rt->rt6i_idev;
struct ifacaddr6 *aca;
aca = kzalloc(sizeof(*aca), GFP_ATOMIC);
......@@ -229,10 +227,8 @@ static struct ifacaddr6 *aca_alloc(struct fib6_info *rt,
return NULL;
aca->aca_addr = *addr;
in6_dev_hold(idev);
aca->aca_idev = idev;
fib6_info_hold(rt);
aca->aca_rt = rt;
fib6_info_hold(f6i);
aca->aca_rt = f6i;
aca->aca_users = 1;
/* aca_tstamp should be updated upon changes */
aca->aca_cstamp = aca->aca_tstamp = jiffies;
......@@ -247,7 +243,7 @@ static struct ifacaddr6 *aca_alloc(struct fib6_info *rt,
int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr)
{
struct ifacaddr6 *aca;
struct fib6_info *rt;
struct fib6_info *f6i;
struct net *net;
int err;
......@@ -268,14 +264,14 @@ int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr)
}
net = dev_net(idev->dev);
rt = addrconf_dst_alloc(net, idev, addr, true, GFP_ATOMIC);
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
f6i = addrconf_f6i_alloc(net, idev, addr, true, GFP_ATOMIC);
if (IS_ERR(f6i)) {
err = PTR_ERR(f6i);
goto out;
}
aca = aca_alloc(rt, addr);
aca = aca_alloc(f6i, addr);
if (!aca) {
fib6_info_release(rt);
fib6_info_release(f6i);
err = -ENOMEM;
goto out;
}
......@@ -289,7 +285,7 @@ int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr)
aca_get(aca);
write_unlock_bh(&idev->lock);
ip6_ins_rt(net, rt);
ip6_ins_rt(net, f6i);
addrconf_join_solict(idev->dev, &aca->aca_addr);
......
......@@ -105,12 +105,12 @@ enum {
FIB6_NO_SERNUM_CHANGE = 0,
};
void fib6_update_sernum(struct net *net, struct fib6_info *rt)
void fib6_update_sernum(struct net *net, struct fib6_info *f6i)
{
struct fib6_node *fn;
fn = rcu_dereference_protected(rt->rt6i_node,
lockdep_is_held(&rt->rt6i_table->tb6_lock));
fn = rcu_dereference_protected(f6i->fib6_node,
lockdep_is_held(&f6i->fib6_table->tb6_lock));
if (fn)
fn->fn_sernum = fib6_new_sernum(net);
}
......@@ -159,10 +159,10 @@ struct fib6_info *fib6_info_alloc(gfp_t gfp_flags)
return NULL;
}
INIT_LIST_HEAD(&f6i->rt6i_siblings);
INIT_LIST_HEAD(&f6i->fib6_siblings);
f6i->fib6_metrics = (struct dst_metrics *)&dst_default_metrics;
atomic_inc(&f6i->rt6i_ref);
atomic_inc(&f6i->fib6_ref);
return f6i;
}
......@@ -172,7 +172,7 @@ void fib6_info_destroy(struct fib6_info *f6i)
struct rt6_exception_bucket *bucket;
struct dst_metrics *m;
WARN_ON(f6i->rt6i_node);
WARN_ON(f6i->fib6_node);
bucket = rcu_dereference_protected(f6i->rt6i_exception_bucket, 1);
if (bucket) {
......@@ -197,8 +197,6 @@ void fib6_info_destroy(struct fib6_info *f6i)
}
}
if (f6i->rt6i_idev)
in6_dev_put(f6i->rt6i_idev);
if (f6i->fib6_nh.nh_dev)
dev_put(f6i->fib6_nh.nh_dev);
......@@ -401,7 +399,7 @@ static int call_fib6_entry_notifiers(struct net *net,
.rt = rt,
};
rt->rt6i_table->fib_seq++;
rt->fib6_table->fib_seq++;
return call_fib6_notifiers(net, event_type, &info.info);
}
......@@ -483,10 +481,10 @@ static int fib6_dump_node(struct fib6_walker *w)
* last sibling of this route (no need to dump the
* sibling routes again)
*/
if (rt->rt6i_nsiblings)
rt = list_last_entry(&rt->rt6i_siblings,
if (rt->fib6_nsiblings)
rt = list_last_entry(&rt->fib6_siblings,
struct fib6_info,
rt6i_siblings);
fib6_siblings);
}
w->leaf = NULL;
return 0;
......@@ -810,7 +808,7 @@ static struct fib6_node *fib6_add_1(struct net *net,
RCU_INIT_POINTER(in->parent, pn);
in->leaf = fn->leaf;
atomic_inc(&rcu_dereference_protected(in->leaf,
lockdep_is_held(&table->tb6_lock))->rt6i_ref);
lockdep_is_held(&table->tb6_lock))->fib6_ref);
/* update parent pointer */
if (dir)
......@@ -865,9 +863,9 @@ static struct fib6_node *fib6_add_1(struct net *net,
static void fib6_purge_rt(struct fib6_info *rt, struct fib6_node *fn,
struct net *net)
{
struct fib6_table *table = rt->rt6i_table;
struct fib6_table *table = rt->fib6_table;
if (atomic_read(&rt->rt6i_ref) != 1) {
if (atomic_read(&rt->fib6_ref) != 1) {
/* This route is used as dummy address holder in some split
* nodes. It is not leaked, but it still holds other resources,
* which must be released in time. So, scan ascendant nodes
......@@ -880,7 +878,7 @@ static void fib6_purge_rt(struct fib6_info *rt, struct fib6_node *fn,
struct fib6_info *new_leaf;
if (!(fn->fn_flags & RTN_RTINFO) && leaf == rt) {
new_leaf = fib6_find_prefix(net, table, fn);
atomic_inc(&new_leaf->rt6i_ref);
atomic_inc(&new_leaf->fib6_ref);
rcu_assign_pointer(fn->leaf, new_leaf);
fib6_info_release(rt);
......@@ -919,7 +917,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
struct netlink_ext_ack *extack)
{
struct fib6_info *leaf = rcu_dereference_protected(fn->leaf,
lockdep_is_held(&rt->rt6i_table->tb6_lock));
lockdep_is_held(&rt->fib6_table->tb6_lock));
struct fib6_info *iter = NULL;
struct fib6_info __rcu **ins;
struct fib6_info __rcu **fallback_ins = NULL;
......@@ -939,12 +937,12 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
for (iter = leaf; iter;
iter = rcu_dereference_protected(iter->rt6_next,
lockdep_is_held(&rt->rt6i_table->tb6_lock))) {
lockdep_is_held(&rt->fib6_table->tb6_lock))) {
/*
* Search for duplicates
*/
if (iter->rt6i_metric == rt->rt6i_metric) {
if (iter->fib6_metric == rt->fib6_metric) {
/*
* Same priority level
*/
......@@ -964,11 +962,11 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
}
if (rt6_duplicate_nexthop(iter, rt)) {
if (rt->rt6i_nsiblings)
rt->rt6i_nsiblings = 0;
if (!(iter->rt6i_flags & RTF_EXPIRES))
if (rt->fib6_nsiblings)
rt->fib6_nsiblings = 0;
if (!(iter->fib6_flags & RTF_EXPIRES))
return -EEXIST;
if (!(rt->rt6i_flags & RTF_EXPIRES))
if (!(rt->fib6_flags & RTF_EXPIRES))
fib6_clean_expires(iter);
else
fib6_set_expires(iter, rt->expires);
......@@ -988,10 +986,10 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
*/
if (rt_can_ecmp &&
rt6_qualify_for_ecmp(iter))
rt->rt6i_nsiblings++;
rt->fib6_nsiblings++;
}
if (iter->rt6i_metric > rt->rt6i_metric)
if (iter->fib6_metric > rt->fib6_metric)
break;
next_iter:
......@@ -1002,7 +1000,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
/* No ECMP-able route found, replace first non-ECMP one */
ins = fallback_ins;
iter = rcu_dereference_protected(*ins,
lockdep_is_held(&rt->rt6i_table->tb6_lock));
lockdep_is_held(&rt->fib6_table->tb6_lock));
found++;
}
......@@ -1011,34 +1009,34 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
fn->rr_ptr = NULL;
/* Link this route to others same route. */
if (rt->rt6i_nsiblings) {
unsigned int rt6i_nsiblings;
if (rt->fib6_nsiblings) {
unsigned int fib6_nsiblings;
struct fib6_info *sibling, *temp_sibling;
/* Find the first route that have the same metric */
sibling = leaf;
while (sibling) {
if (sibling->rt6i_metric == rt->rt6i_metric &&
if (sibling->fib6_metric == rt->fib6_metric &&
rt6_qualify_for_ecmp(sibling)) {
list_add_tail(&rt->rt6i_siblings,
&sibling->rt6i_siblings);
list_add_tail(&rt->fib6_siblings,
&sibling->fib6_siblings);
break;
}
sibling = rcu_dereference_protected(sibling->rt6_next,
lockdep_is_held(&rt->rt6i_table->tb6_lock));
lockdep_is_held(&rt->fib6_table->tb6_lock));
}
/* For each sibling in the list, increment the counter of
* siblings. BUG() if counters does not match, list of siblings
* is broken!
*/
rt6i_nsiblings = 0;
fib6_nsiblings = 0;
list_for_each_entry_safe(sibling, temp_sibling,
&rt->rt6i_siblings, rt6i_siblings) {
sibling->rt6i_nsiblings++;
BUG_ON(sibling->rt6i_nsiblings != rt->rt6i_nsiblings);
rt6i_nsiblings++;
&rt->fib6_siblings, fib6_siblings) {
sibling->fib6_nsiblings++;
BUG_ON(sibling->fib6_nsiblings != rt->fib6_nsiblings);
fib6_nsiblings++;
}
BUG_ON(rt6i_nsiblings != rt->rt6i_nsiblings);
BUG_ON(fib6_nsiblings != rt->fib6_nsiblings);
rt6_multipath_rebalance(temp_sibling);
}
......@@ -1059,8 +1057,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
return err;
rcu_assign_pointer(rt->rt6_next, iter);
atomic_inc(&rt->rt6i_ref);
rcu_assign_pointer(rt->rt6i_node, fn);
atomic_inc(&rt->fib6_ref);
rcu_assign_pointer(rt->fib6_node, fn);
rcu_assign_pointer(*ins, rt);
if (!info->skip_notify)
inet6_rt_notify(RTM_NEWROUTE, rt, info, nlflags);
......@@ -1087,8 +1085,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
if (err)
return err;
atomic_inc(&rt->rt6i_ref);
rcu_assign_pointer(rt->rt6i_node, fn);
atomic_inc(&rt->fib6_ref);
rcu_assign_pointer(rt->fib6_node, fn);
rt->rt6_next = iter->rt6_next;
rcu_assign_pointer(*ins, rt);
if (!info->skip_notify)
......@@ -1097,8 +1095,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
info->nl_net->ipv6.rt6_stats->fib_route_nodes++;
fn->fn_flags |= RTN_RTINFO;
}
nsiblings = iter->rt6i_nsiblings;
iter->rt6i_node = NULL;
nsiblings = iter->fib6_nsiblings;
iter->fib6_node = NULL;
fib6_purge_rt(iter, fn, info->nl_net);
if (rcu_access_pointer(fn->rr_ptr) == iter)
fn->rr_ptr = NULL;
......@@ -1108,13 +1106,13 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
/* Replacing an ECMP route, remove all siblings */
ins = &rt->rt6_next;
iter = rcu_dereference_protected(*ins,
lockdep_is_held(&rt->rt6i_table->tb6_lock));
lockdep_is_held(&rt->fib6_table->tb6_lock));
while (iter) {
if (iter->rt6i_metric > rt->rt6i_metric)
if (iter->fib6_metric > rt->fib6_metric)
break;
if (rt6_qualify_for_ecmp(iter)) {
*ins = iter->rt6_next;
iter->rt6i_node = NULL;
iter->fib6_node = NULL;
fib6_purge_rt(iter, fn, info->nl_net);
if (rcu_access_pointer(fn->rr_ptr) == iter)
fn->rr_ptr = NULL;
......@@ -1125,7 +1123,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
ins = &iter->rt6_next;
}
iter = rcu_dereference_protected(*ins,
lockdep_is_held(&rt->rt6i_table->tb6_lock));
lockdep_is_held(&rt->fib6_table->tb6_lock));
}
WARN_ON(nsiblings != 0);
}
......@@ -1137,7 +1135,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
static void fib6_start_gc(struct net *net, struct fib6_info *rt)
{
if (!timer_pending(&net->ipv6.ip6_fib_timer) &&
(rt->rt6i_flags & RTF_EXPIRES))
(rt->fib6_flags & RTF_EXPIRES))
mod_timer(&net->ipv6.ip6_fib_timer,
jiffies + net->ipv6.sysctl.ip6_rt_gc_interval);
}
......@@ -1152,15 +1150,15 @@ void fib6_force_start_gc(struct net *net)
static void __fib6_update_sernum_upto_root(struct fib6_info *rt,
int sernum)
{
struct fib6_node *fn = rcu_dereference_protected(rt->rt6i_node,
lockdep_is_held(&rt->rt6i_table->tb6_lock));
struct fib6_node *fn = rcu_dereference_protected(rt->fib6_node,
lockdep_is_held(&rt->fib6_table->tb6_lock));
/* paired with smp_rmb() in rt6_get_cookie_safe() */
smp_wmb();
while (fn) {
fn->fn_sernum = sernum;
fn = rcu_dereference_protected(fn->parent,
lockdep_is_held(&rt->rt6i_table->tb6_lock));
lockdep_is_held(&rt->fib6_table->tb6_lock));
}
}
......@@ -1179,7 +1177,7 @@ void fib6_update_sernum_upto_root(struct net *net, struct fib6_info *rt)
int fib6_add(struct fib6_node *root, struct fib6_info *rt,
struct nl_info *info, struct netlink_ext_ack *extack)
{
struct fib6_table *table = rt->rt6i_table;
struct fib6_table *table = rt->fib6_table;
struct fib6_node *fn, *pn = NULL;
int err = -ENOMEM;
int allow_create = 1;
......@@ -1196,8 +1194,8 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt,
pr_warn("RTM_NEWROUTE with no NLM_F_CREATE or NLM_F_REPLACE\n");
fn = fib6_add_1(info->nl_net, table, root,
&rt->rt6i_dst.addr, rt->rt6i_dst.plen,
offsetof(struct fib6_info, rt6i_dst), allow_create,
&rt->fib6_dst.addr, rt->fib6_dst.plen,
offsetof(struct fib6_info, fib6_dst), allow_create,
replace_required, extack);
if (IS_ERR(fn)) {
err = PTR_ERR(fn);
......@@ -1208,7 +1206,7 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt,
pn = fn;
#ifdef CONFIG_IPV6_SUBTREES
if (rt->rt6i_src.plen) {
if (rt->fib6_src.plen) {
struct fib6_node *sn;
if (!rcu_access_pointer(fn->subtree)) {
......@@ -1229,7 +1227,7 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt,
if (!sfn)
goto failure;
atomic_inc(&info->nl_net->ipv6.fib6_null_entry->rt6i_ref);
atomic_inc(&info->nl_net->ipv6.fib6_null_entry->fib6_ref);
rcu_assign_pointer(sfn->leaf,
info->nl_net->ipv6.fib6_null_entry);
sfn->fn_flags = RTN_ROOT;
......@@ -1237,8 +1235,8 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt,
/* Now add the first leaf node to new subtree */
sn = fib6_add_1(info->nl_net, table, sfn,
&rt->rt6i_src.addr, rt->rt6i_src.plen,
offsetof(struct fib6_info, rt6i_src),
&rt->fib6_src.addr, rt->fib6_src.plen,
offsetof(struct fib6_info, fib6_src),
allow_create, replace_required, extack);
if (IS_ERR(sn)) {
......@@ -1256,8 +1254,8 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt,
rcu_assign_pointer(fn->subtree, sfn);
} else {
sn = fib6_add_1(info->nl_net, table, FIB6_SUBTREE(fn),
&rt->rt6i_src.addr, rt->rt6i_src.plen,
offsetof(struct fib6_info, rt6i_src),
&rt->fib6_src.addr, rt->fib6_src.plen,
offsetof(struct fib6_info, fib6_src),
allow_create, replace_required, extack);
if (IS_ERR(sn)) {
......@@ -1272,7 +1270,7 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt,
rcu_assign_pointer(fn->leaf,
info->nl_net->ipv6.fib6_null_entry);
} else {
atomic_inc(&rt->rt6i_ref);
atomic_inc(&rt->fib6_ref);
rcu_assign_pointer(fn->leaf, rt);
}
}
......@@ -1421,12 +1419,12 @@ struct fib6_node *fib6_lookup(struct fib6_node *root, const struct in6_addr *dad
struct fib6_node *fn;
struct lookup_args args[] = {
{
.offset = offsetof(struct fib6_info, rt6i_dst),
.offset = offsetof(struct fib6_info, fib6_dst),
.addr = daddr,
},
#ifdef CONFIG_IPV6_SUBTREES
{
.offset = offsetof(struct fib6_info, rt6i_src),
.offset = offsetof(struct fib6_info, fib6_src),
.addr = saddr,
},
#endif
......@@ -1511,7 +1509,7 @@ struct fib6_node *fib6_locate(struct fib6_node *root,
struct fib6_node *fn;
fn = fib6_locate_1(root, daddr, dst_len,
offsetof(struct fib6_info, rt6i_dst),
offsetof(struct fib6_info, fib6_dst),
exact_match);
#ifdef CONFIG_IPV6_SUBTREES
......@@ -1522,7 +1520,7 @@ struct fib6_node *fib6_locate(struct fib6_node *root,
if (subtree) {
fn = fib6_locate_1(subtree, saddr, src_len,
offsetof(struct fib6_info, rt6i_src),
offsetof(struct fib6_info, fib6_src),
exact_match);
}
}
......@@ -1706,7 +1704,7 @@ static void fib6_del_route(struct fib6_table *table, struct fib6_node *fn,
/* Unlink it */
*rtp = rt->rt6_next;
rt->rt6i_node = NULL;
rt->fib6_node = NULL;
net->ipv6.rt6_stats->fib_rt_entries--;
net->ipv6.rt6_stats->fib_discarded_routes++;
......@@ -1718,14 +1716,14 @@ static void fib6_del_route(struct fib6_table *table, struct fib6_node *fn,
fn->rr_ptr = NULL;
/* Remove this entry from other siblings */
if (rt->rt6i_nsiblings) {
if (rt->fib6_nsiblings) {
struct fib6_info *sibling, *next_sibling;
list_for_each_entry_safe(sibling, next_sibling,
&rt->rt6i_siblings, rt6i_siblings)
sibling->rt6i_nsiblings--;
rt->rt6i_nsiblings = 0;
list_del_init(&rt->rt6i_siblings);
&rt->fib6_siblings, fib6_siblings)
sibling->fib6_nsiblings--;
rt->fib6_nsiblings = 0;
list_del_init(&rt->fib6_siblings);
rt6_multipath_rebalance(next_sibling);
}
......@@ -1765,9 +1763,9 @@ static void fib6_del_route(struct fib6_table *table, struct fib6_node *fn,
/* Need to own table->tb6_lock */
int fib6_del(struct fib6_info *rt, struct nl_info *info)
{
struct fib6_node *fn = rcu_dereference_protected(rt->rt6i_node,
lockdep_is_held(&rt->rt6i_table->tb6_lock));
struct fib6_table *table = rt->rt6i_table;
struct fib6_node *fn = rcu_dereference_protected(rt->fib6_node,
lockdep_is_held(&rt->fib6_table->tb6_lock));
struct fib6_table *table = rt->fib6_table;
struct net *net = info->nl_net;
struct fib6_info __rcu **rtp;
struct fib6_info __rcu **rtp_next;
......@@ -1951,17 +1949,17 @@ static int fib6_clean_node(struct fib6_walker *w)
#if RT6_DEBUG >= 2
pr_debug("%s: del failed: rt=%p@%p err=%d\n",
__func__, rt,
rcu_access_pointer(rt->rt6i_node),
rcu_access_pointer(rt->fib6_node),
res);
#endif
continue;
}
return 0;
} else if (res == -2) {
if (WARN_ON(!rt->rt6i_nsiblings))
if (WARN_ON(!rt->fib6_nsiblings))
continue;
rt = list_last_entry(&rt->rt6i_siblings,
struct fib6_info, rt6i_siblings);
rt = list_last_entry(&rt->fib6_siblings,
struct fib6_info, fib6_siblings);
continue;
}
WARN_ON(res != 0);
......@@ -2045,7 +2043,7 @@ static int fib6_age(struct fib6_info *rt, void *arg)
* Routes are expired even if they are in use.
*/
if (rt->rt6i_flags & RTF_EXPIRES && rt->expires) {
if (rt->fib6_flags & RTF_EXPIRES && rt->expires) {
if (time_after(now, rt->expires)) {
RT6_TRACE("expiring %p\n", rt);
return -1;
......@@ -2243,22 +2241,22 @@ static int ipv6_route_seq_show(struct seq_file *seq, void *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);
seq_printf(seq, "%pi6 %02x ", &rt->fib6_dst.addr, rt->fib6_dst.plen);
#ifdef CONFIG_IPV6_SUBTREES
seq_printf(seq, "%pi6 %02x ", &rt->rt6i_src.addr, rt->rt6i_src.plen);
seq_printf(seq, "%pi6 %02x ", &rt->fib6_src.addr, rt->fib6_src.plen);
#else
seq_puts(seq, "00000000000000000000000000000000 00 ");
#endif
if (rt->rt6i_flags & RTF_GATEWAY)
if (rt->fib6_flags & RTF_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->rt6i_ref), 0,
rt->rt6i_flags, dev ? dev->name : "");
rt->fib6_metric, atomic_read(&rt->fib6_ref), 0,
rt->fib6_flags, dev ? dev->name : "");
iter->w.leaf = NULL;
return 0;
}
......
......@@ -1318,7 +1318,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
}
neigh->flags |= NTF_ROUTER;
} else if (rt) {
rt->rt6i_flags = (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
rt->fib6_flags = (rt->fib6_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
}
if (rt)
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册