diff --git a/net/Kconfig b/net/Kconfig index 21ef8b3e7a..da5eab15d2 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -131,7 +131,7 @@ config NET_ETHERNET no need to define anything special in the configuration file to use Ethernet -- it is the default). -menuconfig NET_6LOWPAN +config NET_6LOWPAN bool "IEEE 802.15.4 6LoWPAN support" default n select NETDEV_MULTINIC if NET_ETHERNET || NET_LOOPBACK || NET_SLIP || NET_TUN diff --git a/net/sixlowpan/Kconfig b/net/sixlowpan/Kconfig index 09bb010c9f..d7635cf362 100644 --- a/net/sixlowpan/Kconfig +++ b/net/sixlowpan/Kconfig @@ -3,7 +3,8 @@ # see the file kconfig-language.txt in the NuttX tools repository. # -if NET_6LOWPAN +menu "6LoWPAN Configuration" + depends on NET_6LOWPAN config NET_6LOWPAN_FRAG bool "6loWPAN Fragmentation" @@ -190,4 +191,13 @@ config NET_6LOWPAN_TCP_RECVWNDO the application is slow to process incoming data, or high (32768 bytes) if the application processes data quickly. -endif # NET_6LOWPAN +config NET_6LOWPAN_DUMPBUFFER + bool "Enable dumping of buffer data" + default n + depends on DEBUG_NET_INFO + ---help--- + Enable dumping of all packet and frame buffers coming into and out + of the 6loWPAN logic. This will generate a large volume of data if + selected. + +endmenu # 6LoWPAN Configuration diff --git a/net/sixlowpan/sixlowpan_framelist.c b/net/sixlowpan/sixlowpan_framelist.c index 0c6519e8fe..7275f21ac3 100644 --- a/net/sixlowpan/sixlowpan_framelist.c +++ b/net/sixlowpan/sixlowpan_framelist.c @@ -261,12 +261,12 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, /* Pre-calculate frame header length. */ - framer_hdrlen = sixlowpan_hdrlen(ieee, ieee->i_panid); + framer_hdrlen = sixlowpan_send_hdrlen(ieee, ieee->i_panid); if (framer_hdrlen < 0) { /* Failed to determine the size of the header failed. */ - nerr("ERROR: sixlowpan_hdrlen() failed: %d\n", framer_hdrlen); + nerr("ERROR: sixlowpan_send_hdrlen() failed: %d\n", framer_hdrlen); return framer_hdrlen; } @@ -340,6 +340,8 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, ninfo("First fragment: length %d, tag %d\n", g_rime_payloadlen, ieee->i_dgramtag); + sixlowpan_dumpbuffer("Outgoing frame", + (FAR const uint8_t *)iob->io_data, iob->io_len); /* Add the first frame to the IOB queue */ @@ -412,6 +414,9 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, ninfo("sixlowpan output: fragment offset %d, length %d, tag %d\n", outlen >> 3, g_rime_payloadlen, ieee->i_dgramtag); + sixlowpan_dumpbuffer("Outgoing frame", + (FAR const uint8_t *)iob->io_data, + iob->io_len); /* Add the next frame to the tail of the IOB queue */ @@ -449,6 +454,10 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, buflen - g_uncomp_hdrlen); iob->io_len = buflen - g_uncomp_hdrlen + g_frame_hdrlen; + ninfo("Non-fragmented: length %d\n", iob->io_len); + sixlowpan_dumpbuffer("Outgoing frame", + (FAR const uint8_t *)iob->io_data, iob->io_len); + /* Add the first frame to the IOB queue */ ieee->i_framelist = iob; diff --git a/net/sixlowpan/sixlowpan_framer.c b/net/sixlowpan/sixlowpan_framer.c index ad502ebbc9..1adad943ab 100644 --- a/net/sixlowpan/sixlowpan_framer.c +++ b/net/sixlowpan/sixlowpan_framer.c @@ -383,7 +383,7 @@ static void sixlowpan_setup_params(FAR struct ieee802154_driver_s *ieee, ****************************************************************************/ /**************************************************************************** - * Function: sixlowpan_hdrlen + * Function: sixlowpan_send_hdrlen * * Description: * This function is before the first frame has been sent in order to @@ -401,7 +401,7 @@ static void sixlowpan_setup_params(FAR struct ieee802154_driver_s *ieee, * ****************************************************************************/ -int sixlowpan_hdrlen(FAR struct ieee802154_driver_s *ieee, +int sixlowpan_send_hdrlen(FAR struct ieee802154_driver_s *ieee, uint16_t dest_panid) { struct frame802154_s params; @@ -453,18 +453,18 @@ int sixlowpan_802154_framecreate(FAR struct frame802154_s *finfo, return 0; } - /* OK, now we have field lengths. Time to actually construct - * the outgoing frame, and store it in the provided buffer + /* OK, now we have field lengths. Time to actually construct the outgoing + * frame, and store it in the provided buffer */ - buf[0] = (finfo->fcf.frame_type & 7) | - ((finfo->fcf.security_enabled & 1) << 3) | - ((finfo->fcf.frame_pending & 1) << 4) | - ((finfo->fcf.ack_required & 1) << 5) | - ((finfo->fcf.panid_compression & 1) << 6); - buf[1] = ((finfo->fcf.dest_addr_mode & 3) << 2) | - ((finfo->fcf.frame_version & 3) << 4) | - ((finfo->fcf.src_addr_mode & 3) << 6); + buf[0] = ((finfo->fcf.frame_type & 7) << FRAME802154_FRAMETYPE_SHIFT) | + ((finfo->fcf.security_enabled & 1) << FRAME802154_SECENABLED_SHIFT) | + ((finfo->fcf.frame_pending & 1) << FRAME802154_FRAMEPENDING_SHIFT) | + ((finfo->fcf.ack_required & 1) << FRAME802154_ACKREQUEST_SHIFT) | + ((finfo->fcf.panid_compression & 1) << FRAME802154_PANIDCOMP_SHIFT); + buf[1] = ((finfo->fcf.dest_addr_mode & 3) << FRAME802154_DSTADDR_SHIFT) | + ((finfo->fcf.frame_version & 3) << FRAME802154_VERSION_SHIFT) | + ((finfo->fcf.src_addr_mode & 3) << FRAME802154_SRCADDR_SHIFT); /* Sequence number */ @@ -483,7 +483,7 @@ int sixlowpan_802154_framecreate(FAR struct frame802154_s *finfo, for (i = flen.dest_addr_len; i > 0; i--) { - buf[pos++] = finfo->dest_addr[i - 1]; + buf[pos++] = finfo->dest_addr[i - 1]; } /* Source PAN ID */ diff --git a/net/sixlowpan/sixlowpan_hc06.c b/net/sixlowpan/sixlowpan_hc06.c index a713e32807..f5d8396e91 100644 --- a/net/sixlowpan/sixlowpan_hc06.c +++ b/net/sixlowpan/sixlowpan_hc06.c @@ -455,8 +455,9 @@ void sixlowpan_compresshdr_hc06(FAR struct ieee802154_driver_s *ieee, uint8_t iphc1; uint8_t tmp; - ninfodumpbuffer("IPv6 before compression", (FAR const uint8_t *)ipv6, - sizeof(struct ipv6_hdr_s)); + sixlowpan_dumpbuffer("IPv6 before compression", + (FAR const uint8_t *)ipv6, + sizeof(struct ipv6_hdr_s)); g_hc06ptr = fptr + 2; diff --git a/net/sixlowpan/sixlowpan_hc1.c b/net/sixlowpan/sixlowpan_hc1.c index 67fa142cf7..a7040d5bcb 100644 --- a/net/sixlowpan/sixlowpan_hc1.c +++ b/net/sixlowpan/sixlowpan_hc1.c @@ -119,7 +119,7 @@ * ipv6 - The IPv6 header to be compressed * destmac - L2 destination address, needed to compress the IP * destination field - * fptr - Pointer to frame data payload. + * fptr - Pointer to frame to be compressed. * * Returned Value: * None @@ -144,15 +144,18 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee, ipv6->proto != IP_PROTO_TCP)) { /* IPV6 DISPATCH - * Something cannot be compressed, use IPV6 DISPATCH, - * compress nothing, copy IPv6 header in rime buffer + * Something cannot be compressed, use IPV6 DISPATCH, compress + * nothing, copy IPv6 header in rime buffer */ - *fptr = SIXLOWPAN_DISPATCH_IPV6; - g_frame_hdrlen += SIXLOWPAN_IPV6_HDR_LEN; - memcpy(fptr + g_frame_hdrlen, ipv6, IPv6_HDRLEN); - g_frame_hdrlen += IPv6_HDRLEN; - g_uncomp_hdrlen += IPv6_HDRLEN; + /* IPv6 dispatch header (1 byte) */ + + hc1[RIME_HC1_DISPATCH] = SIXLOWPAN_DISPATCH_IPV6; + g_frame_hdrlen += SIXLOWPAN_IPV6_HDR_LEN; + + memcpy(fptr + g_frame_hdrlen, ipv6, IPv6_HDRLEN); + g_frame_hdrlen += IPv6_HDRLEN; + g_uncomp_hdrlen += IPv6_HDRLEN; } else { @@ -169,8 +172,8 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee, /* HC1 encoding and ttl */ hc1[RIME_HC1_ENCODING] = 0xfc; - hc1[RIME_HC1_TTL] = ipv6->ttl; - g_frame_hdrlen += SIXLOWPAN_HC1_HDR_LEN; + hc1[RIME_HC1_TTL] = ipv6->ttl; + g_frame_hdrlen += SIXLOWPAN_HC1_HDR_LEN; break; #if CONFIG_NET_TCP @@ -178,8 +181,8 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee, /* HC1 encoding and ttl */ hc1[RIME_HC1_ENCODING] = 0xfe; - hc1[RIME_HC1_TTL] = ipv6->ttl; - g_frame_hdrlen += SIXLOWPAN_HC1_HDR_LEN; + hc1[RIME_HC1_TTL] = ipv6->ttl; + g_frame_hdrlen += SIXLOWPAN_HC1_HDR_LEN; break; #endif /* CONFIG_NET_TCP */ @@ -217,8 +220,8 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee, memcpy(&hcudp[RIME_HC1_HC_UDP_CHKSUM], &udp->udpchksum, 2); - g_frame_hdrlen += SIXLOWPAN_HC1_HC_UDP_HDR_LEN; - g_uncomp_hdrlen += UDP_HDRLEN; + g_frame_hdrlen += SIXLOWPAN_HC1_HC_UDP_HDR_LEN; + g_uncomp_hdrlen += UDP_HDRLEN; } else { diff --git a/net/sixlowpan/sixlowpan_input.c b/net/sixlowpan/sixlowpan_input.c index a098e69dc1..5d0eaa5869 100644 --- a/net/sixlowpan/sixlowpan_input.c +++ b/net/sixlowpan/sixlowpan_input.c @@ -87,6 +87,94 @@ #define IPv6BUF(dev) ((FAR struct ipv6_hdr_s *)((dev)->d_buf)) +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sixlowpan_recv_hdrlen + * + * Description: + * Get the length of the IEEE802.15.4 header on the received frame. + * + * Input Parameters: + * ieee - The IEEE802.15.4 MAC network driver interface. + * iob - The IOB containing the frame. + * + * Returned Value: + * Ok is returned on success; Othewise a negated errno value is returned. + * + * Assumptions: + * Network is locked + * + ****************************************************************************/ + +int sixlowpan_recv_hdrlen(FAR const uint8_t *fptr) +{ + uint16_t hdrlen; + uint8_t addrmode; + + /* Minimum header: 2 byte FCF + 1 byte sequence number */ + + hdrlen = 3; + + /* Account for destination address size */ + + addrmode = (fptr[1] & FRAME802154_DSTADDR_MASK) >> FRAME802154_DSTADDR_SHIFT; + if (addrmode == FRAME802154_SHORTADDRMODE) + { + /* 2 byte dest PAN + 2 byte dest short address */ + + hdrlen += 4; + } + else if (addrmode == FRAME802154_LONGADDRMODE) + { + /* 2 byte dest PAN + 6 byte dest long address */ + + hdrlen += 10; + } + else if (addrmode != FRAME802154_NOADDR) + { + nwarn("WARNING: Unrecognized address mode\n"); + + return -ENOSYS; + } + else if ((fptr[0] & (1 << FRAME802154_PANIDCOMP_SHIFT)) != 0) + { + nwarn("WARNING: PAN compression, but no destination address\n"); + + return -EINVAL; + } + + /* Account for source address size */ + + addrmode = (fptr[1] & FRAME802154_SRCADDR_MASK) >> FRAME802154_SRCADDR_SHIFT; + if (addrmode == FRAME802154_NOADDR) + { + return hdrlen; + } + else + { + if ((fptr[0] & (1 << FRAME802154_PANIDCOMP_SHIFT)) == 0) + { + hdrlen += 2; + } + + /* Add the length of the source address */ + + if (addrmode == FRAME802154_SHORTADDRMODE) + { + return hdrlen + 2; + } + else if (addrmode == FRAME802154_LONGADDRMODE) + { + return hdrlen + 8; + } + } + + return 0; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -128,6 +216,7 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee, uint8_t fragoffset = 0; /* Offset of the fragment in the IP packet */ bool isfrag = false; int reqsize; /* Required buffer size */ + int hdrsize; /* Size of the IEEE802.15.4 header */ #if CONFIG_NET_6LOWPAN_FRAG bool isfirstfrag = false; @@ -141,11 +230,18 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee, */ g_uncomp_hdrlen = 0; - g_frame_hdrlen = 0; + g_frame_hdrlen = 0; - /* The MAC puts the 15.4 payload inside the RIME data buffer */ + /* Get a pointer to the payload following the IEEE802.15.4 frame header. */ - payptr = &iob->io_data[PACKETBUF_HDR_SIZE]; + hdrsize = sixlowpan_recv_hdrlen(iob->io_data); + if (hdrsize < 0) + { + nwarn("Invalid IEEE802.15.2 header: %d\n", hdrsize); + return hdrsize; + } + + payptr = &iob->io_data[hdrsize]; #if CONFIG_NET_6LOWPAN_FRAG /* Since we don't support the mesh and broadcast header, the first header @@ -476,8 +572,9 @@ copypayload: } #endif /* CONFIG_NET_6LOWPAN_FRAG */ - ninfodumpbuffer("IPv6 header", (FAR const uint8_t *)IPv6BUF(&ieee->i_dev), - IPv6_HDRLEN); + sixlowpan_dumpbuffer("IPv6 header", + (FAR const uint8_t *)IPv6BUF(&ieee->i_dev), + IPv6_HDRLEN); return OK; } @@ -497,6 +594,10 @@ copypayload: static int sixlowpan_dispatch(FAR struct ieee802154_driver_s *ieee) { + sixlowpan_dumpbuffer("Incoming packet", + (FAR const uint8_t *)IPv6BUF(&ieee->i_dev), + ieee->i_dev.d_len); + #ifdef CONFIG_NET_PKT /* When packet sockets are enabled, feed the frame into the packet tap */ @@ -591,6 +692,9 @@ int sixlowpan_input(FAR struct ieee802154_driver_s *ieee) FRAME_IOB_REMOVE(ieee, iob); DEBUGASSERT(iob != NULL); + sixlowpan_dumpbuffer("Incoming frame", + (FAR const uint8_t *)iob->io_data, iob->io_len); + /* Process the frame, decompressing it into the packet buffer */ ret = sixlowpan_frame_process(ieee, iob); diff --git a/net/sixlowpan/sixlowpan_internal.h b/net/sixlowpan/sixlowpan_internal.h index 4a8b4ea0a9..1a4f28056e 100644 --- a/net/sixlowpan/sixlowpan_internal.h +++ b/net/sixlowpan/sixlowpan_internal.h @@ -121,33 +121,47 @@ * IEEE802.15.4 spec for details. */ -#define FRAME802154_BEACONFRAME 0x00 -#define FRAME802154_DATAFRAME 0x01 -#define FRAME802154_ACKFRAME 0x02 -#define FRAME802154_CMDFRAME 0x03 +#define FRAME802154_FRAMETYPE_SHIFT (0) /* Bits 0-2: Frame type */ +#define FRAME802154_FRAMETYPE_MASK (7 << FRAME802154_FRAMETYPE_SHIFT) +#define FRAME802154_SECENABLED_SHIFT (3) /* Bit 3: Security enabled */ +#define FRAME802154_FRAMEPENDING_SHIFT (4) /* Bit 4: Frame pending */ +#define FRAME802154_ACKREQUEST_SHIFT (5) /* Bit 5: ACK request */ +#define FRAME802154_PANIDCOMP_SHIFT (6) /* Bit 6: PANID compression */ + /* Bits 7-9: Reserved */ +#define FRAME802154_DSTADDR_SHIFT (2) /* Bits 10-11: Dest address mode */ +#define FRAME802154_DSTADDR_MASK (3 << FRAME802154_DSTADDR_SHIFT) +#define FRAME802154_VERSION_SHIFT (4) /* Bit 12-13: Frame version */ +#define FRAME802154_VERSION_MASK (3 << FRAME802154_VERSION_SHIFT) +#define FRAME802154_SRCADDR_SHIFT (6) /* Bits 14-15: Source address mode */ +#define FRAME802154_SRCADDR_MASK (3 << FRAME802154_SRCADDR_SHIFT) -#define FRAME802154_BEACONREQ 0x07 +/* Unshifted values for use in struct frame802154_fcf_s */ -#define FRAME802154_IEEERESERVED 0x00 -#define FRAME802154_NOADDR 0x00 /* Only valid for ACK or Beacon frames */ -#define FRAME802154_SHORTADDRMODE 0x02 -#define FRAME802154_LONGADDRMODE 0x03 +#define FRAME802154_BEACONFRAME (0) +#define FRAME802154_DATAFRAME (1) +#define FRAME802154_ACKFRAME (2) +#define FRAME802154_CMDFRAME (3) + +#define FRAME802154_BEACONREQ (7) + +#define FRAME802154_IEEERESERVED (0) +#define FRAME802154_NOADDR (0) /* Only valid for ACK or Beacon frames */ +#define FRAME802154_SHORTADDRMODE (2) +#define FRAME802154_LONGADDRMODE (3) #define FRAME802154_NOBEACONS 0x0f #define FRAME802154_BROADCASTADDR 0xffff #define FRAME802154_BROADCASTPANDID 0xffff -#define FRAME802154_IEEE802154_2003 0x00 -#define FRAME802154_IEEE802154_2006 0x01 +#define FRAME802154_IEEE802154_2003 (0) +#define FRAME802154_IEEE802154_2006 (1) -#define FRAME802154_SECURITY_LEVEL_NONE 0 -#define FRAME802154_SECURITY_LEVEL_128 3 +#define FRAME802154_SECURITY_LEVEL_NONE (0) +#define FRAME802154_SECURITY_LEVEL_128 (3) /* Packet buffer Definitions */ -#define PACKETBUF_HDR_SIZE 48 - #define PACKETBUF_ATTR_PACKET_TYPE_DATA 0 #define PACKETBUF_ATTR_PACKET_TYPE_ACK 1 #define PACKETBUF_ATTR_PACKET_TYPE_STREAM 2 @@ -295,6 +309,14 @@ } \ while(0) +/* Debug ********************************************************************/ + +#ifdef CONFIG_NET_6LOWPAN_DUMPBUFFER +# define sixlowpan_dumpbuffer(m,b,s) ninfodumpbuffer(m,b,s) +#else +# define sixlowpan_dumpbuffer(m,b,s) +#endif + /**************************************************************************** * Public Types ****************************************************************************/ @@ -492,7 +514,7 @@ int sixlowpan_send(FAR struct net_driver_s *dev, uint16_t timeout); /**************************************************************************** - * Function: sixlowpan_hdrlen + * Function: sixlowpan_send_hdrlen * * Description: * This function is before the first frame has been sent in order to @@ -510,7 +532,7 @@ int sixlowpan_send(FAR struct net_driver_s *dev, * ****************************************************************************/ -int sixlowpan_hdrlen(FAR struct ieee802154_driver_s *ieee, +int sixlowpan_send_hdrlen(FAR struct ieee802154_driver_s *ieee, uint16_t dest_panid); /**************************************************************************** @@ -617,7 +639,7 @@ void sixlowpan_hc06_initialize(void); * ipv6 - The IPv6 header to be compressed * destmac - L2 destination address, needed to compress the IP * destination field - * fptr - Pointer to frame data payload. + * fptr - Pointer to frame to be compressed. * * Returned Value: * None @@ -678,6 +700,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee, * ipv6 - The IPv6 header to be compressed * destmac - L2 destination address, needed to compress the IP * destination field + * fptr - Pointer to frame to be compressed. * * Returned Value: * None diff --git a/net/sixlowpan/sixlowpan_tcpsend.c b/net/sixlowpan/sixlowpan_tcpsend.c index c075a3b827..1ad8068a31 100644 --- a/net/sixlowpan/sixlowpan_tcpsend.c +++ b/net/sixlowpan/sixlowpan_tcpsend.c @@ -55,6 +55,14 @@ #if defined(CONFIG_NET_6LOWPAN) && defined(CONFIG_NET_TCP) +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Buffer access helpers */ + +#define IPv6BUF(dev) ((FAR struct ipv6_hdr_s *)((dev)->d_buf)) + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -156,6 +164,7 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf, int ret; ninfo("buflen %lu\n", (unsigned long)buflen); + sixlowpan_dumpbuffer("Outgoing TCP payload", buf, buflen); DEBUGASSERT(psock != NULL && psock->s_crefs > 0); DEBUGASSERT(psock->s_type == SOCK_STREAM); @@ -368,6 +377,8 @@ void sixlowpan_tcp_send(FAR struct net_driver_s *dev) /* Double check */ ninfo("d_len %u\n", dev->d_len); + sixlowpan_dumpbuffer("Outgoing TCP packet", + (FAR const uint8_t *)IPv6BUF(dev), dev->d_len); if (dev != NULL && dev->d_len > 0) { diff --git a/net/sixlowpan/sixlowpan_udpsend.c b/net/sixlowpan/sixlowpan_udpsend.c index 53c7ead6ce..717df424a2 100644 --- a/net/sixlowpan/sixlowpan_udpsend.c +++ b/net/sixlowpan/sixlowpan_udpsend.c @@ -167,9 +167,13 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock, uint16_t timeout; int ret; + ninfo("buflen %lu\n", (unsigned long)buflen); + DEBUGASSERT(psock != NULL && psock->s_crefs > 0 && to != NULL); DEBUGASSERT(psock->s_type == SOCK_DGRAM); + sixlowpan_dumpbuffer("Outgoing UDP payload", buf, buflen); + if (psock == NULL || to == NULL) { return (ssize_t)-EINVAL; @@ -352,9 +356,13 @@ ssize_t psock_6lowpan_udp_send(FAR struct socket *psock, FAR const void *buf, FAR struct udp_conn_s *conn; struct sockaddr_in6 to; + ninfo("buflen %lu\n", (unsigned long)buflen); + DEBUGASSERT(psock != NULL && psock->s_crefs > 0); DEBUGASSERT(psock->s_type == SOCK_DGRAM); + sixlowpan_dumpbuffer("Outgoing UDP payload", buf, buflen); + /* Make sure that this is a valid socket */ if (psock != NULL || psock->s_crefs <= 0)