Skip to content

Commit eadfa4c

Browse files
shorman-netronomedavem330
authored andcommitted
nfp: add stats and xmit helpers for representors
Provide helpers for stats and xmit on representor netdevs. Parts based on work by Bert van Leeuwen, Benjamin LaHaise and Jakub Kicinski. Signed-off-by: Simon Horman <[email protected]> Reviewed-by: Jakub Kicinski <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 5de73ee commit eadfa4c

File tree

2 files changed

+226
-1
lines changed

2 files changed

+226
-1
lines changed

drivers/net/ethernet/netronome/nfp/nfp_net_repr.c

Lines changed: 198 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,198 @@
3232
*/
3333

3434
#include <linux/etherdevice.h>
35+
#include <linux/io-64-nonatomic-hi-lo.h>
3536
#include <linux/lockdep.h>
3637
#include <net/dst_metadata.h>
3738

3839
#include "nfpcore/nfp_cpp.h"
3940
#include "nfp_app.h"
4041
#include "nfp_main.h"
42+
#include "nfp_net_ctrl.h"
4143
#include "nfp_net_repr.h"
4244
#include "nfp_port.h"
4345

46+
static void
47+
nfp_repr_inc_tx_stats(struct net_device *netdev, unsigned int len,
48+
int tx_status)
49+
{
50+
struct nfp_repr *repr = netdev_priv(netdev);
51+
struct nfp_repr_pcpu_stats *stats;
52+
53+
if (unlikely(tx_status != NET_XMIT_SUCCESS &&
54+
tx_status != NET_XMIT_CN)) {
55+
this_cpu_inc(repr->stats->tx_drops);
56+
return;
57+
}
58+
59+
stats = this_cpu_ptr(repr->stats);
60+
u64_stats_update_begin(&stats->syncp);
61+
stats->tx_packets++;
62+
stats->tx_bytes += len;
63+
u64_stats_update_end(&stats->syncp);
64+
}
65+
66+
void nfp_repr_inc_rx_stats(struct net_device *netdev, unsigned int len)
67+
{
68+
struct nfp_repr *repr = netdev_priv(netdev);
69+
struct nfp_repr_pcpu_stats *stats;
70+
71+
stats = this_cpu_ptr(repr->stats);
72+
u64_stats_update_begin(&stats->syncp);
73+
stats->rx_packets++;
74+
stats->rx_bytes += len;
75+
u64_stats_update_end(&stats->syncp);
76+
}
77+
78+
static void
79+
nfp_repr_phy_port_get_stats64(const struct nfp_app *app, u8 phy_port,
80+
struct rtnl_link_stats64 *stats)
81+
{
82+
u8 __iomem *mem;
83+
84+
mem = app->pf->mac_stats_mem + phy_port * NFP_MAC_STATS_SIZE;
85+
86+
/* TX and RX stats are flipped as we are returning the stats as seen
87+
* at the switch port corresponding to the phys port.
88+
*/
89+
stats->tx_packets = readq(mem + NFP_MAC_STATS_RX_FRAMES_RECEIVED_OK);
90+
stats->tx_bytes = readq(mem + NFP_MAC_STATS_RX_IN_OCTETS);
91+
stats->tx_dropped = readq(mem + NFP_MAC_STATS_RX_IN_ERRORS);
92+
93+
stats->rx_packets = readq(mem + NFP_MAC_STATS_TX_FRAMES_TRANSMITTED_OK);
94+
stats->rx_bytes = readq(mem + NFP_MAC_STATS_TX_OUT_OCTETS);
95+
stats->rx_dropped = readq(mem + NFP_MAC_STATS_TX_OUT_ERRORS);
96+
}
97+
98+
static void
99+
nfp_repr_vf_get_stats64(const struct nfp_app *app, u8 vf,
100+
struct rtnl_link_stats64 *stats)
101+
{
102+
u8 __iomem *mem;
103+
104+
mem = app->pf->vf_cfg_mem + vf * NFP_NET_CFG_BAR_SZ;
105+
106+
/* TX and RX stats are flipped as we are returning the stats as seen
107+
* at the switch port corresponding to the VF.
108+
*/
109+
stats->tx_packets = readq(mem + NFP_NET_CFG_STATS_RX_FRAMES);
110+
stats->tx_bytes = readq(mem + NFP_NET_CFG_STATS_RX_OCTETS);
111+
stats->tx_dropped = readq(mem + NFP_NET_CFG_STATS_RX_DISCARDS);
112+
113+
stats->rx_packets = readq(mem + NFP_NET_CFG_STATS_TX_FRAMES);
114+
stats->rx_bytes = readq(mem + NFP_NET_CFG_STATS_TX_OCTETS);
115+
stats->rx_dropped = readq(mem + NFP_NET_CFG_STATS_TX_DISCARDS);
116+
}
117+
118+
static void
119+
nfp_repr_pf_get_stats64(const struct nfp_app *app, u8 pf,
120+
struct rtnl_link_stats64 *stats)
121+
{
122+
u8 __iomem *mem;
123+
124+
if (pf)
125+
return;
126+
127+
mem = nfp_cpp_area_iomem(app->pf->data_vnic_bar);
128+
129+
stats->tx_packets = readq(mem + NFP_NET_CFG_STATS_RX_FRAMES);
130+
stats->tx_bytes = readq(mem + NFP_NET_CFG_STATS_RX_OCTETS);
131+
stats->tx_dropped = readq(mem + NFP_NET_CFG_STATS_RX_DISCARDS);
132+
133+
stats->rx_packets = readq(mem + NFP_NET_CFG_STATS_TX_FRAMES);
134+
stats->rx_bytes = readq(mem + NFP_NET_CFG_STATS_TX_OCTETS);
135+
stats->rx_dropped = readq(mem + NFP_NET_CFG_STATS_TX_DISCARDS);
136+
}
137+
138+
void
139+
nfp_repr_get_stats64(const struct nfp_app *app, enum nfp_repr_type type,
140+
u8 port, struct rtnl_link_stats64 *stats)
141+
{
142+
switch (type) {
143+
case NFP_REPR_TYPE_PHYS_PORT:
144+
nfp_repr_phy_port_get_stats64(app, port, stats);
145+
break;
146+
case NFP_REPR_TYPE_PF:
147+
nfp_repr_pf_get_stats64(app, port, stats);
148+
break;
149+
case NFP_REPR_TYPE_VF:
150+
nfp_repr_vf_get_stats64(app, port, stats);
151+
default:
152+
break;
153+
}
154+
}
155+
156+
bool
157+
nfp_repr_has_offload_stats(const struct net_device *dev, int attr_id)
158+
{
159+
switch (attr_id) {
160+
case IFLA_OFFLOAD_XSTATS_CPU_HIT:
161+
return true;
162+
}
163+
164+
return false;
165+
}
166+
167+
static int
168+
nfp_repr_get_host_stats64(const struct net_device *netdev,
169+
struct rtnl_link_stats64 *stats)
170+
{
171+
struct nfp_repr *repr = netdev_priv(netdev);
172+
int i;
173+
174+
for_each_possible_cpu(i) {
175+
u64 tbytes, tpkts, tdrops, rbytes, rpkts;
176+
struct nfp_repr_pcpu_stats *repr_stats;
177+
unsigned int start;
178+
179+
repr_stats = per_cpu_ptr(repr->stats, i);
180+
do {
181+
start = u64_stats_fetch_begin_irq(&repr_stats->syncp);
182+
tbytes = repr_stats->tx_bytes;
183+
tpkts = repr_stats->tx_packets;
184+
tdrops = repr_stats->tx_drops;
185+
rbytes = repr_stats->rx_bytes;
186+
rpkts = repr_stats->rx_packets;
187+
} while (u64_stats_fetch_retry_irq(&repr_stats->syncp, start));
188+
189+
stats->tx_bytes += tbytes;
190+
stats->tx_packets += tpkts;
191+
stats->tx_dropped += tdrops;
192+
stats->rx_bytes += rbytes;
193+
stats->rx_packets += rpkts;
194+
}
195+
196+
return 0;
197+
}
198+
199+
int nfp_repr_get_offload_stats(int attr_id, const struct net_device *dev,
200+
void *stats)
201+
{
202+
switch (attr_id) {
203+
case IFLA_OFFLOAD_XSTATS_CPU_HIT:
204+
return nfp_repr_get_host_stats64(dev, stats);
205+
}
206+
207+
return -EINVAL;
208+
}
209+
210+
netdev_tx_t nfp_repr_xmit(struct sk_buff *skb, struct net_device *netdev)
211+
{
212+
struct nfp_repr *repr = netdev_priv(netdev);
213+
unsigned int len = skb->len;
214+
int ret;
215+
216+
skb_dst_drop(skb);
217+
dst_hold((struct dst_entry *)repr->dst);
218+
skb_dst_set(skb, (struct dst_entry *)repr->dst);
219+
skb->dev = repr->dst->u.port_info.lower_dev;
220+
221+
ret = dev_queue_xmit(skb);
222+
nfp_repr_inc_tx_stats(netdev, len, ret);
223+
224+
return ret;
225+
}
226+
44227
static void nfp_repr_clean(struct nfp_repr *repr)
45228
{
46229
unregister_netdev(repr->netdev);
@@ -93,6 +276,12 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
93276
return err;
94277
}
95278

