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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [net/] [8021q/] [vlan.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * INET         802.1Q VLAN
3
 *              Ethernet-type device handling.
4
 *
5
 * Authors:     Ben Greear <greearb@candelatech.com>
6
 *              Please send support related email to: vlan@scry.wanfear.com
7
 *              VLAN Home Page: http://www.candelatech.com/~greear/vlan.html
8
 *
9
 * Fixes:
10
 *              Fix for packet capture - Nick Eggleston <nick@dccinc.com>;
11
 *              Add HW acceleration hooks - David S. Miller <davem@redhat.com>;
12
 *              Correct all the locking - David S. Miller <davem@redhat.com>;
13
 *              Use hash table for VLAN groups - David S. Miller <davem@redhat.com>
14
 *
15
 *              This program is free software; you can redistribute it and/or
16
 *              modify it under the terms of the GNU General Public License
17
 *              as published by the Free Software Foundation; either version
18
 *              2 of the License, or (at your option) any later version.
19
 */
20
 
21
#include <asm/uaccess.h> /* for copy_from_user */
22
#include <linux/capability.h>
23
#include <linux/module.h>
24
#include <linux/netdevice.h>
25
#include <linux/skbuff.h>
26
#include <net/datalink.h>
27
#include <linux/mm.h>
28
#include <linux/in.h>
29
#include <linux/init.h>
30
#include <net/p8022.h>
31
#include <net/arp.h>
32
#include <linux/rtnetlink.h>
33
#include <linux/notifier.h>
34
#include <net/net_namespace.h>
35
 
36
#include <linux/if_vlan.h>
37
#include "vlan.h"
38
#include "vlanproc.h"
39
 
40
#define DRV_VERSION "1.8"
41
 
42
/* Global VLAN variables */
43
 
44
/* Our listing of VLAN group(s) */
45
static struct hlist_head vlan_group_hash[VLAN_GRP_HASH_SIZE];
46
#define vlan_grp_hashfn(IDX)    ((((IDX) >> VLAN_GRP_HASH_SHIFT) ^ (IDX)) & VLAN_GRP_HASH_MASK)
47
 
48
static char vlan_fullname[] = "802.1Q VLAN Support";
49
static char vlan_version[] = DRV_VERSION;
50
static char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>";
51
static char vlan_buggyright[] = "David S. Miller <davem@redhat.com>";
52
 
53
static int vlan_device_event(struct notifier_block *, unsigned long, void *);
54
static int vlan_ioctl_handler(struct net *net, void __user *);
55
static int unregister_vlan_dev(struct net_device *, unsigned short );
56
 
57
static struct notifier_block vlan_notifier_block = {
58
        .notifier_call = vlan_device_event,
59
};
60
 
61
/* These may be changed at run-time through IOCTLs */
62
 
63
/* Determines interface naming scheme. */
64
unsigned short vlan_name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD;
65
 
66
static struct packet_type vlan_packet_type = {
67
        .type = __constant_htons(ETH_P_8021Q),
68
        .func = vlan_skb_recv, /* VLAN receive method */
69
};
70
 
71
/* End of global variables definitions. */
72
 
73
/*
74
 * Function vlan_proto_init (pro)
75
 *
76
 *    Initialize VLAN protocol layer,
77
 *
78
 */
79
static int __init vlan_proto_init(void)
80
{
81
        int err;
82
 
83
        printk(VLAN_INF "%s v%s %s\n",
84
               vlan_fullname, vlan_version, vlan_copyright);
85
        printk(VLAN_INF "All bugs added by %s\n",
86
               vlan_buggyright);
87
 
88
        /* proc file system initialization */
89
        err = vlan_proc_init();
90
        if (err < 0) {
91
                printk(KERN_ERR
92
                       "%s %s: can't create entry in proc filesystem!\n",
93
                       __FUNCTION__, VLAN_NAME);
94
                return err;
95
        }
96
 
97
        dev_add_pack(&vlan_packet_type);
98
 
99
        /* Register us to receive netdevice events */
100
        err = register_netdevice_notifier(&vlan_notifier_block);
101
        if (err < 0)
102
                goto err1;
103
 
104
        err = vlan_netlink_init();
105
        if (err < 0)
106
                goto err2;
107
 
108
        vlan_ioctl_set(vlan_ioctl_handler);
109
        return 0;
110
 
111
err2:
112
        unregister_netdevice_notifier(&vlan_notifier_block);
113
err1:
114
        vlan_proc_cleanup();
115
        dev_remove_pack(&vlan_packet_type);
116
        return err;
117
}
118
 
119
/*
120
 *     Module 'remove' entry point.
121
 *     o delete /proc/net/router directory and static entries.
122
 */
123
static void __exit vlan_cleanup_module(void)
124
{
125
        int i;
126
 
127
        vlan_ioctl_set(NULL);
128
        vlan_netlink_fini();
129
 
130
        /* Un-register us from receiving netdevice events */
131
        unregister_netdevice_notifier(&vlan_notifier_block);
132
 
133
        dev_remove_pack(&vlan_packet_type);
134
 
135
        /* This table must be empty if there are no module
136
         * references left.
137
         */
138
        for (i = 0; i < VLAN_GRP_HASH_SIZE; i++) {
139
                BUG_ON(!hlist_empty(&vlan_group_hash[i]));
140
        }
141
        vlan_proc_cleanup();
142
 
143
        synchronize_net();
144
}
145
 
146
module_init(vlan_proto_init);
147
module_exit(vlan_cleanup_module);
148
 
149
/* Must be invoked with RCU read lock (no preempt) */
150
static struct vlan_group *__vlan_find_group(int real_dev_ifindex)
151
{
152
        struct vlan_group *grp;
153
        struct hlist_node *n;
154
        int hash = vlan_grp_hashfn(real_dev_ifindex);
155
 
156
        hlist_for_each_entry_rcu(grp, n, &vlan_group_hash[hash], hlist) {
157
                if (grp->real_dev_ifindex == real_dev_ifindex)
158
                        return grp;
159
        }
160
 
161
        return NULL;
162
}
163
 
164
/*  Find the protocol handler.  Assumes VID < VLAN_VID_MASK.
165
 *
166
 * Must be invoked with RCU read lock (no preempt)
167
 */
168
struct net_device *__find_vlan_dev(struct net_device *real_dev,
169
                                   unsigned short VID)
170
{
171
        struct vlan_group *grp = __vlan_find_group(real_dev->ifindex);
172
 
173
        if (grp)
174
                return vlan_group_get_device(grp, VID);
175
 
176
        return NULL;
177
}
178
 
179
static void vlan_group_free(struct vlan_group *grp)
180
{
181
        int i;
182
 
183
        for (i=0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++)
184
                kfree(grp->vlan_devices_arrays[i]);
185
        kfree(grp);
186
}
187
 
188
static struct vlan_group *vlan_group_alloc(int ifindex)
189
{
190
        struct vlan_group *grp;
191
        unsigned int size;
192
        unsigned int i;
193
 
194
        grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
195
        if (!grp)
196
                return NULL;
197
 
198
        size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN;
199
 
200
        for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
201
                grp->vlan_devices_arrays[i] = kzalloc(size, GFP_KERNEL);
202
                if (!grp->vlan_devices_arrays[i])
203
                        goto err;
204
        }
205
 
206
        grp->real_dev_ifindex = ifindex;
207
        hlist_add_head_rcu(&grp->hlist,
208
                           &vlan_group_hash[vlan_grp_hashfn(ifindex)]);
209
        return grp;
210
 
211
err:
212
        vlan_group_free(grp);
213
        return NULL;
214
}
215
 
216
static void vlan_rcu_free(struct rcu_head *rcu)
217
{
218
        vlan_group_free(container_of(rcu, struct vlan_group, rcu));
219
}
220
 
221
 
222
/* This returns 0 if everything went fine.
223
 * It will return 1 if the group was killed as a result.
224
 * A negative return indicates failure.
225
 *
226
 * The RTNL lock must be held.
227
 */
228
static int unregister_vlan_dev(struct net_device *real_dev,
229
                               unsigned short vlan_id)
230
{
231
        struct net_device *dev = NULL;
232
        int real_dev_ifindex = real_dev->ifindex;
233
        struct vlan_group *grp;
234
        int i, ret;
235
 
236
#ifdef VLAN_DEBUG
237
        printk(VLAN_DBG "%s: VID: %i\n", __FUNCTION__, vlan_id);
238
#endif
239
 
240
        /* sanity check */
241
        if (vlan_id >= VLAN_VID_MASK)
242
                return -EINVAL;
243
 
244
        ASSERT_RTNL();
245
        grp = __vlan_find_group(real_dev_ifindex);
246
 
247
        ret = 0;
248
 
249
        if (grp) {
250
                dev = vlan_group_get_device(grp, vlan_id);
251
                if (dev) {
252
                        /* Remove proc entry */
253
                        vlan_proc_rem_dev(dev);
254
 
255
                        /* Take it out of our own structures, but be sure to
256
                         * interlock with HW accelerating devices or SW vlan
257
                         * input packet processing.
258
                         */
259
                        if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
260
                                real_dev->vlan_rx_kill_vid(real_dev, vlan_id);
261
 
262
                        vlan_group_set_device(grp, vlan_id, NULL);
263
                        synchronize_net();
264
 
265
 
266
                        /* Caller unregisters (and if necessary, puts)
267
                         * VLAN device, but we get rid of the reference to
268
                         * real_dev here.
269
                         */
270
                        dev_put(real_dev);
271
 
272
                        /* If the group is now empty, kill off the
273
                         * group.
274
                         */
275
                        for (i = 0; i < VLAN_VID_MASK; i++)
276
                                if (vlan_group_get_device(grp, i))
277
                                        break;
278
 
279
                        if (i == VLAN_VID_MASK) {
280
                                if (real_dev->features & NETIF_F_HW_VLAN_RX)
281
                                        real_dev->vlan_rx_register(real_dev, NULL);
282
 
283
                                hlist_del_rcu(&grp->hlist);
284
 
285
                                /* Free the group, after all cpu's are done. */
286
                                call_rcu(&grp->rcu, vlan_rcu_free);
287
 
288
                                grp = NULL;
289
                                ret = 1;
290
                        }
291
                }
292
        }
293
 
294
        return ret;
295
}
296
 
