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

Commit 897ca373 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'geneve-udp-port-offload'



Anjali Singhai Jain says:

====================
Add support for Geneve udp port offload

This patch series adds new ndo ops for Geneve add/del port, so as
to help offload Geneve tunnel functionalities such as RX checksum,
RSS, filters etc.

i40e driver has been tested with the changes to make sure the offloads
happen.

We do understand that this is not the ideal solution and most likely
will be redone with a more generic offload framework.
But this certainly will enable us to start seeing benefits of the
accelerations for Geneve tunnels.

As a side note, we did find an existing issue in i40e driver where a
service task can modify tunnel data structures with no locks held to
help linearize access. A separate patch will be taking care of that issue.

A question out to the community is regarding the driver Kconfig parameters
for VxLAN and Geneve, it would be ideal to drop those if there is a way
to help resolve vxlan/geneve_get_rx_port symbols while the tunnel modules
are not loaded.

Performance numbers:
With the offloads enable on X722 devices with remote checksum enabled
and no other tuning in terms of cpu governer etc on my test machine:

With offload
Throughput: 5527Mbits/sec with a single thread
%cpu: ~43% per core with 4 threads

Without offload
Throughput: 2364Mbits/sec with a single thread
%cpu: ~99% per core with 4 threads

These numbers will get better for X722 as it is being worked. But
this does bring out the delta in terms of when the stack is notified
with csum_level 1 and CHECKSUM_UNNECESSARY vs not without the RX offload.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 566178f8 cd866606
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -280,6 +280,16 @@ config I40E_VXLAN
	  Say Y here if you want to use Virtual eXtensible Local Area Network
	  Say Y here if you want to use Virtual eXtensible Local Area Network
	  (VXLAN) in the driver.
	  (VXLAN) in the driver.


config I40E_GENEVE
	bool "Generic Network Virtualization Encapsulation (GENEVE) Support"
	depends on I40E && GENEVE && !(I40E=y && GENEVE=m)
	default n
	---help---
	  This allows one to create GENEVE virtual interfaces that provide
	  Layer 2 Networks over Layer 3 Networks. GENEVE is often used
	  to tunnel virtual network infrastructure in virtualized environments.
	  Say Y here if you want to use GENEVE in the driver.

config I40E_DCB
config I40E_DCB
	bool "Data Center Bridging (DCB) Support"
	bool "Data Center Bridging (DCB) Support"
	default n
	default n
+9 −7
Original line number Original line Diff line number Diff line
@@ -245,6 +245,11 @@ struct i40e_tc_configuration {
	struct i40e_tc_info tc_info[I40E_MAX_TRAFFIC_CLASS];
	struct i40e_tc_info tc_info[I40E_MAX_TRAFFIC_CLASS];
};
};


struct i40e_udp_port_config {
	__be16 index;
	u8 type;
};

