]> git.baikalelectronics.ru Git - kernel.git/commitdiff
ipv4: Revert removal of rt_uses_gateway
authorDavid Ahern <dsahern@gmail.com>
Tue, 17 Sep 2019 17:39:49 +0000 (10:39 -0700)
committerJakub Kicinski <jakub.kicinski@netronome.com>
Sat, 21 Sep 2019 01:23:33 +0000 (18:23 -0700)
Julian noted that rt_uses_gateway has a more subtle use than 'is gateway
set':
    https://lore.kernel.org/netdev/alpine.LFD.2.21.1909151104060.2546@ja.home.ssi.bg/

Revert that part of the commit referenced in the Fixes tag.

Currently, there are no u8 holes in 'struct rtable'. There is a 4-byte hole
in the second cacheline which contains the gateway declaration. So move
rt_gw_family down to the gateway declarations since they are always used
together, and then re-use that u8 for rt_uses_gateway. End result is that
rtable size is unchanged.

Fixes: e653b65777bc ("ipv4: Prepare rtable for IPv6 gateway")
Reported-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: David Ahern <dsahern@gmail.com>
Reviewed-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
drivers/infiniband/core/addr.c
include/net/route.h
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

index 9b76a8fcdd2479bc696184eee6848fde6de8d994..bf539c34ccd3bb586859bb490c26cfaeff75d0c5 100644 (file)
@@ -352,7 +352,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_gw_family == AF_INET;
+               return rt->rt_uses_gateway;
        }
 
        rt6 = container_of(dst, struct rt6_info, dst);
index dfce19c9fa9618add7323eeee6e42e6d1a08ad84..6c516840380db2babc82ef05e2f2e3c49aaeafa3 100644 (file)
@@ -53,10 +53,11 @@ struct rtable {
        unsigned int            rt_flags;
        __u16                   rt_type;
        __u8                    rt_is_input;
-       u8                      rt_gw_family;
+       __u8                    rt_uses_gateway;
 
        int                     rt_iif;
 
+       u8                      rt_gw_family;
        /* Info on neighbour */
        union {
                __be32          rt_gw4;
index f5c163d4771be89628a25dd7f132f78afb95af6a..a9183543ca305e1723317a3dfd34af29087b605a 100644 (file)
@@ -560,7 +560,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_gw_family)
+       if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway)
                goto route_err;
        rcu_read_unlock();
        return &rt->dst;
@@ -598,7 +598,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_gw_family)
+       if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway)
                goto route_err;
        return &rt->dst;
 
index 06f6f280b9ff38864020e14a8a728b5258e65b0b..00ec819f949b5e76ea96be901a697f4e12d5cf4d 100644 (file)
@@ -123,7 +123,7 @@ int ip_forward(struct sk_buff *skb)
 
        rt = skb_rtable(skb);
 
-       if (opt->is_strictroute && rt->rt_gw_family)
+       if (opt->is_strictroute && rt->rt_uses_gateway)
                goto sr_failed;
 
        IPCB(skb)->flags |= IPSKB_FORWARDED;
index 5eb73775c3f7da2014bd658980d10d8a22960b6b..a77c3a4c24de40ff6bf3fa9da9a018457139e2b5 100644 (file)
@@ -499,7 +499,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_gw_family)
+       if (inet_opt && inet_opt->opt.is_strictroute && rt->rt_uses_gateway)
                goto no_route;
 
        /* OK, we know where to send it, allocate and build IP header. */
index b6a6f18c3dd144d2feb4b1841845bca5535092fc..7dcce724c78bd6bfbffb66671d594803031b13b6 100644 (file)
@@ -635,6 +635,7 @@ 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_uses_gateway = 1;
                rt->rt_gw_family = AF_INET;
                rt->rt_gw4 = fnhe->fnhe_gw;
        }
@@ -1313,7 +1314,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_gw_family && mtu > 576)
+               if (rt->rt_uses_gateway && mtu > 576)
                        mtu = 576;
        }
 
@@ -1569,6 +1570,7 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr,
                struct fib_nh_common *nhc = FIB_RES_NHC(*res);
 
                if (nhc->nhc_gw_family && nhc->nhc_scope == RT_SCOPE_LINK) {
+                       rt->rt_uses_gateway = 1;
                        rt->rt_gw_family = nhc->nhc_gw_family;
                        /* only INET and INET6 are supported */
                        if (likely(nhc->nhc_gw_family == AF_INET))
@@ -1634,6 +1636,7 @@ struct rtable *rt_dst_alloc(struct net_device *dev,
                rt->rt_iif = 0;
                rt->rt_pmtu = 0;
                rt->rt_mtu_locked = 0;
+               rt->rt_uses_gateway = 0;
                rt->rt_gw_family = 0;
                rt->rt_gw4 = 0;
                INIT_LIST_HEAD(&rt->rt_uncached);
@@ -2694,6 +2697,7 @@ 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_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;
@@ -2778,21 +2782,23 @@ 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_gw_family == AF_INET &&
-           nla_put_in_addr(skb, RTA_GATEWAY, rt->rt_gw4)) {
-               goto nla_put_failure;
-       } else if (rt->rt_gw_family == AF_INET6) {
-               int alen = sizeof(struct in6_addr);
-               struct nlattr *nla;
-               struct rtvia *via;
-
-               nla = nla_reserve(skb, RTA_VIA, alen + 2);
-               if (!nla)
+       if (rt->rt_uses_gateway) {
+               if (rt->rt_gw_family == AF_INET &&
+                   nla_put_in_addr(skb, RTA_GATEWAY, rt->rt_gw4)) {
                        goto nla_put_failure;
-
-               via = nla_data(nla);
-               via->rtvia_family = AF_INET6;
-               memcpy(via->rtvia_addr, &rt->rt_gw6, alen);
+               } else if (rt->rt_gw_family == AF_INET6) {
+                       int alen = sizeof(struct in6_addr);
+                       struct nlattr *nla;
+                       struct rtvia *via;
+
+                       nla = nla_reserve(skb, RTA_VIA, alen + 2);
+                       if (!nla)
+                               goto nla_put_failure;
+
+                       via = nla_data(nla);
+                       via->rtvia_family = AF_INET6;
+                       memcpy(via->rtvia_addr, &rt->rt_gw6, alen);
+               }
        }
 
        expires = rt->dst.expires;
index cdef8f9a3b0166942c3bad33b649dffa97578ca8..35b84b52b7027b35f65b36d6a0160913e8df2c5a 100644 (file)
@@ -85,6 +85,7 @@ 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_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;