diff options
author | Eric Dumazet <edumazet@google.com> | 2012-06-12 19:50:04 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-06-13 18:58:53 -0400 |
commit | d6cb3e41386f20fb0777d0b59a2def82c65d37f7 (patch) | |
tree | f1a04833d77287468411c68fd780b95976e4bf59 /drivers/net/ethernet/broadcom/bnx2x | |
parent | 954fba0274058d27c7c07b5ea07c41b3b7477894 (diff) |
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>
Diffstat (limited to 'drivers/net/ethernet/broadcom/bnx2x')
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 15 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 27 |
2 files changed, 21 insertions, 21 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index e30e2a2f354c..7de824184979 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | |||
@@ -747,21 +747,6 @@ struct bnx2x_fastpath { | |||
747 | 747 | ||
748 | #define ETH_RX_ERROR_FALGS ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG | 748 | #define ETH_RX_ERROR_FALGS ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG |
749 | 749 | ||
750 | #define BNX2X_IP_CSUM_ERR(cqe) \ | ||
751 | (!((cqe)->fast_path_cqe.status_flags & \ | ||
752 | ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG) && \ | ||
753 | ((cqe)->fast_path_cqe.type_error_flags & \ | ||
754 | ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG)) | ||
755 | |||
756 | #define BNX2X_L4_CSUM_ERR(cqe) \ | ||
757 | (!((cqe)->fast_path_cqe.status_flags & \ | ||
758 | ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG) && \ | ||
759 | ((cqe)->fast_path_cqe.type_error_flags & \ | ||
760 | ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG)) | ||
761 | |||
762 | #define BNX2X_RX_CSUM_OK(cqe) \ | ||
763 | (!(BNX2X_L4_CSUM_ERR(cqe) || BNX2X_IP_CSUM_ERR(cqe))) | ||
764 | |||
765 | #define BNX2X_PRS_FLAG_OVERETH_IPV4(flags) \ | 750 | #define BNX2X_PRS_FLAG_OVERETH_IPV4(flags) \ |
766 | (((le16_to_cpu(flags) & \ | 751 | (((le16_to_cpu(flags) & \ |
767 | PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) >> \ | 752 | PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) >> \ |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index ad0743bf4bde..cbc56f274e0c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | |||
@@ -617,6 +617,25 @@ static int bnx2x_alloc_rx_data(struct bnx2x *bp, | |||
617 | return 0; | 617 | return 0; |
618 | } | 618 | } |
619 | 619 | ||
620 | static void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe, | ||
621 | struct bnx2x_fastpath *fp) | ||
622 | { | ||
623 | /* Do nothing if no IP/L4 csum validation was done */ | ||
624 | |||
625 | if (cqe->fast_path_cqe.status_flags & | ||
626 | (ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG | | ||
627 | ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG)) | ||
628 | return; | ||
629 | |||
630 | /* If both IP/L4 validation were done, check if an error was found. */ | ||
631 | |||
632 | if (cqe->fast_path_cqe.type_error_flags & | ||
633 | (ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG | | ||
634 | ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG)) | ||
635 | fp->eth_q_stats.hw_csum_err++; | ||
636 | else | ||
637 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
638 | } | ||
620 | 639 | ||
621 | int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) | 640 | int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) |
622 | { | 641 | { |
@@ -806,13 +825,9 @@ reuse_rx: | |||
806 | 825 | ||
807 | skb_checksum_none_assert(skb); | 826 | skb_checksum_none_assert(skb); |
808 | 827 | ||
809 | if (bp->dev->features & NETIF_F_RXCSUM) { | 828 | if (bp->dev->features & NETIF_F_RXCSUM) |
829 | bnx2x_csum_validate(skb, cqe, fp); | ||
810 | 830 | ||
811 | if (likely(BNX2X_RX_CSUM_OK(cqe))) | ||
812 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
813 | else | ||
814 | fp->eth_q_stats.hw_csum_err++; | ||
815 | } | ||
816 | 831 | ||
817 | skb_record_rx_queue(skb, fp->rx_queue); | 832 | skb_record_rx_queue(skb, fp->rx_queue); |
818 | 833 | ||