net/mlx5e: Fix checksum handling for non-stripped vlan packets
authorSaeed Mahameed <saeedm@mellanox.com>
Sun, 24 Apr 2016 19:51:56 +0000 (22:51 +0300)
committerDavid S. Miller <davem@davemloft.net>
Tue, 26 Apr 2016 19:58:03 +0000 (15:58 -0400)
Now as rx-vlan offload can be disabled, packets can be received
with vlan tag not stripped, which means is_first_ethertype_ip will
return false, for that we need to check if the hardware reported
csum OK so we will report CHECKSUM_UNNECESSARY for those packets.

Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
include/linux/mlx5/device.h

index 6c9c10c131a05f9be6597bf89cc32f39b1ffbe22..5bad17d37d7bcb590fedf465d17e3ee3b8d9148a 100644 (file)
@@ -109,6 +109,7 @@ static void mlx5e_update_sw_counters(struct mlx5e_priv *priv)
                s->lro_bytes    += rq_stats->lro_bytes;
                s->rx_csum_none += rq_stats->csum_none;
                s->rx_csum_sw   += rq_stats->csum_sw;
+               s->rx_csum_inner += rq_stats->csum_inner;
                s->rx_wqe_err   += rq_stats->wqe_err;
                s->rx_mpwqe_filler += rq_stats->mpwqe_filler;
                s->rx_mpwqe_frag   += rq_stats->mpwqe_frag;
index 918b7c7fd74ff688f9fad43b96142be07bd41fe8..23adfe2fcba97d10b34606f6a957ae75e977ca06 100644 (file)
@@ -543,16 +543,26 @@ static inline void mlx5e_handle_csum(struct net_device *netdev,
 
        if (lro) {
                skb->ip_summed = CHECKSUM_UNNECESSARY;
-       } else if (likely(is_first_ethertype_ip(skb))) {
+               return;
+       }
+
+       if (is_first_ethertype_ip(skb)) {
                skb->ip_summed = CHECKSUM_COMPLETE;
                skb->csum = csum_unfold((__force __sum16)cqe->check_sum);
                rq->stats.csum_sw++;
-       } else {
-               goto csum_none;
+               return;
        }
 
-       return;
-
+       if (likely((cqe->hds_ip_ext & CQE_L3_OK) &&
+                  (cqe->hds_ip_ext & CQE_L4_OK))) {
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+               if (cqe_is_tunneled(cqe)) {
+                       skb->csum_level = 1;
+                       skb->encapsulation = 1;
+                       rq->stats.csum_inner++;
+               }
+               return;
+       }
 csum_none:
        skb->ip_summed = CHECKSUM_NONE;
        rq->stats.csum_none++;
index 7cd8cb44b2ab9488f03ce43529d0d4f88ea0cbe0..115752b53d852817be082983c2b3a835565da0c9 100644 (file)
@@ -62,6 +62,7 @@ struct mlx5e_sw_stats {
        u64 rx_csum_good;
        u64 rx_csum_none;
        u64 rx_csum_sw;
+       u64 rx_csum_inner;
        u64 tx_csum_offload;
        u64 tx_csum_inner;
        u64 tx_queue_stopped;
@@ -90,6 +91,7 @@ static const struct counter_desc sw_stats_desc[] = {
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_csum_good) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_csum_none) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_csum_sw) },
+       { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_csum_inner) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_csum_offload) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_csum_inner) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_queue_stopped) },
@@ -272,8 +274,9 @@ static const struct counter_desc pport_per_prio_pfc_stats_desc[] = {
 struct mlx5e_rq_stats {
        u64 packets;
        u64 bytes;
-       u64 csum_none;
        u64 csum_sw;
+       u64 csum_inner;
+       u64 csum_none;
        u64 lro_packets;
        u64 lro_bytes;
        u64 wqe_err;
@@ -285,8 +288,9 @@ struct mlx5e_rq_stats {
 static const struct counter_desc rq_stats_desc[] = {
        { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, packets) },
        { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, bytes) },
-       { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, csum_none) },
        { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, csum_sw) },
+       { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, csum_inner) },
+       { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, csum_none) },
        { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, lro_packets) },
        { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, lro_bytes) },
        { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, wqe_err) },
index 942bccacd7b773f2313aa610166d4d93316ebfae..6bd429b53b77e1b162c1614879f253f6c1d50c2d 100644 (file)
@@ -645,8 +645,9 @@ struct mlx5_err_cqe {
 };
 
 struct mlx5_cqe64 {
-       u8              rsvd0[2];
-       __be16          wqe_id;
+       u8              outer_l3_tunneled;
+       u8              rsvd0;
+       __be16          wqe_id;
        u8              lro_tcppsh_abort_dupack;
        u8              lro_min_ttl;
        __be16          lro_tcp_win;
@@ -659,7 +660,7 @@ struct mlx5_cqe64 {
        __be16          slid;
        __be32          flags_rqpn;
        u8              hds_ip_ext;
-       u8              l4_hdr_type_etc;
+       u8              l4_l3_hdr_type;
        __be16          vlan_info;
        __be32          srqn; /* [31:24]: lro_num_seg, [23:0]: srqn */
        __be32          imm_inval_pkey;
@@ -680,12 +681,22 @@ static inline int get_cqe_lro_tcppsh(struct mlx5_cqe64 *cqe)
 
 static inline u8 get_cqe_l4_hdr_type(struct mlx5_cqe64 *cqe)
 {
-       return (cqe->l4_hdr_type_etc >> 4) & 0x7;
+       return (cqe->l4_l3_hdr_type >> 4) & 0x7;
+}
+
+static inline u8 get_cqe_l3_hdr_type(struct mlx5_cqe64 *cqe)
+{
+       return (cqe->l4_l3_hdr_type >> 2) & 0x3;
+}
+
+static inline u8 cqe_is_tunneled(struct mlx5_cqe64 *cqe)
+{
+       return cqe->outer_l3_tunneled & 0x1;
 }
 
 static inline int cqe_has_vlan(struct mlx5_cqe64 *cqe)
 {
-       return !!(cqe->l4_hdr_type_etc & 0x1);
+       return !!(cqe->l4_l3_hdr_type & 0x1);
 }
 
 static inline u64 get_cqe_ts(struct mlx5_cqe64 *cqe)