mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	vxlan: Add switchdev notifications
When offloading VXLAN devices, drivers need to know about events in VXLAN FDB database. Since VXLAN models a bridge, it is natural to distribute the VXLAN FDB notifications using the pre-existing switchdev notification mechanism. To that end, introduce two new notification types: SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE and SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE. Introduce a new function, vxlan_fdb_switchdev_call_notifiers() to send the new notifier types, and a struct switchdev_notifier_vxlan_fdb_info to communicate the details of the FDB entry under consideration. Invoke the new function from vxlan_fdb_notify(). Signed-off-by: Petr Machata <petrm@mellanox.com> Signed-off-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									5ff4ff4fe8
								
							
						
					
					
						commit
						9a99735317
					
				
					 3 changed files with 58 additions and 2 deletions
				
			
		| 
						 | 
					@ -327,7 +327,7 @@ static inline size_t vxlan_nlmsg_size(void)
 | 
				
			||||||
		+ nla_total_size(sizeof(struct nda_cacheinfo));
 | 
							+ nla_total_size(sizeof(struct nda_cacheinfo));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb,
 | 
					static void __vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb,
 | 
				
			||||||
			       struct vxlan_rdst *rd, int type)
 | 
								       struct vxlan_rdst *rd, int type)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net *net = dev_net(vxlan->dev);
 | 
						struct net *net = dev_net(vxlan->dev);
 | 
				
			||||||
| 
						 | 
					@ -353,6 +353,48 @@ static void vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb,
 | 
				
			||||||
		rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
 | 
							rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void vxlan_fdb_switchdev_call_notifiers(struct vxlan_dev *vxlan,
 | 
				
			||||||
 | 
										       struct vxlan_fdb *fdb,
 | 
				
			||||||
 | 
										       struct vxlan_rdst *rd,
 | 
				
			||||||
 | 
										       bool adding)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct switchdev_notifier_vxlan_fdb_info info;
 | 
				
			||||||
 | 
						enum switchdev_notifier_type notifier_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (WARN_ON(!rd))
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						notifier_type = adding ? SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE
 | 
				
			||||||
 | 
								       : SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						info = (struct switchdev_notifier_vxlan_fdb_info){
 | 
				
			||||||
 | 
							.remote_ip = rd->remote_ip,
 | 
				
			||||||
 | 
							.remote_port = rd->remote_port,
 | 
				
			||||||
 | 
							.remote_vni = rd->remote_vni,
 | 
				
			||||||
 | 
							.remote_ifindex = rd->remote_ifindex,
 | 
				
			||||||
 | 
							.vni = fdb->vni,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						memcpy(info.eth_addr, fdb->eth_addr, ETH_ALEN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						call_switchdev_notifiers(notifier_type, vxlan->dev,
 | 
				
			||||||
 | 
									 &info.info);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb,
 | 
				
			||||||
 | 
								     struct vxlan_rdst *rd, int type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (type) {
 | 
				
			||||||
 | 
						case RTM_NEWNEIGH:
 | 
				
			||||||
 | 
							vxlan_fdb_switchdev_call_notifiers(vxlan, fdb, rd, true);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case RTM_DELNEIGH:
 | 
				
			||||||
 | 
							vxlan_fdb_switchdev_call_notifiers(vxlan, fdb, rd, false);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						__vxlan_fdb_notify(vxlan, fdb, rd, type);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void vxlan_ip_miss(struct net_device *dev, union vxlan_addr *ipa)
 | 
					static void vxlan_ip_miss(struct net_device *dev, union vxlan_addr *ipa)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct vxlan_dev *vxlan = netdev_priv(dev);
 | 
						struct vxlan_dev *vxlan = netdev_priv(dev);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -145,6 +145,9 @@ enum switchdev_notifier_type {
 | 
				
			||||||
	SWITCHDEV_FDB_ADD_TO_DEVICE,
 | 
						SWITCHDEV_FDB_ADD_TO_DEVICE,
 | 
				
			||||||
	SWITCHDEV_FDB_DEL_TO_DEVICE,
 | 
						SWITCHDEV_FDB_DEL_TO_DEVICE,
 | 
				
			||||||
	SWITCHDEV_FDB_OFFLOADED,
 | 
						SWITCHDEV_FDB_OFFLOADED,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE,
 | 
				
			||||||
 | 
						SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct switchdev_notifier_info {
 | 
					struct switchdev_notifier_info {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@
 | 
				
			||||||
#include <net/udp_tunnel.h>
 | 
					#include <net/udp_tunnel.h>
 | 
				
			||||||
#include <net/dst_metadata.h>
 | 
					#include <net/dst_metadata.h>
 | 
				
			||||||
#include <net/rtnetlink.h>
 | 
					#include <net/rtnetlink.h>
 | 
				
			||||||
 | 
					#include <net/switchdev.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* VXLAN protocol (RFC 7348) header:
 | 
					/* VXLAN protocol (RFC 7348) header:
 | 
				
			||||||
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
					 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
				
			||||||
| 
						 | 
					@ -409,4 +410,14 @@ static inline bool netif_is_vxlan(const struct net_device *dev)
 | 
				
			||||||
	       !strcmp(dev->rtnl_link_ops->kind, "vxlan");
 | 
						       !strcmp(dev->rtnl_link_ops->kind, "vxlan");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct switchdev_notifier_vxlan_fdb_info {
 | 
				
			||||||
 | 
						struct switchdev_notifier_info info; /* must be first */
 | 
				
			||||||
 | 
						union vxlan_addr remote_ip;
 | 
				
			||||||
 | 
						__be16 remote_port;
 | 
				
			||||||
 | 
						__be32 remote_vni;
 | 
				
			||||||
 | 
						u32 remote_ifindex;
 | 
				
			||||||
 | 
						u8 eth_addr[ETH_ALEN];
 | 
				
			||||||
 | 
						__be32 vni;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue