OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [8021q/] [vlanproc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/******************************************************************************
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, <greearb@candelatech.com> coppied from wanproc.c
8
 *               by: Gene Kozin <genek@compuserve.com>
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/config.h>
21
#include <linux/stddef.h>       /* offsetof(), etc. */
22
#include <linux/errno.h>        /* return codes */
23
#include <linux/kernel.h>
24
#include <linux/slab.h>         /* kmalloc(), kfree() */
25
#include <linux/mm.h>           /* verify_area(), etc. */
26
#include <linux/string.h>       /* inline mem*, str* functions */
27
#include <linux/init.h>         /* __initfunc et al. */
28
#include <asm/segment.h>        /* kernel <-> user copy */
29
#include <asm/byteorder.h>      /* htons(), etc. */
30
#include <asm/uaccess.h>        /* copy_to_user */
31
#include <asm/io.h>
32
#include <linux/proc_fs.h>
33
#include <linux/fs.h>
34
#include <linux/netdevice.h>
35
#include <linux/if_vlan.h>
36
#include "vlanproc.h"
37
#include "vlan.h"
38
 
39
/****** Function Prototypes *************************************************/
40
 
41
#ifdef CONFIG_PROC_FS
42
 
43
/* Proc filesystem interface */
44
static ssize_t vlan_proc_read(struct file *file, char *buf, size_t count,
45
                              loff_t *ppos);
46
 
47
/* Methods for preparing data for reading proc entries */
48
 
49
static int vlan_config_get_info(char *buf, char **start, off_t offs, int len);
50
static int vlandev_get_info(char *buf, char **start, off_t offs, int len);
51
 
52
/* Miscellaneous */
53
 
54
/*
55
 *      Global Data
56
 */
57
 
58
/*
59
 *      Names of the proc directory entries
60
 */
61
 
62
static char name_root[]  = "vlan";
63
static char name_conf[]  = "config";
64
static char term_msg[]   = "***KERNEL:  Out of buffer space!***\n";
65
 
66
/*
67
 *      Structures for interfacing with the /proc filesystem.
68
 *      VLAN creates its own directory /proc/net/vlan with the folowing
69
 *      entries:
70
 *      config          device status/configuration
71
 *      <device>        entry for each  device
72
 */
73
 
74
/*
75
 *      Generic /proc/net/vlan/<file> file and inode operations
76
 */
77
 
78
static struct file_operations vlan_fops = {
79
        read:   vlan_proc_read,
80
        ioctl: NULL, /* vlan_proc_ioctl */
81
};
82
 
83
/*
84
 *      /proc/net/vlan/<device> file and inode operations
85
 */
86
 
87
static struct file_operations vlandev_fops = {
88
        read:   vlan_proc_read,
89
        ioctl:  NULL, /* vlan_proc_ioctl */
90
};
91
 
92
/*
93
 * Proc filesystem derectory entries.
94
 */
95
 
96
/*
97
 *      /proc/net/vlan
98
 */
99
 
100
static struct proc_dir_entry *proc_vlan_dir;
101
 
102
/*
103
 *      /proc/net/vlan/config
104
 */
105
 
106
static struct proc_dir_entry *proc_vlan_conf;
107
 
108
/* Strings */
109
static char conf_hdr[] = "VLAN Dev name  | VLAN ID\n";
110
 
111
/*
112
 *      Interface functions
113
 */
114
 
115
/*
116
 *      Clean up /proc/net/vlan entries
117
 */
118
 
119
void vlan_proc_cleanup(void)
120
{
121
        if (proc_vlan_conf)
122
                remove_proc_entry(name_conf, proc_vlan_dir);
123
 
124
        if (proc_vlan_dir)
125
                proc_net_remove(name_root);
126
 
127
        /* Dynamically added entries should be cleaned up as their vlan_device
128
         * is removed, so we should not have to take care of it here...
129
         */
130
}
131
 
132
/*
133
 *      Create /proc/net/vlan entries
134
 */
135
 
136
int __init vlan_proc_init(void)
137
{
138
        proc_vlan_dir = proc_mkdir(name_root, proc_net);
139
        if (proc_vlan_dir) {
140
                proc_vlan_conf = create_proc_entry(name_conf,
141
                                                   S_IFREG|S_IRUSR|S_IWUSR,
142
                                                   proc_vlan_dir);
143
                if (proc_vlan_conf) {
144
                        proc_vlan_conf->proc_fops = &vlan_fops;
145
                        proc_vlan_conf->get_info = vlan_config_get_info;
146
                        return 0;
147
                }
148
        }
149
        vlan_proc_cleanup();
150
        return -ENOBUFS;
151
}
152
 
153
/*
154
 *      Add directory entry for VLAN device.
155
 */
156
 
157
int vlan_proc_add_dev (struct net_device *vlandev)
158
{
159
        struct vlan_dev_info *dev_info = VLAN_DEV_INFO(vlandev);
160
 
161
        if (!(vlandev->priv_flags & IFF_802_1Q_VLAN)) {
162
                printk(KERN_ERR
163
                       "ERROR:  vlan_proc_add, device -:%s:- is NOT a VLAN\n",
164
                       vlandev->name);
165
                return -EINVAL;
166
        }
167
 
168
        dev_info->dent = create_proc_entry(vlandev->name,
169
                                           S_IFREG|S_IRUSR|S_IWUSR,
170
                                           proc_vlan_dir);
171
        if (!dev_info->dent)
172
                return -ENOBUFS;
173
 
174
        dev_info->dent->proc_fops = &vlandev_fops;
175
        dev_info->dent->get_info = &vlandev_get_info;
176
        dev_info->dent->data = vlandev;
177
 
178
#ifdef VLAN_DEBUG
179
        printk(KERN_ERR "vlan_proc_add, device -:%s:- being added.\n",
180
               vlandev->name);
181
#endif
182
        return 0;
183
}
184
 
185
/*
186
 *      Delete directory entry for VLAN device.
187
 */
188
int vlan_proc_rem_dev(struct net_device *vlandev)
189
{
190
        if (!vlandev) {
191
                printk(VLAN_ERR "%s: invalid argument: %p\n",
192
                        __FUNCTION__, vlandev);
193
                return -EINVAL;
194
        }
195
 
196
        if (!(vlandev->priv_flags & IFF_802_1Q_VLAN)) {
197
                printk(VLAN_DBG "%s: invalid argument, device: %s is not a VLAN device, priv_flags: 0x%4hX.\n",
198
                        __FUNCTION__, vlandev->name, vlandev->priv_flags);
199
                return -EINVAL;
200
        }
201
 
202
#ifdef VLAN_DEBUG
203
        printk(VLAN_DBG __FUNCTION__ ": dev: %p\n", vlandev);
204
#endif
205
 
206
        /** NOTE:  This will consume the memory pointed to by dent, it seems. */
207
        if (VLAN_DEV_INFO(vlandev)->dent) {
208
                remove_proc_entry(VLAN_DEV_INFO(vlandev)->dent->name, proc_vlan_dir);
209
                VLAN_DEV_INFO(vlandev)->dent = NULL;
210
        }
211
 
212
        return 0;
213
}
214
 
215
/****** Proc filesystem entry points ****************************************/
216
 
217
/*
218
 *      Read VLAN proc directory entry.
219
 *      This is universal routine for reading all entries in /proc/net/vlan
220
 *      directory.  Each directory entry contains a pointer to the 'method' for
221
 *      preparing data for that entry.
222
 *      o verify arguments
223
 *      o allocate kernel buffer
224
 *      o call get_info() to prepare data
225
 *      o copy data to user space
226
 *      o release kernel buffer
227
 *
228
 *      Return: number of bytes copied to user space (0, if no data)
229
 *              <0       error
230
 */
231
static ssize_t vlan_proc_read(struct file *file, char *buf,
232
                              size_t count, loff_t *ppos)
233
{
234
        struct inode *inode = file->f_dentry->d_inode;
235
        struct proc_dir_entry *dent;
236
        char *page;
237
        int pos, offs, len;
238
 
239
        if (count <= 0)
240
                return 0;
241
 
242
        dent = inode->u.generic_ip;
243
        if ((dent == NULL) || (dent->get_info == NULL))
244
                return 0;
245
 
246
        page = kmalloc(VLAN_PROC_BUFSZ, GFP_KERNEL);
247
        VLAN_MEM_DBG("page malloc, addr: %p  size: %i\n",
248
                     page, VLAN_PROC_BUFSZ);
249
 
250
        if (page == NULL)
251
                return -ENOBUFS;
252
 
253
        pos = dent->get_info(page, dent->data, 0, 0);
254
        offs = file->f_pos;
255
        if (offs < pos) {
256
                len = min_t(int, pos - offs, count);
257
                if (copy_to_user(buf, (page + offs), len)) {
258
                        kfree(page);
259
                        return -EFAULT;
260
                }
261
 
262
                file->f_pos += len;
263
        } else {
264
                len = 0;
265
        }
266
 
267
        kfree(page);
268
        VLAN_FMEM_DBG("page free, addr: %p\n", page);
269
        return len;
270
}
271
 
272
/*
273
 * The following few functions build the content of /proc/net/vlan/config
274
 */
275
 
276
static int vlan_proc_get_vlan_info(char* buf, unsigned int cnt)
277
{
278
        struct net_device *vlandev = NULL;
279
        struct vlan_group *grp = NULL;
280
        int h, i;
281
        char *nm_type = NULL;
282
        struct vlan_dev_info *dev_info = NULL;
283
 
284
#ifdef VLAN_DEBUG
285
        printk(VLAN_DBG __FUNCTION__ ": cnt == %i\n", cnt);
286
#endif
287
 
288
        if (vlan_name_type == VLAN_NAME_TYPE_RAW_PLUS_VID) {
289
                nm_type = "VLAN_NAME_TYPE_RAW_PLUS_VID";
290
        } else if (vlan_name_type == VLAN_NAME_TYPE_PLUS_VID_NO_PAD) {
291
                nm_type = "VLAN_NAME_TYPE_PLUS_VID_NO_PAD";
292
        } else if (vlan_name_type == VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD) {
293
                nm_type = "VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD";
294
        } else if (vlan_name_type == VLAN_NAME_TYPE_PLUS_VID) {
295
                nm_type = "VLAN_NAME_TYPE_PLUS_VID";
296
        } else {
297
                nm_type = "UNKNOWN";
298
        }
299
 
300
        cnt += sprintf(buf + cnt, "Name-Type: %s\n", nm_type);
301
 
302
        spin_lock_bh(&vlan_group_lock);
303
        for (h = 0; h < VLAN_GRP_HASH_SIZE; h++) {
304
                for (grp = vlan_group_hash[h]; grp != NULL; grp = grp->next) {
305
                        for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
306
                                vlandev = grp->vlan_devices[i];
307
                                if (!vlandev)
308
                                        continue;
309
 
310
                                if ((cnt + 100) > VLAN_PROC_BUFSZ) {
311
                                        if ((cnt+strlen(term_msg)) < VLAN_PROC_BUFSZ)
312
                                                cnt += sprintf(buf+cnt, "%s", term_msg);
313
 
314
                                        goto out;
315
                                }
316
 
317
                                dev_info = VLAN_DEV_INFO(vlandev);
318
                                cnt += sprintf(buf + cnt, "%-15s| %d  | %s\n",
319
                                               vlandev->name,
320
                                               dev_info->vlan_id,
321
                                               dev_info->real_dev->name);
322
                        }
323
                }
324
        }
325
out:
326
        spin_unlock_bh(&vlan_group_lock);
327
 
328
        return cnt;
329
}
330
 
331
/*
332
 *      Prepare data for reading 'Config' entry.
333
 *      Return length of data.
334
 */
335
 
336
static int vlan_config_get_info(char *buf, char **start,
337
                                off_t offs, int len)
338
{
339
        strcpy(buf, conf_hdr);
340
        return vlan_proc_get_vlan_info(buf, (unsigned int)(strlen(conf_hdr)));
341
}
342
 
343
/*
344
 *      Prepare data for reading <device> entry.
345
 *      Return length of data.
346
 *
347
 *      On entry, the 'start' argument will contain a pointer to VLAN device
348
 *      data space.
349
 */
350
 
351
static int vlandev_get_info(char *buf, char **start,
352
                            off_t offs, int len)
353
{
354
        struct net_device *vlandev = (void *) start;
355
        struct net_device_stats *stats = NULL;
356
        struct vlan_dev_info *dev_info = NULL;
357
        struct vlan_priority_tci_mapping *mp;
358
        int cnt = 0;
359
        int i;
360
 
361
        if ((vlandev == NULL) || (!(vlandev->priv_flags & IFF_802_1Q_VLAN)))
362
                return 0;
363
 
364
        dev_info = VLAN_DEV_INFO(vlandev);
365
 
366
        cnt += sprintf(buf + cnt, "%s  VID: %d   REORDER_HDR: %i  dev->priv_flags: %hx\n",
367
                       vlandev->name, dev_info->vlan_id,
368
                       (int)(dev_info->flags & 1), vlandev->priv_flags);
369
 
370
        stats = vlan_dev_get_stats(vlandev);
371
 
372
        cnt += sprintf(buf + cnt, "%30s: %12lu\n",
373
                       "total frames received", stats->rx_packets);
374
 
375
        cnt += sprintf(buf + cnt, "%30s: %12lu\n",
376
                       "total bytes received", stats->rx_bytes);
377
 
378
        cnt += sprintf(buf + cnt, "%30s: %12lu\n",
379
                       "Broadcast/Multicast Rcvd", stats->multicast);
380
 
381
        cnt += sprintf(buf + cnt, "\n%30s: %12lu\n",
382
                       "total frames transmitted", stats->tx_packets);
383
 
384
        cnt += sprintf(buf + cnt, "%30s: %12lu\n",
385
                       "total bytes transmitted", stats->tx_bytes);
386
 
387
        cnt += sprintf(buf + cnt, "%30s: %12lu\n",
388
                       "total headroom inc", dev_info->cnt_inc_headroom_on_tx);
389
 
390
        cnt += sprintf(buf + cnt, "%30s: %12lu\n",
391
                       "total encap on xmit", dev_info->cnt_encap_on_xmit);
392
 
393
        cnt += sprintf(buf + cnt, "Device: %s", dev_info->real_dev->name);
394
 
395
        /* now show all PRIORITY mappings relating to this VLAN */
396
        cnt += sprintf(buf + cnt, "\nINGRESS priority mappings: 0:%lu  1:%lu  2:%lu  3:%lu  4:%lu  5:%lu  6:%lu 7:%lu\n",
397
                       dev_info->ingress_priority_map[0],
398
                       dev_info->ingress_priority_map[1],
399
                       dev_info->ingress_priority_map[2],
400
                       dev_info->ingress_priority_map[3],
401
                       dev_info->ingress_priority_map[4],
402
                       dev_info->ingress_priority_map[5],
403
                       dev_info->ingress_priority_map[6],
404
                       dev_info->ingress_priority_map[7]);
405
 
406
        if ((cnt + 100) > VLAN_PROC_BUFSZ) {
407
                if ((cnt + strlen(term_msg)) >= VLAN_PROC_BUFSZ) {
408
                        /* should never get here */
409
                        return cnt;
410
                } else {
411
                        cnt += sprintf(buf + cnt, "%s", term_msg);
412
                        return cnt;
413
                }
414
        }
415
 
416
        cnt += sprintf(buf + cnt, "EGRESSS priority Mappings: ");
417
 
418
        for (i = 0; i < 16; i++) {
419
                mp = dev_info->egress_priority_map[i];
420
                while (mp) {
421
                        cnt += sprintf(buf + cnt, "%lu:%hu ",
422
                                       mp->priority, ((mp->vlan_qos >> 13) & 0x7));
423
 
424
                        if ((cnt + 100) > VLAN_PROC_BUFSZ) {
425
                                if ((cnt + strlen(term_msg)) >= VLAN_PROC_BUFSZ) {
426
                                        /* should never get here */
427
                                        return cnt;
428
                                } else {
429
                                        cnt += sprintf(buf + cnt, "%s", term_msg);
430
                                        return cnt;
431
                                }
432
                        }
433
                        mp = mp->next;
434
                }
435
        }
436
 
437
        cnt += sprintf(buf + cnt, "\n");
438
 
439
        return cnt;
440
}
441
 
442
#else /* No CONFIG_PROC_FS */
443
 
444
/*
445
 *      No /proc - output stubs
446
 */
447
 
448
int __init vlan_proc_init (void)
449
{
450
        return 0;
451
}
452
 
453
void vlan_proc_cleanup(void)
454
{
455
        return;
456
}
457
 
458
 
459
int vlan_proc_add_dev(struct net_device *vlandev)
460
{
461
        return 0;
462
}
463
 
464
int vlan_proc_rem_dev(struct net_device *vlandev)
465
{
466
        return 0;
467
}
468
 
469
#endif /* No CONFIG_PROC_FS */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.