Commit 1550c171 authored by David Ahern's avatar David Ahern Committed by David S. Miller

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: 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 bdf00467
...@@ -351,7 +351,7 @@ static bool has_gateway(const struct dst_entry *dst, sa_family_t family) ...@@ -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 ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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 { ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 ...@@ -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 ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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)
skb); err = neigh_xmit(NEIGH_ARP_TABLE, out_dev, &rt->rt_gw4,
else if (rt6) { skb);
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],
......
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