Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2b2450ca authored by David Ahern's avatar David Ahern Committed by David S. Miller
Browse files

ipv6: Move gateway checks to a fib6_nh setting



The gateway setting is not per fib6_info entry but per-fib6_nh. Add a new
fib_nh_has_gw flag to fib6_nh and convert references to RTF_GATEWAY to
the new flag. For IPv6 address the flag is cheaper than checking that
nh_gw is non-0 like IPv4 does.

While this increases fib6_nh by 8-bytes, the effective allocation size of
a fib6_info is unchanged. The 8 bytes is recovered later with a
fib_nh_common change.

Signed-off-by: default avatarDavid Ahern <dsahern@gmail.com>
Reviewed-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent dac7d0f2
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -4913,7 +4913,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->fib6_flags & (RTF_GATEWAY | RTF_ADDRCONF)) == RTF_GATEWAY;
	return !(rt->fib6_flags & RTF_ADDRCONF) && rt->fib6_nh.fib_nh_has_gw;
}

static struct fib6_info *
@@ -5053,7 +5053,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->fib6_flags & RTF_GATEWAY ||
	return rt->fib6_nh.fib_nh_has_gw ||
	       mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, NULL);
}

+1 −0
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@ struct rt6_exception {

struct fib6_nh {
	struct in6_addr		nh_gw;
	bool			fib_nh_has_gw;
	struct net_device	*nh_dev;
	struct lwtunnel_state	*nh_lwtstate;

+2 −2
Original line number Diff line number Diff line
@@ -68,8 +68,8 @@ static inline bool rt6_need_strict(const struct in6_addr *daddr)

static inline bool rt6_qualify_for_ecmp(const struct fib6_info *f6i)
{
	return (f6i->fib6_flags & (RTF_GATEWAY|RTF_ADDRCONF|RTF_DYNAMIC)) ==
	       RTF_GATEWAY;
	return !(f6i->fib6_flags & (RTF_ADDRCONF|RTF_DYNAMIC)) &&
		f6i->fib6_nh.fib_nh_has_gw;
}

void ip6_route_input(struct sk_buff *skb);
+1 −1
Original line number Diff line number Diff line
@@ -4751,7 +4751,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
	if (f6i->fib6_nh.nh_lwtstate)
		return BPF_FIB_LKUP_RET_UNSUPP_LWT;

	if (f6i->fib6_flags & RTF_GATEWAY)
	if (f6i->fib6_nh.fib_nh_has_gw)
		*dst = f6i->fib6_nh.nh_gw;

	dev = f6i->fib6_nh.nh_dev;
+13 −12
Original line number Diff line number Diff line
@@ -173,7 +173,8 @@ static int addrconf_ifdown(struct net_device *dev, int how);
static struct fib6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
						  int plen,
						  const struct net_device *dev,
						  u32 flags, u32 noflags);
						  u32 flags, u32 noflags,
						  bool no_gw);

static void addrconf_dad_start(struct inet6_ifaddr *ifp);
static void addrconf_dad_work(struct work_struct *w);
@@ -1230,10 +1231,8 @@ cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long expires, bool del_r
{
	struct fib6_info *f6i;

	f6i = addrconf_get_prefix_route(&ifp->addr,
				       ifp->prefix_len,
				       ifp->idev->dev,
				       0, RTF_GATEWAY | RTF_DEFAULT);
	f6i = addrconf_get_prefix_route(&ifp->addr, ifp->prefix_len,
					ifp->idev->dev, 0, RTF_DEFAULT, true);
	if (f6i) {
		if (del_rt)
			ip6_del_rt(dev_net(ifp->idev->dev), f6i);
@@ -2402,7 +2401,8 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, u32 metric,
static struct fib6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
						  int plen,
						  const struct net_device *dev,
						  u32 flags, u32 noflags)
						  u32 flags, u32 noflags,
						  bool no_gw)
{
	struct fib6_node *fn;
	struct fib6_info *rt = NULL;
@@ -2421,6 +2421,8 @@ 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 (no_gw && rt->fib6_nh.fib_nh_has_gw)
			continue;
		if ((rt->fib6_flags & flags) != flags)
			continue;
		if ((rt->fib6_flags & noflags) != 0)
@@ -2717,7 +2719,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
					       pinfo->prefix_len,
					       dev,
					       RTF_ADDRCONF | RTF_PREFIX_RT,
					       RTF_GATEWAY | RTF_DEFAULT);
					       RTF_DEFAULT, true);

		if (rt) {
			/* Autoconf prefix route */
@@ -4588,10 +4590,8 @@ static int modify_prefix_route(struct inet6_ifaddr *ifp,
	struct fib6_info *f6i;
	u32 prio;

	f6i = addrconf_get_prefix_route(&ifp->addr,
					ifp->prefix_len,
					ifp->idev->dev,
					0, RTF_GATEWAY | RTF_DEFAULT);
	f6i = addrconf_get_prefix_route(&ifp->addr, ifp->prefix_len,
					ifp->idev->dev, 0, RTF_DEFAULT, true);
	if (!f6i)
		return -ENOENT;

@@ -5972,7 +5972,8 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
			struct fib6_info *rt;

			rt = addrconf_get_prefix_route(&ifp->peer_addr, 128,
						       ifp->idev->dev, 0, 0);
						       ifp->idev->dev, 0, 0,
						       false);
			if (rt)
				ip6_del_rt(net, rt);
		}
Loading