Skip to content

Commit

Permalink
i40e/i40evf: Add exception handling for Tx checksum
Browse files Browse the repository at this point in the history
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: Alexander Duyck <aduyck@mirantis.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
  • Loading branch information
Alexander Duyck authored and Jeff Kirsher committed Feb 18, 2016
1 parent 475b420 commit 529f1f6
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 26 deletions.
34 changes: 22 additions & 12 deletions drivers/net/ethernet/intel/i40e/i40e_txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -2387,10 +2387,10 @@ static int i40e_tsyn(struct i40e_ring *tx_ring, struct sk_buff *skb,
* @tx_ring: Tx descriptor ring
* @cd_tunneling: ptr to context desc bits
**/
static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
u32 *td_cmd, u32 *td_offset,
struct i40e_ring *tx_ring,
u32 *cd_tunneling)
static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
u32 *td_cmd, u32 *td_offset,
struct i40e_ring *tx_ring,
u32 *cd_tunneling)
{
union {
struct iphdr *v4;
Expand All @@ -2407,6 +2407,9 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
__be16 frag_off;
u8 l4_proto = 0;

if (skb->ip_summed != CHECKSUM_PARTIAL)
return 0;

ip.hdr = skb_network_header(skb);
l4.hdr = skb_transport_header(skb);

Expand Down Expand Up @@ -2449,7 +2452,11 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
*tx_flags |= I40E_TX_FLAGS_UDP_TUNNEL;
break;
default:
return;
if (*tx_flags & I40E_TX_FLAGS_TSO)
return -1;

skb_checksum_help(skb);
return 0;
}

/* compute tunnel header size */
Expand Down Expand Up @@ -2513,11 +2520,16 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
break;
default:
break;
if (*tx_flags & I40E_TX_FLAGS_TSO)
return -1;
skb_checksum_help(skb);
return 0;
}

*td_cmd |= cmd;
*td_offset |= offset;

return 1;
}

/**
Expand Down Expand Up @@ -2954,12 +2966,10 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
td_cmd |= I40E_TX_DESC_CMD_ICRC;

/* Always offload the checksum, since it's in the data descriptor */
if (skb->ip_summed == CHECKSUM_PARTIAL) {
tx_flags |= I40E_TX_FLAGS_CSUM;

i40e_tx_enable_csum(skb, &tx_flags, &td_cmd, &td_offset,
tx_ring, &cd_tunneling);
}
tso = i40e_tx_enable_csum(skb, &tx_flags, &td_cmd, &td_offset,
tx_ring, &cd_tunneling);
if (tso < 0)
goto out_drop;

i40e_create_tx_ctx(tx_ring, cd_type_cmd_tso_mss,
cd_tunneling, cd_l2tag2);
Expand Down
1 change: 0 additions & 1 deletion drivers/net/ethernet/intel/i40e/i40e_txrx.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ enum i40e_dyn_idx_t {
#define DESC_NEEDED (MAX_SKB_FRAGS + 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_SW_VLAN BIT(2)
#define I40E_TX_FLAGS_TSO BIT(3)
Expand Down
35 changes: 23 additions & 12 deletions drivers/net/ethernet/intel/i40evf/i40e_txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1602,12 +1602,13 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
* @tx_flags: pointer to Tx flags currently set
* @td_cmd: Tx descriptor command bits to set
* @td_offset: Tx descriptor header offsets to set
* @tx_ring: Tx descriptor ring
* @cd_tunneling: ptr to context desc bits
**/
static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
u32 *td_cmd, u32 *td_offset,
struct i40e_ring *tx_ring,
u32 *cd_tunneling)
static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
u32 *td_cmd, u32 *td_offset,
struct i40e_ring *tx_ring,
u32 *cd_tunneling)
{
union {
struct iphdr *v4;
Expand All @@ -1624,6 +1625,9 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
__be16 frag_off;
u8 l4_proto = 0;

if (skb->ip_summed != CHECKSUM_PARTIAL)
return 0;

ip.hdr = skb_network_header(skb);
l4.hdr = skb_transport_header(skb);

Expand Down Expand Up @@ -1666,7 +1670,11 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
*tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL;
break;
default:
return;
if (*tx_flags & I40E_TX_FLAGS_TSO)
return -1;

skb_checksum_help(skb);
return 0;
}

/* compute tunnel header size */
Expand Down Expand Up @@ -1730,11 +1738,16 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
break;
default:
break;
if (*tx_flags & I40E_TX_FLAGS_TSO)
return -1;
skb_checksum_help(skb);
return 0;
}

*td_cmd |= cmd;
*td_offset |= offset;

return 1;
}

/**
Expand Down Expand Up @@ -2150,12 +2163,10 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
td_cmd |= I40E_TX_DESC_CMD_ICRC;

/* Always offload the checksum, since it's in the data descriptor */
if (skb->ip_summed == CHECKSUM_PARTIAL) {
tx_flags |= I40E_TX_FLAGS_CSUM;

i40e_tx_enable_csum(skb, &tx_flags, &td_cmd, &td_offset,
tx_ring, &cd_tunneling);
}
tso = i40e_tx_enable_csum(skb, &tx_flags, &td_cmd, &td_offset,
tx_ring, &cd_tunneling);
if (tso < 0)
goto out_drop;

i40e_create_tx_ctx(tx_ring, cd_type_cmd_tso_mss,
cd_tunneling, cd_l2tag2);
Expand Down
1 change: 0 additions & 1 deletion drivers/net/ethernet/intel/i40evf/i40e_txrx.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ enum i40e_dyn_idx_t {
#define DESC_NEEDED (MAX_SKB_FRAGS + 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_SW_VLAN BIT(2)
#define I40E_TX_FLAGS_TSO BIT(3)
Expand Down

0 comments on commit 529f1f6

Please sign in to comment.