ipv4: Prepare rtable for IPv6 gateway
authorDavid Ahern <dsahern@gmail.com>
Fri, 5 Apr 2019 23:30:27 +0000 (16:30 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 8 Apr 2019 22:22:40 +0000 (15:22 -0700)
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>
13 files changed:
drivers/infiniband/core/addr.c
drivers/infiniband/hw/nes/nes_cm.c
drivers/net/appletalk/ipddp.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
include/net/route.h
net/atm/clip.c
net/ipv4/inet_connection_sock.c
net/ipv4/ip_forward.c
net/ipv4/ip_output.c
net/ipv4/route.c
net/ipv4/xfrm4_policy.c
net/mpls/mpls_iptunnel.c

index 2649e0f2ff65993e1401b0c2d29e7d3303687ffd..f5ecb660fe7d4a4bfe6222ab8ac141abb6584474 100644 (file)
@@ -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);
index 032883180f6524ce69872fd72f2e2519ad9e5056..0010a3ed64f154b4220db3ee757cf1f44affb82c 100644 (file)
@@ -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)) {
index 3d27616d9c85540304a8d78c4a2f050c0866b9a2..51cf5eca9c7f8de290d5498ef0b9a7f94190004c 100644 (file)
@@ -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);
 
        /*
index 9ab3bd9042959d6943bb5aaa3c84d86233aef132..b9d5830e834472e2192b9912ed3ec494ead7cba4 100644 (file)
@@ -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;
index 536c23c578c348d103858c8fe48fec53d22d49a2..133a497e34576ea9ec24929fb474b72f4f0e1ca1 100644 (file)
@@ -316,7 +316,8 @@ mlxsw_sp_span_gretap4_route(const struct net_device *to_dev,
 
        dev = rt->dst.dev;
        *saddrp = fl4.saddr;
-       *daddrp = rt->rt_gateway;
+       if (rt->rt_gw_family == AF_INET)
+               *daddrp = rt->rt_gw4;
 
 out:
        ip_rt_put(rt);
index 9883dc82f7233dede86ec2e5cfeddf09cf56d62d..96912b099c08a75f1e53e4b180b29a99977987bb 100644 (file)
@@ -55,12 +55,12 @@ struct rtable {
        unsigned int            rt_flags;
        __u16                   rt_type;
        __u8                    rt_is_input;
-       __u8                    rt_uses_gateway;
+       u8                      rt_gw_family;
 
        int                     rt_iif;
 
        /* Info on neighbour */
-       __be32                  rt_gateway;
+       __be32                  rt_gw4;
 
        /* Miscellaneous cached information */
        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)
 {
-       if (rt->rt_gateway)
-               return rt->rt_gateway;
+       if (rt->rt_gw_family == AF_INET)
+               return rt->rt_gw4;
        return daddr;
 }
 
index d795b9c5aea4a4e35021d9db2e10254036df55fe..b9e67e589a7b43eeda8268f329adf607e167e80f 100644 (file)
@@ -345,8 +345,8 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb,
                return NETDEV_TX_OK;
        }
        rt = (struct rtable *) dst;
-       if (rt->rt_gateway)
-               daddr = &rt->rt_gateway;
+       if (rt->rt_gw_family == AF_INET)
+               daddr = &rt->rt_gw4;
        else
                daddr = &ip_hdr(skb)->daddr;
        n = dst_neigh_lookup(dst, daddr);
index 6ea523d71947779b68d599de11a2a74535f578f0..a175e3e7ae97c53d0d9d8392589a86cdbc4c886e 100644 (file)
@@ -564,7 +564,7 @@ struct dst_entry *inet_csk_route_req(const struct sock *sk,
        rt = ip_route_output_flow(net, fl4, sk);
        if (IS_ERR(rt))
                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;
        rcu_read_unlock();
        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);
        if (IS_ERR(rt))
                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;
        return &rt->dst;
 
index 00ec819f949b5e76ea96be901a697f4e12d5cf4d..06f6f280b9ff38864020e14a8a728b5258e65b0b 100644 (file)
@@ -123,7 +123,7 @@ int ip_forward(struct sk_buff *skb)
 
        rt = skb_rtable(skb);
 
-       if (opt->is_strictroute && rt->rt_uses_gateway)
+       if (opt->is_strictroute && rt->rt_gw_family)
                goto sr_failed;
 
        IPCB(skb)->flags |= IPSKB_FORWARDED;
index 10b35328cfbc6336f27396628822d8f8e0381329..a2bd4a6d9e6b6107e2a3c713328e40982bda5224 100644 (file)
@@ -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);
 
 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;
 
        /* OK, we know where to send it, allocate and build IP header. */
