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