arch/arm/src/lpc54xx: Add some hooks for future 802.1q VLAN support. configs/lpcxpresso-lpc54628: Automatically bring up network in the netnsh configuration.

This commit is contained in:
Gregory Nutt 2018-01-02 08:48:30 -06:00
parent 1be5d96c6e
commit d04f166d84
4 changed files with 185 additions and 138 deletions

View File

@ -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.

View File

@ -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:

View File

@ -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

View File

@ -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);