net: ena: use CSUM_CHECKED device indication to report skb's checksum status
authorArthur Kiyanovski <akiyano@amazon.com>
Thu, 11 Oct 2018 08:26:21 +0000 (11:26 +0300)
committerDavid S. Miller <davem@davemloft.net>
Thu, 11 Oct 2018 17:13:51 +0000 (10:13 -0700)
Set skb->ip_summed to the correct value as reported by the device.
Add counter for the case where rx csum offload is enabled but
device didn't check it.

Signed-off-by: Arthur Kiyanovski <akiyano@amazon.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/amazon/ena/ena_eth_com.c
drivers/net/ethernet/amazon/ena/ena_eth_com.h
drivers/net/ethernet/amazon/ena/ena_eth_io_defs.h
drivers/net/ethernet/amazon/ena/ena_ethtool.c
drivers/net/ethernet/amazon/ena/ena_netdev.c
drivers/net/ethernet/amazon/ena/ena_netdev.h

index 2a53b549e55a934129a1b006b8d2c00c3c46e3fb..6f8e15b9b3cf7bf03d00981f73bd6794a7e57ec6 100644 (file)
@@ -354,6 +354,9 @@ static inline void ena_com_rx_set_flags(struct ena_com_rx_ctx *ena_rx_ctx,
        ena_rx_ctx->l4_csum_err =
                (cdesc->status & ENA_ETH_IO_RX_CDESC_BASE_L4_CSUM_ERR_MASK) >>
                ENA_ETH_IO_RX_CDESC_BASE_L4_CSUM_ERR_SHIFT;
+       ena_rx_ctx->l4_csum_checked =
+               !!((cdesc->status & ENA_ETH_IO_RX_CDESC_BASE_L4_CSUM_CHECKED_MASK) >>
+               ENA_ETH_IO_RX_CDESC_BASE_L4_CSUM_CHECKED_SHIFT);
        ena_rx_ctx->hash = cdesc->hash;
        ena_rx_ctx->frag =
                (cdesc->status & ENA_ETH_IO_RX_CDESC_BASE_IPV4_FRAG_MASK) >>
index bcc84072367dfc316fc3d44a46dfd5032b596bea..340d02b64ca69293fdb5f579f9247002203f168c 100644 (file)
@@ -67,6 +67,7 @@ struct ena_com_rx_ctx {
        enum ena_eth_io_l4_proto_index l4_proto;
        bool l3_csum_err;
        bool l4_csum_err;
+       u8 l4_csum_checked;
        /* fragmented packet */
        bool frag;
        u32 hash;
index f320c58793a521004cc358a47f88b161fd919dc4..4c5ccaa13c42a66b66f83a227174c24a68ff486f 100644 (file)
@@ -242,9 +242,13 @@ struct ena_eth_io_rx_cdesc_base {
         *    checksum error detected, or, the controller didn't
         *    validate the checksum. This bit is valid only when
         *    l4_proto_idx indicates TCP/UDP packet, and,
-        *    ipv4_frag is not set
+        *    ipv4_frag is not set. This bit is valid only when
+        *    l4_csum_checked below is set.
         * 15 : ipv4_frag - Indicates IPv4 fragmented packet
-        * 23:16 : reserved16
+        * 16 : l4_csum_checked - L4 checksum was verified
+        *    (could be OK or error), when cleared the status of
+        *    checksum is unknown
+        * 23:17 : reserved17 - MBZ
         * 24 : phase
         * 25 : l3_csum2 - second checksum engine result
         * 26 : first - Indicates first descriptor in
@@ -390,6 +394,8 @@ struct ena_eth_io_numa_node_cfg_reg {
 #define ENA_ETH_IO_RX_CDESC_BASE_L4_CSUM_ERR_MASK BIT(14)
 #define ENA_ETH_IO_RX_CDESC_BASE_IPV4_FRAG_SHIFT 15
 #define ENA_ETH_IO_RX_CDESC_BASE_IPV4_FRAG_MASK BIT(15)
+#define ENA_ETH_IO_RX_CDESC_BASE_L4_CSUM_CHECKED_SHIFT 16
+#define ENA_ETH_IO_RX_CDESC_BASE_L4_CSUM_CHECKED_MASK BIT(16)
 #define ENA_ETH_IO_RX_CDESC_BASE_PHASE_SHIFT 24
 #define ENA_ETH_IO_RX_CDESC_BASE_PHASE_MASK BIT(24)
 #define ENA_ETH_IO_RX_CDESC_BASE_L3_CSUM2_SHIFT 25
index fd28bd0d1c1ed7b773ae9b49360d39d11d1f3ab6..f3a5a384e6e8f9d8620a81676c603b767e7e66ff 100644 (file)
@@ -97,6 +97,7 @@ static const struct ena_stats ena_stats_rx_strings[] = {
        ENA_STAT_RX_ENTRY(rx_copybreak_pkt),
        ENA_STAT_RX_ENTRY(bad_req_id),
        ENA_STAT_RX_ENTRY(empty_rx_ring),
+       ENA_STAT_RX_ENTRY(csum_unchecked),
 };
 
 static const struct ena_stats ena_stats_ena_com_strings[] = {
index 98314b28a000fcd1578eb7df3896c282bf1840f3..eea05847d185db98952b19683b02bf8f46882430 100644 (file)
@@ -994,8 +994,19 @@ static inline void ena_rx_checksum(struct ena_ring *rx_ring,
                        return;
                }
 
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
+               if (likely(ena_rx_ctx->l4_csum_checked)) {
+                       skb->ip_summed = CHECKSUM_UNNECESSARY;
+               } else {
+                       u64_stats_update_begin(&rx_ring->syncp);
+                       rx_ring->rx_stats.csum_unchecked++;
+                       u64_stats_update_end(&rx_ring->syncp);
+                       skb->ip_summed = CHECKSUM_NONE;
+               }
+       } else {
+               skb->ip_summed = CHECKSUM_NONE;
+               return;
        }
+
 }
 
 static void ena_set_rx_hash(struct ena_ring *rx_ring,
index 4fa7d2fda4750d906758b92d1b0b905e2061b36d..2d62e2c7fed7da2c94694719219e80c7fb9d31a9 100644 (file)
@@ -205,6 +205,7 @@ struct ena_stats_rx {
        u64 rx_copybreak_pkt;
        u64 bad_req_id;
        u64 empty_rx_ring;
+       u64 csum_unchecked;
 };
 
 struct ena_ring {