diff options
-rw-r--r-- | drivers/net/macvlan.c | 56 | ||||
-rw-r--r-- | include/linux/if_link.h | 15 |
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 | ||
36 | enum macvlan_mode { | ||
37 | MACVLAN_MODE_PRIVATE = 1, | ||
38 | MACVLAN_MODE_VEPA = 2, | ||
39 | MACVLAN_MODE_BRIDGE = 4, | ||
40 | }; | ||
41 | |||
42 | struct macvlan_port { | 36 | struct 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 | ||
711 | static 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 | |||
720 | static size_t macvlan_get_size(const struct net_device *dev) | ||
721 | { | ||
722 | return nla_total_size(4); | ||
723 | } | ||
724 | |||
725 | static 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 | |||
733 | nla_put_failure: | ||
734 | return -EMSGSIZE; | ||
735 | } | ||
736 | |||
737 | static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = { | ||
738 | [IFLA_MACVLAN_MODE] = { .type = NLA_U32 }, | ||
739 | }; | ||
740 | |||
702 | static struct rtnl_link_ops macvlan_link_ops __read_mostly = { | 741 | static 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 | ||
712 | static int macvlan_device_event(struct notifier_block *unused, | 756 | static 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 */ | ||
185 | enum { | ||
186 | IFLA_MACVLAN_UNSPEC, | ||
187 | IFLA_MACVLAN_MODE, | ||
188 | __IFLA_MACVLAN_MAX, | ||
189 | }; | ||
190 | |||
191 | #define IFLA_MACVLAN_MAX (__IFLA_MACVLAN_MAX - 1) | ||
192 | |||
193 | enum 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 */ |