Skip to content

Commit 8fe52e5

Browse files
committed
net: l2: ethernet: Add new stats API
Add a new API that takes stat type, the networking stack only needs NATIVE stats per-packet, it doesn't need to update vendor stats per-packet. This saves unncessary exchanges in case driver needs to query the firmware for the vendor stats. Signed-off-by: Chaitanya Tata <[email protected]>
1 parent 0b52928 commit 8fe52e5

File tree

4 files changed

+78
-135
lines changed

4 files changed

+78
-135
lines changed

doc/releases/release-notes-4.4.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,13 @@ New APIs and options
130130
* :c:struct:`net_eth_mac_config`
131131
* :c:macro:`NET_ETH_MAC_DT_CONFIG_INIT` and :c:macro:`NET_ETH_MAC_DT_INST_CONFIG_INIT`
132132

133+
* Added :c:enum:`ethernet_stats_type` and optional ``get_stats_type`` callback in
134+
:c:struct:`ethernet_api` to allow filtering of ethernet statistics by type
135+
(common, vendor, or all). Drivers that support vendor-specific statistics can
136+
implement ``get_stats_type`` to skip expensive FW queries when only common stats
137+
are requested. The existing ``get_stats`` API remains unchanged for backward
138+
compatibility.
139+
133140
* Flash
134141

135142
* :dtcompatible:`jedec,mspi-nor` now allows MSPI configuration of read, write and

