Commit fc0663d6b5e6d8e9b57f872a644c0aafd82361b7

Authored by Arnd Bergmann
Committed by David S. Miller
1 parent 8a83a00b07

macvlan: allow multiple driver backends

This makes it possible to hook into the macvlan driver
from another kernel module. In particular, the goal is
to extend it with the macvtap backend that provides
a tun/tap compatible interface directly on the macvlan
device.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 2 changed files with 119 additions and 64 deletions Side-by-side Diff

drivers/net/macvlan.c
... ... @@ -39,31 +39,6 @@
39 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   - */
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   -
56   -struct 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   -
67 42 static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port,
68 43 const unsigned char *addr)
69 44 {
70 45  
71 46  
72 47  
... ... @@ -118,31 +93,17 @@
118 93 return 0;
119 94 }
120 95  
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 96  
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,
  97 +static int macvlan_broadcast_one(struct sk_buff *skb,
  98 + const struct macvlan_dev *vlan,
139 99 const struct ethhdr *eth, bool local)
140 100 {
  101 + struct net_device *dev = vlan->dev;
141 102 if (!skb)
142 103 return NET_RX_DROP;
143 104  
144 105 if (local)
145   - return dev_forward_skb(dev, skb);
  106 + return vlan->forward(dev, skb);
146 107  
147 108 skb->dev = dev;
148 109 if (!compare_ether_addr_64bits(eth->h_dest,
... ... @@ -151,7 +112,7 @@
151 112 else
152 113 skb->pkt_type = PACKET_MULTICAST;
153 114  
154   - return netif_rx(skb);
  115 + return vlan->receive(skb);
155 116 }
156 117  
157 118 static void macvlan_broadcast(struct sk_buff *skb,
... ... @@ -175,7 +136,7 @@
175 136 continue;
176 137  
177 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 140 mode == MACVLAN_MODE_BRIDGE);
180 141 macvlan_count_rx(vlan, skb->len + ETH_HLEN,
181 142 err == NET_RX_SUCCESS, 1);
... ... @@ -238,7 +199,7 @@
238 199 skb->dev = dev;
239 200 skb->pkt_type = PACKET_HOST;
240 201  
241   - netif_rx(skb);
  202 + vlan->receive(skb);
242 203 return NULL;
243 204 }
244 205  
... ... @@ -260,7 +221,7 @@
260 221 dest = macvlan_hash_lookup(port, eth->h_dest);
261 222 if (dest && dest->mode == MACVLAN_MODE_BRIDGE) {
262 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 225 macvlan_count_rx(dest, length,
265 226 ret == NET_RX_SUCCESS, 0);
266 227  
... ... @@ -273,8 +234,8 @@
273 234 return dev_queue_xmit(skb);
274 235 }
275 236  
276   -static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
277   - struct net_device *dev)
  237 +netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
  238 + struct net_device *dev)
278 239 {
279 240 int i = skb_get_queue_mapping(skb);
280 241 struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
... ... @@ -290,6 +251,7 @@
290 251  
291 252 return ret;
292 253 }
  254 +EXPORT_SYMBOL_GPL(macvlan_start_xmit);
293 255  
294 256 static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
295 257 unsigned short type, const void *daddr,
... ... @@ -623,8 +585,11 @@
623 585 return 0;
624 586 }
625 587  
626   -static int macvlan_newlink(struct net *src_net, struct net_device *dev,
627   - struct nlattr *tb[], struct nlattr *data[])
  588 +int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
  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 594 struct macvlan_dev *vlan = netdev_priv(dev);
630 595 struct macvlan_port *port;
... ... @@ -664,6 +629,8 @@
664 629 vlan->lowerdev = lowerdev;
665 630 vlan->dev = dev;
666 631 vlan->port = port;
  632 + vlan->receive = receive;
  633 + vlan->forward = forward;
667 634  
668 635 vlan->mode = MACVLAN_MODE_VEPA;
669 636 if (data && data[IFLA_MACVLAN_MODE])
670 637  
671 638  
... ... @@ -677,9 +644,18 @@
677 644 netif_stacked_transfer_operstate(lowerdev, dev);
678 645 return 0;
679 646 }
  647 +EXPORT_SYMBOL_GPL(macvlan_common_newlink);
680 648  
681   -static void macvlan_dellink(struct net_device *dev, struct list_head *head)
  649 +static int macvlan_newlink(struct net *src_net, struct net_device *dev,
  650 + struct nlattr *tb[], struct nlattr *data[])
682 651 {
  652 + return macvlan_common_newlink(src_net, dev, tb, data,
  653 + netif_rx,
  654 + dev_forward_skb);
  655 +}
  656 +
  657 +void macvlan_dellink(struct net_device *dev, struct list_head *head)
  658 +{
683 659 struct macvlan_dev *vlan = netdev_priv(dev);
684 660 struct macvlan_port *port = vlan->port;
685 661  
... ... @@ -689,6 +665,7 @@
689 665 if (list_empty(&port->vlans))
690 666 macvlan_port_destroy(port->dev);
691 667 }
  668 +EXPORT_SYMBOL_GPL(macvlan_dellink);
692 669  
693 670 static int macvlan_changelink(struct net_device *dev,
694 671 struct nlattr *tb[], struct nlattr *data[])
695 672  
696 673  
... ... @@ -720,19 +697,27 @@
720 697 [IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
721 698 };
722 699  
723   -static struct rtnl_link_ops macvlan_link_ops __read_mostly = {
  700 +int 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 +};
  715 +EXPORT_SYMBOL_GPL(macvlan_link_register);
  716 +
  717 +static struct rtnl_link_ops macvlan_link_ops = {
724 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 719 .newlink = macvlan_newlink,
730 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  
738 723 static int macvlan_device_event(struct notifier_block *unused,
... ... @@ -761,7 +746,7 @@
761 746 break;
762 747 case NETDEV_UNREGISTER:
763 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 750 break;
766 751 }
767 752 return NOTIFY_DONE;
... ... @@ -778,7 +763,7 @@
778 763 register_netdevice_notifier(&macvlan_notifier_block);
779 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 767 if (err < 0)
783 768 goto err1;
784 769 return 0;
include/linux/if_macvlan.h
1 1 #ifndef _LINUX_IF_MACVLAN_H
2 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 +
  10 +struct macvlan_port;
  11 +struct 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 + */
  20 +struct macvlan_rx_stats {
  21 + unsigned long rx_packets;
  22 + unsigned long rx_bytes;
  23 + unsigned long multicast;
  24 + unsigned long rx_errors;
  25 +};
  26 +
  27 +struct 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 +
  39 +static 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 +
  56 +extern 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 +
  62 +extern void macvlan_count_rx(const struct macvlan_dev *vlan,
  63 + unsigned int len, bool success,
  64 + bool multicast);
  65 +
  66 +extern void macvlan_dellink(struct net_device *dev, struct list_head *head);
  67 +
  68 +extern int macvlan_link_register(struct rtnl_link_ops *ops);
  69 +
  70 +extern netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
  71 + struct net_device *dev);
  72 +
  73 +
4 74 extern struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *);
5 75  
6 76 #endif /* _LINUX_IF_MACVLAN_H */