/* struct that defines the Ethernet device */
/* struct that defines the Ethernet device */
struct i40e_pf {
struct i40e_pf {
	struct pci_dev *pdev;
	struct pci_dev *pdev;
@@ -281,11 +286,9 @@ struct i40e_pf {
	u32 fd_atr_cnt;
	u32 fd_atr_cnt;
	u32 fd_tcp_rule;
	u32 fd_tcp_rule;


#ifdef CONFIG_I40E_VXLAN
	struct i40e_udp_port_config udp_ports[I40E_MAX_PF_UDP_OFFLOAD_PORTS];
	__be16  vxlan_ports[I40E_MAX_PF_UDP_OFFLOAD_PORTS];
	u16 pending_udp_bitmap;
	u16 pending_vxlan_bitmap;


#endif
	enum i40e_interrupt_policy int_policy;
	enum i40e_interrupt_policy int_policy;
	u16 rx_itr_default;
	u16 rx_itr_default;
	u16 tx_itr_default;
	u16 tx_itr_default;
@@ -322,9 +325,7 @@ struct i40e_pf {
#define I40E_FLAG_FD_ATR_ENABLED		BIT_ULL(22)
#define I40E_FLAG_FD_ATR_ENABLED		BIT_ULL(22)
#define I40E_FLAG_PTP				BIT_ULL(25)
#define I40E_FLAG_PTP				BIT_ULL(25)
#define I40E_FLAG_MFP_ENABLED			BIT_ULL(26)
#define I40E_FLAG_MFP_ENABLED			BIT_ULL(26)
#ifdef CONFIG_I40E_VXLAN
#define I40E_FLAG_UDP_FILTER_SYNC		BIT_ULL(27)
#define I40E_FLAG_VXLAN_FILTER_SYNC		BIT_ULL(27)
#endif
#define I40E_FLAG_PORT_ID_VALID			BIT_ULL(28)
#define I40E_FLAG_PORT_ID_VALID			BIT_ULL(28)
#define I40E_FLAG_DCB_CAPABLE			BIT_ULL(29)
#define I40E_FLAG_DCB_CAPABLE			BIT_ULL(29)
#define I40E_FLAG_RSS_AQ_CAPABLE		BIT_ULL(31)
#define I40E_FLAG_RSS_AQ_CAPABLE		BIT_ULL(31)
@@ -336,6 +337,7 @@ struct i40e_pf {
#define I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE	BIT_ULL(38)
#define I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE	BIT_ULL(38)
#define I40E_FLAG_LINK_POLLING_ENABLED		BIT_ULL(39)
#define I40E_FLAG_LINK_POLLING_ENABLED		BIT_ULL(39)
#define I40E_FLAG_VEB_MODE_ENABLED		BIT_ULL(40)
#define I40E_FLAG_VEB_MODE_ENABLED		BIT_ULL(40)
#define I40E_FLAG_GENEVE_OFFLOAD_CAPABLE	BIT_ULL(41)
#define I40E_FLAG_NO_PCI_LINK_CHECK		BIT_ULL(42)
#define I40E_FLAG_NO_PCI_LINK_CHECK		BIT_ULL(42)


	/* tracks features that get auto disabled by errors */
	/* tracks features that get auto disabled by errors */
+139 −31
Original line number Original line Diff line number Diff line
@@ -27,9 +27,12 @@
/* Local includes */
/* Local includes */
#include "i40e.h"
#include "i40e.h"
#include "i40e_diag.h"
#include "i40e_diag.h"
#ifdef CONFIG_I40E_VXLAN
#if IS_ENABLED(CONFIG_VXLAN)
#include <net/vxlan.h>
#include <net/vxlan.h>
#endif
#endif
#if IS_ENABLED(CONFIG_GENEVE)
#include <net/geneve.h>
#endif


const char i40e_driver_name[] = "i40e";
const char i40e_driver_name[] = "i40e";
static const char i40e_driver_string[] =
static const char i40e_driver_string[] =
@@ -5336,6 +5339,9 @@ int i40e_open(struct net_device *netdev)
#ifdef CONFIG_I40E_VXLAN
#ifdef CONFIG_I40E_VXLAN
	vxlan_get_rx_port(netdev);
	vxlan_get_rx_port(netdev);
#endif
#endif
#ifdef CONFIG_I40E_GENEVE
	geneve_get_rx_port(netdev);
#endif


	return 0;
	return 0;
}
}
@@ -7036,30 +7042,30 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
	i40e_flush(hw);
	i40e_flush(hw);
}
}


#ifdef CONFIG_I40E_VXLAN
/**
/**
 * i40e_sync_vxlan_filters_subtask - Sync the VSI filter list with HW
 * i40e_sync_udp_filters_subtask - Sync the VSI filter list with HW
 * @pf: board private structure
 * @pf: board private structure
 **/
 **/
static void i40e_sync_vxlan_filters_subtask(struct i40e_pf *pf)
static void i40e_sync_udp_filters_subtask(struct i40e_pf *pf)
{
{
#if IS_ENABLED(CONFIG_VXLAN) || IS_ENABLED(CONFIG_GENEVE)
	struct i40e_hw *hw = &pf->hw;
	struct i40e_hw *hw = &pf->hw;
	i40e_status ret;
	i40e_status ret;
	__be16 port;
	__be16 port;
	int i;
	int i;


	if (!(pf->flags & I40E_FLAG_VXLAN_FILTER_SYNC))
	if (!(pf->flags & I40E_FLAG_UDP_FILTER_SYNC))
		return;
		return;


	pf->flags &= ~I40E_FLAG_VXLAN_FILTER_SYNC;
	pf->flags &= ~I40E_FLAG_UDP_FILTER_SYNC;


	for (i = 0; i < I40E_MAX_PF_UDP_OFFLOAD_PORTS; i++) {
	for (i = 0; i < I40E_MAX_PF_UDP_OFFLOAD_PORTS; i++) {
		if (pf->pending_vxlan_bitmap & BIT_ULL(i)) {
		if (pf->pending_udp_bitmap & BIT_ULL(i)) {
			pf->pending_vxlan_bitmap &= ~BIT_ULL(i);
			pf->pending_udp_bitmap &= ~BIT_ULL(i);
			port = pf->vxlan_ports[i];
			port = pf->udp_ports[i].index;
			if (port)
			if (port)
				ret = i40e_aq_add_udp_tunnel(hw, ntohs(port),
				ret = i40e_aq_add_udp_tunnel(hw, ntohs(port),
						     I40E_AQC_TUNNEL_TYPE_VXLAN,
						     pf->udp_ports[i].type,
						     NULL, NULL);
						     NULL, NULL);
			else
			else
				ret = i40e_aq_del_udp_tunnel(hw, i, NULL);
				ret = i40e_aq_del_udp_tunnel(hw, i, NULL);
@@ -7072,13 +7078,13 @@ static void i40e_sync_vxlan_filters_subtask(struct i40e_pf *pf)
					 i40e_stat_str(&pf->hw, ret),
					 i40e_stat_str(&pf->hw, ret),
					 i40e_aq_str(&pf->hw,
					 i40e_aq_str(&pf->hw,
						    pf->hw.aq.asq_last_status));
						    pf->hw.aq.asq_last_status));
				pf->vxlan_ports[i] = 0;
				pf->udp_ports[i].index = 0;
			}
			}
		}
		}
	}
	}
