Merge remote-tracking branch 'origin/master' into ieee802154

This commit is contained in:
Gregory Nutt 2017-04-02 14:39:45 -06:00
commit c8291a376e
22 changed files with 2556 additions and 597 deletions

View File

@ -90,9 +90,7 @@
# error "Logic to support multiple Ethernet interfaces is incomplete"
#endif
/* If processing is not done at the interrupt level, then work queue support
* is required.
*/
/* Work queue support is required. */
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required

View File

@ -483,7 +483,7 @@ EXTERN const net_ipv6addr_t g_ipv6_llnetmask; /* Netmask for local link addres
#endif
/****************************************************************************
* Function: net_ipv4addr_maskcmp and net_ipv6addr_maskcmp
* Name: net_ipv4addr_maskcmp and net_ipv6addr_maskcmp
*
* Description:
* Compare two IP addresses under a netmask. The mask is used to mask
@ -527,7 +527,86 @@ bool net_ipv6addr_maskcmp(const net_ipv6addr_t addr1,
#endif
/****************************************************************************
* Function: net_ipaddr_mask
* Name: net_ipv6addr_prefixcmp
*
* Description:
* Compare two IPv6 address prefixes.
*
****************************************************************************/
#define net_ipv6addr_prefixcmp(addr1, addr2, length) \
(memcmp(addr1, addr2, length >> 3) == 0)
/****************************************************************************
* Name: net_is_addr_loopback
*
* Description:
* Is Ithe Pv6 address a the loopback address?
*
****************************************************************************/
#define net_is_addr_loopback(a) \
((a)[0] == 0 && (a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \
(a)[4] == 0 && (a)[5] == 0 && (a)[6] == 0 && (a)[7] == 0x0001)
/****************************************************************************
* Name: net_is_addr_unspecified
*
* Description:
* Is Ithe Pv6 address the unspecified address?
*
****************************************************************************/
#define net_is_addr_unspecified(a) \
((a)[0] == 0 && (a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \
(a)[4] == 0 && (a)[5] == 0 && (a)[6] == 0 && (a)[7] == 0)
/****************************************************************************
* Name: net_is_addr_mcast
*
* Description:
* s address a multicast address? see RFC 3513.
*
****************************************************************************/
#define net_is_addr_mcast(a) (((a)[0] & 0xff00) == 0xff00)
/****************************************************************************
* Name: net_is_addr_linklocal_allnodes_mcast
*
* Description:
* Is IPv6 address a the link local all-nodes multicast address?
*
****************************************************************************/
#define net_is_addr_linklocal_allnodes_mcast(a) \
((a)[0] == 0xff02 && (a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \
(a)[4] == 0 && (a)[5] == 0 && (a)[6] == 0 && (a)[7] == 0x0001)
/****************************************************************************
* Name: net_is_addr_linklocal_allrouters_mcast
*
* Description:
* Is IPv6 address a the link local all-routers multicast address?
*
****************************************************************************/
#define net_is_addr_linklocal_allrouters_mcast(a) \
((a)[0] == 0xff02 && (a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \
(a)[4] == 0 && (a)[5] == 0 && (a)[6] == 0 && (a)[7] == 0x0002)
/****************************************************************************
* Name: net_is_addr_linklocal
*
* Description:
* Checks whether the address a is link local.
*
****************************************************************************/
#define net_is_addr_linklocal(a) ((a)[0] == 0xfe80)
/****************************************************************************
* Name: net_ipaddr_mask
*
* Description:
* Mask out the network part of an IP address, given the address and

View File

@ -336,67 +336,51 @@
#endif
#ifdef CONFIG_NET_MULTILINK
# undef __LAST_MIN_UDP_MSS
# undef __LAST_MAX_UDP_MSS
# ifdef CONFIG_NET_ETHERNET
# ifdef __LAST_MIN_UDP_MSS
# define __MIN_UDP_MSS(h) MIN(ETH_UDP_MSS(h),__LAST_MIN_UDP_MSS(h))
# define __MAX_UDP_MSS(h) MAX(ETH_UDP_MSS(h),__LAST_MAX_UDP_MSS(h))
# else
# define __MIN_UDP_MSS(h) ETH_UDP_MSS(h)
# define __MAX_UDP_MSS(h) ETH_UDP_MSS(h)
# endif
# undef __LAST_MIN_UDP_MSS
# undef __LAST_MAX_UDP_MSS
# define __LAST_MIN_UDP_MSS(h) __MIN_UDP_MSS(h)
# define __LAST_MAX_UDP_MSS(h) __MAX_UDP_MSS(h)
# define __MIN_UDP_MSS(h) ETH_UDP_MSS(h)
# define __MAX_UDP_MSS(h) ETH_UDP_MSS(h)
# define __ETH_MIN_UDP_MSS(h) ETH_UDP_MSS(h)
# define __ETH_MAX_UDP_MSS(h) ETH_UDP_MSS(h)
# else
# define __ETH_MIN_UDP_MSS(h) INT_MAX
# define __ETH_MAX_UDP_MSS(h) 0
# endif
# ifdef CONFIG_NET_6LOWPAN
# ifdef __LAST_MIN_UDP_MSS
# define __MIN_UDP_MSS(h) MIN(IEEE802154_UDP_MSS(h),__LAST_MIN_UDP_MSS(h))
# define __MAX_UDP_MSS(h) MAX(IEEE802154_UDP_MSS(h),__LAST_MAX_UDP_MSS(h))
# else
# define __MIN_UDP_MSS(h) IEEE802154_UDP_MSS(h)
# define __MAX_UDP_MSS(h) IEEE802154_UDP_MSS(h)
# endif
# undef __LAST_MIN_UDP_MSS
# undef __LAST_MAX_UDP_MSS
# define __LAST_MIN_UDP_MSS(h) __MIN_UDP_MSS(h)
# define __LAST_MAX_UDP_MSS(h) __MAX_UDP_MSS(h)
# undef __MIN_UDP_MSS
# undef __MIN_UDP_MSS
# define __MIN_UDP_MSS(h) MIN(IEEE802154_UDP_MSS(h),__ETH_MIN_UDP_MSS(h))
# define __MAX_UDP_MSS(h) MAX(IEEE802154_UDP_MSS(h),__ETH_MAX_UDP_MSS(h))
# define __6LOWPAN_MIN_UDP_MSS(h) MIN(IEEE802154_UDP_MSS(h),__ETH_MIN_UDP_MSS(h))
# define __6LOWPAN_MAX_UDP_MSS(h) MAX(IEEE802154_UDP_MSS(h),__ETH_MAX_UDP_MSS(h))
# else
# define __6LOWPAN_MIN_UDP_MSS(h) __ETH_MIN_UDP_MSS(h)
# define __6LOWPAN_MAX_UDP_MSS(h) __ETH_MAX_UDP_MSS(h)
# endif
# ifdef CONFIG_NET_LOOPBACK
# ifdef __LAST_MIN_UDP_MSS
# define __MIN_UDP_MSS(h) MIN(LO_UDP_MSS(h),__LAST_MIN_UDP_MSS(h))
# define __MAX_UDP_MSS(h) MAX(LO_UDP_MSS(h),__LAST_MAX_UDP_MSS(h))
# else
# define __MIN_UDP_MSS(h) LO_UDP_MSS(h)
# define __MAX_UDP_MSS(h) LO_UDP_MSS(h)
# endif
# undef __LAST_MIN_UDP_MSS
# undef __LAST_MAX_UDP_MSS
# define __LAST_MIN_UDP_MSS(h) __MIN_UDP_MSS(h)
# define __LAST_MAX_UDP_MSS(h) __MAX_UDP_MSS(h)
# undef __MIN_UDP_MSS
# undef __MIN_UDP_MSS
# define __MIN_UDP_MSS(h) MIN(LO_UDP_MSS(h),__6LOWPAN_MIN_UDP_MSS(h))
# define __MAX_UDP_MSS(h) MAX(LO_UDP_MSS(h),__6LOWPAN_MAX_UDP_MSS(h))
# define __LOOP_MIN_UDP_MSS(h) MIN(LO_UDP_MSS(h),__6LOWPAN_MIN_UDP_MSS(h))
# define __LOOP_MAX_UDP_MSS(h) MAX(LO_UDP_MSS(h),__6LOWPAN_MAX_UDP_MSS(h))
# else
# define __LOOP_MIN_UDP_MSS(h) __6LOWPAN_MIN_UDP_MSS(h)
# define __LOOP_MAX_UDP_MSS(h) __6LOWPAN_MAX_UDP_MSS(h)
# endif
# ifdef CONFIG_NET_SLIP
# ifdef __LAST_MIN_UDP_MSS
# define __MIN_UDP_MSS(h) MIN(SLIP_UDP_MSS(h),__LAST_MIN_UDP_MSS(h))
# define __MAX_UDP_MSS(h) MAX(SLIP_UDP_MSS(h),__LAST_MAX_UDP_MSS(h))
# else
# define __MIN_UDP_MSS(h) SLIP_UDP_MSS(h)
# define __MAX_UDP_MSS(h) SLIP_UDP_MSS(h)
# endif
# undef __LAST_MIN_UDP_MSS
# undef __LAST_MAX_UDP_MSS
# define __LAST_MIN_UDP_MSS(h) __MIN_UDP_MSS(h)
# define __LAST_MAX_UDP_MSS(h) __MAX_UDP_MSS(h)
# undef __MIN_UDP_MSS
# undef __MIN_UDP_MSS
# define __MIN_UDP_MSS(h) MIN(SLIP_UDP_MSS(h),__LOOP_MIN_UDP_MSS(h))
# define __MAX_UDP_MSS(h) MAX(SLIP_UDP_MSS(h),__LOOP_MAX_UDP_MSS(h))
# define __SLIP_MIN_UDP_MSS(h) MIN(SLIP_UDP_MSS(h),__LOOP_MIN_UDP_MSS(h))
# define __SLIP_MAX_UDP_MSS(h) MAX(SLIP_UDP_MSS(h),__LOOP_MAX_UDP_MSS(h))
# else
# define __SLIP_MIN_UDP_MSS(h) __LOOP_MIN_UDP_MSS(h)
# define __SLIP_MAX_UDP_MSS(h) __LOOP_MAX_UDP_MSS(h)
# endif
# undef __LAST_MIN_UDP_MSS
# undef __LAST_MAX_UDP_MSS
#endif
/* NOTE: MSS calcuation excludes the UDP_HDRLEN. */
@ -531,67 +515,52 @@
#endif
#ifdef CONFIG_NET_MULTILINK
# undef __LAST_MIN_TCP_MSS
# undef __LAST_MAX_TCP_MSS
# ifdef CONFIG_NET_ETHERNET
# ifdef __LAST_MIN_TCP_MSS
# define __MIN_TCP_MSS(h) MIN(ETH_TCP_MSS(h),__LAST_MIN_TCP_MSS(h))
# define __MAX_TCP_MSS(h) MAX(ETH_TCP_MSS(h),__LAST_MAX_TCP_MSS(h))
# else
# define __MIN_TCP_MSS(h) ETH_TCP_MSS(h)
# define __MAX_TCP_MSS(h) ETH_TCP_MSS(h)
# endif
# undef __LAST_MIN_TCP_MSS
# undef __LAST_MAX_TCP_MSS
# define __LAST_MIN_TCP_MSS(h) __MIN_TCP_MSS(h)
# define __LAST_MAX_TCP_MSS(h) __MAX_TCP_MSS(h)
# define __MIN_TCP_MSS(h) ETH_TCP_MSS(h)
# define __MAX_TCP_MSS(h) ETH_TCP_MSS(h)
# define __ETH_MIN_TCP_MSS(h) ETH_TCP_MSS(h)
# define __ETH_MAX_TCP_MSS(h) ETH_TCP_MSS(h)
# else
# define __ETH_MIN_TCP_MSS(h) INT_MAX
# define __ETH_MAX_TCP_MSS(h) 0
# endif
# ifdef CONFIG_NET_6LOWPAN
# ifdef __LAST_MIN_TCP_MSS
# define __MIN_TCP_MSS(h) MIN(IEEE802154_TCP_MSS(h),__LAST_MIN_TCP_MSS(h))
# define __MAX_TCP_MSS(h) MAX(IEEE802154_TCP_MSS(h),__LAST_MAX_TCP_MSS(h))
# else
# define __MIN_TCP_MSS(h) IEEE802154_TCP_MSS(h)
# define __MAX_TCP_MSS(h) IEEE802154_TCP_MSS(h)
# endif
# undef __LAST_MIN_TCP_MSS
# undef __LAST_MAX_TCP_MSS
# define __LAST_MIN_TCP_MSS(h) __MIN_TCP_MSS(h)
# define __LAST_MAX_TCP_MSS(h) __MAX_TCP_MSS(h)
# undef __MIN_TCP_MSS
# undef __MAX_TCP_MSS
# define __MIN_TCP_MSS(h) MIN(IEEE802154_TCP_MSS(h),__ETH_MIN_TCP_MSS(h))
# define __MAX_TCP_MSS(h) MAX(IEEE802154_TCP_MSS(h),__ETH_MAX_TCP_MSS(h))
# define __6LOWPAN_MIN_TCP_MSS(h) MIN(IEEE802154_TCP_MSS(h),__ETH_MIN_TCP_MSS(h))
# define __6LOWPAN_MAX_TCP_MSS(h) MAX(IEEE802154_TCP_MSS(h),__ETH_MAX_TCP_MSS(h))
# else
# define __6LOWPAN_MIN_TCP_MSS(h) __ETH_MIN_TCP_MSS(h)
# define __6LOWPAN_MAX_TCP_MSS(h) __ETH_MAX_TCP_MSS(h)
# endif
# ifdef CONFIG_NET_LOOPBACK
# ifdef __LAST_MIN_TCP_MSS
# define __MIN_TCP_MSS(h) MIN(LO_TCP_MSS(h),__LAST_MIN_TCP_MSS(h))
# define __MAX_TCP_MSS(h) MAX(LO_TCP_MSS(h),__LAST_MAX_TCP_MSS(h))
# else
# define __MIN_TCP_MSS(h) LO_TCP_MSS(h)
# define __MAX_TCP_MSS(h) LO_TCP_MSS(h)
# endif
# undef __LAST_MIN_TCP_MSS
# undef __LAST_MAX_TCP_MSS
# define __LAST_MIN_TCP_MSS(h) __MIN_TCP_MSS(h)
# define __LAST_MAX_TCP_MSS(h) __MAX_TCP_MSS(h)
# undef __MIN_TCP_MSS
# undef __MAX_TCP_MSS
# define __MIN_TCP_MSS(h) MIN(LO_TCP_MSS(h),__6LOWPAN_MIN_TCP_MSS(h))
# define __MAX_TCP_MSS(h) MAX(LO_TCP_MSS(h),__6LOWPAN_MAX_TCP_MSS(h))
# define __LOOP_MIN_TCP_MSS(h) MIN(LO_TCP_MSS(h),__6LOWPAN_MIN_TCP_MSS(h))
# define __LOOP_MAX_TCP_MSS(h) MAX(LO_TCP_MSS(h),__6LOWPAN_MAX_TCP_MSS(h))
# else
# define __LOOP_MIN_TCP_MSS(h) _6LOWPAN_MIN_TCP_MSS(h)
# define __LOOP_MAX_TCP_MSS(h) __6LOWPAN_MAX_TCP_MSS(h)
# endif
# ifdef CONFIG_NET_SLIP
# ifdef __LAST_MIN_TCP_MSS
# define __MIN_TCP_MSS(h) MIN(SLIP_TCP_MSS(h),__LAST_MIN_TCP_MSS(h))
# define __MAX_TCP_MSS(h) MAX(SLIP_TCP_MSS(h),__LAST_MAX_TCP_MSS(h))
# else
# define __MIN_TCP_MSS(h) SLIP_TCP_MSS(h)
# define __MAX_TCP_MSS(h) SLIP_TCP_MSS(h)
# endif
# undef __LAST_MIN_TCP_MSS
# undef __LAST_MAX_TCP_MSS
# define __LAST_MIN_TCP_MSS(h) __MIN_TCP_MSS(h)
# define __LAST_MAX_TCP_MSS(h) __MAX_TCP_MSS(h)
# undef __MIN_TCP_MSS
# undef __MAX_TCP_MSS
# define __MIN_TCP_MSS(h) MIN(SLIP_TCP_MSS(h),__LOOP_MIN_TCP_MSS(h))
# define __MAX_TCP_MSS(h) MAX(SLIP_TCP_MSS(h),__LOOP_MAX_TCP_MSS(h))
# define __SLIP_MIN_TCP_MSS(h) MIN(SLIP_TCP_MSS(h),__LOOP_MIN_TCP_MSS(h))
# define __SLIP_MAX_TCP_MSS(h) MAX(SLIP_TCP_MSS(h),__LOOP_MAX_TCP_MSS(h))
# else
# define __SLIP_MIN_TCP_MSS(h) __LOOP_MIN_TCP_MSS(h)
# define __SLIP_MAX_TCP_MSS(h) __LOOP_MAX_TCP_MSS(h)
# endif
# undef __LAST_MIN_TCP_MSS
# undef __LAST_MAX_TCP_MSS
#endif
/* If IPv4 is supported, it will have the larger MSS.

View File

@ -53,6 +53,7 @@
#include <stdint.h>
#include <nuttx/clock.h>
#include <nuttx/net/iob.h>
#include <nuttx/net/netdev.h>
@ -71,9 +72,13 @@
#define SIXLOWPAN_DISPATCH_IPV6 0x41 /* 01000001 = 65 */
#define SIXLOWPAN_DISPATCH_HC1 0x42 /* 01000010 = 66 */
#define SIXLOWPAN_DISPATCH_IPHC 0x60 /* 011xxxxx = ... */
#define SIXLOWPAN_DISPATCH_IPHC 0x60 /* 011xxxxx */
#define SIXLOWPAN_DISPATCH_IPHC_MASK 0xe0 /* 11100000 */
#define SIXLOWPAN_DISPATCH_FRAG1 0xc0 /* 11000xxx */
#define SIXLOWPAN_DISPATCH_FRAGN 0xe0 /* 11100xxx */
#define SIXLOWPAN_DISPATCH_FRAG_MASK 0xf1 /* 11111000 */
/* HC1 encoding */
@ -155,77 +160,6 @@
#define SIXLOWPAN_FRAG1_HDR_LEN 4
#define SIXLOWPAN_FRAGN_HDR_LEN 5
/* Address compressibility test macros */
/* Check whether we can compress the IID in address 'a' to 16 bits. This is
* used for unicast addresses only, and is true if the address is on the
* format <PREFIX>::0000:00ff:fe00:XXXX
*
* NOTE: we currently assume 64-bits prefixes
*/
#define SIXLOWPAN_IS_IID_16BIT_COMPRESSABLE(a) \
((((a)->u16[4]) == 0) && \
// (((a)->u8[10]) == 0)&& \
(((a)->u8[11]) == 0xff)&& \
(((a)->u8[12]) == 0xfe)&& \
(((a)->u8[13]) == 0))
/* Check whether the 9-bit group-id of the compressed multicast address is
* known. It is true if the 9-bit group is the all nodes or all routers
* group. Parameter 'a' is typed uint8_t *
*/
#define SIXLOWPAN_IS_MCASTADDR_DECOMPRESSABLE(a) \
(((*a & 0x01) == 0) && \
((*(a + 1) == 0x01) || (*(a + 1) == 0x02)))
/* Check whether the 112-bit group-id of the multicast address is mappable
* to a 9-bit group-id. It is true if the group is the all nodes or all
* routers group.
*/
#define SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE(a) \
((((a)->u16[1]) == 0) && \
(((a)->u16[2]) == 0) && \
(((a)->u16[3]) == 0) && \
(((a)->u16[4]) == 0) && \
(((a)->u16[5]) == 0) && \
(((a)->u16[6]) == 0) && \
(((a)->u8[14]) == 0) && \
((((a)->u8[15]) == 1) || (((a)->u8[15]) == 2)))
/* FFXX::00XX:XXXX:XXXX */
#define SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE48(a) \
((((a)->u16[1]) == 0) && \
(((a)->u16[2]) == 0) && \
(((a)->u16[3]) == 0) && \
(((a)->u16[4]) == 0) && \
(((a)->u8[10]) == 0))
/* FFXX::00XX:XXXX */
#define SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE32(a) \
((((a)->u16[1]) == 0) && \
(((a)->u16[2]) == 0) && \
(((a)->u16[3]) == 0) && \
(((a)->u16[4]) == 0) && \
(((a)->u16[5]) == 0) && \
(((a)->u8[12]) == 0))
/* FF02::00XX */
#define SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE8(a) \
((((a)->u8[1]) == 2) && \
(((a)->u16[1]) == 0) && \
(((a)->u16[2]) == 0) && \
(((a)->u16[3]) == 0) && \
(((a)->u16[4]) == 0) && \
(((a)->u16[5]) == 0) && \
(((a)->u16[6]) == 0) && \
(((a)->u8[14]) == 0))
/* This maximum size of an IEEE802.15.4 frame. Certain, non-standard
* devices may exceed this value, however.
*/
@ -402,6 +336,7 @@ struct ieee802154_driver_s
FAR struct iob_s *i_framelist;
/* Driver Configuration ***************************************************/
/* i_panid. The PAN ID is 16-bit number that identifies the network. It
* must be unique to differentiate a network. All the nodes in the same
* network should have the same PAN ID. This value must be provided to
@ -433,30 +368,42 @@ struct ieee802154_driver_s
*/
uint16_t i_dgramtag;
};
/* The structure of a next header compressor. This compressor is provided
* by architecture-specific logic outside of the network stack.
*
* TODO: needs more parameters when compressing extension headers, etc.
*/
struct sixlowpan_nhcompressor_s
{
CODE int (*is_compressable)(uint8_t next_header);
/* Compress next header (TCP/UDP, etc) - ptr points to next header to
* compress.
#if CONFIG_NET_6LOWPAN_FRAG
/* Fragmentation Support *************************************************/
/* Fragementation is handled frame by frame and requires that certain
* state information be retained from frame to frame.
*/
CODE int (*compress)(FAR uint8_t *compressed, FAR uint8_t *uncompressed_len);
/* Uncompress next header (TCP/UDP, etc) - ptr points to next header to
* uncompress.
/* i_pktlen. The total length of the IPv6 packet to be re-assembled in
* d_buf.
*/
CODE int (*uncompress)(FAR uint8_t *compressed, FAR uint8_t *lowpanbuf,
FAR uint8_t *uncompressed_len);
uint16_t i_pktlen;
/* The current accumulated length of the packet being received in d_buf.
* Included IPv6 and protocol headers.
*/
uint16_t i_accumlen;
/* i_reasstag. Each frame in the reassembly has a tag. That tag must
* match the reassembly tag in the fragments being merged.
*/
uint16_t i_reasstag;
/* The source MAC address of the fragments being merged */
struct rimeaddr_s i_fragsrc;
/* That time at which reassembly was started. If the elapsed time
* exceeds CONFIG_NET_6LOWPAN_MAXAGE, then the reassembly will
* be cancelled.
*/
systime_t i_time;
#endif /* CONFIG_NET_6LOWPAN_FRAG */
};
/****************************************************************************
@ -518,21 +465,4 @@ struct sixlowpan_nhcompressor_s
int sixlowpan_input(FAR struct ieee802154_driver_s *ieee);
/****************************************************************************
* Function: sixlowpan_set_compressor
*
* Description:
* Configure to use the architecture-specific compressor.
*
* Input parameters:
* compressor - A reference to the new compressor to be used. This may
* be a NULL value to disable the compressor.
*
* Returned Value:
* None
*
****************************************************************************/
void sixlowpan_set_compressor(FAR struct sixlowpan_nhcompressor_s *compressor);
#endif /* __INCLUDE_NUTTX_NET_SIXLOWOAN_H */

View File

@ -95,6 +95,7 @@
#include "neighbor/neighbor.h"
#include "tcp/tcp.h"
#include "udp/udp.h"
#include "sixlowpan/sixlowpan.h"
#include "pkt/pkt.h"
#include "icmpv6/icmpv6.h"
@ -255,12 +256,45 @@ int ipv6_input(FAR struct net_driver_s *dev)
{
#ifdef NET_TCP_HAVE_STACK
case IP_PROTO_TCP: /* TCP input */
/* Forward the IPv6 TCP packet */
tcp_ipv6_input(dev);
break;
#ifdef CONFIG_NET_6LOWPAN
/* TCP output comes through two different mechansims. Either from:
*
* 1. TCP socket output. For the case of TCP output to an
* IEEE802.15.4, the TCP output is caught in the socket
* send()/sendto() logic and and redirected to 6loWPAN logic.
* 2. TCP output from the TCP state machine. That will pass
* here and can be detected if d_len > 0. It will be redirected
* to 6loWPAN logic here.
*/
#ifdef CONFIG_NET_MULTILINK
/* Handle the case where multiple link layer protocols are supported */
if (dev->d_len > 0 && dev->d_lltype == CONFIG_NET_6LOWPAN)
#else
if (dev->d_len > 0)
#endif
{
/* Let 6loWPAN handle the TCP output */
sixlowpan_tcp_send(dev);
/* Drop the packet in the d_buf */
goto drop;
}
#endif /* CONFIG_NET_6LOWPAN */
break;
#endif /* NET_TCP_HAVE_STACK */
#ifdef NET_UDP_HAVE_STACK
case IP_PROTO_UDP: /* UDP input */
/* Forward the IPv6 UDP packet */
udp_ipv6_input(dev);
break;
#endif
@ -269,6 +303,8 @@ int ipv6_input(FAR struct net_driver_s *dev)
#ifdef CONFIG_NET_ICMPv6
case IP_PROTO_ICMP6: /* ICMP6 input */
/* Forward the ICMPv6 packet */
icmpv6_input(dev);
break;
#endif

View File

@ -132,7 +132,8 @@ config NET_6LOWPAN_MAXAGE
int "Packet reassembly timeout"
default 20
---help---
Timeout for packet reassembly at the 6lowpan layer (should be < 60s)
Timeout for packet reassembly at the 6lowpan layer in units of
seconds (should be < 60s)
config NET_6LOWPAN_MAX_MACTRANSMITS
int "Max MAC transmissions"

View File

@ -41,7 +41,7 @@ ifeq ($(CONFIG_NET_6LOWPAN),y)
NET_CSRCS += sixlowpan_initialize.c sixlowpan_globals.c sixlowpan_utils.c
NET_CSRCS += sixlowpan_input.c sixlowpan_send.c sixlowpan_framer.c
NET_CSRCS += sixlowpan_framelist.c sixlowpan_compressor.c
NET_CSRCS += sixlowpan_framelist.c
ifeq ($(CONFIG_NET_TCP),y)
NET_CSRCS += sixlowpan_tcpsend.c

View File

@ -53,7 +53,9 @@
* Public Function Prototypes
****************************************************************************/
struct socket; /* Forward reference */
struct net_driver_s; /* Forward reference */
struct socket; /* Forward reference */
struct sockaddr; /* Forward reference */
/****************************************************************************
* Name: sixlowpan_initialize
@ -104,6 +106,33 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
size_t len);
#endif
/****************************************************************************
* Function: sixlowpan_tcp_send
*
* Description:
* TCP output comes through two different mechansims. Either from:
*
* 1. TCP socket output. For the case of TCP output to an
* IEEE802.15.4, the TCP output is caught in the socket
* send()/sendto() logic and and redirected to psock_6lowpan_tcp_send().
* 2. TCP output from the TCP state machine. That will occur
* during TCP packet processing by the TCP state meachine. It
* is detected there when ipv6_tcp_input() returns with d_len > 0. This
* will be redirected here.
*
* Parameters:
* dev - An instance of nework device state structure
*
* Returned Value:
* None
*
* Assumptions:
* Called with the network locked.
*
****************************************************************************/
void sixlowpan_tcp_send(FAR struct net_driver_s *dev);
/****************************************************************************
* Function: psock_6lowpan_udp_send
*
@ -132,5 +161,39 @@ ssize_t psock_6lowpan_udp_send(FAR struct socket *psock, FAR const void *buf,
size_t len);
#endif
/****************************************************************************
* Function: psock_6lowpan_udp_sendto
*
* Description:
* If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET)
* socket, the parameters to and 'tolen' are ignored (and the error EISCONN
* may be returned when they are not NULL and 0), and the error ENOTCONN is
* returned when the socket was not actually connected.
*
* Parameters:
* psock A pointer to a NuttX-specific, internal socket structure
* buf Data to send
* len Length of data to send
* flags Send flags
* to Address of recipient
* tolen The length of the address structure
*
* Returned Value:
* On success, returns the number of characters sent. On error,
* -1 is returned, and errno is set appropriately. Returned error
* number must be consistent with definition of errors reported by
* sendto().
*
* Assumptions:
* Called with the network locked.
*
****************************************************************************/
ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock,
FAR const void *buf,
size_t len, int flags,
FAR const struct sockaddr *to,
socklen_t tolen);
#endif /* CONFIG_NET_6LOWPAN */
#endif /* _NET_SIXLOWPAN_SIXLOWPAN_H */

View File

@ -1,79 +0,0 @@
/****************************************************************************
* net/sixlowpan/sixlowpan_compressor.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include "nuttx/net/net.h"
#include "sixlowpan/sixlowpan_internal.h"
#ifdef CONFIG_NET_6LOWPAN
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Function: sixlowpan_set_compressor
*
* Description:
* Configure to use the architecture-specific compressor.
*
* Input parameters:
* compressor - A reference to the new compressor to be used. This may
* be a NULL value to disable the compressor.
*
* Returned Value:
* None
*
****************************************************************************/
void sixlowpan_set_compressor(FAR struct sixlowpan_nhcompressor_s *compressor)
{
/* Make sure that the compressor is not in use */
net_lock();
/* Then instantiate the new compressor */
g_sixlowpan_compressor = compressor;
net_unlock();
}
#endif /* CONFIG_NET_6LOWPAN */

View File

@ -100,8 +100,8 @@
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Input Parameters:
* ieee - Pointer to IEEE802.15.4 MAC driver structure.
* ipv6 - Pointer to the IPv6 header to "compress"
* ieee - Pointer to IEEE802.15.4 MAC driver structure.
* destip - Pointer to the IPv6 header to "compress"
*
* Returned Value:
* None
@ -109,7 +109,7 @@
****************************************************************************/
static void sixlowpan_compress_ipv6hdr(FAR struct ieee802154_driver_s *ieee,
FAR const struct ipv6_hdr_s *ipv6)
FAR const struct ipv6_hdr_s *destip)
{
/* Indicate the IPv6 dispatch and length */
@ -118,7 +118,7 @@ static void sixlowpan_compress_ipv6hdr(FAR struct ieee802154_driver_s *ieee,
/* Copy the IPv6 header and adjust pointers */
memcpy(g_rimeptr + g_rime_hdrlen, ipv6, IPv6_HDRLEN);
memcpy(g_rimeptr + g_rime_hdrlen, destip, IPv6_HDRLEN);
g_rime_hdrlen += IPv6_HDRLEN;
g_uncomp_hdrlen += IPv6_HDRLEN;
}
@ -161,12 +161,12 @@ static void sixlowpan_compress_ipv6hdr(FAR struct ieee802154_driver_s *ieee,
int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
FAR const struct ipv6_hdr_s *destip,
FAR const void *buf, size_t len,
FAR const void *buf, size_t len,
FAR const struct rimeaddr_s *destmac)
{
FAR struct iob_s *iob;
int framer_hdrlen;
struct rimeaddr_s dest;
struct rimeaddr_s bcastmac;
uint16_t outlen = 0;
/* Initialize global data. Locking the network guarantees that we have
@ -211,13 +211,24 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
if (destmac == NULL)
{
memset(&dest, 0, sizeof(struct rimeaddr_s));
}
else
{
rimeaddr_copy(&dest, (FAR const struct rimeaddr_s *)destmac);
memset(&bcastmac, 0, sizeof(struct rimeaddr_s));
destmac = &bcastmac;
}
/* Pre-allocate the IOB to hold frame or the first fragment, waiting if
* necessary.
*/
iob = iob_alloc(false);
DEBUGASSERT(iob != NULL);
/* Initialize the IOB */
iob->io_flink = NULL;
iob->io_len = 0;
iob->io_offset = 0;
iob->io_pktlen = 0;
ninfo("Sending packet len %d\n", len);
#ifndef CONFIG_NET_6LOWPAN_COMPRESSION_IPv6
@ -226,9 +237,9 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
/* Try to compress the headers */
#if defined(CONFIG_NET_6LOWPAN_COMPRESSION_HC1)
sixlowpan_compresshdr_hc1(ieee, &dest);
sixlowpan_compresshdr_hc1(ieee, destip, destmac, iob);
#elif defined(CONFIG_NET_6LOWPAN_COMPRESSION_HC06)
sixlowpan_compresshdr_hc06(ieee, &dest);
sixlowpan_compresshdr_hc06(ieee, destip, destmac, iob);
#else
# error No compression specified
#endif
@ -243,7 +254,7 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
ninfo("Header of len %d\n", g_rime_hdrlen);
rimeaddr_copy(&g_pktaddrs[PACKETBUF_ADDR_RECEIVER], &dest);
rimeaddr_copy(&g_pktaddrs[PACKETBUF_ADDR_RECEIVER], destmac);
/* Pre-calculate frame header length. */
@ -279,20 +290,8 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
ninfo("Fragmentation sending packet len %d\n", len);
/* Allocate an IOB to hold the first fragment, waiting if necessary. */
iob = iob_alloc(false);
DEBUGASSERT(iob != NULL);
/* Initialize the IOB */
iob->io_flink = NULL;
iob->io_len = 0;
iob->io_offset = 0;
iob->io_pktlen = 0;
/* Create 1st Fragment */
/* Add the frame header */
/* Add the frame header using the pre-allocated IOB. */
verify = sixlowpan_framecreate(ieee, iob, ieee->i_panid);
DEBUGASSERT(verify == framer_hdrlen);
@ -434,19 +433,7 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
* and send in one frame.
*/
/* Allocate an IOB to hold the frame, waiting if necessary. */
iob = iob_alloc(false);
DEBUGASSERT(iob != NULL);
/* Initialize the IOB */
iob->io_flink = NULL;
iob->io_len = 0;
iob->io_offset = 0;
iob->io_pktlen = 0;
/* Add the frame header */
/* Add the frame header to the prealloated IOB. */
verify = sixlowpan_framecreate(ieee, iob, ieee->i_panid);
DEBUGASSERT(vreify == framer_hdrlen);

View File

@ -47,10 +47,6 @@
* Public Data
****************************************************************************/
/* A pointer to the optional, architecture-specific compressor */
FAR struct sixlowpan_nhcompressor_s *g_sixlowpan_compressor;
/* The following data values are used to hold intermediate settings while
* processing IEEE802.15.4 frames. These globals are shared with incoming
* and outgoing frame processing and possibly with mutliple IEEE802.15.4 MAC

File diff suppressed because it is too large Load Diff

View File

@ -53,6 +53,17 @@
#ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC1
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Buffer access helpers */
#define IPv6BUF(dev) \
((FAR struct ipv6_hdr_s *)((dev)->d_buf))
#define UDPIPv6BUF(dev) \
((FAR struct udp_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev) + IPv6_HDRLEN])
/****************************************************************************
* Public Functions
****************************************************************************/
@ -102,9 +113,11 @@
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Input Parmeters:
* ieee - A reference to the IEE802.15.4 network device state
* destaddr - L2 destination address, needed to compress the IP
* destination field
* ieee - A reference to the IEE802.15.4 network device state
* ipv6 - The IPv6 header to be compressed
* destmac - L2 destination address, needed to compress the IP
* destination field
* iob - The IOB into which the compressed header should be saved.
*
* Returned Value:
* None
@ -112,9 +125,109 @@
****************************************************************************/
void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
FAR struct rimeaddr_s *destaddr)
FAR const struct ipv6_hdr_s *ipv6,
FAR const struct rimeaddr_s *destmac,
FAR struct iob_s *iob)
{
/* REVISIT: To be provided */
FAR uint8_t *hc1 = RIME_HC1_PTR;
/* Check if all the assumptions for full compression are valid */
if (ipv6->vtc != 0x60 || ipv6->tcflow != 0 || ipv6->flow != 0 ||
!sixlowpan_islinklocal(&ipv6->srcipaddr) ||
!sixlowpan_ismacbased(&ipv6->srcipaddr, &ieee->i_rimeaddr) ||
!sixlowpan_islinklocal(&ipv6->destipaddr) ||
!sixlowpan_ismacbased(&ipv6->destipaddr, destmac) ||
(ipv6->proto != IP_PROTO_ICMP6 && ipv6->proto != IP_PROTO_UDP &&
ipv6->proto != IP_PROTO_TCP))
{
/* IPV6 DISPATCH
* Something cannot be compressed, use IPV6 DISPATCH,
* compress nothing, copy IPv6 header in rime buffer
*/
*g_rimeptr = SIXLOWPAN_DISPATCH_IPV6;
g_rime_hdrlen += SIXLOWPAN_IPV6_HDR_LEN;
memcpy(g_rimeptr + g_rime_hdrlen, ipv6, IPv6_HDRLEN);
g_rime_hdrlen += IPv6_HDRLEN;
g_uncomp_hdrlen += IPv6_HDRLEN;
}
else
{
/* HC1 DISPATCH maximum compresssion:
* All fields in the IP header but Hop Limit are elided. If next
* header is UDP, we compress UDP header using HC2
*/
hc1[RIME_HC1_DISPATCH] = SIXLOWPAN_DISPATCH_HC1;
g_uncomp_hdrlen += IPv6_HDRLEN;
switch (ipv6->proto)
{
case IP_PROTO_ICMP6:
/* HC1 encoding and ttl */
hc1[RIME_HC1_ENCODING] = 0xfc;
hc1[RIME_HC1_TTL] = ipv6->ttl;
g_rime_hdrlen += SIXLOWPAN_HC1_HDR_LEN;
break;
#if CONFIG_NET_TCP
case IP_PROTO_TCP:
/* HC1 encoding and ttl */
hc1[RIME_HC1_ENCODING] = 0xfe;
hc1[RIME_HC1_TTL] = ipv6->ttl;
g_rime_hdrlen += SIXLOWPAN_HC1_HDR_LEN;
break;
#endif /* CONFIG_NET_TCP */
#if CONFIG_NET_UDP
case IP_PROTO_UDP:
FAR struct udp_hdr_s *udp = UDPIPv6BUF(dev);
/* Try to compress UDP header (we do only full compression). This
* is feasible if both src and dest ports are between
* SIXLOWPAN_UDP_PORT_MIN and SIXLOWPAN_UDP_PORT_MIN + 15
*/
ninfo("local/remote port %u/%u\n", udp->srcport, udp->destport);
if (htons(udp->srcport) >= SIXLOWPAN_UDP_PORT_MIN &&
htons(udp->srcport) < SIXLOWPAN_UDP_PORT_MAX &&
htons(udp->destport) >= SIXLOWPAN_UDP_PORT_MIN &&
htons(udp->destport) < SIXLOWPAN_UDP_PORT_MAX)
{
FAR uint8_t *hcudp = RIME_HC1_HC_UDP_PTR;
/* HC1 encoding */
hcudp[RIME_HC1_HC_UDP_HC1_ENCODING] = 0xfb;
/* HC_UDP encoding, ttl, src and dest ports, checksum */
hcudp[RIME_HC1_HC_UDP_UDP_ENCODING] = 0xe0;
hcudp[RIME_HC1_HC_UDP_TTL] = ipv6->ttl;
hcudp[RIME_HC1_HC_UDP_PORTS] =
(uint8_t)((htons(udp->srcport) - SIXLOWPAN_UDP_PORT_MIN) << 4) +
(uint8_t)((htons(udp->destport) - SIXLOWPAN_UDP_PORT_MIN));
memcpy(&hcudp[RIME_HC1_HC_UDP_CHKSUM], &udp->udpchksum, 2);
g_rime_hdrlen += SIXLOWPAN_HC1_HC_UDP_HDR_LEN;
g_uncomp_hdrlen += UIP_UDPH_LEN;
}
else
{
/* HC1 encoding and ttl */
hc1[RIME_HC1_ENCODING] = 0xfa;
hc1[RIME_HC1_TTL] = ipv6->ttl;
g_rime_hdrlen += SIXLOWPAN_HC1_HDR_LEN;
}
break;
#endif /* CONFIG_NET_UDP */
}
}
}
/****************************************************************************
@ -136,14 +249,127 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
* fragment.
*
* Returned Value:
* None
* Zero (OK) is returned on success, on failure a negater errno value is
* returned.
*
****************************************************************************/
void sixlowpan_uncompresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
uint16_t iplen)
int sixlowpan_uncompresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
uint16_t iplen)
{
/* REVISIT: To be provided */
FAR struct ipv6_hdr_s *ipv6 = IPv6BUF(&ieee->i_dev);
FAR uint8_t *hc1 = RIME_HC1_PTR;
/* Format the IPv6 header in the device d_buf */
/* Set version, traffic clase, and flow label */
ipv6->vtc = 0x60; /* Bits 0-3: version, bits 4-7: traffic class (MS) */
ipv6->tcf = 0; /* Bits 0-3: traffic class (LS), 4-bits: flow label (MS) */
ipv6->flow = 0; /* 16-bit flow label (LS) */
/* Use stateless auto-configuration to set source and destination IP
* addresses.
*/
sixlowpan_ipfromrime(&g_pktaddrs[PACKETBUF_ADDR_SENDER],
&ipv6->srcipaddr);
sixlowpan_ipfromrime(&g_pktaddrs[PACKETBUF_ADDR_RECEIVER],
&ipv6->destipaddr);
g_uncomp_hdrlen += IPv6_HDRLEN;
/* len[], proto, and ttl depend on the encoding */
switch (hc1[RIME_HC1_ENCODING] & 0x06)
{
case SIXLOWPAN_HC1_NH_ICMP6:
ipv6->proto = IP_PROTO_ICMP6;
ipv6->ttl = hc1[RIME_HC1_TTL];
g_rime_hdrlen += SIXLOWPAN_HC1_HDR_LEN;
break;
#if CONFIG_NET_TCP
case SIXLOWPAN_HC1_NH_TCP:
ipv6->proto = IP_PROTO_TCP;
ipv6->ttl = hc1[RIME_HC1_TTL];
g_rime_hdrlen += SIXLOWPAN_HC1_HDR_LEN;
break;
#endif /* CONFIG_NET_TCP */
#if CONFIG_NET_UDP
case SIXLOWPAN_HC1_NH_UDP:
{
FAR struct udp_hdr_s *udp = UDPIPv6BUF(&ieee->i_dev);
FAR uint8_t *hcudp = RIME_HC1_HC_UDP_PTR;
ipv6->proto = IP_PROTO_UDP;
if ((hcudp[RIME_HC1_HC_UDP_HC1_ENCODING] & 0x01) != 0)
{
/* UDP header is compressed with HC_UDP */
if (hcudp[RIME_HC1_HC_UDP_UDP_ENCODING] !=
SIXLOWPAN_HC_UDP_ALL_C)
{
nwarn("WARNING: sixlowpan (uncompress_hdr), packet not supported");
return -EOPNOTSUPP;
}
/* IP TTL */
ipv6->ttl = hcudp[RIME_HC1_HC_UDP_TTL];
/* UDP ports, len, checksum */
udp->srcport =
htons(SIXLOWPAN_UDP_PORT_MIN + (hcudp[RIME_HC1_HC_UDP_PORTS] >> 4));
udp->destport =
htons(SIXLOWPAN_UDP_PORT_MIN + (hcudp[RIME_HC1_HC_UDP_PORTS] & 0x0F));
memcpy(&udp->udpchksum, &hcudp[RIME_HC1_HC_UDP_CHKSUM], 2);
g_uncomp_hdrlen += UIP_UDPH_LEN;
g_rime_hdrlen += SIXLOWPAN_HC1_HC_UDP_HDR_LEN;
}
else
{
g_rime_hdrlen += SIXLOWPAN_HC1_HDR_LEN;
}
}
break;
#endif /* CONFIG_NET_UDP */
default:
return -EPROTONOSUPPORT;
}
/* IP length field. */
if (iplen == 0)
{
/* This is not a fragmented packet */
ipv6->len[0] = 0;
ipv6->len[1] = ieee->i_dev.d_len - g_rime_hdrlen + /* REVISIT */
g_uncomp_hdrlen - IPv6_HDRLEN;
}
else
{
/* This is a 1st fragment */
ipv6->len[0] = (iplen - IPv6_HDRLEN) >> 8;
ipv6->len[1] = (iplen - IPv6_HDRLEN) & 0x00FF;
}
/* length field in UDP header */
#if CONFIG_NET_UDP
if (ipv6->proto == IP_PROTO_UDP)
{
FAR struct udp_hdr_s *udp = UDPIPv6BUF(&ieee->i_dev);
memcpy(&udp->udplen, &ipv6->len[0], 2);
}
#endif
return;
}
#endif /* CONFIG_NET_6LOWPAN_COMPRESSION_HC1 */

