--- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -90,6 +90,20 @@ struct vxlan_fdb { /* salt for hash table */ static u32 vxlan_salt __read_mostly; +ATOMIC_NOTIFIER_HEAD(vxlan_fdb_notifier_list); + +void vxlan_fdb_register_notify(struct notifier_block *nb) +{ + atomic_notifier_chain_register(&vxlan_fdb_notifier_list, nb); +} +EXPORT_SYMBOL(vxlan_fdb_register_notify); + +void vxlan_fdb_unregister_notify(struct notifier_block *nb) +{ + atomic_notifier_chain_unregister(&vxlan_fdb_notifier_list, nb); +} +EXPORT_SYMBOL(vxlan_fdb_unregister_notify); + static inline bool vxlan_collect_metadata(struct vxlan_sock *vs) { return vs->flags & VXLAN_F_COLLECT_METADATA || @@ -367,6 +381,7 @@ static void __vxlan_fdb_notify(struct vx { struct net *net = dev_net(vxlan->dev); struct sk_buff *skb; + struct vxlan_fdb_event vfe; int err = -ENOBUFS; skb = nlmsg_new(vxlan_nlmsg_size(), GFP_ATOMIC); @@ -382,6 +397,10 @@ static void __vxlan_fdb_notify(struct vx } rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); + vfe.dev = vxlan->dev; + vfe.rdst = rd; + ether_addr_copy(vfe.eth_addr, fdb->eth_addr); + atomic_notifier_call_chain(&vxlan_fdb_notifier_list, type, (void *)&vfe); return; errout: if (err < 0) @@ -548,6 +567,18 @@ static struct vxlan_fdb *vxlan_find_mac( return f; } +/* Find and update age of fdb entry corresponding to MAC. */ +void vxlan_fdb_update_mac(struct vxlan_dev *vxlan, const u8 *mac, uint32_t vni) +{ + u32 hash_index; + + hash_index = fdb_head_index(vxlan, mac, vni); + spin_lock_bh(&vxlan->hash_lock[hash_index]); + vxlan_find_mac(vxlan, mac, vni); + spin_unlock_bh(&vxlan->hash_lock[hash_index]); +} +EXPORT_SYMBOL(vxlan_fdb_update_mac); + /* caller should hold vxlan->hash_lock */ static struct vxlan_rdst *vxlan_fdb_find_rdst(struct vxlan_fdb *f, union vxlan_addr *ip, __be16 port, @@ -2750,6 +2781,9 @@ static void vxlan_xmit_one(struct sk_buf goto out_unlock; } + /* Reset the skb_iif to Tunnels interface index */ + skb->skb_iif = dev->ifindex; + tos = ip_tunnel_ecn_encap(tos, old_iph, skb); ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); err = vxlan_build_skb(skb, ndst, sizeof(struct iphdr), @@ -2821,6 +2855,9 @@ static void vxlan_xmit_one(struct sk_buf if (err < 0) goto tx_error; + /* Reset the skb_iif to Tunnels interface index */ + skb->skb_iif = dev->ifindex; + udp_tunnel6_xmit_skb(ndst, sock6->sock->sk, skb, dev, &local_ip.sin6.sin6_addr, &dst->sin6.sin6_addr, tos, ttl, --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -293,6 +293,19 @@ struct vxlan_dev { VXLAN_F_UDP_ZERO_CSUM6_RX | \ VXLAN_F_COLLECT_METADATA) +/* + * Application data for fdb notifier event + */ +struct vxlan_fdb_event { + struct net_device *dev; + struct vxlan_rdst *rdst; + u8 eth_addr[ETH_ALEN]; +}; + +extern void vxlan_fdb_register_notify(struct notifier_block *nb); +extern void vxlan_fdb_unregister_notify(struct notifier_block *nb); +extern void vxlan_fdb_update_mac(struct vxlan_dev *vxlan, const u8 *mac, uint32_t vni); + struct net_device *vxlan_dev_create(struct net *net, const char *name, u8 name_assign_type, struct vxlan_config *conf); @@ -381,6 +394,15 @@ static inline __be32 vxlan_compute_rco(u return vni_field; } +/* + * vxlan_get_vni() + * Returns the vni corresponding to tunnel + */ +static inline u32 vxlan_get_vni(struct vxlan_dev *vxlan_tun) +{ + return be32_to_cpu(vxlan_tun->cfg.vni); +} + static inline unsigned short vxlan_get_sk_family(struct vxlan_sock *vs) { return vs->sock->sk->sk_family;