Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

igb: Add UDP segmentation offload support

Based on a series from Alexander Duyck this change adds UDP segmentation
offload support to the igb driver.

CC: Alexander Duyck <alexander.h.duyck@intel.com>
CC: Willem de Bruijn <willemb@google.com>
Signed-off-by: Josh Hunt <johunt@akamai.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

authored by

Josh Hunt and committed by
Jeff Kirsher
4085d06d daee5598

+18 -6
+1
drivers/net/ethernet/intel/igb/e1000_82575.h
··· 127 127 }; 128 128 129 129 #define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ 130 + #define E1000_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */ 130 131 #define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */ 131 132 #define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */ 132 133 #define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */
+17 -6
drivers/net/ethernet/intel/igb/igb_main.c
··· 2516 2516 if (unlikely(mac_hdr_len > IGB_MAX_MAC_HDR_LEN)) 2517 2517 return features & ~(NETIF_F_HW_CSUM | 2518 2518 NETIF_F_SCTP_CRC | 2519 + NETIF_F_GSO_UDP_L4 | 2519 2520 NETIF_F_HW_VLAN_CTAG_TX | 2520 2521 NETIF_F_TSO | 2521 2522 NETIF_F_TSO6); ··· 2525 2524 if (unlikely(network_hdr_len > IGB_MAX_NETWORK_HDR_LEN)) 2526 2525 return features & ~(NETIF_F_HW_CSUM | 2527 2526 NETIF_F_SCTP_CRC | 2527 + NETIF_F_GSO_UDP_L4 | 2528 2528 NETIF_F_TSO | 2529 2529 NETIF_F_TSO6); 2530 2530 ··· 3122 3120 NETIF_F_HW_CSUM; 3123 3121 3124 3122 if (hw->mac.type >= e1000_82576) 3125 - netdev->features |= NETIF_F_SCTP_CRC; 3123 + netdev->features |= NETIF_F_SCTP_CRC | NETIF_F_GSO_UDP_L4; 3126 3124 3127 3125 if (hw->mac.type >= e1000_i350) 3128 3126 netdev->features |= NETIF_F_HW_TC; ··· 5696 5694 } ip; 5697 5695 union { 5698 5696 struct tcphdr *tcp; 5697 + struct udphdr *udp; 5699 5698 unsigned char *hdr; 5700 5699 } l4; 5701 5700 u32 paylen, l4_offset; ··· 5716 5713 l4.hdr = skb_checksum_start(skb); 5717 5714 5718 5715 /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */ 5719 - type_tucmd = E1000_ADVTXD_TUCMD_L4T_TCP; 5716 + type_tucmd = (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) ? 5717 + E1000_ADVTXD_TUCMD_L4T_UDP : E1000_ADVTXD_TUCMD_L4T_TCP; 5720 5718 5721 5719 /* initialize outer IP header fields */ 5722 5720 if (ip.v4->version == 4) { ··· 5745 5741 /* determine offset of inner transport header */ 5746 5742 l4_offset = l4.hdr - skb->data; 5747 5743 5748 - /* compute length of segmentation header */ 5749 - *hdr_len = (l4.tcp->doff * 4) + l4_offset; 5750 - 5751 5744 /* remove payload length from inner checksum */ 5752 5745 paylen = skb->len - l4_offset; 5753 - csum_replace_by_diff(&l4.tcp->check, htonl(paylen)); 5746 + if (type_tucmd & E1000_ADVTXD_TUCMD_L4T_TCP) { 5747 + /* compute length of segmentation header */ 5748 + *hdr_len = (l4.tcp->doff * 4) + l4_offset; 5749 + csum_replace_by_diff(&l4.tcp->check, 5750 + (__force __wsum)htonl(paylen)); 5751 + } else { 5752 + /* compute length of segmentation header */ 5753 + *hdr_len = sizeof(*l4.udp) + l4_offset; 5754 + csum_replace_by_diff(&l4.udp->check, 5755 + (__force __wsum)htonl(paylen)); 5756 + } 5754 5757 5755 5758 /* update gso size and bytecount with header size */ 5756 5759 first->gso_segs = skb_shinfo(skb)->gso_segs;