297
int unregister_vlan_device(struct net_device *dev)
298
{
299
        int ret;
300
 
301
        ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
302
                                  VLAN_DEV_INFO(dev)->vlan_id);
303
        unregister_netdevice(dev);
304
 
305
        if (ret == 1)
306
                ret = 0;
307
        return ret;
308
}
309
 
310
/*
311
 * vlan network devices have devices nesting below it, and are a special
312
 * "super class" of normal network devices; split their locks off into a
313
 * separate class since they always nest.
314
 */
315
static struct lock_class_key vlan_netdev_xmit_lock_key;
316
 
317
static const struct header_ops vlan_header_ops = {
318
        .create  = vlan_dev_hard_header,
319
        .rebuild = vlan_dev_rebuild_header,
320
        .parse   = eth_header_parse,
321
};
322
 
323
static int vlan_dev_init(struct net_device *dev)
324
{
325
        struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
326
        int subclass = 0;
327
 
328
        /* IFF_BROADCAST|IFF_MULTICAST; ??? */
329
        dev->flags  = real_dev->flags & ~IFF_UP;
330
        dev->iflink = real_dev->ifindex;
331
        dev->state  = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
332
                                          (1<<__LINK_STATE_DORMANT))) |
333
                      (1<<__LINK_STATE_PRESENT);