#endif
}
}


#endif
/**
/**
 * i40e_service_task - Run the driver's async subtasks
 * i40e_service_task - Run the driver's async subtasks
 * @work: pointer to work_struct containing our data
 * @work: pointer to work_struct containing our data
@@ -7103,8 +7109,8 @@ static void i40e_service_task(struct work_struct *work)
	i40e_watchdog_subtask(pf);
	i40e_watchdog_subtask(pf);
	i40e_fdir_reinit_subtask(pf);
	i40e_fdir_reinit_subtask(pf);
	i40e_sync_filters_subtask(pf);
	i40e_sync_filters_subtask(pf);
#ifdef CONFIG_I40E_VXLAN
#if IS_ENABLED(CONFIG_VXLAN) || IS_ENABLED(CONFIG_GENEVE)
	i40e_sync_vxlan_filters_subtask(pf);
	i40e_sync_udp_filters_subtask(pf);
#endif
#endif
	i40e_clean_adminq_subtask(pf);
	i40e_clean_adminq_subtask(pf);


@@ -8380,7 +8386,8 @@ static int i40e_sw_init(struct i40e_pf *pf)
			     I40E_FLAG_HW_ATR_EVICT_CAPABLE |
			     I40E_FLAG_HW_ATR_EVICT_CAPABLE |
			     I40E_FLAG_OUTER_UDP_CSUM_CAPABLE |
			     I40E_FLAG_OUTER_UDP_CSUM_CAPABLE |
			     I40E_FLAG_WB_ON_ITR_CAPABLE |
			     I40E_FLAG_WB_ON_ITR_CAPABLE |
			     I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE;
			     I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE |
			     I40E_FLAG_GENEVE_OFFLOAD_CAPABLE;
	}
	}
	pf->eeprom_version = 0xDEAD;
	pf->eeprom_version = 0xDEAD;
	pf->lan_veb = I40E_NO_VEB;
	pf->lan_veb = I40E_NO_VEB;
@@ -8479,26 +8486,27 @@ static int i40e_set_features(struct net_device *netdev,
	return 0;
	return 0;
}
}


#ifdef CONFIG_I40E_VXLAN
#if IS_ENABLED(CONFIG_VXLAN) || IS_ENABLED(CONFIG_GENEVE)
/**
/**
 * i40e_get_vxlan_port_idx - Lookup a possibly offloaded for Rx UDP port
 * i40e_get_udp_port_idx - Lookup a possibly offloaded for Rx UDP port
 * @pf: board private structure
 * @pf: board private structure
 * @port: The UDP port to look up
 * @port: The UDP port to look up
 *
 *
 * Returns the index number or I40E_MAX_PF_UDP_OFFLOAD_PORTS if port not found
 * Returns the index number or I40E_MAX_PF_UDP_OFFLOAD_PORTS if port not found
 **/
 **/
