diff options
author | David S. Miller <davem@davemloft.net> | 2013-02-10 20:14:46 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-02-10 20:14:46 -0500 |
commit | 839c8cc32bc252345f4d5767d2d6cf695f2124ab (patch) | |
tree | d7b0904cf9f44ab1fa5caaca7ba912ad0e944c9e | |
parent | 3955b22b9798ae8694ac053614694695991f0a91 (diff) | |
parent | 0aba93e2b9fb0be4f4dd1b52ef10d789edf15f74 (diff) |
Merge branch 'gso_type'
Michael S. Tsirkin says:
====================
At the moment, macvtap crashes are observed if macvtap is attached
to an interface with LRO enabled.
The crash in question is BUG() in macvtap_skb_to_vnet_hdr.
This happens because several drivers set gso_size but not gso_type
in incoming skbs.
This didn't use to be the case: with intel cards on 3.2 and older
kernels, with qlogic - on 3.4 and older kernels, so it's a regression if
not a recent one.
The following patches fix this for qlogic, broadcom and intel drivers.
I tested that the patch fixes the crash for ixgbe but
don't have qlogic/broadcom hardware to test.
I also only tested TCPv4.
Please review, and consider for 3.8.
Changes from v1:
- added missing htons as suggested by Eric
- backported the relevant bits from
cbf1de72324a8105ddcc3d9ce9acbc613faea17e for bnx2x
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 12 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | 7 |
3 files changed, 17 insertions, 10 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index f771ddfba646..a5edac8df67b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -504,13 +504,11 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp, skb_shinfo(skb)->gso_size = bnx2x_set_lro_mss(bp, tpa_info->parsing_flags, len_on_bd); - /* set for GRO */ - if (fp->mode == TPA_MODE_GRO) - skb_shinfo(skb)->gso_type = - (GET_FLAG(tpa_info->parsing_flags, - PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) == - PRS_FLAG_OVERETH_IPV6) ? - SKB_GSO_TCPV6 : SKB_GSO_TCPV4; + skb_shinfo(skb)->gso_type = + (GET_FLAG(tpa_info->parsing_flags, + PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) == + PRS_FLAG_OVERETH_IPV6) ? + SKB_GSO_TCPV6 : SKB_GSO_TCPV4; } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 20a5af6d87d0..e1b2d22a2850 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1401,6 +1401,10 @@ static void ixgbe_set_rsc_gso_size(struct ixgbe_ring *ring, /* set gso_size to avoid messing up TCP MSS */ skb_shinfo(skb)->gso_size = DIV_ROUND_UP((skb->len - hdr_len), IXGBE_CB(skb)->append_cnt); + if (skb->protocol == __constant_htons(ETH_P_IPV6)) + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; + else + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; } static void ixgbe_update_rsc_stats(struct ixgbe_ring *rx_ring, @@ -1435,6 +1439,8 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring, { struct net_device *dev = rx_ring->netdev; + skb->protocol = eth_type_trans(skb, dev); + ixgbe_update_rsc_stats(rx_ring, skb); ixgbe_rx_hash(rx_ring, rx_desc, skb); @@ -1450,8 +1456,6 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring, } skb_record_rx_queue(skb, rx_ring->queue_index); - - skb->protocol = eth_type_trans(skb, dev); } static void ixgbe_rx_skb(struct ixgbe_q_vector *q_vector, diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c index 6f82812d0fab..09aa310b6194 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c @@ -986,8 +986,13 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, th->seq = htonl(seq_number); length = skb->len; - if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) + if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) { skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1); + if (skb->protocol == htons(ETH_P_IPV6)) + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; + else + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; + } if (vid != 0xffff) __vlan_hwaccel_put_tag(skb, vid); |