* [Intel-wired-lan] [next-queue PATCH 0/3] Add support for GSO partial to Intel NIC drivers
[not found] <20160408203013.12838.63429.stgit@ahduyck-xeon-server>
@ 2016-04-08 21:06 ` Alexander Duyck
2016-04-08 21:06 ` [Intel-wired-lan] [next-queue PATCH 1/3] i40e/i40evf: Add support for GSO partial with UDP_TUNNEL_CSUM and GRE_CSUM Alexander Duyck
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Alexander Duyck @ 2016-04-08 21:06 UTC (permalink / raw)
To: intel-wired-lan
So these are the patches needed to enable tunnel segmentation offloads on
the igb, igbvf, ixgbe, and ixgbevf drivers. In addition this patch extends
the i40e and i40evf drivers to include segmentation support for tunnels
with outer checksums.
The net performance gain for these patches are pretty significant. In the
case of i40e a tunnel with outer checksums showed the following
improvement:
Throughput Throughput Local Local Result
Units CPU Service Tag
Util Demand
%
14066.29 10^6bits/s 3.49 0.651 "before"
20618.16 10^6bits/s 3.09 0.393 "after"
For ixgbe similar results were seen:
Throughput Throughput Local Local Result
Units CPU Service Tag
Util Demand
%
12879.89 10^6bits/s 10.00 0.763 "before"
14286.77 10^6bits/s 5.74 0.395 "after"
These patches all rely on the TSO_MANGLEID and GSO_PARTIAL patches so I
would not recommend applying them until those patches have first been
applied.
---
Alexander Duyck (3):
i40e/i40evf: Add support for GSO partial with UDP_TUNNEL_CSUM and GRE_CSUM
ixgbe/ixgbevf: Add support for GSO partial
igb/igbvf: Add support for GSO partial
drivers/net/ethernet/intel/i40e/i40e_main.c | 10 +
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 7 +
drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 7 +
drivers/net/ethernet/intel/i40evf/i40evf_main.c | 10 +
drivers/net/ethernet/intel/igb/igb_main.c | 112 ++++++++++----
drivers/net/ethernet/intel/igbvf/netdev.c | 173 +++++++++++++--------
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 105 +++++++++----
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 123 ++++++++++++---
8 files changed, 391 insertions(+), 156 deletions(-)
--
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Intel-wired-lan] [next-queue PATCH 1/3] i40e/i40evf: Add support for GSO partial with UDP_TUNNEL_CSUM and GRE_CSUM
2016-04-08 21:06 ` [Intel-wired-lan] [next-queue PATCH 0/3] Add support for GSO partial to Intel NIC drivers Alexander Duyck
@ 2016-04-08 21:06 ` Alexander Duyck
2016-04-09 6:51 ` Jeff Kirsher
2016-04-08 21:06 ` [Intel-wired-lan] [next-queue PATCH 2/3] ixgbe/ixgbevf: Add support for GSO partial Alexander Duyck
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Alexander Duyck @ 2016-04-08 21:06 UTC (permalink / raw)
To: intel-wired-lan
This patch makes it so that i40e and i40evf can use GSO_PARTIAL to support
segmentation for frames with checksums enabled in outer headers. As a
result we can now send data over these types of tunnels at over 20Gb/s
versus the 12Gb/s that was previously possible on my system.
The advantage with the i40e parts is that this offload is mostly
transparent as the hardware still deals with the inner and/or outer IPv4
headers so the IP ID is still incrementing for both when this offload is
performed.
Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 10 ++++++++--
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 7 ++++++-
drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 7 ++++++-
drivers/net/ethernet/intel/i40evf/i40evf_main.c | 10 ++++++++--
4 files changed, 28 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 07a70c4ac49f..6342fab4d177 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -9119,20 +9119,25 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
NETIF_F_TSO_ECN |
NETIF_F_TSO6 |
NETIF_F_GSO_GRE |
+ NETIF_F_GSO_GRE_CSUM |
NETIF_F_GSO_IPIP |
NETIF_F_GSO_SIT |
NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_GSO_UDP_TUNNEL_CSUM |
+ NETIF_F_GSO_PARTIAL |
NETIF_F_SCTP_CRC |
NETIF_F_RXHASH |
NETIF_F_RXCSUM |
0;
if (!(pf->flags & I40E_FLAG_OUTER_UDP_CSUM_CAPABLE))
- netdev->hw_enc_features ^= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+ netdev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+
+ netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
/* record features VLANs can make use of */
- netdev->vlan_features |= netdev->hw_enc_features;
+ netdev->vlan_features |= netdev->hw_enc_features |
+ NETIF_F_TSO_MANGLEID;
if (!(pf->flags & I40E_FLAG_MFP_ENABLED))
netdev->hw_features |= NETIF_F_NTUPLE;
@@ -9142,6 +9147,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
NETIF_F_HW_VLAN_CTAG_RX;
netdev->features |= netdev->hw_features | NETIF_F_HW_VLAN_CTAG_FILTER;
+ netdev->hw_enc_features |= NETIF_F_TSO_MANGLEID;
if (vsi->type == I40E_VSI_MAIN) {
SET_NETDEV_DEV(netdev, &pf->pdev->dev);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 6e44cf118843..ede4183468b9 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -2300,11 +2300,15 @@ static int i40e_tso(struct sk_buff *skb, u8 *hdr_len, u64 *cd_type_cmd_tso_mss)
}
if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE |
+ SKB_GSO_GRE_CSUM |
SKB_GSO_IPIP |
SKB_GSO_SIT |
SKB_GSO_UDP_TUNNEL |
SKB_GSO_UDP_TUNNEL_CSUM)) {
- if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM) {
+ if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
+ (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM)) {
+ l4.udp->len = 0;
+
/* determine offset of outer transport header */
l4_offset = l4.hdr - skb->data;
@@ -2481,6 +2485,7 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
/* indicate if we need to offload outer UDP header */
if ((*tx_flags & I40E_TX_FLAGS_TSO) &&
+ !(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM))
tunnel |= I40E_TXD_CTX_QW0_L4T_CS_MASK;
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
index f101895ecf4a..6ce00547c13e 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
@@ -1565,11 +1565,15 @@ static int i40e_tso(struct sk_buff *skb, u8 *hdr_len, u64 *cd_type_cmd_tso_mss)
}
if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE |
+ SKB_GSO_GRE_CSUM |
SKB_GSO_IPIP |
SKB_GSO_SIT |
SKB_GSO_UDP_TUNNEL |
SKB_GSO_UDP_TUNNEL_CSUM)) {
- if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM) {
+ if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
+ (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM)) {
+ l4.udp->len = 0;
+
/* determine offset of outer transport header */
l4_offset = l4.hdr - skb->data;
@@ -1704,6 +1708,7 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
/* indicate if we need to offload outer UDP header */
if ((*tx_flags & I40E_TX_FLAGS_TSO) &&
+ !(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM))
tunnel |= I40E_TXD_CTX_QW0_L4T_CS_MASK;
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index 806da2686623..42be838ce77e 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -2346,20 +2346,25 @@ int i40evf_process_config(struct i40evf_adapter *adapter)
NETIF_F_TSO_ECN |
NETIF_F_TSO6 |
NETIF_F_GSO_GRE |
+ NETIF_F_GSO_GRE_CSUM |
NETIF_F_GSO_IPIP |
NETIF_F_GSO_SIT |
NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_GSO_UDP_TUNNEL_CSUM |
+ NETIF_F_GSO_PARTIAL |
NETIF_F_SCTP_CRC |
NETIF_F_RXHASH |
NETIF_F_RXCSUM |
0;
if (!(adapter->flags & I40EVF_FLAG_OUTER_UDP_CSUM_CAPABLE))
- netdev->hw_enc_features ^= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+ netdev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+
+ netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
/* record features VLANs can make use of */
- netdev->vlan_features |= netdev->hw_enc_features;
+ netdev->vlan_features |= netdev->hw_enc_features |
+ NETIF_F_TSO_MANGLEID;
/* Write features and hw_features separately to avoid polluting
* with, or dropping, features that are set when we registgered.
@@ -2367,6 +2372,7 @@ int i40evf_process_config(struct i40evf_adapter *adapter)
netdev->hw_features |= netdev->hw_enc_features;
netdev->features |= netdev->hw_enc_features | I40EVF_VLAN_FEATURES;
+ netdev->hw_enc_features |= NETIF_F_TSO_MANGLEID;
/* disable VLAN features if not supported */
if (!(vfres->vf_offload_flags & I40E_VIRTCHNL_VF_OFFLOAD_VLAN))
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Intel-wired-lan] [next-queue PATCH 2/3] ixgbe/ixgbevf: Add support for GSO partial
2016-04-08 21:06 ` [Intel-wired-lan] [next-queue PATCH 0/3] Add support for GSO partial to Intel NIC drivers Alexander Duyck
2016-04-08 21:06 ` [Intel-wired-lan] [next-queue PATCH 1/3] i40e/i40evf: Add support for GSO partial with UDP_TUNNEL_CSUM and GRE_CSUM Alexander Duyck
@ 2016-04-08 21:06 ` Alexander Duyck
2016-04-09 6:53 ` Jeff Kirsher
2016-04-08 21:06 ` [Intel-wired-lan] [next-queue PATCH 3/3] igb/igbvf: " Alexander Duyck
2016-04-09 6:59 ` [Intel-wired-lan] [next-queue PATCH 0/3] Add support for GSO partial to Intel NIC drivers Jeff Kirsher
3 siblings, 1 reply; 8+ messages in thread
From: Alexander Duyck @ 2016-04-08 21:06 UTC (permalink / raw)
To: intel-wired-lan
This patch adds support for partial GSO segmentation in the case of
tunnels. Specifically with this change the driver an perform segmenation
as long as the frame either has IPv6 inner headers, or we are allowed to
mangle the IP IDs on the inner header. This is needed because we will not
be modifying any fields from the start of the start of the outer transport
header to the start of the inner transport header as we are treating them
like they are just a block of IP options.
Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 105 +++++++++++++-----
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 123 ++++++++++++++++-----
2 files changed, 172 insertions(+), 56 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 974aa7ca7a12..5134cb97f33c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -7216,9 +7216,18 @@ static int ixgbe_tso(struct ixgbe_ring *tx_ring,
struct ixgbe_tx_buffer *first,
u8 *hdr_len)
{
+ u32 vlan_macip_lens, type_tucmd, mss_l4len_idx;
struct sk_buff *skb = first->skb;
- u32 vlan_macip_lens, type_tucmd;
- u32 mss_l4len_idx, l4len;
+ union {
+ struct iphdr *v4;
+ struct ipv6hdr *v6;
+ unsigned char *hdr;
+ } ip;
+ union {
+ struct tcphdr *tcp;
+ unsigned char *hdr;
+ } l4;
+ u32 paylen, l4_offset;
int err;
if (skb->ip_summed != CHECKSUM_PARTIAL)
@@ -7231,46 +7240,52 @@ static int ixgbe_tso(struct ixgbe_ring *tx_ring,
if (err < 0)
return err;
+ ip.hdr = skb_network_header(skb);
+ l4.hdr = skb_checksum_start(skb);
+
/* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_TCP;
- if (first->protocol == htons(ETH_P_IP)) {
- struct iphdr *iph = ip_hdr(skb);
- iph->tot_len = 0;
- iph->check = 0;
- tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
- iph->daddr, 0,
- IPPROTO_TCP,
- 0);
+ /* initialize outer IP header fields */
+ if (ip.v4->version == 4) {
+ /* IP header will have to cancel out any data that
+ * is not a part of the outer IP header
+ */
+ ip.v4->check = csum_fold(csum_add(lco_csum(skb),
+ csum_unfold(l4.tcp->check)));
type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4;
+
+ ip.v4->tot_len = 0;
first->tx_flags |= IXGBE_TX_FLAGS_TSO |
IXGBE_TX_FLAGS_CSUM |
IXGBE_TX_FLAGS_IPV4;
- } else if (skb_is_gso_v6(skb)) {
- ipv6_hdr(skb)->payload_len = 0;
- tcp_hdr(skb)->check =
- ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
- &ipv6_hdr(skb)->daddr,
- 0, IPPROTO_TCP, 0);
+ } else {
+ ip.v6->payload_len = 0;
first->tx_flags |= IXGBE_TX_FLAGS_TSO |
IXGBE_TX_FLAGS_CSUM;
}
- /* compute header lengths */
- l4len = tcp_hdrlen(skb);
- *hdr_len = skb_transport_offset(skb) + l4len;
+ /* determine offset of inner transport header */
+ l4_offset = l4.hdr - skb->data;
+
+ /* compute length of segmentation header */
+ *hdr_len = (l4.tcp->doff * 4) + l4_offset;
+
+ /* remove payload length from inner checksum */
+ paylen = skb->len - l4_offset;
+ csum_replace_by_diff(&l4.tcp->check, htonl(paylen));
/* update gso size and bytecount with header size */
first->gso_segs = skb_shinfo(skb)->gso_segs;
first->bytecount += (first->gso_segs - 1) * *hdr_len;
/* mss_l4len_id: use 0 as index for TSO */
- mss_l4len_idx = l4len << IXGBE_ADVTXD_L4LEN_SHIFT;
+ mss_l4len_idx = (*hdr_len - l4_offset) << IXGBE_ADVTXD_L4LEN_SHIFT;
mss_l4len_idx |= skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT;
/* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
- vlan_macip_lens = skb_network_header_len(skb);
- vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT;
+ vlan_macip_lens = l4.hdr - ip.hdr;
+ vlan_macip_lens |= (ip.hdr - skb->data) << IXGBE_ADVTXD_MACLEN_SHIFT;
vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0, type_tucmd,
@@ -8614,6 +8629,14 @@ static int ixgbe_set_features(struct net_device *netdev,
if (changed & NETIF_F_RXALL)
need_reset = true;
+ /* We can only support IPV4 TSO in tunnels if we can mangle the
+ * inner IP ID field, so strip TSO if MANGLEID is not supported.
+ */
+ if (features & NETIF_F_TSO_MANGLEID)
+ netdev->hw_enc_features |= NETIF_F_TSO;
+ else
+ netdev->hw_enc_features &= ~NETIF_F_TSO;
+
netdev->features = features;
#ifdef CONFIG_IXGBE_VXLAN
@@ -8927,17 +8950,25 @@ static void ixgbe_fwd_del(struct net_device *pdev, void *priv)
kfree(fwd_adapter);
}
-#define IXGBE_MAX_TUNNEL_HDR_LEN 80
+#define IXGBE_MAX_MAC_HDR_LEN 127
+#define IXGBE_MAX_NETWORK_HDR_LEN 511
+
static netdev_features_t
ixgbe_features_check(struct sk_buff *skb, struct net_device *dev,
netdev_features_t features)
{
- if (!skb->encapsulation)
- return features;
+ unsigned int network_hdr_len, mac_hdr_len;
- if (unlikely(skb_inner_mac_header(skb) - skb_transport_header(skb) >
- IXGBE_MAX_TUNNEL_HDR_LEN))
- return features & ~NETIF_F_CSUM_MASK;
+ /* Make certain the headers can be described by a context descriptor */
+ mac_hdr_len = skb_network_header(skb) - skb->data;
+ network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb);
+ if (unlikely((mac_hdr_len > IXGBE_MAX_MAC_HDR_LEN) ||
+ (network_hdr_len > IXGBE_MAX_NETWORK_HDR_LEN)))
+ return features & ~(NETIF_F_HW_CSUM |
+ NETIF_F_SCTP_CRC |
+ NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_TSO |
+ NETIF_F_TSO6);
return features;
}
@@ -9309,6 +9340,17 @@ skip_sriov:
NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_CTAG_FILTER;
+#define IXGBE_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \
+ NETIF_F_GSO_GRE_CSUM | \
+ NETIF_F_GSO_IPIP | \
+ NETIF_F_GSO_SIT | \
+ NETIF_F_GSO_UDP_TUNNEL | \
+ NETIF_F_GSO_UDP_TUNNEL_CSUM)
+
+ netdev->gso_partial_features = IXGBE_GSO_PARTIAL_FEATURES;
+ netdev->features |= NETIF_F_GSO_PARTIAL |
+ IXGBE_GSO_PARTIAL_FEATURES;
+
if (hw->mac.type >= ixgbe_mac_82599EB)
netdev->features |= NETIF_F_SCTP_CRC;
@@ -9323,12 +9365,17 @@ skip_sriov:
netdev->vlan_features |= NETIF_F_SG |
NETIF_F_TSO |
+ NETIF_F_TSO_MANGLEID |
NETIF_F_TSO6 |
NETIF_F_HW_CSUM |
NETIF_F_SCTP_CRC;
netdev->mpls_features |= NETIF_F_HW_CSUM;
- netdev->hw_enc_features |= NETIF_F_HW_CSUM;
+ netdev->hw_enc_features |= NETIF_F_HW_CSUM |
+ NETIF_F_TSO_MANGLEID |
+ NETIF_F_TSO6 |
+ NETIF_F_GSO_PARTIAL |
+ IXGBE_GSO_PARTIAL_FEATURES;
netdev->priv_flags |= IFF_UNICAST_FLT;
netdev->priv_flags |= IFF_SUPP_NOFCS;
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 007cbe094990..e4f471787dd4 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -3272,9 +3272,18 @@ static int ixgbevf_tso(struct ixgbevf_ring *tx_ring,
struct ixgbevf_tx_buffer *first,
u8 *hdr_len)
{
+ u32 vlan_macip_lens, type_tucmd, mss_l4len_idx;
struct sk_buff *skb = first->skb;
- u32 vlan_macip_lens, type_tucmd;
- u32 mss_l4len_idx, l4len;
+ union {
+ struct iphdr *v4;
+ struct ipv6hdr *v6;
+ unsigned char *hdr;
+ } ip;
+ union {
+ struct tcphdr *tcp;
+ unsigned char *hdr;
+ } l4;
+ u32 paylen, l4_offset;
int err;
if (skb->ip_summed != CHECKSUM_PARTIAL)
@@ -3287,49 +3296,53 @@ static int ixgbevf_tso(struct ixgbevf_ring *tx_ring,
if (err < 0)
return err;
+ ip.hdr = skb_network_header(skb);
+ l4.hdr = skb_checksum_start(skb);
+
/* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_TCP;
- if (first->protocol == htons(ETH_P_IP)) {
- struct iphdr *iph = ip_hdr(skb);
-
- iph->tot_len = 0;
- iph->check = 0;
- tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
- iph->daddr, 0,
- IPPROTO_TCP,
- 0);
+ /* initialize outer IP header fields */
+ if (ip.v4->version == 4) {
+ /* IP header will have to cancel out any data that
+ * is not a part of the outer IP header
+ */
+ ip.v4->check = csum_fold(csum_add(lco_csum(skb),
+ csum_unfold(l4.tcp->check)));
type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4;
+
+ ip.v4->tot_len = 0;
first->tx_flags |= IXGBE_TX_FLAGS_TSO |
IXGBE_TX_FLAGS_CSUM |
IXGBE_TX_FLAGS_IPV4;
- } else if (skb_is_gso_v6(skb)) {
- ipv6_hdr(skb)->payload_len = 0;
- tcp_hdr(skb)->check =
- ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
- &ipv6_hdr(skb)->daddr,
- 0, IPPROTO_TCP, 0);
+ } else {
+ ip.v6->payload_len = 0;
first->tx_flags |= IXGBE_TX_FLAGS_TSO |
IXGBE_TX_FLAGS_CSUM;
}
- /* compute header lengths */
- l4len = tcp_hdrlen(skb);
- *hdr_len += l4len;
- *hdr_len = skb_transport_offset(skb) + l4len;
+ /* determine offset of inner transport header */
+ l4_offset = l4.hdr - skb->data;
+
+ /* compute length of segmentation header */
+ *hdr_len = (l4.tcp->doff * 4) + l4_offset;
- /* update GSO size and bytecount with header size */
+ /* remove payload length from inner checksum */
+ paylen = skb->len - l4_offset;
+ csum_replace_by_diff(&l4.tcp->check, htonl(paylen));
+
+ /* update gso size and bytecount with header size */
first->gso_segs = skb_shinfo(skb)->gso_segs;
first->bytecount += (first->gso_segs - 1) * *hdr_len;
/* mss_l4len_id: use 1 as index for TSO */
- mss_l4len_idx = l4len << IXGBE_ADVTXD_L4LEN_SHIFT;
+ mss_l4len_idx = (*hdr_len - l4_offset) << IXGBE_ADVTXD_L4LEN_SHIFT;
mss_l4len_idx |= skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT;
mss_l4len_idx |= 1 << IXGBE_ADVTXD_IDX_SHIFT;
/* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
- vlan_macip_lens = skb_network_header_len(skb);
- vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT;
+ vlan_macip_lens = l4.hdr - ip.hdr;
+ vlan_macip_lens |= (ip.hdr - skb->data) << IXGBE_ADVTXD_MACLEN_SHIFT;
vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
ixgbevf_tx_ctxtdesc(tx_ring, vlan_macip_lens,
@@ -3870,6 +3883,45 @@ static struct rtnl_link_stats64 *ixgbevf_get_stats(struct net_device *netdev,
return stats;
}
+static int ixgbevf_set_features(struct net_device *netdev,
+ netdev_features_t features)
+{
+ /* We can only support IPV4 TSO in tunnels if we can mangle the
+ * inner IP ID field, so strip TSO if MANGLEID is not supported.
+ */
+ if (features & NETIF_F_TSO_MANGLEID)
+ netdev->hw_enc_features |= NETIF_F_TSO;
+ else
+ netdev->hw_enc_features &= ~NETIF_F_TSO;
+
+ netdev->features = features;
+
+ return 0;
+}
+
+#define IXGBEVF_MAX_MAC_HDR_LEN 127
+#define IXGBEVF_MAX_NETWORK_HDR_LEN 511
+
+static netdev_features_t
+ixgbevf_features_check(struct sk_buff *skb, struct net_device *dev,
+ netdev_features_t features)
+{
+ unsigned int network_hdr_len, mac_hdr_len;
+
+ /* Make certain the headers can be described by a context descriptor */
+ mac_hdr_len = skb_network_header(skb) - skb->data;
+ network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb);
+ if (unlikely((mac_hdr_len > IXGBEVF_MAX_MAC_HDR_LEN) ||
+ (network_hdr_len > IXGBEVF_MAX_NETWORK_HDR_LEN)))
+ return features & ~(NETIF_F_HW_CSUM |
+ NETIF_F_SCTP_CRC |
+ NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_TSO |
+ NETIF_F_TSO6);
+
+ return features;
+}
+
static const struct net_device_ops ixgbevf_netdev_ops = {
.ndo_open = ixgbevf_open,
.ndo_stop = ixgbevf_close,
@@ -3888,7 +3940,8 @@ static const struct net_device_ops ixgbevf_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ixgbevf_netpoll,
#endif
- .ndo_features_check = passthru_features_check,
+ .ndo_set_features = ixgbevf_set_features,
+ .ndo_features_check = ixgbevf_features_check,
};
static void ixgbevf_assign_netdev_ops(struct net_device *dev)
@@ -3999,6 +4052,17 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
NETIF_F_HW_CSUM |
NETIF_F_SCTP_CRC;
+#define IXGBEVF_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \
+ NETIF_F_GSO_GRE_CSUM | \
+ NETIF_F_GSO_IPIP | \
+ NETIF_F_GSO_SIT | \
+ NETIF_F_GSO_UDP_TUNNEL | \
+ NETIF_F_GSO_UDP_TUNNEL_CSUM)
+
+ netdev->gso_partial_features = IXGBEVF_GSO_PARTIAL_FEATURES;
+ netdev->hw_features |= NETIF_F_GSO_PARTIAL |
+ IXGBEVF_GSO_PARTIAL_FEATURES;
+
netdev->features = netdev->hw_features |
NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX |
@@ -4006,12 +4070,17 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->vlan_features |= NETIF_F_SG |
NETIF_F_TSO |
+ NETIF_F_TSO_MANGLEID |
NETIF_F_TSO6 |
NETIF_F_HW_CSUM |
NETIF_F_SCTP_CRC;
netdev->mpls_features |= NETIF_F_HW_CSUM;
- netdev->hw_enc_features |= NETIF_F_HW_CSUM;
+ netdev->hw_enc_features |= NETIF_F_HW_CSUM |
+ NETIF_F_TSO_MANGLEID |
+ NETIF_F_TSO6 |
+ NETIF_F_GSO_PARTIAL |
+ IXGBEVF_GSO_PARTIAL_FEATURES;
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Intel-wired-lan] [next-queue PATCH 3/3] igb/igbvf: Add support for GSO partial
2016-04-08 21:06 ` [Intel-wired-lan] [next-queue PATCH 0/3] Add support for GSO partial to Intel NIC drivers Alexander Duyck
2016-04-08 21:06 ` [Intel-wired-lan] [next-queue PATCH 1/3] i40e/i40evf: Add support for GSO partial with UDP_TUNNEL_CSUM and GRE_CSUM Alexander Duyck
2016-04-08 21:06 ` [Intel-wired-lan] [next-queue PATCH 2/3] ixgbe/ixgbevf: Add support for GSO partial Alexander Duyck
@ 2016-04-08 21:06 ` Alexander Duyck
2016-04-09 6:59 ` [Intel-wired-lan] [next-queue PATCH 0/3] Add support for GSO partial to Intel NIC drivers Jeff Kirsher
3 siblings, 0 replies; 8+ messages in thread
From: Alexander Duyck @ 2016-04-08 21:06 UTC (permalink / raw)
To: intel-wired-lan
This patch adds support for partial GSO segmentation in the case of
tunnels. Specifically with this change the driver an perform segmenation
as long as the frame either has IPv6 inner headers, or we are allowed to
mangle the IP IDs on the inner header. This is needed because we will not
be modifying any fields from the start of the start of the outer transport
header to the start of the inner transport header as we are treating them
like they are just a block of IP options.
Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
---
drivers/net/ethernet/intel/igb/igb_main.c | 112 ++++++++++++++-----
drivers/net/ethernet/intel/igbvf/netdev.c | 173 ++++++++++++++++++-----------
2 files changed, 191 insertions(+), 94 deletions(-)
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 8e96c35307fb..998a24611246 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2055,6 +2055,14 @@ static int igb_set_features(struct net_device *netdev,
if (changed & NETIF_F_HW_VLAN_CTAG_RX)
igb_vlan_mode(netdev, features);
+ /* We can only support IPV4 TSO in tunnels if we can mangle the
+ * inner IP ID field, so strip TSO if MANGLEID is not supported.
+ */
+ if (features & NETIF_F_TSO_MANGLEID)
+ netdev->hw_enc_features |= NETIF_F_TSO;
+ else
+ netdev->hw_enc_features &= ~NETIF_F_TSO;
+
if (!(changed & (NETIF_F_RXALL | NETIF_F_NTUPLE)))
return 0;
@@ -2087,6 +2095,29 @@ static int igb_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
return ndo_dflt_fdb_add(ndm, tb, dev, addr, vid, flags);
}
+#define IGB_MAX_MAC_HDR_LEN 127
+#define IGB_MAX_NETWORK_HDR_LEN 511
+
+static netdev_features_t
+igb_features_check(struct sk_buff *skb, struct net_device *dev,
+ netdev_features_t features)
+{
+ unsigned int network_hdr_len, mac_hdr_len;
+
+ /* Make certain the headers can be described by a context descriptor */
+ mac_hdr_len = skb_network_header(skb) - skb->data;
+ network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb);
+ if (unlikely((mac_hdr_len > IGB_MAX_MAC_HDR_LEN) ||
+ (network_hdr_len > IGB_MAX_NETWORK_HDR_LEN)))
+ return features & ~(NETIF_F_HW_CSUM |
+ NETIF_F_SCTP_CRC |
+ NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_TSO |
+ NETIF_F_TSO6);
+
+ return features;
+}
+
static const struct net_device_ops igb_netdev_ops = {
.ndo_open = igb_open,
.ndo_stop = igb_close,
@@ -2111,7 +2142,7 @@ static const struct net_device_ops igb_netdev_ops = {
.ndo_fix_features = igb_fix_features,
.ndo_set_features = igb_set_features,
.ndo_fdb_add = igb_ndo_fdb_add,
- .ndo_features_check = passthru_features_check,
+ .ndo_features_check = igb_features_check,
};
/**
@@ -2384,6 +2415,16 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (hw->mac.type >= e1000_82576)
netdev->features |= NETIF_F_SCTP_CRC;
+#define IGB_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \
+ NETIF_F_GSO_GRE_CSUM | \
+ NETIF_F_GSO_IPIP | \
+ NETIF_F_GSO_SIT | \
+ NETIF_F_GSO_UDP_TUNNEL | \
+ NETIF_F_GSO_UDP_TUNNEL_CSUM)
+
+ netdev->gso_partial_features = IGB_GSO_PARTIAL_FEATURES;
+ netdev->features |= NETIF_F_GSO_PARTIAL | IGB_GSO_PARTIAL_FEATURES;
+
/* copy netdev features into list of user selectable features */
netdev->hw_features |= netdev->features;
netdev->hw_features |= NETIF_F_RXALL;
@@ -2396,19 +2437,22 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->vlan_features |= NETIF_F_SG |
NETIF_F_TSO |
+ NETIF_F_TSO_MANGLEID |
NETIF_F_TSO6 |
NETIF_F_HW_CSUM |
NETIF_F_SCTP_CRC;
netdev->mpls_features |= NETIF_F_HW_CSUM;
- netdev->hw_enc_features |= NETIF_F_HW_CSUM;
+ netdev->hw_enc_features |= NETIF_F_HW_CSUM |
+ NETIF_F_TSO_MANGLEID |
+ NETIF_F_TSO6 |
+ NETIF_F_GSO_PARTIAL |
+ IGB_GSO_PARTIAL_FEATURES;
netdev->priv_flags |= IFF_SUPP_NOFCS;
- if (pci_using_dac) {
+ if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
- netdev->vlan_features |= NETIF_F_HIGHDMA;
- }
netdev->priv_flags |= IFF_UNICAST_FLT;
@@ -4842,9 +4886,18 @@ static int igb_tso(struct igb_ring *tx_ring,
struct igb_tx_buffer *first,
u8 *hdr_len)
{
+ u32 vlan_macip_lens, type_tucmd, mss_l4len_idx;
struct sk_buff *skb = first->skb;
- u32 vlan_macip_lens, type_tucmd;
- u32 mss_l4len_idx, l4len;
+ union {
+ struct iphdr *v4;
+ struct ipv6hdr *v6;
+ unsigned char *hdr;
+ } ip;
+ union {
+ struct tcphdr *tcp;
+ unsigned char *hdr;
+ } l4;
+ u32 paylen, l4_offset;
int err;
if (skb->ip_summed != CHECKSUM_PARTIAL)
@@ -4857,45 +4910,52 @@ static int igb_tso(struct igb_ring *tx_ring,
if (err < 0)
return err;
+ ip.hdr = skb_network_header(skb);
+ l4.hdr = skb_checksum_start(skb);
+
/* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
type_tucmd = E1000_ADVTXD_TUCMD_L4T_TCP;
- if (first->protocol == htons(ETH_P_IP)) {
- struct iphdr *iph = ip_hdr(skb);
- iph->tot_len = 0;
- iph->check = 0;
- tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
- iph->daddr, 0,
- IPPROTO_TCP,
- 0);
+ /* initialize outer IP header fields */
+ if (ip.v4->version == 4) {
+ /* IP header will have to cancel out any data that
+ * is not a part of the outer IP header
+ */
+ ip.v4->check = csum_fold(csum_add(lco_csum(skb),
+ csum_unfold(l4.tcp->check)));
type_tucmd |= E1000_ADVTXD_TUCMD_IPV4;
+
+ ip.v4->tot_len = 0;
first->tx_flags |= IGB_TX_FLAGS_TSO |
IGB_TX_FLAGS_CSUM |
IGB_TX_FLAGS_IPV4;
- } else if (skb_is_gso_v6(skb)) {
- ipv6_hdr(skb)->payload_len = 0;
- tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
- &ipv6_hdr(skb)->daddr,
- 0, IPPROTO_TCP, 0);
+ } else {
+ ip.v6->payload_len = 0;
first->tx_flags |= IGB_TX_FLAGS_TSO |
IGB_TX_FLAGS_CSUM;
}
- /* compute header lengths */
- l4len = tcp_hdrlen(skb);
- *hdr_len = skb_transport_offset(skb) + l4len;
+ /* determine offset of inner transport header */
+ l4_offset = l4.hdr - skb->data;
+
+ /* compute length of segmentation header */
+ *hdr_len = (l4.tcp->doff * 4) + l4_offset;
+
+ /* remove payload length from inner checksum */
+ paylen = skb->len - l4_offset;
+ csum_replace_by_diff(&l4.tcp->check, htonl(paylen));
/* update gso size and bytecount with header size */
first->gso_segs = skb_shinfo(skb)->gso_segs;
first->bytecount += (first->gso_segs - 1) * *hdr_len;
/* MSS L4LEN IDX */
- mss_l4len_idx = l4len << E1000_ADVTXD_L4LEN_SHIFT;
+ mss_l4len_idx = (*hdr_len - l4_offset) << E1000_ADVTXD_L4LEN_SHIFT;
mss_l4len_idx |= skb_shinfo(skb)->gso_size << E1000_ADVTXD_MSS_SHIFT;
/* VLAN MACLEN IPLEN */
- vlan_macip_lens = skb_network_header_len(skb);
- vlan_macip_lens |= skb_network_offset(skb) << E1000_ADVTXD_MACLEN_SHIFT;
+ vlan_macip_lens = l4.hdr - ip.hdr;
+ vlan_macip_lens |= (ip.hdr - skb->data) << E1000_ADVTXD_MACLEN_SHIFT;
vlan_macip_lens |= first->tx_flags & IGB_TX_FLAGS_VLAN_MASK;
igb_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, mss_l4len_idx);
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index c12442252adb..cd759c5e09f8 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -1933,83 +1933,74 @@ static void igbvf_tx_ctxtdesc(struct igbvf_ring *tx_ring, u32 vlan_macip_lens,
buffer_info->dma = 0;
}
-static int igbvf_tso(struct igbvf_adapter *adapter,
- struct igbvf_ring *tx_ring,
- struct sk_buff *skb, u32 tx_flags, u8 *hdr_len,
- __be16 protocol)
-{
- struct e1000_adv_tx_context_desc *context_desc;
- struct igbvf_buffer *buffer_info;
- u32 info = 0, tu_cmd = 0;
- u32 mss_l4len_idx, l4len;
- unsigned int i;
+static int igbvf_tso(struct igbvf_ring *tx_ring,
+ struct sk_buff *skb, u32 tx_flags, u8 *hdr_len)
+{
+ u32 vlan_macip_lens, type_tucmd, mss_l4len_idx;
+ union {
+ struct iphdr *v4;
+ struct ipv6hdr *v6;
+ unsigned char *hdr;
+ } ip;
+ union {
+ struct tcphdr *tcp;
+ unsigned char *hdr;
+ } l4;
+ u32 paylen, l4_offset;
int err;
- *hdr_len = 0;
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ return 0;
+
+ if (!skb_is_gso(skb))
+ return 0;
err = skb_cow_head(skb, 0);
- if (err < 0) {
- dev_err(&adapter->pdev->dev, "igbvf_tso returning an error\n");
+ if (err < 0)
return err;
- }
- l4len = tcp_hdrlen(skb);
- *hdr_len += l4len;
-
- if (protocol == htons(ETH_P_IP)) {
- struct iphdr *iph = ip_hdr(skb);
-
- iph->tot_len = 0;
- iph->check = 0;
- tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
- iph->daddr, 0,
- IPPROTO_TCP,
- 0);
- } else if (skb_is_gso_v6(skb)) {
- ipv6_hdr(skb)->payload_len = 0;
- tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
- &ipv6_hdr(skb)->daddr,
- 0, IPPROTO_TCP, 0);
- }
+ ip.hdr = skb_network_header(skb);
+ l4.hdr = skb_checksum_start(skb);
- i = tx_ring->next_to_use;
+ /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
+ type_tucmd = E1000_ADVTXD_TUCMD_L4T_TCP;
- buffer_info = &tx_ring->buffer_info[i];
- context_desc = IGBVF_TX_CTXTDESC_ADV(*tx_ring, i);
- /* VLAN MACLEN IPLEN */
- if (tx_flags & IGBVF_TX_FLAGS_VLAN)
- info |= (tx_flags & IGBVF_TX_FLAGS_VLAN_MASK);
- info |= (skb_network_offset(skb) << E1000_ADVTXD_MACLEN_SHIFT);
- *hdr_len += skb_network_offset(skb);
- info |= (skb_transport_header(skb) - skb_network_header(skb));
- *hdr_len += (skb_transport_header(skb) - skb_network_header(skb));
- context_desc->vlan_macip_lens = cpu_to_le32(info);
+ /* initialize outer IP header fields */
+ if (ip.v4->version == 4) {
+ /* IP header will have to cancel out any data that
+ * is not a part of the outer IP header
+ */
+ ip.v4->check = csum_fold(csum_add(lco_csum(skb),
+ csum_unfold(l4.tcp->check)));
+ type_tucmd |= E1000_ADVTXD_TUCMD_IPV4;
- /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
- tu_cmd |= (E1000_TXD_CMD_DEXT | E1000_ADVTXD_DTYP_CTXT);
+ ip.v4->tot_len = 0;
+ } else {
+ ip.v6->payload_len = 0;
+ }
- if (protocol == htons(ETH_P_IP))
- tu_cmd |= E1000_ADVTXD_TUCMD_IPV4;
- tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP;
+ /* determine offset of inner transport header */
+ l4_offset = l4.hdr - skb->data;
- context_desc->type_tucmd_mlhl = cpu_to_le32(tu_cmd);
+ /* compute length of segmentation header */
+ *hdr_len = (l4.tcp->doff * 4) + l4_offset;
- /* MSS L4LEN IDX */
- mss_l4len_idx = (skb_shinfo(skb)->gso_size << E1000_ADVTXD_MSS_SHIFT);
- mss_l4len_idx |= (l4len << E1000_ADVTXD_L4LEN_SHIFT);
+ /* remove payload length from inner checksum */
+ paylen = skb->len - l4_offset;
+ csum_replace_by_diff(&l4.tcp->check, htonl(paylen));
- context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
- context_desc->seqnum_seed = 0;
+ /* MSS L4LEN IDX */
+ mss_l4len_idx = (*hdr_len - l4_offset) << E1000_ADVTXD_L4LEN_SHIFT;
+ mss_l4len_idx |= skb_shinfo(skb)->gso_size << E1000_ADVTXD_MSS_SHIFT;
- buffer_info->time_stamp = jiffies;
- buffer_info->dma = 0;
- i++;
- if (i == tx_ring->count)
- i = 0;
+ /* VLAN MACLEN IPLEN */
+ vlan_macip_lens = l4.hdr - ip.hdr;
+ vlan_macip_lens |= (ip.hdr - skb->data) << E1000_ADVTXD_MACLEN_SHIFT;
+ vlan_macip_lens |= tx_flags & IGBVF_TX_FLAGS_VLAN_MASK;
- tx_ring->next_to_use = i;
+ igbvf_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, mss_l4len_idx);
- return true;
+ return 1;
}
static inline bool igbvf_ipv6_csum_is_sctp(struct sk_buff *skb)
@@ -2271,8 +2262,7 @@ static netdev_tx_t igbvf_xmit_frame_ring_adv(struct sk_buff *skb,
first = tx_ring->next_to_use;
- tso = skb_is_gso(skb) ?
- igbvf_tso(adapter, tx_ring, skb, tx_flags, &hdr_len, protocol) : 0;
+ tso = igbvf_tso(tx_ring, skb, tx_flags, &hdr_len);
if (unlikely(tso < 0)) {
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
@@ -2612,9 +2602,40 @@ static int igbvf_set_features(struct net_device *netdev,
else
adapter->flags |= IGBVF_FLAG_RX_CSUM_DISABLED;
+ /* We can only support IPV4 TSO in tunnels if we can mangle the
+ * inner IP ID field, so strip TSO if MANGLEID is not supported.
+ */
+ if (features & NETIF_F_TSO_MANGLEID)
+ netdev->hw_enc_features |= NETIF_F_TSO;
+ else
+ netdev->hw_enc_features &= ~NETIF_F_TSO;
+
return 0;
}
+#define IGBVF_MAX_MAC_HDR_LEN 127
+#define IGBVF_MAX_NETWORK_HDR_LEN 511
+
+static netdev_features_t
+igbvf_features_check(struct sk_buff *skb, struct net_device *dev,
+ netdev_features_t features)
+{
+ unsigned int network_hdr_len, mac_hdr_len;
+
+ /* Make certain the headers can be described by a context descriptor */
+ mac_hdr_len = skb_network_header(skb) - skb->data;
+ network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb);
+ if (unlikely((mac_hdr_len > IGBVF_MAX_MAC_HDR_LEN) ||
+ (network_hdr_len > IGBVF_MAX_NETWORK_HDR_LEN)))
+ return features & ~(NETIF_F_HW_CSUM |
+ NETIF_F_SCTP_CRC |
+ NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_TSO |
+ NETIF_F_TSO6);
+
+ return features;
+}
+
static const struct net_device_ops igbvf_netdev_ops = {
.ndo_open = igbvf_open,
.ndo_stop = igbvf_close,
@@ -2631,7 +2652,7 @@ static const struct net_device_ops igbvf_netdev_ops = {
.ndo_poll_controller = igbvf_netpoll,
#endif
.ndo_set_features = igbvf_set_features,
- .ndo_features_check = passthru_features_check,
+ .ndo_features_check = igbvf_features_check,
};
/**
@@ -2739,22 +2760,38 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
NETIF_F_HW_CSUM |
NETIF_F_SCTP_CRC;
+#define IGBVF_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \
+ NETIF_F_GSO_GRE_CSUM | \
+ NETIF_F_GSO_IPIP | \
+ NETIF_F_GSO_SIT | \
+ NETIF_F_GSO_UDP_TUNNEL | \
+ NETIF_F_GSO_UDP_TUNNEL_CSUM)
+
+ netdev->gso_partial_features = IGBVF_GSO_PARTIAL_FEATURES;
+ netdev->hw_features |= NETIF_F_GSO_PARTIAL |
+ IGBVF_GSO_PARTIAL_FEATURES;
+
netdev->features = netdev->hw_features |
NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_CTAG_FILTER;
- if (pci_using_dac)
- netdev->features |= NETIF_F_HIGHDMA;
-
netdev->vlan_features |= NETIF_F_SG |
NETIF_F_TSO |
+ NETIF_F_TSO_MANGLEID |
NETIF_F_TSO6 |
NETIF_F_HW_CSUM |
NETIF_F_SCTP_CRC;
netdev->mpls_features |= NETIF_F_HW_CSUM;
- netdev->hw_enc_features |= NETIF_F_HW_CSUM;
+ netdev->hw_enc_features |= NETIF_F_HW_CSUM |
+ NETIF_F_TSO_MANGLEID |
+ NETIF_F_TSO6 |
+ NETIF_F_GSO_PARTIAL |
+ IGBVF_GSO_PARTIAL_FEATURES;
+
+ if (pci_using_dac)
+ netdev->features |= NETIF_F_HIGHDMA;
/*reset the controller to put the device in a known good state */
err = hw->mac.ops.reset_hw(hw);
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Intel-wired-lan] [next-queue PATCH 1/3] i40e/i40evf: Add support for GSO partial with UDP_TUNNEL_CSUM and GRE_CSUM
2016-04-08 21:06 ` [Intel-wired-lan] [next-queue PATCH 1/3] i40e/i40evf: Add support for GSO partial with UDP_TUNNEL_CSUM and GRE_CSUM Alexander Duyck
@ 2016-04-09 6:51 ` Jeff Kirsher
0 siblings, 0 replies; 8+ messages in thread
From: Jeff Kirsher @ 2016-04-09 6:51 UTC (permalink / raw)
To: intel-wired-lan
On Fri, 2016-04-08 at 17:06 -0400, Alexander Duyck wrote:
> This patch makes it so that i40e and i40evf can use GSO_PARTIAL to
> support
> segmentation for frames with checksums enabled in outer headers.? As
> a
> result we can now send data over these types of tunnels at over
> 20Gb/s
> versus the 12Gb/s that was previously possible on my system.
>
> The advantage with the i40e parts is that this offload is mostly
> transparent as the hardware still deals with the inner and/or outer
> IPv4
> headers so the IP ID is still incrementing for both when this offload
> is
> performed.
>
> Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
> ---
> ?drivers/net/ethernet/intel/i40e/i40e_main.c???? |?? 10 ++++++++--
> ?drivers/net/ethernet/intel/i40e/i40e_txrx.c???? |??? 7 ++++++-
> ?drivers/net/ethernet/intel/i40evf/i40e_txrx.c?? |??? 7 ++++++-
> ?drivers/net/ethernet/intel/i40evf/i40evf_main.c |?? 10 ++++++++--
> ?4 files changed, 28 insertions(+), 6 deletions(-)
Dropping this patch because it does not even compile...
[23:49:07 @jtkirshe-linux:next-queue]$ make -j 77 -s
Makefile:679: Cannot use CONFIG_KCOV: -fsanitize-coverage=trace-pc is
not supported by compiler
? DESCEND??objtool
drivers/net/ethernet/intel/i40evf/i40evf_main.c: In function
?i40evf_process_config?:
drivers/net/ethernet/intel/i40evf/i40evf_main.c:2354:8: error:
?NETIF_F_GSO_PARTIAL? undeclared (first use in this function)
????????NETIF_F_GSO_PARTIAL??|
????????^
drivers/net/ethernet/intel/i40evf/i40evf_main.c:2354:8: note: each
undeclared identifier is reported only once for each function it
appears in
drivers/net/ethernet/intel/i40evf/i40evf_main.c:2361:9: error: ?struct
net_device? has no member named ?gso_partial_features?
???netdev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
?????????^
drivers/net/ethernet/intel/i40evf/i40evf_main.c:2363:8: error: ?struct
net_device? has no member named ?gso_partial_features?
? netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
????????^
drivers/net/ethernet/intel/i40evf/i40evf_main.c:2367:6: error:
?NETIF_F_TSO_MANGLEID? undeclared (first use in this function)
??????NETIF_F_TSO_MANGLEID;
??????^
drivers/net/ethernet/intel/i40evf/i40e_txrx.c: In function ?i40e_tso?:
drivers/net/ethernet/intel/i40evf/i40e_txrx.c:1573:37: error:
?SKB_GSO_PARTIAL? undeclared (first use in this function)
???if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
?????????????????????????????????????^
drivers/net/ethernet/intel/i40evf/i40e_txrx.c:1573:37: note: each
undeclared identifier is reported only once for each function it
appears in
drivers/net/ethernet/intel/i40evf/i40e_txrx.c: In function
?i40e_tx_enable_csum?:
drivers/net/ethernet/intel/i40evf/i40e_txrx.c:1711:37: error:
?SKB_GSO_PARTIAL? undeclared (first use in this function)
???????!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
?????????????????????????????????????^
scripts/Makefile.build:291: recipe for target
'drivers/net/ethernet/intel/i40evf/i40evf_main.o' failed
make[5]: *** [drivers/net/ethernet/intel/i40evf/i40evf_main.o] Error 1
make[5]: *** Waiting for unfinished jobs....
scripts/Makefile.build:291: recipe for target
'drivers/net/ethernet/intel/i40evf/i40e_txrx.o' failed
make[5]: *** [drivers/net/ethernet/intel/i40evf/i40e_txrx.o] Error 1
scripts/Makefile.build:440: recipe for target
'drivers/net/ethernet/intel/i40evf' failed
make[4]: *** [drivers/net/ethernet/intel/i40evf] Error 2
make[4]: *** Waiting for unfinished jobs....
drivers/net/ethernet/intel/i40e/i40e_main.c: In function
?i40e_config_netdev?:
drivers/net/ethernet/intel/i40e/i40e_main.c:9127:8: error:
?NETIF_F_GSO_PARTIAL? undeclared (first use in this function)
????????NETIF_F_GSO_PARTIAL??|
????????^
drivers/net/ethernet/intel/i40e/i40e_main.c:9127:8: note: each
undeclared identifier is reported only once for each function it
appears in
drivers/net/ethernet/intel/i40e/i40e_main.c:9134:9: error: ?struct
net_device? has no member named ?gso_partial_features?
???netdev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
?????????^
drivers/net/ethernet/intel/i40e/i40e_main.c:9136:8: error: ?struct
net_device? has no member named ?gso_partial_features?
? netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
????????^
drivers/net/ethernet/intel/i40e/i40e_main.c:9140:6: error:
?NETIF_F_TSO_MANGLEID? undeclared (first use in this function)
??????NETIF_F_TSO_MANGLEID;
??????^
scripts/Makefile.build:291: recipe for target
'drivers/net/ethernet/intel/i40e/i40e_main.o' failed
make[5]: *** [drivers/net/ethernet/intel/i40e/i40e_main.o] Error 1
make[5]: *** Waiting for unfinished jobs....
drivers/net/ethernet/intel/i40e/i40e_txrx.c: In function ?i40e_tso?:
drivers/net/ethernet/intel/i40e/i40e_txrx.c:2308:37: error:
?SKB_GSO_PARTIAL? undeclared (first use in this function)
???if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
?????????????????????????????????????^
drivers/net/ethernet/intel/i40e/i40e_txrx.c:2308:37: note: each
undeclared identifier is reported only once for each function it
appears in
drivers/net/ethernet/intel/i40e/i40e_txrx.c: In function
?i40e_tx_enable_csum?:
drivers/net/ethernet/intel/i40e/i40e_txrx.c:2488:37: error:
?SKB_GSO_PARTIAL? undeclared (first use in this function)
???????!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
?????????????????????????????????????^
scripts/Makefile.build:291: recipe for target
'drivers/net/ethernet/intel/i40e/i40e_txrx.o' failed
make[5]: *** [drivers/net/ethernet/intel/i40e/i40e_txrx.o] Error 1
scripts/Makefile.build:440: recipe for target
'drivers/net/ethernet/intel/i40e' failed
make[4]: *** [drivers/net/ethernet/intel/i40e] Error 2
scripts/Makefile.build:440: recipe for target
'drivers/net/ethernet/intel' failed
make[3]: *** [drivers/net/ethernet/intel] Error 2
make[3]: *** Waiting for unfinished jobs....
scripts/Makefile.build:440: recipe for target 'drivers/net/ethernet'
failed
make[2]: *** [drivers/net/ethernet] Error 2
scripts/Makefile.build:440: recipe for target 'drivers/net' failed
make[1]: *** [drivers/net] Error 2
make[1]: *** Waiting for unfinished jobs....
Makefile:962: recipe for target 'drivers' failed
make: *** [drivers] Error 2
make: *** Waiting for unfinished jobs....
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.osuosl.org/pipermail/intel-wired-lan/attachments/20160408/a9d36ed9/attachment.asc>
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Intel-wired-lan] [next-queue PATCH 2/3] ixgbe/ixgbevf: Add support for GSO partial
2016-04-08 21:06 ` [Intel-wired-lan] [next-queue PATCH 2/3] ixgbe/ixgbevf: Add support for GSO partial Alexander Duyck
@ 2016-04-09 6:53 ` Jeff Kirsher
0 siblings, 0 replies; 8+ messages in thread
From: Jeff Kirsher @ 2016-04-09 6:53 UTC (permalink / raw)
To: intel-wired-lan
On Fri, 2016-04-08 at 17:06 -0400, Alexander Duyck wrote:
> This patch adds support for partial GSO segmentation in the case of
> tunnels.? Specifically with this change the driver an perform
> segmenation
> as long as the frame either has IPv6 inner headers, or we are allowed
> to
> mangle the IP IDs on the inner header.? This is needed because we
> will not
> be modifying any fields from the start of the start of the outer
> transport
> header to the start of the inner transport header as we are treating
> them
> like they are just a block of IP options.
>
> Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
> ---
> ?drivers/net/ethernet/intel/ixgbe/ixgbe_main.c???? |? 105
> +++++++++++++-----
> ?drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |? 123
> ++++++++++++++++-----
> ?2 files changed, 172 insertions(+), 56 deletions(-)
Dropping this patch (and now the series) because this does not
compile...
[23:51:49 @jtkirshe-linux:next-queue]$ make -j 77 -s
Makefile:679: Cannot use CONFIG_KCOV: -fsanitize-coverage=trace-pc is
not supported by compiler
? DESCEND??objtool
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c: In function
?ixgbevf_set_features?:
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c:3892:17: error:
?NETIF_F_TSO_MANGLEID? undeclared (first use in this function)
? if (features & NETIF_F_TSO_MANGLEID)
?????????????????^
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c:3892:17: note: each
undeclared identifier is reported only once for each function it
appears in
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c: In function
?ixgbevf_probe?:
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c:4062:8: error:
?struct net_device? has no member named ?gso_partial_features?
? netdev->gso_partial_features = IXGBEVF_GSO_PARTIAL_FEATURES;
????????^
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c:4063:25: error:
?NETIF_F_GSO_PARTIAL? undeclared (first use in this function)
? netdev->hw_features |= NETIF_F_GSO_PARTIAL |
?????????????????????????^
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c:4073:6: error:
?NETIF_F_TSO_MANGLEID? undeclared (first use in this function)
??????NETIF_F_TSO_MANGLEID |
??????^
scripts/Makefile.build:291: recipe for target
'drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.o' failed
make[5]: *** [drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.o] Error
1
scripts/Makefile.build:440: recipe for target
'drivers/net/ethernet/intel/ixgbevf' failed
make[4]: *** [drivers/net/ethernet/intel/ixgbevf] Error 2
make[4]: *** Waiting for unfinished jobs....
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c: In function
?ixgbe_set_features?:
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:8635:17: error:
?NETIF_F_TSO_MANGLEID? undeclared (first use in this function)
? if (features & NETIF_F_TSO_MANGLEID)
?????????????????^
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:8635:17: note: each
undeclared identifier is reported only once for each function it
appears in
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c: In function
?ixgbe_probe?:
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:9350:8: error: ?struct
net_device? has no member named ?gso_partial_features?
? netdev->gso_partial_features = IXGBE_GSO_PARTIAL_FEATURES;
????????^
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:9351:22: error:
?NETIF_F_GSO_PARTIAL? undeclared (first use in this function)
? netdev->features |= NETIF_F_GSO_PARTIAL |
??????????????????????^
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:9368:6: error:
?NETIF_F_TSO_MANGLEID? undeclared (first use in this function)
??????NETIF_F_TSO_MANGLEID |
??????^
scripts/Makefile.build:291: recipe for target
'drivers/net/ethernet/intel/ixgbe/ixgbe_main.o' failed
make[5]: *** [drivers/net/ethernet/intel/ixgbe/ixgbe_main.o] Error 1
scripts/Makefile.build:440: recipe for target
'drivers/net/ethernet/intel/ixgbe' failed
make[4]: *** [drivers/net/ethernet/intel/ixgbe] Error 2
scripts/Makefile.build:440: recipe for target
'drivers/net/ethernet/intel' failed
make[3]: *** [drivers/net/ethernet/intel] Error 2
scripts/Makefile.build:440: recipe for target 'drivers/net/ethernet'
failed
make[2]: *** [drivers/net/ethernet] Error 2
scripts/Makefile.build:440: recipe for target 'drivers/net' failed
make[1]: *** [drivers/net] Error 2
Makefile:962: recipe for target 'drivers' failed
make: *** [drivers] Error 2
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.osuosl.org/pipermail/intel-wired-lan/attachments/20160408/ad6b7afd/attachment.asc>
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Intel-wired-lan] [next-queue PATCH 0/3] Add support for GSO partial to Intel NIC drivers
2016-04-08 21:06 ` [Intel-wired-lan] [next-queue PATCH 0/3] Add support for GSO partial to Intel NIC drivers Alexander Duyck
` (2 preceding siblings ...)
2016-04-08 21:06 ` [Intel-wired-lan] [next-queue PATCH 3/3] igb/igbvf: " Alexander Duyck
@ 2016-04-09 6:59 ` Jeff Kirsher
2016-04-09 15:41 ` Alexander Duyck
3 siblings, 1 reply; 8+ messages in thread
From: Jeff Kirsher @ 2016-04-09 6:59 UTC (permalink / raw)
To: intel-wired-lan
On Fri, 2016-04-08 at 17:06 -0400, Alexander Duyck wrote:
> So these are the patches needed to enable tunnel segmentation
> offloads on
> the igb, igbvf, ixgbe, and ixgbevf drivers.? In addition this patch
> extends
> the i40e and i40evf drivers to include segmentation support for
> tunnels
> with outer checksums.
>
> The net performance gain for these patches are pretty significant.?
> In the
> case of i40e a tunnel with outer checksums showed the following
> improvement:
> Throughput Throughput? Local Local?? Result?
> ?????????? Units?????? CPU?? Service Tag????
> ?????????????????????? Util? Demand?????????
> ?????????????????????? %????????????????????
> 14066.29?? 10^6bits/s? 3.49? 0.651?? "before"?
> 20618.16?? 10^6bits/s? 3.09? 0.393?? "after"
>
> For ixgbe similar results were seen:
> Throughput Throughput? Local? Local?? Result?
> ?????????? Units?????? CPU??? Service Tag????
> ?????????????????????? Util?? Demand?????????
> ?????????????????????? %???????????????
> 12879.89?? 10^6bits/s? 10.00? 0.763?? "before"
> 14286.77?? 10^6bits/s? 5.74?? 0.395?? "after"?
>
> These patches all rely on the TSO_MANGLEID and GSO_PARTIAL patches so
> I
> would not recommend applying them until those patches have first been
> applied.
Sorry I did not see this until after I tried applying your series. :-(
Maybe the two dependent patches should have been in the series, so I
and others do not waste their time. ?Or not send this until the two
patches were accepted.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.osuosl.org/pipermail/intel-wired-lan/attachments/20160408/1e0d1721/attachment-0001.asc>
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Intel-wired-lan] [next-queue PATCH 0/3] Add support for GSO partial to Intel NIC drivers
2016-04-09 6:59 ` [Intel-wired-lan] [next-queue PATCH 0/3] Add support for GSO partial to Intel NIC drivers Jeff Kirsher
@ 2016-04-09 15:41 ` Alexander Duyck
0 siblings, 0 replies; 8+ messages in thread
From: Alexander Duyck @ 2016-04-09 15:41 UTC (permalink / raw)
To: intel-wired-lan
On Fri, Apr 8, 2016 at 11:59 PM, Jeff Kirsher
<jeffrey.t.kirsher@intel.com> wrote:
> On Fri, 2016-04-08 at 17:06 -0400, Alexander Duyck wrote:
>> So these are the patches needed to enable tunnel segmentation
>> offloads on
>> the igb, igbvf, ixgbe, and ixgbevf drivers. In addition this patch
>> extends
>> the i40e and i40evf drivers to include segmentation support for
>> tunnels
>> with outer checksums.
>>
>> The net performance gain for these patches are pretty significant.
>> In the
>> case of i40e a tunnel with outer checksums showed the following
>> improvement:
>> Throughput Throughput Local Local Result
>> Units CPU Service Tag
>> Util Demand
>> %
>> 14066.29 10^6bits/s 3.49 0.651 "before"
>> 20618.16 10^6bits/s 3.09 0.393 "after"
>>
>> For ixgbe similar results were seen:
>> Throughput Throughput Local Local Result
>> Units CPU Service Tag
>> Util Demand
>> %
>> 12879.89 10^6bits/s 10.00 0.763 "before"
>> 14286.77 10^6bits/s 5.74 0.395 "after"
>>
>> These patches all rely on the TSO_MANGLEID and GSO_PARTIAL patches so
>> I
>> would not recommend applying them until those patches have first been
>> applied.
>
> Sorry I did not see this until after I tried applying your series. :-(
>
> Maybe the two dependent patches should have been in the series, so I
> and others do not waste their time. Or not send this until the two
> patches were accepted.
Sorry I meant to send these as an RFC but sent it out with the
next-queue tag as I had gotten a bit distracted.
I shouldn't need to resubmit these until the other patches are
accepted so I will probably follow that route.
Thanks.
- Alex
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2016-04-09 15:41 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20160408203013.12838.63429.stgit@ahduyck-xeon-server>
2016-04-08 21:06 ` [Intel-wired-lan] [next-queue PATCH 0/3] Add support for GSO partial to Intel NIC drivers Alexander Duyck
2016-04-08 21:06 ` [Intel-wired-lan] [next-queue PATCH 1/3] i40e/i40evf: Add support for GSO partial with UDP_TUNNEL_CSUM and GRE_CSUM Alexander Duyck
2016-04-09 6:51 ` Jeff Kirsher
2016-04-08 21:06 ` [Intel-wired-lan] [next-queue PATCH 2/3] ixgbe/ixgbevf: Add support for GSO partial Alexander Duyck
2016-04-09 6:53 ` Jeff Kirsher
2016-04-08 21:06 ` [Intel-wired-lan] [next-queue PATCH 3/3] igb/igbvf: " Alexander Duyck
2016-04-09 6:59 ` [Intel-wired-lan] [next-queue PATCH 0/3] Add support for GSO partial to Intel NIC drivers Jeff Kirsher
2016-04-09 15:41 ` Alexander Duyck
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox