6loWPAN: Add a little bit of HC1 compression logic.

This commit is contained in:
Gregory Nutt 2017-04-01 13:42:00 -06:00
parent 7a4af75fcf
commit 64afba55dd
6 changed files with 225 additions and 10 deletions

View File

@ -53,6 +53,17 @@
#ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC1
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Buffer access helpers */
#define IPv6BUF(dev) \
((FAR struct ipv6_hdr_s *)((dev)->d_buf))
#define UDPIPv6BUF(dev) \
((FAR struct udp_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev) + IPv6_HDRLEN])
/****************************************************************************
* Public Functions
****************************************************************************/
@ -136,14 +147,127 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
* fragment.
*
* Returned Value:
* None
* Zero (OK) is returned on success, on failure a negater errno value is
* returned.
*
****************************************************************************/
void sixlowpan_uncompresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
uint16_t iplen)
int sixlowpan_uncompresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
uint16_t iplen)
{
/* REVISIT: To be provided */
FAR struct ipv6_hdr_s *ipv6 = IPv6BUF(&ieee->i_dev);
FAR uint8_t *hc1 = RIME_HC1_PTR;
/* Format the IPv6 header in the device d_buf */
/* Set version, traffic clase, and flow label */
ipv6->vtc = 0x60; /* Bits 0-3: version, bits 4-7: traffic class (MS) */
ipv6->tcf = 0; /* Bits 0-3: traffic class (LS), 4-bits: flow label (MS) */
ipv6->flow = 0; /* 16-bit flow label (LS) */
/* Use stateless auto-configuration to set source and destination IP
* addresses.
*/
sixlowpan_ipfromrime(&g_pktaddrs[PACKETBUF_ADDR_SENDER],
&ipv6->srcipaddr);
sixlowpan_ipfromrime(&g_pktaddrs[PACKETBUF_ADDR_RECEIVER],
&ipv6->destipaddr);
g_uncomp_hdrlen += IPv6_HDRLEN;
/* len[], proto, and ttl depend on the encoding */
switch (hc1[RIME_HC1_ENCODING] & 0x06)
{
case SIXLOWPAN_HC1_NH_ICMP6:
ipv6->proto = IP_PROTO_ICMP6;
ipv6->ttl = hc1[RIME_HC1_TTL];
g_rime_hdrlen += SIXLOWPAN_HC1_HDR_LEN;
break;
#if CONFIG_NET_TCP
case SIXLOWPAN_HC1_NH_TCP:
ipv6->proto = IP_PROTO_TCP;
ipv6->ttl = hc1[RIME_HC1_TTL];
g_rime_hdrlen += SIXLOWPAN_HC1_HDR_LEN;
break;
#endif /* CONFIG_NET_TCP */
#if CONFIG_NET_UDP
case SIXLOWPAN_HC1_NH_UDP:
{
FAR struct udp_hdr_s *udp = UDPIPv6BUF(&ieee->i_dev);
FAR uint8_t *hcudp = RIME_HC1_HC_UDP_PTR;
ipv6->proto = IP_PROTO_UDP;
if ((hcudp[RIME_HC1_HC_UDP_HC1_ENCODING] & 0x01) != 0)
{
/* UDP header is compressed with HC_UDP */
if (hcudp[RIME_HC1_HC_UDP_UDP_ENCODING] !=
SIXLOWPAN_HC_UDP_ALL_C)
{
nwarn("WARNING: sixlowpan (uncompress_hdr), packet not supported");
return -EOPNOTSUPP;
}
/* IP TTL */
ipv6->ttl = hcudp[RIME_HC1_HC_UDP_TTL];
/* UDP ports, len, checksum */
udp->srcport =
htons(SIXLOWPAN_UDP_PORT_MIN + (hcudp[RIME_HC1_HC_UDP_PORTS] >> 4));
udp->destport =
htons(SIXLOWPAN_UDP_PORT_MIN + (hcudp[RIME_HC1_HC_UDP_PORTS] & 0x0F));
memcpy(&udp->udpchksum, &hcudp[RIME_HC1_HC_UDP_CHKSUM], 2);
g_uncomp_hdrlen += UIP_UDPH_LEN;
g_rime_hdrlen += SIXLOWPAN_HC1_HC_UDP_HDR_LEN;
}
else
{
g_rime_hdrlen += SIXLOWPAN_HC1_HDR_LEN;
}
}
break;
#endif /* CONFIG_NET_UDP */
default:
return -EPROTONOSUPPORT;
}
/* IP length field. */
if (iplen == 0)
{
/* This is not a fragmented packet */
ipv6->len[0] = 0;
ipv6->len[1] = ieee->i_dev.d_len - g_rime_hdrlen + /* REVISIT */
g_uncomp_hdrlen - IPv6_HDRLEN;
}
else
{
/* This is a 1st fragment */
ipv6->len[0] = (iplen - IPv6_HDRLEN) >> 8;
ipv6->len[1] = (iplen - IPv6_HDRLEN) & 0x00FF;
}
/* length field in UDP header */
#if CONFIG_NET_UDP
if (ipv6->proto == IP_PROTO_UDP)
{
FAR struct udp_hdr_s *udp = UDPIPv6BUF(&ieee->i_dev);
memcpy(&udp->udplen, &ipv6->len[0], 2);
}
#endif
return;
}
#endif /* CONFIG_NET_6LOWPAN_COMPRESSION_HC1 */

View File

@ -700,8 +700,12 @@ 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);
/* Convert the outgoing packet into a frame list. */

View File

@ -663,5 +663,27 @@ 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
*
* Description:
* sixlowpan_ipfromrime: Use stateless auto-configuration to create an IP
* address from a rime address.
*
* sixlowpan_rimefromip: Assume stateless auto-configuration to extrate
* the rime address from an IP 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);
void sixlowpan_rimefromip(const net_ipv6addr_t ipaddr,
FAR struct rimeaddr_s *rime);
#endif /* CONFIG_NET_6LOWPAN */
#endif /* _NET_SIXLOWPAN_SIXLOWPAN_INTERNAL_H */

View File

@ -167,8 +167,11 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
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.

View File

@ -168,8 +168,11 @@ ssize_t psock_6lowpan_udp_send(FAR struct socket *psock, FAR const void *buf,
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.

View File

@ -66,8 +66,11 @@
#include <nuttx/config.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/net/sixlowpan.h>
#include "sixlowpan/sixlowpan_internal.h"
#ifdef CONFIG_NET_6LOWPAN
@ -96,4 +99,60 @@ int sixlowpan_frame_hdralloc(FAR struct iob_s *iob, int size)
return -ENOMEM;
}
/****************************************************************************
* Name: sixlowpan_ipfromrime
*
* Description:
* Use stateless auto-configuration to create an IP 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);
}
/****************************************************************************
* Name: sixlowpan_rimefromip
*
* Description:
* Assume stateless auto-configuration to extrate the rime address from
* an IP 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_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);
}
#endif /* CONFIG_NET_6LOWPAN */