This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 242c25317872b93020c444ace834806e60ddad95 Author: Zhe Weng <[email protected]> AuthorDate: Tue Jan 7 11:04:53 2025 +0800 net: Add VLAN device support Inspired by Linux's way, we also create VLAN devices for managing VLAN, which will become interfaces like `eth0.58`. QinQ is also supported, we can create VLAN devices above another VLAN devices, like `eth0.100.101` (or even `eth0.1.2.3.4`, also supported on Linux). Signed-off-by: Zhe Weng <[email protected]> --- .../components/drivers/special/net/index.rst | 2 +- .../components/drivers/special/net/vlan.rst | 17 + drivers/net/CMakeLists.txt | 4 + drivers/net/Make.defs | 4 + drivers/net/netdev_upperhalf.c | 233 ++++++++++++- drivers/net/vlan.c | 362 +++++++++++++++++++++ include/nuttx/net/netdev_lowerhalf.h | 38 +++ include/nuttx/net/vlan.h | 107 ++++++ net/Kconfig | 21 ++ 9 files changed, 775 insertions(+), 13 deletions(-) diff --git a/Documentation/components/drivers/special/net/index.rst b/Documentation/components/drivers/special/net/index.rst index 483b70b4a12..03ec5461bae 100644 --- a/Documentation/components/drivers/special/net/index.rst +++ b/Documentation/components/drivers/special/net/index.rst @@ -11,4 +11,4 @@ Network interface drivers :caption: Supported Drivers ethernet.rst - + vlan.rst diff --git a/Documentation/components/drivers/special/net/vlan.rst b/Documentation/components/drivers/special/net/vlan.rst new file mode 100644 index 00000000000..186f6d27091 --- /dev/null +++ b/Documentation/components/drivers/special/net/vlan.rst @@ -0,0 +1,17 @@ +=================== +Vlan Device Drivers +=================== + +- ``include/nuttx/net/vlan.h``. All structures and APIs + needed to work with Vlan drivers are provided in this + header file. +- we also create VLAN devices for managing VLAN, which will become + interfaces like ``eth0.58`` +- QinQ is also supported, we can create VLAN devices above another VLAN + devices, like ``eth0.100.101`` (or even ``eth0.1.2.3.4``, also supported + on Linux). +- Supporting ADD_VLAN_CMD and DEL_VLAN_CMD of SIOCSIFVLAN. +- We add default PCP because some of our apps may not want to set + PCP manually + +- **Driver**: ``drivers/net/vlan.c`` diff --git a/drivers/net/CMakeLists.txt b/drivers/net/CMakeLists.txt index 5120c29d4d1..c8b9fcf1466 100644 --- a/drivers/net/CMakeLists.txt +++ b/drivers/net/CMakeLists.txt @@ -65,6 +65,10 @@ if(CONFIG_NET) list(APPEND SRCS tun.c) endif() + if(CONFIG_NET_VLAN) + list(APPEND SRCS vlan.c) + endif() + if(CONFIG_NET_FTMAC100) list(APPEND SRCS ftmac100.c) endif() diff --git a/drivers/net/Make.defs b/drivers/net/Make.defs index a5f18c71276..9dc64e5c641 100644 --- a/drivers/net/Make.defs +++ b/drivers/net/Make.defs @@ -66,6 +66,10 @@ ifeq ($(CONFIG_NET_TUN),y) CSRCS += tun.c endif +ifeq ($(CONFIG_NET_VLAN),y) + CSRCS += vlan.c +endif + ifeq ($(CONFIG_NET_FTMAC100),y) CSRCS += ftmac100.c endif diff --git a/drivers/net/netdev_upperhalf.c b/drivers/net/netdev_upperhalf.c index e102c0b9c6f..3c6bd282bae 100644 --- a/drivers/net/netdev_upperhalf.c +++ b/drivers/net/netdev_upperhalf.c @@ -39,6 +39,7 @@ #include <nuttx/net/net.h> #include <nuttx/net/netdev_lowerhalf.h> #include <nuttx/net/pkt.h> +#include <nuttx/net/vlan.h> #include <nuttx/semaphore.h> #include <nuttx/spinlock.h> @@ -66,6 +67,14 @@ * Private Types ****************************************************************************/ +#ifdef CONFIG_NET_VLAN +struct netdev_vlan_entry_s +{ + FAR struct netdev_lowerhalf_s *dev; + uint16_t vid; +}; +#endif + /* This structure describes the state of the upper half driver */ struct netdev_upperhalf_s @@ -87,8 +96,18 @@ struct netdev_upperhalf_s #if CONFIG_IOB_NCHAINS > 0 struct iob_queue_s txq; #endif + +#ifdef CONFIG_NET_VLAN + struct netdev_vlan_entry_s vlan[CONFIG_NET_VLAN_COUNT]; +#endif }; +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int netdev_upper_txavail(FAR struct net_driver_s *dev); + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -400,6 +419,7 @@ static void netdev_upper_queue_tx(FAR struct net_driver_s *dev) if ((ret = iob_tryadd_queue(dev->d_iob, &upper->txq)) >= 0) { netdev_iob_clear(dev); + netdev_upper_txavail(dev); } else { @@ -413,6 +433,66 @@ static void netdev_upper_queue_tx(FAR struct net_driver_s *dev) } #endif +/**************************************************************************** + * Name: netdev_upper_vlan_dev + * + * Description: + * Get the VLAN device for the VID. + * + * Input Parameters: + * upper - Reference to the upper half driver structure + * vid - VLAN ID + * + * Returned Value: + * Reference to the network device structure, or NULL if not found. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_VLAN +static FAR struct netdev_lowerhalf_s * +netdev_upper_vlan_dev(FAR struct netdev_upperhalf_s *upper, uint16_t vid) +{ + int i; + + for (i = 0; i < CONFIG_NET_VLAN_COUNT; i++) + { + if (upper->vlan[i].vid == vid) + { + return upper->vlan[i].dev; + } + } + + return NULL; +} + +/**************************************************************************** + * Name: netdev_upper_vlan_foreach + * + * Description: + * Call the callback for each VLAN device. + * + * Input Parameters: + * upper - Reference to the upper half driver structure + * cb - The callback function + * + ****************************************************************************/ + +static void +netdev_upper_vlan_foreach(FAR struct netdev_upperhalf_s *upper, + CODE void (*cb)(FAR struct netdev_lowerhalf_s *)) +{ + int i; + + for (i = 0; i < CONFIG_NET_VLAN_COUNT; i++) + { + if (upper->vlan[i].dev) + { + cb(upper->vlan[i].dev); + } + } +} +#endif + /**************************************************************************** * Name: eth_input * @@ -435,21 +515,45 @@ static void eth_input(FAR struct net_driver_s *dev) /* Check if this is an 802.1Q VLAN tagged packet */ - if (eth_hdr->type == HTONS(TPID_8021QVLAN)) +#ifdef CONFIG_NET_VLAN + if (eth_hdr->type == HTONS(ETHERTYPE_VLAN)) { - /* Need to remove the 4 octet VLAN Tag, by moving src and dest - * addresses 4 octets to the right, and then read the actual - * ethertype. The VLAN ID and priority fields are currently - * ignored. - */ + FAR struct netdev_upperhalf_s *upper = dev->d_private; + FAR struct netdev_lowerhalf_s *vlan; + FAR struct eth_8021qhdr_s *vlan_hdr = NETLLBUF; + uint16_t vid = NTOHS(vlan_hdr->tci) & VLAN_VID_MASK; + + vlan = netdev_upper_vlan_dev(upper, vid); + if (vlan) + { + /* Need to remove the 4 octet VLAN Tag, by moving src and dest + * addresses 4 octets to the right, and then read the actual + * ethertype. + */ + + memmove((FAR uint8_t *)eth_hdr + 4, eth_hdr, + offsetof(struct eth_hdr_s, type)); + netdev_iob_release(&vlan->netdev); + vlan->netdev.d_iob = iob_trimhead(dev->d_iob, 4); + vlan->netdev.d_len = dev->d_len - 4; + netdev_iob_clear(dev); - memmove((FAR uint8_t *)eth_hdr + 4, eth_hdr, - offsetof(struct eth_hdr_s, type)); - dev->d_iob = iob_trimhead(dev->d_iob, 4); - dev->d_len -= 4; + /* Then call eth_input again with the new dev */ - eth_hdr = (FAR struct eth_hdr_s *)NETLLBUF; +#ifdef CONFIG_NET_PKT + pkt_input(&vlan->netdev); +#endif + eth_input(&vlan->netdev); + } + else + { + ninfo("INFO: Dropped, unknown vlan id: %d\n", vid); + NETDEV_RXDROPPED(dev); + dev->d_len = 0; + } } + else +#endif /* We only accept IP packets of the configured type and ARP packets */ @@ -1270,6 +1374,11 @@ int netdev_lower_unregister(FAR struct netdev_lowerhalf_s *dev) } upper = (FAR struct netdev_upperhalf_s *)dev->netdev.d_private; + +#ifdef CONFIG_NET_VLAN + netdev_upper_vlan_foreach(upper, vlan_unregister); +#endif + ret = netdev_unregister(&dev->netdev); if (ret < 0) { @@ -1317,6 +1426,11 @@ int netdev_lower_unregister(FAR struct netdev_lowerhalf_s *dev) void netdev_lower_carrier_on(FAR struct netdev_lowerhalf_s *dev) { +#ifdef CONFIG_NET_VLAN + FAR struct netdev_upperhalf_s *upper = dev->netdev.d_private; + netdev_upper_vlan_foreach(upper, netdev_lower_carrier_on); +#endif + netdev_carrier_on(&dev->netdev); } @@ -1334,6 +1448,11 @@ void netdev_lower_carrier_on(FAR struct netdev_lowerhalf_s *dev) void netdev_lower_carrier_off(FAR struct netdev_lowerhalf_s *dev) { +#ifdef CONFIG_NET_VLAN + FAR struct netdev_upperhalf_s *upper = dev->netdev.d_private; + netdev_upper_vlan_foreach(upper, netdev_lower_carrier_off); +#endif + netdev_carrier_off(&dev->netdev); } @@ -1351,6 +1470,10 @@ void netdev_lower_carrier_off(FAR struct netdev_lowerhalf_s *dev) void netdev_lower_rxready(FAR struct netdev_lowerhalf_s *dev) { #if CONFIG_NETDEV_WORK_THREAD_POLLING_PERIOD == 0 + /* Note: Don't need to handle VLAN here, because RX of VLAN is handled in + * eth_input. + */ + netdev_upper_queue_work(&dev->netdev); #endif } @@ -1368,12 +1491,98 @@ void netdev_lower_rxready(FAR struct netdev_lowerhalf_s *dev) void netdev_lower_txdone(FAR struct netdev_lowerhalf_s *dev) { - NETDEV_TXDONE(&dev->netdev); #if CONFIG_NETDEV_WORK_THREAD_POLLING_PERIOD == 0 +# ifdef CONFIG_NET_VLAN + FAR struct netdev_upperhalf_s *upper = dev->netdev.d_private; + netdev_upper_vlan_foreach(upper, netdev_lower_txdone); +# endif + netdev_upper_queue_work(&dev->netdev); #endif + NETDEV_TXDONE(&dev->netdev); } +/**************************************************************************** + * Name: netdev_lower_vlan_add + * + * Description: + * Add a VLAN device to the network device. + * + * Input Parameters: + * dev - The lower half device driver structure + * vid - VLAN ID + * vlan - The VLAN device to add + * + * Returned Value: + * 0:Success; negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_NET_VLAN +int netdev_lower_vlan_add(FAR struct netdev_lowerhalf_s *dev, uint16_t vid, + FAR struct netdev_lowerhalf_s *vlan) +{ + FAR struct netdev_upperhalf_s *upper = dev->netdev.d_private; + FAR struct netdev_vlan_entry_s *entry = NULL; + int i; + + for (i = 0; i < CONFIG_NET_VLAN_COUNT; i++) + { + if (upper->vlan[i].vid == vid) + { + return -EEXIST; + } + + if (upper->vlan[i].vid == 0 && entry == NULL) + { + entry = &upper->vlan[i]; + } + } + + if (entry) + { + entry->vid = vid; + entry->dev = vlan; + return OK; + } + + return -ENOMEM; +} + +/**************************************************************************** + * Name: netdev_lower_vlan_del + * + * Description: + * Delete a VLAN device from the network device. + * + * Input Parameters: + * dev - The lower half device driver structure + * vid - VLAN ID + * + * Returned Value: + * 0:Success; negated errno on failure + * + ****************************************************************************/ + +int netdev_lower_vlan_del(FAR struct netdev_lowerhalf_s *dev, uint16_t vid) +{ + FAR struct netdev_upperhalf_s *upper = dev->netdev.d_private; + int i; + + for (i = 0; i < CONFIG_NET_VLAN_COUNT; i++) + { + if (upper->vlan[i].vid == vid) + { + upper->vlan[i].vid = 0; + upper->vlan[i].dev = NULL; + return OK; + } + } + + return -ENOENT; +} +#endif + /**************************************************************************** * Name: netpkt_alloc * diff --git a/drivers/net/vlan.c b/drivers/net/vlan.c new file mode 100644 index 00000000000..0b0d33f3609 --- /dev/null +++ b/drivers/net/vlan.c @@ -0,0 +1,362 @@ +/**************************************************************************** + * drivers/net/vlan.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#ifdef CONFIG_NET_VLAN + +#include <debug.h> +#include <stdint.h> +#include <stdio.h> + +#include <nuttx/kmalloc.h> +#include <nuttx/net/netdev_lowerhalf.h> +#include <nuttx/net/vlan.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define VLAN_DEV_NAME_FMT "%s.%i" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct vlan_device_s +{ + struct netdev_lowerhalf_s dev; + + FAR struct netdev_lowerhalf_s *real; + uint16_t vid; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int vlan_ifup(FAR struct netdev_lowerhalf_s *dev); +static int vlan_ifdown(FAR struct netdev_lowerhalf_s *dev); +static int vlan_transmit(FAR struct netdev_lowerhalf_s *dev, + FAR netpkt_t *pkt); +static FAR netpkt_t *vlan_receive(FAR struct netdev_lowerhalf_s *dev); +#ifdef CONFIG_NET_MCASTGROUP +static int vlan_addmac(FAR struct netdev_lowerhalf_s *dev, + FAR const uint8_t *mac); +static int vlan_rmmac(FAR struct netdev_lowerhalf_s *dev, + FAR const uint8_t *mac); +#endif +#ifdef CONFIG_NETDEV_IOCTL +static int vlan_ioctl(FAR struct netdev_lowerhalf_s *dev, int cmd, + unsigned long arg); +#endif +static void vlan_reclaim(FAR struct netdev_lowerhalf_s *dev); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct netdev_ops_s g_vlan_ops = +{ + vlan_ifup, /* ifup */ + vlan_ifdown, /* ifdown */ + vlan_transmit, /* transmit */ + vlan_receive, /* receive */ +#ifdef CONFIG_NET_MCASTGROUP + vlan_addmac, /* addmac */ + vlan_rmmac, /* rmmac */ +#endif +#ifdef CONFIG_NETDEV_IOCTL + vlan_ioctl, /* ioctl */ +#endif + vlan_reclaim /* reclaim */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: vlan_ifup + ****************************************************************************/ + +static int vlan_ifup(FAR struct netdev_lowerhalf_s *dev) +{ + FAR struct vlan_device_s *vlan = (FAR struct vlan_device_s *)dev; + FAR struct netdev_lowerhalf_s *real = vlan->real; + + if (IFF_IS_RUNNING(real->netdev.d_flags)) + { + netdev_lower_carrier_on(dev); + } + + return OK; +} + +/**************************************************************************** + * Name: vlan_ifdown + ****************************************************************************/ + +static int vlan_ifdown(FAR struct netdev_lowerhalf_s *dev) +{ + netdev_lower_carrier_off(dev); + return OK; +} + +/**************************************************************************** + * Name: vlan_transmit + ****************************************************************************/ + +static int vlan_transmit(FAR struct netdev_lowerhalf_s *dev, + FAR netpkt_t *pkt) +{ + FAR struct vlan_device_s *vlan = (FAR struct vlan_device_s *)dev; + FAR struct netdev_lowerhalf_s *real = vlan->real; + FAR struct eth_8021qhdr_s *vlan_hdr; + FAR uint8_t *base = netpkt_getbase(pkt); + FAR uint8_t *data = netpkt_getdata(dev, pkt); + + /* Check space for the VLAN tag, normally we want user to set bigger + * CONFIG_NET_LL_GUARDSIZE to allow inserting VLAN tag in the headroom. + */ + + if (data - base < 4) + { + /* TODO: Support backup path for too small CONFIG_NET_LL_GUARDSIZE */ + + nerr("ERROR: No headroom for VLAN tag, please enlarge " + "CONFIG_NET_LL_GUARDSIZE\n"); + return -ENOMEM; + } + + /* Move the data to make space for the VLAN tag */ + + netpkt_copyin(dev, pkt, data, offsetof(struct eth_hdr_s, type), -4); + netpkt_reset_reserved(dev, pkt, data - base - 4); + + /* Set value of the VLAN tag */ + + vlan_hdr = (FAR struct eth_8021qhdr_s *)netpkt_getdata(dev, pkt); + vlan_hdr->tpid = HTONS(TPID_8021QVLAN); + vlan_hdr->tci = HTONS(vlan->vid); + + /* Transmit the packet on the real device */ + + /* TODO: Call pkt_input to allow tcpdump capture tx packet on real dev. */ + + return real->ops->transmit(real, pkt); +} + +/**************************************************************************** + * Name: vlan_receive + ****************************************************************************/ + +static FAR netpkt_t *vlan_receive(FAR struct netdev_lowerhalf_s *dev) +{ + /* VLAN device doesn't receive packets, the real device does. */ + + return NULL; +} + +/**************************************************************************** + * Name: vlan_addmac + ****************************************************************************/ + +#ifdef CONFIG_NET_MCASTGROUP +static int vlan_addmac(FAR struct netdev_lowerhalf_s *dev, + FAR const uint8_t *mac) +{ + FAR struct vlan_device_s *vlan = (FAR struct vlan_device_s *)dev; + FAR struct netdev_lowerhalf_s *real = vlan->real; + + if (real->ops->addmac) + { + return real->ops->addmac(real, mac); + } + + return -ENOSYS; +} + +/**************************************************************************** + * Name: vlan_rmmac + ****************************************************************************/ + +static int vlan_rmmac(FAR struct netdev_lowerhalf_s *dev, + FAR const uint8_t *mac) +{ + FAR struct vlan_device_s *vlan = (FAR struct vlan_device_s *)dev; + FAR struct netdev_lowerhalf_s *real = vlan->real; + + if (real->ops->rmmac) + { + return real->ops->rmmac(real, mac); + } + + return -ENOSYS; +} +#endif + +/**************************************************************************** + * Name: vlan_ioctl + ****************************************************************************/ + +#ifdef CONFIG_NETDEV_IOCTL +static int vlan_ioctl(FAR struct netdev_lowerhalf_s *dev, int cmd, + unsigned long arg) +{ + FAR struct vlan_device_s *vlan = (FAR struct vlan_device_s *)dev; + FAR struct netdev_lowerhalf_s *real = vlan->real; + + /* TODO: Maybe we should only pass some of IOCTL commands. */ + + if (real->ops->ioctl) + { + return real->ops->ioctl(real, cmd, arg); + } + + return -ENOTTY; +} +#endif + +/**************************************************************************** + * Name: vlan_reclaim + ****************************************************************************/ + +static void vlan_reclaim(FAR struct netdev_lowerhalf_s *dev) +{ + FAR struct vlan_device_s *vlan = (FAR struct vlan_device_s *)dev; + FAR struct netdev_lowerhalf_s *real = vlan->real; + + real->ops->reclaim(real); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: vlan_register + * + * Description: + * Create a new VLAN device and register it. + * + * Input Parameters: + * real - The real device to which the VLAN is attached + * vid - VLAN ID + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +int vlan_register(FAR struct netdev_lowerhalf_s *real, uint16_t vid) +{ + FAR struct vlan_device_s *vlan; + char vlanifname[IFNAMSIZ + 8]; + int ret; + + if (real == NULL || real->netdev.d_lltype != NET_LL_ETHERNET) + { + return -EINVAL; + } + + /* Create a new VLAN device */ + + vlan = kmm_zalloc(sizeof(struct vlan_device_s)); + if (vlan == NULL) + { + return -ENOMEM; + } + + /* Init the VLAN device */ + + vlan->vid = vid; + vlan->real = real; + vlan->dev.quota_ptr = real->quota_ptr; + vlan->dev.ops = &g_vlan_ops; + + /* Set the VLAN device name, use a buffer to make compiler happy */ + + snprintf(vlanifname, sizeof(vlanifname), VLAN_DEV_NAME_FMT, + real->netdev.d_ifname, vid); + strlcpy(vlan->dev.netdev.d_ifname, vlanifname, IFNAMSIZ); + + /* Copy the MAC address from the real device */ + + memcpy(vlan->dev.netdev.d_mac.ether.ether_addr_octet, + real->netdev.d_mac.ether.ether_addr_octet, IFHWADDRLEN); + + /* Register the VLAN device */ + + ret = netdev_lower_vlan_add(real, vid, &vlan->dev); + if (ret < 0) + { + goto errout; + } + + ret = netdev_lower_register(&vlan->dev, NET_LL_ETHERNET); + if (ret < 0) + { + netdev_lower_vlan_del(real, vid); + goto errout; + } + + return ret; + +errout: + kmm_free(vlan); + return ret; +} + +/**************************************************************************** + * Name: vlan_unregister + * + * Description: + * Unregister a VLAN device. + * + * Input Parameters: + * dev - The VLAN device to be unregistered. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void vlan_unregister(FAR struct netdev_lowerhalf_s *dev) +{ + FAR struct vlan_device_s *vlan = (FAR struct vlan_device_s *)dev; + + if (vlan == NULL) + { + return; + } + + netdev_lower_vlan_del(vlan->real, vlan->vid); + netdev_lower_unregister(dev); + kmm_free(dev); +} + +#endif /* CONFIG_NET_VLAN */ diff --git a/include/nuttx/net/netdev_lowerhalf.h b/include/nuttx/net/netdev_lowerhalf.h index 3f7785e23c3..dcc52e56e6f 100644 --- a/include/nuttx/net/netdev_lowerhalf.h +++ b/include/nuttx/net/netdev_lowerhalf.h @@ -323,6 +323,44 @@ void netdev_lower_txdone(FAR struct netdev_lowerhalf_s *dev); #define netdev_lower_quota_load(dev, type) atomic_read(&dev->quota[type]) +/**************************************************************************** + * Name: netdev_lower_vlan_add + * + * Description: + * Add a VLAN device to the network device. + * + * Input Parameters: + * dev - The lower half device driver structure + * vid - VLAN ID + * vlan - The VLAN device to add + * + * Returned Value: + * 0:Success; negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_NET_VLAN +int netdev_lower_vlan_add(FAR struct netdev_lowerhalf_s *dev, uint16_t vid, + FAR struct netdev_lowerhalf_s *vlan); + +/**************************************************************************** + * Name: netdev_lower_vlan_del + * + * Description: + * Delete a VLAN device from the network device. + * + * Input Parameters: + * dev - The lower half device driver structure + * vid - VLAN ID + * + * Returned Value: + * 0:Success; negated errno on failure + * + ****************************************************************************/ + +int netdev_lower_vlan_del(FAR struct netdev_lowerhalf_s *dev, uint16_t vid); +#endif + /**************************************************************************** * Name: netpkt_alloc * diff --git a/include/nuttx/net/vlan.h b/include/nuttx/net/vlan.h new file mode 100644 index 00000000000..1085d540534 --- /dev/null +++ b/include/nuttx/net/vlan.h @@ -0,0 +1,107 @@ +/**************************************************************************** + * include/nuttx/net/vlan.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_VLAN_H +#define __INCLUDE_NUTTX_NET_VLAN_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <nuttx/net/netdev_lowerhalf.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* VLAN tag definitions */ + +#define VLAN_PRIO_MASK 0xe000 /* Priority Code Point */ +#define VLAN_PRIO_SHIFT 13 +#define VLAN_CFI_MASK 0x1000 /* Canonical Format Indicator / Drop Eligible Indicator */ +#define VLAN_VID_MASK 0x0fff /* VLAN Identifier */ +#define VLAN_N_VID 4096 + +#ifdef CONFIG_NET_VLAN + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: vlan_register + * + * Description: + * Create a new VLAN device and register it. + * + * Input Parameters: + * real - The real device to which the VLAN is attached + * vid - VLAN ID + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +int vlan_register(FAR struct netdev_lowerhalf_s *real, uint16_t vid); + +/**************************************************************************** + * Name: vlan_unregister + * + * Description: + * Unregister a VLAN device. + * + * Input Parameters: + * dev - The VLAN device to be unregistered. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void vlan_unregister(FAR struct netdev_lowerhalf_s *dev); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_NET_VLAN */ +#endif /* __INCLUDE_NUTTX_NET_VLAN_H */ diff --git a/net/Kconfig b/net/Kconfig index 10ce0b23017..1e158c9db40 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -138,6 +138,7 @@ config NET_GUARDSIZE config NET_LL_GUARDSIZE int "Data Link Layer(L2) Guard size of Network buffer(IOB)" default 50 if RNDIS + default 18 if NET_VLAN default 16 if NET_CAN && NET_TIMESTAMP default 14 if NET_ETHERNET default 0 @@ -296,6 +297,26 @@ config NET_TUN_PKTSIZE endif # NET_TUN +menuconfig NET_VLAN + bool "VLAN support" + default n + depends on NET_ETHERNET + ---help--- + Enable support for VLANs (Virtual Local Area Networks) on Ethernet + devices. + +if NET_VLAN + +config NET_VLAN_COUNT + int "MAX number of VLAN interfaces per physical interface" + default 2 + range 1 32 + ---help--- + Selects the number of VLAN interfaces per physical interface to support. + Default: 2 + +endif # NET_VLAN + config NETDEV_LATEINIT bool "Late driver initialization" default n