include/zephyr/net/ethernet.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,16 @@ struct ethernet_config {
529529

530530
/** @endcond */
531531

532+
/** Ethernet statistics type (bitmap) */
533+
enum ethernet_stats_type {
534+
/** Common statistics only (excludes vendor statistics) */
535+
ETHERNET_STATS_TYPE_COMMON = BIT(0),
536+
/** Vendor statistics only */
537+
ETHERNET_STATS_TYPE_VENDOR = BIT(1),
538+
/** All statistics */
539+
ETHERNET_STATS_TYPE_ALL = 0xFFFFFFFFU,
540+
};
541+
532542
/** Ethernet L2 API operations. */
533543
struct ethernet_api {
534544
/**
@@ -543,6 +553,14 @@ struct ethernet_api {
543553
*/
544554
#if defined(CONFIG_NET_STATISTICS_ETHERNET)
545555
struct net_stats_eth *(*get_stats)(const struct device *dev);
556+
557+
/** Optional function to collect ethernet specific statistics with
558+
* type filter. If NULL, get_stats() will be called instead, which
559+
* is equivalent to calling this with ETHERNET_STATS_TYPE_ALL.
560+
* @param type Bitmask of ethernet_stats_type values.
561+
*/
562+
struct net_stats_eth *(*get_stats_type)(const struct device *dev,
563+
uint32_t type);
546564
#endif
547565

548566
/** Start the device */

subsys/net/l2/ethernet/eth_stats.h

Lines changed: 45 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -14,211 +14,123 @@
1414
#include <zephyr/net/net_if.h>
1515
#include <zephyr/net/ethernet.h>
1616

17-
static inline void eth_stats_update_bytes_rx(struct net_if *iface,
18-
uint32_t bytes)
17+
static inline struct net_stats_eth *eth_stats_get_common(struct net_if *iface)
1918
{
2019
const struct ethernet_api *api = (const struct ethernet_api *)
2120
net_if_get_device(iface)->api;
22-
struct net_stats_eth *stats;
23-
24-
if (!api->get_stats) {
25-
return;
26-
}
2721

28-
stats = api->get_stats(net_if_get_device(iface));
29-
if (!stats) {
30-
return;
22+
if (api->get_stats_type != NULL) {
23+
return api->get_stats_type(net_if_get_device(iface),
24+
ETHERNET_STATS_TYPE_COMMON);
25+
} else if (api->get_stats != NULL) {
26+
return api->get_stats(net_if_get_device(iface));
3127
}
3228

33-
stats->bytes.received += bytes;
29+
return NULL;
3430
}
3531

36-
static inline void eth_stats_update_bytes_tx(struct net_if *iface,
37-
uint32_t bytes)
32+
static inline void eth_stats_update_bytes_rx(struct net_if *iface, uint32_t bytes)
3833
{
39-
const struct ethernet_api *api = (const struct ethernet_api *)
40-
net_if_get_device(iface)->api;
41-
struct net_stats_eth *stats;
34+
struct net_stats_eth *stats = eth_stats_get_common(iface);
4235

43-
if (!api->get_stats) {
44-
return;
36+
if (stats != NULL) {
37+
stats->bytes.received += bytes;
4538
}
39+
}
4640

47-
stats = api->get_stats(net_if_get_device(iface));
48-
if (!stats) {
49-
return;
50-
}
41+
static inline void eth_stats_update_bytes_tx(struct net_if *iface, uint32_t bytes)
42+
{
43+
struct net_stats_eth *stats = eth_stats_get_common(iface);
5144

52-
stats->bytes.sent += bytes;
45+
if (stats != NULL) {
46+
stats->bytes.sent += bytes;
47+
}
5348
}
5449

5550
static inline void eth_stats_update_pkts_rx(struct net_if *iface)
5651
{
57-
const struct ethernet_api *api = (const struct ethernet_api *)
58-
net_if_get_device(iface)->api;
59-
struct net_stats_eth *stats;
52+
struct net_stats_eth *stats = eth_stats_get_common(iface);
6053

61-
if (!api->get_stats) {
62-
return;
63-
}
64-
65-
stats = api->get_stats(net_if_get_device(iface));
66-
if (!stats) {
67-
return;
54+
if (stats != NULL) {
55+
stats->pkts.rx++;
6856
}
69-
70-
stats->pkts.rx++;
7157
}
7258

7359
static inline void eth_stats_update_pkts_tx(struct net_if *iface)
7460
{
75-
const struct ethernet_api *api = (const struct ethernet_api *)
76-
net_if_get_device(iface)->api;
77-
struct net_stats_eth *stats;
78-
79-
if (!api->get_stats) {
80-
return;
81-
}
61+
struct net_stats_eth *stats = eth_stats_get_common(iface);
8262

83-
stats = api->get_stats(net_if_get_device(iface));
84-
if (!stats) {
85-
return;
63+
if (stats != NULL) {
64+
stats->pkts.tx++;
8665
}
87-
88-
stats->pkts.tx++;
8966
}
9067

9168
static inline void eth_stats_update_broadcast_rx(struct net_if *iface)
9269
{
93-
const struct ethernet_api *api = (const struct ethernet_api *)
94-
net_if_get_device(iface)->api;
95-
struct net_stats_eth *stats;
96-
97-
if (!api->get_stats) {
98-
return;
99-
}
70+
struct net_stats_eth *stats = eth_stats_get_common(iface);
10071

101-
stats = api->get_stats(net_if_get_device(iface));
102-
if (!stats) {
103-
return;
72+
if (stats != NULL) {
73+
stats->broadcast.rx++;
10474
}
105-
106-
stats->broadcast.rx++;
10775
}
10876

10977
static inline void eth_stats_update_broadcast_tx(struct net_if *iface)
11078
{
111-
const struct ethernet_api *api = (const struct ethernet_api *)
112-
net_if_get_device(iface)->api;
113-
struct net_stats_eth *stats;
79+
struct net_stats_eth *stats = eth_stats_get_common(iface);
11480

115-
if (!api->get_stats) {
116-
return;
81+
if (stats != NULL) {
82+
stats->broadcast.tx++;
11783
}
118-
119-
stats = api->get_stats(net_if_get_device(iface));
120-
if (!stats) {
121-
return;
122-
}
123-
124-
stats->broadcast.tx++;
12584
}
12685

12786
static inline void eth_stats_update_multicast_rx(struct net_if *iface)
12887
{
129-
const struct ethernet_api *api = (const struct ethernet_api *)
130-
net_if_get_device(iface)->api;
131-
struct net_stats_eth *stats;
132-
133-
if (!api->get_stats) {
134-
return;
135-
}
88+
struct net_stats_eth *stats = eth_stats_get_common(iface);
13689

137-
stats = api->get_stats(net_if_get_device(iface));
138-
if (!stats) {
139-
return;
90+
if (stats != NULL) {
91+
stats->multicast.rx++;
14092
}
141-
142-
stats->multicast.rx++;
14393
}
14494

14595
static inline void eth_stats_update_multicast_tx(struct net_if *iface)
14696
{
147-
const struct ethernet_api *api = (const struct ethernet_api *)
148-
net_if_get_device(iface)->api;
149-
struct net_stats_eth *stats;
97+
struct net_stats_eth *stats = eth_stats_get_common(iface);
15098

151-
if (!api->get_stats) {
152-
return;
153-
}
154-
155-
stats = api->get_stats(net_if_get_device(iface));
156-
if (!stats) {
157-
return;
99+
if (stats != NULL) {
100+
stats->multicast.tx++;
158101
}
159-
160-
stats->multicast.tx++;
161102
}
162103

163-
164104
static inline void eth_stats_update_errors_rx(struct net_if *iface)
165105
{
166106
struct net_stats_eth *stats;
167-
const struct ethernet_api *api;
168107

169108
if (!iface) {
170109
return;
171110
}
172111

173-
api = ((const struct ethernet_api *)
174-
net_if_get_device(iface)->api);
175-
176-
if (!api->get_stats) {
177-
return;
178-
}
179-
180-
stats = api->get_stats(net_if_get_device(iface));
181-
if (!stats) {
182-
return;
112+
stats = eth_stats_get_common(iface);
113+
if (stats != NULL) {
114+
stats->errors.rx++;
183115
}
184-
185-
stats->errors.rx++;
186116
}
187117

188118
static inline void eth_stats_update_errors_tx(struct net_if *iface)
189119
{
190-
struct net_stats_eth *stats;
191-
const struct ethernet_api *api = ((const struct ethernet_api *)
192-
net_if_get_device(iface)->api);
193-
194-
if (!api->get_stats) {
195-
return;
196-
}
120+
struct net_stats_eth *stats = eth_stats_get_common(iface);
197121

198-
stats = api->get_stats(net_if_get_device(iface));
199-
if (!stats) {
200-
return;
122+
if (stats != NULL) {
123+
stats->errors.tx++;
201124
}
202-
203-
stats->errors.tx++;
204125
}
205126

206127
static inline void eth_stats_update_unknown_protocol(struct net_if *iface)
207128
{
208-
struct net_stats_eth *stats;
209-
const struct ethernet_api *api = ((const struct ethernet_api *)
210-
net_if_get_device(iface)->api);
129+
struct net_stats_eth *stats = eth_stats_get_common(iface);
211130

212-
if (!api->get_stats) {
213-
return;
131+
if (stats != NULL) {
132+
stats->unknown_protocol++;
214133
}
215-
216-
stats = api->get_stats(net_if_get_device(iface));
217-
if (!stats) {
218-
return;
219-
}
220-
221-
stats->unknown_protocol++;
222134
}
223135

224136
#else /* CONFIG_NET_STATISTICS_ETHERNET */

subsys/net/l2/ethernet/ethernet_stats.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,18 @@ static int eth_stats_get(uint64_t mgmt_request, struct net_if *iface,
3131
}
3232

3333
eth = net_if_get_device(iface)->api;
34-
if (eth == NULL || eth->get_stats == NULL) {
34+
if (eth == NULL ||
35+
(eth->get_stats == NULL && eth->get_stats_type == NULL)) {
3536
return -ENOENT;
3637
}
3738

3839
len_chk = sizeof(struct net_stats_eth);
39-
src = eth->get_stats(net_if_get_device(iface));
40+
if (eth->get_stats_type != NULL) {
41+
src = eth->get_stats_type(net_if_get_device(iface),
42+
ETHERNET_STATS_TYPE_ALL);
43+
} else {
44+
src = eth->get_stats(net_if_get_device(iface));
45+
}
4046
break;
4147
}
4248

0 commit comments

Comments
 (0)