diff options
Diffstat (limited to 'drivers/net/macvlan.c')
-rw-r--r-- | drivers/net/macvlan.c | 280 |
1 files changed, 220 insertions, 60 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 3aabfd9dd212..21a9c9ab4b34 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/if_link.h> | 29 | #include <linux/if_link.h> |
30 | #include <linux/if_macvlan.h> | 30 | #include <linux/if_macvlan.h> |
31 | #include <net/rtnetlink.h> | 31 | #include <net/rtnetlink.h> |
32 | #include <net/xfrm.h> | ||
32 | 33 | ||
33 | #define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE) | 34 | #define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE) |
34 | 35 | ||
@@ -38,12 +39,28 @@ struct macvlan_port { | |||
38 | struct list_head vlans; | 39 | struct list_head vlans; |
39 | }; | 40 | }; |
40 | 41 | ||
42 | /** | ||
43 | * struct macvlan_rx_stats - MACVLAN percpu rx stats | ||
44 | * @rx_packets: number of received packets | ||
45 | * @rx_bytes: number of received bytes | ||
46 | * @multicast: number of received multicast packets | ||
47 | * @rx_errors: number of errors | ||
48 | */ | ||
49 | struct macvlan_rx_stats { | ||
50 | unsigned long rx_packets; | ||
51 | unsigned long rx_bytes; | ||
52 | unsigned long multicast; | ||
53 | unsigned long rx_errors; | ||
54 | }; | ||
55 | |||
41 | struct macvlan_dev { | 56 | struct macvlan_dev { |
42 | struct net_device *dev; | 57 | struct net_device *dev; |
43 | struct list_head list; | 58 | struct list_head list; |
44 | struct hlist_node hlist; | 59 | struct hlist_node hlist; |
45 | struct macvlan_port *port; | 60 | struct macvlan_port *port; |
46 | struct net_device *lowerdev; | 61 | struct net_device *lowerdev; |
62 | struct macvlan_rx_stats *rx_stats; | ||
63 | enum macvlan_mode mode; | ||
47 | }; | 64 | }; |
48 | 65 | ||
49 | 66 | ||
@@ -101,41 +118,67 @@ static int macvlan_addr_busy(const struct macvlan_port *port, | |||
101 | return 0; | 118 | return 0; |
102 | } | 119 | } |
103 | 120 | ||
121 | static inline void macvlan_count_rx(const struct macvlan_dev *vlan, | ||
122 | unsigned int len, bool success, | ||
123 | bool multicast) | ||
124 | { | ||
125 | struct macvlan_rx_stats *rx_stats; | ||
126 | |||
127 | rx_stats = per_cpu_ptr(vlan->rx_stats, smp_processor_id()); | ||
128 | if (likely(success)) { | ||
129 | rx_stats->rx_packets++;; | ||
130 | rx_stats->rx_bytes += len; | ||
131 | if (multicast) | ||
132 | rx_stats->multicast++; | ||
133 | } else { | ||
134 | rx_stats->rx_errors++; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | static int macvlan_broadcast_one(struct sk_buff *skb, struct net_device *dev, | ||
139 | const struct ethhdr *eth, bool local) | ||
140 | { | ||
141 | if (!skb) | ||
142 | return NET_RX_DROP; | ||
143 | |||
144 | if (local) | ||
145 | return dev_forward_skb(dev, skb); | ||
146 | |||
147 | skb->dev = dev; | ||
148 | if (!compare_ether_addr_64bits(eth->h_dest, | ||
149 | dev->broadcast)) | ||
150 | skb->pkt_type = PACKET_BROADCAST; | ||
151 | else | ||
152 | skb->pkt_type = PACKET_MULTICAST; | ||
153 | |||
154 | return netif_rx(skb); | ||
155 | } | ||
156 | |||
104 | static void macvlan_broadcast(struct sk_buff *skb, | 157 | static void macvlan_broadcast(struct sk_buff *skb, |
105 | const struct macvlan_port *port) | 158 | const struct macvlan_port *port, |
159 | struct net_device *src, | ||
160 | enum macvlan_mode mode) | ||
106 | { | 161 | { |
107 | const struct ethhdr *eth = eth_hdr(skb); | 162 | const struct ethhdr *eth = eth_hdr(skb); |
108 | const struct macvlan_dev *vlan; | 163 | const struct macvlan_dev *vlan; |
109 | struct hlist_node *n; | 164 | struct hlist_node *n; |
110 | struct net_device *dev; | ||
111 | struct sk_buff *nskb; | 165 | struct sk_buff *nskb; |
112 | unsigned int i; | 166 | unsigned int i; |
167 | int err; | ||
113 | 168 | ||
114 | if (skb->protocol == htons(ETH_P_PAUSE)) | 169 | if (skb->protocol == htons(ETH_P_PAUSE)) |
115 | return; | 170 | return; |
116 | 171 | ||
117 | for (i = 0; i < MACVLAN_HASH_SIZE; i++) { | 172 | for (i = 0; i < MACVLAN_HASH_SIZE; i++) { |
118 | hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[i], hlist) { | 173 | hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[i], hlist) { |
119 | dev = vlan->dev; | 174 | if (vlan->dev == src || !(vlan->mode & mode)) |
120 | |||
121 | nskb = skb_clone(skb, GFP_ATOMIC); | ||
122 | if (nskb == NULL) { | ||
123 | dev->stats.rx_errors++; | ||
124 | dev->stats.rx_dropped++; | ||
125 | continue; | 175 | continue; |
126 | } | ||
127 | |||
128 | dev->stats.rx_bytes += skb->len + ETH_HLEN; | ||
129 | dev->stats.rx_packets++; | ||
130 | dev->stats.multicast++; | ||
131 | |||
132 | nskb->dev = dev; | ||
133 | if (!compare_ether_addr_64bits(eth->h_dest, dev->broadcast)) | ||
134 | nskb->pkt_type = PACKET_BROADCAST; | ||
135 | else | ||
136 | nskb->pkt_type = PACKET_MULTICAST; | ||
137 | 176 | ||
138 | netif_rx(nskb); | 177 | nskb = skb_clone(skb, GFP_ATOMIC); |
178 | err = macvlan_broadcast_one(nskb, vlan->dev, eth, | ||
179 | mode == MACVLAN_MODE_BRIDGE); | ||
180 | macvlan_count_rx(vlan, skb->len + ETH_HLEN, | ||
181 | err == NET_RX_SUCCESS, 1); | ||
139 | } | 182 | } |
140 | } | 183 | } |
141 | } | 184 | } |
@@ -146,14 +189,34 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb) | |||
146 | const struct ethhdr *eth = eth_hdr(skb); | 189 | const struct ethhdr *eth = eth_hdr(skb); |
147 | const struct macvlan_port *port; | 190 | const struct macvlan_port *port; |
148 | const struct macvlan_dev *vlan; | 191 | const struct macvlan_dev *vlan; |
192 | const struct macvlan_dev *src; | ||
149 | struct net_device *dev; | 193 | struct net_device *dev; |
194 | unsigned int len; | ||
150 | 195 | ||
151 | port = rcu_dereference(skb->dev->macvlan_port); | 196 | port = rcu_dereference(skb->dev->macvlan_port); |
152 | if (port == NULL) | 197 | if (port == NULL) |
153 | return skb; | 198 | return skb; |
154 | 199 | ||
155 | if (is_multicast_ether_addr(eth->h_dest)) { | 200 | if (is_multicast_ether_addr(eth->h_dest)) { |
156 | macvlan_broadcast(skb, port); | 201 | src = macvlan_hash_lookup(port, eth->h_source); |
202 | if (!src) | ||
203 | /* frame comes from an external address */ | ||
204 | macvlan_broadcast(skb, port, NULL, | ||
205 | MACVLAN_MODE_PRIVATE | | ||
206 | MACVLAN_MODE_VEPA | | ||
207 | MACVLAN_MODE_BRIDGE); | ||
208 | else if (src->mode == MACVLAN_MODE_VEPA) | ||
209 | /* flood to everyone except source */ | ||
210 | macvlan_broadcast(skb, port, src->dev, | ||
211 | MACVLAN_MODE_VEPA | | ||
212 | MACVLAN_MODE_BRIDGE); | ||
213 | else if (src->mode == MACVLAN_MODE_BRIDGE) | ||
214 | /* | ||
215 | * flood only to VEPA ports, bridge ports | ||
216 | * already saw the frame on the way out. | ||
217 | */ | ||
218 | macvlan_broadcast(skb, port, src->dev, | ||
219 | MACVLAN_MODE_VEPA); | ||
157 | return skb; | 220 | return skb; |
158 | } | 221 | } |
159 | 222 | ||
@@ -166,16 +229,11 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb) | |||
166 | kfree_skb(skb); | 229 | kfree_skb(skb); |
167 | return NULL; | 230 | return NULL; |
168 | } | 231 | } |
169 | 232 | len = skb->len + ETH_HLEN; | |
170 | skb = skb_share_check(skb, GFP_ATOMIC); | 233 | skb = skb_share_check(skb, GFP_ATOMIC); |
171 | if (skb == NULL) { | 234 | macvlan_count_rx(vlan, len, skb != NULL, 0); |
172 | dev->stats.rx_errors++; | 235 | if (!skb) |
173 | dev->stats.rx_dropped++; | ||
174 | return NULL; | 236 | return NULL; |
175 | } | ||
176 | |||
177 | dev->stats.rx_bytes += skb->len + ETH_HLEN; | ||
178 | dev->stats.rx_packets++; | ||
179 | 237 | ||
180 | skb->dev = dev; | 238 | skb->dev = dev; |
181 | skb->pkt_type = PACKET_HOST; | 239 | skb->pkt_type = PACKET_HOST; |
@@ -184,25 +242,53 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb) | |||
184 | return NULL; | 242 | return NULL; |
185 | } | 243 | } |
186 | 244 | ||
245 | static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev) | ||
246 | { | ||
247 | const struct macvlan_dev *vlan = netdev_priv(dev); | ||
248 | const struct macvlan_port *port = vlan->port; | ||
249 | const struct macvlan_dev *dest; | ||
250 | |||
251 | if (vlan->mode == MACVLAN_MODE_BRIDGE) { | ||
252 | const struct ethhdr *eth = (void *)skb->data; | ||
253 | |||
254 | /* send to other bridge ports directly */ | ||
255 | if (is_multicast_ether_addr(eth->h_dest)) { | ||
256 | macvlan_broadcast(skb, port, dev, MACVLAN_MODE_BRIDGE); | ||
257 | goto xmit_world; | ||
258 | } | ||
259 | |||
260 | dest = macvlan_hash_lookup(port, eth->h_dest); | ||
261 | if (dest && dest->mode == MACVLAN_MODE_BRIDGE) { | ||
262 | unsigned int length = skb->len + ETH_HLEN; | ||
263 | int ret = dev_forward_skb(dest->dev, skb); | ||
264 | macvlan_count_rx(dest, length, | ||
265 | ret == NET_RX_SUCCESS, 0); | ||
266 | |||
267 | return NET_XMIT_SUCCESS; | ||
268 | } | ||
269 | } | ||
270 | |||
271 | xmit_world: | ||
272 | skb->dev = vlan->lowerdev; | ||
273 | return dev_queue_xmit(skb); | ||
274 | } | ||
275 | |||
187 | static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb, | 276 | static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb, |
188 | struct net_device *dev) | 277 | struct net_device *dev) |
189 | { | 278 | { |
190 | int i = skb_get_queue_mapping(skb); | 279 | int i = skb_get_queue_mapping(skb); |
191 | struct netdev_queue *txq = netdev_get_tx_queue(dev, i); | 280 | struct netdev_queue *txq = netdev_get_tx_queue(dev, i); |
192 | const struct macvlan_dev *vlan = netdev_priv(dev); | ||
193 | unsigned int len = skb->len; | 281 | unsigned int len = skb->len; |
194 | int ret; | 282 | int ret; |
195 | 283 | ||
196 | skb->dev = vlan->lowerdev; | 284 | ret = macvlan_queue_xmit(skb, dev); |
197 | ret = dev_queue_xmit(skb); | ||
198 | |||
199 | if (likely(ret == NET_XMIT_SUCCESS)) { | 285 | if (likely(ret == NET_XMIT_SUCCESS)) { |
200 | txq->tx_packets++; | 286 | txq->tx_packets++; |
201 | txq->tx_bytes += len; | 287 | txq->tx_bytes += len; |
202 | } else | 288 | } else |
203 | txq->tx_dropped++; | 289 | txq->tx_dropped++; |
204 | 290 | ||
205 | return NETDEV_TX_OK; | 291 | return ret; |
206 | } | 292 | } |
207 | 293 | ||
208 | static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev, | 294 | static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev, |
@@ -360,14 +446,53 @@ static int macvlan_init(struct net_device *dev) | |||
360 | dev->state = (dev->state & ~MACVLAN_STATE_MASK) | | 446 | dev->state = (dev->state & ~MACVLAN_STATE_MASK) | |
361 | (lowerdev->state & MACVLAN_STATE_MASK); | 447 | (lowerdev->state & MACVLAN_STATE_MASK); |
362 | dev->features = lowerdev->features & MACVLAN_FEATURES; | 448 | dev->features = lowerdev->features & MACVLAN_FEATURES; |
449 | dev->gso_max_size = lowerdev->gso_max_size; | ||
363 | dev->iflink = lowerdev->ifindex; | 450 | dev->iflink = lowerdev->ifindex; |
364 | dev->hard_header_len = lowerdev->hard_header_len; | 451 | dev->hard_header_len = lowerdev->hard_header_len; |
365 | 452 | ||
366 | macvlan_set_lockdep_class(dev); | 453 | macvlan_set_lockdep_class(dev); |
367 | 454 | ||
455 | vlan->rx_stats = alloc_percpu(struct macvlan_rx_stats); | ||
456 | if (!vlan->rx_stats) | ||
457 | return -ENOMEM; | ||
458 | |||
368 | return 0; | 459 | return 0; |
369 | } | 460 | } |
370 | 461 | ||
462 | static void macvlan_uninit(struct net_device *dev) | ||
463 | { | ||
464 | struct macvlan_dev *vlan = netdev_priv(dev); | ||
465 | |||
466 | free_percpu(vlan->rx_stats); | ||
467 | } | ||
468 | |||
469 | static struct net_device_stats *macvlan_dev_get_stats(struct net_device *dev) | ||
470 | { | ||
471 | struct net_device_stats *stats = &dev->stats; | ||
472 | struct macvlan_dev *vlan = netdev_priv(dev); | ||
473 | |||
474 | dev_txq_stats_fold(dev, stats); | ||
475 | |||
476 | if (vlan->rx_stats) { | ||
477 | struct macvlan_rx_stats *p, rx = {0}; | ||
478 | int i; | ||
479 | |||
480 | for_each_possible_cpu(i) { | ||
481 | p = per_cpu_ptr(vlan->rx_stats, i); | ||
482 | rx.rx_packets += p->rx_packets; | ||
483 | rx.rx_bytes += p->rx_bytes; | ||
484 | rx.rx_errors += p->rx_errors; | ||
485 | rx.multicast += p->multicast; | ||
486 | } | ||
487 | stats->rx_packets = rx.rx_packets; | ||
488 | stats->rx_bytes = rx.rx_bytes; | ||
489 | stats->rx_errors = rx.rx_errors; | ||
490 | stats->rx_dropped = rx.rx_errors; | ||
491 | stats->multicast = rx.multicast; | ||
492 | } | ||
493 | return stats; | ||
494 | } | ||
495 | |||
371 | static void macvlan_ethtool_get_drvinfo(struct net_device *dev, | 496 | static void macvlan_ethtool_get_drvinfo(struct net_device *dev, |
372 | struct ethtool_drvinfo *drvinfo) | 497 | struct ethtool_drvinfo *drvinfo) |
373 | { | 498 | { |
@@ -404,6 +529,7 @@ static const struct ethtool_ops macvlan_ethtool_ops = { | |||
404 | 529 | ||
405 | static const struct net_device_ops macvlan_netdev_ops = { | 530 | static const struct net_device_ops macvlan_netdev_ops = { |
406 | .ndo_init = macvlan_init, | 531 | .ndo_init = macvlan_init, |
532 | .ndo_uninit = macvlan_uninit, | ||
407 | .ndo_open = macvlan_open, | 533 | .ndo_open = macvlan_open, |
408 | .ndo_stop = macvlan_stop, | 534 | .ndo_stop = macvlan_stop, |
409 | .ndo_start_xmit = macvlan_start_xmit, | 535 | .ndo_start_xmit = macvlan_start_xmit, |
@@ -411,6 +537,7 @@ static const struct net_device_ops macvlan_netdev_ops = { | |||
411 | .ndo_change_rx_flags = macvlan_change_rx_flags, | 537 | .ndo_change_rx_flags = macvlan_change_rx_flags, |
412 | .ndo_set_mac_address = macvlan_set_mac_address, | 538 | .ndo_set_mac_address = macvlan_set_mac_address, |
413 | .ndo_set_multicast_list = macvlan_set_multicast_list, | 539 | .ndo_set_multicast_list = macvlan_set_multicast_list, |
540 | .ndo_get_stats = macvlan_dev_get_stats, | ||
414 | .ndo_validate_addr = eth_validate_addr, | 541 | .ndo_validate_addr = eth_validate_addr, |
415 | }; | 542 | }; |
416 | 543 | ||
@@ -455,25 +582,6 @@ static void macvlan_port_destroy(struct net_device *dev) | |||
455 | kfree(port); | 582 | kfree(port); |
456 | } | 583 | } |
457 | 584 | ||
458 | static void macvlan_transfer_operstate(struct net_device *dev) | ||
459 | { | ||
460 | struct macvlan_dev *vlan = netdev_priv(dev); | ||
461 | const struct net_device *lowerdev = vlan->lowerdev; | ||
462 | |||
463 | if (lowerdev->operstate == IF_OPER_DORMANT) | ||
464 | netif_dormant_on(dev); | ||
465 | else | ||
466 | netif_dormant_off(dev); | ||
467 | |||
468 | if (netif_carrier_ok(lowerdev)) { | ||
469 | if (!netif_carrier_ok(dev)) | ||
470 | netif_carrier_on(dev); | ||
471 | } else { | ||
472 | if (netif_carrier_ok(dev)) | ||
473 | netif_carrier_off(dev); | ||
474 | } | ||
475 | } | ||
476 | |||
477 | static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[]) | 585 | static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[]) |
478 | { | 586 | { |
479 | if (tb[IFLA_ADDRESS]) { | 587 | if (tb[IFLA_ADDRESS]) { |
@@ -482,6 +590,17 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[]) | |||
482 | if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) | 590 | if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) |
483 | return -EADDRNOTAVAIL; | 591 | return -EADDRNOTAVAIL; |
484 | } | 592 | } |
593 | |||
594 | if (data && data[IFLA_MACVLAN_MODE]) { | ||
595 | switch (nla_get_u32(data[IFLA_MACVLAN_MODE])) { | ||
596 | case MACVLAN_MODE_PRIVATE: | ||
597 | case MACVLAN_MODE_VEPA: | ||
598 | case MACVLAN_MODE_BRIDGE: | ||
599 | break; | ||
600 | default: | ||
601 | return -EINVAL; | ||
602 | } | ||
603 | } | ||
485 | return 0; | 604 | return 0; |
486 | } | 605 | } |
487 | 606 | ||
@@ -504,7 +623,7 @@ static int macvlan_get_tx_queues(struct net *net, | |||
504 | return 0; | 623 | return 0; |
505 | } | 624 | } |
506 | 625 | ||
507 | static int macvlan_newlink(struct net_device *dev, | 626 | static int macvlan_newlink(struct net *src_net, struct net_device *dev, |
508 | struct nlattr *tb[], struct nlattr *data[]) | 627 | struct nlattr *tb[], struct nlattr *data[]) |
509 | { | 628 | { |
510 | struct macvlan_dev *vlan = netdev_priv(dev); | 629 | struct macvlan_dev *vlan = netdev_priv(dev); |
@@ -515,7 +634,7 @@ static int macvlan_newlink(struct net_device *dev, | |||
515 | if (!tb[IFLA_LINK]) | 634 | if (!tb[IFLA_LINK]) |
516 | return -EINVAL; | 635 | return -EINVAL; |
517 | 636 | ||
518 | lowerdev = __dev_get_by_index(dev_net(dev), nla_get_u32(tb[IFLA_LINK])); | 637 | lowerdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); |
519 | if (lowerdev == NULL) | 638 | if (lowerdev == NULL) |
520 | return -ENODEV; | 639 | return -ENODEV; |
521 | 640 | ||
@@ -546,27 +665,61 @@ static int macvlan_newlink(struct net_device *dev, | |||
546 | vlan->dev = dev; | 665 | vlan->dev = dev; |
547 | vlan->port = port; | 666 | vlan->port = port; |
548 | 667 | ||
668 | vlan->mode = MACVLAN_MODE_VEPA; | ||
669 | if (data && data[IFLA_MACVLAN_MODE]) | ||
670 | vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]); | ||
671 | |||
549 | err = register_netdevice(dev); | 672 | err = register_netdevice(dev); |
550 | if (err < 0) | 673 | if (err < 0) |
551 | return err; | 674 | return err; |
552 | 675 | ||
553 | list_add_tail(&vlan->list, &port->vlans); | 676 | list_add_tail(&vlan->list, &port->vlans); |
554 | macvlan_transfer_operstate(dev); | 677 | netif_stacked_transfer_operstate(lowerdev, dev); |
555 | return 0; | 678 | return 0; |
556 | } | 679 | } |
557 | 680 | ||
558 | static void macvlan_dellink(struct net_device *dev) | 681 | static void macvlan_dellink(struct net_device *dev, struct list_head *head) |
559 | { | 682 | { |
560 | struct macvlan_dev *vlan = netdev_priv(dev); | 683 | struct macvlan_dev *vlan = netdev_priv(dev); |
561 | struct macvlan_port *port = vlan->port; | 684 | struct macvlan_port *port = vlan->port; |
562 | 685 | ||
563 | list_del(&vlan->list); | 686 | list_del(&vlan->list); |
564 | unregister_netdevice(dev); | 687 | unregister_netdevice_queue(dev, head); |
565 | 688 | ||
566 | if (list_empty(&port->vlans)) | 689 | if (list_empty(&port->vlans)) |
567 | macvlan_port_destroy(port->dev); | 690 | macvlan_port_destroy(port->dev); |
568 | } | 691 | } |
569 | 692 | ||
693 | static int macvlan_changelink(struct net_device *dev, | ||
694 | struct nlattr *tb[], struct nlattr *data[]) | ||
695 | { | ||
696 | struct macvlan_dev *vlan = netdev_priv(dev); | ||
697 | if (data && data[IFLA_MACVLAN_MODE]) | ||
698 | vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]); | ||
699 | return 0; | ||
700 | } | ||
701 | |||
702 | static size_t macvlan_get_size(const struct net_device *dev) | ||
703 | { | ||
704 | return nla_total_size(4); | ||
705 | } | ||
706 | |||
707 | static int macvlan_fill_info(struct sk_buff *skb, | ||
708 | const struct net_device *dev) | ||
709 | { | ||
710 | struct macvlan_dev *vlan = netdev_priv(dev); | ||
711 | |||
712 | NLA_PUT_U32(skb, IFLA_MACVLAN_MODE, vlan->mode); | ||
713 | return 0; | ||
714 | |||
715 | nla_put_failure: | ||
716 | return -EMSGSIZE; | ||
717 | } | ||
718 | |||
719 | static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = { | ||
720 | [IFLA_MACVLAN_MODE] = { .type = NLA_U32 }, | ||
721 | }; | ||
722 | |||
570 | static struct rtnl_link_ops macvlan_link_ops __read_mostly = { | 723 | static struct rtnl_link_ops macvlan_link_ops __read_mostly = { |
571 | .kind = "macvlan", | 724 | .kind = "macvlan", |
572 | .priv_size = sizeof(struct macvlan_dev), | 725 | .priv_size = sizeof(struct macvlan_dev), |
@@ -575,6 +728,11 @@ static struct rtnl_link_ops macvlan_link_ops __read_mostly = { | |||
575 | .validate = macvlan_validate, | 728 | .validate = macvlan_validate, |
576 | .newlink = macvlan_newlink, | 729 | .newlink = macvlan_newlink, |
577 | .dellink = macvlan_dellink, | 730 | .dellink = macvlan_dellink, |
731 | .maxtype = IFLA_MACVLAN_MAX, | ||
732 | .policy = macvlan_policy, | ||
733 | .changelink = macvlan_changelink, | ||
734 | .get_size = macvlan_get_size, | ||
735 | .fill_info = macvlan_fill_info, | ||
578 | }; | 736 | }; |
579 | 737 | ||
580 | static int macvlan_device_event(struct notifier_block *unused, | 738 | static int macvlan_device_event(struct notifier_block *unused, |
@@ -591,17 +749,19 @@ static int macvlan_device_event(struct notifier_block *unused, | |||
591 | switch (event) { | 749 | switch (event) { |
592 | case NETDEV_CHANGE: | 750 | case NETDEV_CHANGE: |
593 | list_for_each_entry(vlan, &port->vlans, list) | 751 | list_for_each_entry(vlan, &port->vlans, list) |
594 | macvlan_transfer_operstate(vlan->dev); | 752 | netif_stacked_transfer_operstate(vlan->lowerdev, |
753 | vlan->dev); | ||
595 | break; | 754 | break; |
596 | case NETDEV_FEAT_CHANGE: | 755 | case NETDEV_FEAT_CHANGE: |
597 | list_for_each_entry(vlan, &port->vlans, list) { | 756 | list_for_each_entry(vlan, &port->vlans, list) { |
598 | vlan->dev->features = dev->features & MACVLAN_FEATURES; | 757 | vlan->dev->features = dev->features & MACVLAN_FEATURES; |
758 | vlan->dev->gso_max_size = dev->gso_max_size; | ||
599 | netdev_features_change(vlan->dev); | 759 | netdev_features_change(vlan->dev); |
600 | } | 760 | } |
601 | break; | 761 | break; |
602 | case NETDEV_UNREGISTER: | 762 | case NETDEV_UNREGISTER: |
603 | list_for_each_entry_safe(vlan, next, &port->vlans, list) | 763 | list_for_each_entry_safe(vlan, next, &port->vlans, list) |
604 | macvlan_dellink(vlan->dev); | 764 | macvlan_dellink(vlan->dev, NULL); |
605 | break; | 765 | break; |
606 | } | 766 | } |
607 | return NOTIFY_DONE; | 767 | return NOTIFY_DONE; |