Skip to content
Permalink
Browse files
wip
  • Loading branch information
pmachata committed Nov 26, 2021
1 parent 59d1583 commit 0839ffb5b56fb6f5e67545c77bf6151fe606835d
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 117 deletions.
@@ -8929,13 +8929,17 @@ static int
mlxsw_sp_router_port_offload_xstats_report_delta(struct mlxsw_sp_rif *rif,
struct netdev_notifier_offload_xstats_info *info)
{
struct netdev_notifier_offload_xstats_rd *ctx = info->report_delta.ctx;
struct rtnl_link_stats64 stats = {
.rx_packets = 1234,
.tx_packets = 5678,
};

netdev_offload_xstats_report_delta(info->report_delta, &stats,
NETDEV_HW_STATS_TYPE_IMMEDIATE);
if (info->report_delta.report_stats)
netdev_offload_xstats_report_delta(ctx, &stats);
else
netdev_offload_xstats_report_delta(ctx, NULL);

return 0;
}

@@ -2861,24 +2861,6 @@ struct netdev_notifier_pre_changeaddr_info {
const unsigned char *dev_addr;
};

// xxx naming. Are these types for hw_stats, or generally for offloaded stats?
#define NETDEV_HW_STATS_TYPES(X) \
X(IMMEDIATE)

#define NETDEV_HW_STATS_EXPAND_BITN(T) \
NETDEV_HW_STATS_BITN_ ## T,
enum {
NETDEV_HW_STATS_TYPES(NETDEV_HW_STATS_EXPAND_BITN)
};
#undef NETDEV_HW_STATS_EXPAND_BITN

#define NETDEV_HW_STATS_EXPAND_TYPE(T) \
NETDEV_HW_STATS_TYPE_ ## T = BIT(NETDEV_HW_STATS_BITN_ ## T),
enum netdev_hw_stats_type {
NETDEV_HW_STATS_TYPES(NETDEV_HW_STATS_EXPAND_TYPE)
};
#undef NETDEV_HW_STATS_EXPAND_TYPE

enum netdev_offload_xstats_cmd {
NETDEV_OFFLOAD_XSTATS_CMD_ENABLE,
NETDEV_OFFLOAD_XSTATS_CMD_DISABLE,
@@ -2890,25 +2872,23 @@ struct netdev_notifier_offload_xstats_info {
enum netdev_offload_xstats_cmd cmd;

union {
/* For ENABLE. A mask of enum netdev_hw_stats_type. */
enum netdev_hw_stats_type hw_stats;

/* For REPORT_DELTA. */
struct netdev_notifier_offload_xstats_rd *report_delta;
struct {
struct netdev_notifier_offload_xstats_rd *ctx;
bool report_stats;
} report_delta;
};
};

int netdev_offload_xstats_hw_stats_enable(struct net_device *dev,
enum netdev_hw_stats_type hw_stats,
struct netlink_ext_ack *extack);
void netdev_offload_xstats_hw_stats_disable(struct net_device *dev);
bool netdev_offload_xstats_hw_stats_enabled(const struct net_device *dev);
int netdev_offload_xstats_hw_stats_get(struct net_device *dev,
struct rtnl_link_stats64 *stats,
enum netdev_hw_stats_type *used_hw_stats,
u32 *in_hw_count,
struct netlink_ext_ack *extack);
void netdev_offload_xstats_report_delta(struct netdev_notifier_offload_xstats_rd *report_delta,
const struct rtnl_link_stats64 *stats,
enum netdev_hw_stats_type hw_stats);
const struct rtnl_link_stats64 *stats);

static inline void netdev_notifier_info_init(struct netdev_notifier_info *info,
struct net_device *dev)
@@ -1159,7 +1159,7 @@ enum {
IFLA_STATS_GET_FILTERS, /* Nest of IFLA_STATS_LINK_*, each a u32 with a
* filter mask for the corresponding stat group.
*/
IFLA_STATS_SET_OFFLOAD_XSTATS_HW_STATS, /* IFLA_HW_STATS_* bitfield */
IFLA_STATS_SET_OFFLOAD_XSTATS_HW_STATS, /* bool as u8 */
__IFLA_STATS_GETSET_MAX,
};

