All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch net-next v8 0/3] return offloaded stats as default and expose original sw stats
@ 2016-09-08  6:19 Jiri Pirko
  2016-09-08  6:19 ` [patch net-next v8 1/3] netdevice: Add offload statistics ndo Jiri Pirko
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Jiri Pirko @ 2016-09-08  6:19 UTC (permalink / raw)
  To: netdev
  Cc: davem, nogahf, idosch, eladr, yotamg, ogerlitz, roopa, nikolay,
	linville, tgraf, gospo, sfeldma, sd, eranbe, ast, edumazet,
	hannes, f.fainelli, dsa

From: Jiri Pirko <jiri@mellanox.com>

The problem we try to handle is about offloaded forwarded packets
which are not seen by kernel. Let me try to draw it:

    port1                       port2 (HW stats are counted here)
      \                          /
       \                        /
        \                      /
         --(A)---- ASIC --(B)--
                    |
                   (C)
                    |
                   CPU (SW stats are counted here)


Now we have couple of flows for TX and RX (direction does not matter here):

1) port1->A->ASIC->C->CPU

   For this flow, HW and SW stats are equal.

2) port1->A->ASIC->C->CPU->C->ASIC->B->port2

   For this flow, HW and SW stats are equal.

3) port1->A->ASIC->B->port2

   For this flow, SW stats are 0.

The purpose of this patchset is to provide facility for user to
find out the difference between flows 1+2 and 3. In other words, user
will be able to see the statistics for the slow-path (through kernel).

Also note that HW stats are what someone calls "accumulated" stats.
Every packet counted by SW is also counted by HW. Not the other way around.

As a default the accumulated stats (HW) will be exposed to user
so the userspace apps can react properly.

This patchset add the SW stats (flows 1+2) under offload related stats, so
in the future we can expose other offload related stat in a similar way.

---
v7->v8:
- patch 2/3
 - move helping const from uapi to rtnetlink
 - cancel driver xstat nesting if it is empty
v6->v7:
- patch 1/3:
 - ndo interface changed to get the wanted stats type as an input.
 - change commit message.
- patch 2/3:
 - create a nesting for offloaded stat and put SW stats under it.
 - change the ndo call to indicate which offload stats we wants.
 - change commit message.
- patch 3/3:
 - change ndo implementation to match the changes in the previous patches.
 - change commit message.
v5->v6:
- patch 2/4 was dropped as requested by Roopa
- patch 1/3:
 - comment changed to indicate that default stats are combined stats
 - commit massage changed
- patch 2/3: (previously 3/4)
 - SW stats return nothing if there is no SW stats ndo
v4->v5:
- updated cover letter
- patch3/4:
  - using memcpy directly to copy stats as requested by DaveM
v3->v4:
- patch1/4:
  - fixed "return ()" pointed out by EricD
- patch2/4:
  - fixed if_nlmsg_size as pointed out by EricD
v2->v3:
- patch1/4:
  - added dev_have_sw_stats helper
- patch2/4:
  - avoided memcpy as requested by DaveM
- patch3/4:
  - use new dev_have_sw_stats helper
v1->v2:
- patch3/4:
  - fixed NULL initialization

Nogah Frankel (3):
  netdevice: Add offload statistics ndo
  net: core: Add offload stats to if_stats_msg
  mlxsw: spectrum: Implement offload stats ndo and expose HW stats by
    default

 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 129 +++++++++++++++++++++++--
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h |   5 +
 include/linux/netdevice.h                      |  12 +++
 include/uapi/linux/if_link.h                   |   9 ++
 net/core/rtnetlink.c                           |  97 ++++++++++++++++++-
 5 files changed, 241 insertions(+), 11 deletions(-)

-- 
2.5.5

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [patch net-next v8 1/3] netdevice: Add offload statistics ndo
  2016-09-08  6:19 [patch net-next v8 0/3] return offloaded stats as default and expose original sw stats Jiri Pirko
@ 2016-09-08  6:19 ` Jiri Pirko
  2016-09-08  6:19 ` [patch net-next v8 2/3] net: core: Add offload stats to if_stats_msg Jiri Pirko
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: Jiri Pirko @ 2016-09-08  6:19 UTC (permalink / raw)
  To: netdev
  Cc: davem, nogahf, idosch, eladr, yotamg, ogerlitz, roopa, nikolay,
	linville, tgraf, gospo, sfeldma, sd, eranbe, ast, edumazet,
	hannes, f.fainelli, dsa

From: Nogah Frankel <nogahf@mellanox.com>

Add a new ndo to return statistics for offloaded operation.
Since there can be many different offloaded operation with many
stats types, the ndo gets an attribute id by which it knows which
stats are wanted. The ndo also gets a void pointer to be cast according
to the attribute id.

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 include/linux/netdevice.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 67bb978..2d2c09b 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -924,6 +924,14 @@ struct netdev_xdp {
  *	3. Update dev->stats asynchronously and atomically, and define
  *	   neither operation.
  *
+ * bool (*ndo_has_offload_stats)(int attr_id)
+ *	Return true if this device supports offload stats of this attr_id.
+ *
+ * int (*ndo_get_offload_stats)(int attr_id, const struct net_device *dev,
+ *	void *attr_data)
+ *	Get statistics for offload operations by attr_id. Write it into the
+ *	attr_data pointer.
+ *
  * int (*ndo_vlan_rx_add_vid)(struct net_device *dev, __be16 proto, u16 vid);
  *	If device supports VLAN filtering this function is called when a
  *	VLAN id is registered.
@@ -1155,6 +1163,10 @@ struct net_device_ops {
 
 	struct rtnl_link_stats64* (*ndo_get_stats64)(struct net_device *dev,
 						     struct rtnl_link_stats64 *storage);
+	bool			(*ndo_has_offload_stats)(int attr_id);
+	int			(*ndo_get_offload_stats)(int attr_id,
+							 const struct net_device *dev,
+							 void *attr_data);
 	struct net_device_stats* (*ndo_get_stats)(struct net_device *dev);
 
 	int			(*ndo_vlan_rx_add_vid)(struct net_device *dev,
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [patch net-next v8 2/3] net: core: Add offload stats to if_stats_msg
  2016-09-08  6:19 [patch net-next v8 0/3] return offloaded stats as default and expose original sw stats Jiri Pirko
  2016-09-08  6:19 ` [patch net-next v8 1/3] netdevice: Add offload statistics ndo Jiri Pirko
