bnx2x: fix checksum validation
bnx2x driver incorrectly sets ip_summed to CHECKSUM_UNNECESSARY on encapsulated segments. TCP stack happily accepts frames with bad checksums, if they are inside a GRE or IPIP encapsulation. Our understanding is that if no IP or L4 csum validation was done by the hardware, we should leave ip_summed as is (CHECKSUM_NONE), since hardware doesn't provide CHECKSUM_COMPLETE support in its cqe. Then, if IP/L4 checksumming was done by the hardware, set CHECKSUM_UNNECESSARY if no error was flagged. Patch based on findings and analysis from Robert Evans Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Eilon Greenstein <eilong@broadcom.com> Cc: Yaniv Rosner <yanivr@broadcom.com> Cc: Merav Sicron <meravs@broadcom.com> Cc: Tom Herbert <therbert@google.com> Cc: Robert Evans <evansr@google.com> Cc: Willem de Bruijn <willemb@google.com> Acked-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
954fba0274
Коммит
d6cb3e4138
|
@ -747,21 +747,6 @@ struct bnx2x_fastpath {
|
||||||
|
|
||||||
#define ETH_RX_ERROR_FALGS ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG
|
#define ETH_RX_ERROR_FALGS ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG
|
||||||
|
|
||||||
#define BNX2X_IP_CSUM_ERR(cqe) \
|
|
||||||
(!((cqe)->fast_path_cqe.status_flags & \
|
|
||||||
ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG) && \
|
|
||||||
((cqe)->fast_path_cqe.type_error_flags & \
|
|
||||||
ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG))
|
|
||||||
|
|
||||||
#define BNX2X_L4_CSUM_ERR(cqe) \
|
|
||||||
(!((cqe)->fast_path_cqe.status_flags & \
|
|
||||||
ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG) && \
|
|
||||||
((cqe)->fast_path_cqe.type_error_flags & \
|
|
||||||
ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG))
|
|
||||||
|
|
||||||
#define BNX2X_RX_CSUM_OK(cqe) \
|
|
||||||
(!(BNX2X_L4_CSUM_ERR(cqe) || BNX2X_IP_CSUM_ERR(cqe)))
|
|
||||||
|
|
||||||
#define BNX2X_PRS_FLAG_OVERETH_IPV4(flags) \
|
#define BNX2X_PRS_FLAG_OVERETH_IPV4(flags) \
|
||||||
(((le16_to_cpu(flags) & \
|
(((le16_to_cpu(flags) & \
|
||||||
PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) >> \
|
PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) >> \
|
||||||
|
|
|
@ -617,6 +617,25 @@ static int bnx2x_alloc_rx_data(struct bnx2x *bp,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe,
|
||||||
|
struct bnx2x_fastpath *fp)
|
||||||
|
{
|
||||||
|
/* Do nothing if no IP/L4 csum validation was done */
|
||||||
|
|
||||||
|
if (cqe->fast_path_cqe.status_flags &
|
||||||
|
(ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG |
|
||||||
|
ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* If both IP/L4 validation were done, check if an error was found. */
|
||||||
|
|
||||||
|
if (cqe->fast_path_cqe.type_error_flags &
|
||||||
|
(ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG |
|
||||||
|
ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG))
|
||||||
|
fp->eth_q_stats.hw_csum_err++;
|
||||||
|
else
|
||||||
|
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||||
|
}
|
||||||
|
|
||||||
int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
|
int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
|
||||||
{
|
{
|
||||||
|
@ -806,13 +825,9 @@ reuse_rx:
|
||||||
|
|
||||||
skb_checksum_none_assert(skb);
|
skb_checksum_none_assert(skb);
|
||||||
|
|
||||||
if (bp->dev->features & NETIF_F_RXCSUM) {
|
if (bp->dev->features & NETIF_F_RXCSUM)
|
||||||
|
bnx2x_csum_validate(skb, cqe, fp);
|
||||||
|
|
||||||
if (likely(BNX2X_RX_CSUM_OK(cqe)))
|
|
||||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
|
||||||
else
|
|
||||||
fp->eth_q_stats.hw_csum_err++;
|
|
||||||
}
|
|
||||||
|
|
||||||
skb_record_rx_queue(skb, fp->rx_queue);
|
skb_record_rx_queue(skb, fp->rx_queue);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче