Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/8021q/vlanproc.c
15109 views
1
/******************************************************************************
2
* vlanproc.c VLAN Module. /proc filesystem interface.
3
*
4
* This module is completely hardware-independent and provides
5
* access to the router using Linux /proc filesystem.
6
*
7
* Author: Ben Greear, <[email protected]> coppied from wanproc.c
8
* by: Gene Kozin <[email protected]>
9
*
10
* Copyright: (c) 1998 Ben Greear
11
*
12
* This program is free software; you can redistribute it and/or
13
* modify it under the terms of the GNU General Public License
14
* as published by the Free Software Foundation; either version
15
* 2 of the License, or (at your option) any later version.
16
* ============================================================================
17
* Jan 20, 1998 Ben Greear Initial Version
18
*****************************************************************************/
19
20
#include <linux/module.h>
21
#include <linux/errno.h>
22
#include <linux/kernel.h>
23
#include <linux/string.h>
24
#include <linux/proc_fs.h>
25
#include <linux/seq_file.h>
26
#include <linux/fs.h>
27
#include <linux/netdevice.h>
28
#include <linux/if_vlan.h>
29
#include <net/net_namespace.h>
30
#include <net/netns/generic.h>
31
#include "vlanproc.h"
32
#include "vlan.h"
33
34
/****** Function Prototypes *************************************************/
35
36
/* Methods for preparing data for reading proc entries */
37
static int vlan_seq_show(struct seq_file *seq, void *v);
38
static void *vlan_seq_start(struct seq_file *seq, loff_t *pos);
39
static void *vlan_seq_next(struct seq_file *seq, void *v, loff_t *pos);
40
static void vlan_seq_stop(struct seq_file *seq, void *);
41
static int vlandev_seq_show(struct seq_file *seq, void *v);
42
43
/*
44
* Global Data
45
*/
46
47
48
/*
49
* Names of the proc directory entries
50
*/
51
52
static const char name_root[] = "vlan";
53
static const char name_conf[] = "config";
54
55
/*
56
* Structures for interfacing with the /proc filesystem.
57
* VLAN creates its own directory /proc/net/vlan with the following
58
* entries:
59
* config device status/configuration
60
* <device> entry for each device
61
*/
62
63
/*
64
* Generic /proc/net/vlan/<file> file and inode operations
65
*/
66
67
static const struct seq_operations vlan_seq_ops = {
68
.start = vlan_seq_start,
69
.next = vlan_seq_next,
70
.stop = vlan_seq_stop,
71
.show = vlan_seq_show,
72
};
73
74
static int vlan_seq_open(struct inode *inode, struct file *file)
75
{
76
return seq_open_net(inode, file, &vlan_seq_ops,
77
sizeof(struct seq_net_private));
78
}
79
80
static const struct file_operations vlan_fops = {
81
.owner = THIS_MODULE,
82
.open = vlan_seq_open,
83
.read = seq_read,
84
.llseek = seq_lseek,
85
.release = seq_release_net,
86
};
87
88
/*
89
* /proc/net/vlan/<device> file and inode operations
90
*/
91
92
static int vlandev_seq_open(struct inode *inode, struct file *file)
93
{
94
return single_open(file, vlandev_seq_show, PDE(inode)->data);
95
}
96
97
static const struct file_operations vlandev_fops = {
98
.owner = THIS_MODULE,
99
.open = vlandev_seq_open,
100
.read = seq_read,
101
.llseek = seq_lseek,
102
.release = single_release,
103
};
104
105
/*
106
* Proc filesystem derectory entries.
107
*/
108
109
/* Strings */
110
static const char *const vlan_name_type_str[VLAN_NAME_TYPE_HIGHEST] = {
111
[VLAN_NAME_TYPE_RAW_PLUS_VID] = "VLAN_NAME_TYPE_RAW_PLUS_VID",
112
[VLAN_NAME_TYPE_PLUS_VID_NO_PAD] = "VLAN_NAME_TYPE_PLUS_VID_NO_PAD",
113
[VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD] = "VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD",
114
[VLAN_NAME_TYPE_PLUS_VID] = "VLAN_NAME_TYPE_PLUS_VID",
115
};
116
/*
117
* Interface functions
118
*/
119
120
/*
121
* Clean up /proc/net/vlan entries
122
*/
123
124
void vlan_proc_cleanup(struct net *net)
125
{
126
struct vlan_net *vn = net_generic(net, vlan_net_id);
127
128
if (vn->proc_vlan_conf)
129
remove_proc_entry(name_conf, vn->proc_vlan_dir);
130
131
if (vn->proc_vlan_dir)
132
proc_net_remove(net, name_root);
133
134
/* Dynamically added entries should be cleaned up as their vlan_device
135
* is removed, so we should not have to take care of it here...
136
*/
137
}
138
139
/*
140
* Create /proc/net/vlan entries
141
*/
142
143
int __net_init vlan_proc_init(struct net *net)
144
{
145
struct vlan_net *vn = net_generic(net, vlan_net_id);
146
147
vn->proc_vlan_dir = proc_net_mkdir(net, name_root, net->proc_net);
148
if (!vn->proc_vlan_dir)
149
goto err;
150
151
vn->proc_vlan_conf = proc_create(name_conf, S_IFREG|S_IRUSR|S_IWUSR,
152
vn->proc_vlan_dir, &vlan_fops);
153
if (!vn->proc_vlan_conf)
154
goto err;
155
return 0;
156
157
err:
158
pr_err("%s: can't create entry in proc filesystem!\n", __func__);
159
vlan_proc_cleanup(net);
160
return -ENOBUFS;
161
}
162
163
/*
164
* Add directory entry for VLAN device.
165
*/
166
167
int vlan_proc_add_dev(struct net_device *vlandev)
168
{
169
struct vlan_dev_info *dev_info = vlan_dev_info(vlandev);
170
struct vlan_net *vn = net_generic(dev_net(vlandev), vlan_net_id);
171
172
dev_info->dent =
173
proc_create_data(vlandev->name, S_IFREG|S_IRUSR|S_IWUSR,
174
vn->proc_vlan_dir, &vlandev_fops, vlandev);
175
if (!dev_info->dent)
176
return -ENOBUFS;
177
return 0;
178
}
179
180
/*
181
* Delete directory entry for VLAN device.
182
*/
183
int vlan_proc_rem_dev(struct net_device *vlandev)
184
{
185
struct vlan_net *vn = net_generic(dev_net(vlandev), vlan_net_id);
186
187
/** NOTE: This will consume the memory pointed to by dent, it seems. */
188
if (vlan_dev_info(vlandev)->dent) {
189
remove_proc_entry(vlan_dev_info(vlandev)->dent->name,
190
vn->proc_vlan_dir);
191
vlan_dev_info(vlandev)->dent = NULL;
192
}
193
return 0;
194
}
195
196
/****** Proc filesystem entry points ****************************************/
197
198
/*
199
* The following few functions build the content of /proc/net/vlan/config
200
*/
201
202
/* start read of /proc/net/vlan/config */
203
static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
204
__acquires(rcu)
205
{
206
struct net_device *dev;
207
struct net *net = seq_file_net(seq);
208
loff_t i = 1;
209
210
rcu_read_lock();
211
if (*pos == 0)
212
return SEQ_START_TOKEN;
213
214
for_each_netdev_rcu(net, dev) {
215
if (!is_vlan_dev(dev))
216
continue;
217
218
if (i++ == *pos)
219
return dev;
220
}
221
222
return NULL;
223
}
224
225
static void *vlan_seq_next(struct seq_file *seq, void *v, loff_t *pos)
226
{
227
struct net_device *dev;
228
struct net *net = seq_file_net(seq);
229
230
++*pos;
231
232
dev = (struct net_device *)v;
233
if (v == SEQ_START_TOKEN)
234
dev = net_device_entry(&net->dev_base_head);
235
236
for_each_netdev_continue_rcu(net, dev) {
237
if (!is_vlan_dev(dev))
238
continue;
239
240
return dev;
241
}
242
243
return NULL;
244
}
245
246
static void vlan_seq_stop(struct seq_file *seq, void *v)
247
__releases(rcu)
248
{
249
rcu_read_unlock();
250
}
251
252
static int vlan_seq_show(struct seq_file *seq, void *v)
253
{
254
struct net *net = seq_file_net(seq);
255
struct vlan_net *vn = net_generic(net, vlan_net_id);
256
257
if (v == SEQ_START_TOKEN) {
258
const char *nmtype = NULL;
259
260
seq_puts(seq, "VLAN Dev name | VLAN ID\n");
261
262
if (vn->name_type < ARRAY_SIZE(vlan_name_type_str))
263
nmtype = vlan_name_type_str[vn->name_type];
264
265
seq_printf(seq, "Name-Type: %s\n",
266
nmtype ? nmtype : "UNKNOWN");
267
} else {
268
const struct net_device *vlandev = v;
269
const struct vlan_dev_info *dev_info = vlan_dev_info(vlandev);
270
271
seq_printf(seq, "%-15s| %d | %s\n", vlandev->name,
272
dev_info->vlan_id, dev_info->real_dev->name);
273
}
274
return 0;
275
}
276
277
static int vlandev_seq_show(struct seq_file *seq, void *offset)
278
{
279
struct net_device *vlandev = (struct net_device *) seq->private;
280
const struct vlan_dev_info *dev_info = vlan_dev_info(vlandev);
281
struct rtnl_link_stats64 temp;
282
const struct rtnl_link_stats64 *stats;
283
static const char fmt64[] = "%30s %12llu\n";
284
int i;
285
286
if (!is_vlan_dev(vlandev))
287
return 0;
288
289
stats = dev_get_stats(vlandev, &temp);
290
seq_printf(seq,
291
"%s VID: %d REORDER_HDR: %i dev->priv_flags: %hx\n",
292
vlandev->name, dev_info->vlan_id,
293
(int)(dev_info->flags & 1), vlandev->priv_flags);
294
295
seq_printf(seq, fmt64, "total frames received", stats->rx_packets);
296
seq_printf(seq, fmt64, "total bytes received", stats->rx_bytes);
297
seq_printf(seq, fmt64, "Broadcast/Multicast Rcvd", stats->multicast);
298
seq_puts(seq, "\n");
299
seq_printf(seq, fmt64, "total frames transmitted", stats->tx_packets);
300
seq_printf(seq, fmt64, "total bytes transmitted", stats->tx_bytes);
301
seq_printf(seq, "Device: %s", dev_info->real_dev->name);
302
/* now show all PRIORITY mappings relating to this VLAN */
303
seq_printf(seq, "\nINGRESS priority mappings: "
304
"0:%u 1:%u 2:%u 3:%u 4:%u 5:%u 6:%u 7:%u\n",
305
dev_info->ingress_priority_map[0],
306
dev_info->ingress_priority_map[1],
307
dev_info->ingress_priority_map[2],
308
dev_info->ingress_priority_map[3],
309
dev_info->ingress_priority_map[4],
310
dev_info->ingress_priority_map[5],
311
dev_info->ingress_priority_map[6],
312
dev_info->ingress_priority_map[7]);
313
314
seq_printf(seq, " EGRESS priority mappings: ");
315
for (i = 0; i < 16; i++) {
316
const struct vlan_priority_tci_mapping *mp
317
= dev_info->egress_priority_map[i];
318
while (mp) {
319
seq_printf(seq, "%u:%hu ",
320
mp->priority, ((mp->vlan_qos >> 13) & 0x7));
321
mp = mp->next;
322
}
323
}
324
seq_puts(seq, "\n");
325
326
return 0;
327
}
328
329