static u8 i40e_get_vxlan_port_idx(struct i40e_pf *pf, __be16 port)
static u8 i40e_get_udp_port_idx(struct i40e_pf *pf, __be16 port)
{
{
	u8 i;
	u8 i;


	for (i = 0; i < I40E_MAX_PF_UDP_OFFLOAD_PORTS; i++) {
	for (i = 0; i < I40E_MAX_PF_UDP_OFFLOAD_PORTS; i++) {
		if (pf->vxlan_ports[i] == port)
		if (pf->udp_ports[i].index == port)
			return i;
			return i;
	}
	}


	return i;
	return i;
}
}


#endif
/**
/**
 * i40e_add_vxlan_port - Get notifications about VXLAN ports that come up
 * i40e_add_vxlan_port - Get notifications about VXLAN ports that come up
 * @netdev: This physical port's netdev
 * @netdev: This physical port's netdev
@@ -8508,6 +8516,7 @@ static u8 i40e_get_vxlan_port_idx(struct i40e_pf *pf, __be16 port)
static void i40e_add_vxlan_port(struct net_device *netdev,
static void i40e_add_vxlan_port(struct net_device *netdev,
				sa_family_t sa_family, __be16 port)
				sa_family_t sa_family, __be16 port)
{
{
#if IS_ENABLED(CONFIG_VXLAN)
	struct i40e_netdev_priv *np = netdev_priv(netdev);
	struct i40e_netdev_priv *np = netdev_priv(netdev);
	struct i40e_vsi *vsi = np->vsi;
	struct i40e_vsi *vsi = np->vsi;
	struct i40e_pf *pf = vsi->back;
	struct i40e_pf *pf = vsi->back;
@@ -8517,7 +8526,7 @@ static void i40e_add_vxlan_port(struct net_device *netdev,
	if (sa_family == AF_INET6)
	if (sa_family == AF_INET6)
		return;
		return;


	idx = i40e_get_vxlan_port_idx(pf, port);
	idx = i40e_get_udp_port_idx(pf, port);


	/* Check if port already exists */
	/* Check if port already exists */
	if (idx < I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
	if (idx < I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
@@ -8527,7 +8536,7 @@ static void i40e_add_vxlan_port(struct net_device *netdev,
	}
	}


	/* Now check if there is space to add the new port */
	/* Now check if there is space to add the new port */
	next_idx = i40e_get_vxlan_port_idx(pf, 0);
	next_idx = i40e_get_udp_port_idx(pf, 0);


	if (next_idx == I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
	if (next_idx == I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
		netdev_info(netdev, "maximum number of vxlan UDP ports reached, not adding port %d\n",
		netdev_info(netdev, "maximum number of vxlan UDP ports reached, not adding port %d\n",
@@ -8536,9 +8545,11 @@ static void i40e_add_vxlan_port(struct net_device *netdev,
	}
	}


	/* New port: add it and mark its index in the bitmap */
	/* New port: add it and mark its index in the bitmap */
	pf->vxlan_ports[next_idx] = port;
	pf->udp_ports[next_idx].index = port;
	pf->pending_vxlan_bitmap |= BIT_ULL(next_idx);
	pf->udp_ports[next_idx].type = I40E_AQC_TUNNEL_TYPE_VXLAN;
	pf->flags |= I40E_FLAG_VXLAN_FILTER_SYNC;
	pf->pending_udp_bitmap |= BIT_ULL(next_idx);
	pf->flags |= I40E_FLAG_UDP_FILTER_SYNC;
#endif
}
}


/**
/**
@@ -8550,6 +8561,7 @@ static void i40e_add_vxlan_port(struct net_device *netdev,
static void i40e_del_vxlan_port(struct net_device *netdev,
static void i40e_del_vxlan_port(struct net_device *netdev,
				sa_family_t sa_family, __be16 port)
				sa_family_t sa_family, __be16 port)
{
{
#if IS_ENABLED(CONFIG_VXLAN)
	struct i40e_netdev_priv *np = netdev_priv(netdev);
	struct i40e_netdev_priv *np = netdev_priv(netdev);
	struct i40e_vsi *vsi = np->vsi;
	struct i40e_vsi *vsi = np->vsi;
	struct i40e_pf *pf = vsi->back;
	struct i40e_pf *pf = vsi->back;
@@ -8558,23 +8570,108 @@ static void i40e_del_vxlan_port(struct net_device *netdev,
	if (sa_family == AF_INET6)
	if (sa_family == AF_INET6)
		return;
		return;


	idx = i40e_get_vxlan_port_idx(pf, port);
	idx = i40e_get_udp_port_idx(pf, port);


	/* Check if port already exists */
	/* Check if port already exists */
	if (idx < I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
	if (idx < I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
		/* if port exists, set it to 0 (mark for deletion)
		/* if port exists, set it to 0 (mark for deletion)
		 * and make it pending
		 * and make it pending
		 */
		 */
		pf->vxlan_ports[idx] = 0;
		pf->udp_ports[idx].index = 0;
		pf->pending_vxlan_bitmap |= BIT_ULL(idx);
		pf->pending_udp_bitmap |= BIT_ULL(idx);
		pf->flags |= I40E_FLAG_VXLAN_FILTER_SYNC;
		pf->flags |= I40E_FLAG_UDP_FILTER_SYNC;
	} else {
	} else {
		netdev_warn(netdev, "vxlan port %d was not found, not deleting\n",
		netdev_warn(netdev, "vxlan port %d was not found, not deleting\n",
			    ntohs(port));
			    ntohs(port));
	}
	}
#endif
}

/**
 * i40e_add_geneve_port - Get notifications about GENEVE ports that come up
 * @netdev: This physical port's netdev
 * @sa_family: Socket Family that GENEVE is notifying us about
 * @port: New UDP port number that GENEVE started listening to
 **/
static void i40e_add_geneve_port(struct net_device *netdev,
				 sa_family_t sa_family, __be16 port)
{
#if IS_ENABLED(CONFIG_GENEVE)
	struct i40e_netdev_priv *np = netdev_priv(netdev);
	struct i40e_vsi *vsi = np->vsi;
	struct i40e_pf *pf = vsi->back;
	u8 next_idx;
	u8 idx;

	if (sa_family == AF_INET6)
		return;

	idx = i40e_get_udp_port_idx(pf, port);

	/* Check if port already exists */
	if (idx < I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
		netdev_info(netdev, "udp port %d already offloaded\n",
			    ntohs(port));
		return;
	}
	}


	/* Now check if there is space to add the new port */
	next_idx = i40e_get_udp_port_idx(pf, 0);

	if (next_idx == I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
		netdev_info(netdev, "maximum number of UDP ports reached, not adding port %d\n",
			    ntohs(port));
		return;
	}

	/* New port: add it and mark its index in the bitmap */
	pf->udp_ports[next_idx].index = port;
	pf->udp_ports[next_idx].type = I40E_AQC_TUNNEL_TYPE_NGE;
	pf->pending_udp_bitmap |= BIT_ULL(next_idx);
	pf->flags |= I40E_FLAG_UDP_FILTER_SYNC;

	dev_info(&pf->pdev->dev, "adding geneve port %d\n", ntohs(port));
#endif
#endif
}

/**
 * i40e_del_geneve_port - Get notifications about GENEVE ports that go away
 * @netdev: This physical port's netdev
 * @sa_family: Socket Family that GENEVE is notifying us about
 * @port: UDP port number that GENEVE stopped listening to
 **/
static void i40e_del_geneve_port(struct net_device *netdev,
				 sa_family_t sa_family, __be16 port)
{
#if IS_ENABLED(CONFIG_GENEVE)
	struct i40e_netdev_priv *np = netdev_priv(netdev);
	struct i40e_vsi *vsi = np->vsi;
	struct i40e_pf *pf = vsi->back;
	u8 idx;

	if (sa_family == AF_INET6)
		return;

	idx = i40e_get_udp_port_idx(pf, port);

	/* Check if port already exists */
	if (idx < I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
		/* if port exists, set it to 0 (mark for deletion)
		 * and make it pending
		 */
		pf->udp_ports[idx].index = 0;
		pf->pending_udp_bitmap |= BIT_ULL(idx);
		pf->flags |= I40E_FLAG_UDP_FILTER_SYNC;

		dev_info(&pf->pdev->dev, "deleting geneve port %d\n",
			 ntohs(port));
	} else {
		netdev_warn(netdev, "geneve port %d was not found, not deleting\n",
			    ntohs(port));
	}
#endif
}

