Commit 0ed8c3dc authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'ipv4-Enable-support-for-IPv6-gateway-with-IPv4-routes'



David Ahern says:

====================
ipv4: Enable support for IPv6 gateway with IPv4 routes

Last set of three with the end goal of enabling IPv6 gateways with IPv4
routes.

This set adds fib6_nh_init and release to the IPv6 stubs, and adds neighbor
helpers that IPv4 code invokes to resolve an IPv6 address. When using
an IPv6 neighbor entry the hh_cache is bypassed as it contains the wrong
ethernet header for an IPv4 packet.

The nh_common nhc_has_gw was a temporary field used to convert existing
code from fib{6}_nh to fib_nh_common. That field is now converted to
nhc_gw_family to differentiate the address family of the gateway entry
as opposed to the address family of the container of fib_nh_common.

Existing code for rtable and fib_config is refactored to prepare
for a v6 address and then support is added. From there various
miscellaneous functions are updated to handle a v6 gateway - from
validating the v6 address to lookups in bpf code to verifying the
nexthop state.

Offload drivers - mlxsw and rocker - are modified to detect the v6
gateway and reject the route as 'unsupported'. e.g.,

    $ ip ro add 172.16.101.0/24 via inet6 fe80::202:ff:fe00:b dev swp1s0
    Error: mlxsw_spectrum: IPv6 gateway with IPv4 route is not supported.

This can be removed in time once support is added to each.

With the infrastructure changes in place, patch 17 enables it by adding
support for RTA_VIA to IPv4. RTA_VIA can be used for IPv4 addresses as
well. Only one of RTA_VIA and RTA_GATEWAY can be passed in a request.

Patch 18 adds a few test cases to fib_tests.sh.

v2
- comments from Ido - fixed typos as noted and updated messages
- add commit message to patch 1
- In patch 9, ipv4: Add fib_check_nh_v6_gw, moved the call to
  fib6_nh_release under the 'if (!err)' check as the intention is
  that release should not be called if init fails.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3b8b11f9 228ddb33
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -351,7 +351,7 @@ static bool has_gateway(const struct dst_entry *dst, sa_family_t family)

	if (family == AF_INET) {
		rt = container_of(dst, struct rtable, dst);
		return rt->rt_uses_gateway;
		return rt->rt_gw_family == AF_INET;
	}

	rt6 = container_of(dst, struct rt6_info, dst);
+1 −1
Original line number Diff line number Diff line
@@ -1407,7 +1407,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
		if (neigh->nud_state & NUD_VALID) {
			nes_debug(NES_DBG_CM, "Neighbor MAC address for 0x%08X"
				  " is %pM, Gateway is 0x%08X \n", dst_ip,
				  neigh->ha, ntohl(rt->rt_gateway));
				  neigh->ha, ntohl(rt->rt_gw4));

			if (arpindex >= 0) {
				if (ether_addr_equal(nesadapter->arp_table[arpindex].mac_addr, neigh->ha)) {
+5 −1
Original line number Diff line number Diff line
@@ -116,11 +116,15 @@ static struct net_device * __init ipddp_init(void)
 */
static netdev_tx_t ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
{
	__be32 paddr = skb_rtable(skb)->rt_gateway;
        struct rtable *rtable = skb_rtable(skb);
        __be32 paddr = 0;
        struct ddpehdr *ddp;
        struct ipddp_route *rt;
        struct atalk_addr *our_addr;

	if (rtable->rt_gw_family == AF_INET)
		paddr = rtable->rt_gw4;

	spin_lock(&ipddp_route_lock);

	/*
+1 −1
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ static int mlx5e_route_lookup_ipv4(struct mlx5e_priv *priv,
	if (ret)
		return ret;

	if (mlx5_lag_is_multipath(mdev) && !rt->rt_gateway)
	if (mlx5_lag_is_multipath(mdev) && rt->rt_gw_family != AF_INET)
		return -ENETUNREACH;
#else
	return -EOPNOTSUPP;
+10 −2
Original line number Diff line number Diff line
@@ -4915,7 +4915,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_ADDRCONF) && rt->fib6_nh.fib_nh_has_gw;
	return !(rt->fib6_flags & RTF_ADDRCONF) && rt->fib6_nh.fib_nh_gw_family;
}

static struct fib6_info *
@@ -5055,7 +5055,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_nh.fib_nh_has_gw ||
	return rt->fib6_nh.fib_nh_gw_family ||
	       mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, NULL);
}

@@ -6092,6 +6092,14 @@ static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
			NL_SET_ERR_MSG_MOD(info->extack, "FIB offload was aborted. Not configuring route");
			return notifier_from_errno(-EINVAL);
		}
		if (info->family == AF_INET) {
			struct fib_entry_notifier_info *fen_info = ptr;

			if (fen_info->fi->fib_nh_is_v6) {
				NL_SET_ERR_MSG_MOD(info->extack, "IPv6 gateway with IPv4 route is not supported");
				return notifier_from_errno(-EINVAL);
			}
		}
		break;
	}

Loading