Skip to content

Commit

Permalink
bnx2x: fix UDP csum offload
Browse files Browse the repository at this point in the history
Fixed packets parameters for FW in UDP checksum offload flow.

Do not dereference TCP headers on non TCP frames.
Reported-by: Eric Dumazet <eric.dumazet@gmail.com>

Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Vladislav Zolotarov authored and David S. Miller committed Apr 23, 2011
1 parent 13f172f commit e39aece
Showing 1 changed file with 24 additions and 10 deletions.
34 changes: 24 additions & 10 deletions drivers/net/bnx2x/bnx2x_cmn.c
Original file line number Diff line number Diff line change
Expand Up @@ -2019,15 +2019,23 @@ static inline void bnx2x_set_pbd_gso(struct sk_buff *skb,
static inline u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb,
u32 *parsing_data, u32 xmit_type)
{
*parsing_data |= ((tcp_hdrlen(skb)/4) <<
ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT) &
ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW;
*parsing_data |=
((((u8 *)skb_transport_header(skb) - skb->data) >> 1) <<
ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT) &
ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W;

*parsing_data |= ((((u8 *)tcp_hdr(skb) - skb->data) / 2) <<
ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT) &
ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W;
if (xmit_type & XMIT_CSUM_TCP) {
*parsing_data |= ((tcp_hdrlen(skb) / 4) <<
ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT) &
ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW;

return skb_transport_header(skb) + tcp_hdrlen(skb) - skb->data;
return skb_transport_header(skb) + tcp_hdrlen(skb) - skb->data;
} else
/* We support checksum offload for TCP and UDP only.
* No need to pass the UDP header length - it's a constant.
*/
return skb_transport_header(skb) +
sizeof(struct udphdr) - skb->data;
}

/**
Expand All @@ -2043,17 +2051,23 @@ static inline u8 bnx2x_set_pbd_csum(struct bnx2x *bp, struct sk_buff *skb,
struct eth_tx_parse_bd_e1x *pbd,
u32 xmit_type)
{
u8 hlen = (skb_network_header(skb) - skb->data) / 2;
u8 hlen = (skb_network_header(skb) - skb->data) >> 1;

/* for now NS flag is not used in Linux */
pbd->global_data =
(hlen | ((skb->protocol == cpu_to_be16(ETH_P_8021Q)) <<
ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT));

pbd->ip_hlen_w = (skb_transport_header(skb) -
skb_network_header(skb)) / 2;
skb_network_header(skb)) >> 1;

hlen += pbd->ip_hlen_w + tcp_hdrlen(skb) / 2;
hlen += pbd->ip_hlen_w;

/* We support checksum offload for TCP and UDP only */
if (xmit_type & XMIT_CSUM_TCP)
hlen += tcp_hdrlen(skb) / 2;
else
hlen += sizeof(struct udphdr) / 2;

pbd->total_hlen_w = cpu_to_le16(hlen);
hlen = hlen*2;
Expand Down

0 comments on commit e39aece

Please sign in to comment.