@ 2016-09-08  6:19 ` Jiri Pirko
  2016-09-09 13:23   ` Nikolay Aleksandrov
  2016-09-09 13:36   ` Nikolay Aleksandrov
  2016-09-08  6:19 ` [patch net-next v8 3/3] mlxsw: spectrum: Implement offload stats ndo and expose HW stats by default Jiri Pirko
  2016-09-09  2:21 ` [patch net-next v8 0/3] return offloaded stats as default and expose original sw stats Roopa Prabhu
  3 siblings, 2 replies; 9+ messages in thread
From: Jiri Pirko @ 2016-09-08  6:19 UTC (permalink / raw)
  To: netdev
  Cc: davem, nogahf, idosch, eladr, yotamg, ogerlitz, roopa, nikolay,
	linville, tgraf, gospo, sfeldma, sd, eranbe, ast, edumazet,
	hannes, f.fainelli, dsa

From: Nogah Frankel <nogahf@mellanox.com>

Add a nested attribute of offload stats to if_stats_msg
named IFLA_STATS_LINK_OFFLOAD_XSTATS.
Under it, add SW stats, meaning stats only per packets that went via
slowpath to the cpu, named IFLA_OFFLOAD_XSTATS_CPU_HIT.

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 include/uapi/linux/if_link.h |  9 ++++
 net/core/rtnetlink.c         | 97 ++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 102 insertions(+), 4 deletions(-)

diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 9bf3aec..2351776 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -826,6 +826,7 @@ enum {
 	IFLA_STATS_LINK_64,
 	IFLA_STATS_LINK_XSTATS,
 	IFLA_STATS_LINK_XSTATS_SLAVE,
+	IFLA_STATS_LINK_OFFLOAD_XSTATS,
 	__IFLA_STATS_MAX,
 };
 
@@ -845,6 +846,14 @@ enum {
 };
 #define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1)
 
+/* These are stats embedded into IFLA_STATS_LINK_OFFLOAD_XSTATS */
+enum {
+	IFLA_OFFLOAD_XSTATS_UNSPEC,
+	IFLA_OFFLOAD_XSTATS_CPU_HIT, /* struct rtnl_link_stats64 */
+	__IFLA_OFFLOAD_XSTATS_MAX
+};
+#define IFLA_OFFLOAD_XSTATS_MAX (__IFLA_OFFLOAD_XSTATS_MAX - 1)
+
 /* XDP section */
 
 enum {
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 1dfca1c..fe3c1ba 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -3577,6 +3577,79 @@ static bool stats_attr_valid(unsigned int mask, int attrid, int idxattr)
 	       (!idxattr || idxattr == attrid);
 }
 
+#define IFLA_OFFLOAD_XSTATS_FIRST (IFLA_OFFLOAD_XSTATS_UNSPEC + 1)
+static int rtnl_get_offload_stats_attr_size(int attr_id)
+{
+	switch (attr_id) {
+	case IFLA_OFFLOAD_XSTATS_CPU_HIT:
+		return sizeof(struct rtnl_link_stats64);
+	}
+
+	return 0;
+}
+
+static int rtnl_get_offload_stats(struct sk_buff *skb, struct net_device *dev)
+{
+	struct nlattr *attr = NULL;
+	int attr_id, size;
+	void *attr_data;
+	int err;
+
+	if (!(dev->netdev_ops && dev->netdev_ops->ndo_has_offload_stats &&
+	      dev->netdev_ops->ndo_get_offload_stats))
+		return -ENODATA;
+
+	for (attr_id = IFLA_OFFLOAD_XSTATS_FIRST;
+	     attr_id <= IFLA_OFFLOAD_XSTATS_MAX; attr_id++) {
+		size = rtnl_get_offload_stats_attr_size(attr_id);
+		if (!size)
+			continue;
+
+		if (!dev->netdev_ops->ndo_has_offload_stats(attr_id))
+			continue;
+
+		attr = nla_reserve_64bit(skb, attr_id, size,
+					 IFLA_OFFLOAD_XSTATS_UNSPEC);
+		if (!attr)
+			return -EMSGSIZE;
+
+		attr_data = nla_data(attr);
+		memset(attr_data, 0, size);
+		err = dev->netdev_ops->ndo_get_offload_stats(attr_id, dev,
+							     attr_data);
+		if (err)
+			return err;
+	}
+
+	if (!attr)
+		return -ENODATA;
+	return 0;
+}
+
+static int rtnl_get_offload_stats_size(const struct net_device *dev)
+{
+	int nla_size = 0;
+	int attr_id;
+	int size;
+
+	if (!(dev->netdev_ops && dev->netdev_ops->ndo_has_offload_stats &&
+	      dev->netdev_ops->ndo_get_offload_stats))
+		return 0;
+
+	for (attr_id = IFLA_OFFLOAD_XSTATS_FIRST;
+	     attr_id <= IFLA_OFFLOAD_XSTATS_MAX; attr_id++) {
+		if (!dev->netdev_ops->ndo_has_offload_stats(attr_id))
+			continue;
+		size = rtnl_get_offload_stats_attr_size(attr_id);
+		nla_size += nla_total_size_64bit(size);
+	}
+
+	if (nla_size != 0)
+		nla_size += nla_total_size(0);
+
+	return nla_size;
+}
+
 static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
 			       int type, u32 pid, u32 seq, u32 change,
 			       unsigned int flags, unsigned int filter_mask,
@@ -3586,6 +3659,7 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
 	struct nlmsghdr *nlh;
 	struct nlattr *attr;
 	int s_prividx = *prividx;
+	int err;
 
 	ASSERT_RTNL();
 
@@ -3614,8 +3688,6 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
 		const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
 
 		if (ops && ops->fill_linkxstats) {
-			int err;
-
 			*idxattr = IFLA_STATS_LINK_XSTATS;
 			attr = nla_nest_start(skb,
 					      IFLA_STATS_LINK_XSTATS);
@@ -3639,8 +3711,6 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
 		if (master)
 			ops = master->rtnl_link_ops;
 		if (ops && ops->fill_linkxstats) {
-			int err;
-
 			*idxattr = IFLA_STATS_LINK_XSTATS_SLAVE;
 			attr = nla_nest_start(skb,
 					      IFLA_STATS_LINK_XSTATS_SLAVE);
@@ -3655,6 +3725,22 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
 		}
 	}
 
+	if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS,
+			     *idxattr)) {
+		attr = nla_nest_start(skb, IFLA_STATS_LINK_OFFLOAD_XSTATS);
+		if (!attr)
+			goto nla_put_failure;
+
+		err = rtnl_get_offload_stats(skb, dev);
+		if (err == -ENODATA)
+			nla_nest_cancel(skb, attr);
+		else
+			nla_nest_end(skb, attr);
+
+		if ((err) && (err != -ENODATA))
+			goto nla_put_failure;
+	}
+
 	nlmsg_end(skb, nlh);
 
 	return 0;
@@ -3712,6 +3798,9 @@ static size_t if_nlmsg_stats_size(const struct net_device *dev,
 		}
 	}
 
+	if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS, 0))
+		size += rtnl_get_offload_stats_size(dev);
+
 	return size;
 }
 
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [patch net-next v8 3/3] mlxsw: spectrum: Implement offload stats ndo and expose HW stats by default
  2016-09-08  6:19 [patch net-next v8 0/3] return offloaded stats as default and expose original sw stats Jiri Pirko
  2016-09-08  6:19 ` [patch net-next v8 1/3] netdevice: Add offload statistics ndo Jiri Pirko
  2016-09-08  6:19 ` [patch net-next v8 2/3] net: core: Add offload stats to if_stats_msg Jiri Pirko
@ 2016-09-08  6:19 ` Jiri Pirko
  2016-09-09  2:21 ` [patch net-next v8 0/3] return offloaded stats as default and expose original sw stats Roopa Prabhu
  3 siblings, 0 replies; 9+ messages in thread
From: Jiri Pirko @ 2016-09-08  6:19 UTC (permalink / raw)
  To: netdev
  Cc: davem, nogahf, idosch, eladr, yotamg, ogerlitz, roopa, nikolay,
	linville, tgraf, gospo, sfeldma, sd, eranbe, ast, edumazet,
	hannes, f.fainelli, dsa

From: Nogah Frankel <nogahf@mellanox.com>

Change the default statistics ndo to return HW statistics
(like the one returned by ethtool_ops).
The HW stats are collected to a cache by delayed work every 1 sec.
Implement the offload stat ndo.
Add a function to get SW statistics, to be called from this function.

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 129 +++++++++++++++++++++++--
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h |   5 +
 2 files changed, 127 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 6c6b726..2a7f93f 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -818,9 +818,9 @@ err_span_port_mtu_update:
 	return err;
 }
 
-static struct rtnl_link_stats64 *
-mlxsw_sp_port_get_stats64(struct net_device *dev,
-			  struct rtnl_link_stats64 *stats)
+int
+mlxsw_sp_port_get_sw_stats64(const struct net_device *dev,
+			     struct rtnl_link_stats64 *stats)
 {
 	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
 	struct mlxsw_sp_port_pcpu_stats *p;
@@ -847,6 +847,107 @@ mlxsw_sp_port_get_stats64(struct net_device *dev,
 		tx_dropped	+= p->tx_dropped;
 	}
 	stats->tx_dropped	= tx_dropped;
+	return 0;
+}
+
+bool mlxsw_sp_port_has_offload_stats(int attr_id)
+{
+	switch (attr_id) {
+	case IFLA_OFFLOAD_XSTATS_CPU_HIT:
+		return true;
+	}
+
+	return false;
+}
+
+int mlxsw_sp_port_get_offload_stats(int attr_id, const struct net_device *dev,
+				    void *sp)
+{
+	switch (attr_id) {
+	case IFLA_OFFLOAD_XSTATS_CPU_HIT:
+		return mlxsw_sp_port_get_sw_stats64(dev, sp);
+	}
+
+	return -EINVAL;
+}
+
+static int mlxsw_sp_port_get_stats_raw(struct net_device *dev, int grp,
+				       int prio, char *ppcnt_pl)
+{
+	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+
+	mlxsw_reg_ppcnt_pack(ppcnt_pl, mlxsw_sp_port->local_port, grp, prio);
+	return mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ppcnt), ppcnt_pl);
+}
+
+static int mlxsw_sp_port_get_hw_stats(struct net_device *dev,
+				      struct rtnl_link_stats64 *stats)
+{
+	char ppcnt_pl[MLXSW_REG_PPCNT_LEN];
+	int err;
+
+	err = mlxsw_sp_port_get_stats_raw(dev, MLXSW_REG_PPCNT_IEEE_8023_CNT,
+					  0, ppcnt_pl);
+	if (err)
+		goto out;
+
+	stats->tx_packets =
+		mlxsw_reg_ppcnt_a_frames_transmitted_ok_get(ppcnt_pl);
+	stats->rx_packets =
+		mlxsw_reg_ppcnt_a_frames_received_ok_get(ppcnt_pl);
+	stats->tx_bytes =
+		mlxsw_reg_ppcnt_a_octets_transmitted_ok_get(ppcnt_pl);
+	stats->rx_bytes =
+		mlxsw_reg_ppcnt_a_octets_received_ok_get(ppcnt_pl);
+	stats->multicast =
+		mlxsw_reg_ppcnt_a_multicast_frames_received_ok_get(ppcnt_pl);
+
+	stats->rx_crc_errors =
+		mlxsw_reg_ppcnt_a_frame_check_sequence_errors_get(ppcnt_pl);
+	stats->rx_frame_errors =
+		mlxsw_reg_ppcnt_a_alignment_errors_get(ppcnt_pl);
+
+	stats->rx_length_errors = (
+		mlxsw_reg_ppcnt_a_in_range_length_errors_get(ppcnt_pl) +
+		mlxsw_reg_ppcnt_a_out_of_range_length_field_get(ppcnt_pl) +
+		mlxsw_reg_ppcnt_a_frame_too_long_errors_get(ppcnt_pl));
+
+	stats->rx_errors = (stats->rx_crc_errors +
+		stats->rx_frame_errors + stats->rx_length_errors);
+
+out:
+	return err;
+}
+
+static void update_stats_cache(struct work_struct *work)
+{
+	struct mlxsw_sp_port *mlxsw_sp_port =
+		container_of(work, struct mlxsw_sp_port,
+			     hw_stats.update_dw.work);
+
+	if (!netif_carrier_ok(mlxsw_sp_port->dev))
+		goto out;
+
+	mlxsw_sp_port_get_hw_stats(mlxsw_sp_port->dev,
+				   mlxsw_sp_port->hw_stats.cache);
+
+out:
+	mlxsw_core_schedule_dw(&mlxsw_sp_port->hw_stats.update_dw,
+			       MLXSW_HW_STATS_UPDATE_TIME);
+}
+
+/* Return the stats from a cache that is updated periodically,
+ * as this function might get called in an atomic context.
+ */
+static struct rtnl_link_stats64 *
+mlxsw_sp_port_get_stats64(struct net_device *dev,
+			  struct rtnl_link_stats64 *stats)
+{
+	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+
+	memcpy(stats, mlxsw_sp_port->hw_stats.cache, sizeof(*stats));
+
 	return stats;
 }
 
@@ -1208,6 +1309,8 @@ static const struct net_device_ops mlxsw_sp_port_netdev_ops = {
 	.ndo_set_mac_address	= mlxsw_sp_port_set_mac_address,
 	.ndo_change_mtu		= mlxsw_sp_port_change_mtu,
 	.ndo_get_stats64	= mlxsw_sp_port_get_stats64,
+	.ndo_has_offload_stats	= mlxsw_sp_port_has_offload_stats,
+	.ndo_get_offload_stats	= mlxsw_sp_port_get_offload_stats,
 	.ndo_vlan_rx_add_vid	= mlxsw_sp_port_add_vid,
 	.ndo_vlan_rx_kill_vid	= mlxsw_sp_port_kill_vid,
 	.ndo_neigh_construct	= mlxsw_sp_router_neigh_construct,
@@ -1546,8 +1649,6 @@ static void __mlxsw_sp_port_get_stats(struct net_device *dev,
 				      enum mlxsw_reg_ppcnt_grp grp, int prio,
 				      u64 *data, int data_index)
 {
-	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
-	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
 	struct mlxsw_sp_port_hw_stats *hw_stats;
 	char ppcnt_pl[MLXSW_REG_PPCNT_LEN];
 	int i, len;
@@ -1556,8 +1657,7 @@ static void __mlxsw_sp_port_get_stats(struct net_device *dev,
 	err = mlxsw_sp_get_hw_stats_by_group(&hw_stats, &len, grp);
 	if (err)
 		return;
-	mlxsw_reg_ppcnt_pack(ppcnt_pl, mlxsw_sp_port->local_port, grp, prio);
-	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ppcnt), ppcnt_pl);
+	mlxsw_sp_port_get_stats_raw(dev, grp, prio, ppcnt_pl);
 	for (i = 0; i < len; i++)
 		data[data_index + i] = !err ? hw_stats[i].getter(ppcnt_pl) : 0;
 }
@@ -2102,6 +2202,16 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
 		goto err_alloc_stats;
 	}
 
+	mlxsw_sp_port->hw_stats.cache =
+		kzalloc(sizeof(*mlxsw_sp_port->hw_stats.cache), GFP_KERNEL);
+
+	if (!mlxsw_sp_port->hw_stats.cache) {
+		err = -ENOMEM;
+		goto err_alloc_hw_stats;
+	}
+	INIT_DELAYED_WORK(&mlxsw_sp_port->hw_stats.update_dw,
+			  &update_stats_cache);
+
 	dev->netdev_ops = &mlxsw_sp_port_netdev_ops;
 	dev->ethtool_ops = &mlxsw_sp_port_ethtool_ops;
 
@@ -2202,6 +2312,7 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
 		goto err_core_port_init;
 	}
 
+	mlxsw_core_schedule_dw(&mlxsw_sp_port->hw_stats.update_dw, 0);
 	return 0;
 
 err_core_port_init:
@@ -2222,6 +2333,8 @@ err_port_speed_by_width_set:
 err_port_swid_set:
 err_port_system_port_mapping_set:
 err_dev_addr_init:
+	kfree(mlxsw_sp_port->hw_stats.cache);
+err_alloc_hw_stats:
 	free_percpu(mlxsw_sp_port->pcpu_stats);
 err_alloc_stats:
 	kfree(mlxsw_sp_port->untagged_vlans);
@@ -2238,6 +2351,7 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
 
 	if (!mlxsw_sp_port)
 		return;
+	cancel_delayed_work_sync(&mlxsw_sp_port->hw_stats.update_dw);
 	mlxsw_core_port_fini(&mlxsw_sp_port->core_port);
 	unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */
 	mlxsw_sp->ports[local_port] = NULL;
@@ -2247,6 +2361,7 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
 	mlxsw_sp_port_swid_set(mlxsw_sp_port, MLXSW_PORT_SWID_DISABLED_PORT);
 	mlxsw_sp_port_module_unmap(mlxsw_sp, mlxsw_sp_port->local_port);
 	free_percpu(mlxsw_sp_port->pcpu_stats);
+	kfree(mlxsw_sp_port->hw_stats.cache);
 	kfree(mlxsw_sp_port->untagged_vlans);
 	kfree(mlxsw_sp_port->active_vlans);
 	WARN_ON_ONCE(!list_empty(&mlxsw_sp_port->vports_list));
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 01537d3..69aefb1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -360,6 +360,11 @@ struct mlxsw_sp_port {
 	struct list_head vports_list;
 	/* TC handles */
 	struct list_head mall_tc_list;
+	struct {
+		#define MLXSW_HW_STATS_UPDATE_TIME HZ
+		struct rtnl_link_stats64 *cache;
+		struct delayed_work update_dw;
+	} hw_stats;
 };
 
 struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev);
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [patch net-next v8 0/3] return offloaded stats as default and expose original sw stats
  2016-09-08  6:19 [patch net-next v8 0/3] return offloaded stats as default and expose original sw stats Jiri Pirko
                   ` (2 preceding siblings ...)
  2016-09-08  6:19 ` [patch net-next v8 3/3] mlxsw: spectrum: Implement offload stats ndo and expose HW stats by default Jiri Pirko
@ 2016-09-09  2:21 ` Roopa Prabhu
  3 siblings, 0 replies; 9+ messages in thread
