Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ipv4: Revert removal of rt_uses_gateway

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: 1550c171935d ("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>

authored by

David Ahern and committed by
Jakub Kicinski
77d5bc7e e84622ce

+28 -20
+1 -1
drivers/infiniband/core/addr.c
··· 352 352 353 353 if (family == AF_INET) { 354 354 rt = container_of(dst, struct rtable, dst); 355 - return rt->rt_gw_family == AF_INET; 355 + return rt->rt_uses_gateway; 356 356 } 357 357 358 358 rt6 = container_of(dst, struct rt6_info, dst);
+2 -1
include/net/route.h
··· 53 53 unsigned int rt_flags; 54 54 __u16 rt_type; 55 55 __u8 rt_is_input; 56 - u8 rt_gw_family; 56 + __u8 rt_uses_gateway; 57 57 58 58 int rt_iif; 59 59 60 + u8 rt_gw_family; 60 61 /* Info on neighbour */ 61 62 union { 62 63 __be32 rt_gw4;
+2 -2
net/ipv4/inet_connection_sock.c
··· 560 560 rt = ip_route_output_flow(net, fl4, sk); 561 561 if (IS_ERR(rt)) 562 562 goto no_route; 563 - if (opt && opt->opt.is_strictroute && rt->rt_gw_family) 563 + if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway) 564 564 goto route_err; 565 565 rcu_read_unlock(); 566 566 return &rt->dst; ··· 598 598 rt = ip_route_output_flow(net, fl4, sk); 599 599 if (IS_ERR(rt)) 600 600 goto no_route; 601 - if (opt && opt->opt.is_strictroute && rt->rt_gw_family) 601 + if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway) 602 602 goto route_err; 603 603 return &rt->dst; 604 604
+1 -1
net/ipv4/ip_forward.c
··· 123 123 124 124 rt = skb_rtable(skb); 125 125 126 - if (opt->is_strictroute && rt->rt_gw_family) 126 + if (opt->is_strictroute && rt->rt_uses_gateway) 127 127 goto sr_failed; 128 128 129 129 IPCB(skb)->flags |= IPSKB_FORWARDED;
+1 -1
net/ipv4/ip_output.c
··· 499 499 skb_dst_set_noref(skb, &rt->dst); 500 500 501 501 packet_routed: 502 - if (inet_opt && inet_opt->opt.is_strictroute && rt->rt_gw_family) 502 + if (inet_opt && inet_opt->opt.is_strictroute && rt->rt_uses_gateway) 503 503 goto no_route; 504 504 505 505 /* OK, we know where to send it, allocate and build IP header. */
+20 -14
net/ipv4/route.c
··· 635 635 636 636 if (fnhe->fnhe_gw) { 637 637 rt->rt_flags |= RTCF_REDIRECTED; 638 + rt->rt_uses_gateway = 1; 638 639 rt->rt_gw_family = AF_INET; 639 640 rt->rt_gw4 = fnhe->fnhe_gw; 640 641 } ··· 1314 1313 mtu = READ_ONCE(dst->dev->mtu); 1315 1314 1316 1315 if (unlikely(ip_mtu_locked(dst))) { 1317 - if (rt->rt_gw_family && mtu > 576) 1316 + if (rt->rt_uses_gateway && mtu > 576) 1318 1317 mtu = 576; 1319 1318 } 1320 1319 ··· 1570 1569 struct fib_nh_common *nhc = FIB_RES_NHC(*res); 1571 1570 1572 1571 if (nhc->nhc_gw_family && nhc->nhc_scope == RT_SCOPE_LINK) { 1572 + rt->rt_uses_gateway = 1; 1573 1573 rt->rt_gw_family = nhc->nhc_gw_family; 1574 1574 /* only INET and INET6 are supported */ 1575 1575 if (likely(nhc->nhc_gw_family == AF_INET)) ··· 1636 1634 rt->rt_iif = 0; 1637 1635 rt->rt_pmtu = 0; 1638 1636 rt->rt_mtu_locked = 0; 1637 + rt->rt_uses_gateway = 0; 1639 1638 rt->rt_gw_family = 0; 1640 1639 rt->rt_gw4 = 0; 1641 1640 INIT_LIST_HEAD(&rt->rt_uncached); ··· 2697 2694 rt->rt_genid = rt_genid_ipv4(net); 2698 2695 rt->rt_flags = ort->rt_flags; 2699 2696 rt->rt_type = ort->rt_type; 2697 + rt->rt_uses_gateway = ort->rt_uses_gateway; 2700 2698 rt->rt_gw_family = ort->rt_gw_family; 2701 2699 if (rt->rt_gw_family == AF_INET) 2702 2700 rt->rt_gw4 = ort->rt_gw4; ··· 2782 2778 if (nla_put_in_addr(skb, RTA_PREFSRC, fl4->saddr)) 2783 2779 goto nla_put_failure; 2784 2780 } 2785 - if (rt->rt_gw_family == AF_INET && 2786 - nla_put_in_addr(skb, RTA_GATEWAY, rt->rt_gw4)) { 2787 - goto nla_put_failure; 2788 - } else if (rt->rt_gw_family == AF_INET6) { 2789 - int alen = sizeof(struct in6_addr); 2790 - struct nlattr *nla; 2791 - struct rtvia *via; 2792 - 2793 - nla = nla_reserve(skb, RTA_VIA, alen + 2); 2794 - if (!nla) 2781 + if (rt->rt_uses_gateway) { 2782 + if (rt->rt_gw_family == AF_INET && 2783 + nla_put_in_addr(skb, RTA_GATEWAY, rt->rt_gw4)) { 2795 2784 goto nla_put_failure; 2785 + } else if (rt->rt_gw_family == AF_INET6) { 2786 + int alen = sizeof(struct in6_addr); 2787 + struct nlattr *nla; 2788 + struct rtvia *via; 2796 2789 2797 - via = nla_data(nla); 2798 - via->rtvia_family = AF_INET6; 2799 - memcpy(via->rtvia_addr, &rt->rt_gw6, alen); 2790 + nla = nla_reserve(skb, RTA_VIA, alen + 2); 2791 + if (!nla) 2792 + goto nla_put_failure; 2793 + 2794 + via = nla_data(nla); 2795 + via->rtvia_family = AF_INET6; 2796 + memcpy(via->rtvia_addr, &rt->rt_gw6, alen); 2797 + } 2800 2798 } 2801 2799 2802 2800 expires = rt->dst.expires;
+1
net/ipv4/xfrm4_policy.c
··· 85 85 xdst->u.rt.rt_flags = rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST | 86 86 RTCF_LOCAL); 87 87 xdst->u.rt.rt_type = rt->rt_type; 88 + xdst->u.rt.rt_uses_gateway = rt->rt_uses_gateway; 88 89 xdst->u.rt.rt_gw_family = rt->rt_gw_family; 89 90 if (rt->rt_gw_family == AF_INET) 90 91 xdst->u.rt.rt_gw4 = rt->rt_gw4;