On 02/08/2025 9:30, Vadim Fedorenko wrote:
diff --git a/Documentation/networking/ethtool-netlink.rst 
b/Documentation/networking/ethtool-netlink.rst
index ab20c644af248..b270886c5f5d5 100644
--- a/Documentation/networking/ethtool-netlink.rst
+++ b/Documentation/networking/ethtool-netlink.rst
@@ -1541,6 +1541,11 @@ Drivers fill in the statistics in the following 
structure:
  .. kernel-doc:: include/linux/ethtool.h
      :identifiers: ethtool_fec_stats
+Statistics may have FEC bins histogram attribute ``ETHTOOL_A_FEC_STAT_HIST``
+as defined in IEEE 802.3ck-2022 and 802.3df-2024. Nested attributes will have
+the range of FEC errors in the bin (inclusive) and the amount of error events
+in the bin.
+

Maybe worth mentioning per-lane histograms here.

  FEC_SET
  =======
diff --git a/drivers/net/netdevsim/ethtool.c b/drivers/net/netdevsim/ethtool.c
index f631d90c428ac..1dc9a6c126b24 100644
--- a/drivers/net/netdevsim/ethtool.c
+++ b/drivers/net/netdevsim/ethtool.c
@@ -164,12 +164,29 @@ nsim_set_fecparam(struct net_device *dev, struct 
ethtool_fecparam *fecparam)
        ns->ethtool.fec.active_fec = 1 << (fls(fec) - 1);
        return 0;
  }
+static const struct ethtool_fec_hist_range netdevsim_fec_ranges[] = {
+       { 0, 0},
+       { 1, 3},
+       { 4, 7},
+       { 0, 0}
+};


Following up on the discussion from v1, I agree with Gal's concern about pushing array management into the driver. It adds complexity especially when ranges depend on FEC mode.

The approach Andrew suggested makes sense to me. A simple helper to add a bin would support both static and dynamic cases.

  static void
-nsim_get_fec_stats(struct net_device *dev, struct ethtool_fec_stats *fec_stats)
+nsim_get_fec_stats(struct net_device *dev, struct ethtool_fec_stats *fec_stats,
+                  const struct ethtool_fec_hist_range **ranges)
  {
+       *ranges = netdevsim_fec_ranges;
+
        fec_stats->corrected_blocks.total = 123;
        fec_stats->uncorrectable_blocks.total = 4;
+
+       fec_stats->hist[0].bin_value = 345;

bin_value is 345 but the per-lane sum is 445.

+       fec_stats->hist[1].bin_value = 12;
+       fec_stats->hist[2].bin_value = 2;
+       fec_stats->hist[0].bin_value_per_lane[0] = 125;
+       fec_stats->hist[0].bin_value_per_lane[1] = 120;
+       fec_stats->hist[0].bin_value_per_lane[2] = 100;
+       fec_stats->hist[0].bin_value_per_lane[3] = 100;
  }
+static int fec_put_hist(struct sk_buff *skb, const struct fec_stat_hist *hist,
+                       const struct ethtool_fec_hist_range *ranges)
+{
+       struct nlattr *nest;
+       int i, j;
+
+       if (!ranges)
+               return 0;
+
+       for (i = 0; i < ETHTOOL_FEC_HIST_MAX; i++) {
+               if (i && !ranges[i].low && !ranges[i].high)
+                       break;
+
+               nest = nla_nest_start(skb, ETHTOOL_A_FEC_STAT_HIST);
+               if (!nest)
+                       return -EMSGSIZE;
+
+               if (nla_put_u32(skb, ETHTOOL_A_FEC_HIST_BIN_LOW,
+                                ranges[i].low) ||
+                   nla_put_u32(skb, ETHTOOL_A_FEC_HIST_BIN_HIGH,
+                                ranges[i].high) ||
+                   nla_put_uint(skb, ETHTOOL_A_FEC_HIST_BIN_VAL,
+                                hist[i].bin_value))

Should skip bins where hist[i].bin_value isn’t set.


Thanks,
Carolina

Reply via email to