From: Roopa Prabhu @ 2016-09-09  2:21 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: netdev, davem, nogahf, idosch, eladr, yotamg, ogerlitz, nikolay,
	linville, tgraf, gospo, sfeldma, sd, eranbe, ast, edumazet,
	hannes, f.fainelli, dsa

On 9/7/16, 11:19 PM, Jiri Pirko wrote:
> From: Jiri Pirko <jiri@mellanox.com>
>
> The problem we try to handle is about offloaded forwarded packets
> which are not seen by kernel. Let me try to draw it:
>
>     port1                       port2 (HW stats are counted here)
>       \                          /
>        \                        /
>         \                      /
>          --(A)---- ASIC --(B)--
>                     |
>                    (C)
>                     |
>                    CPU (SW stats are counted here)
>
>
> Now we have couple of flows for TX and RX (direction does not matter here):
>
> 1) port1->A->ASIC->C->CPU
>
>    For this flow, HW and SW stats are equal.
>
> 2) port1->A->ASIC->C->CPU->C->ASIC->B->port2
>
>    For this flow, HW and SW stats are equal.
>
> 3) port1->A->ASIC->B->port2
>
>    For this flow, SW stats are 0.
>
> The purpose of this patchset is to provide facility for user to
> find out the difference between flows 1+2 and 3. In other words, user
> will be able to see the statistics for the slow-path (through kernel).
>
> Also note that HW stats are what someone calls "accumulated" stats.
> Every packet counted by SW is also counted by HW. Not the other way around.
>
> As a default the accumulated stats (HW) will be exposed to user
> so the userspace apps can react properly.
>
> This patchset add the SW stats (flows 1+2) under offload related stats, so
> in the future we can expose other offload related stat in a similar way.
>