static int i40e_get_phys_port_id(struct net_device *netdev,
static int i40e_get_phys_port_id(struct net_device *netdev,
				 struct netdev_phys_item_id *ppid)
				 struct netdev_phys_item_id *ppid)
{
{
@@ -8752,7 +8849,10 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
				       nlflags, 0, 0, filter_mask, NULL);
				       nlflags, 0, 0, filter_mask, NULL);
}
}


#define I40E_MAX_TUNNEL_HDR_LEN 80
/* Hardware supports L4 tunnel length of 128B (=2^7) which includes
 * inner mac plus all inner ethertypes.
 */
#define I40E_MAX_TUNNEL_HDR_LEN 128
/**
/**
 * i40e_features_check - Validate encapsulated packet conforms to limits
 * i40e_features_check - Validate encapsulated packet conforms to limits
 * @skb: skb buff
 * @skb: skb buff
@@ -8764,7 +8864,7 @@ static netdev_features_t i40e_features_check(struct sk_buff *skb,
					     netdev_features_t features)
					     netdev_features_t features)
{
{
	if (skb->encapsulation &&
	if (skb->encapsulation &&
	    (skb_inner_mac_header(skb) - skb_transport_header(skb) >
	    ((skb_inner_network_header(skb) - skb_transport_header(skb)) >
	     I40E_MAX_TUNNEL_HDR_LEN))
	     I40E_MAX_TUNNEL_HDR_LEN))
		return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
		return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);


@@ -8799,9 +8899,13 @@ static const struct net_device_ops i40e_netdev_ops = {
	.ndo_get_vf_config	= i40e_ndo_get_vf_config,
	.ndo_get_vf_config	= i40e_ndo_get_vf_config,
	.ndo_set_vf_link_state	= i40e_ndo_set_vf_link_state,
	.ndo_set_vf_link_state	= i40e_ndo_set_vf_link_state,
	.ndo_set_vf_spoofchk	= i40e_ndo_set_vf_spoofchk,
	.ndo_set_vf_spoofchk	= i40e_ndo_set_vf_spoofchk,
#ifdef CONFIG_I40E_VXLAN
#if IS_ENABLED(CONFIG_VXLAN)
	.ndo_add_vxlan_port	= i40e_add_vxlan_port,
	.ndo_add_vxlan_port	= i40e_add_vxlan_port,
	.ndo_del_vxlan_port	= i40e_del_vxlan_port,
	.ndo_del_vxlan_port	= i40e_del_vxlan_port,
#endif
#if IS_ENABLED(CONFIG_GENEVE)
	.ndo_add_geneve_port	= i40e_add_geneve_port,
	.ndo_del_geneve_port	= i40e_del_geneve_port,
#endif
#endif
	.ndo_get_phys_port_id	= i40e_get_phys_port_id,
	.ndo_get_phys_port_id	= i40e_get_phys_port_id,
	.ndo_fdb_add		= i40e_ndo_fdb_add,
	.ndo_fdb_add		= i40e_ndo_fdb_add,
@@ -8836,6 +8940,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
	np->vsi = vsi;
	np->vsi = vsi;


	netdev->hw_enc_features |= NETIF_F_IP_CSUM	 |
	netdev->hw_enc_features |= NETIF_F_IP_CSUM	 |
				  NETIF_F_RXCSUM	 |
				  NETIF_F_GSO_UDP_TUNNEL |
				  NETIF_F_GSO_UDP_TUNNEL |
				  NETIF_F_GSO_GRE	 |
				  NETIF_F_GSO_GRE	 |
				  NETIF_F_TSO;
				  NETIF_F_TSO;
@@ -10348,6 +10453,9 @@ static void i40e_print_features(struct i40e_pf *pf)
		i += snprintf(&buf[i], REMAIN(i), " DCB");
		i += snprintf(&buf[i], REMAIN(i), " DCB");
#if IS_ENABLED(CONFIG_VXLAN)
#if IS_ENABLED(CONFIG_VXLAN)
	i += snprintf(&buf[i], REMAIN(i), " VxLAN");
	i += snprintf(&buf[i], REMAIN(i), " VxLAN");
#endif
#if IS_ENABLED(CONFIG_GENEVE)
	i += snprintf(&buf[i], REMAIN(i), " Geneve");
#endif
#endif
	if (pf->flags & I40E_FLAG_PTP)
	if (pf->flags & I40E_FLAG_PTP)
		i += snprintf(&buf[i], REMAIN(i), " PTP");
		i += snprintf(&buf[i], REMAIN(i), " PTP");
+4 −4
Original line number Original line Diff line number Diff line
@@ -1380,7 +1380,7 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
	if (rx_error & BIT(I40E_RX_DESC_ERROR_PPRS_SHIFT))
	if (rx_error & BIT(I40E_RX_DESC_ERROR_PPRS_SHIFT))
		return;
		return;


	/* If VXLAN traffic has an outer UDPv4 checksum we need to check
	/* If VXLAN/GENEVE traffic has an outer UDPv4 checksum we need to check
	 * it in the driver, hardware does not do it for us.
	 * it in the driver, hardware does not do it for us.
	 * Since L3L4P bit was set we assume a valid IHL value (>=5)
	 * Since L3L4P bit was set we assume a valid IHL value (>=5)
	 * so the total length of IPv4 header is IHL*4 bytes
	 * so the total length of IPv4 header is IHL*4 bytes
@@ -2001,7 +2001,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
	if (!(tx_flags & (I40E_TX_FLAGS_IPV4 | I40E_TX_FLAGS_IPV6)))
	if (!(tx_flags & (I40E_TX_FLAGS_IPV4 | I40E_TX_FLAGS_IPV6)))
		return;
		return;


	if (!(tx_flags & I40E_TX_FLAGS_VXLAN_TUNNEL)) {
	if (!(tx_flags & I40E_TX_FLAGS_UDP_TUNNEL)) {
		/* snag network header to get L4 type and address */
		/* snag network header to get L4 type and address */
		hdr.network = skb_network_header(skb);
		hdr.network = skb_network_header(skb);


