|
@@ -957,16 +957,24 @@ out:
|
|
*/
|
|
*/
|
|
static bool vxlan_snoop(struct net_device *dev,
|
|
static bool vxlan_snoop(struct net_device *dev,
|
|
union vxlan_addr *src_ip, const u8 *src_mac,
|
|
union vxlan_addr *src_ip, const u8 *src_mac,
|
|
- __be32 vni)
|
|
|
|
|
|
+ u32 src_ifindex, __be32 vni)
|
|
{
|
|
{
|
|
struct vxlan_dev *vxlan = netdev_priv(dev);
|
|
struct vxlan_dev *vxlan = netdev_priv(dev);
|
|
struct vxlan_fdb *f;
|
|
struct vxlan_fdb *f;
|
|
|
|
+ u32 ifindex = 0;
|
|
|
|
+
|
|
|
|
+#if IS_ENABLED(CONFIG_IPV6)
|
|
|
|
+ if (src_ip->sa.sa_family == AF_INET6 &&
|
|
|
|
+ (ipv6_addr_type(&src_ip->sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL))
|
|
|
|
+ ifindex = src_ifindex;
|
|
|
|
+#endif
|
|
|
|
|
|
f = vxlan_find_mac(vxlan, src_mac, vni);
|
|
f = vxlan_find_mac(vxlan, src_mac, vni);
|
|
if (likely(f)) {
|
|
if (likely(f)) {
|
|
struct vxlan_rdst *rdst = first_remote_rcu(f);
|
|
struct vxlan_rdst *rdst = first_remote_rcu(f);
|
|
|
|
|
|
- if (likely(vxlan_addr_equal(&rdst->remote_ip, src_ip)))
|
|
|
|
|
|
+ if (likely(vxlan_addr_equal(&rdst->remote_ip, src_ip) &&
|
|
|
|
+ rdst->remote_ifindex == ifindex))
|
|
return false;
|
|
return false;
|
|
|
|
|
|
/* Don't migrate static entries, drop packets */
|
|
/* Don't migrate static entries, drop packets */
|
|
@@ -993,7 +1001,7 @@ static bool vxlan_snoop(struct net_device *dev,
|
|
vxlan->cfg.dst_port,
|
|
vxlan->cfg.dst_port,
|
|
vni,
|
|
vni,
|
|
vxlan->default_dst.remote_vni,
|
|
vxlan->default_dst.remote_vni,
|
|
- 0, NTF_SELF);
|
|
|
|
|
|
+ ifindex, NTF_SELF);
|
|
spin_unlock(&vxlan->hash_lock);
|
|
spin_unlock(&vxlan->hash_lock);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1264,6 +1272,7 @@ static bool vxlan_set_mac(struct vxlan_dev *vxlan,
|
|
struct sk_buff *skb, __be32 vni)
|
|
struct sk_buff *skb, __be32 vni)
|
|
{
|
|
{
|
|
union vxlan_addr saddr;
|
|
union vxlan_addr saddr;
|
|
|
|
+ u32 ifindex = skb->dev->ifindex;
|
|
|
|
|
|
skb_reset_mac_header(skb);
|
|
skb_reset_mac_header(skb);
|
|
skb->protocol = eth_type_trans(skb, vxlan->dev);
|
|
skb->protocol = eth_type_trans(skb, vxlan->dev);
|
|
@@ -1285,7 +1294,7 @@ static bool vxlan_set_mac(struct vxlan_dev *vxlan,
|
|
}
|
|
}
|
|
|
|
|
|
if ((vxlan->cfg.flags & VXLAN_F_LEARN) &&
|
|
if ((vxlan->cfg.flags & VXLAN_F_LEARN) &&
|
|
- vxlan_snoop(skb->dev, &saddr, eth_hdr(skb)->h_source, vni))
|
|
|
|
|
|
+ vxlan_snoop(skb->dev, &saddr, eth_hdr(skb)->h_source, ifindex, vni))
|
|
return false;
|
|
return false;
|
|
|
|
|
|
return true;
|
|
return true;
|
|
@@ -1994,7 +2003,8 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
|
|
}
|
|
}
|
|
|
|
|
|
if (dst_vxlan->cfg.flags & VXLAN_F_LEARN)
|
|
if (dst_vxlan->cfg.flags & VXLAN_F_LEARN)
|
|
- vxlan_snoop(skb->dev, &loopback, eth_hdr(skb)->h_source, vni);
|
|
|
|
|
|
+ vxlan_snoop(skb->dev, &loopback, eth_hdr(skb)->h_source, 0,
|
|
|
|
+ vni);
|
|
|
|
|
|
u64_stats_update_begin(&tx_stats->syncp);
|
|
u64_stats_update_begin(&tx_stats->syncp);
|
|
tx_stats->tx_packets++;
|
|
tx_stats->tx_packets++;
|