Commit 31578419 authored by Alexander Duyck's avatar Alexander Duyck Committed by Tim Gardner

i40e/i40evf: Add exception handling for Tx checksum

BugLink: http://bugs.launchpad.net/bugs/1547674

Add exception handling to the Tx checksum path so that we can handle cases
of TSO where the frame is bad, or Tx checksum where we didn't recognize a
protocol

Drop I40E_TX_FLAGS_CSUM as it is unused, move the CHECKSUM_PARTIAL check
into the function itself so that we can decrease indent.
Signed-off-by: default avatarAlexander Duyck <aduyck@mirantis.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
(cherry picked from net-next commit 529f1f65)
Signed-off-by: default avatarTim Gardner <tim.gardner@canonical.com>
parent ba493b28
...@@ -2388,10 +2388,10 @@ static int i40e_tsyn(struct i40e_ring *tx_ring, struct sk_buff *skb, ...@@ -2388,10 +2388,10 @@ static int i40e_tsyn(struct i40e_ring *tx_ring, struct sk_buff *skb,
* @tx_ring: Tx descriptor ring * @tx_ring: Tx descriptor ring
* @cd_tunneling: ptr to context desc bits * @cd_tunneling: ptr to context desc bits
**/ **/
static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
u32 *td_cmd, u32 *td_offset, u32 *td_cmd, u32 *td_offset,
struct i40e_ring *tx_ring, struct i40e_ring *tx_ring,
u32 *cd_tunneling) u32 *cd_tunneling)
{ {
union { union {
struct iphdr *v4; struct iphdr *v4;
...@@ -2408,6 +2408,9 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, ...@@ -2408,6 +2408,9 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
__be16 frag_off; __be16 frag_off;
u8 l4_proto = 0; u8 l4_proto = 0;
if (skb->ip_summed != CHECKSUM_PARTIAL)
return 0;
ip.hdr = skb_network_header(skb); ip.hdr = skb_network_header(skb);
l4.hdr = skb_transport_header(skb); l4.hdr = skb_transport_header(skb);
...@@ -2450,7 +2453,11 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, ...@@ -2450,7 +2453,11 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
*tx_flags |= I40E_TX_FLAGS_UDP_TUNNEL; *tx_flags |= I40E_TX_FLAGS_UDP_TUNNEL;
break; break;
default: default:
return; if (*tx_flags & I40E_TX_FLAGS_TSO)
return -1;
skb_checksum_help(skb);
return 0;
} }
/* compute tunnel header size */ /* compute tunnel header size */
...@@ -2514,11 +2521,16 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, ...@@ -2514,11 +2521,16 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT; I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
break; break;
default: default:
break; if (*tx_flags & I40E_TX_FLAGS_TSO)
return -1;
skb_checksum_help(skb);
return 0;
} }
*td_cmd |= cmd; *td_cmd |= cmd;
*td_offset |= offset; *td_offset |= offset;
return 1;
} }
/** /**
...@@ -2955,12 +2967,10 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb, ...@@ -2955,12 +2967,10 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
td_cmd |= I40E_TX_DESC_CMD_ICRC; td_cmd |= I40E_TX_DESC_CMD_ICRC;
/* Always offload the checksum, since it's in the data descriptor */ /* Always offload the checksum, since it's in the data descriptor */
if (skb->ip_summed == CHECKSUM_PARTIAL) { tso = i40e_tx_enable_csum(skb, &tx_flags, &td_cmd, &td_offset,
tx_flags |= I40E_TX_FLAGS_CSUM; tx_ring, &cd_tunneling);
if (tso < 0)
i40e_tx_enable_csum(skb, &tx_flags, &td_cmd, &td_offset, goto out_drop;
tx_ring, &cd_tunneling);
}
i40e_create_tx_ctx(tx_ring, cd_type_cmd_tso_mss, i40e_create_tx_ctx(tx_ring, cd_type_cmd_tso_mss,
cd_tunneling, cd_l2tag2); cd_tunneling, cd_l2tag2);
......
...@@ -153,7 +153,6 @@ enum i40e_dyn_idx_t { ...@@ -153,7 +153,6 @@ enum i40e_dyn_idx_t {
#define DESC_NEEDED (MAX_SKB_FRAGS + 4) #define DESC_NEEDED (MAX_SKB_FRAGS + 4)
#define I40E_MIN_DESC_PENDING 4 #define I40E_MIN_DESC_PENDING 4
#define I40E_TX_FLAGS_CSUM BIT(0)
#define I40E_TX_FLAGS_HW_VLAN BIT(1) #define I40E_TX_FLAGS_HW_VLAN BIT(1)
#define I40E_TX_FLAGS_SW_VLAN BIT(2) #define I40E_TX_FLAGS_SW_VLAN BIT(2)
#define I40E_TX_FLAGS_TSO BIT(3) #define I40E_TX_FLAGS_TSO BIT(3)
......
...@@ -1603,12 +1603,13 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, ...@@ -1603,12 +1603,13 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
* @tx_flags: pointer to Tx flags currently set * @tx_flags: pointer to Tx flags currently set
* @td_cmd: Tx descriptor command bits to set * @td_cmd: Tx descriptor command bits to set
* @td_offset: Tx descriptor header offsets to set * @td_offset: Tx descriptor header offsets to set
* @tx_ring: Tx descriptor ring
* @cd_tunneling: ptr to context desc bits * @cd_tunneling: ptr to context desc bits
**/ **/
static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
u32 *td_cmd, u32 *td_offset, u32 *td_cmd, u32 *td_offset,
struct i40e_ring *tx_ring, struct i40e_ring *tx_ring,
u32 *cd_tunneling) u32 *cd_tunneling)
{ {
union { union {
struct iphdr *v4; struct iphdr *v4;
...@@ -1625,6 +1626,9 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, ...@@ -1625,6 +1626,9 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
__be16 frag_off; __be16 frag_off;
u8 l4_proto = 0; u8 l4_proto = 0;
if (skb->ip_summed != CHECKSUM_PARTIAL)
return 0;
ip.hdr = skb_network_header(skb); ip.hdr = skb_network_header(skb);
l4.hdr = skb_transport_header(skb); l4.hdr = skb_transport_header(skb);
...@@ -1667,7 +1671,11 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, ...@@ -1667,7 +1671,11 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
*tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL; *tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL;
break; break;
default: default:
return; if (*tx_flags & I40E_TX_FLAGS_TSO)
return -1;
skb_checksum_help(skb);
return 0;
} }
/* compute tunnel header size */ /* compute tunnel header size */
...@@ -1731,11 +1739,16 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, ...@@ -1731,11 +1739,16 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT; I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
break; break;
default: default:
break; if (*tx_flags & I40E_TX_FLAGS_TSO)
return -1;
skb_checksum_help(skb);
return 0;
} }
*td_cmd |= cmd; *td_cmd |= cmd;
*td_offset |= offset; *td_offset |= offset;
return 1;
} }
/** /**
...@@ -2151,12 +2164,10 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb, ...@@ -2151,12 +2164,10 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
td_cmd |= I40E_TX_DESC_CMD_ICRC; td_cmd |= I40E_TX_DESC_CMD_ICRC;
/* Always offload the checksum, since it's in the data descriptor */ /* Always offload the checksum, since it's in the data descriptor */
if (skb->ip_summed == CHECKSUM_PARTIAL) { tso = i40e_tx_enable_csum(skb, &tx_flags, &td_cmd, &td_offset,
tx_flags |= I40E_TX_FLAGS_CSUM; tx_ring, &cd_tunneling);
if (tso < 0)
i40e_tx_enable_csum(skb, &tx_flags, &td_cmd, &td_offset, goto out_drop;
tx_ring, &cd_tunneling);
}
i40e_create_tx_ctx(tx_ring, cd_type_cmd_tso_mss, i40e_create_tx_ctx(tx_ring, cd_type_cmd_tso_mss,
cd_tunneling, cd_l2tag2); cd_tunneling, cd_l2tag2);
......
...@@ -153,7 +153,6 @@ enum i40e_dyn_idx_t { ...@@ -153,7 +153,6 @@ enum i40e_dyn_idx_t {
#define DESC_NEEDED (MAX_SKB_FRAGS + 4) #define DESC_NEEDED (MAX_SKB_FRAGS + 4)
#define I40E_MIN_DESC_PENDING 4 #define I40E_MIN_DESC_PENDING 4
#define I40E_TX_FLAGS_CSUM BIT(0)
#define I40E_TX_FLAGS_HW_VLAN BIT(1) #define I40E_TX_FLAGS_HW_VLAN BIT(1)
#define I40E_TX_FLAGS_SW_VLAN BIT(2) #define I40E_TX_FLAGS_SW_VLAN BIT(2)
#define I40E_TX_FLAGS_TSO BIT(3) #define I40E_TX_FLAGS_TSO BIT(3)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment