Commit db53cd3d authored by David Ahern's avatar David Ahern Committed by Jakub Kicinski
Browse files

net: Handle l3mdev in ip_tunnel_init_flow



Ido reported that the commit referenced in the Fixes tag broke
a gre use case with dummy devices. Add a check to ip_tunnel_init_flow
to see if the oif is an l3mdev port and if so set the oif to 0 to
avoid the oif comparison in fib_lookup_good_nhc.

Fixes: 40867d74 ("net: Add l3mdev index to flow struct and avoid oif reset for port devices")
Reported-by: default avatarIdo Schimmel <idosch@idosch.org>
Signed-off-by: default avatarDavid Ahern <dsahern@kernel.org>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 83daab06
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -423,7 +423,7 @@ mlxsw_sp_span_gretap4_route(const struct net_device *to_dev,

	parms = mlxsw_sp_ipip_netdev_parms4(to_dev);
	ip_tunnel_init_flow(&fl4, parms.iph.protocol, *daddrp, *saddrp,
			    0, 0, parms.link, tun->fwmark, 0);
			    0, 0, dev_net(to_dev), parms.link, tun->fwmark, 0);

	rt = ip_route_output_key(tun->net, &fl4);
	if (IS_ERR(rt))
+9 −2
Original line number Diff line number Diff line
@@ -243,11 +243,18 @@ static inline __be32 tunnel_id_to_key32(__be64 tun_id)
static inline void ip_tunnel_init_flow(struct flowi4 *fl4,
				       int proto,
				       __be32 daddr, __be32 saddr,
				       __be32 key, __u8 tos, int oif,
				       __be32 key, __u8 tos,
				       struct net *net, int oif,
				       __u32 mark, __u32 tun_inner_hash)
{
	memset(fl4, 0, sizeof(*fl4));
	fl4->flowi4_oif = oif;

	if (oif) {
		fl4->flowi4_l3mdev = l3mdev_master_upper_ifindex_by_index_rcu(net, oif);
		/* Legacy VRF/l3mdev use case */
		fl4->flowi4_oif = fl4->flowi4_l3mdev ? 0 : oif;
	}

	fl4->daddr = daddr;
	fl4->saddr = saddr;
	fl4->flowi4_tos = tos;
+2 −2
Original line number Diff line number Diff line
@@ -605,8 +605,8 @@ static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
	key = &info->key;
	ip_tunnel_init_flow(&fl4, IPPROTO_GRE, key->u.ipv4.dst, key->u.ipv4.src,
			    tunnel_id_to_key32(key->tun_id),
			    key->tos & ~INET_ECN_MASK, 0, skb->mark,
			    skb_get_hash(skb));
			    key->tos & ~INET_ECN_MASK, dev_net(dev), 0,
			    skb->mark, skb_get_hash(skb));
	rt = ip_route_output_key(dev_net(dev), &fl4);
	if (IS_ERR(rt))
		return PTR_ERR(rt);
+5 −4
Original line number Diff line number Diff line
@@ -294,8 +294,8 @@ static int ip_tunnel_bind_dev(struct net_device *dev)

		ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr,
				    iph->saddr, tunnel->parms.o_key,
				    RT_TOS(iph->tos), tunnel->parms.link,
				    tunnel->fwmark, 0);
				    RT_TOS(iph->tos), dev_net(dev),
				    tunnel->parms.link, tunnel->fwmark, 0);
		rt = ip_route_output_key(tunnel->net, &fl4);

		if (!IS_ERR(rt)) {
@@ -570,7 +570,7 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
	}
	ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src,
			    tunnel_id_to_key32(key->tun_id), RT_TOS(tos),
			    0, skb->mark, skb_get_hash(skb));
			    dev_net(dev), 0, skb->mark, skb_get_hash(skb));
	if (tunnel->encap.type != TUNNEL_ENCAP_NONE)
		goto tx_error;

@@ -726,7 +726,8 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
	}

	ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr,
			    tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link,
			    tunnel->parms.o_key, RT_TOS(tos),
			    dev_net(dev), tunnel->parms.link,
			    tunnel->fwmark, skb_get_hash(skb));

	if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0)