334
 
335
        /* ipv6 shared card related stuff */
336
        dev->dev_id = real_dev->dev_id;
337
 
338
        if (is_zero_ether_addr(dev->dev_addr))
339
                memcpy(dev->dev_addr, real_dev->dev_addr, dev->addr_len);
340
        if (is_zero_ether_addr(dev->broadcast))
341
                memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len);
342
 
343
        if (real_dev->features & NETIF_F_HW_VLAN_TX) {
344
                dev->header_ops      = real_dev->header_ops;
345
                dev->hard_header_len = real_dev->hard_header_len;
346
                dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit;
347
        } else {
348
                dev->header_ops      = &vlan_header_ops;
349
                dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
350
                dev->hard_start_xmit = vlan_dev_hard_start_xmit;
351
        }
352
 
353
        if (real_dev->priv_flags & IFF_802_1Q_VLAN)
354
                subclass = 1;
355
 
356
        lockdep_set_class_and_subclass(&dev->_xmit_lock,
357
                                &vlan_netdev_xmit_lock_key, subclass);
358
        return 0;
359
}
360
 
361
void vlan_setup(struct net_device *new_dev)
362
{
363
        ether_setup(new_dev);
364
 
365
        /* new_dev->ifindex = 0;  it will be set when added to
366
         * the global list.
367
         * iflink is set as well.
368
         */
369
        new_dev->get_stats = vlan_dev_get_stats;
370
 
371
        /* Make this thing known as a VLAN device */
372
        new_dev->priv_flags |= IFF_802_1Q_VLAN;
373
 
374
        /* Set us up to have no queue, as the underlying Hardware device
375
         * can do all the queueing we could want.
376
         */
377
        new_dev->tx_queue_len = 0;
378
 
379
        /* set up method calls */
380
        new_dev->change_mtu = vlan_dev_change_mtu;
381
        new_dev->init = vlan_dev_init;
382
        new_dev->open = vlan_dev_open;
383
        new_dev->stop = vlan_dev_stop;
384
        new_dev->set_mac_address = vlan_set_mac_address;
385
        new_dev->set_multicast_list = vlan_dev_set_multicast_list;
386
        new_dev->change_rx_flags = vlan_change_rx_flags;
387
        new_dev->destructor = free_netdev;
388
        new_dev->do_ioctl = vlan_dev_ioctl;
389
 
390
        memset(new_dev->broadcast, 0, ETH_ALEN);
391
}
392
 
393
static void vlan_transfer_operstate(const struct net_device *dev, struct net_device *vlandev)
394
{
395
        /* Have to respect userspace enforced dormant state
396
         * of real device, also must allow supplicant running
397
         * on VLAN device
398
         */
399
        if (dev->operstate == IF_OPER_DORMANT)
400
                netif_dormant_on(vlandev);
401
        else
402
                netif_dormant_off(vlandev);
403
 
404
        if (netif_carrier_ok(dev)) {
405
                if (!netif_carrier_ok(vlandev))
406
                        netif_carrier_on(vlandev);
407
        } else {
408
                if (netif_carrier_ok(vlandev))
409
                        netif_carrier_off(vlandev);
410
        }
411
}
412
 
413
int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id)
414
{
415
        if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
416
                printk(VLAN_DBG "%s: VLANs not supported on %s.\n",
417
                        __FUNCTION__, real_dev->name);
418
                return -EOPNOTSUPP;
419
        }
420
 
421
        if ((real_dev->features & NETIF_F_HW_VLAN_RX) &&
422
            !real_dev->vlan_rx_register) {
423
                printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
424
                        __FUNCTION__, real_dev->name);
425
                return -EOPNOTSUPP;
426
        }
427
 
428
        if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