Acked-by: Roopa Prabhu <roopa@cumulusnetworks.com>

thanks.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch net-next v8 2/3] net: core: Add offload stats to if_stats_msg
  2016-09-08  6:19 ` [patch net-next v8 2/3] net: core: Add offload stats to if_stats_msg Jiri Pirko
@ 2016-09-09 13:23   ` Nikolay Aleksandrov
  2016-09-09 13:36   ` Nikolay Aleksandrov
  1 sibling, 0 replies; 9+ messages in thread
From: Nikolay Aleksandrov @ 2016-09-09 13:23 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Linux Kernel Network Developers, David S. Miller, nogahf,
	Ido Schimmel, eladr, yotamg, ogerlitz, Roopa Prabhu, linville,
	tgraf, Andy Gospodarek, sfeldma, sd, eranbe, ast, edumazet,
	hannes, f.fainelli, dsa


> On Sep 8, 2016, at 9:19 AM, Jiri Pirko <jiri@resnulli.us> wrote:
> 
> From: Nogah Frankel <nogahf@mellanox.com>
> 
> Add a nested attribute of offload stats to if_stats_msg
> named IFLA_STATS_LINK_OFFLOAD_XSTATS.
> Under it, add SW stats, meaning stats only per packets that went via
> slowpath to the cpu, named IFLA_OFFLOAD_XSTATS_CPU_HIT.
> 
> Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
> ---
> include/uapi/linux/if_link.h |  9 ++++
> net/core/rtnetlink.c         | 97 ++++++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 102 insertions(+), 4 deletions(-)
> 
[snip]
> 
> +	if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS,
> +			     *idxattr)) {
> +		attr = nla_nest_start(skb, IFLA_STATS_LINK_OFFLOAD_XSTATS);
> +		if (!attr)
> +			goto nla_put_failure;
> +
> +		err = rtnl_get_offload_stats(skb, dev);
> +		if (err == -ENODATA)
> +			nla_nest_cancel(skb, attr);
> +		else
> +			nla_nest_end(skb, attr);
> +
> +		if ((err) && (err != -ENODATA))
> +			goto nla_put_failure;

Hi,
Sorry I’m a little late to the party, one minor nit though - could you please drop the extra braces here.
Overall the set looks good to me and you can add my

Reviewed-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>

Thanks,
 Nik

> +	}
> +
> 	nlmsg_end(skb, nlh);
> 
> 	return 0;
> @@ -3712,6 +3798,9 @@ static size_t if_nlmsg_stats_size(const struct net_device *dev,
> 		}
> 	}
> 
> +	if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS, 0))
> +		size += rtnl_get_offload_stats_size(dev);
> +
> 	return size;
> }
> 
> -- 
> 2.5.5
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch net-next v8 2/3] net: core: Add offload stats to if_stats_msg
  2016-09-08  6:19 ` [patch net-next v8 2/3] net: core: Add offload stats to if_stats_msg Jiri Pirko
  2016-09-09 13:23   ` Nikolay Aleksandrov
@ 2016-09-09 13:36   ` Nikolay Aleksandrov
  2016-09-09 13:39     ` Nikolay Aleksandrov
  1 sibling, 1 reply; 9+ messages in thread
From: Nikolay Aleksandrov @ 2016-09-09 13:36 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Linux Kernel Network Developers, David S. Miller, nogahf, idosch,
	eladr, yotamg, ogerlitz, roopa, linville, tgraf, gospo, sfeldma,
	sd, eranbe, ast, edumazet, hannes, f.fainelli, dsa


> On Sep 8, 2016, at 9:19 AM, Jiri Pirko <jiri@resnulli.us> wrote:
> 
> From: Nogah Frankel <nogahf@mellanox.com>
> 
> Add a nested attribute of offload stats to if_stats_msg
> named IFLA_STATS_LINK_OFFLOAD_XSTATS.
> Under it, add SW stats, meaning stats only per packets that went via
> slowpath to the cpu, named IFLA_OFFLOAD_XSTATS_CPU_HIT.
> 
> Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
> ---
> include/uapi/linux/if_link.h |  9 ++++
> net/core/rtnetlink.c         | 97 ++++++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 102 insertions(+), 4 deletions(-)
> 
[snip]
> @@ -3655,6 +3725,22 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
> 		}
> 	}
> 
> +	if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS,
> +			     *idxattr)) {
> +		attr = nla_nest_start(skb, IFLA_STATS_LINK_OFFLOAD_XSTATS);
> +		if (!attr)
> +			goto nla_put_failure;
> +
> +		err = rtnl_get_offload_stats(skb, dev);
> +		if (err == -ENODATA)
> +			nla_nest_cancel(skb, attr);
> +		else
> +			nla_nest_end(skb, attr);
> +
> +		if ((err) && (err != -ENODATA))
> +			goto nla_put_failure;
> +	}
> +

Hmm, actually on a second read I think there’s a potential problem here. Since you don’t set *idxattr and if the space
isn’t enough the dump will get restarted and this will lead to an infinite loop.
I.e. if the previous attributes filled the skb and there’s not enough room for this one, it will return an error
but *idxattr will be == 0 from the previous attribute thus the whole dump will be restarted (this is in case someone
requests this attribute with some of the others of course).

Cheers,
 Nik


> 	nlmsg_end(skb, nlh);
> 
> 	return 0;
> @@ -3712,6 +3798,9 @@ static size_t if_nlmsg_stats_size(const struct net_device *dev,
> 		}
> 	}
> 
> +	if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS, 0))
> +		size += rtnl_get_offload_stats_size(dev);
> +
> 	return size;
> }
> 
> -- 
> 2.5.5
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch net-next v8 2/3] net: core: Add offload stats to if_stats_msg
  2016-09-09 13:36   ` Nikolay Aleksandrov
