aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/macvlan.c113
-rw-r--r--include/linux/if_macvlan.h70
2 files changed, 119 insertions, 64 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index d32e0bdfc5e9..40faa368b07a 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -39,31 +39,6 @@ struct macvlan_port {
39 struct list_head vlans; 39 struct list_head vlans;
40}; 40};
41 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 */
49struct macvlan_rx_stats {
50 unsigned long rx_packets;
51 unsigned long rx_bytes;
52 unsigned long multicast;
53 unsigned long rx_errors;
54};
55
56struct macvlan_dev {
57 struct net_device *dev;
58 struct list_head list;
59 struct hlist_node hlist;
60 struct macvlan_port *port;
61 struct net_device *lowerdev;
62 struct macvlan_rx_stats *rx_stats;
63 enum macvlan_mode mode;
64};
65
66
67static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port, 42static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port,
68 const unsigned char *addr) 43 const unsigned char *addr)
69{ 44{
@@ -118,31 +93,17 @@ static int macvlan_addr_busy(const struct macvlan_port *port,
118 return 0; 93 return 0;
119} 94}
120 95
121static 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 96
138static int macvlan_broadcast_one(struct sk_buff *skb, struct net_device *dev, 97static int macvlan_broadcast_one(struct sk_buff *skb,
98 const struct macvlan_dev *vlan,
139 const struct ethhdr *eth, bool local) 99 const struct ethhdr *eth, bool local)
140{ 100{
101 struct net_device *dev = vlan->dev;
141 if (!skb) 102 if (!skb)
142 return NET_RX_DROP; 103 return NET_RX_DROP;
143 104
144 if (local) 105 if (local)
145 return dev_forward_skb(dev, skb); 106 return vlan->forward(dev, skb);
146 107
147 skb->dev = dev; 108 skb->dev = dev;
148 if (!compare_ether_addr_64bits(eth->h_dest, 109 if (!compare_ether_addr_64bits(eth->h_dest,
@@ -151,7 +112,7 @@ static int macvlan_broadcast_one(struct sk_buff *skb, struct net_device *dev,
151 else 112 else
152 skb->pkt_type = PACKET_MULTICAST; 113 skb->pkt_type = PACKET_MULTICAST;
153 114
154 return netif_rx(skb); 115 return vlan->receive(skb);
155} 116}
156 117
157static void macvlan_broadcast(struct sk_buff *skb, 118static void macvlan_broadcast(struct sk_buff *skb,
@@ -175,7 +136,7 @@ static void macvlan_broadcast(struct sk_buff *skb,
175 continue; 136 continue;
176 137
177 nskb = skb_clone(skb, GFP_ATOMIC); 138 nskb = skb_clone(skb, GFP_ATOMIC);
178 err = macvlan_broadcast_one(nskb, vlan->dev, eth, 139 err = macvlan_broadcast_one(nskb, vlan, eth,
179 mode == MACVLAN_MODE_BRIDGE); 140 mode == MACVLAN_MODE_BRIDGE);
180 macvlan_count_rx(vlan, skb->len + ETH_HLEN, 141 macvlan_count_rx(vlan, skb->len + ETH_HLEN,
181 err == NET_RX_SUCCESS, 1); 142 err == NET_RX_SUCCESS, 1);
@@ -238,7 +199,7 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
238 skb->dev = dev; 199 skb->dev = dev;
239 skb->pkt_type = PACKET_HOST; 200 skb->pkt_type = PACKET_HOST;
240 201
241 netif_rx(skb); 202 vlan->receive(skb);
242 return NULL; 203 return NULL;
243} 204}
244 205
@@ -260,7 +221,7 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
260 dest = macvlan_hash_lookup(port, eth->h_dest); 221 dest = macvlan_hash_lookup(port, eth->h_dest);
261 if (dest && dest->mode == MACVLAN_MODE_BRIDGE) { 222 if (dest && dest->mode == MACVLAN_MODE_BRIDGE) {
262 unsigned int length = skb->len + ETH_HLEN; 223 unsigned int length = skb->len + ETH_HLEN;
263 int ret = dev_forward_skb(dest->dev, skb); 224 int ret = dest->forward(dest->dev, skb);
264 macvlan_count_rx(dest, length, 225 macvlan_count_rx(dest, length,
265 ret == NET_RX_SUCCESS, 0); 226 ret == NET_RX_SUCCESS, 0);
266 227
@@ -273,8 +234,8 @@ xmit_world:
273 return dev_queue_xmit(skb); 234 return dev_queue_xmit(skb);
274} 235}
275 236
276static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb, 237netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
277 struct net_device *dev) 238 struct net_device *dev)
278{ 239{
279 int i = skb_get_queue_mapping(skb); 240 int i = skb_get_queue_mapping(skb);
280 struct netdev_queue *txq = netdev_get_tx_queue(dev, i); 241 struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
@@ -290,6 +251,7 @@ static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
290 251
291 return ret; 252 return ret;
292} 253}
254EXPORT_SYMBOL_GPL(macvlan_start_xmit);
293 255
294static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev, 256static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
295 unsigned short type, const void *daddr, 257 unsigned short type, const void *daddr,
@@ -623,8 +585,11 @@ static int macvlan_get_tx_queues(struct net *net,
623 return 0; 585 return 0;
624} 586}
625 587
626static int macvlan_newlink(struct net *src_net, struct net_device *dev, 588int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
627 struct nlattr *tb[], struct nlattr *data[]) 589 struct nlattr *tb[], struct nlattr *data[],
590 int (*receive)(struct sk_buff *skb),
591 int (*forward)(struct net_device *dev,
592 struct sk_buff *skb))
628{ 593{
629 struct macvlan_dev *vlan = netdev_priv(dev); 594 struct macvlan_dev *vlan = netdev_priv(dev);
630 struct macvlan_port *port; 595 struct macvlan_port *port;
@@ -664,6 +629,8 @@ static int macvlan_newlink(struct net *src_net, struct net_device *dev,
664 vlan->lowerdev = lowerdev; 629 vlan->lowerdev = lowerdev;
665 vlan->dev = dev; 630 vlan->dev = dev;
666 vlan->port = port; 631 vlan->port = port;
632 vlan->receive = receive;
633 vlan->forward = forward;
667 634
668 vlan->mode = MACVLAN_MODE_VEPA; 635 vlan->mode = MACVLAN_MODE_VEPA;
669 if (data && data[IFLA_MACVLAN_MODE]) 636 if (data && data[IFLA_MACVLAN_MODE])
@@ -677,8 +644,17 @@ static int macvlan_newlink(struct net *src_net, struct net_device *dev,
677 netif_stacked_transfer_operstate(lowerdev, dev); 644 netif_stacked_transfer_operstate(lowerdev, dev);
678 return 0; 645 return 0;
679} 646}
647EXPORT_SYMBOL_GPL(macvlan_common_newlink);
680 648
681static void macvlan_dellink(struct net_device *dev, struct list_head *head) 649static int macvlan_newlink(struct net *src_net, struct net_device *dev,
650 struct nlattr *tb[], struct nlattr *data[])
651{
652 return macvlan_common_newlink(src_net, dev, tb, data,
653 netif_rx,
654 dev_forward_skb);
655}
656
657void macvlan_dellink(struct net_device *dev, struct list_head *head)
682{ 658{
683 struct macvlan_dev *vlan = netdev_priv(dev); 659 struct macvlan_dev *vlan = netdev_priv(dev);
684 struct macvlan_port *port = vlan->port; 660 struct macvlan_port *port = vlan->port;
@@ -689,6 +665,7 @@ static void macvlan_dellink(struct net_device *dev, struct list_head *head)
689 if (list_empty(&port->vlans)) 665 if (list_empty(&port->vlans))
690 macvlan_port_destroy(port->dev); 666 macvlan_port_destroy(port->dev);
691} 667}
668EXPORT_SYMBOL_GPL(macvlan_dellink);
692 669
693static int macvlan_changelink(struct net_device *dev, 670static int macvlan_changelink(struct net_device *dev,
694 struct nlattr *tb[], struct nlattr *data[]) 671 struct nlattr *tb[], struct nlattr *data[])
@@ -720,19 +697,27 @@ static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = {
720 [IFLA_MACVLAN_MODE] = { .type = NLA_U32 }, 697 [IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
721}; 698};
722 699
723static struct rtnl_link_ops macvlan_link_ops __read_mostly = { 700int macvlan_link_register(struct rtnl_link_ops *ops)
701{
702 /* common fields */
703 ops->priv_size = sizeof(struct macvlan_dev);
704 ops->get_tx_queues = macvlan_get_tx_queues;
705 ops->setup = macvlan_setup;
706 ops->validate = macvlan_validate;
707 ops->maxtype = IFLA_MACVLAN_MAX;
708 ops->policy = macvlan_policy;
709 ops->changelink = macvlan_changelink;
710 ops->get_size = macvlan_get_size;
711 ops->fill_info = macvlan_fill_info;
712
713 return rtnl_link_register(ops);
714};
715EXPORT_SYMBOL_GPL(macvlan_link_register);
716
717static struct rtnl_link_ops macvlan_link_ops = {
724 .kind = "macvlan", 718 .kind = "macvlan",
725 .priv_size = sizeof(struct macvlan_dev),
726 .get_tx_queues = macvlan_get_tx_queues,
727 .setup = macvlan_setup,
728 .validate = macvlan_validate,
729 .newlink = macvlan_newlink, 719 .newlink = macvlan_newlink,
730 .dellink = macvlan_dellink, 720 .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,
736}; 721};
737 722
738static int macvlan_device_event(struct notifier_block *unused, 723static int macvlan_device_event(struct notifier_block *unused,
@@ -761,7 +746,7 @@ static int macvlan_device_event(struct notifier_block *unused,
761 break; 746 break;
762 case NETDEV_UNREGISTER: 747 case NETDEV_UNREGISTER:
763 list_for_each_entry_safe(vlan, next, &port->vlans, list) 748 list_for_each_entry_safe(vlan, next, &port->vlans, list)
764 macvlan_dellink(vlan->dev, NULL); 749 vlan->dev->rtnl_link_ops->dellink(vlan->dev, NULL);
765 break; 750 break;
766 } 751 }
767 return NOTIFY_DONE; 752 return NOTIFY_DONE;
@@ -778,7 +763,7 @@ static int __init macvlan_init_module(void)
778 register_netdevice_notifier(&macvlan_notifier_block); 763 register_netdevice_notifier(&macvlan_notifier_block);
779 macvlan_handle_frame_hook = macvlan_handle_frame; 764 macvlan_handle_frame_hook = macvlan_handle_frame;
780 765
781 err = rtnl_link_register(&macvlan_link_ops); 766 err = macvlan_link_register(&macvlan_link_ops);
782 if (err < 0) 767 if (err < 0)
783 goto err1; 768 goto err1;
784 return 0; 769 return 0;
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index 5f200bac3749..9a11544bb0b1 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -1,6 +1,76 @@
1#ifndef _LINUX_IF_MACVLAN_H 1#ifndef _LINUX_IF_MACVLAN_H
2#define _LINUX_IF_MACVLAN_H 2#define _LINUX_IF_MACVLAN_H
3 3
4#include <linux/if_link.h>
5#include <linux/list.h>
6#include <linux/netdevice.h>
7#include <linux/netlink.h>
8#include <net/netlink.h>
9
10struct macvlan_port;
11struct macvtap_queue;
12
13/**
14 * struct macvlan_rx_stats - MACVLAN percpu rx stats
15 * @rx_packets: number of received packets
16 * @rx_bytes: number of received bytes
17 * @multicast: number of received multicast packets
18 * @rx_errors: number of errors
19 */
20struct macvlan_rx_stats {
21 unsigned long rx_packets;
22 unsigned long rx_bytes;
23 unsigned long multicast;
24 unsigned long rx_errors;
25};
26
27struct macvlan_dev {
28 struct net_device *dev;
29 struct list_head list;
30 struct hlist_node hlist;
31 struct macvlan_port *port;
32 struct net_device *lowerdev;
33 struct macvlan_rx_stats *rx_stats;
34 enum macvlan_mode mode;
35 int (*receive)(struct sk_buff *skb);
36 int (*forward)(struct net_device *dev, struct sk_buff *skb);
37};
38
39static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
40 unsigned int len, bool success,
41 bool multicast)
42{
43 struct macvlan_rx_stats *rx_stats;
44
45 rx_stats = per_cpu_ptr(vlan->rx_stats, smp_processor_id());
46 if (likely(success)) {
47 rx_stats->rx_packets++;;
48 rx_stats->rx_bytes += len;
49 if (multicast)
50 rx_stats->multicast++;
51 } else {
52 rx_stats->rx_errors++;
53 }
54}
55
56extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
57 struct nlattr *tb[], struct nlattr *data[],
58 int (*receive)(struct sk_buff *skb),
59 int (*forward)(struct net_device *dev,
60 struct sk_buff *skb));
61
62extern void macvlan_count_rx(const struct macvlan_dev *vlan,
63 unsigned int len, bool success,
64 bool multicast);
65
66extern void macvlan_dellink(struct net_device *dev, struct list_head *head);
67
68extern int macvlan_link_register(struct rtnl_link_ops *ops);
69
70extern netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
71 struct net_device *dev);
72
73
4extern struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *); 74extern struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *);
5 75
6#endif /* _LINUX_IF_MACVLAN_H */ 76#endif /* _LINUX_IF_MACVLAN_H */