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.
Unified · Split
| @@ -423,7 +423,7 @@ mlxsw_sp_span_gretap4_route(const struct net_device *to_dev, · 422 unmodified lines | ||
| 423 | 423 | |
| 424 | 424 | parms = mlxsw_sp_ipip_netdev_parms4(to_dev); |
| 425 | 425 | ip_tunnel_init_flow(&fl4, parms.iph.protocol, *daddrp, *saddrp, |
| 426 | − 0, 0, parms.link, tun->fwmark, 0); | |
| 426 | + 0, 0, dev_net(to_dev), parms.link, tun->fwmark, 0); | |
| 427 | 427 | |
| 428 | 428 | rt = ip_route_output_key(tun->net, &fl4); |
| 429 | 429 | if (IS_ERR(rt)) |
| @@ -243,11 +243,18 @@ static inline __be32 tunnel_id_to_key32(__be64 tun_id) · 242 unmodified lines | ||
| 243 | 243 | static inline void ip_tunnel_init_flow(struct flowi4 *fl4, |
| 244 | 244 | int proto, |
| 245 | 245 | __be32 daddr, __be32 saddr, |
| 246 | − __be32 key, __u8 tos, int oif, | |
| 246 | + __be32 key, __u8 tos, | |
| 247 | + struct net *net, int oif, | |
| 247 | 248 | __u32 mark, __u32 tun_inner_hash) |
| 248 | 249 | { |
| 249 | 250 | memset(fl4, 0, sizeof(*fl4)); |
| 250 | − fl4->flowi4_oif = oif; | |
| 251 | + | |
| 252 | + if (oif) { | |
| 253 | + fl4->flowi4_l3mdev = l3mdev_master_upper_ifindex_by_index_rcu(net, oif); | |
| 254 | + /* Legacy VRF/l3mdev use case */ | |
| 255 | + fl4->flowi4_oif = fl4->flowi4_l3mdev ? 0 : oif; | |
| 256 | + } | |
| 257 | + | |
| 251 | 258 | fl4->daddr = daddr; |
| 252 | 259 | fl4->saddr = saddr; |
| 253 | 260 | fl4->flowi4_tos = tos; |
| @@ -605,8 +605,8 @@ static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) · 604 unmodified lines | ||
| 605 | 605 | key = &info->key; |
| 606 | 606 | ip_tunnel_init_flow(&fl4, IPPROTO_GRE, key->u.ipv4.dst, key->u.ipv4.src, |
| 607 | 607 | tunnel_id_to_key32(key->tun_id), |
| 608 | − key->tos & ~INET_ECN_MASK, 0, skb->mark, | |
| 609 | − skb_get_hash(skb)); | |
| 608 | + key->tos & ~INET_ECN_MASK, dev_net(dev), 0, | |
| 609 | + skb->mark, skb_get_hash(skb)); | |
| 610 | 610 | rt = ip_route_output_key(dev_net(dev), &fl4); |
| 611 | 611 | if (IS_ERR(rt)) |
| 612 | 612 | return PTR_ERR(rt); |
| @@ -294,8 +294,8 @@ static int ip_tunnel_bind_dev(struct net_device *dev) · 293 unmodified lines | ||
| 294 | 294 | |
| 295 | 295 | ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr, |
| 296 | 296 | iph->saddr, tunnel->parms.o_key, |
| 297 | − RT_TOS(iph->tos), tunnel->parms.link, | |
| 298 | − tunnel->fwmark, 0); | |
| 297 | + RT_TOS(iph->tos), dev_net(dev), | |
| 298 | + tunnel->parms.link, tunnel->fwmark, 0); | |
| 299 | 299 | rt = ip_route_output_key(tunnel->net, &fl4); |
| 300 | 300 | |
| 301 | 301 | if (!IS_ERR(rt)) { |
| @@ -570,7 +570,7 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, · 268 unmodified lines | ||
| 570 | 570 | } |
| 571 | 571 | ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src, |
| 572 | 572 | tunnel_id_to_key32(key->tun_id), RT_TOS(tos), |
| 573 | − 0, skb->mark, skb_get_hash(skb)); | |
| 573 | + dev_net(dev), 0, skb->mark, skb_get_hash(skb)); | |
| 574 | 574 | if (tunnel->encap.type != TUNNEL_ENCAP_NONE) |
| 575 | 575 | goto tx_error; |
| 576 | 576 | |
| @@ -726,7 +726,8 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, · 149 unmodified lines | ||
| 726 | 726 | } |
| 727 | 727 | |
| 728 | 728 | ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr, |
| 729 | − tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link, | |
| 729 | + tunnel->parms.o_key, RT_TOS(tos), | |
| 730 | + dev_net(dev), tunnel->parms.link, | |
| 730 | 731 | tunnel->fwmark, skb_get_hash(skb)); |
| 731 | 732 | |
| 732 | 733 | if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0) |