|
@@ -23,6 +23,7 @@ static const struct nla_policy vlan_policy[IFLA_VLAN_MAX + 1] = {
|
|
|
[IFLA_VLAN_FLAGS] = { .len = sizeof(struct ifla_vlan_flags) },
|
|
|
[IFLA_VLAN_EGRESS_QOS] = { .type = NLA_NESTED },
|
|
|
[IFLA_VLAN_INGRESS_QOS] = { .type = NLA_NESTED },
|
|
|
+ [IFLA_VLAN_PROTOCOL] = { .type = NLA_U16 },
|
|
|
};
|
|
|
|
|
|
static const struct nla_policy vlan_map_policy[IFLA_VLAN_QOS_MAX + 1] = {
|
|
@@ -53,6 +54,16 @@ static int vlan_validate(struct nlattr *tb[], struct nlattr *data[])
|
|
|
if (!data)
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ if (data[IFLA_VLAN_PROTOCOL]) {
|
|
|
+ switch (nla_get_be16(data[IFLA_VLAN_PROTOCOL])) {
|
|
|
+ case __constant_htons(ETH_P_8021Q):
|
|
|
+ case __constant_htons(ETH_P_8021AD):
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return -EPROTONOSUPPORT;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if (data[IFLA_VLAN_ID]) {
|
|
|
id = nla_get_u16(data[IFLA_VLAN_ID]);
|
|
|
if (id >= VLAN_VID_MASK)
|
|
@@ -107,6 +118,7 @@ static int vlan_newlink(struct net *src_net, struct net_device *dev,
|
|
|
{
|
|
|
struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
|
|
|
struct net_device *real_dev;
|
|
|
+ __be16 proto;
|
|
|
int err;
|
|
|
|
|
|
if (!data[IFLA_VLAN_ID])
|
|
@@ -118,7 +130,12 @@ static int vlan_newlink(struct net *src_net, struct net_device *dev,
|
|
|
if (!real_dev)
|
|
|
return -ENODEV;
|
|
|
|
|
|
- vlan->vlan_proto = htons(ETH_P_8021Q);
|
|
|
+ if (data[IFLA_VLAN_PROTOCOL])
|
|
|
+ proto = nla_get_be16(data[IFLA_VLAN_PROTOCOL]);
|
|
|
+ else
|
|
|
+ proto = htons(ETH_P_8021Q);
|
|
|
+
|
|
|
+ vlan->vlan_proto = proto;
|
|
|
vlan->vlan_id = nla_get_u16(data[IFLA_VLAN_ID]);
|
|
|
vlan->real_dev = real_dev;
|
|
|
vlan->flags = VLAN_FLAG_REORDER_HDR;
|
|
@@ -152,7 +169,8 @@ static size_t vlan_get_size(const struct net_device *dev)
|
|
|
{
|
|
|
struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
|
|
|
|
|
|
- return nla_total_size(2) + /* IFLA_VLAN_ID */
|
|
|
+ return nla_total_size(2) + /* IFLA_VLAN_PROTOCOL */
|
|
|
+ nla_total_size(2) + /* IFLA_VLAN_ID */
|
|
|
sizeof(struct ifla_vlan_flags) + /* IFLA_VLAN_FLAGS */
|
|
|
vlan_qos_map_size(vlan->nr_ingress_mappings) +
|
|
|
vlan_qos_map_size(vlan->nr_egress_mappings);
|
|
@@ -167,7 +185,8 @@ static int vlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
|
|
|
struct nlattr *nest;
|
|
|
unsigned int i;
|
|
|
|
|
|
- if (nla_put_u16(skb, IFLA_VLAN_ID, vlan_dev_priv(dev)->vlan_id))
|
|
|
+ if (nla_put_be16(skb, IFLA_VLAN_PROTOCOL, vlan->vlan_proto) ||
|
|
|
+ nla_put_u16(skb, IFLA_VLAN_ID, vlan->vlan_id))
|
|
|
goto nla_put_failure;
|
|
|
if (vlan->flags) {
|
|
|
f.flags = vlan->flags;
|