279+
static void nfp_repr_free(struct nfp_repr *repr)
280+
{
281+
free_percpu(repr->stats);
282+
free_netdev(repr->netdev);
283+
}
284+
96285
struct net_device *nfp_repr_alloc(struct nfp_app *app)
97286
{
98287
struct net_device *netdev;
@@ -106,15 +295,23 @@ struct net_device *nfp_repr_alloc(struct nfp_app *app)
106295
repr->netdev = netdev;
107296
repr->app = app;
108297

298+
repr->stats = netdev_alloc_pcpu_stats(struct nfp_repr_pcpu_stats);
299+
if (!repr->stats)
300+
goto err_free_netdev;
301+
109302
return netdev;
303+
304+
err_free_netdev:
305+
free_netdev(netdev);
306+
return NULL;
110307
}
111308

112309
static void nfp_repr_clean_and_free(struct nfp_repr *repr)
113310
{
114311
nfp_info(repr->app->cpp, "Destroying Representor(%s)\n",
115312
repr->netdev->name);
116313
nfp_repr_clean(repr);
117-
free_netdev(repr->netdev);
314+
nfp_repr_free(repr);
118315
}
119316

120317
void nfp_reprs_clean_and_free(struct nfp_reprs *reprs)

drivers/net/ethernet/netronome/nfp/nfp_net_repr.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,38 @@ struct nfp_reprs {
4848
struct net_device *reprs[0];
4949
};
5050

