diff --git a/include/nuttx/net/sixlowpan.h b/include/nuttx/net/sixlowpan.h index be7f9f1e36..376fbf2d9c 100644 --- a/include/nuttx/net/sixlowpan.h +++ b/include/nuttx/net/sixlowpan.h @@ -232,18 +232,91 @@ #define SIXLOWPAN_MAC_STDFRAME 127 +/* 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 +#define PACKETBUF_ATTR_PACKET_TYPE_STREAM_END 3 +#define PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP 4 + +/* Packet buffer attributes (indices into i_pktattr) */ + +#define PACKETBUF_ATTR_NONE 0 + +/* Scope 0 attributes: used only on the local node. */ + +#define PACKETBUF_ATTR_CHANNEL 1 +#define PACKETBUF_ATTR_NETWORK_ID 2 +#define PACKETBUF_ATTR_LINK_QUALITY 3 +#define PACKETBUF_ATTR_RSSI 4 +#define PACKETBUF_ATTR_TIMESTAMP 5 +#define PACKETBUF_ATTR_RADIO_TXPOWER 6 +#define PACKETBUF_ATTR_LISTEN_TIME 7 +#define PACKETBUF_ATTR_TRANSMIT_TIME 8 +#define PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS 9 +#define PACKETBUF_ATTR_MAC_SEQNO 10 +#define PACKETBUF_ATTR_MAC_ACK 11 + +/* Scope 1 attributes: used between two neighbors only. */ + +#define PACKETBUF_ATTR_RELIABLE 12 +#define PACKETBUF_ATTR_PACKET_ID 13 +#define PACKETBUF_ATTR_PACKET_TYPE 14 +#define PACKETBUF_ATTR_REXMIT 15 +#define PACKETBUF_ATTR_MAX_REXMIT 16 +#define PACKETBUF_ATTR_NUM_REXMIT 17 +#define PACKETBUF_ATTR_PENDING 18 + +/* Scope 2 attributes: used between end-to-end nodes. */ + +#define PACKETBUF_ATTR_HOPS 11 +#define PACKETBUF_ATTR_TTL 20 +#define PACKETBUF_ATTR_EPACKET_ID 21 +#define PACKETBUF_ATTR_EPACKET_TYPE 22 +#define PACKETBUF_ATTR_ERELIABLE 23 + +#define PACKETBUF_NUM_ATTRS 24 + + /* Addresses (indices into i_pktaddr) */ + +#define PACKETBUF_ADDR_SENDER 0 +#define PACKETBUF_ADDR_RECEIVER 1 +#define PACKETBUF_ADDR_ESENDER 2 +#define PACKETBUF_ADDR_ERECEIVER 3 + +#define PACKETBUF_NUM_ADDRS 4 + /**************************************************************************** * Public Types ****************************************************************************/ +/* Rime address representation */ + +struct rimeaddr_s +{ + uint8_t u8[CONFIG_NET_6LOWPAN_RIMEADDR_SIZE]; +}; + /* The device structure for IEEE802.15.4 MAC network device differs from the * standard Ethernet MAC device structure. The main reason for this * difference is that fragmentation must be supported. * * The IEEE802.15.4 MAC does not use the d_buf packet buffer directly. - * Rather, it uses a smaller frame buffer. The packet data is provided to - * the frame buffer each time that the IEEE802.15.4 MAC needs to send - * more data. + * Rather, it uses a smaller frame buffer, i_frame. + * + * - The packet fragment data is provided to the i_frame buffer each time + * that the IEEE802.15.4 MAC needs to send more data. The length of + * the frame is provided in i_frame. + * + * In this case, the d_buf holds the packet data yet to be sent; d_len + * holds the size of entire packet. + * + * - Received frames are provided by IEEE802.15.4 MAC to the network + * via i_frame with length i_framelen for reassembly in d_buf; d_len + * will hold the size of the reassembled packet. * * This is accomplished by "inheriting" the standard 'struct net_driver_s' * and appending the frame buffer as well as other metadata needed to @@ -286,6 +359,40 @@ struct ieee802154_driver_s */ uint16_t i_framelen; + + /* The following fields are device-specific metadata used by the 6loWPAN + * stack and should not be modified by the IEEE802.15.4 MAC network drvier. + */ + + /* A pointer to the rime buffer. + * + * We initialize it to the beginning of the rime buffer, then access + * different fields by updating the offset ieee->i_rime_hdrlen. + */ + + FAR uint8_t *i_rimeptr; + + /* i_uncomp_hdrlen is the length of the headers before compression (if HC2 + * is used this includes the UDP header in addition to the IP header). + */ + + uint8_t i_uncomp_hdrlen; + + /* i_rime_hdrlen is the total length of (the processed) 6lowpan headers + * (fragment headers, IPV6 or HC1, HC2, and HC1 and HC2 non compressed + * fields). + */ + + uint8_t i_rime_hdrlen; + + /* Next available pointer into header */ + + uint8_t i_hdrptr; + + /* Packet buffer metadata: Attributes and addresses */ + + uint16_t i_pktattrs[PACKETBUF_NUM_ATTRS]; + struct rimeaddr_s i_pktaddrs[PACKETBUF_NUM_ADDRS]; }; /* The structure of a next header compressor. This compressor is provided @@ -357,6 +464,8 @@ void sixlowpan_set_compressor(FAR struct sixlowpan_nhcompressor_s *compressor); * ****************************************************************************/ +#ifdef CONFIG_NET_6LOWPAN_SNIFFER void sixlowpan_set_sniffer(FAR struct sixlowpan_rime_sniffer_s *sniffer); +#endif #endif /* __INCLUDE_NUTTX_NET_SIXLOWOAN_H */ diff --git a/net/sixlowpan/Kconfig b/net/sixlowpan/Kconfig index 84cb1c6652..7031f21e62 100644 --- a/net/sixlowpan/Kconfig +++ b/net/sixlowpan/Kconfig @@ -169,4 +169,10 @@ config NET_6LOWPAN_TCP_RECVWNDO is slow to process incoming data, or high (32768 bytes) if the application processes data quickly. REVISIT! +config NET_6LOWPAN_SNIFFER + default n + ---help--- + Enable use use an architecture-specific sniffer to support tracing + of IP. + endif # NET_6LOWPAN diff --git a/net/sixlowpan/Make.defs b/net/sixlowpan/Make.defs index 1e58151731..8494f61f3b 100644 --- a/net/sixlowpan/Make.defs +++ b/net/sixlowpan/Make.defs @@ -39,9 +39,9 @@ ifeq ($(CONFIG_NET_6LOWPAN),y) # Include IEEE 802.15.4 file in the build -NET_CSRCS += sixlowpan_initialize.c sixlowpan_globals.c +NET_CSRCS += sixlowpan_initialize.c sixlowpan_globals.c sixlowpan_utils.c NET_CSRCS += sixlowpan_input.c sixlowpan_send.c -NET_CSRCS += sixlowpan_compressor.c sixlowpan_sniffer.c +NET_CSRCS += sixlowpan_compressor.c ifeq ($(CONFIG_NET_6LOWPAN_COMPRESSION_HC1),y) NET_CSRCS += sixlowpan_hc1.c @@ -51,6 +51,10 @@ ifeq ($(CONFIG_NET_6LOWPAN_COMPRESSION_HC06),y) NET_CSRCS += sixlowpan_hc06.c endif +ifeq ($(CONFIG_NET_6LOWPAN_SNIFFER),y) +NET_CSRCS += sixlowpan_sniffer.c +endif + # Include the sixlowpan directory in the build DEPPATH += --dep-path sixlowpan diff --git a/net/sixlowpan/sixlowpan.h b/net/sixlowpan/sixlowpan.h index 3acd0f4804..b003445fc6 100644 --- a/net/sixlowpan/sixlowpan.h +++ b/net/sixlowpan/sixlowpan.h @@ -61,13 +61,6 @@ * Public Types ****************************************************************************/ -/* Rime address representation */ - -struct rimeaddr_s -{ - uint8_t u8[CONFIG_NET_6LOWPAN_RIMEADDR_SIZE]; -}; - /**************************************************************************** * Public Data ****************************************************************************/ @@ -77,10 +70,16 @@ struct rimeaddr_s struct sixlowpan_nhcompressor_s; /* Foward reference */ extern FAR struct sixlowpan_nhcompressor_s *g_sixlowpan_compressor; +#ifdef CONFIG_NET_6LOWPAN_SNIFFER /* Rime Sniffer support for one single listener to enable trace of IP */ struct sixlowpan_rime_sniffer_s; /* Foward reference */ extern FAR struct sixlowpan_rime_sniffer_s *g_sixlowpan_sniffer; +#endif + +/* All zero rime address */ + +extern const struct rimeaddr_s g_rimeaddr_null; /**************************************************************************** * Public Types @@ -90,8 +89,10 @@ extern FAR struct sixlowpan_rime_sniffer_s *g_sixlowpan_sniffer; * Public Function Prototypes ****************************************************************************/ -struct net_driver_s; /* Forward reference */ -struct socket; /* Forward reference */ +struct net_driver_s; /* Forward reference */ +struct ieee802154_driver_s; /* Forward reference */ +struct rimeaddr_s; /* Forward reference */ +struct socket; /* Forward reference */ /**************************************************************************** * Name: sixlowpan_initialize @@ -132,6 +133,9 @@ void sixlowpan_initialize(void); * must be consistent with definition of errors reported by send() or * sendto(). * + * Assumptions: + * Called with the network locked. + * ****************************************************************************/ #ifdef CONFIG_NET_TCP @@ -157,6 +161,9 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf, * must be consistent with definition of errors reported by send() or * sendto(). * + * Assumptions: + * Called with the network locked. + * ****************************************************************************/ #ifdef CONFIG_NET_UDP @@ -319,5 +326,16 @@ void sixlowpan_uncompresshdr_hc1(FAR struct net_driver_s *dev, uint16_t ip_len); #endif +/**************************************************************************** + * Name: sixlowpan_pktbuf_reset + * + * Description: + * Reset all attributes and addresses in the packet buffer metadata in the + * provided IEEE802.15.4 MAC driver structure. + * + ****************************************************************************/ + +void sixlowpan_pktbuf_reset(FAR struct ieee802154_driver_s *ieee); + #endif /* CONFIG_NET_6LOWPAN */ #endif /* _NET_SIXLOWPAN_SIXLOWPAN_H */ diff --git a/net/sixlowpan/sixlowpan_globals.c b/net/sixlowpan/sixlowpan_globals.c index 6a5729d619..ce5e06b490 100644 --- a/net/sixlowpan/sixlowpan_globals.c +++ b/net/sixlowpan/sixlowpan_globals.c @@ -53,8 +53,10 @@ FAR struct sixlowpan_nhcompressor_s *g_sixlowpan_compressor; +#ifdef CONFIG_NET_6LOWPAN_SNIFFER /* A pointer to the optional, architecture-specific sniffer */ FAR struct sixlowpan_rime_sniffer_s *g_sixlowpan_sniffer; +#endif #endif /* CONFIG_NET_6LOWPAN */ diff --git a/net/sixlowpan/sixlowpan_send.c b/net/sixlowpan/sixlowpan_send.c index b85c685f42..ce99656770 100644 --- a/net/sixlowpan/sixlowpan_send.c +++ b/net/sixlowpan/sixlowpan_send.c @@ -39,12 +39,17 @@ #include +#include #include #include #include -#include "nuttx/net/net.h" #include "nuttx/net/netdev.h" +#include "nuttx/net/ip.h" +#include "nuttx/net/tcp.h" +#include "nuttx/net/udp.h" +#include "nuttx/net/icmpv6.h" +#include "nuttx/net/sixlowpan.h" #include "netdev/netdev.h" #include "socket/socket.h" @@ -54,11 +59,133 @@ #ifdef CONFIG_NET_6LOWPAN +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* IPv6 + TCP header */ + +struct ipv6tcp_hdr_s +{ + struct ipv6_hdr_s ipv6; + struct tcp_hdr_s tcp; +}; + +/* IPv6 + UDP header */ + +struct ipv6udp_hdr_s +{ + struct ipv6_hdr_s ipv6; + struct udp_hdr_s udp; +}; + +/* IPv6 + ICMPv6 header */ + +struct ipv6icmp_hdr_s +{ + struct ipv6_hdr_s ipv6; + struct icmpv6_iphdr_s icmp; +}; /**************************************************************************** - * Public Functions + * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: sixlowpan_set_pktattrs + * + * Description: + * Setup some packet buffer attributes + * Input Parameters: + * ieee - Pointer to IEEE802.15.4 MAC driver structure. + * ipv6 - Pointer to the IPv6 header to "compress" + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void sixlowpan_set_pktattrs(FAR struct ieee802154_driver_s *ieee, + FAR const struct ipv6_hdr_s *ipv6) +{ + int attr = 0; + + /* Set protocol in NETWORK_ID */ + + ieee->i_pktattrs[PACKETBUF_ATTR_NETWORK_ID] = ipv6->proto; + + /* Assign values to the channel attribute (port or type + code) */ + + if (ipv6->proto == IP_PROTO_UDP) + { + FAR struct udp_hdr_s *udp = &((FAR struct ipv6udp_hdr_s *)ipv6)->udp; + + attr = udp->srcport; + if (udp->destport < attr) + { + attr = udp->destport; + } + } + else if (ipv6->proto == IP_PROTO_TCP) + { + FAR struct tcp_hdr_s *tcp = &((FAR struct ipv6tcp_hdr_s *)ipv6)->tcp; + + attr = tcp->srcport; + if (tcp->destport < attr) + { + attr = tcp->destport; + } + } + else if (ipv6->proto == IP_PROTO_ICMP6) + { + FAR struct icmpv6_iphdr_s *icmp = &((FAR struct ipv6icmp_hdr_s *)ipv6)->icmp; + + attr = icmp->type << 8 | icmp->code; + } + + ieee->i_pktattrs[PACKETBUF_ATTR_CHANNEL] = attr; +} + +/**************************************************************************** + * Name: sixlowpan_compress_ipv6hdr + * + * Description: + * IPv6 dispatch "compression" function. Packets "Compression" when only + * IPv6 dispatch is used + * + * There is no compression in this case, all fields are sent + * inline. We just add the IPv6 dispatch byte before the packet. + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | IPv6 Dsp | IPv6 header and payload ... + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Input Parameters: + * ieee - Pointer to IEEE802.15.4 MAC driver structure. + * ipv6 - Pointer to the IPv6 header to "compress" + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void sixlowpan_compress_ipv6hdr(FAR struct ieee802154_driver_s *ieee, + FAR const struct ipv6_hdr_s *ipv6) +{ + /* Indicate the IPv6 dispatch and length */ + + *ieee->i_rimeptr = SIXLOWPAN_DISPATCH_IPV6; + ieee->i_rime_hdrlen += SIXLOWPAN_IPV6_HDR_LEN; + + /* Copy the IPv6 header and adjust pointers */ + + memcpy(ieee->i_rimeptr + ieee->i_rime_hdrlen, ipv6, IPv6_HDRLEN); + ieee->i_rime_hdrlen += IPv6_HDRLEN; + ieee->i_uncomp_hdrlen += IPv6_HDRLEN; +} + /**************************************************************************** * Name: sixlowpan_send * @@ -76,6 +203,7 @@ * * Input Parameters: * dev - The IEEE802.15.4 MAC network driver interface. + * ipv6 - IPv6 plus TCP or UDP headers. * raddr - The MAC address of the destination * * Returned Value: @@ -89,13 +217,60 @@ * ****************************************************************************/ -int sixlowpan_send(FAR struct net_driver_s *dev, net_ipv6addr_t raddr) +int sixlowpan_send(FAR struct net_driver_s *dev, + FAR const struct ipv6_hdr_s *ipv6, net_ipv6addr_t raddr) { FAR struct ieee802154_driver_s *ieee = (FAR struct ieee802154_driver_s *)dev; - net_lock(); - /* REVISIT: To be provided */ - net_unlock(); + int framer_hdrlen; /* Framer header length */ + struct rimeaddr_s dest; /* The MAC address of the destination of the packet */ + uint16_t outlen; /* Number of bytes processed. */ + + /* Initialize device-specific data */ + + ieee->i_uncomp_hdrlen = 0; + ieee->i_rime_hdrlen = 0; + + /* Reset rime buffer, packet buffer metatadata */ + + dev->d_len = 0; + + sixlowpan_pktbuf_reset(ieee); + + ieee->i_rimeptr = &dev->d_buf[PACKETBUF_HDR_SIZE]; + ieee->i_pktattrs[PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS] = CONFIG_NET_6LOWPAN_MAX_MACTRANSMITS; + +#ifdef CONFIG_NET_6LOWPAN_SNIFFER + if (g_sixlowpan_sniffer != NULL) + { + /* Call the attribution when the callback comes, but set attributes here */ + + sixlowpan_set_pktattrs(ieee, ipv6); + } +#endif + + /* Set stream mode for all TCP packets, except FIN packets. */ + + if (ipv6->proto == IP_PROTO_TCP) + { + FAR const struct tcp_hdr_s *tcp = &((FAR const struct ipv6tcp_hdr_s *)ipv6)->tcp; + + if ((tcp->flags & TCP_FIN) == 0 && + (tcp->flags & TCP_CTL) != TCP_ACK) + { + ieee->i_pktattrs[PACKETBUF_ATTR_PACKET_TYPE] = PACKETBUF_ATTR_PACKET_TYPE_STREAM; + } + else if ((tcp->flags & TCP_FIN) == TCP_FIN) + { + ieee->i_pktattrs[PACKETBUF_ATTR_PACKET_TYPE] = PACKETBUF_ATTR_PACKET_TYPE_STREAM_END; + } + } + + /* The destination address will be tagged to each outbound packet. If the + * argument raddr is NULL, we are sending a broadcast packet. + */ + +#warning Missing logic return -ENOSYS; } @@ -121,6 +296,9 @@ int sixlowpan_send(FAR struct net_driver_s *dev, net_ipv6addr_t raddr) * must be consistent with definition of errors reported by send() or * sendto(). * + * Assumptions: + * Called with the network locked. + * ****************************************************************************/ #ifdef CONFIG_NET_TCP @@ -129,6 +307,7 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf, { FAR struct tcp_conn_s *conn; FAR struct net_driver_s *dev; + struct ipv6tcp_hdr_s ipv6tcp; int ret; DEBUGASSERT(psock != NULL && psock->s_crefs > 0); @@ -194,6 +373,9 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf, } #endif + /* Initialize the IPv6/TCP headers */ +#warning Missing logic + /* Set the socket state to sending */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND); @@ -202,7 +384,8 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf, * packet. */ - ret = sixlowpan_send(dev, conn->u.ipv6.raddr); + ret = sixlowpan_send(dev, (FAR const struct ipv6_hdr_s *)&ipv6tcp, + conn->u.ipv6.raddr); if (ret < 0) { nerr("ERROR: sixlowpan_send() failed: %d\n", ret); @@ -230,6 +413,9 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf, * must be consistent with definition of errors reported by send() or * sendto(). * + * Assumptions: + * Called with the network locked. + * ****************************************************************************/ #ifdef CONFIG_NET_UDP @@ -238,6 +424,7 @@ ssize_t psock_6lowpan_udp_send(FAR struct socket *psock, FAR const void *buf, { FAR struct udp_conn_s *conn; FAR struct net_driver_s *dev; + struct ipv6udp_hdr_s ipv6udp; int ret; DEBUGASSERT(psock != NULL && psock->s_crefs > 0); @@ -304,6 +491,9 @@ ssize_t psock_6lowpan_udp_send(FAR struct socket *psock, FAR const void *buf, } #endif + /* Initialize the IPv6/UDP headers */ +#warning Missing logic + /* Set the socket state to sending */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND); @@ -312,7 +502,8 @@ ssize_t psock_6lowpan_udp_send(FAR struct socket *psock, FAR const void *buf, * packet. */ - ret = sixlowpan_send(dev, conn->u.ipv6.raddr); + ret = sixlowpan_send(dev, (FAR const struct ipv6_hdr_s *)&ipv6udp, + conn->u.ipv6.raddr); if (ret < 0) { nerr("ERROR: sixlowpan_send() failed: %d\n", ret); diff --git a/net/sixlowpan/sixlowpan_sniffer.c b/net/sixlowpan/sixlowpan_sniffer.c index baf3acc09c..f6134a86f0 100644 --- a/net/sixlowpan/sixlowpan_sniffer.c +++ b/net/sixlowpan/sixlowpan_sniffer.c @@ -44,7 +44,7 @@ #include "sixlowpan/sixlowpan.h" -#ifdef CONFIG_NET_6LOWPAN +#ifdef CONFIG_NET_6LOWPAN_SNIFFER /**************************************************************************** * Public Functions @@ -78,4 +78,4 @@ void sixlowpan_set_sniffer(FAR struct sixlowpan_rime_sniffer_s *sniffer) net_unlock(); } -#endif /* CONFIG_NET_6LOWPAN */ +#endif /* CONFIG_NET_6LOWPAN_SNIFFER */