@@ -2086,7 +2086,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
		     I40E_TXD_FLTR_QW1_FD_STATUS_SHIFT;
		     I40E_TXD_FLTR_QW1_FD_STATUS_SHIFT;


	dtype_cmd |= I40E_TXD_FLTR_QW1_CNT_ENA_MASK;
	dtype_cmd |= I40E_TXD_FLTR_QW1_CNT_ENA_MASK;
	if (!(tx_flags & I40E_TX_FLAGS_VXLAN_TUNNEL))
	if (!(tx_flags & I40E_TX_FLAGS_UDP_TUNNEL))
		dtype_cmd |=
		dtype_cmd |=
			((u32)I40E_FD_ATR_STAT_IDX(pf->hw.pf_id) <<
			((u32)I40E_FD_ATR_STAT_IDX(pf->hw.pf_id) <<
			I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT) &
			I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT) &
@@ -2319,7 +2319,7 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
			oudph = udp_hdr(skb);
			oudph = udp_hdr(skb);
			oiph = ip_hdr(skb);
			oiph = ip_hdr(skb);
			l4_tunnel = I40E_TXD_CTX_UDP_TUNNELING;
			l4_tunnel = I40E_TXD_CTX_UDP_TUNNELING;
			*tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL;
			*tx_flags |= I40E_TX_FLAGS_UDP_TUNNEL;
			break;
			break;
		case IPPROTO_GRE:
		case IPPROTO_GRE:
			l4_tunnel = I40E_TXD_CTX_GRE_TUNNELING;
			l4_tunnel = I40E_TXD_CTX_GRE_TUNNELING;
+1 −1
Original line number Original line Diff line number Diff line
@@ -163,7 +163,7 @@ enum i40e_dyn_idx_t {
#define I40E_TX_FLAGS_FSO		BIT(7)
#define I40E_TX_FLAGS_FSO		BIT(7)
#define I40E_TX_FLAGS_TSYN		BIT(8)
#define I40E_TX_FLAGS_TSYN		BIT(8)
#define I40E_TX_FLAGS_FD_SB		BIT(9)
#define I40E_TX_FLAGS_FD_SB		BIT(9)
#define I40E_TX_FLAGS_VXLAN_TUNNEL	BIT(10)
#define I40E_TX_FLAGS_UDP_TUNNEL	BIT(10)
#define I40E_TX_FLAGS_VLAN_MASK		0xffff0000
#define I40E_TX_FLAGS_VLAN_MASK		0xffff0000
#define I40E_TX_FLAGS_VLAN_PRIO_MASK	0xe0000000
#define I40E_TX_FLAGS_VLAN_PRIO_MASK	0xe0000000
#define I40E_TX_FLAGS_VLAN_PRIO_SHIFT	29
#define I40E_TX_FLAGS_VLAN_PRIO_SHIFT	29
Loading