net/mlx5: Add packet dropped while vport down statistics
authorMoshe Shemesh <moshe@mellanox.com>
Sat, 13 Jan 2018 22:56:25 +0000 (00:56 +0200)
committerSaeed Mahameed <saeedm@mellanox.com>
Mon, 26 Mar 2018 20:47:11 +0000 (13:47 -0700)
Added the following packets dropped while vport down statistics:

Rx dropped while vport down - counts packets which were steered by
e-switch to a vport, but dropped since the vport was down. This counter
will be shown on ip link tool as part of the vport rx_dropped counter.

Tx dropped while vport down - counts packets which were transmitted by
a vport, but dropped due to vport logical link down. This counter
will be shown on ip link tool as part of the vport tx_dropped counter.

The counters are read from FW by command QUERY_VNIC_ENV.

Signed-off-by: Moshe Shemesh <moshe@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/vport.c
include/linux/mlx5/mlx5_ifc.h
include/linux/mlx5/vport.h

index 77b7272eaaa8ba366a25503c16ffd111373892ba..332bc56306bf5cb22b2a7283f80a3b2c1f4e9a10 100644 (file)
@@ -2096,17 +2096,19 @@ unlock:
        return err;
 }
 
-static void mlx5_eswitch_query_vport_drop_stats(struct mlx5_core_dev *dev,
-                                               int vport_idx,
-                                               struct mlx5_vport_drop_stats *stats)
+static int mlx5_eswitch_query_vport_drop_stats(struct mlx5_core_dev *dev,
+                                              int vport_idx,
+                                              struct mlx5_vport_drop_stats *stats)
 {
        struct mlx5_eswitch *esw = dev->priv.eswitch;
        struct mlx5_vport *vport = &esw->vports[vport_idx];
+       u64 rx_discard_vport_down, tx_discard_vport_down;
        u64 bytes = 0;
        u16 idx = 0;
+       int err = 0;
 
        if (!vport->enabled || esw->mode != SRIOV_LEGACY)
-               return;
+               return 0;
 
        if (vport->egress.drop_counter) {
                idx = vport->egress.drop_counter->id;
@@ -2117,6 +2119,23 @@ static void mlx5_eswitch_query_vport_drop_stats(struct mlx5_core_dev *dev,
                idx = vport->ingress.drop_counter->id;
                mlx5_fc_query(dev, idx, &stats->tx_dropped, &bytes);
        }
+
+       if (!MLX5_CAP_GEN(dev, receive_discard_vport_down) &&
+           !MLX5_CAP_GEN(dev, transmit_discard_vport_down))
+               return 0;
+
+       err = mlx5_query_vport_down_stats(dev, vport_idx,
+                                         &rx_discard_vport_down,
+                                         &tx_discard_vport_down);
+       if (err)
+               return err;
+
+       if (MLX5_CAP_GEN(dev, receive_discard_vport_down))
+               stats->rx_dropped += rx_discard_vport_down;
+       if (MLX5_CAP_GEN(dev, transmit_discard_vport_down))
+               stats->tx_dropped += tx_discard_vport_down;
+
+       return 0;
 }
 
 int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
@@ -2180,7 +2199,9 @@ int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
        vf_stats->broadcast =
                MLX5_GET_CTR(out, received_eth_broadcast.packets);
 
-       mlx5_eswitch_query_vport_drop_stats(esw->dev, vport, &stats);
+       err = mlx5_eswitch_query_vport_drop_stats(esw->dev, vport, &stats);
+       if (err)
+               goto free_out;
        vf_stats->rx_dropped = stats.rx_dropped;
        vf_stats->tx_dropped = stats.tx_dropped;
 
index dfe36cf6fbeab1813975652ba10250ab2fb0afbf..177e076b8d17f88d4f8b3a86692cf965bbc7333e 100644 (file)
@@ -1070,6 +1070,32 @@ free:
 }
 EXPORT_SYMBOL_GPL(mlx5_core_query_vport_counter);
 
+int mlx5_query_vport_down_stats(struct mlx5_core_dev *mdev, u16 vport,
+                               u64 *rx_discard_vport_down,
+                               u64 *tx_discard_vport_down)
+{
+       u32 out[MLX5_ST_SZ_DW(query_vnic_env_out)] = {0};
+       u32 in[MLX5_ST_SZ_DW(query_vnic_env_in)] = {0};
+       int err;
+
+       MLX5_SET(query_vnic_env_in, in, opcode,
+                MLX5_CMD_OP_QUERY_VNIC_ENV);
+       MLX5_SET(query_vnic_env_in, in, op_mod, 0);
+       MLX5_SET(query_vnic_env_in, in, vport_number, vport);
+       if (vport)
+               MLX5_SET(query_vnic_env_in, in, other_vport, 1);
+
+       err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
+       if (err)
+               return err;
+
+       *rx_discard_vport_down = MLX5_GET64(query_vnic_env_out, out,
+                                           vport_env.receive_discard_vport_down);
+       *tx_discard_vport_down = MLX5_GET64(query_vnic_env_out, out,
+                                           vport_env.transmit_discard_vport_down);
+       return 0;
+}
+
 int mlx5_core_modify_hca_vport_context(struct mlx5_core_dev *dev,
                                       u8 other_vport, u8 port_num,
                                       int vf,
index 9202113f552c438237683cc7575642c054725121..1f3483d40055f84b0b063d2503bc521db540412c 100644 (file)
@@ -1009,7 +1009,9 @@ struct mlx5_ifc_cmd_hca_cap_bits {
        u8         log_max_xrcd[0x5];
 
        u8         nic_receive_steering_discard[0x1];
-       u8         reserved_at_341[0x7];
+       u8         receive_discard_vport_down[0x1];
+       u8         transmit_discard_vport_down[0x1];
+       u8         reserved_at_343[0x5];
        u8         log_max_flow_counter_bulk[0x8];
        u8         max_flow_counter_15_0[0x10];
 
index 64e193e8739471b1f003234bf4501adab7d61ede..9208cb8809ac49b4cc2008455e991ecae7388559 100644 (file)
@@ -107,6 +107,9 @@ int mlx5_modify_nic_vport_vlans(struct mlx5_core_dev *dev,
 
 int mlx5_nic_vport_enable_roce(struct mlx5_core_dev *mdev);
 int mlx5_nic_vport_disable_roce(struct mlx5_core_dev *mdev);
+int mlx5_query_vport_down_stats(struct mlx5_core_dev *mdev, u16 vport,
+                               u64 *rx_discard_vport_down,
+                               u64 *tx_discard_vport_down);
 int mlx5_core_query_vport_counter(struct mlx5_core_dev *dev, u8 other_vport,
                                  int vf, u8 port_num, void *out,
                                  size_t out_sz);