Skip to content

Commit 24b2c37

Browse files
ecree-solarflaredavem330
authored andcommitted
sfc: advertise encapsulated offloads on EF10
Necessitates an .ndo_features_check, as the EF10 datapath has several limitations on what it can handle. Signed-off-by: Edward Cree <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0ce8df6 commit 24b2c37

File tree

4 files changed

+104
-0
lines changed

4 files changed

+104
-0
lines changed

drivers/net/ethernet/sfc/ef10.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,6 +1304,7 @@ static void efx_ef10_fini_nic(struct efx_nic *efx)
13041304
static int efx_ef10_init_nic(struct efx_nic *efx)
13051305
{
13061306
struct efx_ef10_nic_data *nic_data = efx->nic_data;
1307+
netdev_features_t hw_enc_features = 0;
13071308
int rc;
13081309

13091310
if (nic_data->must_check_datapath_caps) {
@@ -1348,6 +1349,21 @@ static int efx_ef10_init_nic(struct efx_nic *efx)
13481349
nic_data->must_restore_piobufs = false;
13491350
}
13501351

1352+
/* add encapsulated checksum offload features */
1353+
if (efx_has_cap(efx, VXLAN_NVGRE) && !efx_ef10_is_vf(efx))
1354+
hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
1355+
/* add encapsulated TSO features */
1356+
if (efx_has_cap(efx, TX_TSO_V2_ENCAP)) {
1357+
netdev_features_t encap_tso_features;
1358+
1359+
encap_tso_features = NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE |
1360+
NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM;
1361+
1362+
hw_enc_features |= encap_tso_features | NETIF_F_TSO;
1363+
efx->net_dev->features |= encap_tso_features;
1364+
}
1365+
efx->net_dev->hw_enc_features = hw_enc_features;
1366+
13511367
/* don't fail init if RSS setup doesn't work */
13521368
rc = efx->type->rx_push_rss_config(efx, false,
13531369
efx->rss_context.rx_indir_table, NULL);

drivers/net/ethernet/sfc/efx.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@ static const struct net_device_ops efx_netdev_ops = {
596596
.ndo_set_mac_address = efx_set_mac_address,
597597
.ndo_set_rx_mode = efx_set_rx_mode,
598598
.ndo_set_features = efx_set_features,
599+
.ndo_features_check = efx_features_check,
599600
.ndo_vlan_rx_add_vid = efx_vlan_rx_add_vid,
600601
.ndo_vlan_rx_kill_vid = efx_vlan_rx_kill_vid,
601602
#ifdef CONFIG_SFC_SRIOV

drivers/net/ethernet/sfc/efx_common.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "net_driver.h"
1212
#include <linux/module.h>
1313
#include <linux/netdevice.h>
14+
#include <net/gre.h>
1415
#include "efx_common.h"
1516
#include "efx_channels.h"
1617
#include "efx.h"
@@ -1287,6 +1288,89 @@ const struct pci_error_handlers efx_err_handlers = {
12871288
.resume = efx_io_resume,
12881289
};
12891290

1291+
/* Determine whether the NIC will be able to handle TX offloads for a given
1292+
* encapsulated packet.
1293+
*/
1294+
static bool efx_can_encap_offloads(struct efx_nic *efx, struct sk_buff *skb)
1295+
{
1296+
struct gre_base_hdr *greh;
1297+
__be16 dst_port;
1298+
u8 ipproto;
1299+
1300+
/* Does the NIC support encap offloads?
1301+
* If not, we should never get here, because we shouldn't have
1302+
* advertised encap offload feature flags in the first place.
1303+
*/
1304+
if (WARN_ON_ONCE(!efx->type->udp_tnl_has_port))
1305+
return false;
1306+
1307+
/* Determine encapsulation protocol in use */
1308+
switch (skb->protocol) {
1309+
case htons(ETH_P_IP):
1310+
ipproto = ip_hdr(skb)->protocol;
1311+
break;
1312+
case htons(ETH_P_IPV6):
1313+
/* If there are extension headers, this will cause us to
1314+
* think we can't offload something that we maybe could have.
1315+
*/
1316+
ipproto = ipv6_hdr(skb)->nexthdr;
1317+
break;
1318+
default:
1319+
/* Not IP, so can't offload it */
1320+
return false;
1321+
}
1322+
switch (ipproto) {
1323+
case IPPROTO_GRE:
1324+
/* We support NVGRE but not IP over GRE or random gretaps.
1325+
* Specifically, the NIC will accept GRE as encapsulated if
1326+
* the inner protocol is Ethernet, but only handle it
1327+
* correctly if the GRE header is 8 bytes long. Moreover,
1328+
* it will not update the Checksum or Sequence Number fields
1329+
* if they are present. (The Routing Present flag,
1330+
* GRE_ROUTING, cannot be set else the header would be more
1331+
* than 8 bytes long; so we don't have to worry about it.)
1332+
*/
1333+
if (skb->inner_protocol_type != ENCAP_TYPE_ETHER)
1334+
return false;
1335+
if (ntohs(skb->inner_protocol) != ETH_P_TEB)
1336+
return false;
1337+
if (skb_inner_mac_header(skb) - skb_transport_header(skb) != 8)
1338+
return false;
1339+
greh = (struct gre_base_hdr *)skb_transport_header(skb);
1340+
return !(greh->flags & (GRE_CSUM | GRE_SEQ));
1341+
case IPPROTO_UDP:
1342+
/* If the port is registered for a UDP tunnel, we assume the
1343+
* packet is for that tunnel, and the NIC will handle it as
1344+
* such. If not, the NIC won't know what to do with it.
1345+
*/
1346+
dst_port = udp_hdr(skb)->dest;
1347+
return efx->type->udp_tnl_has_port(efx, dst_port);
1348+
default:
1349+
return false;
1350+
}
1351+
}
1352+
1353+
netdev_features_t efx_features_check(struct sk_buff *skb, struct net_device *dev,
1354+
netdev_features_t features)
1355+
{
1356+
struct efx_nic *efx = netdev_priv(dev);
1357+
1358+
if (skb->encapsulation) {
1359+
if (features & NETIF_F_GSO_MASK)
1360+
/* Hardware can only do TSO with at most 208 bytes
1361+
* of headers.
1362+
*/
1363+
if (skb_inner_transport_offset(skb) >
1364+
EFX_TSO2_MAX_HDRLEN)
1365+
features &= ~(NETIF_F_GSO_MASK);
1366+
if (features & (NETIF_F_GSO_MASK | NETIF_F_CSUM_MASK))
1367+
if (!efx_can_encap_offloads(efx, skb))
1368+
features &= ~(NETIF_F_GSO_MASK |
1369+
NETIF_F_CSUM_MASK);
1370+
}
1371+
return features;
1372+
}
1373+
12901374
int efx_get_phys_port_id(struct net_device *net_dev,
12911375
struct netdev_phys_item_id *ppid)
12921376
{

drivers/net/ethernet/sfc/efx_common.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ int efx_change_mtu(struct net_device *net_dev, int new_mtu);
105105

106106
extern const struct pci_error_handlers efx_err_handlers;
107107

108+
netdev_features_t efx_features_check(struct sk_buff *skb, struct net_device *dev,
109+
netdev_features_t features);
110+
108111
int efx_get_phys_port_id(struct net_device *net_dev,
109112
struct netdev_phys_item_id *ppid);
110113

0 commit comments

Comments
 (0)