51+
/**
52+
* struct nfp_repr_pcpu_stats
53+
* @rx_packets: Received packets
54+
* @rx_bytes: Received bytes
55+
* @tx_packets: Transmitted packets
56+
* @tx_bytes: Transmitted dropped
57+
* @tx_drops: Packets dropped on transmit
58+
* @syncp: Reference count
59+
*/
60+
struct nfp_repr_pcpu_stats {
61+
u64 rx_packets;
62+
u64 rx_bytes;
63+
u64 tx_packets;
64+
u64 tx_bytes;
65+
u64 tx_drops;
66+
struct u64_stats_sync syncp;
67+
};
68+
5169
/**
5270
* struct nfp_repr - priv data for representor netdevs
5371
* @netdev: Back pointer to netdev
5472
* @dst: Destination for packet TX
5573
* @port: Port of representor
5674
* @app: APP handle
75+
* @stats: Statistic of packets hitting CPU
5776
*/
5877
struct nfp_repr {
5978
struct net_device *netdev;
6079
struct metadata_dst *dst;
6180
struct nfp_port *port;
6281
struct nfp_app *app;
82+
struct nfp_repr_pcpu_stats __percpu *stats;
6383
};
6484

6585
/**
@@ -77,6 +97,14 @@ enum nfp_repr_type {
7797
};
7898
#define NFP_REPR_TYPE_MAX (__NFP_REPR_TYPE_MAX - 1)
7999

100+
void nfp_repr_inc_rx_stats(struct net_device *netdev, unsigned int len);
101+
void
102+
nfp_repr_get_stats64(const struct nfp_app *app, enum nfp_repr_type type,
103+
u8 port, struct rtnl_link_stats64 *stats);
104+
bool nfp_repr_has_offload_stats(const struct net_device *dev, int attr_id);
105+
int nfp_repr_get_offload_stats(int attr_id, const struct net_device *dev,
106+
void *stats);
107+
netdev_tx_t nfp_repr_xmit(struct sk_buff *skb, struct net_device *netdev);
80108
int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
81109
const struct net_device_ops *netdev_ops,
82110
u32 cmsg_port_id, struct nfp_port *port,

0 commit comments

Comments
 (0)