aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2009-11-26 01:07:11 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-26 18:53:10 -0500
commit27c0b1a850cdea6298f573d835782f3337be913c (patch)
tree447d5db320dfa2d558a73f841c76b04b975e6ee0
parent618e1b7482f7a8a4c6c6e8ccbe140e4c331df4e9 (diff)
macvlan: export macvlan mode through netlink
In order to support all three modes of macvlan at runtime, extend the existing netlink protocol to allow choosing the mode per macvlan slave interface. This depends on a matching patch to iproute2 in order to become accessible in user land. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/macvlan.c56
-rw-r--r--include/linux/if_link.h15
2 files changed, 65 insertions, 6 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index d6bd84353f44..322112c7358a 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -33,12 +33,6 @@
33 33
34#define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE) 34#define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE)
35 35
36enum macvlan_mode {
37 MACVLAN_MODE_PRIVATE = 1,
38 MACVLAN_MODE_VEPA = 2,
39 MACVLAN_MODE_BRIDGE = 4,
40};
41
42struct macvlan_port { 36struct macvlan_port {
43 struct net_device *dev; 37 struct net_device *dev;
44 struct hlist_head vlan_hash[MACVLAN_HASH_SIZE]; 38 struct hlist_head vlan_hash[MACVLAN_HASH_SIZE];
@@ -614,6 +608,17 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
614 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) 608 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
615 return -EADDRNOTAVAIL; 609 return -EADDRNOTAVAIL;
616 } 610 }
611
612 if (data && data[IFLA_MACVLAN_MODE]) {
613 switch (nla_get_u32(data[IFLA_MACVLAN_MODE])) {
614 case MACVLAN_MODE_PRIVATE:
615 case MACVLAN_MODE_VEPA:
616 case MACVLAN_MODE_BRIDGE:
617 break;
618 default:
619 return -EINVAL;
620 }
621 }
617 return 0; 622 return 0;
618} 623}
619 624
@@ -678,6 +683,10 @@ static int macvlan_newlink(struct net *src_net, struct net_device *dev,
678 vlan->dev = dev; 683 vlan->dev = dev;
679 vlan->port = port; 684 vlan->port = port;
680 685
686 vlan->mode = MACVLAN_MODE_VEPA;
687 if (data && data[IFLA_MACVLAN_MODE])
688 vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
689
681 err = register_netdevice(dev); 690 err = register_netdevice(dev);
682 if (err < 0) 691 if (err < 0)
683 return err; 692 return err;
@@ -699,6 +708,36 @@ static void macvlan_dellink(struct net_device *dev, struct list_head *head)
699 macvlan_port_destroy(port->dev); 708 macvlan_port_destroy(port->dev);
700} 709}
701 710
711static int macvlan_changelink(struct net_device *dev,
712 struct nlattr *tb[], struct nlattr *data[])
713{
714 struct macvlan_dev *vlan = netdev_priv(dev);
715 if (data && data[IFLA_MACVLAN_MODE])
716 vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
717 return 0;
718}
719
720static size_t macvlan_get_size(const struct net_device *dev)
721{
722 return nla_total_size(4);
723}
724
725static int macvlan_fill_info(struct sk_buff *skb,
726 const struct net_device *dev)
727{
728 struct macvlan_dev *vlan = netdev_priv(dev);
729
730 NLA_PUT_U32(skb, IFLA_MACVLAN_MODE, vlan->mode);
731 return 0;
732
733nla_put_failure:
734 return -EMSGSIZE;
735}
736
737static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = {
738 [IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
739};
740
702static struct rtnl_link_ops macvlan_link_ops __read_mostly = { 741static struct rtnl_link_ops macvlan_link_ops __read_mostly = {
703 .kind = "macvlan", 742 .kind = "macvlan",
704 .priv_size = sizeof(struct macvlan_dev), 743 .priv_size = sizeof(struct macvlan_dev),
@@ -707,6 +746,11 @@ static struct rtnl_link_ops macvlan_link_ops __read_mostly = {
707 .validate = macvlan_validate, 746 .validate = macvlan_validate,
708 .newlink = macvlan_newlink, 747 .newlink = macvlan_newlink,
709 .dellink = macvlan_dellink, 748 .dellink = macvlan_dellink,
749 .maxtype = IFLA_MACVLAN_MAX,
750 .policy = macvlan_policy,
751 .changelink = macvlan_changelink,
752 .get_size = macvlan_get_size,
753 .fill_info = macvlan_fill_info,
710}; 754};
711 755
712static int macvlan_device_event(struct notifier_block *unused, 756static int macvlan_device_event(struct notifier_block *unused,
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 1d3b2425f661..6674791622ca 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -181,4 +181,19 @@ struct ifla_vlan_qos_mapping {
181 __u32 to; 181 __u32 to;
182}; 182};
183 183
184/* MACVLAN section */
185enum {
186 IFLA_MACVLAN_UNSPEC,
187 IFLA_MACVLAN_MODE,
188 __IFLA_MACVLAN_MAX,
189};
190
191#define IFLA_MACVLAN_MAX (__IFLA_MACVLAN_MAX - 1)
192
193enum macvlan_mode {
194 MACVLAN_MODE_PRIVATE = 1, /* don't talk to other macvlans */
195 MACVLAN_MODE_VEPA = 2, /* talk to other ports through ext bridge */
196 MACVLAN_MODE_BRIDGE = 4, /* talk to bridge ports directly */
197};
198
184#endif /* _LINUX_IF_LINK_H */ 199#endif /* _LINUX_IF_LINK_H */