From 95aba99f41333ad430496eab2596bc8b489ae731 Mon Sep 17 00:00:00 2001 From: Dirk Ziegelmeier Date: Fri, 19 Oct 2018 22:30:17 +0200 Subject: [PATCH] Implement task #11620: Add outgoing VLAN PCP support for Ethernet level QoS Apply rebased patch from Timmy Brolin --- src/core/tcp.c | 29 ++++++++++++++++------------- src/core/tcp_in.c | 3 +++ src/include/lwip/netif.h | 22 ++++++++++++++-------- src/include/lwip/opt.h | 34 +++++++++++++++++++++++----------- src/netif/ethernet.c | 12 ++++++++++-- 5 files changed, 66 insertions(+), 34 deletions(-) diff --git a/src/core/tcp.c b/src/core/tcp.c index ce03c816..1f91d24b 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c @@ -11,7 +11,7 @@ * Common functions for the TCP implementation, such as functions * for manipulating the data structures and the TCP timer functions. TCP functions * related to input and output is found in tcp_in.c and tcp_out.c respectively.\n - * + * * TCP connection setup * -------------------- * The functions used for setting up connections is similar to that of @@ -24,7 +24,7 @@ * - tcp_listen() and tcp_listen_with_backlog() * - tcp_accept() * - tcp_connect() - * + * * Sending TCP data * ---------------- * TCP data is sent by enqueueing the data with a call to tcp_write() and @@ -34,7 +34,7 @@ * - tcp_write() * - tcp_output() * - tcp_sent() - * + * * Receiving TCP data * ------------------ * TCP data reception is callback based - an application specified @@ -44,7 +44,7 @@ * window. * - tcp_recv() * - tcp_recved() - * + * * Application polling * ------------------- * When a connection is idle (i.e., no data is either transmitted or @@ -62,7 +62,7 @@ * - tcp_close() * - tcp_abort() * - tcp_err() - * + * */ /* @@ -469,7 +469,7 @@ tcp_close_shutdown_fin(struct tcp_pcb *pcb) * a closing state), the connection is closed, and put in a closing state. * The pcb is then automatically freed in tcp_slowtmr(). It is therefore * unsafe to reference it (unless an error is returned). - * + * * The function may return ERR_MEM if no memory * was available for closing the connection. If so, the application * should wait and try again either by using the acknowledgment @@ -797,7 +797,7 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err) * When an incoming connection is accepted, the function specified with * the tcp_accept() function will be called. The pcb has to be bound * to a local port with the tcp_bind() function. - * + * * The tcp_listen() function returns a new connection identifier, and * the one passed as an argument to the function will be * deallocated. The reason for this behavior is that less memory is @@ -812,7 +812,7 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err) * The backlog limits the number of outstanding connections * in the listen queue to the value specified by the backlog argument. * To use it, your need to set TCP_LISTEN_BACKLOG=1 in your lwipopts.h. - * + * * @param pcb the original tcp_pcb * @param backlog the incoming connections queue limit * @return tcp_pcb used for listening, consumes less memory. @@ -892,6 +892,9 @@ tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err) lpcb->netif_idx = NETIF_NO_INDEX; lpcb->ttl = pcb->ttl; lpcb->tos = pcb->tos; +#if LWIP_VLAN_PCP + lpcb->netif_hints.tci = pcb->netif_hints.tci; +#endif /* LWIP_VLAN_PCP */ #if LWIP_IPV4 && LWIP_IPV6 IP_SET_TYPE_VAL(lpcb->remote_ip, pcb->local_ip.type); #endif /* LWIP_IPV4 && LWIP_IPV6 */ @@ -1049,7 +1052,7 @@ again: * Connects to another host. The function given as the "connected" * argument will be called when the connection has been established. * Sets up the pcb to connect to the remote host and sends the - * initial SYN segment which opens the connection. + * initial SYN segment which opens the connection. * * The tcp_connect() function returns immediately; it does not wait for * the connection to be properly setup. Instead, it will call the @@ -1721,14 +1724,14 @@ tcp_kill_prio(u8_t prio) mprio = LWIP_MIN(TCP_PRIO_MAX, prio); - /* We want to kill connections with a lower prio, so bail out if + /* We want to kill connections with a lower prio, so bail out if * supplied prio is 0 - there can never be a lower prio */ if (mprio == 0) { return; } - /* We only want kill connections with a lower prio, so decrement prio by one + /* We only want kill connections with a lower prio, so decrement prio by one * and start searching for oldest connection with same or lower priority than mprio. * We want to find the connections with the lowest possible prio, and among * these the one with the longest inactivity time. @@ -2051,7 +2054,7 @@ tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent) * @ingroup tcp_raw * Used to specify the function that should be called when a fatal error * has occurred on the connection. - * + * * If a connection is aborted because of an error, the application is * alerted of this event by the err callback. Errors that might abort a * connection are when there is a shortage of memory. The callback @@ -2101,7 +2104,7 @@ tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept) * number of TCP coarse grained timer shots, which typically occurs * twice a second. An interval of 10 means that the application would * be polled every 5 seconds. - * + * * When a connection is idle (i.e., no data is either transmitted or * received), lwIP will repeatedly poll the application by calling a * specified callback function. This can be used either as a watchdog diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index 428a6f48..d1fe067a 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -690,6 +690,9 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) #if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG npcb->listener = pcb; #endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */ +#if LWIP_VLAN_PCP + npcb->netif_hints.tci = pcb->netif_hints.tci; +#endif /* LWIP_VLAN_PCP */ /* inherit socket options */ npcb->so_options = pcb->so_options & SOF_INHERITED; npcb->netif_idx = pcb->netif_idx; diff --git a/src/include/lwip/netif.h b/src/include/lwip/netif.h index 9e2007a6..013a69b5 100644 --- a/src/include/lwip/netif.h +++ b/src/include/lwip/netif.h @@ -248,14 +248,20 @@ typedef u8_t netif_addr_idx_t; #define NETIF_ADDR_IDX_MAX 0x7F #endif +#if LWIP_NETIF_HWADDRHINT || LWIP_VLAN_PCP + #define LWIP_NETIF_USE_HINTS 1 + struct netif_hint { #if LWIP_NETIF_HWADDRHINT -#define LWIP_NETIF_USE_HINTS 1 -struct netif_hint { - netif_addr_idx_t addr_hint; -}; -#else /* LWIP_NETIF_HWADDRHINT */ -#define LWIP_NETIF_USE_HINTS 0 -#endif /* LWIP_NETIF_HWADDRHINT */ + u8_t addr_hint; +#endif +#if LWIP_VLAN_PCP + /** VLAN hader is set if this is >= 0 (but must be <= 0xFFFF) */ + s32_t tci; +#endif + }; +#else /* LWIP_NETIF_HWADDRHINT || LWIP_VLAN_PCP */ + #define LWIP_NETIF_USE_HINTS 0 +#endif /* LWIP_NETIF_HWADDRHINT || LWIP_VLAN_PCP*/ /** Generic data structure used for all lwIP network interfaces. * The following fields should be filled in by the initialization @@ -348,7 +354,7 @@ struct netif { u8_t flags; /** descriptive abbreviation */ char name[2]; - /** number of this interface. Used for @ref if_api and @ref netifapi_netif, + /** number of this interface. Used for @ref if_api and @ref netifapi_netif, * as well as for IPv6 zones */ u8_t num; #if LWIP_IPV6_AUTOCONFIG diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index 90fce4f0..fb4b10c8 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -677,6 +677,18 @@ #define ETHARP_SUPPORT_VLAN 0 #endif +/** + * LWIP_VLAN_PCP==1: Enable outgoing VLAN taggning of frames on a per-PCB basis + * for QoS purposes. With this feature enabled, each PCB has a new variable: "tci". + * (Tag Control Identifier). The TCI contains three fields: VID, CFI and PCP. + * VID is the VLAN ID, which should be set to zero. + * The "CFI" bit is used to enable or disable VLAN tags for the PCB. + * PCP (Priority Code Point) is a 3 bit field used for Ethernet level QoS. + */ +#ifndef LWIP_VLAN_PCP +#define LWIP_VLAN_PCP 0 +#endif + /** LWIP_ETHERNET==1: enable ethernet support even though ARP might be disabled */ #if !defined LWIP_ETHERNET || defined __DOXYGEN__ @@ -1548,13 +1560,13 @@ * link level header. The default is 14, the standard value for * Ethernet. */ -#if !defined PBUF_LINK_HLEN || defined __DOXYGEN__ -#if defined LWIP_HOOK_VLAN_SET && !defined __DOXYGEN__ -#define PBUF_LINK_HLEN (18 + ETH_PAD_SIZE) -#else /* LWIP_HOOK_VLAN_SET */ -#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) -#endif /* LWIP_HOOK_VLAN_SET */ -#endif + #if !defined PBUF_LINK_HLEN || defined __DOXYGEN__ +#if (defined LWIP_HOOK_VLAN_SET || LWIP_VLAN_PCP) && !defined __DOXYGEN__ + #define PBUF_LINK_HLEN (18 + ETH_PAD_SIZE) +#else /* LWIP_HOOK_VLAN_SET || LWIP_VLAN_PCP */ + #define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) +#endif /* LWIP_HOOK_VLAN_SET || LWIP_VLAN_PCP */ + #endif /** * PBUF_LINK_ENCAPSULATION_HLEN: the number of bytes that should be allocated @@ -1626,7 +1638,7 @@ #endif /** - * LWIP_NETIF_EXT_STATUS_CALLBACK==1: Support an extended callback function + * LWIP_NETIF_EXT_STATUS_CALLBACK==1: Support an extended callback function * for several netif related event that supports multiple subscribers. * @see netif_ext_status_callback */ @@ -2423,7 +2435,7 @@ * All addresses that have a scope according to the default policy (link-local * unicast addresses, interface-local and link-local multicast addresses) should * now have a zone set on them before being passed to the core API, although - * lwIP will currently attempt to select a zone on the caller's behalf when + * lwIP will currently attempt to select a zone on the caller's behalf when * necessary. Applications that directly assign IPv6 addresses to interfaces * (which is NOT recommended) must now ensure that link-local addresses carry * the netif's zone. See the new ip6_zone.h header file for more information and @@ -3061,8 +3073,8 @@ * - src: source eth address * - dst: destination eth address * - eth_type: ethernet type to packet to be sent\n - * - * + * + * * Return values: * - <0: Packet shall not contain VLAN header. * - 0 <= return value <= 0xFFFF: Packet shall contain VLAN header. Return value is prio_vid in host byte order. diff --git a/src/netif/ethernet.c b/src/netif/ethernet.c index dd171e28..9e367f8c 100644 --- a/src/netif/ethernet.c +++ b/src/netif/ethernet.c @@ -273,8 +273,16 @@ ethernet_output(struct netif * netif, struct pbuf * p, struct eth_hdr *ethhdr; u16_t eth_type_be = lwip_htons(eth_type); -#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) - s32_t vlan_prio_vid = LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type); +#if ETHARP_SUPPORT_VLAN + s32_t vlan_prio_vid; +#ifdef LWIP_HOOK_VLAN_SET + vlan_prio_vid = LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type); +#elif LWIP_VLAN_PCP + vlan_prio_vid = -1; + if (netif->hints && (netif->hints->tci >= 0)) { + vlan_prio_vid = (u16_t)netif->hints->tci; + } +#endif if (vlan_prio_vid >= 0) { struct eth_vlan_hdr *vlanhdr;