Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/core/gen_stats.c
15109 views
1
/*
2
* 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
*
9
* Authors: Thomas Graf <[email protected]>
10
* Jamal Hadi Salim
11
* Alexey Kuznetsov, <[email protected]>
12
*
13
* See Documentation/networking/gen_stats.txt
14
*/
15
16
#include <linux/types.h>
17
#include <linux/kernel.h>
18
#include <linux/module.h>
19
#include <linux/interrupt.h>
20
#include <linux/socket.h>
21
#include <linux/rtnetlink.h>
22
#include <linux/gen_stats.h>
23
#include <net/netlink.h>
24
#include <net/gen_stats.h>
25
26
27
static inline int
28
gnet_stats_copy(struct gnet_dump *d, int type, void *buf, int size)
29
{
30
NLA_PUT(d->skb, type, size, buf);
31
return 0;
32
33
nla_put_failure:
34
spin_unlock_bh(d->lock);
35
return -1;
36
}
37
38
/**
39
* gnet_stats_start_copy_compat - start dumping procedure in compatibility mode
40
* @skb: socket buffer to put statistics TLVs into
41
* @type: TLV type for top level statistic TLV
42
* @tc_stats_type: TLV type for backward compatibility struct tc_stats TLV
43
* @xstats_type: TLV type for backward compatibility xstats TLV
44
* @lock: statistics lock
45
* @d: dumping handle
46
*
47
* Initializes the dumping handle, grabs the statistic lock and appends
48
* an empty TLV header to the socket buffer for use a container for all
49
* other statistic TLVS.
50
*
51
* The dumping handle is marked to be in backward compatibility mode telling
52
* all gnet_stats_copy_XXX() functions to fill a local copy of struct tc_stats.
53
*
54
* Returns 0 on success or -1 if the room in the socket buffer was not sufficient.
55
*/
56
int
57
gnet_stats_start_copy_compat(struct sk_buff *skb, int type, int tc_stats_type,
58
int xstats_type, spinlock_t *lock, struct gnet_dump *d)
59
__acquires(lock)
60
{
61
memset(d, 0, sizeof(*d));
62
63
spin_lock_bh(lock);
64
d->lock = lock;
65
if (type)
66
d->tail = (struct nlattr *)skb_tail_pointer(skb);
67
d->skb = skb;
68
d->compat_tc_stats = tc_stats_type;
69
d->compat_xstats = xstats_type;
70
71
if (d->tail)
72
return gnet_stats_copy(d, type, NULL, 0);
73
74
return 0;
75
}
76
EXPORT_SYMBOL(gnet_stats_start_copy_compat);
77
78
/**
79
* gnet_stats_start_copy_compat - start dumping procedure in compatibility mode
80
* @skb: socket buffer to put statistics TLVs into
81
* @type: TLV type for top level statistic TLV
82
* @lock: statistics lock
83
* @d: dumping handle
84
*
85
* Initializes the dumping handle, grabs the statistic lock and appends
86
* an empty TLV header to the socket buffer for use a container for all
87
* other statistic TLVS.
88
*
89
* Returns 0 on success or -1 if the room in the socket buffer was not sufficient.
90
*/
91
int
92
gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock,
93
struct gnet_dump *d)
94
{
95
return gnet_stats_start_copy_compat(skb, type, 0, 0, lock, d);
96
}
97
EXPORT_SYMBOL(gnet_stats_start_copy);
98
99
/**
100
* gnet_stats_copy_basic - copy basic statistics into statistic TLV
101
* @d: dumping handle
102
* @b: basic statistics
103
*
104
* Appends the basic statistics to the top level TLV created by
105
* gnet_stats_start_copy().
106
*
107
* Returns 0 on success or -1 with the statistic lock released
108
* if the room in the socket buffer was not sufficient.
109
*/
110
int
111
gnet_stats_copy_basic(struct gnet_dump *d, struct gnet_stats_basic_packed *b)
112
{
113
if (d->compat_tc_stats) {
114
d->tc_stats.bytes = b->bytes;
115
d->tc_stats.packets = b->packets;
116
}
117
118
if (d->tail) {
119
struct gnet_stats_basic sb;
120
121
memset(&sb, 0, sizeof(sb));
122
sb.bytes = b->bytes;
123
sb.packets = b->packets;
124
return gnet_stats_copy(d, TCA_STATS_BASIC, &sb, sizeof(sb));
125
}
126
return 0;
127
}
128
EXPORT_SYMBOL(gnet_stats_copy_basic);
129
130
/**
131
* gnet_stats_copy_rate_est - copy rate estimator statistics into statistics TLV
132
* @d: dumping handle
133
* @b: basic statistics
134
* @r: rate estimator statistics
135
*
136
* Appends the rate estimator statistics to the top level TLV created by
137
* gnet_stats_start_copy().
138
*
139
* Returns 0 on success or -1 with the statistic lock released
140
* if the room in the socket buffer was not sufficient.
141
*/
142
int
143
gnet_stats_copy_rate_est(struct gnet_dump *d,
144
const struct gnet_stats_basic_packed *b,
145
struct gnet_stats_rate_est *r)
146
{
147
if (b && !gen_estimator_active(b, r))
148
return 0;
149
150
if (d->compat_tc_stats) {
151
d->tc_stats.bps = r->bps;
152
d->tc_stats.pps = r->pps;
153
}
154
155
if (d->tail)
156
return gnet_stats_copy(d, TCA_STATS_RATE_EST, r, sizeof(*r));
157
158
return 0;
159
}
160
EXPORT_SYMBOL(gnet_stats_copy_rate_est);
161
162
/**
163
* gnet_stats_copy_queue - copy queue statistics into statistics TLV
164
* @d: dumping handle
165
* @q: queue statistics
166
*
167
* Appends the queue statistics to the top level TLV created by
168
* gnet_stats_start_copy().
169
*
170
* Returns 0 on success or -1 with the statistic lock released
171
* if the room in the socket buffer was not sufficient.
172
*/
173
int
174
gnet_stats_copy_queue(struct gnet_dump *d, struct gnet_stats_queue *q)
175
{
176
if (d->compat_tc_stats) {
177
d->tc_stats.drops = q->drops;
178
d->tc_stats.qlen = q->qlen;
179
d->tc_stats.backlog = q->backlog;
180
d->tc_stats.overlimits = q->overlimits;
181
}
182
183
if (d->tail)
184
return gnet_stats_copy(d, TCA_STATS_QUEUE, q, sizeof(*q));
185
186
return 0;
187
}
188
EXPORT_SYMBOL(gnet_stats_copy_queue);
189
190
/**
191
* gnet_stats_copy_app - copy application specific statistics into statistics TLV
192
* @d: dumping handle
193
* @st: application specific statistics data
194
* @len: length of data
195
*
196
* Appends the application sepecific statistics to the top level TLV created by
197
* gnet_stats_start_copy() and remembers the data for XSTATS if the dumping
198
* handle is in backward compatibility mode.
199
*
200
* Returns 0 on success or -1 with the statistic lock released
201
* if the room in the socket buffer was not sufficient.
202
*/
203
int
204
gnet_stats_copy_app(struct gnet_dump *d, void *st, int len)
205
{
206
if (d->compat_xstats) {
207
d->xstats = st;
208
d->xstats_len = len;
209
}
210
211
if (d->tail)
212
return gnet_stats_copy(d, TCA_STATS_APP, st, len);
213
214
return 0;
215
}
216
EXPORT_SYMBOL(gnet_stats_copy_app);
217
218
/**
219
* gnet_stats_finish_copy - finish dumping procedure
220
* @d: dumping handle
221
*
222
* Corrects the length of the top level TLV to include all TLVs added
223
* by gnet_stats_copy_XXX() calls. Adds the backward compatibility TLVs
224
* if gnet_stats_start_copy_compat() was used and releases the statistics
225
* lock.
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_finish_copy(struct gnet_dump *d)
232
{
233
if (d->tail)
234
d->tail->nla_len = skb_tail_pointer(d->skb) - (u8 *)d->tail;
235
236
if (d->compat_tc_stats)
237
if (gnet_stats_copy(d, d->compat_tc_stats, &d->tc_stats,
238
sizeof(d->tc_stats)) < 0)
239
return -1;
240
241
if (d->compat_xstats && d->xstats) {
242
if (gnet_stats_copy(d, d->compat_xstats, d->xstats,
243
d->xstats_len) < 0)
244
return -1;
245
}
246
247
spin_unlock_bh(d->lock);
248
return 0;
249
}
250
EXPORT_SYMBOL(gnet_stats_finish_copy);
251
252