@ 2016-09-09 13:39     ` Nikolay Aleksandrov
  2016-09-12 11:29       ` Nogah Frankel
  0 siblings, 1 reply; 9+ messages in thread
From: Nikolay Aleksandrov @ 2016-09-09 13:39 UTC (permalink / raw)
  To: Nikolay Aleksandrov
  Cc: Jiri Pirko, Linux Kernel Network Developers, David S. Miller,
	nogahf, idosch, eladr, yotamg, ogerlitz, roopa, linville, tgraf,
	gospo, sfeldma, sd, eranbe, ast, edumazet, hannes, f.fainelli,
	dsa


> On Sep 9, 2016, at 4:36 PM, Nikolay Aleksandrov <nikolay@cumulusnetworks.com> wrote:
> 
>> 
>> On Sep 8, 2016, at 9:19 AM, Jiri Pirko <jiri@resnulli.us> wrote:
>> 
>> From: Nogah Frankel <nogahf@mellanox.com>
>> 
>> Add a nested attribute of offload stats to if_stats_msg
>> named IFLA_STATS_LINK_OFFLOAD_XSTATS.
>> Under it, add SW stats, meaning stats only per packets that went via
>> slowpath to the cpu, named IFLA_OFFLOAD_XSTATS_CPU_HIT.
>> 
>> Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
>> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
>> ---
>> include/uapi/linux/if_link.h |  9 ++++
>> net/core/rtnetlink.c         | 97 ++++++++++++++++++++++++++++++++++++++++++--
>> 2 files changed, 102 insertions(+), 4 deletions(-)
>> 
> [snip]
>> @@ -3655,6 +3725,22 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
>> 		}
>> 	}
>> 
>> +	if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS,
>> +			     *idxattr)) {
>> +		attr = nla_nest_start(skb, IFLA_STATS_LINK_OFFLOAD_XSTATS);
>> +		if (!attr)
>> +			goto nla_put_failure;
>> +
>> +		err = rtnl_get_offload_stats(skb, dev);
>> +		if (err == -ENODATA)
>> +			nla_nest_cancel(skb, attr);
>> +		else
>> +			nla_nest_end(skb, attr);
>> +
>> +		if ((err) && (err != -ENODATA))
>> +			goto nla_put_failure;
>> +	}
>> +
> 
> Hmm, actually on a second read I think there’s a potential problem here. Since you don’t set *idxattr and if the space
> isn’t enough the dump will get restarted and this will lead to an infinite loop.

