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>
This commit is contained in:
parent
618e1b7482
commit
27c0b1a850
2 changed files with 65 additions and 6 deletions
|
@ -33,12 +33,6 @@
|
||||||
|
|
||||||
#define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE)
|
#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 macvlan_port {
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
struct hlist_head vlan_hash[MACVLAN_HASH_SIZE];
|
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])))
|
if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
|
||||||
return -EADDRNOTAVAIL;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,6 +683,10 @@ static int macvlan_newlink(struct net *src_net, struct net_device *dev,
|
||||||
vlan->dev = dev;
|
vlan->dev = dev;
|
||||||
vlan->port = port;
|
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);
|
err = register_netdevice(dev);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
@ -699,6 +708,36 @@ static void macvlan_dellink(struct net_device *dev, struct list_head *head)
|
||||||
macvlan_port_destroy(port->dev);
|
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 = {
|
static struct rtnl_link_ops macvlan_link_ops __read_mostly = {
|
||||||
.kind = "macvlan",
|
.kind = "macvlan",
|
||||||
.priv_size = sizeof(struct macvlan_dev),
|
.priv_size = sizeof(struct macvlan_dev),
|
||||||
|
@ -707,6 +746,11 @@ static struct rtnl_link_ops macvlan_link_ops __read_mostly = {
|
||||||
.validate = macvlan_validate,
|
.validate = macvlan_validate,
|
||||||
.newlink = macvlan_newlink,
|
.newlink = macvlan_newlink,
|
||||||
.dellink = macvlan_dellink,
|
.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,
|
static int macvlan_device_event(struct notifier_block *unused,
|
||||||
|
|
|
@ -181,4 +181,19 @@ struct ifla_vlan_qos_mapping {
|
||||||
__u32 to;
|
__u32 to;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* MACVLAN section */
|
||||||
|
enum {
|
||||||
|
IFLA_MACVLAN_UNSPEC,
|
||||||
|
IFLA_MACVLAN_MODE,
|
||||||
|
__IFLA_MACVLAN_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define IFLA_MACVLAN_MAX (__IFLA_MACVLAN_MAX - 1)
|
||||||
|
|
||||||
|
enum macvlan_mode {
|
||||||
|
MACVLAN_MODE_PRIVATE = 1, /* don't talk to other macvlans */
|
||||||
|
MACVLAN_MODE_VEPA = 2, /* talk to other ports through ext bridge */
|
||||||
|
MACVLAN_MODE_BRIDGE = 4, /* talk to bridge ports directly */
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* _LINUX_IF_LINK_H */
|
#endif /* _LINUX_IF_LINK_H */
|
||||||
|
|
Loading…
Reference in a new issue