Skip to content

Commit b4fb2d3

Browse files
jdamato-fslyanguy11
authored andcommitted
i40e: Add support for MPLS + TSO
This change adds support for TSO of MPLS packets. In my tests with tcpdump it seems to work. Note this test setup has a 9000 byte MTU: MPLS (label 100, exp 0, [S], ttl 64) IP srcip.50086 > dstip.1234: Flags [P.], seq 593345:644401, ack 0, win 420, options [nop,nop,TS val 45022534 ecr 1722291395], length 51056 IP dstip.1234 > srcip.50086: Flags [.], ack 593345, win 122, options [nop,nop,TS val 1722291395 ecr 45022534], length 0 IP dstip.1234 > srcip.50086: Flags [.], ack 602289, win 105, options [nop,nop,TS val 1722291395 ecr 45022534], length 0 IP dstip.1234 > srcip.50086: Flags [.], ack 620177, win 71, options [nop,nop,TS val 1722291395 ecr 45022534], length 0 MPLS (label 100, exp 0, [S], ttl 64) IP srcip.50086 > dstip.1234: Flags [P.], seq 644401:655953, ack 0, win 420, options [nop,nop,TS val 45022534 ecr 1722291395], length 11552 IP dstip.1234 > srcip.50086: Flags [.], ack 638065, win 37, options [nop,nop,TS val 1722291395 ecr 45022534], length 0 IP dstip.1234 > srcip.50086: Flags [.], ack 644401, win 25, options [nop,nop,TS val 1722291395 ecr 45022534], length 0 IP dstip.1234 > srcip.50086: Flags [.], ack 653345, win 8, options [nop,nop,TS val 1722291395 ecr 45022534], length 0 IP dstip.1234 > srcip.50086: Flags [.], ack 655953, win 3, options [nop,nop,TS val 1722291395 ecr 45022534], length 0 Signed-off-by: Joe Damato <[email protected]> Co-developed-by: Mike Gallo <[email protected]> Signed-off-by: Mike Gallo <[email protected]> Tested-by: Gurucharan <[email protected]> (A Contingent worker at Intel) Signed-off-by: Tony Nguyen <[email protected]>
1 parent 590032a commit b4fb2d3

File tree

2 files changed

+48
-19
lines changed

2 files changed

+48
-19
lines changed

drivers/net/ethernet/intel/i40e/i40e_main.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13436,8 +13436,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
1343613436
np->vsi = vsi;
1343713437

1343813438
hw_enc_features = NETIF_F_SG |
13439-
NETIF_F_IP_CSUM |
13440-
NETIF_F_IPV6_CSUM |
13439+
NETIF_F_HW_CSUM |
1344113440
NETIF_F_HIGHDMA |
1344213441
NETIF_F_SOFT_FEATURES |
1344313442
NETIF_F_TSO |
@@ -13468,6 +13467,23 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
1346813467
/* record features VLANs can make use of */
1346913468
netdev->vlan_features |= hw_enc_features | NETIF_F_TSO_MANGLEID;
1347013469

13470+
#define I40E_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \
13471+
NETIF_F_GSO_GRE_CSUM | \
13472+
NETIF_F_GSO_IPXIP4 | \
13473+
NETIF_F_GSO_IPXIP6 | \
13474+
NETIF_F_GSO_UDP_TUNNEL | \
13475+
NETIF_F_GSO_UDP_TUNNEL_CSUM)
13476+
13477+
netdev->gso_partial_features = I40E_GSO_PARTIAL_FEATURES;
13478+
netdev->features |= NETIF_F_GSO_PARTIAL |
13479+
I40E_GSO_PARTIAL_FEATURES;
13480+
13481+
netdev->mpls_features |= NETIF_F_SG;
13482+
netdev->mpls_features |= NETIF_F_HW_CSUM;
13483+
netdev->mpls_features |= NETIF_F_TSO;
13484+
netdev->mpls_features |= NETIF_F_TSO6;
13485+
netdev->mpls_features |= I40E_GSO_PARTIAL_FEATURES;
13486+
1347113487
/* enable macvlan offloads */
1347213488
netdev->hw_features |= NETIF_F_HW_L2FW_DOFFLOAD;
1347313489

drivers/net/ethernet/intel/i40e/i40e_txrx.c

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <linux/prefetch.h>
55
#include <linux/bpf_trace.h>
6+
#include <net/mpls.h>
67
#include <net/xdp.h>
78
#include "i40e.h"
89
#include "i40e_trace.h"
@@ -3015,6 +3016,7 @@ static int i40e_tso(struct i40e_tx_buffer *first, u8 *hdr_len,
30153016
{
30163017
struct sk_buff *skb = first->skb;
30173018
u64 cd_cmd, cd_tso_len, cd_mss;
3019+
__be16 protocol;
30183020
union {
30193021
struct iphdr *v4;
30203022
struct ipv6hdr *v6;
@@ -3026,7 +3028,7 @@ static int i40e_tso(struct i40e_tx_buffer *first, u8 *hdr_len,
30263028
unsigned char *hdr;
30273029
} l4;
30283030
u32 paylen, l4_offset;
3029-
u16 gso_segs, gso_size;
3031+
u16 gso_size;
30303032
int err;
30313033

30323034
if (skb->ip_summed != CHECKSUM_PARTIAL)
@@ -3039,15 +3041,23 @@ static int i40e_tso(struct i40e_tx_buffer *first, u8 *hdr_len,
30393041
if (err < 0)
30403042
return err;
30413043

3042-
ip.hdr = skb_network_header(skb);
3043-
l4.hdr = skb_transport_header(skb);
3044+
protocol = vlan_get_protocol(skb);
3045+
3046+
if (eth_p_mpls(protocol))
3047+
ip.hdr = skb_inner_network_header(skb);
3048+
else
3049+
ip.hdr = skb_network_header(skb);
3050+
l4.hdr = skb_checksum_start(skb);
30443051

30453052
/* initialize outer IP header fields */
30463053
if (ip.v4->version == 4) {
30473054
ip.v4->tot_len = 0;
30483055
ip.v4->check = 0;
3056+
3057+
first->tx_flags |= I40E_TX_FLAGS_TSO;
30493058
} else {
30503059
ip.v6->payload_len = 0;
3060+
first->tx_flags |= I40E_TX_FLAGS_TSO;
30513061
}
30523062

30533063
if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE |
@@ -3100,10 +3110,9 @@ static int i40e_tso(struct i40e_tx_buffer *first, u8 *hdr_len,
31003110

31013111
/* pull values out of skb_shinfo */
31023112
gso_size = skb_shinfo(skb)->gso_size;
3103-
gso_segs = skb_shinfo(skb)->gso_segs;
31043113

31053114
/* update GSO size and bytecount with header size */
3106-
first->gso_segs = gso_segs;
3115+
first->gso_segs = skb_shinfo(skb)->gso_segs;
31073116
first->bytecount += (first->gso_segs - 1) * *hdr_len;
31083117

31093118
/* find the field values */
@@ -3187,13 +3196,27 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
31873196
unsigned char *exthdr;
31883197
u32 offset, cmd = 0;
31893198
__be16 frag_off;
3199+
__be16 protocol;
31903200
u8 l4_proto = 0;
31913201

31923202
if (skb->ip_summed != CHECKSUM_PARTIAL)
31933203
return 0;
31943204

3195-
ip.hdr = skb_network_header(skb);
3196-
l4.hdr = skb_transport_header(skb);
3205+
protocol = vlan_get_protocol(skb);
3206+
3207+
if (eth_p_mpls(protocol))
3208+
ip.hdr = skb_inner_network_header(skb);
3209+
else
3210+
ip.hdr = skb_network_header(skb);
3211+
l4.hdr = skb_checksum_start(skb);
3212+
3213+
/* set the tx_flags to indicate the IP protocol type. this is
3214+
* required so that checksum header computation below is accurate.
3215+
*/
3216+
if (ip.v4->version == 4)
3217+
*tx_flags |= I40E_TX_FLAGS_IPV4;
3218+
else
3219+
*tx_flags |= I40E_TX_FLAGS_IPV6;
31973220

31983221
/* compute outer L2 header size */
31993222
offset = ((ip.hdr - skb->data) / 2) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT;
@@ -3749,7 +3772,6 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
37493772
struct i40e_tx_buffer *first;
37503773
u32 td_offset = 0;
37513774
u32 tx_flags = 0;
3752-
__be16 protocol;
37533775
u32 td_cmd = 0;
37543776
u8 hdr_len = 0;
37553777
int tso, count;
@@ -3791,15 +3813,6 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
37913813
if (i40e_tx_prepare_vlan_flags(skb, tx_ring, &tx_flags))
37923814
goto out_drop;
37933815

3794-
/* obtain protocol of skb */
3795-
protocol = vlan_get_protocol(skb);
3796-
3797-
/* setup IPv4/IPv6 offloads */
3798-
if (protocol == htons(ETH_P_IP))
3799-
tx_flags |= I40E_TX_FLAGS_IPV4;
3800-
else if (protocol == htons(ETH_P_IPV6))
3801-
tx_flags |= I40E_TX_FLAGS_IPV6;
3802-
38033816
tso = i40e_tso(first, &hdr_len, &cd_type_cmd_tso_mss);
38043817

38053818
if (tso < 0)

0 commit comments

Comments
 (0)