6loWPAN: A little HC1 compression logic.

This commit is contained in:
Gregory Nutt 2017-04-01 15:05:38 -06:00
parent 64afba55dd
commit 5af0909275
4 changed files with 171 additions and 19 deletions

View file

@ -203,7 +203,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
* destaddr - L2 destination address, needed to compress the IP
* destination field
* iob - The IOB into which the compressed header should be saved.
*
* Returned Value:
* None

View file

@ -114,8 +114,10 @@
*
* Input Parmeters:
* ieee - A reference to the IEE802.15.4 network device state
* ipv6 - The IPv6 header to be compressed
* destaddr - L2 destination address, needed to compress the IP
* destination field
* iob - The IOB into which the compressed header should be saved.
*
* Returned Value:
* None
@ -123,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 *destaddr,
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, destaddr) ||
(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 */
}
}
}
/****************************************************************************

View file

@ -228,7 +228,7 @@
/* 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 \
{ \
@ -396,6 +396,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 */
@ -559,7 +560,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
* destaddr - 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,8 +571,10 @@ 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 *destaddr,
FAR struct iob_s *iob);
#endif
/****************************************************************************
@ -612,8 +618,10 @@ void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee,
*
* Input Parmeters:
* ieee - A reference to the IEE802.15.4 network device state
* ipv6 - The IPv6 header to be compressed
* destaddr - 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 +630,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 *destaddr,
FAR struct iob_s *iob);
#endif
/****************************************************************************
@ -664,26 +674,34 @@ void sixlowpan_uncompresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
int sixlowpan_frame_hdralloc(FAR struct iob_s *iob, int size);
/****************************************************************************
* Name: sixlowpan_ipfromrime and sixlowpan_rimefromip
* Name: sixlowpan_islinklocal, sixlowpan_ipfromrime, sixlowpan_rimefromip,
* and sixlowpan_ismacbased
*
* Description:
* sixlowpan_ipfromrime: Use stateless auto-configuration to create an IP
* address from a rime address.
* sixlowpan_ipfromrime: Create a link local IPv6 address from a rime
* address.
*
* sixlowpan_rimefromip: Assume stateless auto-configuration to extrate
* the rime address from an IP 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 xxxx 0000 0000 2-byte Rime address (VALID?)
* fe80 0000 0000 0000 xxxx 0000 0000 0000 2-byte Rime address (VALID?)
* fe80 0000 0000 0000 xxxx xxxx xxxx xxxx 8-byte Rime address
*
****************************************************************************/
#define sixlowpan_islinklocal(ipaddr) ((ipaddr)[0] = NTOHS(0xfe80))
void sixlowpan_ipfromrime(FAR const struct rimeaddr_s *rime,
net_ipv6addr_t ipaddr);
void sixlowpan_rimefromip(const net_ipv6addr_t ipaddr,
FAR struct rimeaddr_s *rime);
bool sixlowpan_ismacbased(const net_ipv6addr_t ipaddr,
FAR const struct rimeaddr_s *rime);
#endif /* CONFIG_NET_6LOWPAN */
#endif /* _NET_SIXLOWPAN_SIXLOWPAN_INTERNAL_H */

View file

@ -103,8 +103,7 @@ int sixlowpan_frame_hdralloc(FAR struct iob_s *iob, int size)
* Name: sixlowpan_ipfromrime
*
* Description:
* Use stateless auto-configuration to create an IP address from a rime
* address:
* Create a link local IPv6 address from a rime address:
*
* 128 112 96 80 64 48 32 16
* ---- ---- ---- ---- ---- ---- ---- ----
@ -129,18 +128,18 @@ void sixlowpan_ipfromrime(FAR const struct rimeaddr_s *rime,
*/
memcpy(&ipaddr[4], rime, CONFIG_NET_6LOWPAN_RIMEADDR_SIZE);
ipaddr[4] ^= 0x0200;
}
/****************************************************************************
* Name: sixlowpan_rimefromip
*
* Description:
* Assume stateless auto-configuration to extrate the rime address from
* an IP address:
* Extract the rime address from a link local IPv6 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 0000 0000 0000 2-byte Rime address (VALID?)
* fe80 0000 0000 0000 xxxx xxxx xxxx xxxx 8-byte Rime address
*
****************************************************************************/
@ -153,6 +152,36 @@ void sixlowpan_rimefromip(const net_ipv6addr_t ipaddr,
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 */