View File

@ -1,6 +1,6 @@
/****************************************************************************
* net/sixlowpan/sixlowpan_input.c
* 6lowpan implementation (RFC4944 and draft-ietf-6lowpan-hc-06)
* 6loWPAN implementation (RFC4944 and draft-ietf-6loWPAN-hc-06)
*
* Copyright (C) 2017, Gregory Nutt, all rights reserved
* Author: Gregory Nutt <gnutt@nuttx.org>
@ -49,10 +49,15 @@
#include <nuttx/config.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#if CONFIG_NET_6LOWPAN_FRAG
# include "nuttx/clock.h"
#endif
#include "nuttx/net/netdev.h"
#include "nuttx/net/ip.h"
#include "nuttx/net/sixlowpan.h"
@ -74,95 +79,18 @@
#define INPUT_PARTIAL 0 /* Frame processed successful, packet incomplete */
#define INPUT_COMPLETE 1 /* Frame processed successful, packet complete */
/* Re-assembly timeout in clock ticks */
#define NET_6LOWPAN_TIMEOUT SEC2TICK(CONFIG_NET_6LOWPAN_MAXAGE)
/* Buffer access helpers */
#define IPv6BUF(dev) ((FAR struct ipv6_hdr_s *)((dev)->d_buf))
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Function: sixlowpan_isbroadcast
*
* Description:
* Return the address length associated with a 2-bit address mode
*
* Input parameters:
* addrmode - The address mode
*
* Returned Value:
* The address length associated with the address mode.
*
****************************************************************************/
static bool sixlowpan_isbroadcast(uint8_t mode, FAR uint8_t *addr)
{
int i = ((mode == FRAME802154_SHORTADDRMODE) ? 2 : 8);
while (i-- > 0)
{
if (addr[i] != 0xff)
{
return false;
}
}
return true;
}
/****************************************************************************
* 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 */
g_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;
}
g_pktattrs[PACKETBUF_ATTR_CHANNEL] = attr;
}
/****************************************************************************
* Name: sixlowpan_frame_process
*
@ -185,13 +113,365 @@ static void sixlowpan_set_pktattrs(FAR struct ieee802154_driver_s *ieee,
* Returned Value:
* Ok is returned on success; Othewise a negated errno value is returned.
*
* Assumptions:
* Network is locked
*
****************************************************************************/
static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee,
FAR struct iob_s *iob)
{
/* REVISIT: To be provided */
return -ENOSYS;
FAR uint8_t *hc1 = RIME_HC1_PTR;
uint16_t fragsize = 0; /* Size of the IP packet (read from fragment) */
uint8_t fragoffset = 0; /* Offset of the fragment in the IP packet */
bool isfrag = false;
int reqsize; /* Required buffer size */
#if CONFIG_NET_6LOWPAN_FRAG
bool isfirstfrag = false;
bool islastfrag = false;
uint16_t fragtag = 0; /* Tag of the fragment */
systime_t elapsed; /* Elapsed time */
#endif /* CONFIG_NET_6LOWPAN_FRAG */
/* Initialize global data. Locking the network guarantees that we have
* exclusive use of the global values for intermediate calculations.
*/
g_uncomp_hdrlen = 0;
g_rime_hdrlen = 0;
/* The MAC puts the 15.4 payload inside the RIME data buffer */
g_rimeptr = &iob->io_data[PACKETBUF_HDR_SIZE];
#if CONFIG_NET_6LOWPAN_FRAG
/* If reassembly timed out, cancel it */
elapsed = clock_systimer() - ieee->i_time;
if (elapsed > NET_6LOWPAN_TIMEOUT)
{
nwarn("WARNING: Reassembly timed out\n");
ieee->i_pktlen = 0;
ieee->i_accumlen = 0;
}
/* Since we don't support the mesh and broadcast header, the first header
* we look for is the fragmentation header
*/
switch ((GETINT16(RIME_FRAG_PTR, RIME_FRAG_DISPATCH_SIZE) & 0xf800) >> 8)
{
/* First fragment of new reassembly */
case SIXLOWPAN_DISPATCH_FRAG1:
{
/* Set up for the reassembly */
fragoffset = 0;
fragsize = GETINT16(RIME_FRAG_PTR, RIME_FRAG_DISPATCH_SIZE) & 0x07ff;
fragtag = GETINT16(RIME_FRAG_PTR, RIME_FRAG_TAG);
ninfo("FRAG1: size %d, tag %d, offset %d\n",
fragsize, fragtag, fragoffset);
g_rime_hdrlen += SIXLOWPAN_FRAG1_HDR_LEN;
/* Indicate the first fragment of the reassembly */
isfirstfrag = true;
isfrag = true;
}
break;
case SIXLOWPAN_DISPATCH_FRAGN:
{
/* Set offset, tag, size. Offset is in units of 8 bytes. */
fragoffset = RIME_FRAG_PTR[RIME_FRAG_OFFSET];
fragtag = GETINT16(RIME_FRAG_PTR, RIME_FRAG_TAG);
fragsize = GETINT16(RIME_FRAG_PTR, RIME_FRAG_DISPATCH_SIZE) & 0x07ff;
ninfo("FRAGN: size %d, tag %d, offset %d\n",
fragsize, fragtag, fragoffset);
g_rime_hdrlen += SIXLOWPAN_FRAGN_HDR_LEN;
ninfo("islastfrag?: i_accumlen %d g_rime_payloadlen %d fragsize %d\n",
ieee->i_accumlen, iob->io_len - g_rime_hdrlen, fragsize);
/* Indicate that this frame is a another fragment for reassembly */
isfrag = true;
/* Check if it is the last fragement to be processed.
*
* If this is the last fragment, we may shave off any extrenous
* bytes at the end. We must be liberal in what we accept.
*/
if (ieee->i_accumlen + iob->io_len - g_rime_hdrlen >= fragsize)
{
islastfrag = true;
}
}
break;
/* Not a fragment */
default:
break;
}
/* Check if we are currently reassembling a packet */
if (ieee->i_accumlen > 0)
{
/* In this case what we expect is that the next frame will hold the
* next FRAGN of the sequence. We have to handle a few exeptional
* cases that we need to handle:
*
* 1. If we are currently reassembling a packet, but have just received
* the first fragment of another packet. We can either ignore it and
* hope to receive the rest of the under-reassembly packet fragments,
* or we can discard the previous packet altogether, and start
* reassembling the new packet. Here we discard the previous packet,
* and start reassembling the new packet.
* 2. The new frame is not a fragment. We should be able to handle this
* case, but we cannot because that would require two packet buffers.
* It could be handled with a more extensive design.
* 3. The fragment came from a different sender. What would this mean?
*
*/
if (!isfrag)
{
/* Discard the partially assembled packet */
nwarn("WARNING: Non-fragment frame received during reassembly\n");
ieee->i_pktlen = 0;
ieee->i_accumlen = 0;
}
/* It is a fragment of some kind. Drop any zero length fragments */
else if (fragsize == 0)
{
nwarn("WARNING: Dropping zero-length 6loWPAN fragment\n");
return OK;
}
/* A non-zero, first fragement received while we are in the middle of
* rassembly. Discard the partially assembled packet and start over.
*/
else if (isfirstfrag)
{
nwarn("WARNING: First fragment frame received during reassembly\n");
ieee->i_pktlen = 0;
ieee->i_accumlen = 0;
}
/* Verify that this fragment is part of that reassembly sequence */
else if (fragsize != ieee->i_pktlen || ieee->i_reasstag != fragtag ||
!rimeaddr_cmp(&ieee->i_fragsrc, &g_pktaddrs[PACKETBUF_ADDR_SENDER]))
{
/* The packet is a fragment that does not belong to the packet
* being reassembled or the packet is not a fragment.
*/
nwarn("WARNING: Dropping 6loWPAN packet that is not a fragment of "
"the packet currently being reassembled\n");
return OK;
}
/* Looks good. We are currently processing a reassembling sequence and
* we recieved a valid FRAGN fragment. Skip the header compression
* dispatch logic.
*/
goto copypayload;
}
/* There is no reassembly in progress. Check if we received a fragment */
else if (isfrag)
{
/* Another case that we have to handle is if a FRAGN fragment of a
* reassembly is received, but we are not currently reassembling a
* packet. I think we have no choice but to drop the packet in this
* case.
*/
if (!isfirstfrag)
{
nwarn("WARNING: FRAGN 6loWPAN fragment while not reassembling\n");
return OK;
}
/* Start reassembly if we received a non-zero length, first fragment */
if (fragsize > 0)
{
/* Drop the packet if it cannot fit into the d_buf */
if (fragsize > CONFIG_NET_6LOWPAN_MTU)
{
nwarn("WARNING: Reassembled packet size exeeds CONFIG_NET_6LOWPAN_MTU\n");
return OK;
}
/* Set up for the reassembly */
ieee->i_pktlen = fragsize;
ieee->i_reasstag = fragtag;
ieee->i_time = clock_systimer();
ninfo("Starting reassembly: i_pktlen %d, i_pktlen %d\n",
ieee->i_pktlen, ieee->i_reasstag);
rimeaddr_copy(&ieee->i_fragsrc, &g_pktaddrs[PACKETBUF_ADDR_SENDER]);
}
}
#endif /* CONFIG_NET_6LOWPAN_FRAG */
/* Process next dispatch and headers */
#ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC06
if ((hc1[RIME_HC1_DISPATCH] & SIXLOWPAN_DISPATCH_IPHC_MASK) == SIXLOWPAN_DISPATCH_IPHC)
{
ninfo("IPHC Dispatch\n");
sixlowpan_uncompresshdr_hc06(ieee, fragsize);
}
else
#endif /* CONFIG_NET_6LOWPAN_COMPRESSION_HC06 */
#ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC1
if (hc1[RIME_HC1_DISPATCH] == SIXLOWPAN_DISPATCH_HC1)
{
ninfo("HC1 Dispatch\n");
sixlowpan_uncompresshdr_hc1(ieee, fragsize);
}
else
#endif /* CONFIG_NET_6LOWPAN_COMPRESSION_HC1 */
if (hc1[RIME_HC1_DISPATCH] == SIXLOWPAN_DISPATCH_IPV6)
{
ninfo("IPV6 Dispatch\n");
g_rime_hdrlen += SIXLOWPAN_IPV6_HDR_LEN;
/* Put uncompressed IP header in d_buf. */
memcpy(ieee->i_dev.d_buf, g_rimeptr + g_rime_hdrlen, IPv6_HDRLEN);
/* Update g_uncomp_hdrlen and g_rime_hdrlen. */
g_rime_hdrlen += IPv6_HDRLEN;
g_uncomp_hdrlen += IPv6_HDRLEN;
}
else
{
/* Unknown or unsupported header */
nwarn("WARNING unknown dispatch: %u\n", hc1[RIME_HC1_DISPATCH]);
return OK;
}
#if CONFIG_NET_6LOWPAN_FRAG
copypayload:
#endif /* CONFIG_NET_6LOWPAN_FRAG */
/* Copy "payload" from the rime buffer to the d_buf. If this frame is a
* first fragment or not part of a fragmented packet, we have already
* copied the compressed headers, g_uncomp_hdrlen and g_rime_hdrlen are
* non-zerio, fragoffset is.
*/
if (ieee->i_dev.d_len < g_rime_hdrlen)
{
ninfo("SIXLOWPAN: packet dropped due to header > total packet\n");
return OK;
}
g_rime_payloadlen = ieee->i_dev.d_len - g_rime_hdrlen;
/* Sanity-check size of incoming packet to avoid buffer overflow */
reqsize = g_uncomp_hdrlen + (uint16_t) (fragoffset << 3) + g_rime_payloadlen;
if (reqsize > CONFIG_NET_6LOWPAN_MTU)
{
ninfo("Required buffer size: %d+%d+%d=%d Available: %d\n",
g_uncomp_hdrlen, (int)(fragoffset << 3), g_rime_payloadlen,
reqsize, CONFIG_NET_6LOWPAN_MTU);
return OK;
}
memcpy((FAR uint8_t *)ieee->i_dev.d_buf + g_uncomp_hdrlen +
(int)(fragoffset << 3), g_rimeptr + g_rime_hdrlen,
g_rime_payloadlen);
#if CONFIG_NET_6LOWPAN_FRAG
/* Update ieee->i_accumlen if the frame is a fragment, ieee->i_pktlen
* otherwise.
*/
if (isfrag)
{
/* Add the size of the header only for the first fragment. */
if (isfirstfrag)
{
ieee->i_accumlen += g_uncomp_hdrlen;
}
/* For the last fragment, we are OK if there is extraneous bytes at the
* end of the packet.
*/
if (islastfrag)
{
ieee->i_accumlen = fragsize;
}
else
{
ieee->i_accumlen += g_rime_payloadlen;
}
ninfo("i_accumlen %d, g_rime_payloadlen %d\n",
ieee->i_accumlen, g_rime_payloadlen);
}
else
#endif /* CONFIG_NET_6LOWPAN_FRAG */
{
ieee->i_pktlen = g_rime_payloadlen + g_uncomp_hdrlen;
}
#if CONFIG_NET_6LOWPAN_FRAG
/* If we have a full IP packet in sixlowpan_buf, deliver it to
* the IP stack
*/
ninfo("sixlowpan_init i_accumlen %d, ieee->i_pktlen %d\n",
ieee->i_accumlen, ieee->i_pktlen);
if (ieee->i_accumlen == 0 || ieee->i_accumlen == ieee->i_pktlen)
{
FAR struct ipv6_hdr_s *ipv6 = IPv6BUF(&ieee->i_dev);
ninfo("IP packet ready (length %d)\n", ieee->i_pktlen);
/* REVISIT -- clearly wrong. */
memcpy((FAR uint8_t *)ipv6, (FAR uint8_t *)ipv6, ieee->i_pktlen);
ieee->i_pktlen = 0;
ieee->i_accumlen = 0;
}
#endif /* CONFIG_NET_6LOWPAN_FRAG */
ninfodumpbuffer("IPv6 header", IPv6BUF(ieee->i_dev), IPv6_HDRLEN)
return OK;
}
/****************************************************************************
@ -326,7 +606,10 @@ int sixlowpan_input(FAR struct ieee802154_driver_s *ieee)
if (ieee->i_dev.d_len > 0)
{
FAR struct ipv6_hdr_s *ipv6hdr;
FAR uint8_t *buffer;
struct rimeaddr_s destmac;
size_t hdrlen;
size_t buflen;
/* The IPv6 header followed by TCP or UDP headers should
* lie at the beginning of d_buf since there is no link
@ -335,13 +618,53 @@ int sixlowpan_input(FAR struct ieee802154_driver_s *ieee)
ipv6hdr = (FAR struct ipv6_hdr_s *)(ieee->i_dev.d_buf);
/* Get the Rime MAC address of the destination */
#warning Missing logic
/* Get the Rime MAC address of the destination. This
* assumes an encoding of the MAC address in the IPv6
* address.
*/
sixlowpan_rimefromip(ipv6hdr->destipaddr, &destmac);
/* The data payload should follow the IPv6 header plus
* the protocol header.
*/
if (ipv6hdr->proto != IP_PROTO_TCP)
{
hdrlen = IPv6_HDRLEN + TCP_HDRLEN;
}
else if (ipv6hdr->proto != IP_PROTO_UDP)
{
hdrlen = IPv6_HDRLEN + UDP_HDRLEN;
}
else if (ipv6hdr->proto != IP_PROTO_ICMP6)
{
hdrlen = IPv6_HDRLEN + ICMPv6_HDRLEN;
}
else
{
nwarn("WARNING: Unsupported protoype: %u\n",
ipv6hdr->proto);
ret = -EPROTO;
goto drop;
}
if (hdrlen < ieee->i_dev.d_len)
{
nwarn("WARNING: Packet to small: Have %u need >%u\n",
ieee->i_dev.d_len, hdrlen);
ret = -ENOBUFS;
goto drop;
}
/* Convert the outgoing packet into a frame list. */
ret = sixlowpan_queue_frames(ieee, ipv6hdr, ieee->i_dev.d_buf,
ieee->i_dev.d_len, &destmac);
buffer = ieee->i_dev.d_buf + hdrlen;
buflen = ieee->i_dev.d_len - hdrlen;
ret = sixlowpan_queue_frames(ieee, ipv6hdr, buffer, buflen,
&destmac);
drop:
ieee->i_dev.d_len = 0;
}
}

