Subject: Re: [PATCH] vlan: fix the bug that cannot create vlan4095

From: Ido Schimmel <[email-masked]>
Date: Mon, 18 May 2020 10:01:36 +0300

On Mon, May 18, 2020 at 01:27:55PM +0800, Huang Qijun wrote:
> According to the 8021q standard, the VLAN id range is 1 to 4095.

No, on IEEE8021VlanIndex the standard says:

"A value used to index per-VLAN tables: values of 0 and 4095 are not
permitted. If the value is between 1 and 4094 inclusive, it represents
an IEEE 802.1Q VLAN-ID with global scope within a given bridged domain
(see VlanId textual convention). If the value is greater than 4095, then
it represents a VLAN with scope local to the particular agent, i.e., one
without a global VLAN-ID assigned to it. Such VLANs are outside the
scope of IEEE 802.1Q, but it is convenient to be able to manage them"

>From Wikipedia as well:

"A 12-bit field specifying the VLAN to which the frame belongs. The
hexadecimal values of 0x000 and 0xFFF are reserved. All other values may
be used as VLAN identifiers, allowing up to 4,094 VLANs. [...] The VID
value 0xFFF is reserved for implementation use; it must not be
configured or transmitted. 0xFFF can be used to indicate a wildcard
match in management operations or filtering database entries."

https://en.wikipedia.org/wiki/IEEE_802.1Q

> But in the register_vlan_device function, the range is 1 to 4094,
> because ">= VLAN_VID_MASK" is used to determine whether the id
> is illegal. This will prevent the creation of the vlan4095 interface:
>     $ vconfig add sit0 4095
>     vconfig: ioctl error for add: Numerical result out of range
> 
> To fix this error, this patch uses ">= VLAN_N_VID" instead to
> determine if the id is illegal.
> 
> Signed-off-by: Huang Qijun <[email-masked]>
> ---
>  net/8021q/vlan.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
> index d4bcfd8f95bf..5de7861ddf64 100644
> --- a/net/8021q/vlan.c
> +++ b/net/8021q/vlan.c
> @@ -219,7 +219,7 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
>  	char name[IFNAMSIZ];
>  	int err;
>  
> -	if (vlan_id >= VLAN_VID_MASK)
> +	if (vlan_id >= VLAN_N_VID)
>  		return -ERANGE;
>  
>  	err = vlan_check_real_dev(real_dev, htons(ETH_P_8021Q), vlan_id,
> -- 
> 2.17.1
>