@@ -9,6 +9,11 @@ struct stats_req_info {
DECLARE_BITMAP(stat_mask, __ETHTOOL_STATS_CNT);
};
+struct rmon_stats_put_ctx {
+ const struct ethtool_rmon_stats *rmon_stats;
+ const struct ethtool_rmon_hist_range *rmon_ranges;
+};
+
#define STATS_REQINFO(__req_base) \
container_of(__req_base, struct stats_req_info, base)
@@ -110,8 +115,11 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base,
const struct stats_req_info *req_info = STATS_REQINFO(req_base);
struct stats_reply_data *data = STATS_REPDATA(reply_base);
struct net_device *dev = reply_base->dev;
+ const struct ethtool_ops *ops;
int ret;
+ ops = dev->ethtool_ops;
+
ret = ethnl_ops_begin(dev);
if (ret < 0)
return ret;
@@ -122,18 +130,18 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base,
memset(&data->stats, 0xff, sizeof(data->stats));
if (test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask) &&
- dev->ethtool_ops->get_eth_phy_stats)
- dev->ethtool_ops->get_eth_phy_stats(dev, &data->phy_stats);
+ ops->get_eth_phy_stats)
+ ops->get_eth_phy_stats(dev, &data->phy_stats);
if (test_bit(ETHTOOL_STATS_ETH_MAC, req_info->stat_mask) &&
- dev->ethtool_ops->get_eth_mac_stats)
- dev->ethtool_ops->get_eth_mac_stats(dev, &data->mac_stats);
+ ops->get_eth_mac_stats)
+ ops->get_eth_mac_stats(dev, &data->mac_stats);
if (test_bit(ETHTOOL_STATS_ETH_CTRL, req_info->stat_mask) &&
- dev->ethtool_ops->get_eth_ctrl_stats)
- dev->ethtool_ops->get_eth_ctrl_stats(dev, &data->ctrl_stats);
+ ops->get_eth_ctrl_stats)
+ ops->get_eth_ctrl_stats(dev, &data->ctrl_stats);
if (test_bit(ETHTOOL_STATS_RMON, req_info->stat_mask) &&
- dev->ethtool_ops->get_rmon_stats)
- dev->ethtool_ops->get_rmon_stats(dev, &data->rmon_stats,
- &data->rmon_ranges);
+ ops->get_rmon_stats)
+ ops->get_rmon_stats(dev, &data->rmon_stats,
+ &data->rmon_ranges);
ethnl_ops_complete(dev);
return 0;
@@ -212,76 +220,82 @@ static int stat_put(struct sk_buff *skb, u16 attrtype, u64 val)
return 0;
}
-static int stats_put_phy_stats(struct sk_buff *skb,
- const struct stats_reply_data *data)
+static int stats_put_phy_stats(struct sk_buff *skb, const void *src)
{
+ const struct ethtool_eth_phy_stats *phy_stats = src;
+
if (stat_put(skb, ETHTOOL_A_STATS_ETH_PHY_5_SYM_ERR,
- data->phy_stats.SymbolErrorDuringCarrier))
+ phy_stats->SymbolErrorDuringCarrier))
return -EMSGSIZE;
+
return 0;
}
-static int stats_put_mac_stats(struct sk_buff *skb,
- const struct stats_reply_data *data)
+static int stats_put_mac_stats(struct sk_buff *skb, const void *src)
{
+ const struct ethtool_eth_mac_stats *mac_stats = src;
+
if (stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_2_TX_PKT,
- data->mac_stats.FramesTransmittedOK) ||
+ mac_stats->FramesTransmittedOK) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_3_SINGLE_COL,
- data->mac_stats.SingleCollisionFrames) ||
+ mac_stats->SingleCollisionFrames) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_4_MULTI_COL,
- data->mac_stats.MultipleCollisionFrames) ||
+ mac_stats->MultipleCollisionFrames) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_5_RX_PKT,
- data->mac_stats.FramesReceivedOK) ||
+ mac_stats->FramesReceivedOK) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_6_FCS_ERR,
- data->mac_stats.FrameCheckSequenceErrors) ||
+ mac_stats->FrameCheckSequenceErrors) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_7_ALIGN_ERR,
- data->mac_stats.AlignmentErrors) ||
+ mac_stats->AlignmentErrors) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_8_TX_BYTES,
- data->mac_stats.OctetsTransmittedOK) ||
+ mac_stats->OctetsTransmittedOK) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_9_TX_DEFER,
- data->mac_stats.FramesWithDeferredXmissions) ||
+ mac_stats->FramesWithDeferredXmissions) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_10_LATE_COL,
- data->mac_stats.LateCollisions) ||
+ mac_stats->LateCollisions) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_11_XS_COL,
- data->mac_stats.FramesAbortedDueToXSColls) ||
+ mac_stats->FramesAbortedDueToXSColls) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_12_TX_INT_ERR,
- data->mac_stats.FramesLostDueToIntMACXmitError) ||
+ mac_stats->FramesLostDueToIntMACXmitError) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_13_CS_ERR,
- data->mac_stats.CarrierSenseErrors) ||
+ mac_stats->CarrierSenseErrors) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_14_RX_BYTES,
- data->mac_stats.OctetsReceivedOK) ||
+ mac_stats->OctetsReceivedOK) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_15_RX_INT_ERR,
- data->mac_stats.FramesLostDueToIntMACRcvError) ||
+ mac_stats->FramesLostDueToIntMACRcvError) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_18_TX_MCAST,
- data->mac_stats.MulticastFramesXmittedOK) ||
+ mac_stats->MulticastFramesXmittedOK) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_19_TX_BCAST,
- data->mac_stats.BroadcastFramesXmittedOK) ||
+ mac_stats->BroadcastFramesXmittedOK) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_20_XS_DEFER,
- data->mac_stats.FramesWithExcessiveDeferral) ||
+ mac_stats->FramesWithExcessiveDeferral) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_21_RX_MCAST,
- data->mac_stats.MulticastFramesReceivedOK) ||
+ mac_stats->MulticastFramesReceivedOK) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_22_RX_BCAST,
- data->mac_stats.BroadcastFramesReceivedOK) ||
+ mac_stats->BroadcastFramesReceivedOK) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_23_IR_LEN_ERR,
- data->mac_stats.InRangeLengthErrors) ||
+ mac_stats->InRangeLengthErrors) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_24_OOR_LEN,
- data->mac_stats.OutOfRangeLengthField) ||
+ mac_stats->OutOfRangeLengthField) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_MAC_25_TOO_LONG_ERR,
- data->mac_stats.FrameTooLongErrors))
+ mac_stats->FrameTooLongErrors))
return -EMSGSIZE;
+
return 0;
}
-static int stats_put_ctrl_stats(struct sk_buff *skb,
- const struct stats_reply_data *data)
+static int stats_put_ctrl_stats(struct sk_buff *skb, const void *src)
{
+ const struct ethtool_eth_ctrl_stats *ctrl_stats = src;
+
if (stat_put(skb, ETHTOOL_A_STATS_ETH_CTRL_3_TX,
- data->ctrl_stats.MACControlFramesTransmitted) ||
+ ctrl_stats->MACControlFramesTransmitted) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_CTRL_4_RX,
- data->ctrl_stats.MACControlFramesReceived) ||
+ ctrl_stats->MACControlFramesReceived) ||
stat_put(skb, ETHTOOL_A_STATS_ETH_CTRL_5_RX_UNSUP,
- data->ctrl_stats.UnsupportedOpcodesReceived))
+ ctrl_stats->UnsupportedOpcodesReceived))
return -EMSGSIZE;
+
return 0;
}
@@ -322,33 +336,34 @@ static int stats_put_rmon_hist(struct sk_buff *skb, u32 attr, const u64 *hist,
return -EMSGSIZE;
}
-static int stats_put_rmon_stats(struct sk_buff *skb,
- const struct stats_reply_data *data)
+static int stats_put_rmon_stats(struct sk_buff *skb, const void *src)
{
+ const struct ethtool_rmon_hist_range *rmon_ranges;
+ const struct ethtool_rmon_stats *rmon_stats;
+ const struct rmon_stats_put_ctx *ctx = src;
+
+ rmon_stats = ctx->rmon_stats;
+ rmon_ranges = ctx->rmon_ranges;
+
if (stats_put_rmon_hist(skb, ETHTOOL_A_STATS_GRP_HIST_RX,
- data->rmon_stats.hist, data->rmon_ranges) ||
+ rmon_stats->hist, rmon_ranges) ||
stats_put_rmon_hist(skb, ETHTOOL_A_STATS_GRP_HIST_TX,
- data->rmon_stats.hist_tx, data->rmon_ranges))
+ rmon_stats->hist_tx, rmon_ranges))
return -EMSGSIZE;
if (stat_put(skb, ETHTOOL_A_STATS_RMON_UNDERSIZE,
- data->rmon_stats.undersize_pkts) ||
+ rmon_stats->undersize_pkts) ||
stat_put(skb, ETHTOOL_A_STATS_RMON_OVERSIZE,
- data->rmon_stats.oversize_pkts) ||
- stat_put(skb, ETHTOOL_A_STATS_RMON_FRAG,
- data->rmon_stats.fragments) ||
- stat_put(skb, ETHTOOL_A_STATS_RMON_JABBER,
- data->rmon_stats.jabbers))
+ rmon_stats->oversize_pkts) ||
+ stat_put(skb, ETHTOOL_A_STATS_RMON_FRAG, rmon_stats->fragments) ||
+ stat_put(skb, ETHTOOL_A_STATS_RMON_JABBER, rmon_stats->jabbers))
return -EMSGSIZE;
return 0;
}
-static int stats_put_stats(struct sk_buff *skb,
- const struct stats_reply_data *data,
- u32 id, u32 ss_id,
- int (*cb)(struct sk_buff *skb,
- const struct stats_reply_data *data))
+static int stats_put_stats(struct sk_buff *skb, const void *src, u32 id, u32 ss_id,
+ int (*cb)(struct sk_buff *skb, const void *src))
{
struct nlattr *nest;
@@ -360,7 +375,7 @@ static int stats_put_stats(struct sk_buff *skb,
nla_put_u32(skb, ETHTOOL_A_STATS_GRP_SS_ID, ss_id))
goto err_cancel;
- if (cb(skb, data))
+ if (cb(skb, src))
goto err_cancel;
nla_nest_end(skb, nest);
@@ -380,20 +395,29 @@ static int stats_fill_reply(struct sk_buff *skb,
int ret = 0;
if (!ret && test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask))
- ret = stats_put_stats(skb, data, ETHTOOL_STATS_ETH_PHY,
+ ret = stats_put_stats(skb, &data->phy_stats,
+ ETHTOOL_STATS_ETH_PHY,
ETH_SS_STATS_ETH_PHY,
stats_put_phy_stats);
if (!ret && test_bit(ETHTOOL_STATS_ETH_MAC, req_info->stat_mask))
- ret = stats_put_stats(skb, data, ETHTOOL_STATS_ETH_MAC,
+ ret = stats_put_stats(skb, &data->mac_stats,
+ ETHTOOL_STATS_ETH_MAC,
ETH_SS_STATS_ETH_MAC,
stats_put_mac_stats);
if (!ret && test_bit(ETHTOOL_STATS_ETH_CTRL, req_info->stat_mask))
- ret = stats_put_stats(skb, data, ETHTOOL_STATS_ETH_CTRL,
+ ret = stats_put_stats(skb, &data->ctrl_stats,
+ ETHTOOL_STATS_ETH_CTRL,
ETH_SS_STATS_ETH_CTRL,
stats_put_ctrl_stats);
- if (!ret && test_bit(ETHTOOL_STATS_RMON, req_info->stat_mask))
- ret = stats_put_stats(skb, data, ETHTOOL_STATS_RMON,
+ if (!ret && test_bit(ETHTOOL_STATS_RMON, req_info->stat_mask)) {
+ struct rmon_stats_put_ctx ctx = {
+ .rmon_stats = &data->rmon_stats,
+ .rmon_ranges = data->rmon_ranges,
+ };
+
+ ret = stats_put_stats(skb, &ctx, ETHTOOL_STATS_RMON,
ETH_SS_STATS_RMON, stats_put_rmon_stats);
+ }
return ret;
}
IEEE 802.3 defines a MAC merge layer, for supporting the 802.1Q Frame Preemption capability. Beyond the MAC merge layer there are 2 distinct MACs, one is for express traffic (eMAC, aka the good old MAC that the Linux network stack knows about) and the other is for preemptable traffic (pMAC). The pMAC is a MAC in its own right, and has a full set of statistics that can be exposed through the standardized ethtool counters (RMON, 802.3 etc). In preparation for extending struct stats_reply_data to store both the eMAC and the pMAC stats structures, modify stats_put_stats() to not assume that we only care about the eMAC stats. Instead, we will introduce separate ops for pMAC stats, and put those stats into separate netlink attributes, and take them from different instances of the same structure types as in the case of the eMAC. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> --- net/ethtool/stats.c | 148 +++++++++++++++++++++++++------------------- 1 file changed, 86 insertions(+), 62 deletions(-)