|
@@ -33,12 +33,6 @@
|
|
|
|
|
|
#define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE)
|
|
|
|
|
|
-enum macvlan_mode {
|
|
|
- MACVLAN_MODE_PRIVATE = 1,
|
|
|
- MACVLAN_MODE_VEPA = 2,
|
|
|
- MACVLAN_MODE_BRIDGE = 4,
|
|
|
-};
|
|
|
-
|
|
|
struct macvlan_port {
|
|
|
struct net_device *dev;
|
|
|
struct hlist_head vlan_hash[MACVLAN_HASH_SIZE];
|
|
@@ -614,6 +608,17 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
|
|
|
if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
|
|
|
return -EADDRNOTAVAIL;
|
|
|
}
|
|
|
+
|
|
|
+ if (data && data[IFLA_MACVLAN_MODE]) {
|
|
|
+ switch (nla_get_u32(data[IFLA_MACVLAN_MODE])) {
|
|
|
+ case MACVLAN_MODE_PRIVATE:
|
|
|
+ case MACVLAN_MODE_VEPA:
|
|
|
+ case MACVLAN_MODE_BRIDGE:
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ }
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -678,6 +683,10 @@ static int macvlan_newlink(struct net *src_net, struct net_device *dev,
|
|
|
vlan->dev = dev;
|
|
|
vlan->port = port;
|
|
|
|
|
|
+ vlan->mode = MACVLAN_MODE_VEPA;
|
|
|
+ if (data && data[IFLA_MACVLAN_MODE])
|
|
|
+ vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
|
|
|
+
|
|
|
err = register_netdevice(dev);
|
|
|
if (err < 0)
|
|
|
return err;
|
|
@@ -699,6 +708,36 @@ static void macvlan_dellink(struct net_device *dev, struct list_head *head)
|
|
|
macvlan_port_destroy(port->dev);
|
|
|
}
|
|
|
|
|
|
+static int macvlan_changelink(struct net_device *dev,
|
|
|
+ struct nlattr *tb[], struct nlattr *data[])
|
|
|
+{
|
|
|
+ struct macvlan_dev *vlan = netdev_priv(dev);
|
|
|
+ if (data && data[IFLA_MACVLAN_MODE])
|
|
|
+ vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static size_t macvlan_get_size(const struct net_device *dev)
|
|
|
+{
|
|
|
+ return nla_total_size(4);
|
|
|
+}
|
|
|
+
|
|
|
+static int macvlan_fill_info(struct sk_buff *skb,
|
|
|
+ const struct net_device *dev)
|
|
|
+{
|
|
|
+ struct macvlan_dev *vlan = netdev_priv(dev);
|
|
|
+
|
|
|
+ NLA_PUT_U32(skb, IFLA_MACVLAN_MODE, vlan->mode);
|
|
|
+ return 0;
|
|
|
+
|
|
|
+nla_put_failure:
|
|
|
+ return -EMSGSIZE;
|
|
|
+}
|
|
|
+
|
|
|
+static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = {
|
|
|
+ [IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
|
|
|
+};
|
|
|
+
|
|
|
static struct rtnl_link_ops macvlan_link_ops __read_mostly = {
|
|
|
.kind = "macvlan",
|
|
|
.priv_size = sizeof(struct macvlan_dev),
|
|
@@ -707,6 +746,11 @@ static struct rtnl_link_ops macvlan_link_ops __read_mostly = {
|
|
|
.validate = macvlan_validate,
|
|
|
.newlink = macvlan_newlink,
|
|
|
.dellink = macvlan_dellink,
|
|
|
+ .maxtype = IFLA_MACVLAN_MAX,
|
|
|
+ .policy = macvlan_policy,
|
|
|
+ .changelink = macvlan_changelink,
|
|
|
+ .get_size = macvlan_get_size,
|
|
|
+ .fill_info = macvlan_fill_info,
|
|
|
};
|
|
|
|
|
|
static int macvlan_device_event(struct notifier_block *unused,
|