Commit 77d5bc7e authored by David Ahern's avatar David Ahern Committed by Jakub Kicinski

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: 1550c171 ("ipv4: Prepare rtable for IPv6 gateway")
Reported-by: default avatarJulian Anastasov <ja@ssi.bg>
Signed-off-by: default avatarDavid Ahern <dsahern@gmail.com>
Reviewed-by: default avatarJulian Anastasov <ja@ssi.bg>
Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
parent e84622ce
...@@ -352,7 +352,7 @@ static bool has_gateway(const struct dst_entry *dst, sa_family_t family) ...@@ -352,7 +352,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_gw_family == AF_INET; return rt->rt_uses_gateway;
} }
rt6 = container_of(dst, struct rt6_info, dst); rt6 = container_of(dst, struct rt6_info, dst);
......
...@@ -53,10 +53,11 @@ struct rtable { ...@@ -53,10 +53,11 @@ 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_gw_family; __u8 rt_uses_gateway;
int rt_iif; int rt_iif;
u8 rt_gw_family;
/* Info on neighbour */ /* Info on neighbour */
union { union {
__be32 rt_gw4; __be32 rt_gw4;
......
...@@ -560,7 +560,7 @@ struct dst_entry *inet_csk_route_req(const struct sock *sk, ...@@ -560,7 +560,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_gw_family) if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway)
goto route_err; goto route_err;
rcu_read_unlock(); rcu_read_unlock();
return &rt->dst; return &rt->dst;
...@@ -598,7 +598,7 @@ struct dst_entry *inet_csk_route_child_sock(const struct sock *sk, ...@@ -598,7 +598,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_gw_family) if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway)
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_gw_family) if (opt->is_strictroute && rt->rt_uses_gateway)
goto sr_failed; goto sr_failed;
IPCB(skb)->flags |= IPSKB_FORWARDED; IPCB(skb)->flags |= IPSKB_FORWARDED;
......
...@@ -499,7 +499,7 @@ int __ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, ...@@ -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); skb_dst_set_noref(skb, &rt->dst);
packet_routed: 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; 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. */
......
...@@ -635,6 +635,7 @@ static void fill_route_from_fnhe(struct rtable *rt, struct fib_nh_exception *fnh ...@@ -635,6 +635,7 @@ 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_uses_gateway = 1;
rt->rt_gw_family = AF_INET; rt->rt_gw_family = AF_INET;
rt->rt_gw4 = fnhe->fnhe_gw; rt->rt_gw4 = fnhe->fnhe_gw;
} }
...@@ -1313,7 +1314,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst) ...@@ -1313,7 +1314,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_gw_family && mtu > 576) if (rt->rt_uses_gateway && mtu > 576)
mtu = 576; mtu = 576;
} }
...@@ -1569,6 +1570,7 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr, ...@@ -1569,6 +1570,7 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr,
struct fib_nh_common *nhc = FIB_RES_NHC(*res); struct fib_nh_common *nhc = FIB_RES_NHC(*res);
if (nhc->nhc_gw_family && nhc->nhc_scope == RT_SCOPE_LINK) { if (nhc->nhc_gw_family && nhc->nhc_scope == RT_SCOPE_LINK) {
rt->rt_uses_gateway = 1;
rt->rt_gw_family = nhc->nhc_gw_family; rt->rt_gw_family = nhc->nhc_gw_family;
/* only INET and INET6 are supported */ /* only INET and INET6 are supported */
if (likely(nhc->nhc_gw_family == AF_INET)) if (likely(nhc->nhc_gw_family == AF_INET))
...@@ -1634,6 +1636,7 @@ struct rtable *rt_dst_alloc(struct net_device *dev, ...@@ -1634,6 +1636,7 @@ 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_uses_gateway = 0;
rt->rt_gw_family = 0; rt->rt_gw_family = 0;
rt->rt_gw4 = 0; rt->rt_gw4 = 0;
INIT_LIST_HEAD(&rt->rt_uncached); INIT_LIST_HEAD(&rt->rt_uncached);
...@@ -2694,6 +2697,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or ...@@ -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_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_uses_gateway = ort->rt_uses_gateway;
rt->rt_gw_family = ort->rt_gw_family; rt->rt_gw_family = ort->rt_gw_family;
if (rt->rt_gw_family == AF_INET) if (rt->rt_gw_family == AF_INET)
rt->rt_gw4 = ort->rt_gw4; rt->rt_gw4 = ort->rt_gw4;
...@@ -2778,21 +2782,23 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, ...@@ -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)) if (nla_put_in_addr(skb, RTA_PREFSRC, fl4->saddr))
goto nla_put_failure; goto nla_put_failure;
} }
if (rt->rt_gw_family == AF_INET && if (rt->rt_uses_gateway) {
nla_put_in_addr(skb, RTA_GATEWAY, rt->rt_gw4)) { if (rt->rt_gw_family == AF_INET &&
goto nla_put_failure; nla_put_in_addr(skb, RTA_GATEWAY, rt->rt_gw4)) {
} 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; goto nla_put_failure;
} else if (rt->rt_gw_family == AF_INET6) {
via = nla_data(nla); int alen = sizeof(struct in6_addr);
via->rtvia_family = AF_INET6; struct nlattr *nla;
memcpy(via->rtvia_addr, &rt->rt_gw6, alen); 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; expires = rt->dst.expires;
......
...@@ -85,6 +85,7 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, ...@@ -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 | 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_uses_gateway = rt->rt_uses_gateway;
xdst->u.rt.rt_gw_family = rt->rt_gw_family; xdst->u.rt.rt_gw_family = rt->rt_gw_family;
if (rt->rt_gw_family == AF_INET) if (rt->rt_gw_family == AF_INET)
xdst->u.rt.rt_gw4 = rt->rt_gw4; xdst->u.rt.rt_gw4 = rt->rt_gw4;
......
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