diff --git a/include/nuttx/net/ip.h b/include/nuttx/net/ip.h index 8a9c8422443..c7b606078b7 100644 --- a/include/nuttx/net/ip.h +++ b/include/nuttx/net/ip.h @@ -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,7 @@ bool net_ipv6addr_maskcmp(const net_ipv6addr_t addr1, #endif /**************************************************************************** - * Function: net_ipv6addr_prefixcmp + * Name: net_ipv6addr_prefixcmp * * Description: * Compare two IPv6 address prefixes. @@ -538,7 +538,75 @@ bool net_ipv6addr_maskcmp(const net_ipv6addr_t addr1, (memcmp(addr1, addr2, length >> 3) == 0) /**************************************************************************** - * Function: net_ipaddr_mask + * 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 diff --git a/include/nuttx/net/sixlowpan.h b/include/nuttx/net/sixlowpan.h index 21fac9b2ca3..ebeb34933ac 100644 --- a/include/nuttx/net/sixlowpan.h +++ b/include/nuttx/net/sixlowpan.h @@ -160,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 ::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. */ diff --git a/net/sixlowpan/sixlowpan_hc06.c b/net/sixlowpan/sixlowpan_hc06.c index 7e151f2c373..270c6f68853 100644 --- a/net/sixlowpan/sixlowpan_hc06.c +++ b/net/sixlowpan/sixlowpan_hc06.c @@ -121,7 +121,7 @@ static FAR uint8_t *g_hc06ptr; * 0 -> 16 bytes from packet * 1 -> 2 bytes from prefix - bunch of zeroes and 8 from packet * 2 -> 2 bytes from prefix - 0000::00ff:fe00:XXXX from packet - * 3 -> 2 bytes from prefix - infer 8 bytes from lladdr + * 3 -> 2 bytes from prefix - infer 8 bytes from MAC address * * NOTE: => the uncompress function does change 0xf to 0x10 * NOTE: 0x00 => no-autoconfig => unspecified @@ -134,7 +134,7 @@ static const uint8_t g_unc_llconf[] = { 0x0f, 0x28, 0x22, 0x20 }; * 0 -> 0 bits from packet [unspecified / reserved] * 1 -> 8 bytes from prefix - bunch of zeroes and 8 from packet * 2 -> 8 bytes from prefix - 0000::00ff:fe00:XXXX + 2 from packet - * 3 -> 8 bytes from prefix - infer 8 bytes from lladdr + * 3 -> 8 bytes from prefix - infer 8 bytes from MAC address */ static const uint8_t g_unc_ctxconf[] = { 0x00, 0x88, 0x82, 0x80 }; @@ -144,7 +144,7 @@ static const uint8_t g_unc_ctxconf[] = { 0x00, 0x88, 0x82, 0x80 }; * 0 -> 0 bits from packet * 1 -> 2 bytes from prefix - bunch of zeroes 5 from packet * 2 -> 2 bytes from prefix - zeroes + 3 from packet - * 3 -> 2 bytes from prefix - infer 1 bytes from lladdr + * 3 -> 2 bytes from prefix - infer 1 bytes from MAC address */ static const uint8_t g_unc_mxconf[] = { 0x0f, 0x25, 0x23, 0x21 }; @@ -202,7 +202,7 @@ static FAR struct sixlowpan_addrcontext_s * ****************************************************************************/ static FAR struct sixlowpan_addrcontext_s * - find_addrcontext_byprefix(FAR net_ipv6addr_t *ipaddr) + find_addrcontext_byprefix(FAR const net_ipv6addr_t ipaddr) { #if CONFIG_NET_6LOWPAN_MAXADDRCONTEXT > 0 int i; @@ -222,6 +222,45 @@ static FAR struct sixlowpan_addrcontext_s * return NULL; } +/**************************************************************************** + * Name: uncompress_addr + * + * Description: + * Uncompress addresses based on a prefix and a postfix with zeroes in + * between. If the postfix is zero in length it will use the link address + * to configure the IP address (autoconf style). + * + * prefpost takes a byte where the first nibble specify prefix count + * and the second postfix count (NOTE: 15/0xf => 16 bytes copy). + * + ****************************************************************************/ + +static uint8_t compress_addr_64(FAR const net_ipv6addr_t ipaddr, + FAR const struct rimeaddr_s *macaddr, + uint8_t bitpos) +{ + if (sixlowpan_ismacbased(ipaddr, macaddr)) + { + return 3 << bitpos; /* 0-bits */ + } + else if (SIXLOWPAN_IS_IID_16BIT_COMPRESSABLE(ipaddr)) + { + /* Compress IID to 16 bits xxxx::0000:00ff:fe00:XXXX */ + + memcpy(g_hc06ptr, &ipaddr[7], 2); + g_hc06ptr += 2; + return 2 << bitpos; /* 16-bits */ + } + else + { + /* Do not compress IID => xxxx::IID */ + + memcpy(g_hc06ptr, &ipaddr[4], 8); + g_hc06ptr += 8; + return 1 << bitpos; /* 64-bits */ + } +} + /**************************************************************************** * Name: uncompress_addr * @@ -367,8 +406,7 @@ void sixlowpan_hc06_initialize(void) * Compress IP/UDP header * * This function is called by the 6lowpan code to create a compressed - * 6lowpan packet in the packetbuf buffer from a full IPv6 packet in the - * uip_buf buffer. + * 6lowpan packet in the frame buffer from a full IPv6 packet. * * HC-06 (draft-ietf-6lowpan-hc, version 6) * http://tools.ietf.org/html/draft-ietf-6lowpan-hc-06 @@ -395,11 +433,11 @@ void sixlowpan_hc06_initialize(void) * neither compress the IID. * * Input Parameters: - * ieee - A reference to the IEE802.15.4 network device state - * destip - 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. + * 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 @@ -407,11 +445,370 @@ void sixlowpan_hc06_initialize(void) ****************************************************************************/ void sixlowpan_compresshdr_hc06(FAR struct ieee802154_driver_s *ieee, - FAR const struct ipv6_hdr_s *destip, + 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 *iphc = RIME_IPHC_BUF; + FAR struct sixlowpan_addrcontext_s *addrcontext; + uint8_t iphc0; + uint8_t iphc1; + uint8_t tmp; + + ninfodumpbuffer("IPv6 before compression", ipv6, sizeof(ipv6_hdr_s)); + + g_hc06ptr = g_rimeptr + 2; + + /* As we copy some bit-length fields, in the IPHC encoding bytes, + * we sometimes use |= + * If the field is 0, and the current bit value in memory is 1, + * this does not work. We therefore reset the IPHC encoding here + */ + + iphc0 = SIXLOWPAN_DISPATCH_IPHC; + iphc1 = 0; + iphc[2] = 0; /* Might not be used - but needs to be cleared */ + + /* Address handling needs to be made first since it might cause an extra + * byte with [ SCI | DCI ] + */ + + /* Check if dest address context exists (for allocating third byte) + * + * TODO: fix this so that it remembers the looked up values for avoiding two + * lookups - or set the lookup values immediately + */ + + if (find_addrcontext_byprefix(ipv6->destipaddr) != NULL || + find_addrcontext_byprefix(ipv6->srcipaddr) != NULL) + { + /* set address context flag and increase g_hc06ptr */ + + ninfo("Decompressing dest or src ipaddr. Setting CID\n"); + iphc1 |= SIXLOWPAN_IPHC_CID; + g_hc06ptr++; + } + + /* Traffic class, flow label + * + * If flow label is 0, compress it. If traffic class is 0, compress it + * We have to process both in the same time as the offset of traffic class + * depends on the presence of version and flow label + */ + + /* hc06 format of tc is ECN | DSCP , original is DSCP | ECN */ + + tmp = (ipv6->vtc << 4) | (ipv6->tcf >> 4); + tmp = ((tmp & 0x03) << 6) | (tmp >> 2); + + if (((ipv6->tcf & 0x0f) == 0) && (ipv6->flow == 0)) + { + /* Flow label can be compressed */ + + iphc0 |= SIXLOWPAN_IPHC_FL_C; + if (((ipv6->vtc & 0x0f) == 0) && ((ipv6->tcf & 0xf0) == 0)) + { + /* Compress (elide) all */ + + iphc0 |= SIXLOWPAN_IPHC_TC_C; + } + else + { + /* Sompress only the flow label */ + + *g_hc06ptr = tmp; + g_hc06ptr += 1; + } + } + else + { + /* Flow label cannot be compressed */ + + if (((ipv6->vtc & 0x0f) == 0) && ((ipv6->tcf & 0xF0) == 0)) + { + /* Compress only traffic class */ + + iphc0 |= SIXLOWPAN_IPHC_TC_C; + *g_hc06ptr = (tmp & 0xc0) | (ipv6->tcf & 0x0f); + memcpy(g_hc06ptr + 1, &ipv6->flow, 2); + g_hc06ptr += 3; + } + else + { + /* Compress nothing */ + + memcpy(g_hc06ptr, &ipv6->vtc, 4); + + /* But replace the top byte with the new ECN | DSCP format */ + + *g_hc06ptr = tmp; + g_hc06ptr += 4; + } + } + + /* Note that the payload length is always compressed */ + + /* Next header. We compress it if UDP */ + +#if CONFIG_NET_UDP || UIP_CONF_ROUTER + if (ipv6->proto == IP_PROTO_UDP) + { + iphc0 |= SIXLOWPAN_IPHC_NH_C; + } +#endif /* CONFIG_NET_UDP */ + + if ((iphc0 & SIXLOWPAN_IPHC_NH_C) == 0) + { + *g_hc06ptr = ipv6->proto; + g_hc06ptr += 1; + } + + /* Hop limit + * + * if 1: compress, encoding is 01 + * if 64: compress, encoding is 10 + * if 255: compress, encoding is 11 + * else do not compress + */ + + switch (ipv6->ttl) + { + case 1: + iphc0 |= SIXLOWPAN_IPHC_TTL_1; + break; + + case 64: + iphc0 |= SIXLOWPAN_IPHC_TTL_64; + break; + + case 255: + iphc0 |= SIXLOWPAN_IPHC_TTL_255; + break; + + default: + *g_hc06ptr = ipv6->ttl; + g_hc06ptr += 1; + break; + } + + /* Source address - cannot be multicast */ + + if (net_is_addr_unspecified(ipv6->srcipaddr)) + { + ninfo("Compressing unspecified. Setting SAC\n"); + + iphc1 |= SIXLOWPAN_IPHC_SAC; + iphc1 |= SIXLOWPAN_IPHC_SAM_00; + } + else if ((addrcontext = find_addrcontext_byprefix(ipv6->srcipaddr)) != NULL) + { + /* Elide the prefix - indicate by CID and set address context + SAC */ + + ninfo("Compressing src with address context. Setting CID and SAC context: %d\n", + addrcontext->number); + + iphc1 |= SIXLOWPAN_IPHC_CID | SIXLOWPAN_IPHC_SAC; + iphc[2] |= addrcontext->number << 4; + + /* Compession compare with this nodes address (source) */ + + iphc1 |= compress_addr_64(ipv6->srcipaddr, &ieee->i_nodeaddr, + SIXLOWPAN_IPHC_SAM_BIT); + + /* No address context found for this address */ + } + else if (net_is_addr_linklocal(ipv6->srcipaddr) && + ipv6->destipaddr[1] == 0 && ipv6->destipaddr[2] == 0 && + ipv6->destipaddr[3] == 0) + { + iphc1 |= compress_addr_64(ipv6->srcipaddr, &ieee->i_nodeaddr, + SIXLOWPAN_IPHC_SAM_BIT); + } + else + { + /* Send the full address => SAC = 0, SAM = 00 */ + + iphc1 |= SIXLOWPAN_IPHC_SAM_00; /* 128-bits */ + memcpy(g_hc06ptr, ipv6->srcipaddr, 16); + g_hc06ptr += 16; + } + + /* Destination address */ + + if (net_is_addr_mcast(ipv6->destipaddr)) + { + /* Address is multicast, try to compress */ + + iphc1 |= SIXLOWPAN_IPHC_M; + if (SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE8(ipv6->destipaddr)) + { + iphc1 |= SIXLOWPAN_IPHC_DAM_11; + + /* Use last byte */ + + *g_hc06ptr = ipv6->destipaddr[7] & 0x00ff; + g_hc06ptr += 1; + } + else if (SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE32(ipv6->destipaddr)) + { + FAR uint8_t *iptr = (FAR uint8_t *)ipv6->destipaddr; + + iphc1 |= SIXLOWPAN_IPHC_DAM_10; + + /* Second byte + the last three */ + + *g_hc06ptr = iptr[1]; + memcpy(g_hc06ptr + 1, &iptr[13], 3); + g_hc06ptr += 4; + } + else if (SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE48(ipv6->destipaddr)) + { + FAR uint8_t *iptr = (FAR uint8_t *)ipv6->destipaddr; + + iphc1 |= SIXLOWPAN_IPHC_DAM_01; + + /* Second byte + the last five */ + + *g_hc06ptr = iptr[1]; + memcpy(g_hc06ptr + 1, &iptr[11], 5); + g_hc06ptr += 6; + } + else + { + iphc1 |= SIXLOWPAN_IPHC_DAM_00; + + /* Full address */ + + memcpy(g_hc06ptr, ipv6->destipaddr, 16); + g_hc06ptr += 16; + } + } + else + { + /* Address is unicast, try to compress */ + + if ((addrcontext = find_addrcontext_byprefix(ipv6->destipaddr)) != NULL) + { + /* Elide the prefix */ + + iphc1 |= SIXLOWPAN_IPHC_DAC; + iphc[2] |= addrcontext->number; + + /* Compession compare with link adress (destination) */ + + iphc1 |= compress_addr_64(ipv6->destipaddr, destmac, + SIXLOWPAN_IPHC_DAM_BIT); + + /* No address context found for this address */ + } + else if (net_is_addr_linklocal(ipv6->destipaddr) && + ipv6->destipaddr[1] == 0 && ipv6->destipaddr[2] == 0 && + ipv6->destipaddr[3] == 0) + { + iphc1 |= compress_addr_64(ipv6->destipaddr, destmac, + SIXLOWPAN_IPHC_DAM_BIT); + } + else + { + /* Send the full address */ + + iphc1 |= SIXLOWPAN_IPHC_DAM_00; /* 128-bits */ + memcpy(g_hc06ptr, ipv6->destipaddr, 16); + g_hc06ptr += 16; + } + } + + g_uncomp_hdrlen = IPv6_HDRLEN; + +#if CONFIG_NET_UDP + /* UDP header compression */ + + if (ipv6->proto == IP_PROTO_UDP) + { + FAR struct udp_hdr_s *udp = UDPIPv6BUF(ieee); + + ninfo("Uncompressed UDP ports on send side: %x, %x\n", + ntohs(udp->srcport), ntohs(udp->destport)); + + /* Mask out the last 4 bits can be used as a mask */ + + if (((ntohs(udp->srcport) & 0xfff0) == SIXLOWPAN_UDP_4_BIT_PORT_MIN) && + ((ntohs(udp->destport) & 0xfff0) == SIXLOWPAN_UDP_4_BIT_PORT_MIN)) + { + /* We can compress 12 bits of both source and dest */ + + *g_hc06ptr = SIXLOWPAN_NHC_UDP_CS_P_11; + + ninfo("Remove 12b of both source & dest with prefix 0xfob\n"); + + *(g_hc06ptr + 1) = + (uint8_t)((ntohs(udp->srcport) - SIXLOWPAN_UDP_4_BIT_PORT_MIN) << 4) + + (uint8_t)((ntohs(udp->destport) - SIXLOWPAN_UDP_4_BIT_PORT_MIN)); + + g_hc06ptr += 2; + } + else if ((ntohs(udp->destport) & 0xff00) == + SIXLOWPAN_UDP_8_BIT_PORT_MIN) + { + /* We can compress 8 bits of dest, leave source. */ + + *g_hc06ptr = SIXLOWPAN_NHC_UDP_CS_P_01; + + ninfo("Leave source, remove 8 bits of dest with prefix 0xF0\n"); + + memcpy(g_hc06ptr + 1, &udp->srcport, 2); + *(g_hc06ptr + 3) = + (uint8_t) ((ntohs(udp->destport) - + SIXLOWPAN_UDP_8_BIT_PORT_MIN)); + g_hc06ptr += 4; + } + else if ((ntohs(udp->srcport) & 0xff00) == + SIXLOWPAN_UDP_8_BIT_PORT_MIN) + { + /* We can compress 8 bits of src, leave dest. Copy compressed port */ + + *g_hc06ptr = SIXLOWPAN_NHC_UDP_CS_P_10; + + ninfo("Remove 8 bits of source with prefix 0xF0, leave dest. hch: %u\n", + *g_hc06ptr); + + *(g_hc06ptr + 1) = + (uint8_t)((ntohs(udp->srcport) - SIXLOWPAN_UDP_8_BIT_PORT_MIN)); + + memcpy(g_hc06ptr + 2, &udp->destport, 2); + g_hc06ptr += 4; + } + else + { + /* we cannot compress. Copy uncompressed ports, full checksum */ + + *g_hc06ptr = SIXLOWPAN_NHC_UDP_CS_P_00; + + nwarn("WARNING: Cannot compress headers\n"); + + memcpy(g_hc06ptr + 1, &udp->srcport, 4); + g_hc06ptr += 5; + } + + /* Always inline the checksum */ + + if (1) + { + memcpy(g_hc06ptr, &udp->udpchksum, 2); + g_hc06ptr += 2; + } + + g_uncomp_hdrlen += UDP_HDRLEN; + } +#endif /* CONFIG_NET_UDP */ + + /* Before the g_rime_hdrlen operation */ + + iphc[0] = iphc0; + iphc[1] = iphc1; + + g_rime_hdrlen = g_hc06ptr - g_rimeptr; + return; } /**************************************************************************** @@ -529,7 +926,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee, /* Next header is carried inline */ ipv6->proto = *g_hc06ptr; - ninfo("IPHC: next header inline: %d\n", ipv6->proto); + ninfo("Next header inline: %d\n", ipv6->proto); g_hc06ptr += 1; } @@ -563,7 +960,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee, addrcontext = find_addrcontext_bynumber(sci); if (addrcontext == NULL) { - ninfo("sixlowpan uncompress_hdr: error address context not found\n"); + nerr("ERROR: Address context not found\n"); return; } } @@ -633,7 +1030,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee, if (addrcontext == NULL) { - ninfo("sixlowpan uncompress_hdr: error address context not found\n"); + ninfo("ERROR: Address context not found\n"); return; } @@ -666,7 +1063,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee, ipv6->proto = IP_PROTO_UDP; checksum_compressed = *g_hc06ptr & SIXLOWPAN_NHC_UDP_CHECKSUMC; - ninfo("IPHC: Incoming header value: %i\n", *g_hc06ptr); + ninfo("Incoming header value: %i\n", *g_hc06ptr); switch (*g_hc06ptr & SIXLOWPAN_NHC_UDP_CS_P_11) { @@ -676,9 +1073,8 @@ void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee, memcpy(&udp->srcport, g_hc06ptr + 1, 2); memcpy(&udp->destport, g_hc06ptr + 3, 2); - ninfo("IPHC: Uncompressed UDP ports (ptr+5): %x, %x\n", - htons(udp->srcport), - htons(udp->destport)); + ninfo("Uncompressed UDP ports (ptr+5): %x, %x\n", + htons(udp->srcport), htons(udp->destport)); g_hc06ptr += 5; break; @@ -688,15 +1084,14 @@ void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee, * inline */ - ninfo("IPHC: Decompressing destination\n"); + ninfo("Decompressing destination\n"); memcpy(&udp->srcport, g_hc06ptr + 1, 2); udp->destport = htons(SIXLOWPAN_UDP_8_BIT_PORT_MIN + (*(g_hc06ptr + 3))); - ninfo("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n", - htons(udp->srcport), - htons(udp->destport)); + ninfo("Uncompressed UDP ports (ptr+4): %x, %x\n", + htons(udp->srcport), htons(udp->destport)); g_hc06ptr += 4; break; @@ -706,15 +1101,14 @@ void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee, * inline */ - ninfo("IPHC: Decompressing source\n"); + ninfo("Decompressing source\n"); udp->srcport = htons(SIXLOWPAN_UDP_8_BIT_PORT_MIN + (*(g_hc06ptr + 1))); memcpy(&udp->destport, g_hc06ptr + 2, 2); - ninfo("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n", - htons(udp->srcport), - htons(udp->destport)); + ninfo("Uncompressed UDP ports (ptr+4): %x, %x\n", + htons(udp->srcport), htons(udp->destport)); g_hc06ptr += 4; break; @@ -727,10 +1121,10 @@ void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee, (*(g_hc06ptr + 1) >> 4)); udp->destport = htons(SIXLOWPAN_UDP_4_BIT_PORT_MIN + - ((*(g_hc06ptr + 1)) & 0x0F)); - ninfo("IPHC: Uncompressed UDP ports (ptr+2): %x, %x\n", - htons(udp->srcport), - htons(udp->destport)); + ((*(g_hc06ptr + 1)) & 0x0f)); + + ninfo("Uncompressed UDP ports (ptr+2): %x, %x\n", + htons(udp->srcport), htons(udp->destport)); g_hc06ptr += 2; break; @@ -746,7 +1140,8 @@ void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee, memcpy(&udp->udpchksum, g_hc06ptr, 2); g_hc06ptr += 2; - ninfo("IPHC: sixlowpan uncompress_hdr: checksum included\n"); + + ninfo("Checksum included\n"); } else { diff --git a/net/sixlowpan/sixlowpan_hc1.c b/net/sixlowpan/sixlowpan_hc1.c index c3b5be08999..fd45280ea04 100644 --- a/net/sixlowpan/sixlowpan_hc1.c +++ b/net/sixlowpan/sixlowpan_hc1.c @@ -113,11 +113,11 @@ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * Input Parmeters: - * ieee - A reference to the IEE802.15.4 network device state - * destip - 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. + * 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 @@ -125,7 +125,7 @@ ****************************************************************************/ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee, - FAR const struct ipv6_hdr_s *destip, + FAR const struct ipv6_hdr_s *ipv6, FAR const struct rimeaddr_s *destmac, FAR struct iob_s *iob) { @@ -133,13 +133,13 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee, /* Check if all the assumptions for full compression are valid */ - if (destip->vtc != 0x60 || destip->tcflow != 0 || destip->flow != 0 || - !sixlowpan_islinklocal(&destip->srcipaddr) || - !sixlowpan_ismacbased(&destip->srcipaddr, &ieee->i_rimeaddr) || - !sixlowpan_islinklocal(&destip->destipaddr) || - !sixlowpan_ismacbased(&destip->destipaddr, destmac) || - (destip->proto != IP_PROTO_ICMP6 && destip->proto != IP_PROTO_UDP && - destip->proto != IP_PROTO_TCP)) + 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, @@ -148,7 +148,7 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee, *g_rimeptr = SIXLOWPAN_DISPATCH_IPV6; g_rime_hdrlen += SIXLOWPAN_IPV6_HDR_LEN; - memcpy(g_rimeptr + g_rime_hdrlen, destip, IPv6_HDRLEN); + memcpy(g_rimeptr + g_rime_hdrlen, ipv6, IPv6_HDRLEN); g_rime_hdrlen += IPv6_HDRLEN; g_uncomp_hdrlen += IPv6_HDRLEN; } @@ -161,13 +161,13 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee, hc1[RIME_HC1_DISPATCH] = SIXLOWPAN_DISPATCH_HC1; g_uncomp_hdrlen += IPv6_HDRLEN; - switch (destip->proto) + switch (ipv6->proto) { case IP_PROTO_ICMP6: /* HC1 encoding and ttl */ hc1[RIME_HC1_ENCODING] = 0xfc; - hc1[RIME_HC1_TTL] = destip->ttl; + hc1[RIME_HC1_TTL] = ipv6->ttl; g_rime_hdrlen += SIXLOWPAN_HC1_HDR_LEN; break; @@ -176,7 +176,7 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee, /* HC1 encoding and ttl */ hc1[RIME_HC1_ENCODING] = 0xfe; - hc1[RIME_HC1_TTL] = destip->ttl; + hc1[RIME_HC1_TTL] = ipv6->ttl; g_rime_hdrlen += SIXLOWPAN_HC1_HDR_LEN; break; #endif /* CONFIG_NET_TCP */ @@ -206,7 +206,7 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee, /* HC_UDP encoding, ttl, src and dest ports, checksum */ hcudp[RIME_HC1_HC_UDP_UDP_ENCODING] = 0xe0; - hcudp[RIME_HC1_HC_UDP_TTL] = destip->ttl; + 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)); @@ -221,7 +221,7 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee, /* HC1 encoding and ttl */ hc1[RIME_HC1_ENCODING] = 0xfa; - hc1[RIME_HC1_TTL] = destip->ttl; + hc1[RIME_HC1_TTL] = ipv6->ttl; g_rime_hdrlen += SIXLOWPAN_HC1_HDR_LEN; } break; @@ -257,24 +257,24 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee, int sixlowpan_uncompresshdr_hc1(FAR struct ieee802154_driver_s *ieee, uint16_t iplen) { - FAR struct ipv6_hdr_s *destip = IPv6BUF(&ieee->i_dev); + 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 */ - destip->vtc = 0x60; /* Bits 0-3: version, bits 4-7: traffic class (MS) */ - destip->tcf = 0; /* Bits 0-3: traffic class (LS), 4-bits: flow label (MS) */ - destip->flow = 0; /* 16-bit flow label (LS) */ + 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], - &destip->srcipaddr); + &ipv6->srcipaddr); sixlowpan_ipfromrime(&g_pktaddrs[PACKETBUF_ADDR_RECEIVER], - &destip->destipaddr); + &ipv6->destipaddr); g_uncomp_hdrlen += IPv6_HDRLEN; /* len[], proto, and ttl depend on the encoding */ @@ -282,15 +282,15 @@ int sixlowpan_uncompresshdr_hc1(FAR struct ieee802154_driver_s *ieee, switch (hc1[RIME_HC1_ENCODING] & 0x06) { case SIXLOWPAN_HC1_NH_ICMP6: - destip->proto = IP_PROTO_ICMP6; - destip->ttl = hc1[RIME_HC1_TTL]; + 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: - destip->proto = IP_PROTO_TCP; - destip->ttl = hc1[RIME_HC1_TTL]; + ipv6->proto = IP_PROTO_TCP; + ipv6->ttl = hc1[RIME_HC1_TTL]; g_rime_hdrlen += SIXLOWPAN_HC1_HDR_LEN; break; #endif /* CONFIG_NET_TCP */ @@ -301,7 +301,7 @@ int sixlowpan_uncompresshdr_hc1(FAR struct ieee802154_driver_s *ieee, FAR struct udp_hdr_s *udp = UDPIPv6BUF(&ieee->i_dev); FAR uint8_t *hcudp = RIME_HC1_HC_UDP_PTR; - destip->proto = IP_PROTO_UDP; + ipv6->proto = IP_PROTO_UDP; if ((hcudp[RIME_HC1_HC_UDP_HC1_ENCODING] & 0x01) != 0) { /* UDP header is compressed with HC_UDP */ @@ -315,7 +315,7 @@ int sixlowpan_uncompresshdr_hc1(FAR struct ieee802154_driver_s *ieee, /* IP TTL */ - destip->ttl = hcudp[RIME_HC1_HC_UDP_TTL]; + ipv6->ttl = hcudp[RIME_HC1_HC_UDP_TTL]; /* UDP ports, len, checksum */ @@ -347,25 +347,25 @@ int sixlowpan_uncompresshdr_hc1(FAR struct ieee802154_driver_s *ieee, { /* This is not a fragmented packet */ - destip->len[0] = 0; - destip->len[1] = ieee->i_dev.d_len - g_rime_hdrlen + /* REVISIT */ - g_uncomp_hdrlen - IPv6_HDRLEN; + 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 */ - destip->len[0] = (iplen - IPv6_HDRLEN) >> 8; - destip->len[1] = (iplen - IPv6_HDRLEN) & 0x00FF; + ipv6->len[0] = (iplen - IPv6_HDRLEN) >> 8; + ipv6->len[1] = (iplen - IPv6_HDRLEN) & 0x00FF; } /* length field in UDP header */ #if CONFIG_NET_UDP - if (destip->proto == IP_PROTO_UDP) + if (ipv6->proto == IP_PROTO_UDP) { FAR struct udp_hdr_s *udp = UDPIPv6BUF(&ieee->i_dev); - memcpy(&udp->udplen, &destip->len[0], 2); + memcpy(&udp->udplen, &ipv6->len[0], 2); } #endif diff --git a/net/sixlowpan/sixlowpan_internal.h b/net/sixlowpan/sixlowpan_internal.h index 4b56f57aa5c..dff37cf6f85 100644 --- a/net/sixlowpan/sixlowpan_internal.h +++ b/net/sixlowpan/sixlowpan_internal.h @@ -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,6 +225,68 @@ #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 ::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 ::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) \ @@ -538,7 +600,7 @@ void sixlowpan_hc06_initialize(void); #endif /**************************************************************************** - * Name: sixlowpan_hc06_initialize + * Name: sixlowpan_compresshdr_hc06 * * Description: * Compress IP/UDP header @@ -555,7 +617,7 @@ void sixlowpan_hc06_initialize(void); * * Input Parameters: * ieee - A reference to the IEE802.15.4 network device state - * destip - The IPv6 header to be compressed + * 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. @@ -567,13 +629,13 @@ void sixlowpan_hc06_initialize(void); #ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC06 void sixlowpan_compresshdr_hc06(FAR struct ieee802154_driver_s *ieee, - FAR const struct ipv6_hdr_s *destip, + 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 @@ -612,11 +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 - * destip - The IPv6 header to be compressed + * 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. + * destination field + * iob - The IOB into which the compressed header should be saved. * * Returned Value: * None @@ -625,7 +687,7 @@ 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 const struct ipv6_hdr_s *destip, + FAR const struct ipv6_hdr_s *ipv6, FAR const struct rimeaddr_s *destmac, FAR struct iob_s *iob); #endif @@ -673,7 +735,7 @@ int sixlowpan_frame_hdralloc(FAR struct iob_s *iob, int size); * and sixlowpan_ismacbased * * Description: - * sixlowpan_ipfromrime: Create a link local IPv6 address from a rime + * sixlowpan_ipfromrime: Create a link local IPv6 address from a rime * address. * * sixlowpan_rimefromip: Extract the rime address from a link local IPv6