index e7338e421796a8151e62a454221ee9cb64ec4315..b77b4950d0c7cf7b5c3059c3e50209172ddda9af 100644 (file)
@@ -434,14 +434,13 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
                                           struct sk_buff *skb,
                                           const void *daddr)
 {
+       const struct rtable *rt = container_of(dst, struct rtable, dst);
        struct net_device *dev = dst->dev;
        const __be32 *pkey = daddr;
-       const struct rtable *rt;
        struct neighbour *n;
 
-       rt = (const struct rtable *) dst;
-       if (rt->rt_gateway)
-               pkey = (const __be32 *) &rt->rt_gateway;
+       if (rt->rt_gw_family == AF_INET)
+               pkey = (const __be32 *) &rt->rt_gw4;
        else if (skb)
                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)
 {
+       const struct rtable *rt = container_of(dst, struct rtable, dst);
        struct net_device *dev = dst->dev;
        const __be32 *pkey = daddr;
-       const struct rtable *rt;
 
-       rt = (const struct rtable *)dst;
-       if (rt->rt_gateway)
-               pkey = (const __be32 *)&rt->rt_gateway;
+       if (rt->rt_gw_family == AF_INET)
+               pkey = (const __be32 *)&rt->rt_gw4;
        else if (!daddr ||
                 (rt->rt_flags &
                  (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) {
                rt->rt_flags |= RTCF_REDIRECTED;
-               rt->rt_gateway = fnhe->fnhe_gw;
-               rt->rt_uses_gateway = 1;
+               rt->rt_gw_family = AF_INET;
+               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;
        }
 
-       if (rt->rt_gateway != old_gw)
+       if (rt->rt_gw_family != AF_INET || rt->rt_gw4 != old_gw)
                return;
 
        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);
 
        if (unlikely(ip_mtu_locked(dst))) {
-               if (rt->rt_uses_gateway && mtu > 576)
+               if (rt->rt_gw_family && mtu > 576)
                        mtu = 576;
        }
 
@@ -1410,8 +1408,10 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
                        orig = NULL;
                }
                fill_route_from_fnhe(rt, fnhe);
-               if (!rt->rt_gateway)
-                       rt->rt_gateway = daddr;
+               if (!rt->rt_gw4) {
+                       rt->rt_gw4 = daddr;
+                       rt->rt_gw_family = AF_INET;
+               }
 
                if (do_cache) {
                        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);
 
                if (nh->fib_nh_gw4 && nh->fib_nh_scope == RT_SCOPE_LINK) {
-                       rt->rt_gateway = nh->fib_nh_gw4;
-                       rt->rt_uses_gateway = 1;
+                       rt->rt_gw4 = nh->fib_nh_gw4;
+                       rt->rt_gw_family = AF_INET;
                }
                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
                         * route into the cache we really need to set it.
                         */
-                       if (!rt->rt_gateway)
-                               rt->rt_gateway = daddr;
+                       if (!rt->rt_gw4) {
+                               rt->rt_gw_family = AF_INET;
+                               rt->rt_gw4 = daddr;
+                       }
                        rt_add_uncached_list(rt);
                }
        } else
@@ -1591,8 +1593,8 @@ struct rtable *rt_dst_alloc(struct net_device *dev,
                rt->rt_iif = 0;
                rt->rt_pmtu = 0;
                rt->rt_mtu_locked = 0;
-               rt->rt_gateway = 0;
-               rt->rt_uses_gateway = 0;
+               rt->rt_gw_family = 0;
+               rt->rt_gw4 = 0;
                INIT_LIST_HEAD(&rt->rt_uncached);
 
                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_flags = ort->rt_flags;
                rt->rt_type = ort->rt_type;
-               rt->rt_gateway = ort->rt_gateway;
-               rt->rt_uses_gateway = ort->rt_uses_gateway;
+               rt->rt_gw_family = ort->rt_gw_family;
+               if (rt->rt_gw_family == AF_INET)
+                       rt->rt_gw4 = ort->rt_gw4;
 
                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))
                        goto nla_put_failure;
        }
-       if (rt->rt_uses_gateway &&
-           nla_put_in_addr(skb, RTA_GATEWAY, rt->rt_gateway))
+       if (rt->rt_gw_family == AF_INET &&
+           nla_put_in_addr(skb, RTA_GATEWAY, rt->rt_gw4))
                goto nla_put_failure;
 
        expires = rt->dst.expires;
index d73a6d6652f60f8b81d47bb36766aa0d0329f3ce..ee53a91526e55f0efba52312f2b5c0cf31b579c9 100644 (file)
@@ -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 |
                                              RTCF_LOCAL);
        xdst->u.rt.rt_type = rt->rt_type;
-       xdst->u.rt.rt_gateway = rt->rt_gateway;
-       xdst->u.rt.rt_uses_gateway = rt->rt_uses_gateway;
+       xdst->u.rt.rt_gw_family = rt->rt_gw_family;
+       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_mtu_locked = rt->rt_mtu_locked;
        INIT_LIST_HEAD(&xdst->u.rt.rt_uncached);
index f3a8557494d60e4d1ffe1f89fa32ea00c13eabab..1f61b4e53686e17511027aa81b9ab61f3b979a20 100644 (file)
@@ -137,10 +137,13 @@ static int mpls_xmit(struct sk_buff *skb)
 
        mpls_stats_inc_outucastpkts(out_dev, skb);
 
-       if (rt)
-               err = neigh_xmit(NEIGH_ARP_TABLE, out_dev, &rt->rt_gateway,
-                                skb);
-       else if (rt6) {
+       if (rt) {
+               if (rt->rt_gw_family == AF_INET)
+                       err = neigh_xmit(NEIGH_ARP_TABLE, out_dev, &rt->rt_gw4,
+                                        skb);
+               else
+                       err = -EAFNOSUPPORT;
+       } else if (rt6) {
                if (ipv6_addr_v4mapped(&rt6->rt6i_gateway)) {
                        /* 6PE (RFC 4798) */
                        err = neigh_xmit(NEIGH_ARP_TABLE, out_dev, &rt6->rt6i_gateway.s6_addr32[3],