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

Commit 56eda01d authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'udp-tunnel-offloads-toggle'



Sabrina Dubroca says:

====================
Allow to switch off UDP-based tunnel offloads per netdevice

This patchset adds a new netdevice feature to toggle RX offloads of
UDP-based tunnel via ethtool. This is useful if the offload is causing
issues, for example if the hardware is buggy.

The feature is added to all devices providing the ->ndo_udp_tunnel_add
op, and enabled by default to preserve current behavior.

When the administrator disables this feature on a device, all
currently offloaded ports are cleared from the device.  When the
feature is turned on, the stack notifies the device about all current
ports.

v2:
 - rename feature bit to NETIF_F_RX_UDP_TUNNEL_PORT
 - rename ethtool feature to rx-udp_tunnel-port-offload
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5b861f6b 04584957
Loading
Loading
Loading
Loading
+18 −6
Original line number Diff line number Diff line
@@ -1016,16 +1016,22 @@ static struct device_type geneve_type = {
 * supply the listening GENEVE udp ports. Callers are expected
 * to implement the ndo_udp_tunnel_add.
 */
static void geneve_push_rx_ports(struct net_device *dev)
static void geneve_offload_rx_ports(struct net_device *dev, bool push)
{
	struct net *net = dev_net(dev);
	struct geneve_net *gn = net_generic(net, geneve_net_id);
	struct geneve_sock *gs;

	rcu_read_lock();
	list_for_each_entry_rcu(gs, &gn->sock_list, list)
	list_for_each_entry_rcu(gs, &gn->sock_list, list) {
		if (push) {
			udp_tunnel_push_rx_port(dev, gs->sock,
						UDP_TUNNEL_TYPE_GENEVE);
		} else {
			udp_tunnel_drop_rx_port(dev, gs->sock,
						UDP_TUNNEL_TYPE_GENEVE);
		}
	}
	rcu_read_unlock();
}

@@ -1560,8 +1566,14 @@ static int geneve_netdevice_event(struct notifier_block *unused,
{
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);

	if (event == NETDEV_UDP_TUNNEL_PUSH_INFO)
		geneve_push_rx_ports(dev);
	if (event == NETDEV_UDP_TUNNEL_PUSH_INFO ||
	    event == NETDEV_UDP_TUNNEL_DROP_INFO) {
		geneve_offload_rx_ports(dev, event == NETDEV_UDP_TUNNEL_PUSH_INFO);
	} else if (event == NETDEV_UNREGISTER) {
		geneve_offload_rx_ports(dev, false);
	} else if (event == NETDEV_REGISTER) {
		geneve_offload_rx_ports(dev, true);
	}

	return NOTIFY_DONE;
}
+22 −9
Original line number Diff line number Diff line
@@ -2608,7 +2608,7 @@ static struct device_type vxlan_type = {
 * supply the listening VXLAN udp ports. Callers are expected
 * to implement the ndo_udp_tunnel_add.
 */
static void vxlan_push_rx_ports(struct net_device *dev)
static void vxlan_offload_rx_ports(struct net_device *dev, bool push)
{
	struct vxlan_sock *vs;
	struct net *net = dev_net(dev);
@@ -2617,11 +2617,19 @@ static void vxlan_push_rx_ports(struct net_device *dev)

	spin_lock(&vn->sock_lock);
	for (i = 0; i < PORT_HASH_SIZE; ++i) {
		hlist_for_each_entry_rcu(vs, &vn->sock_list[i], hlist)
			udp_tunnel_push_rx_port(dev, vs->sock,
						(vs->flags & VXLAN_F_GPE) ?
						UDP_TUNNEL_TYPE_VXLAN_GPE :
						UDP_TUNNEL_TYPE_VXLAN);
		hlist_for_each_entry_rcu(vs, &vn->sock_list[i], hlist) {
			unsigned short type;

			if (vs->flags & VXLAN_F_GPE)
				type = UDP_TUNNEL_TYPE_VXLAN_GPE;
			else
				type = UDP_TUNNEL_TYPE_VXLAN;

			if (push)
				udp_tunnel_push_rx_port(dev, vs->sock, type);
			else
				udp_tunnel_drop_rx_port(dev, vs->sock, type);
		}
	}
	spin_unlock(&vn->sock_lock);
}
@@ -3630,10 +3638,15 @@ static int vxlan_netdevice_event(struct notifier_block *unused,
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
	struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);

	if (event == NETDEV_UNREGISTER)
	if (event == NETDEV_UNREGISTER) {
		vxlan_offload_rx_ports(dev, false);
		vxlan_handle_lowerdev_unregister(vn, dev);
	else if (event == NETDEV_UDP_TUNNEL_PUSH_INFO)
		vxlan_push_rx_ports(dev);
	} else if (event == NETDEV_REGISTER) {
		vxlan_offload_rx_ports(dev, true);
	} else if (event == NETDEV_UDP_TUNNEL_PUSH_INFO ||
		   event == NETDEV_UDP_TUNNEL_DROP_INFO) {
		vxlan_offload_rx_ports(dev, event == NETDEV_UDP_TUNNEL_PUSH_INFO);
	}

	return NOTIFY_DONE;
}
+2 −0
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ enum {
	NETIF_F_HW_TC_BIT,		/* Offload TC infrastructure */
	NETIF_F_HW_ESP_BIT,		/* Hardware ESP transformation offload */
	NETIF_F_HW_ESP_TX_CSUM_BIT,	/* ESP with TX checksum offload */
	NETIF_F_RX_UDP_TUNNEL_PORT_BIT, /* Offload of RX port for UDP tunnels */

	/*
	 * Add your fresh new feature above and remember to update
@@ -138,6 +139,7 @@ enum {
#define NETIF_F_HW_TC		__NETIF_F(HW_TC)
#define NETIF_F_HW_ESP		__NETIF_F(HW_ESP)
#define NETIF_F_HW_ESP_TX_CSUM	__NETIF_F(HW_ESP_TX_CSUM)
#define	NETIF_F_RX_UDP_TUNNEL_PORT  __NETIF_F(RX_UDP_TUNNEL_PORT)

#define for_each_netdev_feature(mask_addr, bit)	\
	for_each_set_bit(bit, (unsigned long *)mask_addr, NETDEV_FEATURE_COUNT)
+1 −0
Original line number Diff line number Diff line
@@ -2317,6 +2317,7 @@ struct netdev_lag_lower_state_info {
#define NETDEV_PRECHANGEUPPER	0x001A
#define NETDEV_CHANGELOWERSTATE	0x001B
#define NETDEV_UDP_TUNNEL_PUSH_INFO	0x001C
#define NETDEV_UDP_TUNNEL_DROP_INFO	0x001D
#define NETDEV_CHANGE_TX_QUEUE_LEN	0x001E

int register_netdevice_notifier(struct notifier_block *nb);
+8 −0
Original line number Diff line number Diff line
@@ -115,6 +115,8 @@ struct udp_tunnel_info {
/* Notify network devices of offloadable types */
void udp_tunnel_push_rx_port(struct net_device *dev, struct socket *sock,
			     unsigned short type);
void udp_tunnel_drop_rx_port(struct net_device *dev, struct socket *sock,
			     unsigned short type);
void udp_tunnel_notify_add_rx_port(struct socket *sock, unsigned short type);
void udp_tunnel_notify_del_rx_port(struct socket *sock, unsigned short type);

@@ -124,6 +126,12 @@ static inline void udp_tunnel_get_rx_info(struct net_device *dev)
	call_netdevice_notifiers(NETDEV_UDP_TUNNEL_PUSH_INFO, dev);
}

static inline void udp_tunnel_drop_rx_info(struct net_device *dev)
{
	ASSERT_RTNL();
	call_netdevice_notifiers(NETDEV_UDP_TUNNEL_DROP_INFO, dev);
}

/* Transmit the skb using UDP encapsulation. */
void udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb,
			 __be32 src, __be32 dst, __u8 tos, __u8 ttl,
Loading