Err, poor choice of words. I meant the loop will be for userspace since the dump will err out at the same spot all the time so it
won’t be able to ever finish. :-)

> I.e. if the previous attributes filled the skb and there’s not enough room for this one, it will return an error
> but *idxattr will be == 0 from the previous attribute thus the whole dump will be restarted (this is in case someone
> requests this attribute with some of the others of course).
> 
> Cheers,
> Nik
> 
> 
>> 	nlmsg_end(skb, nlh);
>> 
>> 	return 0;
>> @@ -3712,6 +3798,9 @@ static size_t if_nlmsg_stats_size(const struct net_device *dev,
>> 		}
>> 	}
>> 
>> +	if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS, 0))
>> +		size += rtnl_get_offload_stats_size(dev);
>> +
>> 	return size;
>> }
>> 
>> -- 
>> 2.5.5

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [patch net-next v8 2/3] net: core: Add offload stats to if_stats_msg
  2016-09-09 13:39     ` Nikolay Aleksandrov
@ 2016-09-12 11:29       ` Nogah Frankel
  0 siblings, 0 replies; 9+ messages in thread
From: Nogah Frankel @ 2016-09-12 11:29 UTC (permalink / raw)
  To: Nikolay Aleksandrov
  Cc: Jiri Pirko, Linux Kernel Network Developers, David S. Miller,
	Ido Schimmel, Elad Raz, Yotam Gigi, Or Gerlitz, roopa, linville,
	tgraf, gospo, sfeldma, sd, Eran Ben Elisha, ast, edumazet,
	hannes, f.fainelli@gmail.com

