net/vlan: Allow setting default priority (PCP)

1. We add default PCP because some of our apps may not want to set PCP
   manually (e.g. Our user may just ping with pre-set PCP)
2. The `vlan_qos` is used as PCP when setting Linux's priority mapping:
   https://github.com/torvalds/linux/blob/v6.12/net/8021q/vlan.c#L590
   Although `vlan_qos` is not used when creating VLAN on Linux, we can
   use it as PCP on creating VLAN (without changing its meaning), and
   keep compatible with Linux's creating (Exactly the same when
   `vlan_qos` is 0).

Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
Zhe Weng 2025-02-07 14:25:08 +08:00 committed by Alan C. Assis
parent 2b34bcfcb1
commit 8d7799d6c1
3 changed files with 18 additions and 7 deletions

View file

@ -1156,7 +1156,7 @@ int netdev_upper_vlan_ioctl(FAR struct netdev_lowerhalf_s *lower,
switch (args->cmd)
{
case ADD_VLAN_CMD:
return vlan_register(lower, args->u.VID);
return vlan_register(lower, args->u.VID, args->vlan_qos);
case DEL_VLAN_CMD:
vlan_unregister(lower);

View file

@ -51,7 +51,7 @@ struct vlan_device_s
struct netdev_lowerhalf_s dev;
FAR struct netdev_lowerhalf_s *real;
uint16_t vid;
uint16_t tci;
};
/****************************************************************************
@ -161,7 +161,7 @@ static int vlan_transmit(FAR struct netdev_lowerhalf_s *dev,
vlan_hdr = (FAR struct eth_8021qhdr_s *)netpkt_getdata(dev, pkt);
vlan_hdr->tpid = HTONS(TPID_8021QVLAN);
vlan_hdr->tci = HTONS(vlan->vid);
vlan_hdr->tci = HTONS(vlan->tci);
/* Transmit the packet on the real device */
@ -266,13 +266,15 @@ static void vlan_reclaim(FAR struct netdev_lowerhalf_s *dev)
* Input Parameters:
* real - The real device to which the VLAN is attached
* vid - VLAN ID
* prio - Default VLAN priority (PCP)
*
* Returned Value:
* OK on success; Negated errno on failure.
*
****************************************************************************/
int vlan_register(FAR struct netdev_lowerhalf_s *real, uint16_t vid)
int vlan_register(FAR struct netdev_lowerhalf_s *real, uint16_t vid,
uint16_t prio)
{
FAR struct vlan_device_s *vlan;
char vlanifname[IFNAMSIZ + 8];
@ -283,6 +285,12 @@ int vlan_register(FAR struct netdev_lowerhalf_s *real, uint16_t vid)
return -EINVAL;
}
if (vid >= VLAN_N_VID || prio > (VLAN_PRIO_MASK >> VLAN_PRIO_SHIFT))
{
nerr("ERROR: Invalid VID %" PRIu16 " with PCP %" PRIu16, vid, prio);
return -EINVAL;
}
/* Create a new VLAN device */
vlan = kmm_zalloc(sizeof(struct vlan_device_s));
@ -293,7 +301,8 @@ int vlan_register(FAR struct netdev_lowerhalf_s *real, uint16_t vid)
/* Init the VLAN device */
vlan->vid = vid;
vlan->tci = (vid & VLAN_VID_MASK) |
((prio << VLAN_PRIO_SHIFT) & VLAN_PRIO_MASK);
vlan->real = real;
vlan->dev.quota_ptr = real->quota_ptr;
vlan->dev.ops = &g_vlan_ops;
@ -354,7 +363,7 @@ void vlan_unregister(FAR struct netdev_lowerhalf_s *dev)
return;
}
netdev_lower_vlan_del(vlan->real, vlan->vid);
netdev_lower_vlan_del(vlan->real, vlan->tci & VLAN_VID_MASK);
netdev_lower_unregister(dev);
kmm_free(dev);
}

View file

@ -103,13 +103,15 @@ extern "C"
* Input Parameters:
* real - The real device to which the VLAN is attached
* vid - VLAN ID
* prio - Default VLAN priority (PCP)
*
* Returned Value:
* OK on success; Negated errno on failure.
*
****************************************************************************/
int vlan_register(FAR struct netdev_lowerhalf_s *real, uint16_t vid);
int vlan_register(FAR struct netdev_lowerhalf_s *real, uint16_t vid,
uint16_t prio);
/****************************************************************************
* Name: vlan_unregister