65 #include "dev/watchdog.h" 66 #include "net/link-stats.h" 71 #include "net/ipv6/uipbuf.h" 81 #define LOG_MODULE "6LoWPAN" 82 #define LOG_LEVEL LOG_LEVEL_6LOWPAN 84 #define GET16(ptr,index) (((uint16_t)((ptr)[index] << 8)) | ((ptr)[(index) + 1])) 85 #define SET16(ptr,index,value) do { \ 86 (ptr)[index] = ((value) >> 8) & 0xff; \ 87 (ptr)[index + 1] = (value) & 0xff; \ 93 #define PACKETBUF_FRAG_PTR (packetbuf_ptr) 94 #define PACKETBUF_FRAG_DISPATCH_SIZE 0 95 #define PACKETBUF_FRAG_TAG 2 96 #define PACKETBUF_FRAG_OFFSET 4 99 #define PACKETBUF_IPHC_BUF ((uint8_t *)(packetbuf_ptr + packetbuf_hdr_len)) 100 #define PACKETBUF_PAYLOAD_END ((uint8_t *)(packetbuf_ptr + mac_max_payload)) 102 #define PACKETBUF_6LO_PTR (packetbuf_ptr + packetbuf_hdr_len) 103 #define PACKETBUF_6LO_DISPATCH 0 104 #define PACKETBUF_6LO_ENCODING 1 105 #define PACKETBUF_6LO_TTL 2 107 #define PACKETBUF_6LO_HC_UDP_PTR (packetbuf_ptr + packetbuf_hdr_len) 108 #define PACKETBUF_6LO_HC_UDP_DISPATCH 0 109 #define PACKETBUF_6LO_HC_UDP_HC1_ENCODING 1 110 #define PACKETBUF_6LO_HC_UDP_UDP_ENCODING 2 111 #define PACKETBUF_6LO_HC_UDP_TTL 3 112 #define PACKETBUF_6LO_HC_UDP_PORTS 4 113 #define PACKETBUF_6LO_HC_UDP_CHKSUM 5 120 #define SICSLOWPAN_IP_BUF(buf) ((struct uip_ip_hdr *)buf) 121 #define SICSLOWPAN_UDP_BUF(buf) ((struct uip_udp_hdr *)&buf[UIP_IPH_LEN]) 122 #define SICSLOWPAN_IPPAYLOAD_BUF(buf) (&buf[UIP_IPH_LEN]) 124 #define UIP_IPPAYLOAD_BUF_POS(pos) (&uip_buf[UIP_IPH_LEN + (pos)]) 125 #define UIP_UDP_BUF_POS(pos) ((struct uip_udp_hdr *)UIP_IPPAYLOAD_BUF_POS(pos)) 130 #ifdef SICSLOWPAN_CONF_COMPRESS_EXT_HDR 131 #define COMPRESS_EXT_HDR SICSLOWPAN_CONF_COMPRESS_EXT_HDR 134 #define COMPRESS_EXT_HDR 1 138 #define IS_COMPRESSABLE_PROTO(x) (x == UIP_PROTO_UDP \ 139 || x == UIP_PROTO_HBHO \ 140 || x == UIP_PROTO_DESTO \ 141 || x == UIP_PROTO_ROUTING \ 142 || x == UIP_PROTO_FRAG) 144 #define IS_COMPRESSABLE_PROTO(x) (x == UIP_PROTO_UDP) 196 static int last_rssi;
202 #if SICSLOWPAN_CONF_FRAG 203 static uint16_t my_tag;
209 #ifdef SICSLOWPAN_CONF_FRAGMENT_BUFFERS 210 #define SICSLOWPAN_FRAGMENT_BUFFERS SICSLOWPAN_CONF_FRAGMENT_BUFFERS 212 #define SICSLOWPAN_FRAGMENT_BUFFERS 12 220 #ifdef SICSLOWPAN_CONF_REASS_CONTEXTS 221 #define SICSLOWPAN_REASS_CONTEXTS SICSLOWPAN_CONF_REASS_CONTEXTS 223 #define SICSLOWPAN_REASS_CONTEXTS 2 227 #ifdef SICSLOWPAN_CONF_FRAGMENT_SIZE 228 #define SICSLOWPAN_FRAGMENT_SIZE SICSLOWPAN_CONF_FRAGMENT_SIZE 231 #define SICSLOWPAN_FRAGMENT_SIZE (127 - 2 - 15) 235 #define SICSLOWPAN_FIRST_FRAGMENT_SIZE (SICSLOWPAN_FRAGMENT_SIZE + 38) 238 struct sicslowpan_frag_info {
248 uint16_t reassembled_len;
250 struct timer reass_timer;
253 uint16_t first_frag_len;
256 uint8_t first_frag[SICSLOWPAN_FIRST_FRAGMENT_SIZE];
259 static struct sicslowpan_frag_info frag_info[SICSLOWPAN_REASS_CONTEXTS];
261 struct sicslowpan_frag_buf {
268 uint8_t data[SICSLOWPAN_FRAGMENT_SIZE];
271 static struct sicslowpan_frag_buf frag_buf[SICSLOWPAN_FRAGMENT_BUFFERS];
275 clear_fragments(uint8_t frag_info_index)
279 frag_info[frag_info_index].len = 0;
280 for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) {
281 if(frag_buf[i].len > 0 && frag_buf[i].index == frag_info_index) {
291 timeout_fragments(
int not_context)
295 for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
296 if(frag_info[i].len > 0 && i != not_context &&
299 count += clear_fragments(i);
306 store_fragment(uint8_t index, uint8_t offset)
309 for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) {
310 if(frag_buf[i].len == 0) {
312 frag_buf[i].offset = offset;
314 frag_buf[i].index = index;
318 return frag_buf[i].len;
327 add_fragment(uint16_t tag, uint16_t frag_size, uint8_t offset)
335 for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
337 if(frag_info[i].len > 0 &&
timer_expired(&frag_info[i].reass_timer)) {
342 if(found < 0 && frag_info[i].len == 0) {
350 LOG_WARN(
"reassembly: failed to store new fragment session - tag: %d\n", tag);
355 frag_info[found].len = frag_size;
356 frag_info[found].tag = tag;
358 packetbuf_addr(PACKETBUF_ADDR_SENDER));
366 for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
367 if(frag_info[i].tag == tag && frag_info[i].len > 0 &&
368 linkaddr_cmp(&frag_info[i].sender, packetbuf_addr(PACKETBUF_ADDR_SENDER))) {
377 LOG_WARN(
"reassembly: failed to store N-fragment - could not find session - tag: %d offset: %d\n", tag, offset);
382 len = store_fragment(i, offset);
383 if(len < 0 && timeout_fragments(i) > 0) {
384 len = store_fragment(i, offset);
387 frag_info[i].reassembled_len += len;
392 LOG_WARN(
"reassembly: failed to store fragment - packet reassembly will fail tag:%d l\n", frag_info[i].tag);
405 memcpy((uint8_t *)
UIP_IP_BUF, (uint8_t *)frag_info[context].first_frag,
406 frag_info[context].first_frag_len);
407 for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) {
409 if(frag_buf[i].len > 0 && frag_buf[i].index == context) {
410 memcpy((uint8_t *)UIP_IP_BUF + (uint16_t)(frag_buf[i].offset << 3),
411 (uint8_t *)frag_buf[i].data, frag_buf[i].len);
415 clear_fragments(context);
424 static struct netstack_sniffer *callback = NULL;
427 netstack_sniffer_add(
struct netstack_sniffer *s)
433 netstack_sniffer_remove(
struct netstack_sniffer *s)
439 set_packet_attrs(
void)
443 packetbuf_set_attr(PACKETBUF_ATTR_NETWORK_ID,
UIP_IP_BUF->proto);
447 c = UIP_UDP_BUF_POS(0)->srcport;
448 if(UIP_UDP_BUF_POS(0)->destport < c) {
449 c = UIP_UDP_BUF_POS(0)->destport;
451 }
else if(
UIP_IP_BUF->proto == UIP_PROTO_TCP) {
452 c = UIP_TCP_BUF->srcport;
453 if(UIP_TCP_BUF->destport < c) {
454 c = UIP_TCP_BUF->destport;
456 }
else if(
UIP_IP_BUF->proto == UIP_PROTO_ICMP6) {
460 packetbuf_set_attr(PACKETBUF_ATTR_CHANNEL, c);
470 #if SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC 476 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 478 addr_contexts[SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS];
494 const uint8_t unc_llconf[] = {0x0f,0x28,0x22,0x20};
501 const uint8_t unc_ctxconf[] = {0x00,0x88,0x82,0x80};
508 const uint8_t unc_mxconf[] = {0x0f, 0x25, 0x23, 0x21};
511 const uint8_t llprefix[] = {0xfe, 0x80};
514 static const uint8_t ttl_values[] = {0, 1, 64, 255};
525 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 528 if((addr_contexts[i].used == 1) &&
529 uip_ipaddr_prefixcmp(&addr_contexts[i].prefix, ipaddr, 64)) {
530 return &addr_contexts[i];
542 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 545 if((addr_contexts[i].used == 1) &&
546 addr_contexts[i].number == number) {
547 return &addr_contexts[i];
555 compress_addr_64(uint8_t bitpos, uip_ipaddr_t *
ipaddr, uip_lladdr_t *lladdr)
580 uncompress_addr(uip_ipaddr_t *
ipaddr, uint8_t
const prefix[],
581 uint8_t pref_post_count, uip_lladdr_t *lladdr)
583 uint8_t prefcount = pref_post_count >> 4;
584 uint8_t postcount = pref_post_count & 0x0f;
586 prefcount = prefcount == 15 ? 16 : prefcount;
587 postcount = postcount == 15 ? 16 : postcount;
589 LOG_DBG(
"uncompression: address %d %d", prefcount, postcount);
592 memcpy(
ipaddr, prefix, prefcount);
594 if(prefcount + postcount < 16) {
595 memset(&
ipaddr->u8[prefcount], 0, 16 - (prefcount + postcount));
599 if(postcount == 2 && prefcount < 11) {
605 }
else if (prefcount > 0) {
653 uint8_t tmp, iphc0, iphc1, *next_hdr, *next_nhc;
655 struct uip_udp_hdr *udp_buf;
657 if(LOG_DBG_ENABLED) {
659 LOG_DBG(
"compression: before (%d): ",
UIP_IP_BUF->len[1]);
660 for(ndx = 0; ndx <
UIP_IP_BUF->len[1] + 40; ndx++) {
661 uint8_t data = ((uint8_t *) (
UIP_IP_BUF))[ndx];
662 LOG_DBG_(
"%02x", data);
669 #define CHECK_BUFFER_SPACE(writelen) do { \ 670 if(hc06_ptr + (writelen) >= PACKETBUF_PAYLOAD_END) { \ 671 LOG_WARN("Not enough packetbuf space to compress header (%u bytes, %u left). Aborting.\n", \ 672 (unsigned)(writelen), (unsigned)(PACKETBUF_PAYLOAD_END - hc06_ptr)); \ 682 CHECK_BUFFER_SPACE(38);
691 iphc0 = SICSLOWPAN_DISPATCH_IPHC;
693 PACKETBUF_IPHC_BUF[2] = 0;
708 LOG_DBG(
"compression: dest or src ipaddr - setting CID\n");
709 iphc1 |= SICSLOWPAN_IPHC_CID;
723 tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
728 iphc0 |= SICSLOWPAN_IPHC_FL_C;
732 iphc0 |= SICSLOWPAN_IPHC_TC_C;
743 iphc0 |= SICSLOWPAN_IPHC_TC_C;
760 if(IS_COMPRESSABLE_PROTO(
UIP_IP_BUF->proto)) {
761 iphc0 |= SICSLOWPAN_IPHC_NH_C;
765 if((iphc0 & SICSLOWPAN_IPHC_NH_C) == 0) {
779 iphc0 |= SICSLOWPAN_IPHC_TTL_1;
782 iphc0 |= SICSLOWPAN_IPHC_TTL_64;
785 iphc0 |= SICSLOWPAN_IPHC_TTL_255;
795 LOG_DBG(
"compression: addr unspecified - setting SAC\n");
796 iphc1 |= SICSLOWPAN_IPHC_SAC;
797 iphc1 |= SICSLOWPAN_IPHC_SAM_00;
801 LOG_DBG(
"compression: src with context - setting CID & SAC ctx: %d\n",
803 iphc1 |= SICSLOWPAN_IPHC_CID | SICSLOWPAN_IPHC_SAC;
804 PACKETBUF_IPHC_BUF[2] |= context->number << 4;
807 iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_SAM_BIT,
814 iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_SAM_BIT,
818 iphc1 |= SICSLOWPAN_IPHC_SAM_00;
826 iphc1 |= SICSLOWPAN_IPHC_M;
827 if(sicslowpan_is_mcast_addr_compressable8(&
UIP_IP_BUF->destipaddr)) {
828 iphc1 |= SICSLOWPAN_IPHC_DAM_11;
832 }
else if(sicslowpan_is_mcast_addr_compressable32(&
UIP_IP_BUF->destipaddr)) {
833 iphc1 |= SICSLOWPAN_IPHC_DAM_10;
838 }
else if(sicslowpan_is_mcast_addr_compressable48(&
UIP_IP_BUF->destipaddr)) {
839 iphc1 |= SICSLOWPAN_IPHC_DAM_01;
845 iphc1 |= SICSLOWPAN_IPHC_DAM_00;
854 iphc1 |= SICSLOWPAN_IPHC_DAC;
855 PACKETBUF_IPHC_BUF[2] |= context->number;
858 iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
860 (uip_lladdr_t *)link_destaddr);
866 iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
867 &
UIP_IP_BUF->destipaddr, (uip_lladdr_t *)link_destaddr);
870 iphc1 |= SICSLOWPAN_IPHC_DAM_00;
884 LOG_DBG(
"compression: first header: %d\n", *next_hdr);
885 while(next_hdr != NULL && IS_COMPRESSABLE_PROTO(*next_hdr)) {
886 LOG_DBG(
"compression: next header: %d\n", *next_hdr);
891 proto = SICSLOWPAN_NHC_ETX_HDR_HBHO;
892 case UIP_PROTO_ROUTING:
893 proto = proto == -1 ? SICSLOWPAN_NHC_ETX_HDR_ROUTING : proto;
895 proto = proto == -1 ? SICSLOWPAN_NHC_ETX_HDR_FRAG : proto;
896 case UIP_PROTO_DESTO:
899 struct uip_ext_hdr *ext_hdr =
900 (
struct uip_ext_hdr *) UIP_IPPAYLOAD_BUF_POS(ext_hdr_len);
902 proto = proto == -1 ? SICSLOWPAN_NHC_ETX_HDR_DESTO : proto;
904 len = (ext_hdr->len << 3) + 8;
905 LOG_DBG(
"compression: next header %d (len:%d)\n", *next_hdr, len);
907 next_hdr = &ext_hdr->next;
911 if(!IS_COMPRESSABLE_PROTO(*next_hdr)) {
912 CHECK_BUFFER_SPACE(1);
914 LOG_DBG(
"compression: keeping the next header in this ext hdr: %d\n",
918 CHECK_BUFFER_SPACE(len);
921 ext_hdr = (
struct uip_ext_hdr *)
hc06_ptr;
922 ext_hdr->len = len - 2;
929 *next_nhc = SICSLOWPAN_NHC_EXT_HDR |
930 (IS_COMPRESSABLE_PROTO(*next_hdr) ? SICSLOWPAN_NHC_BIT : 0) |
939 udp_buf = UIP_UDP_BUF_POS(ext_hdr_len);
940 LOG_DBG(
"compression: inlined UDP ports on send side: %x, %x\n",
943 if(((
UIP_HTONS(udp_buf->srcport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN) &&
944 ((
UIP_HTONS(udp_buf->destport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN)) {
946 *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_11;
947 LOG_DBG(
"IPHC: remove 12 b of both source & dest with prefix 0xFOB\n");
948 CHECK_BUFFER_SPACE(1);
951 SICSLOWPAN_UDP_4_BIT_PORT_MIN) << 4) +
952 (uint8_t)((
UIP_HTONS(udp_buf->destport) -
953 SICSLOWPAN_UDP_4_BIT_PORT_MIN));
955 }
else if((
UIP_HTONS(udp_buf->destport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
957 *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_01;
958 LOG_DBG(
"IPHC: leave source, remove 8 bits of dest with prefix 0xF0\n");
959 CHECK_BUFFER_SPACE(3);
960 memcpy(
hc06_ptr, &udp_buf->srcport, 2);
962 (uint8_t)((
UIP_HTONS(udp_buf->destport) -
963 SICSLOWPAN_UDP_8_BIT_PORT_MIN));
965 }
else if((
UIP_HTONS(udp_buf->srcport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
967 *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_10;
968 LOG_DBG(
"IPHC: remove 8 bits of source with prefix 0xF0, leave dest. hch: %i\n", *next_nhc);
969 CHECK_BUFFER_SPACE(3);
972 SICSLOWPAN_UDP_8_BIT_PORT_MIN));
973 memcpy(
hc06_ptr + 1, &udp_buf->destport, 2);
977 *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_00;
978 LOG_DBG(
"IPHC: cannot compress UDP headers\n");
979 CHECK_BUFFER_SPACE(4);
980 memcpy(
hc06_ptr, &udp_buf->srcport, 4);
984 CHECK_BUFFER_SPACE(2);
985 memcpy(
hc06_ptr, &udp_buf->udpchksum, 2);
992 LOG_ERR(
"compression: could not handle compression of header");
995 if(next_hdr != NULL) {
998 LOG_DBG(
"compression: last header could is not compressed: %d\n", *next_hdr);
1001 PACKETBUF_IPHC_BUF[0] = iphc0;
1002 PACKETBUF_IPHC_BUF[1] = iphc1;
1004 if(LOG_DBG_ENABLED) {
1008 uint8_t data = ((uint8_t *) packetbuf_ptr)[ndx];
1009 LOG_DBG_(
"%02x", data);
1039 uint8_t tmp, iphc0, iphc1, nhc;
1040 struct uip_ext_hdr *exthdr;
1041 uint8_t* last_nextheader;
1042 uint8_t* ip_payload;
1043 uint8_t ext_hdr_len = 0;
1048 iphc0 = PACKETBUF_IPHC_BUF[0];
1049 iphc1 = PACKETBUF_IPHC_BUF[1];
1052 if(iphc1 & SICSLOWPAN_IPHC_CID) {
1053 LOG_DBG(
"uncompression: CID flag set - increase header with one\n");
1058 if((iphc0 & SICSLOWPAN_IPHC_FL_C) == 0) {
1060 if((iphc0 & SICSLOWPAN_IPHC_TC_C) == 0) {
1062 memcpy(&SICSLOWPAN_IP_BUF(buf)->tcflow,
hc06_ptr + 1, 3);
1067 SICSLOWPAN_IP_BUF(buf)->vtc = 0x60 | ((tmp >> 2) & 0x0f);
1069 SICSLOWPAN_IP_BUF(buf)->tcflow = ((tmp >> 2) & 0x30) | (tmp << 6) |
1070 (SICSLOWPAN_IP_BUF(buf)->tcflow & 0x0f);
1073 SICSLOWPAN_IP_BUF(buf)->vtc = 0x60;
1075 SICSLOWPAN_IP_BUF(buf)->tcflow = (*
hc06_ptr & 0x0F) |
1077 memcpy(&SICSLOWPAN_IP_BUF(buf)->flow,
hc06_ptr + 1, 2);
1083 if((iphc0 & SICSLOWPAN_IPHC_TC_C) == 0) {
1085 SICSLOWPAN_IP_BUF(buf)->vtc = 0x60 | ((*
hc06_ptr >> 2) & 0x0f);
1086 SICSLOWPAN_IP_BUF(buf)->tcflow = ((*hc06_ptr << 6) & 0xC0) | ((*hc06_ptr >> 2) & 0x30);
1087 SICSLOWPAN_IP_BUF(buf)->flow = 0;
1091 SICSLOWPAN_IP_BUF(buf)->vtc = 0x60;
1092 SICSLOWPAN_IP_BUF(buf)->tcflow = 0;
1093 SICSLOWPAN_IP_BUF(buf)->flow = 0;
1098 if((iphc0 & SICSLOWPAN_IPHC_NH_C) == 0) {
1100 SICSLOWPAN_IP_BUF(buf)->proto = *
hc06_ptr;
1101 LOG_DBG(
"uncompression: next header inline: %d\n", SICSLOWPAN_IP_BUF(buf)->proto);
1106 if((iphc0 & 0x03) != SICSLOWPAN_IPHC_TTL_I) {
1107 SICSLOWPAN_IP_BUF(buf)->ttl = ttl_values[iphc0 & 0x03];
1109 SICSLOWPAN_IP_BUF(buf)->ttl = *
hc06_ptr;
1114 tmp = ((iphc1 & SICSLOWPAN_IPHC_SAM_11) >> SICSLOWPAN_IPHC_SAM_BIT) & 0x03;
1117 if(iphc1 & SICSLOWPAN_IPHC_SAC) {
1118 uint8_t sci = (iphc1 & SICSLOWPAN_IPHC_CID) ?
1119 PACKETBUF_IPHC_BUF[2] >> 4 : 0;
1124 if(context == NULL) {
1125 LOG_ERR(
"uncompression: error context not found\n");
1130 uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->srcipaddr,
1131 tmp != 0 ? context->prefix : NULL, unc_ctxconf[tmp],
1132 (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
1135 uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->srcipaddr, llprefix, unc_llconf[tmp],
1136 (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
1141 tmp = ((iphc1 & SICSLOWPAN_IPHC_DAM_11) >> SICSLOWPAN_IPHC_DAM_BIT) & 0x03;
1144 if(iphc1 & SICSLOWPAN_IPHC_M) {
1146 if(iphc1 & SICSLOWPAN_IPHC_DAC) {
1154 uint8_t prefix[] = {0xff, 0x02};
1155 if(tmp > 0 && tmp < 3) {
1160 uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, prefix,
1161 unc_mxconf[tmp], NULL);
1166 if(iphc1 & SICSLOWPAN_IPHC_DAC) {
1167 uint8_t dci = (iphc1 & SICSLOWPAN_IPHC_CID) ? PACKETBUF_IPHC_BUF[2] & 0x0f : 0;
1171 if(context == NULL) {
1172 LOG_ERR(
"uncompression: error context not found\n");
1175 uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, context->prefix,
1177 (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
1180 uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, llprefix,
1182 (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
1188 nhc = iphc0 & SICSLOWPAN_IPHC_NH_C;
1190 last_nextheader = &SICSLOWPAN_IP_BUF(buf)->proto;
1191 ip_payload = SICSLOWPAN_IPPAYLOAD_BUF(buf);
1193 while(nhc && (*
hc06_ptr & SICSLOWPAN_NHC_MASK) == SICSLOWPAN_NHC_EXT_HDR) {
1194 uint8_t eid = (*
hc06_ptr & 0x0e) >> 1;
1207 LOG_DBG(
"uncompression: next header is inlined. Next: %d\n", next);
1212 LOG_DBG(
"uncompression: found ext header id: %d next: %d len: %d\n", eid, next, len);
1214 case SICSLOWPAN_NHC_ETX_HDR_HBHO:
1217 case SICSLOWPAN_NHC_ETX_HDR_ROUTING:
1218 proto = UIP_PROTO_ROUTING;
1220 case SICSLOWPAN_NHC_ETX_HDR_FRAG:
1221 proto = UIP_PROTO_FRAG;
1223 case SICSLOWPAN_NHC_ETX_HDR_DESTO:
1224 proto = UIP_PROTO_DESTO;
1227 LOG_DBG(
"uncompression: error unsupported ext header\n");
1230 *last_nextheader = proto;
1232 exthdr = (
struct uip_ext_hdr *)ip_payload;
1233 exthdr->len = (2 + len) / 8 - 1;
1234 exthdr->next = next;
1235 last_nextheader = &exthdr->next;
1236 memcpy((uint8_t*)exthdr + 2,
hc06_ptr, len);
1239 ip_payload += (exthdr->len + 1) * 8;
1240 ext_hdr_len += (exthdr->len + 1) * 8;
1242 LOG_DBG(
"uncompression: %d len: %d exhdrlen: %d (calc: %d)\n",
1243 proto, len, exthdr->len, (exthdr->len + 1) * 8);
1247 if(nhc && (*
hc06_ptr & SICSLOWPAN_NHC_UDP_MASK) == SICSLOWPAN_NHC_UDP_ID) {
1248 struct uip_udp_hdr *udp_buf = (
struct uip_udp_hdr *)ip_payload;
1250 uint8_t checksum_compressed;
1251 *last_nextheader = UIP_PROTO_UDP;
1252 checksum_compressed = *
hc06_ptr & SICSLOWPAN_NHC_UDP_CHECKSUMC;
1253 LOG_DBG(
"uncompression: incoming header value: %i\n", *
hc06_ptr);
1254 switch(*
hc06_ptr & SICSLOWPAN_NHC_UDP_CS_P_11) {
1255 case SICSLOWPAN_NHC_UDP_CS_P_00:
1257 memcpy(&udp_buf->srcport,
hc06_ptr + 1, 2);
1258 memcpy(&udp_buf->destport,
hc06_ptr + 3, 2);
1259 LOG_DBG(
"uncompression: UDP ports (ptr+5): %x, %x\n",
1265 case SICSLOWPAN_NHC_UDP_CS_P_01:
1267 LOG_DBG(
"uncompression: destination address\n");
1268 memcpy(&udp_buf->srcport,
hc06_ptr + 1, 2);
1269 udp_buf->destport =
UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN + (*(
hc06_ptr + 3)));
1270 LOG_DBG(
"uncompression: UDP ports (ptr+4): %x, %x\n",
1275 case SICSLOWPAN_NHC_UDP_CS_P_10:
1277 LOG_DBG(
"uncompression: source address\n");
1278 udp_buf->srcport =
UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN +
1280 memcpy(&udp_buf->destport,
hc06_ptr + 2, 2);
1281 LOG_DBG(
"uncompression: UDP ports (ptr+4): %x, %x\n",
1286 case SICSLOWPAN_NHC_UDP_CS_P_11:
1288 udp_buf->srcport =
UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
1290 udp_buf->destport =
UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
1292 LOG_DBG(
"uncompression: UDP ports (ptr+2): %x, %x\n",
1297 LOG_DBG(
"uncompression: error unsupported UDP compression\n");
1300 if(!checksum_compressed) {
1301 memcpy(&udp_buf->udpchksum,
hc06_ptr, 2);
1303 LOG_DBG(
"uncompression: checksum included\n");
1305 LOG_DBG(
"uncompression: checksum *NOT* included\n");
1310 udp_buf->udplen =
UIP_HTONS(ip_len == 0 ? udp_len :
1311 ip_len - UIP_IPH_LEN - ext_hdr_len);
1312 LOG_DBG(
"uncompression: UDP length: %u (ext: %u) ip_len: %d udp_len: %d\n",
1313 UIP_HTONS(udp_buf->udplen), ext_hdr_len, ip_len, udp_len);
1323 LOG_DBG(
"uncompression: IP payload length: %d. %u - %u + %u - %u\n", len,
1327 SICSLOWPAN_IP_BUF(buf)->len[0] = len >> 8;
1328 SICSLOWPAN_IP_BUF(buf)->len[1] = len & 0x00FF;
1331 SICSLOWPAN_IP_BUF(buf)->len[0] = (ip_len - UIP_IPH_LEN) >> 8;
1332 SICSLOWPAN_IP_BUF(buf)->len[1] = (ip_len - UIP_IPH_LEN) & 0x00FF;
1338 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH 1347 PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] = SICSLOWPAN_DISPATCH_PAGING | (page & 0x0f);
1369 if((PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & SICSLOWPAN_DISPATCH_PAGING_MASK) == SICSLOWPAN_DISPATCH_PAGING) {
1371 curr_page = PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & 0x0f;
1400 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6 1402 compress_hdr_ipv6(linkaddr_t *link_destaddr)
1424 const linkaddr_t *dest;
1426 if(callback != NULL) {
1427 callback->output_callback(status);
1432 dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
1438 link_stats_packet_sent(dest, status, transmissions);
1441 NETSTACK_ROUTING.
link_callback(dest, status, transmissions);
1459 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, dest);
1461 #if NETSTACK_CONF_BRIDGE_MODE 1463 packetbuf_set_addr(PACKETBUF_ADDR_SENDER,(
void*)&
uip_lladdr);
1474 #if SICSLOWPAN_CONF_FRAG 1484 fragment_copy_payload_and_send(uint16_t uip_offset, linkaddr_t *dest) {
1493 q = queuebuf_new_from_packetbuf();
1495 LOG_WARN(
"output: could not allocate queuebuf, dropping fragment\n");
1503 queuebuf_to_packetbuf(q);
1510 LOG_ERR(
"output: error in fragment tx, dropping subsequent fragments.\n");
1553 if(localdest == NULL) {
1559 LOG_INFO(
"output: sending IPv6 packet with len %d\n",
uip_len);
1562 packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS,
1563 uipbuf_get_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS));
1566 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest);
1567 #if LLSEC802154_USES_AUX_HEADER 1569 packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL,
1570 uipbuf_get_attr(UIPBUF_ATTR_LLSEC_LEVEL));
1571 #if LLSEC802154_USES_EXPLICIT_KEYS 1572 packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX,
1573 uipbuf_get_attr(UIPBUF_ATTR_LLSEC_KEY_ID));
1581 LOG_WARN(
"output: failed to calculate payload size - dropping packet\n");
1586 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6 1587 compress_hdr_ipv6(&dest);
1589 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH 1597 #if SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC 1608 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest);
1611 LOG_INFO(
"output: header len %d -> %d, total len %d -> %d, MAC max payload %d, frag_needed %d\n",
1617 #if SICSLOWPAN_CONF_FRAG 1619 uint16_t processed_ip_out_len;
1636 int fragn_max_payload = (
mac_max_payload - SICSLOWPAN_FRAGN_HDR_LEN) & 0xfffffff8;
1638 int last_fragn_max_payload =
mac_max_payload - SICSLOWPAN_FRAGN_HDR_LEN;
1640 int middle_fragn_total_payload = MAX(total_payload - frag1_payload - last_fragn_max_payload, 0);
1642 int fragment_count = 2;
1643 if(middle_fragn_total_payload > 0) {
1644 fragment_count += 1 + (middle_fragn_total_payload - 1) / fragn_max_payload;
1647 int freebuf = queuebuf_numfree() - 1;
1648 LOG_INFO(
"output: fragmentation needed, fragments: %u, free queuebufs: %u\n",
1649 fragment_count, freebuf);
1651 if(freebuf < fragment_count) {
1652 LOG_WARN(
"output: dropping packet, not enough free bufs (needed: %u, free: %u)\n",
1653 fragment_count, freebuf);
1657 if(frag1_payload < 0) {
1661 LOG_WARN(
"output: compressed header does not fit first fragment\n");
1668 frag_tag = my_tag++;
1675 SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE,
1676 ((SICSLOWPAN_DISPATCH_FRAG1 << 8) |
uip_len));
1677 SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG, frag_tag);
1684 LOG_INFO(
"output: fragment %d/%d (tag %d, payload %d)\n",
1685 curr_frag + 1, fragment_count,
1695 SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE,
1696 ((SICSLOWPAN_DISPATCH_FRAGN << 8) |
uip_len));
1702 while(processed_ip_out_len <
uip_len) {
1705 PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET] = processed_ip_out_len >> 3;
1708 if(
uip_len - processed_ip_out_len > last_fragn_max_payload) {
1710 packetbuf_payload_len = fragn_max_payload;
1713 packetbuf_payload_len =
uip_len - processed_ip_out_len;
1718 LOG_INFO(
"output: fragment %d/%d (tag %d, payload %d, offset %d)\n",
1719 curr_frag + 1, fragment_count,
1720 frag_tag, packetbuf_payload_len, processed_ip_out_len);
1721 if(fragment_copy_payload_and_send(processed_ip_out_len, &dest) == 0) {
1728 LOG_ERR(
"output: Packet too large to be sent without fragmentation support; dropping packet\n");
1761 uint16_t frag_size = 0;
1763 uint8_t frag_offset = 0;
1766 #if SICSLOWPAN_CONF_FRAG 1767 uint8_t is_fragment = 0;
1768 int8_t frag_context = 0;
1771 uint16_t frag_tag = 0;
1772 uint8_t first_fragment = 0, last_fragment = 0;
1776 link_stats_input_callback(packetbuf_addr(PACKETBUF_ADDR_SENDER));
1786 LOG_WARN(
"input: empty packet\n");
1798 last_rssi = (
signed short)packetbuf_attr(PACKETBUF_ATTR_RSSI);
1800 #if SICSLOWPAN_CONF_FRAG 1806 switch((GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) >> 8) & SICSLOWPAN_DISPATCH_FRAG_MASK) {
1807 case SICSLOWPAN_DISPATCH_FRAG1:
1809 frag_size = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) & 0x07ff;
1810 frag_tag = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG);
1815 LOG_INFO(
"input: received first element of a fragmented packet (tag %d, len %d)\n",
1816 frag_tag, frag_size);
1819 frag_context = add_fragment(frag_tag, frag_size, frag_offset);
1821 if(frag_context == -1) {
1822 LOG_ERR(
"input: failed to allocate new reassembly context\n");
1826 buffer = frag_info[frag_context].first_frag;
1828 case SICSLOWPAN_DISPATCH_FRAGN:
1833 frag_offset = PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET];
1834 frag_tag = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG);
1835 frag_size = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) & 0x07ff;
1840 frag_context = add_fragment(frag_tag, frag_size, frag_offset);
1842 if(frag_context == -1) {
1843 LOG_ERR(
"input: reassembly context not found (tag %d)\n", frag_tag);
1851 if(frag_info[frag_context].reassembled_len >= frag_size) {
1860 if(is_fragment && !first_fragment) {
1870 LOG_INFO(
"input: page 1, 6LoRH\n");
1873 LOG_ERR(
"input: page %u not supported\n",
curr_page);
1878 if((PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & SICSLOWPAN_DISPATCH_IPHC_MASK) == SICSLOWPAN_DISPATCH_IPHC) {
1879 LOG_DBG(
"uncompression: IPHC dispatch\n");
1881 }
else if(PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] == SICSLOWPAN_DISPATCH_IPV6) {
1882 LOG_DBG(
"uncompression: IPV6 dispatch\n");
1892 LOG_ERR(
"uncompression: unknown dispatch: 0x%02x\n",
1893 PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & SICSLOWPAN_DISPATCH_IPHC_MASK);
1897 #if SICSLOWPAN_CONF_FRAG 1908 LOG_ERR(
"input: packet dropped due to header > total packet\n");
1913 #if SICSLOWPAN_CONF_FRAG 1915 LOG_INFO(
"input: fragment (tag %d, payload %d, offset %d) -- %u %u\n",
1924 if(req_size >
sizeof(
uip_buf)) {
1926 "input: packet dropped, minimum required IP_BUF size: %d+%d+%d=%d (current size: %u)\n",
1935 if(buffer != NULL) {
1941 #if SICSLOWPAN_CONF_FRAG 1944 if(first_fragment != 0) {
1950 if(last_fragment != 0) {
1951 frag_info[frag_context].reassembled_len = frag_size;
1953 copy_frags2uip(frag_context);
1961 if(!is_fragment || last_fragment) {
1963 if(is_fragment != 0 && last_fragment != 0) {
1971 LOG_INFO(
"input: received IPv6 packet with len %d\n",
1974 if(LOG_DBG_ENABLED) {
1976 LOG_DBG(
"uncompression: after (%u):",
UIP_IP_BUF->len[1]);
1977 for (ndx = 0; ndx <
UIP_IP_BUF->len[1] + 40; ndx++) {
1978 uint8_t data = ((uint8_t *) (
UIP_IP_BUF))[ndx];
1979 LOG_DBG_(
"%02x", data);
1987 callback->input_callback();
1990 #if LLSEC802154_USES_AUX_HEADER 1995 uipbuf_set_attr(UIPBUF_ATTR_LLSEC_LEVEL,
1996 packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL));
1997 #if LLSEC802154_USES_EXPLICIT_KEYS 1998 uipbuf_set_attr(UIPBUF_ATTR_LLSEC_KEY_ID,
1999 packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX));
2004 #if SICSLOWPAN_CONF_FRAG 2014 sicslowpan_init(
void)
2017 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPHC 2023 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 2024 addr_contexts[0].used = 1;
2025 addr_contexts[0].number = 0;
2026 #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_0 2027 SICSLOWPAN_CONF_ADDR_CONTEXT_0;
2029 addr_contexts[0].prefix[0] = UIP_DS6_DEFAULT_PREFIX_0;
2030 addr_contexts[0].prefix[1] = UIP_DS6_DEFAULT_PREFIX_1;
2034 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 1 2038 #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_1 2040 addr_contexts[1].used = 1;
2041 addr_contexts[1].number = 1;
2042 SICSLOWPAN_CONF_ADDR_CONTEXT_1;
2043 #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_2 2045 addr_contexts[2].used = 1;
2046 addr_contexts[2].number = 2;
2047 SICSLOWPAN_CONF_ADDR_CONTEXT_2;
2050 addr_contexts[i].used = 0;
2053 addr_contexts[i].used = 0;
2063 sicslowpan_get_last_rssi(
void)
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
#define UIP_IP_BUF
Direct access to IPv6 header.
static uint8_t packetbuf_hdr_len
packetbuf_hdr_len is the total length of (the processed) 6lowpan headers (fragment headers...
uip_lladdr_t uip_lladdr
Host L2 address.
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
Header for the Contiki/uIP interface.
static void digest_paging_dispatch(void)
Digest 6lorh headers before IPHC.
The MAC layer transmission could not be performed because of a fatal error.
void packetbuf_clear(void)
Clear and reset the packetbuf.
uint16_t uip_len
The length of the packet in the uip_buf buffer.
static int packetbuf_payload_len
The length of the payload in the Packetbuf buffer.
#define UIP_ICMP_BUF
Direct access to ICMP, UDP, and TCP headers and payload, with implicit ext header offset (global uip_...
void(* link_callback)(const linkaddr_t *addr, int status, int numtx)
Called by lower layers after every packet transmission.
static void send_packet(linkaddr_t *dest)
This function is called by the 6lowpan code to send out a packet.
#define UIP_PROTO_HBHO
extension headers types
static void digest_6lorh_hdr(void)
Digest 6lorh headers before IPHC.
static void packet_sent(void *ptr, int status, int transmissions)
Callback function for the MAC packet sent callback.
void uip_ds6_link_callback(int status, int numtx)
The callback function to update link-layer stats in a neighbor cache.
void uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
set the last 64 bits of an IP address based on the MAC address
const linkaddr_t linkaddr_null
The null link-layer address.
static uint8_t output(const linkaddr_t *localdest)
Take an IP packet and format it to be sent on an 802.15.4 network using 6lowpan.
Header file for IPv6-related data structures.
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
Configuration options for uIP.
#define sicslowpan_is_iid_16_bit_compressable(a)
check whether we can compress the IID in address 'a' to 16 bits.
static int mac_max_payload
mac_max_payload is the maimum payload space on the MAC frame.
#define CLOCK_SECOND
A second, measured in system clock time.
#define uip_is_addr_mac_addr_based(a, m)
was addr (a) forged based on the mac address m a type is uip_ipaddr_t m type is uiplladdr_t ...
static void add_paging_dispatch(uint8_t page)
Adds Paging dispatch byte.
Header file for the Packet queue buffer management
The MAC layer did not get an acknowledgement for the packet.
static void uncompress_hdr_iphc(uint8_t *buf, uint16_t ip_len)
Uncompress IPHC (i.e., IPHC and LOWPAN_UDP) headers and put them in sicslowpan_buf.
static uint8_t uncomp_hdr_len
uncomp_hdr_len is the length of the headers before compression (if HC2 is used this includes the UDP ...
The MAC layer transmission was OK.
static int last_tx_status
the result of the last transmitted fragment
The structure of a network driver in Contiki.
static uint8_t curr_page
The current page (RFC 4944)
#define SICSLOWPAN_REASS_MAXAGE
Timeout for packet reassembly at the 6lowpan layer (should be < 60s)
static uint8_t * hc06_ptr
pointer to the byte where to write next inline field.
#define uip_is_addr_unspecified(a)
Is IPv6 address a the unspecified address a is of type uip_ipaddr_t.
Routing driver header file
#define uip_buf
Macro to access uip_aligned_buf as an array of bytes.
int timer_expired(struct timer *t)
Check if a timer has expired.
The header for fragments.
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a link-layer address.
#define uip_is_addr_mcast(a)
is address a multicast address, see RFC 4291 a is of type uip_ipaddr_t*
#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS
If we use IPHC compression, how many address contexts do we support.
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
void(* send)(mac_callback_t sent_callback, void *ptr)
Send a packet from the packetbuf.
Header file for the uIP TCP/IP stack.
static int compress_hdr_iphc(linkaddr_t *link_destaddr)
Compress IP/UDP header.
static void add_6lorh_hdr(void)
Adds 6lorh headers before IPHC.
Header file for the Packet buffer (packetbuf) management
Include file for the Contiki low-layer network stack (NETSTACK)
int(* max_payload)(void)
Read out estimated max payload size based on payload in packetbuf.
void watchdog_periodic(void)
Writes the WDT clear sequence.
Header file for the 6lowpan implementation (RFC4944 and draft-hui-6lowpan-hc-01) ...
#define uip_is_addr_linklocal(a)
is addr (a) a link local unicast address, see RFC 4291 i.e.
Header file for the logging system
static void input(void)
Process a received 6lowpan packet.
static struct sicslowpan_addr_context * addr_context_lookup_by_number(uint8_t number)
find the context with the given number
static struct sicslowpan_addr_context * addr_context_lookup_by_prefix(uip_ipaddr_t *ipaddr)
find the context corresponding to prefix ipaddr
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
void tcpip_input(void)
Deliver an incoming packet to the TCP/IP stack.
static uint8_t * packetbuf_ptr
A pointer to the packetbuf buffer.
static struct sicslowpan_addr_context * context
Addresses contexts for IPHC.