macvlan: cleanup rx statistics
[deliverable/linux.git] / drivers / net / macvlan.c
CommitLineData
b863ceb7
PM
1/*
2 * Copyright (c) 2007 Patrick McHardy <kaber@trash.net>
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 as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
8 *
9 * The code this is based on carried the following copyright notice:
10 * ---
11 * (C) Copyright 2001-2006
12 * Alex Zeffertt, Cambridge Broadband Ltd, ajz@cambridgebroadband.com
13 * Re-worked by Ben Greear <greearb@candelatech.com>
14 * ---
15 */
16#include <linux/kernel.h>
17#include <linux/types.h>
18#include <linux/module.h>
19#include <linux/init.h>
20#include <linux/errno.h>
21#include <linux/slab.h>
22#include <linux/string.h>
82524746 23#include <linux/rculist.h>
b863ceb7
PM
24#include <linux/notifier.h>
25#include <linux/netdevice.h>
26#include <linux/etherdevice.h>
27#include <linux/ethtool.h>
28#include <linux/if_arp.h>
29#include <linux/if_link.h>
30#include <linux/if_macvlan.h>
31#include <net/rtnetlink.h>
32
33#define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE)
34
35struct macvlan_port {
36 struct net_device *dev;
37 struct hlist_head vlan_hash[MACVLAN_HASH_SIZE];
38 struct list_head vlans;
39};
40
fccaf710
ED
41/**
42 * struct macvlan_rx_stats - MACVLAN percpu rx stats
43 * @rx_packets: number of received packets
44 * @rx_bytes: number of received bytes
45 * @multicast: number of received multicast packets
46 * @rx_errors: number of errors
47 */
48struct macvlan_rx_stats {
49 unsigned long rx_packets;
50 unsigned long rx_bytes;
51 unsigned long multicast;
52 unsigned long rx_errors;
53};
54
b863ceb7
PM
55struct macvlan_dev {
56 struct net_device *dev;
57 struct list_head list;
58 struct hlist_node hlist;
59 struct macvlan_port *port;
60 struct net_device *lowerdev;
fccaf710 61 struct macvlan_rx_stats *rx_stats;
b863ceb7
PM
62};
63
64
65static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port,
66 const unsigned char *addr)
67{
68 struct macvlan_dev *vlan;
69 struct hlist_node *n;
70
71 hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[addr[5]], hlist) {
ac06713d 72 if (!compare_ether_addr_64bits(vlan->dev->dev_addr, addr))
b863ceb7
PM
73 return vlan;
74 }
75 return NULL;
76}
77
f9ac30f0
EB
78static void macvlan_hash_add(struct macvlan_dev *vlan)
79{
80 struct macvlan_port *port = vlan->port;
81 const unsigned char *addr = vlan->dev->dev_addr;
82
83 hlist_add_head_rcu(&vlan->hlist, &port->vlan_hash[addr[5]]);
84}
85
86static void macvlan_hash_del(struct macvlan_dev *vlan)
87{
88 hlist_del_rcu(&vlan->hlist);
89 synchronize_rcu();
90}
91
92static void macvlan_hash_change_addr(struct macvlan_dev *vlan,
93 const unsigned char *addr)
94{
95 macvlan_hash_del(vlan);
96 /* Now that we are unhashed it is safe to change the device
97 * address without confusing packet delivery.
98 */
99 memcpy(vlan->dev->dev_addr, addr, ETH_ALEN);
100 macvlan_hash_add(vlan);
101}
102
103static int macvlan_addr_busy(const struct macvlan_port *port,
104 const unsigned char *addr)
105{
106 /* Test to see if the specified multicast address is
107 * currently in use by the underlying device or
108 * another macvlan.
109 */
ac06713d 110 if (!compare_ether_addr_64bits(port->dev->dev_addr, addr))
f9ac30f0
EB
111 return 1;
112
113 if (macvlan_hash_lookup(port, addr))
114 return 1;
115
116 return 0;
117}
118
a1e514c5
AB
119static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
120 unsigned int len, bool success,
121 bool multicast)
122{
123 struct macvlan_rx_stats *rx_stats;
124
125 rx_stats = per_cpu_ptr(vlan->rx_stats, smp_processor_id());
126 if (likely(success)) {
127 rx_stats->rx_packets++;;
128 rx_stats->rx_bytes += len;
129 if (multicast)
130 rx_stats->multicast++;
131 } else {
132 rx_stats->rx_errors++;
133 }
134}
135
136static int macvlan_broadcast_one(struct sk_buff *skb, struct net_device *dev,
137 const struct ethhdr *eth)
138{
139 if (!skb)
140 return NET_RX_DROP;
141
142 skb->dev = dev;
143 if (!compare_ether_addr_64bits(eth->h_dest,
144 dev->broadcast))
145 skb->pkt_type = PACKET_BROADCAST;
146 else
147 skb->pkt_type = PACKET_MULTICAST;
148
149 return netif_rx(skb);
150}
151
b863ceb7
PM
152static void macvlan_broadcast(struct sk_buff *skb,
153 const struct macvlan_port *port)
154{
155 const struct ethhdr *eth = eth_hdr(skb);
156 const struct macvlan_dev *vlan;
157 struct hlist_node *n;
b863ceb7
PM
158 struct sk_buff *nskb;
159 unsigned int i;
a1e514c5 160 int err;
b863ceb7 161
efbbced3
PM
162 if (skb->protocol == htons(ETH_P_PAUSE))
163 return;
164
b863ceb7
PM
165 for (i = 0; i < MACVLAN_HASH_SIZE; i++) {
166 hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[i], hlist) {
b863ceb7 167 nskb = skb_clone(skb, GFP_ATOMIC);
a1e514c5
AB
168 err = macvlan_broadcast_one(nskb, vlan->dev, eth);
169 macvlan_count_rx(vlan, skb->len + ETH_HLEN,
170 err == NET_RX_SUCCESS, 1);
b863ceb7
PM
171 }
172 }
173}
174
175/* called under rcu_read_lock() from netif_receive_skb */
176static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
177{
178 const struct ethhdr *eth = eth_hdr(skb);
179 const struct macvlan_port *port;
180 const struct macvlan_dev *vlan;
181 struct net_device *dev;
a1e514c5 182 unsigned int len;
b863ceb7
PM
183
184 port = rcu_dereference(skb->dev->macvlan_port);
185 if (port == NULL)
186 return skb;
187
188 if (is_multicast_ether_addr(eth->h_dest)) {
189 macvlan_broadcast(skb, port);
190 return skb;
191 }
192
193 vlan = macvlan_hash_lookup(port, eth->h_dest);
194 if (vlan == NULL)
195 return skb;
196
197 dev = vlan->dev;
198 if (unlikely(!(dev->flags & IFF_UP))) {
199 kfree_skb(skb);
200 return NULL;
201 }
a1e514c5 202 len = skb->len + ETH_HLEN;
b863ceb7 203 skb = skb_share_check(skb, GFP_ATOMIC);
a1e514c5
AB
204 macvlan_count_rx(vlan, len, skb != NULL, 0);
205 if (!skb)
b863ceb7 206 return NULL;
b863ceb7
PM
207
208 skb->dev = dev;
209 skb->pkt_type = PACKET_HOST;
210
211 netif_rx(skb);
212 return NULL;
213}
214
424efe9c
SH
215static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
216 struct net_device *dev)
b863ceb7 217{
2c114553
ED
218 int i = skb_get_queue_mapping(skb);
219 struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
b863ceb7
PM
220 const struct macvlan_dev *vlan = netdev_priv(dev);
221 unsigned int len = skb->len;
222 int ret;
223
224 skb->dev = vlan->lowerdev;
225 ret = dev_queue_xmit(skb);
226
227 if (likely(ret == NET_XMIT_SUCCESS)) {
2c114553
ED
228 txq->tx_packets++;
229 txq->tx_bytes += len;
230 } else
231 txq->tx_dropped++;
232
cbbef5e1 233 return ret;
b863ceb7
PM
234}
235
236static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
3b04ddde
SH
237 unsigned short type, const void *daddr,
238 const void *saddr, unsigned len)
b863ceb7
PM
239{
240 const struct macvlan_dev *vlan = netdev_priv(dev);
241 struct net_device *lowerdev = vlan->lowerdev;
242
0c4e8581
SH
243 return dev_hard_header(skb, lowerdev, type, daddr,
244 saddr ? : dev->dev_addr, len);
b863ceb7
PM
245}
246
3b04ddde
SH
247static const struct header_ops macvlan_hard_header_ops = {
248 .create = macvlan_hard_header,
249 .rebuild = eth_rebuild_header,
250 .parse = eth_header_parse,
3b04ddde
SH
251 .cache = eth_header_cache,
252 .cache_update = eth_header_cache_update,
253};
254
b863ceb7
PM
255static int macvlan_open(struct net_device *dev)
256{
257 struct macvlan_dev *vlan = netdev_priv(dev);
b863ceb7
PM
258 struct net_device *lowerdev = vlan->lowerdev;
259 int err;
260
f9ac30f0
EB
261 err = -EBUSY;
262 if (macvlan_addr_busy(vlan->port, dev->dev_addr))
263 goto out;
264
ccffad25 265 err = dev_unicast_add(lowerdev, dev->dev_addr);
b863ceb7 266 if (err < 0)
b89fb7da
WC
267 goto out;
268 if (dev->flags & IFF_ALLMULTI) {
269 err = dev_set_allmulti(lowerdev, 1);
270 if (err < 0)
271 goto del_unicast;
272 }
f9ac30f0 273 macvlan_hash_add(vlan);
b863ceb7 274 return 0;
b89fb7da
WC
275
276del_unicast:
ccffad25 277 dev_unicast_delete(lowerdev, dev->dev_addr);
b89fb7da
WC
278out:
279 return err;
b863ceb7
PM
280}
281
282static int macvlan_stop(struct net_device *dev)
283{
284 struct macvlan_dev *vlan = netdev_priv(dev);
285 struct net_device *lowerdev = vlan->lowerdev;
286
287 dev_mc_unsync(lowerdev, dev);
288 if (dev->flags & IFF_ALLMULTI)
289 dev_set_allmulti(lowerdev, -1);
290
ccffad25 291 dev_unicast_delete(lowerdev, dev->dev_addr);
b863ceb7 292
f9ac30f0 293 macvlan_hash_del(vlan);
b863ceb7
PM
294 return 0;
295}
296
ad5d20a6
PM
297static int macvlan_set_mac_address(struct net_device *dev, void *p)
298{
299 struct macvlan_dev *vlan = netdev_priv(dev);
300 struct net_device *lowerdev = vlan->lowerdev;
301 struct sockaddr *addr = p;
302 int err;
303
304 if (!is_valid_ether_addr(addr->sa_data))
305 return -EADDRNOTAVAIL;
306
f9ac30f0
EB
307 if (!(dev->flags & IFF_UP)) {
308 /* Just copy in the new address */
309 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
310 } else {
311 /* Rehash and update the device filters */
312 if (macvlan_addr_busy(vlan->port, addr->sa_data))
313 return -EBUSY;
ad5d20a6 314
ccffad25
JP
315 err = dev_unicast_add(lowerdev, addr->sa_data);
316 if (err)
f9ac30f0 317 return err;
ad5d20a6 318
ccffad25 319 dev_unicast_delete(lowerdev, dev->dev_addr);
f9ac30f0
EB
320
321 macvlan_hash_change_addr(vlan, addr->sa_data);
322 }
ad5d20a6
PM
323 return 0;
324}
325
b863ceb7
PM
326static void macvlan_change_rx_flags(struct net_device *dev, int change)
327{
328 struct macvlan_dev *vlan = netdev_priv(dev);
329 struct net_device *lowerdev = vlan->lowerdev;
330
331 if (change & IFF_ALLMULTI)
332 dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1);
333}
334
335static void macvlan_set_multicast_list(struct net_device *dev)
336{
337 struct macvlan_dev *vlan = netdev_priv(dev);
338
339 dev_mc_sync(vlan->lowerdev, dev);
340}
341
342static int macvlan_change_mtu(struct net_device *dev, int new_mtu)
343{
344 struct macvlan_dev *vlan = netdev_priv(dev);
345
346 if (new_mtu < 68 || vlan->lowerdev->mtu < new_mtu)
347 return -EINVAL;
348 dev->mtu = new_mtu;
349 return 0;
350}
351
352/*
353 * macvlan network devices have devices nesting below it and are a special
354 * "super class" of normal network devices; split their locks off into a
355 * separate class since they always nest.
356 */
357static struct lock_class_key macvlan_netdev_xmit_lock_key;
cf508b12 358static struct lock_class_key macvlan_netdev_addr_lock_key;
b863ceb7
PM
359
360#define MACVLAN_FEATURES \
361 (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
362 NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \
363 NETIF_F_TSO_ECN | NETIF_F_TSO6)
364
365#define MACVLAN_STATE_MASK \
366 ((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))
367
e8a0464c
DM
368static void macvlan_set_lockdep_class_one(struct net_device *dev,
369 struct netdev_queue *txq,
370 void *_unused)
c773e847
DM
371{
372 lockdep_set_class(&txq->_xmit_lock,
373 &macvlan_netdev_xmit_lock_key);
374}
375
376static void macvlan_set_lockdep_class(struct net_device *dev)
377{
cf508b12
DM
378 lockdep_set_class(&dev->addr_list_lock,
379 &macvlan_netdev_addr_lock_key);
e8a0464c 380 netdev_for_each_tx_queue(dev, macvlan_set_lockdep_class_one, NULL);
c773e847
DM
381}
382
b863ceb7
PM
383static int macvlan_init(struct net_device *dev)
384{
385 struct macvlan_dev *vlan = netdev_priv(dev);
386 const struct net_device *lowerdev = vlan->lowerdev;
387
388 dev->state = (dev->state & ~MACVLAN_STATE_MASK) |
389 (lowerdev->state & MACVLAN_STATE_MASK);
390 dev->features = lowerdev->features & MACVLAN_FEATURES;
391 dev->iflink = lowerdev->ifindex;
ef5c8996 392 dev->hard_header_len = lowerdev->hard_header_len;
b863ceb7 393
c773e847
DM
394 macvlan_set_lockdep_class(dev);
395
fccaf710
ED
396 vlan->rx_stats = alloc_percpu(struct macvlan_rx_stats);
397 if (!vlan->rx_stats)
398 return -ENOMEM;
399
b863ceb7
PM
400 return 0;
401}
402
fccaf710
ED
403static void macvlan_uninit(struct net_device *dev)
404{
405 struct macvlan_dev *vlan = netdev_priv(dev);
406
407 free_percpu(vlan->rx_stats);
408}
409
410static struct net_device_stats *macvlan_dev_get_stats(struct net_device *dev)
411{
412 struct net_device_stats *stats = &dev->stats;
413 struct macvlan_dev *vlan = netdev_priv(dev);
414
415 dev_txq_stats_fold(dev, stats);
416
417 if (vlan->rx_stats) {
418 struct macvlan_rx_stats *p, rx = {0};
419 int i;
420
421 for_each_possible_cpu(i) {
422 p = per_cpu_ptr(vlan->rx_stats, i);
423 rx.rx_packets += p->rx_packets;
424 rx.rx_bytes += p->rx_bytes;
425 rx.rx_errors += p->rx_errors;
426 rx.multicast += p->multicast;
427 }
428 stats->rx_packets = rx.rx_packets;
429 stats->rx_bytes = rx.rx_bytes;
430 stats->rx_errors = rx.rx_errors;
431 stats->rx_dropped = rx.rx_errors;
432 stats->multicast = rx.multicast;
433 }
434 return stats;
435}
436
b863ceb7
PM
437static void macvlan_ethtool_get_drvinfo(struct net_device *dev,
438 struct ethtool_drvinfo *drvinfo)
439{
440 snprintf(drvinfo->driver, 32, "macvlan");
441 snprintf(drvinfo->version, 32, "0.1");
442}
443
444static u32 macvlan_ethtool_get_rx_csum(struct net_device *dev)
445{
446 const struct macvlan_dev *vlan = netdev_priv(dev);
b1b67dd4 447 return dev_ethtool_get_rx_csum(vlan->lowerdev);
b863ceb7
PM
448}
449
9edb8bb6
SH
450static int macvlan_ethtool_get_settings(struct net_device *dev,
451 struct ethtool_cmd *cmd)
452{
453 const struct macvlan_dev *vlan = netdev_priv(dev);
b1b67dd4 454 return dev_ethtool_get_settings(vlan->lowerdev, cmd);
9edb8bb6
SH
455}
456
457static u32 macvlan_ethtool_get_flags(struct net_device *dev)
458{
459 const struct macvlan_dev *vlan = netdev_priv(dev);
b1b67dd4 460 return dev_ethtool_get_flags(vlan->lowerdev);
9edb8bb6
SH
461}
462
b863ceb7
PM
463static const struct ethtool_ops macvlan_ethtool_ops = {
464 .get_link = ethtool_op_get_link,
9edb8bb6 465 .get_settings = macvlan_ethtool_get_settings,
b863ceb7 466 .get_rx_csum = macvlan_ethtool_get_rx_csum,
b863ceb7 467 .get_drvinfo = macvlan_ethtool_get_drvinfo,
9edb8bb6 468 .get_flags = macvlan_ethtool_get_flags,
b863ceb7
PM
469};
470
54a30c97
SH
471static const struct net_device_ops macvlan_netdev_ops = {
472 .ndo_init = macvlan_init,
fccaf710 473 .ndo_uninit = macvlan_uninit,
54a30c97
SH
474 .ndo_open = macvlan_open,
475 .ndo_stop = macvlan_stop,
00829823 476 .ndo_start_xmit = macvlan_start_xmit,
54a30c97
SH
477 .ndo_change_mtu = macvlan_change_mtu,
478 .ndo_change_rx_flags = macvlan_change_rx_flags,
479 .ndo_set_mac_address = macvlan_set_mac_address,
480 .ndo_set_multicast_list = macvlan_set_multicast_list,
fccaf710 481 .ndo_get_stats = macvlan_dev_get_stats,
54a30c97
SH
482 .ndo_validate_addr = eth_validate_addr,
483};
484
b863ceb7
PM
485static void macvlan_setup(struct net_device *dev)
486{
487 ether_setup(dev);
488
93f154b5 489 dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
54a30c97 490 dev->netdev_ops = &macvlan_netdev_ops;
b863ceb7 491 dev->destructor = free_netdev;
3b04ddde 492 dev->header_ops = &macvlan_hard_header_ops,
b863ceb7
PM
493 dev->ethtool_ops = &macvlan_ethtool_ops;
494 dev->tx_queue_len = 0;
495}
496
497static int macvlan_port_create(struct net_device *dev)
498{
499 struct macvlan_port *port;
500 unsigned int i;
501
502 if (dev->type != ARPHRD_ETHER || dev->flags & IFF_LOOPBACK)
503 return -EINVAL;
504
505 port = kzalloc(sizeof(*port), GFP_KERNEL);
506 if (port == NULL)
507 return -ENOMEM;
508
509 port->dev = dev;
510 INIT_LIST_HEAD(&port->vlans);
511 for (i = 0; i < MACVLAN_HASH_SIZE; i++)
512 INIT_HLIST_HEAD(&port->vlan_hash[i]);
513 rcu_assign_pointer(dev->macvlan_port, port);
514 return 0;
515}
516
517static void macvlan_port_destroy(struct net_device *dev)
518{
519 struct macvlan_port *port = dev->macvlan_port;
520
521 rcu_assign_pointer(dev->macvlan_port, NULL);
522 synchronize_rcu();
523 kfree(port);
524}
525
526static void macvlan_transfer_operstate(struct net_device *dev)
527{
528 struct macvlan_dev *vlan = netdev_priv(dev);
529 const struct net_device *lowerdev = vlan->lowerdev;
530
531 if (lowerdev->operstate == IF_OPER_DORMANT)
532 netif_dormant_on(dev);
533 else
534 netif_dormant_off(dev);
535
536 if (netif_carrier_ok(lowerdev)) {
537 if (!netif_carrier_ok(dev))
538 netif_carrier_on(dev);
539 } else {
f12ca5f9 540 if (netif_carrier_ok(dev))
b863ceb7
PM
541 netif_carrier_off(dev);
542 }
543}
544
545static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
546{
547 if (tb[IFLA_ADDRESS]) {
548 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
549 return -EINVAL;
550 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
551 return -EADDRNOTAVAIL;
552 }
553 return 0;
554}
555
2c114553
ED
556static int macvlan_get_tx_queues(struct net *net,
557 struct nlattr *tb[],
558 unsigned int *num_tx_queues,
559 unsigned int *real_num_tx_queues)
560{
561 struct net_device *real_dev;
562
563 if (!tb[IFLA_LINK])
564 return -EINVAL;
565
566 real_dev = __dev_get_by_index(net, nla_get_u32(tb[IFLA_LINK]));
567 if (!real_dev)
568 return -ENODEV;
569
570 *num_tx_queues = real_dev->num_tx_queues;
571 *real_num_tx_queues = real_dev->real_num_tx_queues;
572 return 0;
573}
574
81adee47 575static int macvlan_newlink(struct net *src_net, struct net_device *dev,
b863ceb7
PM
576 struct nlattr *tb[], struct nlattr *data[])
577{
578 struct macvlan_dev *vlan = netdev_priv(dev);
579 struct macvlan_port *port;
580 struct net_device *lowerdev;
581 int err;
582
583 if (!tb[IFLA_LINK])
584 return -EINVAL;
585
81adee47 586 lowerdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
b863ceb7
PM
587 if (lowerdev == NULL)
588 return -ENODEV;
589
b0832a29
EB
590 /* When creating macvlans on top of other macvlans - use
591 * the real device as the lowerdev.
a6ca5f1d 592 */
b0832a29
EB
593 if (lowerdev->rtnl_link_ops == dev->rtnl_link_ops) {
594 struct macvlan_dev *lowervlan = netdev_priv(lowerdev);
595 lowerdev = lowervlan->lowerdev;
596 }
a6ca5f1d 597
b863ceb7
PM
598 if (!tb[IFLA_MTU])
599 dev->mtu = lowerdev->mtu;
600 else if (dev->mtu > lowerdev->mtu)
601 return -EINVAL;
602
603 if (!tb[IFLA_ADDRESS])
604 random_ether_addr(dev->dev_addr);
605
606 if (lowerdev->macvlan_port == NULL) {
607 err = macvlan_port_create(lowerdev);
608 if (err < 0)
609 return err;
610 }
611 port = lowerdev->macvlan_port;
612
613 vlan->lowerdev = lowerdev;
614 vlan->dev = dev;
615 vlan->port = port;
616
617 err = register_netdevice(dev);
618 if (err < 0)
619 return err;
620
621 list_add_tail(&vlan->list, &port->vlans);
622 macvlan_transfer_operstate(dev);
623 return 0;
624}
625
23289a37 626static void macvlan_dellink(struct net_device *dev, struct list_head *head)
b863ceb7
PM
627{
628 struct macvlan_dev *vlan = netdev_priv(dev);
629 struct macvlan_port *port = vlan->port;
630
631 list_del(&vlan->list);
23289a37 632 unregister_netdevice_queue(dev, head);
b863ceb7
PM
633
634 if (list_empty(&port->vlans))
73120964 635 macvlan_port_destroy(port->dev);
b863ceb7
PM
636}
637
638static struct rtnl_link_ops macvlan_link_ops __read_mostly = {
639 .kind = "macvlan",
640 .priv_size = sizeof(struct macvlan_dev),
2c114553 641 .get_tx_queues = macvlan_get_tx_queues,
b863ceb7
PM
642 .setup = macvlan_setup,
643 .validate = macvlan_validate,
644 .newlink = macvlan_newlink,
645 .dellink = macvlan_dellink,
646};
647
648static int macvlan_device_event(struct notifier_block *unused,
649 unsigned long event, void *ptr)
650{
651 struct net_device *dev = ptr;
652 struct macvlan_dev *vlan, *next;
653 struct macvlan_port *port;
654
655 port = dev->macvlan_port;
656 if (port == NULL)
657 return NOTIFY_DONE;
658
659 switch (event) {
660 case NETDEV_CHANGE:
661 list_for_each_entry(vlan, &port->vlans, list)
662 macvlan_transfer_operstate(vlan->dev);
663 break;
664 case NETDEV_FEAT_CHANGE:
665 list_for_each_entry(vlan, &port->vlans, list) {
666 vlan->dev->features = dev->features & MACVLAN_FEATURES;
667 netdev_features_change(vlan->dev);
668 }
669 break;
670 case NETDEV_UNREGISTER:
671 list_for_each_entry_safe(vlan, next, &port->vlans, list)
23289a37 672 macvlan_dellink(vlan->dev, NULL);
b863ceb7
PM
673 break;
674 }
675 return NOTIFY_DONE;
676}
677
678static struct notifier_block macvlan_notifier_block __read_mostly = {
679 .notifier_call = macvlan_device_event,
680};
681
682static int __init macvlan_init_module(void)
683{
684 int err;
685
686 register_netdevice_notifier(&macvlan_notifier_block);
687 macvlan_handle_frame_hook = macvlan_handle_frame;
688
689 err = rtnl_link_register(&macvlan_link_ops);
690 if (err < 0)
691 goto err1;
692 return 0;
693err1:
52913246 694 macvlan_handle_frame_hook = NULL;
b863ceb7
PM
695 unregister_netdevice_notifier(&macvlan_notifier_block);
696 return err;
697}
698
699static void __exit macvlan_cleanup_module(void)
700{
701 rtnl_link_unregister(&macvlan_link_ops);
702 macvlan_handle_frame_hook = NULL;
703 unregister_netdevice_notifier(&macvlan_notifier_block);
704}
705
706module_init(macvlan_init_module);
707module_exit(macvlan_cleanup_module);
708
709MODULE_LICENSE("GPL");
710MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
711MODULE_DESCRIPTION("Driver for MAC address based VLANs");
712MODULE_ALIAS_RTNL_LINK("macvlan");
This page took 0.473658 seconds and 5 git commands to generate.