.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * 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. |
---|
8 | 4 | * |
---|
9 | 5 | * Authors: Thomas Graf <tgraf@suug.ch> |
---|
10 | 6 | * Jamal Hadi Salim |
---|
11 | 7 | * Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
---|
12 | 8 | * |
---|
13 | | - * See Documentation/networking/gen_stats.txt |
---|
| 9 | + * See Documentation/networking/gen_stats.rst |
---|
14 | 10 | */ |
---|
15 | 11 | |
---|
16 | 12 | #include <linux/types.h> |
---|
.. | .. |
---|
127 | 123 | for_each_possible_cpu(i) { |
---|
128 | 124 | struct gnet_stats_basic_cpu *bcpu = per_cpu_ptr(cpu, i); |
---|
129 | 125 | unsigned int start; |
---|
130 | | - u64 bytes; |
---|
131 | | - u32 packets; |
---|
| 126 | + u64 bytes, packets; |
---|
132 | 127 | |
---|
133 | 128 | do { |
---|
134 | 129 | start = u64_stats_fetch_begin_irq(&bcpu->syncp); |
---|
.. | .. |
---|
142 | 137 | } |
---|
143 | 138 | |
---|
144 | 139 | void |
---|
145 | | -__gnet_stats_copy_basic(net_seqlock_t *running, |
---|
| 140 | +__gnet_stats_copy_basic(const seqcount_t *running, |
---|
146 | 141 | struct gnet_stats_basic_packed *bstats, |
---|
147 | 142 | struct gnet_stats_basic_cpu __percpu *cpu, |
---|
148 | 143 | struct gnet_stats_basic_packed *b) |
---|
.. | .. |
---|
155 | 150 | } |
---|
156 | 151 | do { |
---|
157 | 152 | if (running) |
---|
158 | | - seq = net_seq_begin(running); |
---|
| 153 | + seq = read_seqcount_begin(running); |
---|
159 | 154 | bstats->bytes = b->bytes; |
---|
160 | 155 | bstats->packets = b->packets; |
---|
161 | | - } while (running && net_seq_retry(running, seq)); |
---|
| 156 | + } while (running && read_seqcount_retry(running, seq)); |
---|
162 | 157 | } |
---|
163 | 158 | 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 | +} |
---|
164 | 192 | |
---|
165 | 193 | /** |
---|
166 | 194 | * gnet_stats_copy_basic - copy basic statistics into statistic TLV |
---|
.. | .. |
---|
176 | 204 | * if the room in the socket buffer was not sufficient. |
---|
177 | 205 | */ |
---|
178 | 206 | int |
---|
179 | | -gnet_stats_copy_basic(net_seqlock_t *running, |
---|
| 207 | +gnet_stats_copy_basic(const seqcount_t *running, |
---|
180 | 208 | struct gnet_dump *d, |
---|
181 | 209 | struct gnet_stats_basic_cpu __percpu *cpu, |
---|
182 | 210 | struct gnet_stats_basic_packed *b) |
---|
183 | 211 | { |
---|
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); |
---|
203 | 214 | } |
---|
204 | 215 | 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); |
---|
205 | 240 | |
---|
206 | 241 | /** |
---|
207 | 242 | * gnet_stats_copy_rate_est - copy rate estimator statistics into statistics TLV |
---|
.. | .. |
---|
256 | 291 | for_each_possible_cpu(i) { |
---|
257 | 292 | const struct gnet_stats_queue *qcpu = per_cpu_ptr(q, i); |
---|
258 | 293 | |
---|
| 294 | + qstats->qlen = 0; |
---|
259 | 295 | qstats->backlog += qcpu->backlog; |
---|
260 | 296 | qstats->drops += qcpu->drops; |
---|
261 | 297 | qstats->requeues += qcpu->requeues; |
---|
.. | .. |
---|
271 | 307 | if (cpu) { |
---|
272 | 308 | __gnet_stats_copy_queue_cpu(qstats, cpu); |
---|
273 | 309 | } else { |
---|
| 310 | + qstats->qlen = q->qlen; |
---|
274 | 311 | qstats->backlog = q->backlog; |
---|
275 | 312 | qstats->drops = q->drops; |
---|
276 | 313 | qstats->requeues = q->requeues; |
---|