> -----Original Message-----
> From: Nikolay Aleksandrov [mailto:nikolay@cumulusnetworks.com]
> Sent: Friday, September 09, 2016 4:39 PM
> To: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
> Cc: Jiri Pirko <jiri@resnulli.us>; Linux Kernel Network Developers <netdev@vger.kernel.org>; David S. Miller
> <davem@davemloft.net>; Nogah Frankel <nogahf@mellanox.com>; Ido Schimmel <idosch@mellanox.com>; Elad Raz
> <eladr@mellanox.com>; Yotam Gigi <yotamg@mellanox.com>; Or Gerlitz <ogerlitz@mellanox.com>; roopa@cumulusnetworks.com;
> linville@tuxdriver.com; tgraf@suug.ch; gospo@cumulusnetworks.com; sfeldma@gmail.com; sd@queasysnail.net; Eran Ben Elisha
> <eranbe@mellanox.com>; ast@plumgrid.com; edumazet@google.com; hannes@stressinduktion.org; f.fainelli@gmail.com;
> dsa@cumulusnetworks.com
> Subject: Re: [patch net-next v8 2/3] net: core: Add offload stats to if_stats_msg
> 
> 
> > On Sep 9, 2016, at 4:36 PM, Nikolay Aleksandrov <nikolay@cumulusnetworks.com> wrote:
> >
> >>
> >> On Sep 8, 2016, at 9:19 AM, Jiri Pirko <jiri@resnulli.us> wrote:
> >>
> >> From: Nogah Frankel <nogahf@mellanox.com>
> >>
> >> Add a nested attribute of offload stats to if_stats_msg
> >> named IFLA_STATS_LINK_OFFLOAD_XSTATS.
> >> Under it, add SW stats, meaning stats only per packets that went via
> >> slowpath to the cpu, named IFLA_OFFLOAD_XSTATS_CPU_HIT.
> >>
> >> Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
> >> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
> >> ---
> >> include/uapi/linux/if_link.h |  9 ++++
> >> net/core/rtnetlink.c         | 97 ++++++++++++++++++++++++++++++++++++++++++--
> >> 2 files changed, 102 insertions(+), 4 deletions(-)
> >>
> > [snip]
> >> @@ -3655,6 +3725,22 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
> >> 		}
> >> 	}
> >>
> >> +	if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS,
> >> +			     *idxattr)) {
> >> +		attr = nla_nest_start(skb, IFLA_STATS_LINK_OFFLOAD_XSTATS);
> >> +		if (!attr)
> >> +			goto nla_put_failure;
> >> +
> >> +		err = rtnl_get_offload_stats(skb, dev);
> >> +		if (err == -ENODATA)
> >> +			nla_nest_cancel(skb, attr);
> >> +		else
> >> +			nla_nest_end(skb, attr);
> >> +
> >> +		if ((err) && (err != -ENODATA))
> >> +			goto nla_put_failure;
> >> +	}
> >> +
> >
> > Hmm, actually on a second read I think there’s a potential problem here. Since you don’t set *idxattr and if the space
> > isn’t enough the dump will get restarted and this will lead to an infinite loop.
> 
> Err, poor choice of words. I meant the loop will be for userspace since the dump will err out at the same spot all the time so it
> won’t be able to ever finish. :-)
> 
> > I.e. if the previous attributes filled the skb and there’s not enough room for this one, it will return an error
> > but *idxattr will be == 0 from the previous attribute thus the whole dump will be restarted (this is in case someone
> > requests this attribute with some of the others of course).
> >
> > Cheers,
> > Nik
> >
> >

