hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/net/core/gen_stats.c
....@@ -1,16 +1,12 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * net/core/gen_stats.c
3
- *
4
- * This program is free software; you can redistribute it and/or
5
- * modify it under the terms of the GNU General Public License
6
- * as published by the Free Software Foundation; either version
7
- * 2 of the License, or (at your option) any later version.
84 *
95 * Authors: Thomas Graf <tgraf@suug.ch>
106 * Jamal Hadi Salim
117 * Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
128 *
13
- * See Documentation/networking/gen_stats.txt
9
+ * See Documentation/networking/gen_stats.rst
1410 */
1511
1612 #include <linux/types.h>
....@@ -127,8 +123,7 @@
127123 for_each_possible_cpu(i) {
128124 struct gnet_stats_basic_cpu *bcpu = per_cpu_ptr(cpu, i);
129125 unsigned int start;
130
- u64 bytes;
131
- u32 packets;
126
+ u64 bytes, packets;
132127
133128 do {
134129 start = u64_stats_fetch_begin_irq(&bcpu->syncp);
....@@ -142,7 +137,7 @@
142137 }
143138
144139 void
145
-__gnet_stats_copy_basic(net_seqlock_t *running,
140
+__gnet_stats_copy_basic(const seqcount_t *running,
146141 struct gnet_stats_basic_packed *bstats,
147142 struct gnet_stats_basic_cpu __percpu *cpu,
148143 struct gnet_stats_basic_packed *b)
....@@ -155,12 +150,45 @@
155150 }
156151 do {
157152 if (running)
158
- seq = net_seq_begin(running);
153
+ seq = read_seqcount_begin(running);
159154 bstats->bytes = b->bytes;
160155 bstats->packets = b->packets;
161
- } while (running && net_seq_retry(running, seq));
156
+ } while (running && read_seqcount_retry(running, seq));
162157 }
163158 EXPORT_SYMBOL(__gnet_stats_copy_basic);
159
+
160
+static int
161
+___gnet_stats_copy_basic(const seqcount_t *running,
162
+ struct gnet_dump *d,
163
+ struct gnet_stats_basic_cpu __percpu *cpu,
164
+ struct gnet_stats_basic_packed *b,
165
+ int type)
166
+{
167
+ struct gnet_stats_basic_packed bstats = {0};
168
+
169
+ __gnet_stats_copy_basic(running, &bstats, cpu, b);
170
+
171
+ if (d->compat_tc_stats && type == TCA_STATS_BASIC) {
172
+ d->tc_stats.bytes = bstats.bytes;
173
+ d->tc_stats.packets = bstats.packets;
174
+ }
175
+
176
+ if (d->tail) {
177
+ struct gnet_stats_basic sb;
178
+ int res;
179
+
180
+ memset(&sb, 0, sizeof(sb));
181
+ sb.bytes = bstats.bytes;
182
+ sb.packets = bstats.packets;
183
+ res = gnet_stats_copy(d, type, &sb, sizeof(sb), TCA_STATS_PAD);
184
+ if (res < 0 || sb.packets == bstats.packets)
185
+ return res;
186
+ /* emit 64bit stats only if needed */
187
+ return gnet_stats_copy(d, TCA_STATS_PKT64, &bstats.packets,
188
+ sizeof(bstats.packets), TCA_STATS_PAD);
189
+ }
190
+ return 0;
191
+}
164192
165193 /**
166194 * gnet_stats_copy_basic - copy basic statistics into statistic TLV
....@@ -176,32 +204,39 @@
176204 * if the room in the socket buffer was not sufficient.
177205 */
178206 int
179
-gnet_stats_copy_basic(net_seqlock_t *running,
207
+gnet_stats_copy_basic(const seqcount_t *running,
180208 struct gnet_dump *d,
181209 struct gnet_stats_basic_cpu __percpu *cpu,
182210 struct gnet_stats_basic_packed *b)
183211 {
184
- struct gnet_stats_basic_packed bstats = {0};
185
-
186
- __gnet_stats_copy_basic(running, &bstats, cpu, b);
187
-
188
- if (d->compat_tc_stats) {
189
- d->tc_stats.bytes = bstats.bytes;
190
- d->tc_stats.packets = bstats.packets;
191
- }
192
-
193
- if (d->tail) {
194
- struct gnet_stats_basic sb;
195
-
196
- memset(&sb, 0, sizeof(sb));
197
- sb.bytes = bstats.bytes;
198
- sb.packets = bstats.packets;
199
- return gnet_stats_copy(d, TCA_STATS_BASIC, &sb, sizeof(sb),
200
- TCA_STATS_PAD);
201
- }
202
- return 0;
212
+ return ___gnet_stats_copy_basic(running, d, cpu, b,
213
+ TCA_STATS_BASIC);
203214 }
204215 EXPORT_SYMBOL(gnet_stats_copy_basic);
216
+
217
+/**
218
+ * gnet_stats_copy_basic_hw - copy basic hw statistics into statistic TLV
219
+ * @running: seqcount_t pointer
220
+ * @d: dumping handle
221
+ * @cpu: copy statistic per cpu
222
+ * @b: basic statistics
223
+ *
224
+ * Appends the basic statistics to the top level TLV created by
225
+ * gnet_stats_start_copy().
226
+ *
227
+ * Returns 0 on success or -1 with the statistic lock released
228
+ * if the room in the socket buffer was not sufficient.
229
+ */
230
+int
231
+gnet_stats_copy_basic_hw(const seqcount_t *running,
232
+ struct gnet_dump *d,
233
+ struct gnet_stats_basic_cpu __percpu *cpu,
234
+ struct gnet_stats_basic_packed *b)
235
+{
236
+ return ___gnet_stats_copy_basic(running, d, cpu, b,
237
+ TCA_STATS_BASIC_HW);
238
+}
239
+EXPORT_SYMBOL(gnet_stats_copy_basic_hw);
205240
206241 /**
207242 * gnet_stats_copy_rate_est - copy rate estimator statistics into statistics TLV
....@@ -256,6 +291,7 @@
256291 for_each_possible_cpu(i) {
257292 const struct gnet_stats_queue *qcpu = per_cpu_ptr(q, i);
258293
294
+ qstats->qlen = 0;
259295 qstats->backlog += qcpu->backlog;
260296 qstats->drops += qcpu->drops;
261297 qstats->requeues += qcpu->requeues;
....@@ -271,6 +307,7 @@
271307 if (cpu) {
272308 __gnet_stats_copy_queue_cpu(qstats, cpu);
273309 } else {
310
+ qstats->qlen = q->qlen;
274311 qstats->backlog = q->backlog;
275312 qstats->drops = q->drops;
276313 qstats->requeues = q->requeues;