Commit 58189ca7 authored by David Ahern's avatar David Ahern Committed by David S. Miller

net: Fix vti use case with oif in dst lookups

Steffen reported that the recent change to add oif to dst lookups breaks
the VTI use case. The problem is that with the oif set in the flow struct
the comparison to the nh_oif is triggered. Fix by splitting the
FLOWI_FLAG_VRFSRC into 2 flags -- one that triggers the vrf device cache
bypass (FLOWI_FLAG_VRFSRC) and another telling the lookup to not compare
nh oif (FLOWI_FLAG_SKIP_NH_OIF).

Fixes: 42a7b32b ("xfrm: Add oif to dst lookups")
Signed-off-by: default avatarDavid Ahern <dsa@cumulusnetworks.com>
Acked-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d828755e
...@@ -193,7 +193,8 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb, ...@@ -193,7 +193,8 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb,
.flowi4_oif = vrf_dev->ifindex, .flowi4_oif = vrf_dev->ifindex,
.flowi4_iif = LOOPBACK_IFINDEX, .flowi4_iif = LOOPBACK_IFINDEX,
.flowi4_tos = RT_TOS(ip4h->tos), .flowi4_tos = RT_TOS(ip4h->tos),
.flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_VRFSRC, .flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_VRFSRC |
FLOWI_FLAG_SKIP_NH_OIF,
.daddr = ip4h->daddr, .daddr = ip4h->daddr,
}; };
......
...@@ -35,6 +35,7 @@ struct flowi_common { ...@@ -35,6 +35,7 @@ struct flowi_common {
#define FLOWI_FLAG_ANYSRC 0x01 #define FLOWI_FLAG_ANYSRC 0x01
#define FLOWI_FLAG_KNOWN_NH 0x02 #define FLOWI_FLAG_KNOWN_NH 0x02
#define FLOWI_FLAG_VRFSRC 0x04 #define FLOWI_FLAG_VRFSRC 0x04
#define FLOWI_FLAG_SKIP_NH_OIF 0x08
__u32 flowic_secid; __u32 flowic_secid;
struct flowi_tunnel flowic_tun_key; struct flowi_tunnel flowic_tun_key;
}; };
......
...@@ -255,7 +255,7 @@ static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst, __be32 ...@@ -255,7 +255,7 @@ static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst, __be32
flow_flags |= FLOWI_FLAG_ANYSRC; flow_flags |= FLOWI_FLAG_ANYSRC;
if (netif_index_is_vrf(sock_net(sk), oif)) if (netif_index_is_vrf(sock_net(sk), oif))
flow_flags |= FLOWI_FLAG_VRFSRC; flow_flags |= FLOWI_FLAG_VRFSRC | FLOWI_FLAG_SKIP_NH_OIF;
flowi4_init_output(fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE, flowi4_init_output(fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE,
protocol, flow_flags, dst, src, dport, sport); protocol, flow_flags, dst, src, dport, sport);
......
...@@ -1426,7 +1426,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, ...@@ -1426,7 +1426,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
nh->nh_flags & RTNH_F_LINKDOWN && nh->nh_flags & RTNH_F_LINKDOWN &&
!(fib_flags & FIB_LOOKUP_IGNORE_LINKSTATE)) !(fib_flags & FIB_LOOKUP_IGNORE_LINKSTATE))
continue; continue;
if (!(flp->flowi4_flags & FLOWI_FLAG_VRFSRC)) { if (!(flp->flowi4_flags & FLOWI_FLAG_SKIP_NH_OIF)) {
if (flp->flowi4_oif && if (flp->flowi4_oif &&
flp->flowi4_oif != nh->nh_oif) flp->flowi4_oif != nh->nh_oif)
continue; continue;
......
...@@ -1024,7 +1024,8 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) ...@@ -1024,7 +1024,8 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
if (netif_index_is_vrf(net, ipc.oif)) { if (netif_index_is_vrf(net, ipc.oif)) {
flowi4_init_output(fl4, ipc.oif, sk->sk_mark, tos, flowi4_init_output(fl4, ipc.oif, sk->sk_mark, tos,
RT_SCOPE_UNIVERSE, sk->sk_protocol, RT_SCOPE_UNIVERSE, sk->sk_protocol,
(flow_flags | FLOWI_FLAG_VRFSRC), (flow_flags | FLOWI_FLAG_VRFSRC |
FLOWI_FLAG_SKIP_NH_OIF),
faddr, saddr, dport, faddr, saddr, dport,
inet->inet_sport); inet->inet_sport);
......
...@@ -33,6 +33,8 @@ static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4, ...@@ -33,6 +33,8 @@ static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,
if (saddr) if (saddr)
fl4->saddr = saddr->a4; fl4->saddr = saddr->a4;
fl4->flowi4_flags = FLOWI_FLAG_SKIP_NH_OIF;
rt = __ip_route_output_key(net, fl4); rt = __ip_route_output_key(net, fl4);
if (!IS_ERR(rt)) if (!IS_ERR(rt))
return &rt->dst; return &rt->dst;
......
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