I'll fix it. Thanks.

> >> 	nlmsg_end(skb, nlh);
> >>
> >> 	return 0;
> >> @@ -3712,6 +3798,9 @@ static size_t if_nlmsg_stats_size(const struct net_device *dev,
> >> 		}
> >> 	}
> >>
> >> +	if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS, 0))
> >> +		size += rtnl_get_offload_stats_size(dev);
> >> +
> >> 	return size;
> >> }
> >>
> >> --
> >> 2.5.5


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-09-12 13:04 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-08  6:19 [patch net-next v8 0/3] return offloaded stats as default and expose original sw stats Jiri Pirko
2016-09-08  6:19 ` [patch net-next v8 1/3] netdevice: Add offload statistics ndo Jiri Pirko
2016-09-08  6:19 ` [patch net-next v8 2/3] net: core: Add offload stats to if_stats_msg Jiri Pirko
2016-09-09 13:23   ` Nikolay Aleksandrov
2016-09-09 13:36   ` Nikolay Aleksandrov
2016-09-09 13:39     ` Nikolay Aleksandrov
2016-09-12 11:29       ` Nogah Frankel
2016-09-08  6:19 ` [patch net-next v8 3/3] mlxsw: spectrum: Implement offload stats ndo and expose HW stats by default Jiri Pirko
2016-09-09  2:21 ` [patch net-next v8 0/3] return offloaded stats as default and expose original sw stats Roopa Prabhu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.