Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9a997353 authored by Petr Machata's avatar Petr Machata Committed by David S. Miller
Browse files

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: default avatarPetr Machata <petrm@mellanox.com>
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5ff4ff4f
Loading
Loading
Loading
Loading
+44 −2
Original line number Diff line number Diff line
@@ -327,7 +327,7 @@ static inline size_t vxlan_nlmsg_size(void)
		+ 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 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);
}

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)
{
	struct vxlan_dev *vxlan = netdev_priv(dev);
+3 −0
Original line number Diff line number Diff line
@@ -145,6 +145,9 @@ enum switchdev_notifier_type {
	SWITCHDEV_FDB_ADD_TO_DEVICE,
	SWITCHDEV_FDB_DEL_TO_DEVICE,
	SWITCHDEV_FDB_OFFLOADED,

	SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE,
	SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE,
};

struct switchdev_notifier_info {
+11 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
#include <net/udp_tunnel.h>
#include <net/dst_metadata.h>
#include <net/rtnetlink.h>
#include <net/switchdev.h>

/* 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");
}

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