Networking: Rethink IPv6 all-nodes packet routing.
This commit is contained in:
parent
680368b656
commit
572cf51fa4
@ -24,15 +24,15 @@ config SPIRIT_PKTLEN
|
||||
Fixed pkt sizes are used. This setting describes that fixed packet
|
||||
size.
|
||||
|
||||
"Sometimes Spirit1 seems to NOT deliver (correctly) the 'IRQ_RX_DATA_READY'
|
||||
event for packets which have a length which is close to a multiple of
|
||||
RX FIFO size. Furthermore, in these cases also the content delivery seems
|
||||
to be compromised as well as the generation of RX/TX FIFO errors.
|
||||
This can be avoided by reducing the maximum packet length to a value which
|
||||
is lower than the RX FIFO size."
|
||||
|
||||
Also, with a packet size of 96, I have seen CRC failures on the receiving
|
||||
side. With a packet size of 94, CRC filtering behaves well.
|
||||
This comment exists in the STMicro Spirit driver. I have not
|
||||
experienced this myself, but this is something you should be aware
|
||||
of: "Sometimes Spirit1 seems to NOT deliver (correctly) the
|
||||
'IRQ_RX_DATA_READY' event for packets which have a length which is
|
||||
close to a multiple of RX FIFO size. Furthermore, in these cases
|
||||
also the content delivery seems to be compromised as well as the
|
||||
generation of RX/TX FIFO errors. This can be avoided by reducing
|
||||
the maximum packet length to a value which is lower than the RX FIFO
|
||||
size."
|
||||
|
||||
config SPIRIT_FIFOS
|
||||
bool "FIFO Watermarks"
|
||||
@ -48,12 +48,15 @@ config SPIRIT_FIFOS
|
||||
occurrences of RX FIFO errors if the packet size is less than but close
|
||||
to 96.
|
||||
|
||||
"Sometimes Spirit1 seems to NOT deliver (correctly) the 'IRQ_RX_DATA_READY'
|
||||
event for packets which have a length which is close to a multiple of
|
||||
RX FIFO size. Furthermore, in these cases also the content delivery seems
|
||||
to be compromised as well as the generation of RX/TX FIFO errors.
|
||||
This can be avoided by reducing the maximum packet length to a value which
|
||||
is lower than the RX FIFO size."
|
||||
This comment exists in the STMicro Spirit driver. I have not
|
||||
experienced this myself, but this is something you should be aware
|
||||
of: "Sometimes Spirit1 seems to NOT deliver (correctly) the
|
||||
'IRQ_RX_DATA_READY' event for packets which have a length which is
|
||||
close to a multiple of RX FIFO size. Furthermore, in these cases
|
||||
also the content delivery seems to be compromised as well as the
|
||||
generation of RX/TX FIFO errors. This can be avoided by reducing
|
||||
the maximum packet length to a value which is lower than the RX FIFO
|
||||
size."
|
||||
|
||||
From my reading, the only known work-around is to reduce the maximum
|
||||
packet size so that it is smaller than 96. Hence, this option is
|
||||
@ -86,6 +89,13 @@ config SPIRIT_CRCDISABLE
|
||||
---help---
|
||||
Disables CRC calculation and filtering. Default is enabled.
|
||||
|
||||
Errata: "Using the STack packet format and no CRC field, the
|
||||
reading from RX FIFO to the last received byte, is not possible. ..."
|
||||
Workaround: "By configuring the packet handler with at least one byte
|
||||
of CRC, the problem is solved. If the CRC is not required in the
|
||||
application, configure one byte of CRC in the receiver only, to read
|
||||
the payload correctly from RX FIFO."
|
||||
|
||||
config SPIRIT_HUBNODE
|
||||
hex "Address of hub node"
|
||||
default 0x34
|
||||
|
@ -92,8 +92,8 @@ EXTERN uint16_t g_ipid;
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
EXTERN const net_ipv6addr_t g_ipv6_allzeroaddr; /* An address of all zeroes */
|
||||
#if defined(CONFIG_NET_ICMPv6_AUTOCONF) || defined(CONFIG_NET_ICMPv6_ROUTER)
|
||||
EXTERN const net_ipv6addr_t g_ipv6_allnodes; /* All link local nodes */
|
||||
#if defined(CONFIG_NET_ICMPv6_AUTOCONF) || defined(CONFIG_NET_ICMPv6_ROUTER)
|
||||
EXTERN const net_ipv6addr_t g_ipv6_allrouters; /* All link local routers */
|
||||
#ifdef CONFIG_NET_ICMPv6_AUTOCONF
|
||||
EXTERN const net_ipv6addr_t g_ipv6_llnetmask; /* Netmask for local link address */
|
||||
|
@ -53,10 +53,12 @@
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/net/ip.h>
|
||||
#include <nuttx/net/sixlowpan.h>
|
||||
#include <nuttx/wireless/pktradio.h>
|
||||
#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
|
||||
|
||||
#include "inet/inet.h"
|
||||
#include "sixlowpan/sixlowpan_internal.h"
|
||||
|
||||
#ifdef CONFIG_NET_6LOWPAN
|
||||
@ -233,9 +235,7 @@ int sixlowpan_destaddrfromip(FAR struct sixlowpan_driver_s *radio,
|
||||
* disturbing every interface in the network.
|
||||
*/
|
||||
|
||||
if (ipaddr[1] == 0 && ipaddr[2] == 0 && ipaddr[3] == 0 &&
|
||||
ipaddr[4] == 0 && ipaddr[5] == 0 && ipaddr[5] == 0 &&
|
||||
ipaddr[7] == HTONS(0x0001))
|
||||
if (net_ipv6addr_cmp(ipaddr, g_ipv6_allnodes))
|
||||
{
|
||||
memcpy(destaddr, &properties.sp_bcast,
|
||||
sizeof(struct netdev_varaddr_s));
|
||||
|
@ -277,6 +277,9 @@ static uint16_t udp_select_port(void)
|
||||
static inline FAR struct udp_conn_s *
|
||||
udp_ipv4_active(FAR struct net_driver_s *dev, FAR struct udp_hdr_s *udp)
|
||||
{
|
||||
#ifdef CONFIG_NET_BROADCAST
|
||||
static const inaddr_t bcast = INADDR_BROADCAST;
|
||||
#endif
|
||||
FAR struct ipv4_hdr_s *ip = IPv4BUF;
|
||||
FAR struct udp_conn_s *conn;
|
||||
|
||||
@ -315,13 +318,26 @@ static inline FAR struct udp_conn_s *
|
||||
|
||||
if (conn->lport != 0 && udp->destport == conn->lport &&
|
||||
(conn->rport == 0 || udp->srcport == conn->rport) &&
|
||||
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
/* Local port accepts any address on this port or there
|
||||
* is an exact match in destipaddr and the bound local
|
||||
* address. This catches the receipt of a broadcast when
|
||||
* the socket is bound to INADDR_ANY.
|
||||
*/
|
||||
|
||||
(net_ipv4addr_cmp(conn->u.ipv4.laddr, INADDR_ANY) ||
|
||||
net_ipv4addr_cmp(conn->u.ipv4.laddr, INADDR_BROADCAST) ||
|
||||
net_ipv4addr_hdrcmp(ip->destipaddr, &conn->u.ipv4.laddr)) &&
|
||||
#endif
|
||||
/* If not connected to a remote address, or a broadcast address
|
||||
* destipaddr was received, or there is an exact match between the
|
||||
* srcipaddr and the bound IP address, then accept the packet.
|
||||
*/
|
||||
|
||||
(net_ipv4addr_cmp(conn->u.ipv4.raddr, INADDR_ANY) ||
|
||||
net_ipv4addr_cmp(conn->u.ipv4.raddr, INADDR_BROADCAST) ||
|
||||
#ifdef CONFIG_NET_BROADCAST
|
||||
net_ipv4addr_hdrcmp(ip->destipaddr, &bcast) ||
|
||||
#endif
|
||||
net_ipv4addr_hdrcmp(ip->srcipaddr, &conn->u.ipv4.raddr)))
|
||||
{
|
||||
/* Matching connection found.. return a reference to it */
|
||||
@ -370,7 +386,7 @@ static inline FAR struct udp_conn_s *
|
||||
* - If multiple network interfaces are supported, then the local
|
||||
* IP address is available and we will insist that the
|
||||
* destination IP matches the bound address. If a socket is bound to
|
||||
* INADDRY_ANY (laddr), then it should receive all packets directed
|
||||
* INADDR6_ANY (laddr), then it should receive all packets directed
|
||||
* to the port. REVISIT: Should also depend on SO_BROADCAST.
|
||||
* - Finally, if the connection is bound to a remote IP address,
|
||||
* the source IP address of the packet is checked.
|
||||
@ -380,7 +396,8 @@ static inline FAR struct udp_conn_s *
|
||||
*
|
||||
* To send and receive multicast packets, the application should:
|
||||
*
|
||||
* - Bind socket to INADDR6_ANY or to a specific <multicast-address>
|
||||
* - Bind socket to INADDR6_ANY (for the all-nodes multicast address)
|
||||
* or to a specific <multicast-address>
|
||||
* - setsockopt to SO_BROADCAST (for all-nodes address)
|
||||
* - call sendto with sendaddr.sin_addr.s_addr = <multicast-address>
|
||||
* - call recvfrom.
|
||||
@ -390,11 +407,27 @@ static inline FAR struct udp_conn_s *
|
||||
|
||||
if (conn->lport != 0 && udp->destport == conn->lport &&
|
||||
(conn->rport == 0 || udp->srcport == conn->rport) &&
|
||||
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
/* Local port accepts any address on this port or there
|
||||
* is an exact match in destipaddr and the bound local
|
||||
* address. This catches the cast of the all nodes multicast
|
||||
* when the socket is bound to INADDR6_ANY.
|
||||
*/
|
||||
|
||||
(net_ipv6addr_cmp(conn->u.ipv6.laddr, g_ipv6_allzeroaddr) ||
|
||||
net_ipv6addr_hdrcmp(ip->destipaddr, conn->u.ipv6.laddr)) &&
|
||||
#endif
|
||||
/* If not connected to a remote address, or a all-nodes multicast
|
||||
* destipaddr was received, or there is an exact match between the
|
||||
* srcipaddr and the bound remote IP address, then accept the
|
||||
* packet.
|
||||
*/
|
||||
|
||||
(net_ipv6addr_cmp(conn->u.ipv6.raddr, g_ipv6_allzeroaddr) ||
|
||||
#ifdef CONFIG_NET_BROADCAST
|
||||
net_ipv6addr_hdrcmp(ip->destipaddr, g_ipv6_allnodes) ||
|
||||
#endif
|
||||
net_ipv6addr_hdrcmp(ip->srcipaddr, conn->u.ipv6.raddr)))
|
||||
{
|
||||
/* Matching connection found.. return a reference to it */
|
||||
|
Loading…
Reference in New Issue
Block a user