lowpan6_common.c: add comments from ble version

This commit is contained in:
goldsimon 2018-03-21 22:53:08 +01:00
parent a4b9beef04
commit ac03107036
2 changed files with 130 additions and 15 deletions

View File

@ -90,4 +90,17 @@
#define LWIP_LOWPAN6_802154_DEBUG LWIP_DBG_OFF
#endif
/** LWIP_LOWPAN6_IP_COMPRESSED_DEBUG: enable compressed IP frame
* output debugging
*/
#ifndef LWIP_LOWPAN6_IP_COMPRESSED_DEBUG
#define LWIP_LOWPAN6_IP_COMPRESSED_DEBUG LWIP_DBG_OFF
#endif
/** LWIP_LOWPAN6_DECOMPRESSION_DEBUG: enable decompression debug output
*/
#ifndef LWIP_LOWPAN6_DECOMPRESSION_DEBUG
#define LWIP_LOWPAN6_DECOMPRESSION_DEBUG LWIP_DBG_OFF
#endif
#endif /* LWIP_HDR_LOWPAN6_OPTS_H */

View File

@ -398,6 +398,7 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize,
u16_t lowpan6_offset;
struct ip6_hdr *ip6hdr;
s8_t i;
u32_t header_temp;
u16_t ip6_offset = IP6_HLEN;
LWIP_ASSERT("lowpan6_buffer != NULL", lowpan6_buffer != NULL);
@ -412,84 +413,143 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize,
return ERR_MEM;
}
/* output the full compressed packet, if set in @see lowpan6_opts.h */
#if LWIP_LOWPAN6_IP_COMPRESSED_DEBUG
{
u16_t j;
LWIP_DEBUGF(LWIP_LOWPAN6_IP_COMPRESSED_DEBUG, ("lowpan6_decompress_hdr: IP6 payload (compressed): \n"));
for (j = 0; j < lowpan6_bufsize; j++) {
if ((j % 4) == 0) {
LWIP_DEBUGF(LWIP_LOWPAN6_IP_COMPRESSED_DEBUG, ("\n"));
}
LWIP_DEBUGF(LWIP_LOWPAN6_IP_COMPRESSED_DEBUG, ("%2X ", lowpan6_buffer[j]));
}
LWIP_DEBUGF(LWIP_LOWPAN6_IP_COMPRESSED_DEBUG, ("\np->len: %d", lowpan6_bufsize));
}
#endif
/* offset for inline IP headers (RFC 6282 ch3)*/
lowpan6_offset = 2;
/* if CID is set (context identifier), the context byte
* follows immediately after the header, so other IPHC fields are @+3 */
if (lowpan6_buffer[1] & 0x80) {
lowpan6_offset++;
}
/* Set IPv6 version, traffic class and flow label. */
/* Set IPv6 version, traffic class and flow label. (RFC6282, ch 3.1.1.)*/
if ((lowpan6_buffer[0] & 0x18) == 0x00) {
IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset], ((lowpan6_buffer[lowpan6_offset + 1] & 0x0f) << 16) | (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset + 3]);
header_temp = ((lowpan6_buffer[lowpan6_offset+1] & 0x0f) << 16) | \
(lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset+3];
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 00, ECN: 0x%2x, Flowlabel+DSCP: 0x%8X\n", \
lowpan6_buffer[lowpan6_offset],header_temp));
IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset], header_temp);
/* increase offset, processed 4 bytes here:
* TF=00: ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)*/
lowpan6_offset += 4;
} else if ((lowpan6_buffer[0] & 0x18) == 0x08) {
IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset] & 0xc0, ((lowpan6_buffer[lowpan6_offset] & 0x0f) << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset + 2]);
header_temp = ((lowpan6_buffer[lowpan6_offset] & 0x0f) << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset+2];
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 01, ECN: 0x%2x, Flowlabel: 0x%2X, DSCP ignored\n", \
lowpan6_buffer[lowpan6_offset] & 0xc0,header_temp));
IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset] & 0xc0, header_temp);
/* increase offset, processed 3 bytes here:
* TF=01: ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided.*/
lowpan6_offset += 3;
} else if ((lowpan6_buffer[0] & 0x18) == 0x10) {
IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset], 0);
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 10, DCSP+ECN: 0x%2x, Flowlabel ignored\n", lowpan6_buffer[lowpan6_offset]));
IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset],0);
/* increase offset, processed 1 byte here:
* ECN + DSCP (1 byte), Flow Label is elided.*/
lowpan6_offset += 1;
} else if ((lowpan6_buffer[0] & 0x18) == 0x18) {
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 11, DCSP/ECN & Flowlabel ignored\n"));
/* don't increase offset, no bytes processed here */
IP6H_VTCFL_SET(ip6hdr, 6, 0, 0);
}
/* Set Next Header */
/* Set Next Header (NH) */
if ((lowpan6_buffer[0] & 0x04) == 0x00) {
/* 0: full next header byte carried inline (increase offset)*/
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("NH: 0x%2X\n", lowpan6_buffer[lowpan6_offset+1]));
IP6H_NEXTH_SET(ip6hdr, lowpan6_buffer[lowpan6_offset++]);
} else {
/* 1: NH compression, LOWPAN_NHC (RFC6282, ch 4.1) */
/* We should fill this later with NHC decoding */
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("NH: skipped, later done with NHC\n"));
IP6H_NEXTH_SET(ip6hdr, 0);
}
/* Set Hop Limit */
/* Set Hop Limit, either carried inline or 3 different hops (1,64,255) */
if ((lowpan6_buffer[0] & 0x03) == 0x00) {
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("Hops: full value: %d\n", lowpan6_buffer[lowpan6_offset+1]));
IP6H_HOPLIM_SET(ip6hdr, lowpan6_buffer[lowpan6_offset++]);
} else if ((lowpan6_buffer[0] & 0x03) == 0x01) {
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("Hops: compressed: 1\n"));
IP6H_HOPLIM_SET(ip6hdr, 1);
} else if ((lowpan6_buffer[0] & 0x03) == 0x02) {
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("Hops: compressed: 64\n"));
IP6H_HOPLIM_SET(ip6hdr, 64);
} else if ((lowpan6_buffer[0] & 0x03) == 0x03) {
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("Hops: compressed: 255\n"));
IP6H_HOPLIM_SET(ip6hdr, 255);
}
/* Source address decoding. */
if ((lowpan6_buffer[1] & 0x40) == 0x00) {
/* Source address compression (SAC) = 0 -> stateless compression */
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("SAC == 0, no context byte\n"));
/* Stateless compression */
if ((lowpan6_buffer[1] & 0x30) == 0x00) {
/* copy full address */
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("SAM == 00, no src compression, fetching 128bits inline\n"));
/* copy full address, increase offset by 16 Bytes */
MEMCPY(&ip6hdr->src.addr[0], lowpan6_buffer + lowpan6_offset, 16);
lowpan6_offset += 16;
} else if ((lowpan6_buffer[1] & 0x30) == 0x10) {
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("SAM == 01, src compression, 64bits inline\n"));
/* set 64 bits to link local */
ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL);
ip6hdr->src.addr[1] = 0;
/* copy 8 Bytes, increase offset */
MEMCPY(&ip6hdr->src.addr[2], lowpan6_buffer + lowpan6_offset, 8);
lowpan6_offset += 8;
} else if ((lowpan6_buffer[1] & 0x30) == 0x20) {
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("SAM == 10, src compression, 16bits inline\n"));
/* set 96 bits to link local */
ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL);
ip6hdr->src.addr[1] = 0;
ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL);
/* extract remaining 16bits from inline bytes, increase offset */
ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) |
lowpan6_buffer[lowpan6_offset + 1]);
lowpan6_offset += 2;
} else if ((lowpan6_buffer[1] & 0x30) == 0x30) {
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("SAM == 11, src compression, 0bits inline, using other headers\n"));
/* no information avalaible, using other layers, see RFC6282 ch 3.2.2 */
ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL);
ip6hdr->src.addr[1] = 0;
if (src->addr_len == 2) {
ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL);
ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]);
} else {
} else if (src->addr_len == 8) {
ip6hdr->src.addr[2] = lwip_htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) |
(src->addr[2] << 8) | src->addr[3]);
ip6hdr->src.addr[3] = lwip_htonl((src->addr[4] << 24) | (src->addr[5] << 16) |
(src->addr[6] << 8) | src->addr[7]);
} else {
/* invalid source address length */
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("Invalid source address length\n"));
return ERR_VAL;
}
}
} else {
/* Stateful compression */
/* Source address compression (SAC) = 1 -> stateful/context-based compression */
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("SAC == 1, additional context byte\n"));
if ((lowpan6_buffer[1] & 0x30) == 0x00) {
/* ANY address */
/* SAM=00, address=> :: (ANY) */
ip6hdr->src.addr[0] = 0;
ip6hdr->src.addr[1] = 0;
ip6hdr->src.addr[2] = 0;
ip6hdr->src.addr[3] = 0;
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("SAM == 00, context compression, ANY (::)\n"));
} else {
/* Set prefix from context info */
if (lowpan6_buffer[1] & 0x80) {
@ -504,54 +564,75 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize,
#if LWIP_6LOWPAN_NUM_CONTEXTS > 0
ip6hdr->src.addr[0] = lowpan6_contexts[i].addr[0];
ip6hdr->src.addr[1] = lowpan6_contexts[i].addr[1];
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("SAM == xx, context compression found @%d: %8X, %8X\n", (int)i, ip6hdr->src.addr[0], ip6hdr->src.addr[1]));
#else
LWIP_UNUSED_ARG(lowpan6_contexts);
#endif
}
/* determine further address bits */
if ((lowpan6_buffer[1] & 0x30) == 0x10) {
/* SAM=01, load additional 64bits */
MEMCPY(&ip6hdr->src.addr[2], lowpan6_buffer + lowpan6_offset, 8);
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("SAM == 01, context compression, 64bits inline\n"));
lowpan6_offset += 8;
} else if ((lowpan6_buffer[1] & 0x30) == 0x20) {
/* SAM=01, load additional 16bits */
ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL);
ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset + 1]);
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("SAM == 10, context compression, 16bits inline\n"));
lowpan6_offset += 2;
} else if ((lowpan6_buffer[1] & 0x30) == 0x30) {
/* SAM=11, address is fully elided, load from other layers */
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("SAM == 11, context compression, 0bits inline, using other headers\n"));
if (src->addr_len == 2) {
ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL);
ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]);
} else {
} else if (src->addr_len == 8) {
ip6hdr->src.addr[2] = lwip_htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) | (src->addr[2] << 8) | src->addr[3]);
ip6hdr->src.addr[3] = lwip_htonl((src->addr[4] << 24) | (src->addr[5] << 16) | (src->addr[6] << 8) | src->addr[7]);
} else {
/* invalid source address length */
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("Invalid source address length\n"));
return ERR_VAL;
}
}
}
/* Destination address decoding. */
if (lowpan6_buffer[1] & 0x08) {
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("M=1: multicast\n"));
/* Multicast destination */
if (lowpan6_buffer[1] & 0x04) {
LWIP_DEBUGF(LWIP_DBG_ON,("DAC == 1, context multicast: unsupported!!!\n"));
/* @todo support stateful multicast addressing */
return ERR_VAL;
}
if ((lowpan6_buffer[1] & 0x03) == 0x00) {
/* copy full address */
/* DAM = 00, copy full address (128bits) */
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("DAM == 00, no dst compression, fetching 128bits inline\n"));
MEMCPY(&ip6hdr->dest.addr[0], lowpan6_buffer + lowpan6_offset, 16);
lowpan6_offset += 16;
} else if ((lowpan6_buffer[1] & 0x03) == 0x01) {
/* DAM = 01, copy 4 bytes (32bits) */
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("DAM == 01, dst address form (48bits): ffXX::00XX:XXXX:XXXX\n"));
ip6hdr->dest.addr[0] = lwip_htonl(0xff000000UL | (lowpan6_buffer[lowpan6_offset++] << 16));
ip6hdr->dest.addr[1] = 0;
ip6hdr->dest.addr[2] = lwip_htonl(lowpan6_buffer[lowpan6_offset++]);
ip6hdr->dest.addr[3] = lwip_htonl((lowpan6_buffer[lowpan6_offset] << 24) | (lowpan6_buffer[lowpan6_offset + 1] << 16) | (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset + 3]);
lowpan6_offset += 4;
} else if ((lowpan6_buffer[1] & 0x03) == 0x02) {
/* DAM = 10, copy 3 bytes (24bits) */
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("DAM == 10, dst address form (32bits): ffXX::00XX:XXXX\n"));
ip6hdr->dest.addr[0] = lwip_htonl(0xff000000UL | (lowpan6_buffer[lowpan6_offset++] << 16));
ip6hdr->dest.addr[1] = 0;
ip6hdr->dest.addr[2] = 0;
ip6hdr->dest.addr[3] = lwip_htonl((lowpan6_buffer[lowpan6_offset] << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset + 2]);
lowpan6_offset += 3;
} else if ((lowpan6_buffer[1] & 0x03) == 0x03) {
/* DAM = 11, copy 1 byte (8bits) */
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("DAM == 11, dst address form (8bits): ff02::00XX\n"));
ip6hdr->dest.addr[0] = PP_HTONL(0xff020000UL);
ip6hdr->dest.addr[1] = 0;
ip6hdr->dest.addr[2] = 0;
@ -559,7 +640,9 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize,
}
} else {
/* no Multicast (M=0) */
if (lowpan6_buffer[1] & 0x04) {
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("DAC == 1, stateful compression\n"));
/* Stateful destination compression */
/* Set prefix from context info */
if (lowpan6_buffer[1] & 0x80) {
@ -576,29 +659,42 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize,
ip6hdr->dest.addr[1] = lowpan6_contexts[i].addr[1];
#endif
} else {
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("DAC == 0, stateless compression, setting link local prefix\n"));
/* Link local address compression */
ip6hdr->dest.addr[0] = PP_HTONL(0xfe800000UL);
ip6hdr->dest.addr[1] = 0;
}
/* M=0, DAC=0, determining destination address length via DAM=xx */
if ((lowpan6_buffer[1] & 0x03) == 0x00) {
/* copy full address */
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("DAM == 00, no dst compression, fetching 128bits inline"));
/* DAM=00, copy full address */
MEMCPY(&ip6hdr->dest.addr[0], lowpan6_buffer + lowpan6_offset, 16);
lowpan6_offset += 16;
} else if ((lowpan6_buffer[1] & 0x03) == 0x01) {
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("DAM == 01, dst compression, 64bits inline\n"));
/* DAM=01, copy 64 inline bits, increase offset */
MEMCPY(&ip6hdr->dest.addr[2], lowpan6_buffer + lowpan6_offset, 8);
lowpan6_offset += 8;
} else if ((lowpan6_buffer[1] & 0x03) == 0x02) {
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("DAM == 01, dst compression, 16bits inline\n"));
/* DAM=10, copy 16 inline bits, increase offset */
ip6hdr->dest.addr[2] = PP_HTONL(0x000000ffUL);
ip6hdr->dest.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset + 1]);
lowpan6_offset += 2;
} else if ((lowpan6_buffer[1] & 0x03) == 0x03) {
/* DAM=11, no bits available, use other headers (not done here) */
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG,("DAM == 01, dst compression, 0bits inline, using other headers\n"));
if (dest->addr_len == 2) {
ip6hdr->dest.addr[2] = PP_HTONL(0x000000ffUL);
ip6hdr->dest.addr[3] = lwip_htonl(0xfe000000UL | (dest->addr[0] << 8) | dest->addr[1]);
} else {
} else if (dest->addr_len == 8) {
ip6hdr->dest.addr[2] = lwip_htonl(((dest->addr[0] ^ 2) << 24) | (dest->addr[1] << 16) | dest->addr[2] << 8 | dest->addr[3]);
ip6hdr->dest.addr[3] = lwip_htonl((dest->addr[4] << 24) | (dest->addr[5] << 16) | dest->addr[6] << 8 | dest->addr[7]);
} else {
/* invalid destination address length */
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("Invalid destination address length\n"));
return ERR_VAL;
}
}
}
@ -606,9 +702,12 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize,
/* Next Header Compression (NHC) decoding? */
if (lowpan6_buffer[0] & 0x04) {
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("NHC decoding\n"));
#if LWIP_UDP
if ((lowpan6_buffer[lowpan6_offset] & 0xf8) == 0xf0) {
/* NHC: UDP */
struct udp_hdr *udphdr;
LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("NHC: UDP\n"));
/* UDP compression */
IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_UDP);
@ -617,12 +716,14 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize,
return ERR_MEM;
}
/* Checksum decompression */
if (lowpan6_buffer[lowpan6_offset] & 0x04) {
/* @todo support checksum decompress */
LWIP_DEBUGF(LWIP_DBG_ON, ("NHC: UDP chechsum decompression UNSUPPORTED\n"));
return ERR_VAL;
}
/* Decompress ports */
/* Decompress ports, according to RFC4944 */
i = lowpan6_buffer[lowpan6_offset++] & 0x03;
if (i == 0) {
udphdr->src = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]);
@ -653,6 +754,7 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize,
} else
#endif /* LWIP_UDP */
{
LWIP_DEBUGF(LWIP_DBG_ON,("NHC: unsupported protocol!\n"));
/* @todo support NHC other than UDP */
return ERR_VAL;
}