View File

@ -89,7 +89,7 @@
* The fragment header is used when the payload is too large to fit in a
* single IEEE 802.15.4 frame. The fragment header contains three fields:
* Datagram size, datagram tag and datagram offset.
*
*
* 1. Datagram size describes the total (un-fragmented) payload.
* 2. Datagram tag identifies the set of fragments and is used to match
* fragments of the same payload.
@ -225,10 +225,72 @@
#define FRAME_SIZE(ieee,iob) \
((iob)->io_len)
/* Address compressibility test macros **************************************/
/* Check whether we can compress the IID in address 'a' to 16 bits. This is
* used for unicast addresses only, and is true if the address is on the
* format <PREFIX>::0000:00ff:fe00:XXXX
*
* NOTE: we currently assume 64-bits prefixes
*/
/* Check whether we can compress the IID in address 'a' to 16 bits. This is
* used for unicast addresses only, and is true if the address is on the
* format <PREFIX>::0000:00ff:fe00:XXXX.
*
* NOTE: we currently assume 64-bits prefixes. Big-endian, network order is
* assumed.
*/
#define SIXLOWPAN_IS_IID_16BIT_COMPRESSABLE(a) \
((((a)[4]) == 0x0000) && (((a)[5]) == 0x00ff) && (((a)[6]) == 0xfe00))
/* Check whether the 9-bit group-id of the compressed multicast address is
* known. It is true if the 9-bit group is the all nodes or all routers
* group. Parameter 'a' is typed uint8_t *
*/
#define SIXLOWPAN_IS_MCASTADDR_DECOMPRESSABLE(a) \
(((*a & 0x01) == 0) && \
((*(a + 1) == 0x01) || (*(a + 1) == 0x02)))
/* Check whether the 112-bit group-id of the multicast address is mappable
* to a 9-bit group-id. It is true if the group is the all nodes or all
* routers group:
*
* XXXX:0000:0000:0000:0000:0000:0000:0001 All nodes address
* XXXX:0000:0000:0000:0000:0000:0000:0002 All routers address
*/
#define SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE(a) \
((a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \
(a)[4] == 0 && (a)[5] == 0 && (a)[6] == 0 && \
((a)[7] == 0x0001 || (a)[7] == 0x0002))
/* FFXX:0000:0000:0000:0000:00XX:XXXX:XXXX */
#define SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE48(a) \
((a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \
(a)[4] == 0 && (((a)[5] & 0xff00) == 0))
/* FFXX:0000:0000:0000:0000:0000:00XX:XXXX */
#define SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE32(a) \
((a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \
(a)[4] == 0 && (a)[5] == 0 && ((a)[6] & 0xff00) == 0)
/* FF02:0000:0000:0000:0000:0000:0000:00XX */
#define SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE8(a) \
((((a)[0] & 0x00ff) == 0x0002) && \
(a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \
(a)[4] == 0 && (a)[5] == 0 && (a)[6] == 0 && \
(((a)[7] & 0xff00) == 0x0000))
/* General helper macros ****************************************************/
#define GETINT16(ptr,index) \
((((uint16_t)((ptr)[index]) << 8)) | ((uint16_t)(((ptr)[(index) + 1]))))
((((uint16_t)((ptr)[index])) << 8) | ((uint16_t)(((ptr)[(index) + 1]))))
#define PUTINT16(ptr,index,value) \
do \
{ \
@ -335,11 +397,6 @@ struct frame802154_s
* Public Data
****************************************************************************/
/* A pointer to the optional, architecture-specific compressor */
struct sixlowpan_nhcompressor_s; /* Foward reference */
extern FAR struct sixlowpan_nhcompressor_s *g_sixlowpan_compressor;
/* The following data values are used to hold intermediate settings while
* processing IEEE802.15.4 frames. These globals are shared with incoming
* and outgoing frame processing and possibly with mutliple IEEE802.15.4 MAC
@ -396,6 +453,7 @@ extern struct rimeaddr_s g_pktaddrs[PACKETBUF_NUM_ADDRS];
struct net_driver_s; /* Forward reference */
struct ieee802154_driver_s; /* Forward reference */
struct ipv6_hdr_s; /* Forward reference */
struct rimeaddr_s; /* Forward reference */
struct iob_s; /* Forward reference */
@ -407,7 +465,7 @@ struct iob_s; /* Forward reference */
* it to be sent on an 802.15.4 network using 6lowpan. Called from common
* UDP/TCP send logic.
*
* The payload data is in the caller 'buf' and is of length 'len'.
* The payload data is in the caller 'buf' and is of length 'buflen'.
* Compressed headers will be added and if necessary the packet is
* fragmented. The resulting packet/fragments are put in ieee->i_framelist
* and the entire list of frames will be delivered to the 802.15.4 MAC via
@ -415,9 +473,9 @@ struct iob_s; /* Forward reference */
*
* Input Parameters:
* dev - The IEEE802.15.4 MAC network driver interface.
* ipv6 - IPv6 plus TCP or UDP headers.
* destip - IPv6 plus TCP or UDP headers.
* buf - Data to send
* len - Length of data to send
* buflen - Length of data to send
* raddr - The MAC address of the destination
* timeout - Send timeout in deciseconds
*
@ -433,8 +491,8 @@ struct iob_s; /* Forward reference */
****************************************************************************/
int sixlowpan_send(FAR struct net_driver_s *dev,
FAR const struct ipv6_hdr_s *ipv6, FAR const void *buf,
size_t len, FAR const struct rimeaddr_s *raddr,
FAR const struct ipv6_hdr_s *destip, FAR const void *buf,
size_t buflen, FAR const struct rimeaddr_s *raddr,
uint16_t timeout);
/****************************************************************************
@ -499,7 +557,7 @@ int sixlowpan_framecreate(FAR struct ieee802154_driver_s *ieee,
* ieee - The IEEE802.15.4 MAC driver instance
* ipv6hdr - IPv6 header followed by TCP or UDP header.
* buf - Data to send
* len - Length of data to send
* buflen - Length of data to send
* destmac - The IEEE802.15.4 MAC address of the destination
*
* Returned Value:
@ -515,7 +573,7 @@ int sixlowpan_framecreate(FAR struct ieee802154_driver_s *ieee,
int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
FAR const struct ipv6_hdr_s *ipv6hdr,
FAR const void *buf, size_t len,
FAR const void *buf, size_t buflen,
FAR const struct rimeaddr_s *destmac);
/****************************************************************************
@ -542,7 +600,7 @@ void sixlowpan_hc06_initialize(void);
#endif
/****************************************************************************
* Name: sixlowpan_hc06_initialize
* Name: sixlowpan_compresshdr_hc06
*
* Description:
* Compress IP/UDP header
@ -559,7 +617,10 @@ void sixlowpan_hc06_initialize(void);
*
* Input Parameters:
* ieee - A reference to the IEE802.15.4 network device state
* destaddr - L2 destination address, needed to compress IP dest
* ipv6 - The IPv6 header to be compressed
* destmac - L2 destination address, needed to compress the IP
* destination field
* iob - The IOB into which the compressed header should be saved.
*
* Returned Value:
* None
@ -567,12 +628,14 @@ void sixlowpan_hc06_initialize(void);
****************************************************************************/
#ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC06
void sixlowpan_compresshdr_hc06(FAR struct ieee802154_driver_s *dev,
FAR struct rimeaddr_s *destaddr);
void sixlowpan_compresshdr_hc06(FAR struct ieee802154_driver_s *ieee,
FAR const struct ipv6_hdr_s *ipv6,
FAR const struct rimeaddr_s *destmac,
FAR struct iob_s *iob);
#endif
/****************************************************************************
* Name: sixlowpan_hc06_initialize
* Name: sixlowpan_uncompresshdr_hc06
*
* Description:
* Uncompress HC06 (i.e., IPHC and LOWPAN_UDP) headers and put them in
@ -587,7 +650,7 @@ void sixlowpan_compresshdr_hc06(FAR struct ieee802154_driver_s *dev,
* Input Parmeters:
* ieee - A reference to the IEE802.15.4 network device state
* iplen - Equal to 0 if the packet is not a fragment (IP length is then
* inferred from the L2 length), non 0 if the packet is a 1st
* inferred from the L2 length), non 0 if the packet is a first
* fragment.
*
* Returned Value:
@ -611,9 +674,11 @@ void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee,
* uip_buf buffer.
*
* Input Parmeters:
* ieee - A reference to the IEE802.15.4 network device state
* destaddr - L2 destination address, needed to compress the IP
* destination field
* ieee - A reference to the IEE802.15.4 network device state
* ipv6 - The IPv6 header to be compressed
* destmac - L2 destination address, needed to compress the IP
* destination field
* iob - The IOB into which the compressed header should be saved.
*
* Returned Value:
* None
@ -622,7 +687,9 @@ void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee,
#ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC1
void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
FAR struct rimeaddr_s *destaddr);
FAR const struct ipv6_hdr_s *ipv6,
FAR const struct rimeaddr_s *destmac,
FAR struct iob_s *iob);
#endif
/****************************************************************************
@ -640,7 +707,7 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
* Input Parameters:
* ieee - A reference to the IEE802.15.4 network device state
* iplen - Equal to 0 if the packet is not a fragment (IP length is then
* inferred from the L2 length), non 0 if the packet is a 1st
* inferred from the L2 length), non 0 if the packet is a first
* fragment.
*
* Returned Value:
@ -663,5 +730,35 @@ void sixlowpan_uncompresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
int sixlowpan_frame_hdralloc(FAR struct iob_s *iob, int size);
/****************************************************************************
* Name: sixlowpan_islinklocal, sixlowpan_ipfromrime, sixlowpan_rimefromip,
* and sixlowpan_ismacbased
*
* Description:
* sixlowpan_ipfromrime: Create a link local IPv6 address from a rime
* address.
*
* sixlowpan_rimefromip: Extract the rime address from a link local IPv6
* address.
*
* sixlowpan_islinklocal and sixlowpan_ismacbased will return true for
* address created in this fashion.
*
* 128 112 96 80 64 48 32 16
* ---- ---- ---- ---- ---- ---- ---- ----
* fe80 0000 0000 0000 xxxx 0000 0000 0000 2-byte Rime address (VALID?)
* fe80 0000 0000 0000 xxxx xxxx xxxx xxxx 8-byte Rime address
*
****************************************************************************/
#define sixlowpan_islinklocal(ipaddr) ((ipaddr)[0] = NTOHS(0xfe80))
void sixlowpan_ipfromrime(FAR const struct rimeaddr_s *rime,
net_ipv6addr_t ipaddr);
void sixlowpan_rimefromip(const net_ipv6addr_t ipaddr,
FAR struct rimeaddr_s *rime);
bool sixlowpan_ismacbased(const net_ipv6addr_t ipaddr,
FAR const struct rimeaddr_s *rime);
#endif /* CONFIG_NET_6LOWPAN */
#endif /* _NET_SIXLOWPAN_SIXLOWPAN_INTERNAL_H */

View File

@ -54,6 +54,17 @@
#ifdef CONFIG_NET_6LOWPAN
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* These are temporary stubs. Something like this would be needed to
* monitor the health of a IPv6 neighbor.
*/
#define neighbor_reachable(dev)
#define neighbor_notreachable(dev)
/****************************************************************************
* Private Types
****************************************************************************/
@ -172,6 +183,7 @@ static uint16_t send_interrupt(FAR struct net_driver_s *dev,
sinfo->s_destmac);
flags &= ~WPAN_POLL;
neighbor_reachable(dev);
goto end_wait;
}
@ -183,6 +195,7 @@ static uint16_t send_interrupt(FAR struct net_driver_s *dev,
nwarn("WARNING: SEND timeout\n");
sinfo->s_result = -ETIMEDOUT;
neighbor_notreachable(dev);
goto end_wait;
}

View File

@ -39,11 +39,13 @@
#include <nuttx/config.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include "nuttx/net/netdev.h"
#include "nuttx/net/netstats.h"
#include "netdev/netdev.h"
#include "socket/socket.h"
@ -66,7 +68,7 @@
* Parameters:
* psock - An instance of the internal socket structure.
* buf - Data to send
* len - Length of data to send
* bulen - Length of data to send
*
* Returned Value:
* On success, returns the number of characters sent. On error,
@ -80,13 +82,14 @@
****************************************************************************/
ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
size_t len)
size_t buflen)
{
FAR struct tcp_conn_s *conn;
FAR struct net_driver_s *dev;
struct ipv6tcp_hdr_s ipv6tcp;
struct rimeaddr_s destmac;
uint16_t timeout;
uint16_t iplen;
int ret;
DEBUGASSERT(psock != NULL && psock->s_crefs > 0);
@ -113,7 +116,7 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
conn = (FAR struct tcp_conn_s *)psock->s_conn;
DEBUGASSERT(conn != NULL);
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
#ifdef CONFIG_NET_IPv4
/* Ignore if not IPv6 domain */
if (conn->domain != PF_INET6)
@ -161,14 +164,88 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
#endif
/* Initialize the IPv6/TCP headers */
#warning Missing logic
/* Initialize the IPv6/UDP headers */
ipv6tcp.ipv6.vtc = 0x60;
ipv6tcp.ipv6.tcf = 0x00;
ipv6tcp.ipv6.flow = 0x00;
ipv6tcp.ipv6.proto = IP_PROTO_TCP;
ipv6tcp.ipv6.ttl = IP_TTL;
/* The IPv6 header length field does not include the size of IPv6 IP
* header.
*/
iplen = buflen + TCP_HDRLEN;
ipv6tcp.ipv6.len[0] = (iplen >> 8);
ipv6tcp.ipv6.len[1] = (iplen & 0xff);
/* Copy the source and destination addresses */
net_ipv6addr_hdrcopy(ipv6tcp.ipv6.srcipaddr, conn->u.ipv6.laddr);
net_ipv6addr_hdrcopy(ipv6tcp.ipv6.destipaddr, conn->u.ipv6.raddr);
ninfo("IPv6 length: %d\n", ((int)ipv6->len[0] << 8) + ipv6->len[1]);
#ifdef CONFIG_NET_STATISTICS
g_netstats.ipv6.sent++;
#endif
/* Initialize the TCP header */
ipv6tcp.tcp.srcport = conn->lport; /* Local port */
ipv6tcp.tcp.destport = conn->rport; /* Connected remote port */
memcpy(ipv6tcp.tcp.ackno, conn->rcvseq, 4); /* ACK number */
memcpy(ipv6tcp.tcp.seqno, conn->sndseq, 4); /* Sequence number */
ipv6tcp.tcp.tcpoffset = (TCP_HDRLEN / 4) << 4; /* No optdata */
ipv6tcp.tcp.urgp[0] = 0; /* No urgent data */
ipv6tcp.tcp.urgp[1] = 0;
/* Set the TCP window */
if (conn->tcpstateflags & TCP_STOPPED)
{
/* If the connection has issued TCP_STOPPED, we advertise a zero
* window so that the remote host will stop sending data.
*/
ipv6tcp.tcp.wnd[0] = 0;
ipv6tcp.tcp.wnd[1] = 0;
}
else
{
ipv6tcp.tcp.wnd[0] = ((NET_DEV_RCVWNDO(dev)) >> 8);
ipv6tcp.tcp.wnd[1] = ((NET_DEV_RCVWNDO(dev)) & 0xff);
}
/* Calculate TCP checksum. */
ipv6tcp.tcp.tcpchksum = 0;
#if 0
/* REVISIT: Current checksum logic expects the IPv6 header, the UDP header, and
* the payload data to be in contiguous memory.
*/
ipv6tcp.tcp.tcpchksum = ~tcp_ipv6_chksum(dev);
#endif
ninfo("Outgoing TCP packet length: %d bytes\n", iplen + IOPv6_HDRLEN);
#ifdef CONFIG_NET_STATISTICS
g_netstats.tcp.sent++;
#endif
/* Set the socket state to sending */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
/* Get the Rime MAC address of the destination */
#warning Missing logic
/* Get the Rime MAC address of the destination This assumes an encoding
* of the MAC address in the IPv6 address.
*/
sixlowpan_rimefromip(conn->u.ipv6.raddr, &destmac);
/* If routable, then call sixlowpan_send() to format and send the 6loWPAN
* packet.
@ -181,7 +258,7 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
#endif
ret = sixlowpan_send(dev, (FAR const struct ipv6_hdr_s *)&ipv6tcp,
buf, len, &destmac, timeout);
buf, buflen, &destmac, timeout);
if (ret < 0)
{
nerr("ERROR: sixlowpan_send() failed: %d\n", ret);
@ -193,4 +270,86 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
return ret;
}
/****************************************************************************
* Function: sixlowpan_tcp_send
*
* Description:
* TCP output comes through two different mechansims. Either from:
*
* 1. TCP socket output. For the case of TCP output to an
* IEEE802.15.4, the TCP output is caught in the socket
* send()/sendto() logic and and redirected to psock_6lowpan_tcp_send().
* 2. TCP output from the TCP state machine. That will occur
* during TCP packet processing by the TCP state meachine. It
* is detected there when ipv6_tcp_input() returns with d_len > 0. This
* will be redirected here.
*
* Parameters:
* dev - An instance of nework device state structure
*
* Returned Value:
* None
*
* Assumptions:
* Called with the network locked.
*
****************************************************************************/
void sixlowpan_tcp_send(FAR struct net_driver_s *dev)
{
DEBUGASSERT(dev != NULL && dev->d_len > 0);
/* Double check */
if (dev != NULL && dev->d_len > 0)
{
FAR struct ipv6_hdr_s *ipv6hdr;
/* The IPv6 header followed by a TCP headers should lie at the
* beginning of d_buf since there is no link layer protocol header
* and the TCP state machine should only response with TCP packets.
*/
ipv6hdr = (FAR struct ipv6_hdr_s *)(dev->d_buf);
/* The TCP data payload should follow the IPv6 header plus the
* protocol header.
*/
if (ipv6hdr->proto != IP_PROTO_TCP)
{
nwarn("WARNING: Expected TCP protoype: %u\n", ipv6hdr->proto);
}
else
{
size_t hdrlen;
hdrlen = IPv6_HDRLEN + TCP_HDRLEN;
if (hdrlen < dev->d_len)
{
nwarn("WARNING: Packet to small: Have %u need >%u\n",
dev->d_len, hdrlen);
}
else
{
struct rimeaddr_s destmac;
/* Get the Rime MAC address of the destination. This assumes
* an encoding of the MAC address in the IPv6 address.
*/
sixlowpan_rimefromip(ipv6hdr->destipaddr, &destmac);
/* Convert the outgoing packet into a frame list. */
(void)sixlowpan_queue_frames(
(FAR struct ieee802154_driver_s *)dev, ipv6hdr,
dev->d_buf + hdrlen, dev->d_len - hdrlen, &destmac);
}
}
}
dev->d_len = 0;
}
#endif /* CONFIG_NET_6LOWPAN && CONFIG_NET_TCP */

View File

@ -39,11 +39,14 @@
#include <nuttx/config.h>
#include <sys/socket.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include "nuttx/net/netdev.h"
#include "nuttx/net/netstats.h"
#include "netdev/netdev.h"
#include "socket/socket.h"
@ -57,21 +60,26 @@
****************************************************************************/
/****************************************************************************
* Function: psock_6lowpan_udp_send
* Function: psock_6lowpan_udp_sendto
*
* Description:
* psock_6lowpan_udp_send() call may be used with connectionlesss UDP
* sockets.
* If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET)
* socket, the parameters to and 'tolen' are ignored (and the error EISCONN
* may be returned when they are not NULL and 0), and the error ENOTCONN is
* returned when the socket was not actually connected.
*
* Parameters:
* psock - An instance of the internal socket structure.
* buf - Data to send
* len - Length of data to send
* psock A pointer to a NuttX-specific, internal socket structure
* buf Data to send
* buflen Length of data to send
* flags Send flags
* to Address of recipient
* tolen The length of the address structure
*
* Returned Value:
* On success, returns the number of characters sent. On error,
* -1 is returned, and errno is set appropriately. Returned error numbers
* must be consistent with definition of errors reported by send() or
* -1 is returned, and errno is set appropriately. Returned error
* number must be consistent with definition of errors reported by
* sendto().
*
* Assumptions:
@ -79,16 +87,215 @@
*
****************************************************************************/
ssize_t psock_6lowpan_udp_send(FAR struct socket *psock, FAR const void *buf,
size_t len)
ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock,
FAR const void *buf,
size_t buflen, int flags,
FAR const struct sockaddr *to,
socklen_t tolen)
{
FAR struct sockaddr_in6 *to6 = (FAR struct sockaddr_in6 *)to;
FAR struct udp_conn_s *conn;
FAR struct net_driver_s *dev;
struct ipv6udp_hdr_s ipv6udp;
struct rimeaddr_s destmac;
uint16_t iplen;
uint16_t timeout;
int ret;
DEBUGASSERT(psock != NULL && psock->s_crefs > 0 && to != NULL);
DEBUGASSERT(psock->s_type == SOCK_DGRAM);
if (psock == NULL || to == NULL)
{
return (ssize_t)-EINVAL;
}
/* Make sure that this is a datagram valid socket */
if (psock->s_crefs <= 0 || psock->s_type != SOCK_DGRAM)
{
nerr("ERROR: Invalid socket\n");
return (ssize_t)-EBADF;
}
/* Make sure that the destination address is valid */
if (to6->sin6_family != AF_INET6 || tolen < sizeof(struct sockaddr_in6))
{
nerr("ERROR: Invalid destination address\n");
return (ssize_t)-EAFNOSUPPORT;
}
/* Get the underlying UDP "connection" structure */
conn = (FAR struct udp_conn_s *)psock->s_conn;
DEBUGASSERT(conn != NULL);
/* Ignore if not IPv6 domain */
if (conn->domain != PF_INET6)
{
nwarn("WARNING: Not IPv6\n");
return (ssize_t)-EPROTOTYPE;
}
/* Route outgoing message to the correct device */
#ifdef CONFIG_NETDEV_MULTINIC
dev = netdev_findby_ipv6addr(conn->u.ipv6.laddr,
to6->sin6_addr.in6_u.u6_addr16);
#ifdef CONFIG_NETDEV_MULTILINK
if (dev == NULL || dev->d_lltype != NET_LL_IEEE802154)
#else
if (dev == NULL)
#endif
{
nwarn("WARNING: Not routable or not IEEE802.15.4 MAC\n");
return (ssize_t)-ENETUNREACH;
}
#else
dev = netdev_findby_ipv6addr(to6->sin6_addr.in6_u.u6_addr16);
#ifdef CONFIG_NETDEV_MULTILINK
if (dev == NULL || dev->d_lltype != NET_LL_IEEE802154)
#else
if (dev == NULL)
#endif
{
nwarn("WARNING: Not routable\n");
return (ssize_t)-ENETUNREACH;
}
#endif
#ifdef CONFIG_NET_ICMPv6_NEIGHBOR
/* Make sure that the IP address mapping is in the Neighbor Table */
ret = icmpv6_neighbor(to6->sin6_addr.in6_u.u6_addr16);
if (ret < 0)
{
nerr("ERROR: Not reachable\n");
return (ssize_t)-ENETUNREACH;
}
#endif
/* Initialize the IPv6/UDP headers */
ipv6udp.ipv6.vtc = 0x60;
ipv6udp.ipv6.tcf = 0x00;
ipv6udp.ipv6.flow = 0x00;
ipv6udp.ipv6.proto = IP_PROTO_UDP;
ipv6udp.ipv6.ttl = conn->ttl;
/* The IPv6 header length field does not include the size of IPv6 IP
* header.
*/
iplen = buflen + UDP_HDRLEN;
ipv6udp.ipv6.len[0] = (iplen >> 8);
ipv6udp.ipv6.len[1] = (iplen & 0xff);
/* Copy the source and destination addresses */
net_ipv6addr_hdrcopy(ipv6udp.ipv6.srcipaddr, to6->sin6_addr.in6_u.u6_addr16);
net_ipv6addr_hdrcopy(ipv6udp.ipv6.destipaddr, conn->u.ipv6.raddr);
ninfo("IPv6 length: %d\n", ((int)ipv6->len[0] << 8) + ipv6->len[1]);
#ifdef CONFIG_NET_STATISTICS
g_netstats.ipv6.sent++;
#endif
/* Initialize the UDP header */
ipv6udp.udp.srcport = conn->lport;
ipv6udp.udp.destport = to6->sin6_port;
ipv6udp.udp.udplen = htons(iplen);
ipv6udp.udp.udpchksum = 0;
ipv6udp.udp.udpchksum = 0;
#warning Missing logic
#if 0 /* REVISIT */
#ifdef CONFIG_NET_UDP_CHECKSUMS
/* Calculate UDP checksum. */
/* REVISIT: Current checksum logic expects the IPv6 header, the UDP header, and
* the payload data to be in contiguous memory.
*/
ipv6udp.udp.udpchksum = ~udp_ipv6_chksum(dev);
if (ipv6udp.udp.udpchksum == 0)
{
ipv6udp.udp.udpchksum = 0xffff;
}
#endif /* CONFIG_NET_UDP_CHECKSUMS */
#endif /* REVISIT */
ninfo("Outgoing UDP packet length: %d\n", iplen + IPv6_HDRLEN);
#ifdef CONFIG_NET_STATISTICS
g_netstats.udp.sent++;
#endif
/* Set the socket state to sending */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
/* Get the Rime MAC address of the destination This assumes an encoding
* of the MAC address in the IPv6 address.
*/
sixlowpan_rimefromip(to6->sin6_addr.in6_u.u6_addr16, &destmac);
/* If routable, then call sixlowpan_send() to format and send the 6loWPAN
* packet.
*/
#ifdef CONFIG_NET_SOCKOPTS
timeout = psock->s_sndtimeo;
#else
timeout = 0;
#endif
ret = sixlowpan_send(dev, (FAR const struct ipv6_hdr_s *)&ipv6udp,
buf, buflen, &destmac, timeout);
if (ret < 0)
{
nerr("ERROR: sixlowpan_send() failed: %d\n", ret);
}
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
return ret;
}
/****************************************************************************
* Function: psock_6lowpan_udp_send
*
* Description:
* psock_6lowpan_udp_send() call may be used with connectionlesss UDP
* sockets.
*
* Parameters:
* psock - An instance of the internal socket structure.
* buf - Data to send
* buflen - Length of data to send
*
* Returned Value:
* On success, returns the number of characters sent. On error,
* -1 is returned, and errno is set appropriately. Returned error numbers
* must be consistent with definition of errors reported by send().
*
* Assumptions:
* Called with the network locked.
*
****************************************************************************/
ssize_t psock_6lowpan_udp_send(FAR struct socket *psock, FAR const void *buf,
size_t buflen)
{
FAR struct udp_conn_s *conn;
struct sockaddr_in6 to;
DEBUGASSERT(psock != NULL && psock->s_crefs > 0);
DEBUGASSERT(psock->s_type == SOCK_DGRAM);
@ -114,7 +321,6 @@ ssize_t psock_6lowpan_udp_send(FAR struct socket *psock, FAR const void *buf,
conn = (FAR struct udp_conn_s *)psock->s_conn;
DEBUGASSERT(conn != NULL);
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
/* Ignore if not IPv6 domain */
if (conn->domain != PF_INET6)
@ -122,76 +328,16 @@ ssize_t psock_6lowpan_udp_send(FAR struct socket *psock, FAR const void *buf,
nwarn("WARNING: Not IPv6\n");
return (ssize_t)-EPROTOTYPE;
}
#endif
/* Route outgoing message to the correct device */
/* Create the 'to' address */
#ifdef CONFIG_NETDEV_MULTINIC
dev = netdev_findby_ipv6addr(conn->u.ipv6.laddr, conn->u.ipv6.raddr);
#ifdef CONFIG_NETDEV_MULTILINK
if (dev == NULL || dev->d_lltype != NET_LL_IEEE802154)
#else
if (dev == NULL)
#endif
{
nwarn("WARNING: Not routable or not IEEE802.15.4 MAC\n");
return (ssize_t)-ENETUNREACH;
}
#else
dev = netdev_findby_ipv6addr(conn->u.ipv6.raddr);
#ifdef CONFIG_NETDEV_MULTILINK
if (dev == NULL || dev->d_lltype != NET_LL_IEEE802154)
#else
if (dev == NULL)
#endif
{
nwarn("WARNING: Not routable\n");
return (ssize_t)-ENETUNREACH;
}
#endif
to.sin6_family = AF_INET6;
to.sin6_port = conn->rport; /* Already network order */
memcpy(to.sin6_addr.in6_u.u6_addr16, conn->u.ipv6.raddr, 16);
#ifdef CONFIG_NET_ICMPv6_NEIGHBOR
/* Make sure that the IP address mapping is in the Neighbor Table */
ret = icmpv6_neighbor(conn->u.ipv6.raddr);
if (ret < 0)
{
nerr("ERROR: Not reachable\n");
return (ssize_t)-ENETUNREACH;
}
#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);
/* Get the Rime MAC address of the destination */
#warning Missing logic
/* If routable, then call sixlowpan_send() to format and send the 6loWPAN
* packet.
*/
#ifdef CONFIG_NET_SOCKOPTS
timeout = psock->s_sndtimeo;
#else
timeout = 0;
#endif
ret = sixlowpan_send(dev, (FAR const struct ipv6_hdr_s *)&ipv6udp,
buf, len, &destmac, timeout);
if (ret < 0)
{
nerr("ERROR: sixlowpan_send() failed: %d\n", ret);
}
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
return ret;
return psock_6lowpan_udp_sendto(psock, buf, buflen, 0,
(FAR const struct sockaddr *)&to,
sizeof(struct sockaddr_in6));
}
#endif /* CONFIG_NET_6LOWPAN && CONFIG_NET_UDP */

View File

@ -66,8 +66,11 @@
#include <nuttx/config.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/net/sixlowpan.h>
#include "sixlowpan/sixlowpan_internal.h"
#ifdef CONFIG_NET_6LOWPAN
@ -96,4 +99,89 @@ int sixlowpan_frame_hdralloc(FAR struct iob_s *iob, int size)
return -ENOMEM;
}
/****************************************************************************
* Name: sixlowpan_ipfromrime
*
* Description:
* Create a link local IPv6 address from a rime address:
*
* 128 112 96 80 64 48 32 16
* ---- ---- ---- ---- ---- ---- ---- ----
* fe80 0000 0000 0000 xxxx xxxx 0000 0000 2-byte Rime address (VALID?)
* fe80 0000 0000 0000 xxxx xxxx xxxx xxxx 8-byte Rime address
*
****************************************************************************/
void sixlowpan_ipfromrime(FAR const struct rimeaddr_s *rime,
net_ipv6addr_t ipaddr)
{
memset(ipaddr, 0, sizeof(net_ipv6addr_t));
ipaddr[0] = 0xfe80;
/* We consider only links with IEEE EUI-64 identifier or IEEE 48-bit MAC
* addresses. NOTE: that CONFIG_NET_6LOWPAN_RIMEADDR_SIZE may be 2 or
* 8. In the case of 2, we treat the address like an 8 byte address with
* the lower bytes set to zero.
*
* REVISIT: This is just a guess so that I can continue making forward
* progress. What is the correct policy?
*/
memcpy(&ipaddr[4], rime, CONFIG_NET_6LOWPAN_RIMEADDR_SIZE);
ipaddr[4] ^= 0x0200;
}
/****************************************************************************
* Name: sixlowpan_rimefromip
*
* Description:
* Extract the rime address from a link local IPv6 address:
*
* 128 112 96 80 64 48 32 16
* ---- ---- ---- ---- ---- ---- ---- ----
* fe80 0000 0000 0000 xxxx 0000 0000 0000 2-byte Rime address (VALID?)
* fe80 0000 0000 0000 xxxx xxxx xxxx xxxx 8-byte Rime address
*
****************************************************************************/
void sixlowpan_rimefromip(const net_ipv6addr_t ipaddr,
FAR struct rimeaddr_s *rime)
{
/* REVISIT: See notes about 2 byte addresses in sixlowpan_ipfromrime() */
DEBUGASSERT(ipaddr[0] == 0xfe80);
memcpy(rime, &ipaddr[4], CONFIG_NET_6LOWPAN_RIMEADDR_SIZE);
rime->u8[0] ^= 0x02;
}
/****************************************************************************
* Name: sixlowpan_ismacbased
*
* Description:
* Extract the rime address from a link local IPv6 address:
*
* 128 112 96 80 64 48 32 16
* ---- ---- ---- ---- ---- ---- ---- ----
* fe80 0000 0000 0000 xxxx 0000 0000 0000 2-byte Rime address (VALID?)
* fe80 0000 0000 0000 xxxx xxxx xxxx xxxx 8-byte Rime address
*
****************************************************************************/
bool sixlowpan_ismacbased(const net_ipv6addr_t ipaddr,
FAR const struct rimeaddr_s *rime)
{
FAR const uint8_t *rimeptr = rime->u8;
#if CONFIG_NET_6LOWPAN_RIMEADDR_SIZE == 2
return ((ipaddr[4] == (GETINT16(rimeptr, 0) ^ 0x0200)) &&
ipaddr[5] == 0 && ipaddr[6] == 0 && ipaddr[7] == 0);
#else /* CONFIG_NET_6LOWPAN_RIMEADDR_SIZE == 8 */
return ((ipaddr[4] == (GETINT16(rimeptr, 0) ^ 0x0200)) &&
ipaddr[5] == GETINT16(rimeptr, 2) &&
ipaddr[6] == GETINT16(rimeptr, 4) &&
ipaddr[7] == GETINT16(rimeptr, 6));
#endif
}
#endif /* CONFIG_NET_6LOWPAN */

View File

@ -1,7 +1,7 @@
/****************************************************************************
* net/socket/send.c
*
* Copyright (C) 2007-2014, 2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2014, 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -166,29 +166,18 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
ret = psock_6lowpan_tcp_send(psock, buf, len);
#ifdef CONFIG_NETDEV_MULTINIC
#if defined(CONFIG_NETDEV_MULTINIC) && defined(NET_TCP_HAVE_STACK)
if (ret < 0)
{
/* TCP/IP packet send */
ret = psock_tcp_send(psock, buf, len);
#ifdef NET_TCP_HAVE_STACK
ret = psock_tcp_send(psock, buf, len);
#else
ret = -ENOSYS;
#endif
}
#endif /* CONFIG_NETDEV_MULTINIC */
#else /* CONFIG_NET_6LOWPAN */
/* Only TCP/IP packet send */
#ifdef NET_TCP_HAVE_STACK
ret = psock_tcp_send(psock, buf, len);
#endif /* CONFIG_NETDEV_MULTINIC && NET_TCP_HAVE_STACK */
#elif defined(NET_TCP_HAVE_STACK)
nsent = psock_tcp_send(psock, buf, len, flags, to, tolen);
#else
ret = -ENOSYS;
#endif
nsent = -ENOSYS;
#endif /* CONFIG_NET_6LOWPAN */
}
#endif /* CONFIG_NET_TCP */
@ -215,34 +204,25 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
else
#endif
{
#ifdef CONFIG_NET_6LOWPAN
#if defined(CONFIG_NET_6LOWPAN)
/* Try 6loWPAN UDP packet send */
ret = psock_6lowpan_udp_send(psock, buf, len);
#ifdef CONFIG_NETDEV_MULTINIC
#if defined(CONFIG_NETDEV_MULTINIC) && defined(NET_UDP_HAVE_STACK)
if (ret < 0)
{
/* UDP/IP packet send */
ret = psock_udp_send(psock, buf, len);
#ifdef NET_UDP_HAVE_STACK
ret = psock_udp_send(psock, buf, len);
#else
ret = -ENOSYS;
#endif
}
#endif /* CONFIG_NETDEV_MULTINIC */
#else /* CONFIG_NET_6LOWPAN */
#endif /* CONFIG_NETDEV_MULTINIC && NET_UDP_HAVE_STACK */
#elif defined(NET_UDP_HAVE_STACK)
/* Only UDP/IP packet send */
#ifdef NET_UDP_HAVE_STACK
ret = psock_udp_send(psock, buf, len);
#else
ret = -ENOSYS;
#endif
#endif /* CONFIG_NET_6LOWPAN */
}
#endif /* CONFIG_NET_UDP */