@@ -8361,25 +8361,23 @@ void netdev_bonding_info_change(struct net_device *dev,
EXPORT_SYMBOL(netdev_bonding_info_change);

int netdev_offload_xstats_hw_stats_enable(struct net_device *dev,
u32 req_hw_stats,
struct netlink_ext_ack *extack)
{
struct netdev_notifier_offload_xstats_info info = {
.info.dev = dev,
.info.extack = extack,
.cmd = NETDEV_OFFLOAD_XSTATS_CMD_ENABLE,
.hw_stats = req_hw_stats,
};
struct rtnl_link_stats64 *stats;
int err;
int rc;

if (!dev->offload_hw_stats) {
dev->offload_hw_stats = kzalloc(sizeof(*dev->offload_hw_stats),
GFP_KERNEL);
if (!dev->offload_hw_stats)
return -ENOMEM;
}
if (dev->offload_hw_stats)
return 0;

dev->offload_hw_stats = kzalloc(sizeof(*dev->offload_hw_stats),
GFP_KERNEL);
if (!dev->offload_hw_stats)
return -ENOMEM;

rc = call_netdevice_notifiers_info(NETDEV_OFFLOAD_XSTATS_CMD,
&info.info);
@@ -8392,7 +8390,8 @@ int netdev_offload_xstats_hw_stats_enable(struct net_device *dev,
return 0;

free_stats:
kfree(stats);
kfree(dev->offload_hw_stats);
dev->offload_hw_stats = NULL;
return err;
}
EXPORT_SYMBOL(netdev_offload_xstats_hw_stats_enable);
@@ -8414,9 +8413,15 @@ void netdev_offload_xstats_hw_stats_disable(struct net_device *dev)
}
EXPORT_SYMBOL(netdev_offload_xstats_hw_stats_disable);

bool netdev_offload_xstats_hw_stats_enabled(const struct net_device *dev)
{
return dev->offload_hw_stats;
}
EXPORT_SYMBOL(netdev_offload_xstats_hw_stats_enabled);

struct netdev_notifier_offload_xstats_rd {
struct rtnl_link_stats64 stats;
enum netdev_hw_stats_type hw_stats;
u32 in_hw_count;
};

static void netdev_link_stats64_add(struct rtnl_link_stats64 *dest,
@@ -8450,44 +8455,45 @@ static void netdev_link_stats64_add(struct rtnl_link_stats64 *dest,

int netdev_offload_xstats_hw_stats_get(struct net_device *dev,
struct rtnl_link_stats64 *stats,
enum netdev_hw_stats_type *used_hw_stats,
u32 *in_hw_count,
struct netlink_ext_ack *extack)
{
struct netdev_notifier_offload_xstats_rd report_delta = {};
struct netdev_notifier_offload_xstats_info info = {
.info.dev = dev,
.info.extack = extack,
.cmd = NETDEV_OFFLOAD_XSTATS_CMD_REPORT_DELTA,
.report_delta = &report_delta,
.report_delta.report_stats = (stats != NULL),
.report_delta.ctx = &report_delta,
};
int rc;

if (!dev->offload_hw_stats)
return -ENOENT;
WARN_ON(stats && !dev->offload_hw_stats);

rc = call_netdevice_notifiers_info(NETDEV_OFFLOAD_XSTATS_CMD,
&info.info);

/* Cache whatever we got, even if there was an error, otherwise the
* successful stats retrievals would get lost.
*/
netdev_link_stats64_add(dev->offload_hw_stats, &report_delta.stats);
*stats = *dev->offload_hw_stats;
*used_hw_stats = report_delta.hw_stats;
if (dev->offload_hw_stats)
netdev_link_stats64_add(dev->offload_hw_stats,
&report_delta.stats);
if (stats)
*stats = *dev->offload_hw_stats;
*in_hw_count = report_delta.in_hw_count;

return notifier_to_errno(rc);
}
EXPORT_SYMBOL(netdev_offload_xstats_hw_stats_get);

void
netdev_offload_xstats_report_delta(struct netdev_notifier_offload_xstats_rd *report_delta,
const struct rtnl_link_stats64 *stats,
enum netdev_hw_stats_type hw_stats)
const struct rtnl_link_stats64 *stats)
{
WARN_ON(hweight32(hw_stats) != 1);

report_delta->hw_stats |= hw_stats;
netdev_link_stats64_add(&report_delta->stats, stats);
report_delta->in_hw_count++;
if (stats)
netdev_link_stats64_add(&report_delta->stats, stats);
}
EXPORT_SYMBOL(netdev_offload_xstats_report_delta);

0 comments on commit 0839ffb

Please sign in to comment.