diff options
Diffstat (limited to 'drivers/net/ethernet/intel/i40evf/i40e_txrx.c')
-rw-r--r-- | drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 74 |
1 files changed, 55 insertions, 19 deletions
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index ae089df7df19..48ebb6cd69f2 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c | |||
@@ -728,10 +728,12 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi, | |||
728 | u32 rx_error, | 728 | u32 rx_error, |
729 | u16 rx_ptype) | 729 | u16 rx_ptype) |
730 | { | 730 | { |
731 | struct i40e_rx_ptype_decoded decoded = decode_rx_desc_ptype(rx_ptype); | ||
732 | bool ipv4 = false, ipv6 = false; | ||
731 | bool ipv4_tunnel, ipv6_tunnel; | 733 | bool ipv4_tunnel, ipv6_tunnel; |
732 | __wsum rx_udp_csum; | 734 | __wsum rx_udp_csum; |
733 | __sum16 csum; | ||
734 | struct iphdr *iph; | 735 | struct iphdr *iph; |
736 | __sum16 csum; | ||
735 | 737 | ||
736 | ipv4_tunnel = (rx_ptype > I40E_RX_PTYPE_GRENAT4_MAC_PAY3) && | 738 | ipv4_tunnel = (rx_ptype > I40E_RX_PTYPE_GRENAT4_MAC_PAY3) && |
737 | (rx_ptype < I40E_RX_PTYPE_GRENAT4_MACVLAN_IPV6_ICMP_PAY4); | 739 | (rx_ptype < I40E_RX_PTYPE_GRENAT4_MACVLAN_IPV6_ICMP_PAY4); |
@@ -742,29 +744,57 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi, | |||
742 | skb->ip_summed = CHECKSUM_NONE; | 744 | skb->ip_summed = CHECKSUM_NONE; |
743 | 745 | ||
744 | /* Rx csum enabled and ip headers found? */ | 746 | /* Rx csum enabled and ip headers found? */ |
745 | if (!(vsi->netdev->features & NETIF_F_RXCSUM && | 747 | if (!(vsi->netdev->features & NETIF_F_RXCSUM)) |
746 | rx_status & (1 << I40E_RX_DESC_STATUS_L3L4P_SHIFT))) | 748 | return; |
749 | |||
750 | /* did the hardware decode the packet and checksum? */ | ||
751 | if (!(rx_status & (1 << I40E_RX_DESC_STATUS_L3L4P_SHIFT))) | ||
752 | return; | ||
753 | |||
754 | /* both known and outer_ip must be set for the below code to work */ | ||
755 | if (!(decoded.known && decoded.outer_ip)) | ||
747 | return; | 756 | return; |
748 | 757 | ||
758 | if (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP && | ||
759 | decoded.outer_ip_ver == I40E_RX_PTYPE_OUTER_IPV4) | ||
760 | ipv4 = true; | ||
761 | else if (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP && | ||
762 | decoded.outer_ip_ver == I40E_RX_PTYPE_OUTER_IPV6) | ||
763 | ipv6 = true; | ||
764 | |||
765 | if (ipv4 && | ||
766 | (rx_error & ((1 << I40E_RX_DESC_ERROR_IPE_SHIFT) | | ||
767 | (1 << I40E_RX_DESC_ERROR_EIPE_SHIFT)))) | ||
768 | goto checksum_fail; | ||
769 | |||
749 | /* likely incorrect csum if alternate IP extension headers found */ | 770 | /* likely incorrect csum if alternate IP extension headers found */ |
750 | if (rx_status & (1 << I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT)) | 771 | if (ipv6 && |
772 | decoded.inner_prot == I40E_RX_PTYPE_INNER_PROT_TCP && | ||
773 | rx_error & (1 << I40E_RX_DESC_ERROR_L4E_SHIFT) && | ||
774 | rx_status & (1 << I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT)) | ||
775 | /* don't increment checksum err here, non-fatal err */ | ||
751 | return; | 776 | return; |
752 | 777 | ||
753 | /* IP or L4 or outmost IP checksum error */ | 778 | /* there was some L4 error, count error and punt packet to the stack */ |
754 | if (rx_error & ((1 << I40E_RX_DESC_ERROR_IPE_SHIFT) | | 779 | if (rx_error & (1 << I40E_RX_DESC_ERROR_L4E_SHIFT)) |
755 | (1 << I40E_RX_DESC_ERROR_L4E_SHIFT) | | 780 | goto checksum_fail; |
756 | (1 << I40E_RX_DESC_ERROR_EIPE_SHIFT))) { | 781 | |
757 | vsi->back->hw_csum_rx_error++; | 782 | /* handle packets that were not able to be checksummed due |
783 | * to arrival speed, in this case the stack can compute | ||
784 | * the csum. | ||
785 | */ | ||
786 | if (rx_error & (1 << I40E_RX_DESC_ERROR_PPRS_SHIFT)) | ||
758 | return; | 787 | return; |
759 | } | ||
760 | 788 | ||
789 | /* If VXLAN traffic has an outer UDPv4 checksum we need to check | ||
790 | * it in the driver, hardware does not do it for us. | ||
791 | * Since L3L4P bit was set we assume a valid IHL value (>=5) | ||
792 | * so the total length of IPv4 header is IHL*4 bytes | ||
793 | * The UDP_0 bit *may* bet set if the *inner* header is UDP | ||
794 | */ | ||
761 | if (ipv4_tunnel && | 795 | if (ipv4_tunnel && |
796 | (decoded.inner_prot != I40E_RX_PTYPE_INNER_PROT_UDP) && | ||
762 | !(rx_status & (1 << I40E_RX_DESC_STATUS_UDP_0_SHIFT))) { | 797 | !(rx_status & (1 << I40E_RX_DESC_STATUS_UDP_0_SHIFT))) { |
763 | /* If VXLAN traffic has an outer UDPv4 checksum we need to check | ||
764 | * it in the driver, hardware does not do it for us. | ||
765 | * Since L3L4P bit was set we assume a valid IHL value (>=5) | ||
766 | * so the total length of IPv4 header is IHL*4 bytes | ||
767 | */ | ||
768 | skb->transport_header = skb->mac_header + | 798 | skb->transport_header = skb->mac_header + |
769 | sizeof(struct ethhdr) + | 799 | sizeof(struct ethhdr) + |
770 | (ip_hdr(skb)->ihl * 4); | 800 | (ip_hdr(skb)->ihl * 4); |
@@ -781,13 +811,16 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi, | |||
781 | (skb->len - skb_transport_offset(skb)), | 811 | (skb->len - skb_transport_offset(skb)), |
782 | IPPROTO_UDP, rx_udp_csum); | 812 | IPPROTO_UDP, rx_udp_csum); |
783 | 813 | ||
784 | if (udp_hdr(skb)->check != csum) { | 814 | if (udp_hdr(skb)->check != csum) |
785 | vsi->back->hw_csum_rx_error++; | 815 | goto checksum_fail; |
786 | return; | ||
787 | } | ||
788 | } | 816 | } |
789 | 817 | ||
790 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 818 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
819 | |||
820 | return; | ||
821 | |||
822 | checksum_fail: | ||
823 | vsi->back->hw_csum_rx_error++; | ||
791 | } | 824 | } |
792 | 825 | ||
793 | /** | 826 | /** |
@@ -956,6 +989,9 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) | |||
956 | /* ERR_MASK will only have valid bits if EOP set */ | 989 | /* ERR_MASK will only have valid bits if EOP set */ |
957 | if (unlikely(rx_error & (1 << I40E_RX_DESC_ERROR_RXE_SHIFT))) { | 990 | if (unlikely(rx_error & (1 << I40E_RX_DESC_ERROR_RXE_SHIFT))) { |
958 | dev_kfree_skb_any(skb); | 991 | dev_kfree_skb_any(skb); |
992 | /* TODO: shouldn't we increment a counter indicating the | ||
993 | * drop? | ||
994 | */ | ||
959 | goto next_desc; | 995 | goto next_desc; |
960 | } | 996 | } |
961 | 997 | ||