View File

@ -49,6 +49,7 @@
#include <nuttx/net/net.h>
#include "udp/udp.h"
#include "sixlowpan/sixlowpan.h"
#include "local/local.h"
#include "socket/socket.h"
#include "usrsock/usrsock.h"
@ -237,11 +238,24 @@ ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
else
#endif
{
#ifdef NET_UDP_HAVE_STACK
#if defined(CONFIG_NET_6LOWPAN)
/* Try 6loWPAN UDP packet sendto() */
nsent = psock_6lowpan_udp_sendto(psock, buf, len, flags, to, tolen);
#if defined(CONFIG_NETDEV_MULTINIC) && defined(NET_UDP_HAVE_STACK)
if (nsent < 0)
{
/* UDP/IP packet sendto */
nsent = psock_udp_sendto(psock, buf, len, flags, to, tolen);
}
#endif /* CONFIG_NETDEV_MULTINIC && NET_UDP_HAVE_STACK */
#elif defined(NET_UDP_HAVE_STACK)
nsent = psock_udp_sendto(psock, buf, len, flags, to, tolen);
#else
nsent = -ENOSYS;
#endif
#endif /* CONFIG_NET_6LOWPAN */
}
#endif /* CONFIG_NET_UDP */

View File

@ -2,7 +2,7 @@
* net/tcp/tcp_input.c
* Handling incoming TCP input
*
* Copyright (C) 2007-2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2014, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Adapted for NuttX from logic in uIP which also has a BSD-like license: