Merge remote-tracking branch 'origin/master' into ieee802154
This commit is contained in:
commit
c8291a376e
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
@ -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);
|
||||
|
@ -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
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user