429
            (!real_dev->vlan_rx_add_vid || !real_dev->vlan_rx_kill_vid)) {
430
                printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
431
                        __FUNCTION__, real_dev->name);
432
                return -EOPNOTSUPP;
433
        }
434
 
435
        /* The real device must be up and operating in order to
436
         * assosciate a VLAN device with it.
437
         */
438
        if (!(real_dev->flags & IFF_UP))
439
                return -ENETDOWN;
440
 
441
        if (__find_vlan_dev(real_dev, vlan_id) != NULL) {
442
                /* was already registered. */
443
                printk(VLAN_DBG "%s: ALREADY had VLAN registered\n", __FUNCTION__);
444
                return -EEXIST;
445
        }
446
 
447
        return 0;
448
}
449
 
450
int register_vlan_dev(struct net_device *dev)
451
{
452
        struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
453
        struct net_device *real_dev = vlan->real_dev;
454
        unsigned short vlan_id = vlan->vlan_id;
455
        struct vlan_group *grp, *ngrp = NULL;
456
        int err;
457
 
458
        grp = __vlan_find_group(real_dev->ifindex);
459
        if (!grp) {
460
                ngrp = grp = vlan_group_alloc(real_dev->ifindex);
461
                if (!grp)
462
                        return -ENOBUFS;
463
        }
464
 
465
        err = register_netdevice(dev);
466
        if (err < 0)
467
                goto out_free_group;
468
 
469
        /* Account for reference in struct vlan_dev_info */
470
        dev_hold(real_dev);
471
 
472
        vlan_transfer_operstate(real_dev, dev);
473
        linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */
474
 
475
        /* So, got the sucker initialized, now lets place
476
         * it into our local structure.
477
         */
478
        vlan_group_set_device(grp, vlan_id, dev);
479
        if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX)
480
                real_dev->vlan_rx_register(real_dev, ngrp);
481
        if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
482
                real_dev->vlan_rx_add_vid(real_dev, vlan_id);
483
 
484
        if (vlan_proc_add_dev(dev) < 0)
485
                printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n",
486
                       dev->name);
487
        return 0;
488
 
489
out_free_group:
490
        if (ngrp)
491
                vlan_group_free(ngrp);
492
        return err;
493
}
494
 
495
/*  Attach a VLAN device to a mac address (ie Ethernet Card).
496
 *  Returns 0 if the device was created or a negative error code otherwise.
497
 */
498
static int register_vlan_device(struct net_device *real_dev,
499
                                unsigned short VLAN_ID)
500
{
501
        struct net_device *new_dev;
502
        char name[IFNAMSIZ];
503
        int err;
504
 
505
#ifdef VLAN_DEBUG
506
        printk(VLAN_DBG "%s: if_name -:%s:-     vid: %i\n",
507
                __FUNCTION__, eth_IF_name, VLAN_ID);
508
#endif
509
 
510
        if (VLAN_ID >= VLAN_VID_MASK)
511
                return -ERANGE;
512
 
513
        err = vlan_check_real_dev(real_dev, VLAN_ID);
514
        if (err < 0)
515
                return err;
516
 
517
        /* Gotta set up the fields for the device. */
518
#ifdef VLAN_DEBUG
519
        printk(VLAN_DBG "About to allocate name, vlan_name_type: %i\n",
520
               vlan_name_type);
521
#endif
522
        switch (vlan_name_type) {
523
        case VLAN_NAME_TYPE_RAW_PLUS_VID:
524
                /* name will look like:  eth1.0005 */
525
                snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, VLAN_ID);
526
                break;
527
        case VLAN_NAME_TYPE_PLUS_VID_NO_PAD:
528
                /* Put our vlan.VID in the name.
529
                 * Name will look like:  vlan5
530
                 */
531
                snprintf(name, IFNAMSIZ, "vlan%i", VLAN_ID);
532
                break;
533
        case VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD:
534
                /* Put our vlan.VID in the name.
535
                 * Name will look like:  eth0.5
536
                 */
537
                snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, VLAN_ID);
538
                break;
539
        case VLAN_NAME_TYPE_PLUS_VID:
540
                /* Put our vlan.VID in the name.
541
                 * Name will look like:  vlan0005
542
                 */
543
        default:
544
                snprintf(name, IFNAMSIZ, "vlan%.4i", VLAN_ID);
545
        }
546
 
547
        new_dev = alloc_netdev(sizeof(struct vlan_dev_info), name,
548
                               vlan_setup);
549
 
550
        if (new_dev == NULL)
551
                return -ENOBUFS;
552
 
553
        /* need 4 bytes for extra VLAN header info,
554
         * hope the underlying device can handle it.
555
         */
556
        new_dev->mtu = real_dev->mtu;
557
 
558
#ifdef VLAN_DEBUG
559
        printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name);
560
        VLAN_MEM_DBG("new_dev->priv malloc, addr: %p  size: %i\n",
561
                     new_dev->priv,
562
                     sizeof(struct vlan_dev_info));
563
#endif
564
 
565
        VLAN_DEV_INFO(new_dev)->vlan_id = VLAN_ID; /* 1 through VLAN_VID_MASK */
566
        VLAN_DEV_INFO(new_dev)->real_dev = real_dev;
567
        VLAN_DEV_INFO(new_dev)->dent = NULL;
568
        VLAN_DEV_INFO(new_dev)->flags = VLAN_FLAG_REORDER_HDR;
569
 
570
        new_dev->rtnl_link_ops = &vlan_link_ops;
571
        err = register_vlan_dev(new_dev);
572
        if (err < 0)
573
                goto out_free_newdev;
574
 
575
#ifdef VLAN_DEBUG
576
        printk(VLAN_DBG "Allocated new device successfully, returning.\n");
577
#endif
578
        return 0;
579
 
580
out_free_newdev:
581
        free_netdev(new_dev);
582
        return err;
583
}
584
 
585
static void vlan_sync_address(struct net_device *dev,
586
                              struct net_device *vlandev)
587
{
588
        struct vlan_dev_info *vlan = VLAN_DEV_INFO(vlandev);
589
 
590
        /* May be called without an actual change */
591
        if (!compare_ether_addr(vlan->real_dev_addr, dev->dev_addr))
592
                return;
593
 
594
        /* vlan address was different from the old address and is equal to
595
         * the new address */
596
        if (compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) &&
597
            !compare_ether_addr(vlandev->dev_addr, dev->dev_addr))
598
                dev_unicast_delete(dev, vlandev->dev_addr, ETH_ALEN);
599
 
600
        /* vlan address was equal to the old address and is different from
601
         * the new address */
602
        if (!compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) &&
603
            compare_ether_addr(vlandev->dev_addr, dev->dev_addr))
604
                dev_unicast_add(dev, vlandev->dev_addr, ETH_ALEN);
605
 
606
        memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN);
607
}
608
 
609
static int vlan_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
610
{
611
        struct net_device *dev = ptr;
612
        struct vlan_group *grp = __vlan_find_group(dev->ifindex);
613
        int i, flgs;
614
        struct net_device *vlandev;
615
 
616
        if (dev->nd_net != &init_net)
617
                return NOTIFY_DONE;
618
 
619
        if (!grp)
620
                goto out;
621
 
622
        /* It is OK that we do not hold the group lock right now,
623
         * as we run under the RTNL lock.
624
         */
625
 
626
        switch (event) {
627
        case NETDEV_CHANGE:
628
                /* Propagate real device state to vlan devices */
629
                for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
630
                        vlandev = vlan_group_get_device(grp, i);
631
                        if (!vlandev)
632
                                continue;
633
 
634
                        vlan_transfer_operstate(dev, vlandev);
635
                }
636
                break;
637
 
638
        case NETDEV_CHANGEADDR:
639
                /* Adjust unicast filters on underlying device */
640
                for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
641
                        vlandev = vlan_group_get_device(grp, i);
642
                        if (!vlandev)
643
                                continue;
644
 
645
                        flgs = vlandev->flags;
646
                        if (!(flgs & IFF_UP))
647
                                continue;
648
 
649
                        vlan_sync_address(dev, vlandev);
650
                }
