forked from mirrors/linux
		
	ipv4: Prepare rtable for IPv6 gateway
To allow the gateway to be either an IPv4 or IPv6 address, remove rt_uses_gateway from rtable and replace with rt_gw_family. If rt_gw_family is set it implies rt_uses_gateway. Rename rt_gateway to rt_gw4 to represent the IPv4 version. Signed-off-by: David Ahern <dsahern@gmail.com> Reviewed-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									bdf0046771
								
							
						
					
					
						commit
						1550c17193
					
				
					 13 changed files with 57 additions and 45 deletions
				
			
		|  | @ -351,7 +351,7 @@ static bool has_gateway(const struct dst_entry *dst, sa_family_t family) | ||||||
| 
 | 
 | ||||||
| 	if (family == AF_INET) { | 	if (family == AF_INET) { | ||||||
| 		rt = container_of(dst, struct rtable, dst); | 		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); | 	rt6 = container_of(dst, struct rt6_info, dst); | ||||||
|  |  | ||||||
|  | @ -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) { | 		if (neigh->nud_state & NUD_VALID) { | ||||||
| 			nes_debug(NES_DBG_CM, "Neighbor MAC address for 0x%08X" | 			nes_debug(NES_DBG_CM, "Neighbor MAC address for 0x%08X" | ||||||
| 				  " is %pM, Gateway is 0x%08X \n", dst_ip, | 				  " 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 (arpindex >= 0) { | ||||||
| 				if (ether_addr_equal(nesadapter->arp_table[arpindex].mac_addr, neigh->ha)) { | 				if (ether_addr_equal(nesadapter->arp_table[arpindex].mac_addr, neigh->ha)) { | ||||||
|  |  | ||||||
|  | @ -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) | 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 ddpehdr *ddp; | ||||||
|         struct ipddp_route *rt; |         struct ipddp_route *rt; | ||||||
|         struct atalk_addr *our_addr; |         struct atalk_addr *our_addr; | ||||||
| 
 | 
 | ||||||
|  | 	if (rtable->rt_gw_family == AF_INET) | ||||||
|  | 		paddr = rtable->rt_gw4; | ||||||
|  | 
 | ||||||
| 	spin_lock(&ipddp_route_lock); | 	spin_lock(&ipddp_route_lock); | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
|  |  | ||||||
|  | @ -70,7 +70,7 @@ static int mlx5e_route_lookup_ipv4(struct mlx5e_priv *priv, | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return 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; | 		return -ENETUNREACH; | ||||||
| #else | #else | ||||||
| 	return -EOPNOTSUPP; | 	return -EOPNOTSUPP; | ||||||
|  |  | ||||||
|  | @ -316,7 +316,8 @@ mlxsw_sp_span_gretap4_route(const struct net_device *to_dev, | ||||||
| 
 | 
 | ||||||
| 	dev = rt->dst.dev; | 	dev = rt->dst.dev; | ||||||
| 	*saddrp = fl4.saddr; | 	*saddrp = fl4.saddr; | ||||||
| 	*daddrp = rt->rt_gateway; | 	if (rt->rt_gw_family == AF_INET) | ||||||
|  | 		*daddrp = rt->rt_gw4; | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
| 	ip_rt_put(rt); | 	ip_rt_put(rt); | ||||||
|  |  | ||||||
|  | @ -55,12 +55,12 @@ struct rtable { | ||||||
| 	unsigned int		rt_flags; | 	unsigned int		rt_flags; | ||||||
| 	__u16			rt_type; | 	__u16			rt_type; | ||||||
| 	__u8			rt_is_input; | 	__u8			rt_is_input; | ||||||
| 	__u8			rt_uses_gateway; | 	u8			rt_gw_family; | ||||||
| 
 | 
 | ||||||
| 	int			rt_iif; | 	int			rt_iif; | ||||||
| 
 | 
 | ||||||
| 	/* Info on neighbour */ | 	/* Info on neighbour */ | ||||||
| 	__be32			rt_gateway; | 	__be32			rt_gw4; | ||||||
| 
 | 
 | ||||||
| 	/* Miscellaneous cached information */ | 	/* Miscellaneous cached information */ | ||||||
| 	u32			rt_mtu_locked:1, | 	u32			rt_mtu_locked:1, | ||||||
|  | @ -82,8 +82,8 @@ static inline bool rt_is_output_route(const struct rtable *rt) | ||||||
| 
 | 
 | ||||||
| static inline __be32 rt_nexthop(const struct rtable *rt, __be32 daddr) | static inline __be32 rt_nexthop(const struct rtable *rt, __be32 daddr) | ||||||
| { | { | ||||||
| 	if (rt->rt_gateway) | 	if (rt->rt_gw_family == AF_INET) | ||||||
| 		return rt->rt_gateway; | 		return rt->rt_gw4; | ||||||
| 	return daddr; | 	return daddr; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -345,8 +345,8 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb, | ||||||
| 		return NETDEV_TX_OK; | 		return NETDEV_TX_OK; | ||||||
| 	} | 	} | ||||||
| 	rt = (struct rtable *) dst; | 	rt = (struct rtable *) dst; | ||||||
| 	if (rt->rt_gateway) | 	if (rt->rt_gw_family == AF_INET) | ||||||
| 		daddr = &rt->rt_gateway; | 		daddr = &rt->rt_gw4; | ||||||
| 	else | 	else | ||||||
| 		daddr = &ip_hdr(skb)->daddr; | 		daddr = &ip_hdr(skb)->daddr; | ||||||
| 	n = dst_neigh_lookup(dst, daddr); | 	n = dst_neigh_lookup(dst, daddr); | ||||||
|  |  | ||||||
|  | @ -564,7 +564,7 @@ struct dst_entry *inet_csk_route_req(const struct sock *sk, | ||||||
| 	rt = ip_route_output_flow(net, fl4, sk); | 	rt = ip_route_output_flow(net, fl4, sk); | ||||||
| 	if (IS_ERR(rt)) | 	if (IS_ERR(rt)) | ||||||
| 		goto no_route; | 		goto no_route; | ||||||
| 	if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway) | 	if (opt && opt->opt.is_strictroute && rt->rt_gw_family) | ||||||
| 		goto route_err; | 		goto route_err; | ||||||
| 	rcu_read_unlock(); | 	rcu_read_unlock(); | ||||||
| 	return &rt->dst; | 	return &rt->dst; | ||||||
|  | @ -602,7 +602,7 @@ struct dst_entry *inet_csk_route_child_sock(const struct sock *sk, | ||||||
| 	rt = ip_route_output_flow(net, fl4, sk); | 	rt = ip_route_output_flow(net, fl4, sk); | ||||||
| 	if (IS_ERR(rt)) | 	if (IS_ERR(rt)) | ||||||
| 		goto no_route; | 		goto no_route; | ||||||
| 	if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway) | 	if (opt && opt->opt.is_strictroute && rt->rt_gw_family) | ||||||
| 		goto route_err; | 		goto route_err; | ||||||
| 	return &rt->dst; | 	return &rt->dst; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -123,7 +123,7 @@ int ip_forward(struct sk_buff *skb) | ||||||
| 
 | 
 | ||||||
| 	rt = skb_rtable(skb); | 	rt = skb_rtable(skb); | ||||||
| 
 | 
 | ||||||
| 	if (opt->is_strictroute && rt->rt_uses_gateway) | 	if (opt->is_strictroute && rt->rt_gw_family) | ||||||
| 		goto sr_failed; | 		goto sr_failed; | ||||||
| 
 | 
 | ||||||
| 	IPCB(skb)->flags |= IPSKB_FORWARDED; | 	IPCB(skb)->flags |= IPSKB_FORWARDED; | ||||||
|  |  | ||||||
|  | @ -472,7 +472,7 @@ int __ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | ||||||
| 	skb_dst_set_noref(skb, &rt->dst); | 	skb_dst_set_noref(skb, &rt->dst); | ||||||
| 
 | 
 | ||||||
| packet_routed: | packet_routed: | ||||||
| 	if (inet_opt && inet_opt->opt.is_strictroute && rt->rt_uses_gateway) | 	if (inet_opt && inet_opt->opt.is_strictroute && rt->rt_gw_family) | ||||||
| 		goto no_route; | 		goto no_route; | ||||||
| 
 | 
 | ||||||
| 	/* OK, we know where to send it, allocate and build IP header. */ | 	/* OK, we know where to send it, allocate and build IP header. */ | ||||||
|  |  | ||||||
|  | @ -434,14 +434,13 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, | ||||||
| 					   struct sk_buff *skb, | 					   struct sk_buff *skb, | ||||||
| 					   const void *daddr) | 					   const void *daddr) | ||||||
| { | { | ||||||
|  | 	const struct rtable *rt = container_of(dst, struct rtable, dst); | ||||||
| 	struct net_device *dev = dst->dev; | 	struct net_device *dev = dst->dev; | ||||||
| 	const __be32 *pkey = daddr; | 	const __be32 *pkey = daddr; | ||||||
| 	const struct rtable *rt; |  | ||||||
| 	struct neighbour *n; | 	struct neighbour *n; | ||||||
| 
 | 
 | ||||||
| 	rt = (const struct rtable *) dst; | 	if (rt->rt_gw_family == AF_INET) | ||||||
| 	if (rt->rt_gateway) | 		pkey = (const __be32 *) &rt->rt_gw4; | ||||||
| 		pkey = (const __be32 *) &rt->rt_gateway; |  | ||||||
| 	else if (skb) | 	else if (skb) | ||||||
| 		pkey = &ip_hdr(skb)->daddr; | 		pkey = &ip_hdr(skb)->daddr; | ||||||
| 
 | 
 | ||||||
|  | @ -453,13 +452,12 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, | ||||||
| 
 | 
 | ||||||
| static void ipv4_confirm_neigh(const struct dst_entry *dst, const void *daddr) | static void ipv4_confirm_neigh(const struct dst_entry *dst, const void *daddr) | ||||||
| { | { | ||||||
|  | 	const struct rtable *rt = container_of(dst, struct rtable, dst); | ||||||
| 	struct net_device *dev = dst->dev; | 	struct net_device *dev = dst->dev; | ||||||
| 	const __be32 *pkey = daddr; | 	const __be32 *pkey = daddr; | ||||||
| 	const struct rtable *rt; |  | ||||||
| 
 | 
 | ||||||
| 	rt = (const struct rtable *)dst; | 	if (rt->rt_gw_family == AF_INET) | ||||||
| 	if (rt->rt_gateway) | 		pkey = (const __be32 *)&rt->rt_gw4; | ||||||
| 		pkey = (const __be32 *)&rt->rt_gateway; |  | ||||||
| 	else if (!daddr || | 	else if (!daddr || | ||||||
| 		 (rt->rt_flags & | 		 (rt->rt_flags & | ||||||
| 		  (RTCF_MULTICAST | RTCF_BROADCAST | RTCF_LOCAL))) | 		  (RTCF_MULTICAST | RTCF_BROADCAST | RTCF_LOCAL))) | ||||||
|  | @ -629,8 +627,8 @@ static void fill_route_from_fnhe(struct rtable *rt, struct fib_nh_exception *fnh | ||||||
| 
 | 
 | ||||||
| 	if (fnhe->fnhe_gw) { | 	if (fnhe->fnhe_gw) { | ||||||
| 		rt->rt_flags |= RTCF_REDIRECTED; | 		rt->rt_flags |= RTCF_REDIRECTED; | ||||||
| 		rt->rt_gateway = fnhe->fnhe_gw; | 		rt->rt_gw_family = AF_INET; | ||||||
| 		rt->rt_uses_gateway = 1; | 		rt->rt_gw4 = fnhe->fnhe_gw; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -747,7 +745,7 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (rt->rt_gateway != old_gw) | 	if (rt->rt_gw_family != AF_INET || rt->rt_gw4 != old_gw) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	in_dev = __in_dev_get_rcu(dev); | 	in_dev = __in_dev_get_rcu(dev); | ||||||
|  | @ -1282,7 +1280,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst) | ||||||
| 	mtu = READ_ONCE(dst->dev->mtu); | 	mtu = READ_ONCE(dst->dev->mtu); | ||||||
| 
 | 
 | ||||||
| 	if (unlikely(ip_mtu_locked(dst))) { | 	if (unlikely(ip_mtu_locked(dst))) { | ||||||
| 		if (rt->rt_uses_gateway && mtu > 576) | 		if (rt->rt_gw_family && mtu > 576) | ||||||
| 			mtu = 576; | 			mtu = 576; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -1410,8 +1408,10 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, | ||||||
| 			orig = NULL; | 			orig = NULL; | ||||||
| 		} | 		} | ||||||
| 		fill_route_from_fnhe(rt, fnhe); | 		fill_route_from_fnhe(rt, fnhe); | ||||||
| 		if (!rt->rt_gateway) | 		if (!rt->rt_gw4) { | ||||||
| 			rt->rt_gateway = daddr; | 			rt->rt_gw4 = daddr; | ||||||
|  | 			rt->rt_gw_family = AF_INET; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		if (do_cache) { | 		if (do_cache) { | ||||||
| 			dst_hold(&rt->dst); | 			dst_hold(&rt->dst); | ||||||
|  | @ -1538,8 +1538,8 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr, | ||||||
| 		struct fib_nh *nh = container_of(nhc, struct fib_nh, nh_common); | 		struct fib_nh *nh = container_of(nhc, struct fib_nh, nh_common); | ||||||
| 
 | 
 | ||||||
| 		if (nh->fib_nh_gw4 && nh->fib_nh_scope == RT_SCOPE_LINK) { | 		if (nh->fib_nh_gw4 && nh->fib_nh_scope == RT_SCOPE_LINK) { | ||||||
| 			rt->rt_gateway = nh->fib_nh_gw4; | 			rt->rt_gw4 = nh->fib_nh_gw4; | ||||||
| 			rt->rt_uses_gateway = 1; | 			rt->rt_gw_family = AF_INET; | ||||||
| 		} | 		} | ||||||
| 		ip_dst_init_metrics(&rt->dst, fi->fib_metrics); | 		ip_dst_init_metrics(&rt->dst, fi->fib_metrics); | ||||||
| 
 | 
 | ||||||
|  | @ -1557,8 +1557,10 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr, | ||||||
| 			 * However, if we are unsuccessful at storing this | 			 * However, if we are unsuccessful at storing this | ||||||
| 			 * route into the cache we really need to set it. | 			 * route into the cache we really need to set it. | ||||||
| 			 */ | 			 */ | ||||||
| 			if (!rt->rt_gateway) | 			if (!rt->rt_gw4) { | ||||||
| 				rt->rt_gateway = daddr; | 				rt->rt_gw_family = AF_INET; | ||||||
|  | 				rt->rt_gw4 = daddr; | ||||||
|  | 			} | ||||||
| 			rt_add_uncached_list(rt); | 			rt_add_uncached_list(rt); | ||||||
| 		} | 		} | ||||||
| 	} else | 	} else | ||||||
|  | @ -1591,8 +1593,8 @@ struct rtable *rt_dst_alloc(struct net_device *dev, | ||||||
| 		rt->rt_iif = 0; | 		rt->rt_iif = 0; | ||||||
| 		rt->rt_pmtu = 0; | 		rt->rt_pmtu = 0; | ||||||
| 		rt->rt_mtu_locked = 0; | 		rt->rt_mtu_locked = 0; | ||||||
| 		rt->rt_gateway = 0; | 		rt->rt_gw_family = 0; | ||||||
| 		rt->rt_uses_gateway = 0; | 		rt->rt_gw4 = 0; | ||||||
| 		INIT_LIST_HEAD(&rt->rt_uncached); | 		INIT_LIST_HEAD(&rt->rt_uncached); | ||||||
| 
 | 
 | ||||||
| 		rt->dst.output = ip_output; | 		rt->dst.output = ip_output; | ||||||
|  | @ -2595,8 +2597,9 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or | ||||||
| 		rt->rt_genid = rt_genid_ipv4(net); | 		rt->rt_genid = rt_genid_ipv4(net); | ||||||
| 		rt->rt_flags = ort->rt_flags; | 		rt->rt_flags = ort->rt_flags; | ||||||
| 		rt->rt_type = ort->rt_type; | 		rt->rt_type = ort->rt_type; | ||||||
| 		rt->rt_gateway = ort->rt_gateway; | 		rt->rt_gw_family = ort->rt_gw_family; | ||||||
| 		rt->rt_uses_gateway = ort->rt_uses_gateway; | 		if (rt->rt_gw_family == AF_INET) | ||||||
|  | 			rt->rt_gw4 = ort->rt_gw4; | ||||||
| 
 | 
 | ||||||
| 		INIT_LIST_HEAD(&rt->rt_uncached); | 		INIT_LIST_HEAD(&rt->rt_uncached); | ||||||
| 	} | 	} | ||||||
|  | @ -2675,8 +2678,8 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, | ||||||
| 		if (nla_put_in_addr(skb, RTA_PREFSRC, fl4->saddr)) | 		if (nla_put_in_addr(skb, RTA_PREFSRC, fl4->saddr)) | ||||||
| 			goto nla_put_failure; | 			goto nla_put_failure; | ||||||
| 	} | 	} | ||||||
| 	if (rt->rt_uses_gateway && | 	if (rt->rt_gw_family == AF_INET && | ||||||
| 	    nla_put_in_addr(skb, RTA_GATEWAY, rt->rt_gateway)) | 	    nla_put_in_addr(skb, RTA_GATEWAY, rt->rt_gw4)) | ||||||
| 		goto nla_put_failure; | 		goto nla_put_failure; | ||||||
| 
 | 
 | ||||||
| 	expires = rt->dst.expires; | 	expires = rt->dst.expires; | ||||||
|  |  | ||||||
|  | @ -97,8 +97,9 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, | ||||||
| 	xdst->u.rt.rt_flags = rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST | | 	xdst->u.rt.rt_flags = rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST | | ||||||
| 					      RTCF_LOCAL); | 					      RTCF_LOCAL); | ||||||
| 	xdst->u.rt.rt_type = rt->rt_type; | 	xdst->u.rt.rt_type = rt->rt_type; | ||||||
| 	xdst->u.rt.rt_gateway = rt->rt_gateway; | 	xdst->u.rt.rt_gw_family = rt->rt_gw_family; | ||||||
| 	xdst->u.rt.rt_uses_gateway = rt->rt_uses_gateway; | 	if (rt->rt_gw_family == AF_INET) | ||||||
|  | 		xdst->u.rt.rt_gw4 = rt->rt_gw4; | ||||||
| 	xdst->u.rt.rt_pmtu = rt->rt_pmtu; | 	xdst->u.rt.rt_pmtu = rt->rt_pmtu; | ||||||
| 	xdst->u.rt.rt_mtu_locked = rt->rt_mtu_locked; | 	xdst->u.rt.rt_mtu_locked = rt->rt_mtu_locked; | ||||||
| 	INIT_LIST_HEAD(&xdst->u.rt.rt_uncached); | 	INIT_LIST_HEAD(&xdst->u.rt.rt_uncached); | ||||||
|  |  | ||||||
|  | @ -137,10 +137,13 @@ static int mpls_xmit(struct sk_buff *skb) | ||||||
| 
 | 
 | ||||||
| 	mpls_stats_inc_outucastpkts(out_dev, skb); | 	mpls_stats_inc_outucastpkts(out_dev, skb); | ||||||
| 
 | 
 | ||||||
| 	if (rt) | 	if (rt) { | ||||||
| 		err = neigh_xmit(NEIGH_ARP_TABLE, out_dev, &rt->rt_gateway, | 		if (rt->rt_gw_family == AF_INET) | ||||||
|  | 			err = neigh_xmit(NEIGH_ARP_TABLE, out_dev, &rt->rt_gw4, | ||||||
| 					 skb); | 					 skb); | ||||||
| 	else if (rt6) { | 		else | ||||||
|  | 			err = -EAFNOSUPPORT; | ||||||
|  | 	} else if (rt6) { | ||||||
| 		if (ipv6_addr_v4mapped(&rt6->rt6i_gateway)) { | 		if (ipv6_addr_v4mapped(&rt6->rt6i_gateway)) { | ||||||
| 			/* 6PE (RFC 4798) */ | 			/* 6PE (RFC 4798) */ | ||||||
| 			err = neigh_xmit(NEIGH_ARP_TABLE, out_dev, &rt6->rt6i_gateway.s6_addr32[3], | 			err = neigh_xmit(NEIGH_ARP_TABLE, out_dev, &rt6->rt6i_gateway.s6_addr32[3], | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 David Ahern
						David Ahern