| .. | .. |
|---|
| 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; |
|---|