651
                break;
652
 
653
        case NETDEV_DOWN:
654
                /* Put all VLANs for this dev in the down state too.  */
655
                for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
656
                        vlandev = vlan_group_get_device(grp, i);
657
                        if (!vlandev)
658
                                continue;
659
 
660
                        flgs = vlandev->flags;
661
                        if (!(flgs & IFF_UP))
662
                                continue;
663
 
664
                        dev_change_flags(vlandev, flgs & ~IFF_UP);
665
                }
666
                break;
667
 
668
        case NETDEV_UP:
669
                /* Put all VLANs for this dev in the up state too.  */
670
                for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
671
                        vlandev = vlan_group_get_device(grp, i);
672
                        if (!vlandev)
673
                                continue;
674
 
675
                        flgs = vlandev->flags;
676
                        if (flgs & IFF_UP)
677
                                continue;
678
 
679
                        dev_change_flags(vlandev, flgs | IFF_UP);
680
                }
681
                break;
682
 
683
        case NETDEV_UNREGISTER:
684
                /* Delete all VLANs for this dev. */
685
                for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
686
                        int ret;
687
 
688
                        vlandev = vlan_group_get_device(grp, i);
689
                        if (!vlandev)
690
                                continue;
691
 
692
                        ret = unregister_vlan_dev(dev,
693
                                                  VLAN_DEV_INFO(vlandev)->vlan_id);
694
 
695
                        unregister_netdevice(vlandev);
696
 
697
                        /* Group was destroyed? */
698
                        if (ret == 1)
699
                                break;
700
                }
701
                break;
702
        }
703
 
704
out:
705
        return NOTIFY_DONE;
706
}
707
 
708
/*
709
 *      VLAN IOCTL handler.
710
 *      o execute requested action or pass command to the device driver
711
 *   arg is really a struct vlan_ioctl_args __user *.
712
 */
713
static int vlan_ioctl_handler(struct net *net, void __user *arg)
714
{
715
        int err;
716
        unsigned short vid = 0;
717
        struct vlan_ioctl_args args;
718
        struct net_device *dev = NULL;
719
 
720
        if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args)))
721
                return -EFAULT;
722
 
723
        /* Null terminate this sucker, just in case. */
724
        args.device1[23] = 0;
725
        args.u.device2[23] = 0;
726
 
727
#ifdef VLAN_DEBUG
728
        printk(VLAN_DBG "%s: args.cmd: %x\n", __FUNCTION__, args.cmd);
729
#endif
730
 
731
        rtnl_lock();
732
 
733
        switch (args.cmd) {
734
        case SET_VLAN_INGRESS_PRIORITY_CMD:
735
        case SET_VLAN_EGRESS_PRIORITY_CMD:
736
        case SET_VLAN_FLAG_CMD:
737
        case ADD_VLAN_CMD:
738
        case DEL_VLAN_CMD:
739
        case GET_VLAN_REALDEV_NAME_CMD:
740
        case GET_VLAN_VID_CMD:
741
                err = -ENODEV;
742
                dev = __dev_get_by_name(&init_net, args.device1);
743
                if (!dev)
744
                        goto out;
745
 
746
                err = -EINVAL;
747
                if (args.cmd != ADD_VLAN_CMD &&
748
                    !(dev->priv_flags & IFF_802_1Q_VLAN))
749
                        goto out;
750
        }
751
 
752
        switch (args.cmd) {
753
        case SET_VLAN_INGRESS_PRIORITY_CMD:
754
                err = -EPERM;
755
                if (!capable(CAP_NET_ADMIN))
756
                        break;
757
                vlan_dev_set_ingress_priority(dev,
758
                                              args.u.skb_priority,
759
                                              args.vlan_qos);
760
                err = 0;
761
                break;
762
 
763
        case SET_VLAN_EGRESS_PRIORITY_CMD:
764
                err = -EPERM;
765
                if (!capable(CAP_NET_ADMIN))
766
                        break;
767
                err = vlan_dev_set_egress_priority(dev,
768
                                                   args.u.skb_priority,
769
                                                   args.vlan_qos);
770
                break;
771
 
772
        case SET_VLAN_FLAG_CMD:
773
                err = -EPERM;
774
                if (!capable(CAP_NET_ADMIN))
775
                        break;
776
                err = vlan_dev_set_vlan_flag(dev,
777
                                             args.u.flag,
778
                                             args.vlan_qos);
779
                break;
780
 
781
        case SET_VLAN_NAME_TYPE_CMD:
782
                err = -EPERM;
783
                if (!capable(CAP_NET_ADMIN))
784
                        break;
785
                if ((args.u.name_type >= 0) &&
786
                    (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
787
                        vlan_name_type = args.u.name_type;
788
                        err = 0;
789
                } else {
790
                        err = -EINVAL;
791
                }
792
                break;
793
 
794
        case ADD_VLAN_CMD:
795
                err = -EPERM;
796
                if (!capable(CAP_NET_ADMIN))
797
                        break;
798
                err = register_vlan_device(dev, args.u.VID);
799
                break;
800
 
801
        case DEL_VLAN_CMD:
802
                err = -EPERM;
803
                if (!capable(CAP_NET_ADMIN))
804
                        break;
805
                err = unregister_vlan_device(dev);
806
                break;
807
 
808
        case GET_VLAN_INGRESS_PRIORITY_CMD:
809
                /* TODO:  Implement
810
                   err = vlan_dev_get_ingress_priority(args);
811
                   if (copy_to_user((void*)arg, &args,
812
                        sizeof(struct vlan_ioctl_args))) {
813
                        err = -EFAULT;
814
                   }
815
                */
816
                err = -EINVAL;
817
                break;
818
        case GET_VLAN_EGRESS_PRIORITY_CMD:
819
                /* TODO:  Implement
820
                   err = vlan_dev_get_egress_priority(args.device1, &(args.args);
821
                   if (copy_to_user((void*)arg, &args,
822
                        sizeof(struct vlan_ioctl_args))) {
823
                        err = -EFAULT;
824
                   }
825
                */
826
                err = -EINVAL;
827
                break;
828
        case GET_VLAN_REALDEV_NAME_CMD:
829
                err = 0;
830
                vlan_dev_get_realdev_name(dev, args.u.device2);
831
                if (copy_to_user(arg, &args,
832
                                 sizeof(struct vlan_ioctl_args))) {
833
                        err = -EFAULT;
834
                }
835
                break;
836
 
837
        case GET_VLAN_VID_CMD:
838
                err = 0;
839
                vlan_dev_get_vid(dev, &vid);
840
                args.u.VID = vid;
841
                if (copy_to_user(arg, &args,
842
                                 sizeof(struct vlan_ioctl_args))) {
843
                      err = -EFAULT;
844
                }
845
                break;
846
 
847
        default:
848
                /* pass on to underlying device instead?? */
849
                printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n",
850
                        __FUNCTION__, args.cmd);
851
                err = -EINVAL;
852
                break;
853
        }
854
out:
855
        rtnl_unlock();
856
        return err;
857
}
858
 
859
MODULE_LICENSE("GPL");
860
MODULE_VERSION(DRV_VERSION);

powered by: WebSVN 2.1.0

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