diff --git a/arch/arm/src/lpc54xx/lpc54_ethernet.c b/arch/arm/src/lpc54xx/lpc54_ethernet.c index 488ee5bfc89..d89317247dc 100644 --- a/arch/arm/src/lpc54xx/lpc54_ethernet.c +++ b/arch/arm/src/lpc54xx/lpc54_ethernet.c @@ -46,9 +46,8 @@ * * 2. Multi-queuing not fully; supported. The second queue is intended to * support QVLAN, AVB type packets which have an 18-byte IEEE 802.1q - * Ethernet header. That implies that we would need to support two - * devices instances: One with a standard Ethernet header and one with - * an IEEE 802.1q Ethernet header. + * Ethernet header. I propose handling this case with a new network + * interface qvlan_input(). * * 3. Multicast address filtering. Unlike other hardware, this Ethernet * does not seem to support explicit Multicast address filtering as @@ -380,7 +379,8 @@ static int lpc54_eth_txpoll(struct net_driver_s *dev); /* Interrupt handling */ -static void lpc54_eth_rxdisptch(struct lpc54_ethdriver_s *priv); +static void lpc54_eth_reply(struct lpc54_ethdriver_s *priv); +static void lpc54_eth_rxdispatch(struct lpc54_ethdriver_s *priv); static int lpc54_eth_receive(struct lpc54_ethdriver_s *priv, unsigned int chan); static void lpc54_eth_txdone(struct lpc54_ethdriver_s *priv, @@ -844,6 +844,77 @@ static int lpc54_eth_txpoll(struct net_driver_s *dev) return 0; } +/**************************************************************************** + * Name: lpc54_eth_reply + * + * Description: + * After a packet has been received and dispatched to the network, it + * may return return with an outgoing packet. This function checks for + * that case and performs the transmission if necessary. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * The network is locked. + * + ****************************************************************************/ + +static void lpc54_eth_reply(struct lpc54_ethdriver_s *priv) +{ + struct lpc54_txring_s *txring; + unsigned int chan; + + /* If the packet dispatch resulted in data that should be sent out on the + * network, the field d_len will set to a value > 0. + */ + + if (priv->eth_dev.d_len > 0) + { + /* Update the Ethernet header with the correct MAC address */ + +#ifdef CONFIG_LPC54_ETH_MULTIQUEUE + /* Check for an outgoing 802.1q VLAN packet */ +#warning Missing Logic +#endif + +#ifdef CONFIG_NET_IPv4 +#ifdef CONFIG_NET_IPv6 + /* Check for an outgoing IPv4 packet */ + + if (IFF_IS_IPv4(priv->eth_dev.d_flags)) +#endif + { + arp_out(&priv->eth_dev); + } +#endif + +#ifdef CONFIG_NET_IPv6 +#ifdef CONFIG_NET_IPv4 + /* Otherwise, it must be an outgoing IPv6 packet */ + + else +#endif + { + neighbor_out(&priv->eth_dev); + } +#endif + + /* And send the packet */ + + chan = lpc54_eth_getring(priv); + txring = &priv->eth_txring[chan]; + + (txring->tr_buffers)[txring->tr_supply] = + (uint32_t *)priv->eth_dev.d_buf; + + lpc54_eth_transmit(priv, chan); + } +} + /**************************************************************************** * Name: lpc54_eth_rxdispatch * @@ -862,11 +933,8 @@ static int lpc54_eth_txpoll(struct net_driver_s *dev) * ****************************************************************************/ -static void lpc54_eth_rxdisptch(struct lpc54_ethdriver_s *priv) +static void lpc54_eth_rxdispatch(struct lpc54_ethdriver_s *priv) { - struct lpc54_txring_s *txring; - unsigned int chan; - #ifdef CONFIG_NET_PKT /* When packet sockets are enabled, feed the frame into the packet tap */ @@ -881,44 +949,14 @@ static void lpc54_eth_rxdisptch(struct lpc54_ethdriver_s *priv) ninfo("IPv4 packet\n"); NETDEV_RXIPV4(&priv->eth_dev); - /* Handle ARP on input then give the IPv4 packet to the network - * layer - */ + /* Handle ARP on input, then dispatch IPv4 packet to the network layer */ arp_ipin(&priv->eth_dev); ipv4_input(&priv->eth_dev); - /* If the above function invocation resulted in data that should be - * sent out on the network, the field d_len will set to a value > 0. - */ + /* Check for a reply to the IPv4 packet */ - if (priv->eth_dev.d_len > 0) - { - /* Update the Ethernet header with the correct MAC address */ - -#ifdef CONFIG_NET_IPv6 - if (IFF_IS_IPv4(priv->eth_dev.d_flags)) -#endif - { - arp_out(&priv->eth_dev); - } -#ifdef CONFIG_NET_IPv6 - else - { - neighbor_out(&priv->eth_dev); - } -#endif - - /* And send the packet */ - - chan = lpc54_eth_getring(priv); - txring = &priv->eth_txring[chan]; - - (txring->tr_buffers)[txring->tr_supply] = - (uint32_t *)priv->eth_dev.d_buf; - - lpc54_eth_transmit(priv, chan); - } + lpc54_eth_reply(priv); } else #endif @@ -928,47 +966,40 @@ static void lpc54_eth_rxdisptch(struct lpc54_ethdriver_s *priv) ninfo("Iv6 packet\n"); NETDEV_RXIPV6(&priv->eth_dev); - /* Give the IPv6 packet to the network layer */ + /* Dispatch IPv6 packet to the network layer */ ipv6_input(&priv->eth_dev); - /* If the above function invocation resulted in data that should be - * sent out on the network, the field d_len will set to a value > 0. - */ + /* Check for a reply to the IPv6 packet */ - if (priv->eth_dev.d_len > 0) - { - /* Update the Ethernet header with the correct MAC address */ - -#ifdef CONFIG_NET_IPv4 - if (IFF_IS_IPv4(priv->eth_dev.d_flags)) - { - arp_out(&priv->eth_dev); - } - else -#endif -#ifdef CONFIG_NET_IPv6 - { - neighbor_out(&priv->eth_dev); - } + lpc54_eth_reply(priv); + } + else #endif +#ifdef CONFIG_LPC54_ETH_MULTIQUEUE + if (ETH8021QWBUF->tpid == HTONS(TPID_8021QVLAN)) + { + ninfo("IEEE 802.1q packet\n"); + NETDEV_RXQVLAN(&priv->eth_dev); - /* And send the packet */ + /* Dispatch the 802.1q VLAN packet to the network layer */ - chan = lpc54_eth_getring(priv); - txring = &priv->eth_txring[chan]; + qvlan_input(&priv->eth_dev); - (txring->tr_buffers)[txring->tr_supply] = - (uint32_t *)priv->eth_dev.d_buf; + /* Check for a reply to the 802.1q VLAN packet */ - lpc54_eth_transmit(priv, chan); - } + lpc54_eth_reply(priv); } else #endif #ifdef CONFIG_NET_ARP if (ETHBUF->type == htons(ETHTYPE_ARP)) { + struct lpc54_txring_s *txring; + unsigned int chan; + + /* Dispatch the ARP packet to the network layer */ + arp_arpin(&priv->eth_dev); NETDEV_RXARP(&priv->eth_dev); @@ -994,7 +1025,7 @@ static void lpc54_eth_rxdisptch(struct lpc54_ethdriver_s *priv) } /* On entry, d_buf refers to the receive buffer as set by logic in - * lpc54_eth_receive(). If lpc54_eth_transmit() was called to respond + * lpc54_eth_receive(). If lpc54_eth_transmit() was called to reply * with an outgoing packet, then that packet was removed for transmission * and d_buf was nullified. Otherwise, d_buf still holds the stale * receive buffer and we will need to dispose of it here. @@ -1123,7 +1154,7 @@ static int lpc54_eth_receive(struct lpc54_ethdriver_s *priv, * handled if there is an available Tx descriptor. */ - lpc54_eth_rxdisptch(priv); + lpc54_eth_rxdispatch(priv); /* Allocate a new Rx buffer and update the Rx buffer * descriptor. diff --git a/configs/lpcxpresso-lpc54628/README.txt b/configs/lpcxpresso-lpc54628/README.txt index ecf7b22bb2d..ca8cbb0f725 100644 --- a/configs/lpcxpresso-lpc54628/README.txt +++ b/configs/lpcxpresso-lpc54628/README.txt @@ -86,7 +86,16 @@ STATUS of this writing. Also added the netnsh configuration will, eventually, be used to test the Ethernet driver. 2018-01-01: There Ethernet driver appears to be fully functional although - more testing is certainly needed. + more testing is certainly needed. I believe that there is a memory + corruption issue that cause problems occasionally. For example, after + a longer Telnet session, I sometimes see the following after exiting + the session from the host: + + up_assert: Assertion failed at file:mm_heap/mm_free.c line: 129 + + which is a clear indication heap corruption. Increasing the size of some + stacks might correct this problem, but I have not yet experimented with + that. There is still no support for the Accelerometer, SPIFI, or USB. There is a complete but not-yet-functional SD card. There is a partial SPI driver, @@ -240,29 +249,22 @@ Configurations 2. SD card and I2C support are not enabled. The I2C tool application is not enabled - 3. SDRAM support is enabled and the SDRAM is added to the system heap. The - Ramtest applications is not enabled. + 3. SDRAM support is enabled and the SDRAM is added to the system heap. + The ramtest application is not enabled. - 4. This configuration does not include support for aysnchronous network + 4. This configuration does not include support for asynchronous network initialization. As a consequence, NSH must bring up the network before you get the NSH prompt. If the network cable is unplugged, this can mean a significant delay before you see the prompt. - 5. In this configuration, the network network does not come up - automatically after it has been initialized. You will need to - explicitly bring the network up from the NSH command line: + 5. In this configuration, the network the network and the Telnet + daemon are available by the time that the NSH prompt is presented. - nsh> ifup eth0 + Telnet defaults to IPv6 so to use it from the host PS, you would have + to do: - 6. Telnet is supported, but the Telnet daemon must be started manually - like: + $ telnet fc00::42 - nsh> telnetd ipv4 - - Use the argument 'ipv6' to run telnet in the IPv6 address space. With - the above command, you can create a remote Telnet session via: - - $ telnet 10.0.0.2 nsh: diff --git a/configs/lpcxpresso-lpc54628/netnsh/defconfig b/configs/lpcxpresso-lpc54628/netnsh/defconfig index a3458de2175..89836e60109 100644 --- a/configs/lpcxpresso-lpc54628/netnsh/defconfig +++ b/configs/lpcxpresso-lpc54628/netnsh/defconfig @@ -1,5 +1,4 @@ # CONFIG_ARCH_FPU is not set -# CONFIG_NSH_DISABLE_TELNETD is not set CONFIG_ARCH_BOARD_LPCXPRESSO_LPC54628=y CONFIG_ARCH_BOARD="lpcxpresso-lpc54628" CONFIG_ARCH_BUTTONS=y @@ -50,7 +49,6 @@ CONFIG_NSH_ARCHINIT=y CONFIG_NSH_BUILTIN_APPS=y CONFIG_NSH_FILEIOSIZE=512 CONFIG_NSH_LINELEN=64 -CONFIG_NSH_NETLOCAL=y CONFIG_NSH_NOMAC=y CONFIG_NSH_READLINE=y CONFIG_PREALLOC_MQ_MSGS=4 diff --git a/drivers/net/skeleton.c b/drivers/net/skeleton.c index 0216d73de08..fb2d084b51f 100644 --- a/drivers/net/skeleton.c +++ b/drivers/net/skeleton.c @@ -156,6 +156,7 @@ static int skel_txpoll(FAR struct net_driver_s *dev); /* Interrupt handling */ +static void skel_reply(struct skel_driver_s *priv) static void skel_receive(FAR struct skel_driver_s *priv); static void skel_txdone(FAR struct skel_driver_s *priv); @@ -309,6 +310,63 @@ static int skel_txpoll(FAR struct net_driver_s *dev) return 0; } +/**************************************************************************** + * Name: skel_reply + * + * Description: + * After a packet has been received and dispatched to the network, it + * may return return with an outgoing packet. This function checks for + * that case and performs the transmission if necessary. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * The network is locked. + * + ****************************************************************************/ + +static void skel_reply(struct skel_driver_s *priv) +{ + /* If the packet dispatch resulted in data that should be sent out on the + * network, the field d_len will set to a value > 0. + */ + + if (priv->sk_dev.d_len > 0) + { + /* Update the Ethernet header with the correct MAC address */ + +#ifdef CONFIG_NET_IPv4 +#ifdef CONFIG_NET_IPv6 + /* Check for an outgoing IPv4 packet */ + + if (IFF_IS_IPv4(priv->sk_dev.d_flags)) +#endif + { + arp_out(&priv->sk_dev); + } +#endif + +#ifdef CONFIG_NET_IPv6 +#ifdef CONFIG_NET_IPv4 + /* Otherwise, it must be an outgoing IPv6 packet */ + + else +#endif + { + neighbor_out(&skel->sk_dev); + } +#endif + + /* And send the packet */ + + skel_transmit(priv); + } +} + /**************************************************************************** * Name: skel_receive * @@ -354,38 +412,16 @@ static void skel_receive(FAR struct skel_driver_s *priv) ninfo("IPv4 frame\n"); NETDEV_RXIPV4(&priv->sk_dev); - /* Handle ARP on input then give the IPv4 packet to the network - * layer + /* Handle ARP on input, then dispatch IPv4 packet to the network + * layer. */ arp_ipin(&priv->sk_dev); ipv4_input(&priv->sk_dev); - /* If the above function invocation resulted in data that should be - * sent out on the network, the field d_len will set to a value > 0. - */ + /* Check for a reply to the IPv4 packet */ - if (priv->sk_dev.d_len > 0) - { - /* Update the Ethernet header with the correct MAC address */ - -#ifdef CONFIG_NET_IPv6 - if (IFF_IS_IPv4(priv->sk_dev.d_flags)) -#endif - { - arp_out(&priv->sk_dev); - } -#ifdef CONFIG_NET_IPv6 - else - { - neighbor_out(&skel->sk_dev); - } -#endif - - /* And send the packet */ - - skel_transmit(priv); - } + skel_reply(priv); } else #endif @@ -395,41 +431,21 @@ static void skel_receive(FAR struct skel_driver_s *priv) ninfo("Iv6 frame\n"); NETDEV_RXIPV6(&priv->sk_dev); - /* Give the IPv6 packet to the network layer */ + /* Dispatch IPv6 packet to the network layer */ ipv6_input(&priv->sk_dev); - /* If the above function invocation resulted in data that should be - * sent out on the network, the field d_len will set to a value > 0. - */ + /* Check for a reply to the IPv6 packet */ - if (priv->sk_dev.d_len > 0) - { - /* Update the Ethernet header with the correct MAC address */ - -#ifdef CONFIG_NET_IPv4 - if (IFF_IS_IPv4(priv->sk_dev.d_flags)) - { - arp_out(&priv->sk_dev); - } - else -#endif -#ifdef CONFIG_NET_IPv6 - { - neighbor_out(&priv->sk_dev); - } -#endif - - /* And send the packet */ - - skel_transmit(priv); - } + skel_reply(priv); } else #endif #ifdef CONFIG_NET_ARP if (BUF->type == htons(ETHTYPE_ARP)) { + /* Dispatch ARP packet to the network layer */ + arp_arpin(&priv->sk_dev); NETDEV_RXARP(&priv->sk_dev);