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]) 125 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) 126 #define UIP_UDP_BUF(p) ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN + p]) 127 #define UIP_TCP_BUF ((struct uip_tcp_hdr *)&uip_buf[UIP_LLIPH_LEN]) 128 #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[UIP_LLIPH_LEN]) 129 #define UIP_IPPAYLOAD_BUF(pos) (&uip_buf[UIP_LLIPH_LEN + pos]) 137 #ifdef SICSLOWPAN_CONF_MAC_MAX_PAYLOAD 138 #define MAC_MAX_PAYLOAD SICSLOWPAN_CONF_MAC_MAX_PAYLOAD 140 #define MAC_MAX_PAYLOAD (127 - 2) 145 #ifdef SICSLOWPAN_CONF_MAC_MAX_HEADER 146 #define MAC_MAX_HEADER SICSLOWPAN_CONF_MAC_MAX_HEADER 148 #define MAC_MAX_HEADER 21 152 #ifdef SICSLOWPAN_CONF_COMPRESS_EXT_HDR 153 #define COMPRESS_EXT_HDR SICSLOWPAN_CONF_COMPRESS_EXT_HDR 156 #define COMPRESS_EXT_HDR 1 160 #define IS_COMPRESSABLE_PROTO(x) (x == UIP_PROTO_UDP \ 161 || x == UIP_PROTO_HBHO \ 162 || x == UIP_PROTO_DESTO \ 163 || x == UIP_PROTO_ROUTING \ 164 || x == UIP_PROTO_FRAG) 166 #define IS_COMPRESSABLE_PROTO(x) (x == UIP_PROTO_UDP) 218 static int last_rssi;
224 #if SICSLOWPAN_CONF_FRAG 225 static uint16_t my_tag;
231 #ifdef SICSLOWPAN_CONF_FRAGMENT_BUFFERS 232 #define SICSLOWPAN_FRAGMENT_BUFFERS SICSLOWPAN_CONF_FRAGMENT_BUFFERS 234 #define SICSLOWPAN_FRAGMENT_BUFFERS 12 242 #ifdef SICSLOWPAN_CONF_REASS_CONTEXTS 243 #define SICSLOWPAN_REASS_CONTEXTS SICSLOWPAN_CONF_REASS_CONTEXTS 245 #define SICSLOWPAN_REASS_CONTEXTS 2 249 #ifdef SICSLOWPAN_CONF_FRAGMENT_SIZE 250 #define SICSLOWPAN_FRAGMENT_SIZE SICSLOWPAN_CONF_FRAGMENT_SIZE 253 #define SICSLOWPAN_FRAGMENT_SIZE (MAC_MAX_PAYLOAD - 15) 257 #define SICSLOWPAN_FIRST_FRAGMENT_SIZE (SICSLOWPAN_FRAGMENT_SIZE + 38) 260 struct sicslowpan_frag_info {
270 uint16_t reassembled_len;
272 struct timer reass_timer;
275 uint16_t first_frag_len;
278 uint8_t first_frag[SICSLOWPAN_FIRST_FRAGMENT_SIZE];
281 static struct sicslowpan_frag_info frag_info[SICSLOWPAN_REASS_CONTEXTS];
283 struct sicslowpan_frag_buf {
290 uint8_t data[SICSLOWPAN_FRAGMENT_SIZE];
293 static struct sicslowpan_frag_buf frag_buf[SICSLOWPAN_FRAGMENT_BUFFERS];
297 clear_fragments(uint8_t frag_info_index)
301 frag_info[frag_info_index].len = 0;
302 for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) {
303 if(frag_buf[i].len > 0 && frag_buf[i].index == frag_info_index) {
313 timeout_fragments(
int not_context)
317 for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
318 if(frag_info[i].len > 0 && i != not_context &&
321 count += clear_fragments(i);
328 store_fragment(uint8_t index, uint8_t offset)
331 for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) {
332 if(frag_buf[i].len == 0) {
334 frag_buf[i].offset = offset;
336 frag_buf[i].index = index;
340 return frag_buf[i].len;
349 add_fragment(uint16_t tag, uint16_t frag_size, uint8_t offset)
357 for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
359 if(frag_info[i].len > 0 &&
timer_expired(&frag_info[i].reass_timer)) {
364 if(found < 0 && frag_info[i].len == 0) {
372 LOG_WARN(
"reassembly: failed to store new fragment session - tag: %d\n", tag);
377 frag_info[found].len = frag_size;
378 frag_info[found].tag = tag;
380 packetbuf_addr(PACKETBUF_ADDR_SENDER));
388 for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
389 if(frag_info[i].tag == tag && frag_info[i].len > 0 &&
390 linkaddr_cmp(&frag_info[i].sender, packetbuf_addr(PACKETBUF_ADDR_SENDER))) {
399 LOG_WARN(
"reassembly: failed to store N-fragment - could not find session - tag: %d offset: %d\n", tag, offset);
404 len = store_fragment(i, offset);
405 if(len < 0 && timeout_fragments(i) > 0) {
406 len = store_fragment(i, offset);
409 frag_info[i].reassembled_len += len;
414 LOG_WARN(
"reassembly: failed to store fragment - packet reassembly will fail tag:%d l\n", frag_info[i].tag);
427 memcpy((uint8_t *)
UIP_IP_BUF, (uint8_t *)frag_info[context].first_frag,
428 frag_info[context].first_frag_len);
429 for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) {
431 if(frag_buf[i].len > 0 && frag_buf[i].index == context) {
432 memcpy((uint8_t *)UIP_IP_BUF + (uint16_t)(frag_buf[i].offset << 3),
433 (uint8_t *)frag_buf[i].data, frag_buf[i].len);
437 clear_fragments(context);
446 static struct netstack_sniffer *callback = NULL;
449 netstack_sniffer_add(
struct netstack_sniffer *s)
455 netstack_sniffer_remove(
struct netstack_sniffer *s)
461 set_packet_attrs(
void)
465 packetbuf_set_attr(PACKETBUF_ATTR_NETWORK_ID,
UIP_IP_BUF->proto);
469 c = UIP_UDP_BUF(0)->srcport;
470 if(UIP_UDP_BUF(0)->destport < c) {
471 c = UIP_UDP_BUF(0)->destport;
473 }
else if(
UIP_IP_BUF->proto == UIP_PROTO_TCP) {
474 c = UIP_TCP_BUF->srcport;
475 if(UIP_TCP_BUF->destport < c) {
476 c = UIP_TCP_BUF->destport;
478 }
else if(
UIP_IP_BUF->proto == UIP_PROTO_ICMP6) {
482 packetbuf_set_attr(PACKETBUF_ATTR_CHANNEL, c);
492 #if SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC 498 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 500 addr_contexts[SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS];
516 const uint8_t unc_llconf[] = {0x0f,0x28,0x22,0x20};
523 const uint8_t unc_ctxconf[] = {0x00,0x88,0x82,0x80};
530 const uint8_t unc_mxconf[] = {0x0f, 0x25, 0x23, 0x21};
533 const uint8_t llprefix[] = {0xfe, 0x80};
536 static const uint8_t ttl_values[] = {0, 1, 64, 255};
547 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 550 if((addr_contexts[i].used == 1) &&
551 uip_ipaddr_prefixcmp(&addr_contexts[i].prefix, ipaddr, 64)) {
552 return &addr_contexts[i];
564 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 567 if((addr_contexts[i].used == 1) &&
568 addr_contexts[i].number == number) {
569 return &addr_contexts[i];
577 compress_addr_64(uint8_t bitpos, uip_ipaddr_t *
ipaddr, uip_lladdr_t *lladdr)
602 uncompress_addr(uip_ipaddr_t *
ipaddr, uint8_t
const prefix[],
603 uint8_t pref_post_count, uip_lladdr_t *lladdr)
605 uint8_t prefcount = pref_post_count >> 4;
606 uint8_t postcount = pref_post_count & 0x0f;
608 prefcount = prefcount == 15 ? 16 : prefcount;
609 postcount = postcount == 15 ? 16 : postcount;
611 LOG_DBG(
"uncompression: address %d %d", prefcount, postcount);
614 memcpy(
ipaddr, prefix, prefcount);
616 if(prefcount + postcount < 16) {
617 memset(&
ipaddr->u8[prefcount], 0, 16 - (prefcount + postcount));
621 if(postcount == 2 && prefcount < 11) {
627 }
else if (prefcount > 0) {
675 uint8_t tmp, iphc0, iphc1, *next_hdr, *next_nhc;
677 struct uip_udp_hdr *udp_buf;
679 if(LOG_DBG_ENABLED) {
681 LOG_DBG(
"compression: before (%d): ",
UIP_IP_BUF->len[1]);
682 for(ndx = 0; ndx <
UIP_IP_BUF->len[1] + 40; ndx++) {
683 uint8_t data = ((uint8_t *) (
UIP_IP_BUF))[ndx];
684 LOG_DBG_(
"%02x", data);
691 #define CHECK_BUFFER_SPACE(writelen) do { \ 692 if(hc06_ptr + (writelen) >= PACKETBUF_PAYLOAD_END) { \ 693 LOG_WARN("Not enough packetbuf space to compress header (%u bytes, %u left). Aborting.\n", \ 694 (unsigned)(writelen), (unsigned)(PACKETBUF_PAYLOAD_END - hc06_ptr)); \ 704 CHECK_BUFFER_SPACE(38);
713 iphc0 = SICSLOWPAN_DISPATCH_IPHC;
715 PACKETBUF_IPHC_BUF[2] = 0;
730 LOG_DBG(
"compression: dest or src ipaddr - setting CID\n");
731 iphc1 |= SICSLOWPAN_IPHC_CID;
745 tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
750 iphc0 |= SICSLOWPAN_IPHC_FL_C;
754 iphc0 |= SICSLOWPAN_IPHC_TC_C;
765 iphc0 |= SICSLOWPAN_IPHC_TC_C;
782 if(IS_COMPRESSABLE_PROTO(
UIP_IP_BUF->proto)) {
783 iphc0 |= SICSLOWPAN_IPHC_NH_C;
787 if((iphc0 & SICSLOWPAN_IPHC_NH_C) == 0) {
801 iphc0 |= SICSLOWPAN_IPHC_TTL_1;
804 iphc0 |= SICSLOWPAN_IPHC_TTL_64;
807 iphc0 |= SICSLOWPAN_IPHC_TTL_255;
817 LOG_DBG(
"compression: addr unspecified - setting SAC\n");
818 iphc1 |= SICSLOWPAN_IPHC_SAC;
819 iphc1 |= SICSLOWPAN_IPHC_SAM_00;
823 LOG_DBG(
"compression: src with context - setting CID & SAC ctx: %d\n",
825 iphc1 |= SICSLOWPAN_IPHC_CID | SICSLOWPAN_IPHC_SAC;
826 PACKETBUF_IPHC_BUF[2] |= context->number << 4;
829 iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_SAM_BIT,
836 iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_SAM_BIT,
840 iphc1 |= SICSLOWPAN_IPHC_SAM_00;
848 iphc1 |= SICSLOWPAN_IPHC_M;
849 if(sicslowpan_is_mcast_addr_compressable8(&
UIP_IP_BUF->destipaddr)) {
850 iphc1 |= SICSLOWPAN_IPHC_DAM_11;
854 }
else if(sicslowpan_is_mcast_addr_compressable32(&
UIP_IP_BUF->destipaddr)) {
855 iphc1 |= SICSLOWPAN_IPHC_DAM_10;
860 }
else if(sicslowpan_is_mcast_addr_compressable48(&
UIP_IP_BUF->destipaddr)) {
861 iphc1 |= SICSLOWPAN_IPHC_DAM_01;
867 iphc1 |= SICSLOWPAN_IPHC_DAM_00;
876 iphc1 |= SICSLOWPAN_IPHC_DAC;
877 PACKETBUF_IPHC_BUF[2] |= context->number;
880 iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
882 (uip_lladdr_t *)link_destaddr);
888 iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
889 &
UIP_IP_BUF->destipaddr, (uip_lladdr_t *)link_destaddr);
892 iphc1 |= SICSLOWPAN_IPHC_DAM_00;
906 LOG_DBG(
"compression: first header: %d\n", *next_hdr);
907 while(next_hdr != NULL && IS_COMPRESSABLE_PROTO(*next_hdr)) {
908 LOG_DBG(
"compression: next header: %d\n", *next_hdr);
913 proto = SICSLOWPAN_NHC_ETX_HDR_HBHO;
914 case UIP_PROTO_ROUTING:
915 proto = proto == -1 ? SICSLOWPAN_NHC_ETX_HDR_ROUTING : proto;
917 proto = proto == -1 ? SICSLOWPAN_NHC_ETX_HDR_FRAG : proto;
918 case UIP_PROTO_DESTO:
921 struct uip_ext_hdr *ext_hdr =
922 (
struct uip_ext_hdr *) UIP_IPPAYLOAD_BUF(ext_hdr_len);
924 proto = proto == -1 ? SICSLOWPAN_NHC_ETX_HDR_DESTO : proto;
926 len = (ext_hdr->len << 3) + 8;
927 LOG_DBG(
"compression: next header %d (len:%d)\n", *next_hdr, len);
929 next_hdr = &ext_hdr->next;
933 if(!IS_COMPRESSABLE_PROTO(*next_hdr)) {
934 CHECK_BUFFER_SPACE(1);
936 LOG_DBG(
"compression: keeping the next header in this ext hdr: %d\n",
940 CHECK_BUFFER_SPACE(len);
943 ext_hdr = (
struct uip_ext_hdr *)
hc06_ptr;
944 ext_hdr->len = len - 2;
951 *next_nhc = SICSLOWPAN_NHC_EXT_HDR |
952 (IS_COMPRESSABLE_PROTO(*next_hdr) ? SICSLOWPAN_NHC_BIT : 0) |
961 udp_buf = UIP_UDP_BUF(ext_hdr_len);
962 LOG_DBG(
"compression: inlined UDP ports on send side: %x, %x\n",
965 if(((
UIP_HTONS(udp_buf->srcport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN) &&
966 ((
UIP_HTONS(udp_buf->destport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN)) {
968 *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_11;
969 LOG_DBG(
"IPHC: remove 12 b of both source & dest with prefix 0xFOB\n");
970 CHECK_BUFFER_SPACE(1);
973 SICSLOWPAN_UDP_4_BIT_PORT_MIN) << 4) +
974 (uint8_t)((
UIP_HTONS(udp_buf->destport) -
975 SICSLOWPAN_UDP_4_BIT_PORT_MIN));
977 }
else if((
UIP_HTONS(udp_buf->destport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
979 *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_01;
980 LOG_DBG(
"IPHC: leave source, remove 8 bits of dest with prefix 0xF0\n");
981 CHECK_BUFFER_SPACE(3);
982 memcpy(
hc06_ptr, &udp_buf->srcport, 2);
984 (uint8_t)((
UIP_HTONS(udp_buf->destport) -
985 SICSLOWPAN_UDP_8_BIT_PORT_MIN));
987 }
else if((
UIP_HTONS(udp_buf->srcport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
989 *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_10;
990 LOG_DBG(
"IPHC: remove 8 bits of source with prefix 0xF0, leave dest. hch: %i\n", *next_nhc);
991 CHECK_BUFFER_SPACE(3);
994 SICSLOWPAN_UDP_8_BIT_PORT_MIN));
995 memcpy(
hc06_ptr + 1, &udp_buf->destport, 2);
999 *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_00;
1000 LOG_DBG(
"IPHC: cannot compress UDP headers\n");
1001 CHECK_BUFFER_SPACE(4);
1002 memcpy(
hc06_ptr, &udp_buf->srcport, 4);
1006 CHECK_BUFFER_SPACE(2);
1007 memcpy(
hc06_ptr, &udp_buf->udpchksum, 2);
1014 LOG_ERR(
"compression: could not handle compression of header");
1017 if(next_hdr != NULL) {
1020 LOG_DBG(
"compression: last header could is not compressed: %d\n", *next_hdr);
1023 PACKETBUF_IPHC_BUF[0] = iphc0;
1024 PACKETBUF_IPHC_BUF[1] = iphc1;
1026 if(LOG_DBG_ENABLED) {
1030 uint8_t data = ((uint8_t *) packetbuf_ptr)[ndx];
1031 LOG_DBG_(
"%02x", data);
1061 uint8_t tmp, iphc0, iphc1, nhc;
1062 struct uip_ext_hdr *exthdr;
1063 uint8_t* last_nextheader;
1064 uint8_t* ip_payload;
1065 uint8_t ext_hdr_len = 0;
1070 iphc0 = PACKETBUF_IPHC_BUF[0];
1071 iphc1 = PACKETBUF_IPHC_BUF[1];
1074 if(iphc1 & SICSLOWPAN_IPHC_CID) {
1075 LOG_DBG(
"uncompression: CID flag set - increase header with one\n");
1080 if((iphc0 & SICSLOWPAN_IPHC_FL_C) == 0) {
1082 if((iphc0 & SICSLOWPAN_IPHC_TC_C) == 0) {
1084 memcpy(&SICSLOWPAN_IP_BUF(buf)->tcflow,
hc06_ptr + 1, 3);
1089 SICSLOWPAN_IP_BUF(buf)->vtc = 0x60 | ((tmp >> 2) & 0x0f);
1091 SICSLOWPAN_IP_BUF(buf)->tcflow = ((tmp >> 2) & 0x30) | (tmp << 6) |
1092 (SICSLOWPAN_IP_BUF(buf)->tcflow & 0x0f);
1095 SICSLOWPAN_IP_BUF(buf)->vtc = 0x60;
1097 SICSLOWPAN_IP_BUF(buf)->tcflow = (*
hc06_ptr & 0x0F) |
1099 memcpy(&SICSLOWPAN_IP_BUF(buf)->flow,
hc06_ptr + 1, 2);
1105 if((iphc0 & SICSLOWPAN_IPHC_TC_C) == 0) {
1107 SICSLOWPAN_IP_BUF(buf)->vtc = 0x60 | ((*
hc06_ptr >> 2) & 0x0f);
1108 SICSLOWPAN_IP_BUF(buf)->tcflow = ((*hc06_ptr << 6) & 0xC0) | ((*hc06_ptr >> 2) & 0x30);
1109 SICSLOWPAN_IP_BUF(buf)->flow = 0;
1113 SICSLOWPAN_IP_BUF(buf)->vtc = 0x60;
1114 SICSLOWPAN_IP_BUF(buf)->tcflow = 0;
1115 SICSLOWPAN_IP_BUF(buf)->flow = 0;
1120 if((iphc0 & SICSLOWPAN_IPHC_NH_C) == 0) {
1122 SICSLOWPAN_IP_BUF(buf)->proto = *
hc06_ptr;
1123 LOG_DBG(
"uncompression: next header inline: %d\n", SICSLOWPAN_IP_BUF(buf)->proto);
1128 if((iphc0 & 0x03) != SICSLOWPAN_IPHC_TTL_I) {
1129 SICSLOWPAN_IP_BUF(buf)->ttl = ttl_values[iphc0 & 0x03];
1131 SICSLOWPAN_IP_BUF(buf)->ttl = *
hc06_ptr;
1136 tmp = ((iphc1 & SICSLOWPAN_IPHC_SAM_11) >> SICSLOWPAN_IPHC_SAM_BIT) & 0x03;
1139 if(iphc1 & SICSLOWPAN_IPHC_SAC) {
1140 uint8_t sci = (iphc1 & SICSLOWPAN_IPHC_CID) ?
1141 PACKETBUF_IPHC_BUF[2] >> 4 : 0;
1146 if(context == NULL) {
1147 LOG_ERR(
"uncompression: error context not found\n");
1152 uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->srcipaddr,
1153 tmp != 0 ? context->prefix : NULL, unc_ctxconf[tmp],
1154 (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
1157 uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->srcipaddr, llprefix, unc_llconf[tmp],
1158 (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
1163 tmp = ((iphc1 & SICSLOWPAN_IPHC_DAM_11) >> SICSLOWPAN_IPHC_DAM_BIT) & 0x03;
1166 if(iphc1 & SICSLOWPAN_IPHC_M) {
1168 if(iphc1 & SICSLOWPAN_IPHC_DAC) {
1176 uint8_t prefix[] = {0xff, 0x02};
1177 if(tmp > 0 && tmp < 3) {
1182 uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, prefix,
1183 unc_mxconf[tmp], NULL);
1188 if(iphc1 & SICSLOWPAN_IPHC_DAC) {
1189 uint8_t dci = (iphc1 & SICSLOWPAN_IPHC_CID) ? PACKETBUF_IPHC_BUF[2] & 0x0f : 0;
1193 if(context == NULL) {
1194 LOG_ERR(
"uncompression: error context not found\n");
1197 uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, context->prefix,
1199 (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
1202 uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, llprefix,
1204 (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
1210 nhc = iphc0 & SICSLOWPAN_IPHC_NH_C;
1212 last_nextheader = &SICSLOWPAN_IP_BUF(buf)->proto;
1213 ip_payload = SICSLOWPAN_IPPAYLOAD_BUF(buf);
1215 while(nhc && (*
hc06_ptr & SICSLOWPAN_NHC_MASK) == SICSLOWPAN_NHC_EXT_HDR) {
1216 uint8_t eid = (*
hc06_ptr & 0x0e) >> 1;
1229 LOG_DBG(
"uncompression: next header is inlined. Next: %d\n", next);
1234 LOG_DBG(
"uncompression: found ext header id: %d next: %d len: %d\n", eid, next, len);
1236 case SICSLOWPAN_NHC_ETX_HDR_HBHO:
1239 case SICSLOWPAN_NHC_ETX_HDR_ROUTING:
1240 proto = UIP_PROTO_ROUTING;
1242 case SICSLOWPAN_NHC_ETX_HDR_FRAG:
1243 proto = UIP_PROTO_FRAG;
1245 case SICSLOWPAN_NHC_ETX_HDR_DESTO:
1246 proto = UIP_PROTO_DESTO;
1249 LOG_DBG(
"uncompression: error unsupported ext header\n");
1252 *last_nextheader = proto;
1254 exthdr = (
struct uip_ext_hdr *)ip_payload;
1255 exthdr->len = (2 + len) / 8 - 1;
1256 exthdr->next = next;
1257 last_nextheader = &exthdr->next;
1258 memcpy((uint8_t*)exthdr + 2,
hc06_ptr, len);
1261 ip_payload += (exthdr->len + 1) * 8;
1262 ext_hdr_len += (exthdr->len + 1) * 8;
1264 LOG_DBG(
"uncompression: %d len: %d exhdrlen: %d (calc: %d)\n",
1265 proto, len, exthdr->len, (exthdr->len + 1) * 8);
1269 if(nhc && (*
hc06_ptr & SICSLOWPAN_NHC_UDP_MASK) == SICSLOWPAN_NHC_UDP_ID) {
1270 struct uip_udp_hdr *udp_buf = (
struct uip_udp_hdr *)ip_payload;
1272 uint8_t checksum_compressed;
1273 *last_nextheader = UIP_PROTO_UDP;
1274 checksum_compressed = *
hc06_ptr & SICSLOWPAN_NHC_UDP_CHECKSUMC;
1275 LOG_DBG(
"uncompression: incoming header value: %i\n", *
hc06_ptr);
1276 switch(*
hc06_ptr & SICSLOWPAN_NHC_UDP_CS_P_11) {
1277 case SICSLOWPAN_NHC_UDP_CS_P_00:
1279 memcpy(&udp_buf->srcport,
hc06_ptr + 1, 2);
1280 memcpy(&udp_buf->destport,
hc06_ptr + 3, 2);
1281 LOG_DBG(
"uncompression: UDP ports (ptr+5): %x, %x\n",
1287 case SICSLOWPAN_NHC_UDP_CS_P_01:
1289 LOG_DBG(
"uncompression: destination address\n");
1290 memcpy(&udp_buf->srcport,
hc06_ptr + 1, 2);
1291 udp_buf->destport =
UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN + (*(
hc06_ptr + 3)));
1292 LOG_DBG(
"uncompression: UDP ports (ptr+4): %x, %x\n",
1297 case SICSLOWPAN_NHC_UDP_CS_P_10:
1299 LOG_DBG(
"uncompression: source address\n");
1300 udp_buf->srcport =
UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN +
1302 memcpy(&udp_buf->destport,
hc06_ptr + 2, 2);
1303 LOG_DBG(
"uncompression: UDP ports (ptr+4): %x, %x\n",
1308 case SICSLOWPAN_NHC_UDP_CS_P_11:
1310 udp_buf->srcport =
UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
1312 udp_buf->destport =
UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
1314 LOG_DBG(
"uncompression: UDP ports (ptr+2): %x, %x\n",
1319 LOG_DBG(
"uncompression: error unsupported UDP compression\n");
1322 if(!checksum_compressed) {
1323 memcpy(&udp_buf->udpchksum,
hc06_ptr, 2);
1325 LOG_DBG(
"uncompression: checksum included\n");
1327 LOG_DBG(
"uncompression: checksum *NOT* included\n");
1332 udp_buf->udplen =
UIP_HTONS(ip_len == 0 ? udp_len :
1333 ip_len - UIP_IPH_LEN - ext_hdr_len);
1334 LOG_DBG(
"uncompression: UDP length: %u (ext: %u) ip_len: %d udp_len: %d\n",
1335 UIP_HTONS(udp_buf->udplen), ext_hdr_len, ip_len, udp_len);
1345 LOG_DBG(
"uncompression: IP payload length: %d. %u - %u + %u - %u\n", len,
1349 SICSLOWPAN_IP_BUF(buf)->len[0] = len >> 8;
1350 SICSLOWPAN_IP_BUF(buf)->len[1] = len & 0x00FF;
1353 SICSLOWPAN_IP_BUF(buf)->len[0] = (ip_len - UIP_IPH_LEN) >> 8;
1354 SICSLOWPAN_IP_BUF(buf)->len[1] = (ip_len - UIP_IPH_LEN) & 0x00FF;
1360 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH 1369 PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] = SICSLOWPAN_DISPATCH_PAGING | (page & 0x0f);
1391 if((PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & SICSLOWPAN_DISPATCH_PAGING_MASK) == SICSLOWPAN_DISPATCH_PAGING) {
1393 curr_page = PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & 0x0f;
1422 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6 1424 compress_hdr_ipv6(linkaddr_t *link_destaddr)
1446 const linkaddr_t *dest;
1448 if(callback != NULL) {
1449 callback->output_callback(status);
1454 dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
1460 link_stats_packet_sent(dest, status, transmissions);
1463 NETSTACK_ROUTING.
link_callback(dest, status, transmissions);
1466 uip_ds6_link_callback(status, transmissions);
1481 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, dest);
1483 #if NETSTACK_CONF_BRIDGE_MODE 1485 packetbuf_set_addr(PACKETBUF_ADDR_SENDER,(
void*)&
uip_lladdr);
1496 #if SICSLOWPAN_CONF_FRAG 1506 fragment_copy_payload_and_send(uint16_t uip_offset, linkaddr_t *dest) {
1515 q = queuebuf_new_from_packetbuf();
1517 LOG_WARN(
"output: could not allocate queuebuf, dropping fragment\n");
1525 queuebuf_to_packetbuf(q);
1532 LOG_ERR(
"output: error in fragment tx, dropping subsequent fragments.\n");
1577 if(localdest == NULL) {
1583 LOG_INFO(
"output: sending IPv6 packet with len %d\n",
uip_len);
1586 packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS,
1587 uipbuf_get_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS));
1590 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest);
1591 framer_hdrlen = NETSTACK_FRAMER.length();
1592 if(framer_hdrlen < 0) {
1600 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6 1601 compress_hdr_ipv6(&dest);
1603 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH 1611 #if SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC 1621 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest);
1622 framer_hdrlen = NETSTACK_FRAMER.length();
1623 if(framer_hdrlen < 0) {
1630 LOG_INFO(
"output: header len %d -> %d, total len %d -> %d, MAC max payload %d, frag_needed %d\n",
1633 max_payload, frag_needed);
1636 #if SICSLOWPAN_CONF_FRAG 1638 uint16_t processed_ip_out_len;
1653 int frag1_payload = (max_payload -
packetbuf_hdr_len - SICSLOWPAN_FRAG1_HDR_LEN) & 0xfffffff8;
1655 int fragn_max_payload = (max_payload - SICSLOWPAN_FRAGN_HDR_LEN) & 0xfffffff8;
1657 int last_fragn_max_payload = max_payload - SICSLOWPAN_FRAGN_HDR_LEN;
1659 int middle_fragn_total_payload = MAX(total_payload - frag1_payload - last_fragn_max_payload, 0);
1661 int fragment_count = 2;
1662 if(middle_fragn_total_payload > 0) {
1663 fragment_count += 1 + (middle_fragn_total_payload - 1) / fragn_max_payload;
1666 int freebuf = queuebuf_numfree() - 1;
1667 LOG_INFO(
"output: fragmentation needed, fragments: %u, free queuebufs: %u\n",
1668 fragment_count, freebuf);
1670 if(freebuf < fragment_count) {
1671 LOG_WARN(
"output: dropping packet, not enough free bufs (needed: %u, free: %u)\n",
1672 fragment_count, freebuf);
1676 if(frag1_payload < 0) {
1680 LOG_WARN(
"output: compressed header does not fit first fragment\n");
1687 frag_tag = my_tag++;
1694 SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE,
1695 ((SICSLOWPAN_DISPATCH_FRAG1 << 8) |
uip_len));
1696 SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG, frag_tag);
1703 LOG_INFO(
"output: fragment %d/%d (tag %d, payload %d)\n",
1704 curr_frag + 1, fragment_count,
1714 SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE,
1715 ((SICSLOWPAN_DISPATCH_FRAGN << 8) |
uip_len));
1721 while(processed_ip_out_len <
uip_len) {
1724 PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET] = processed_ip_out_len >> 3;
1727 if(
uip_len - processed_ip_out_len > last_fragn_max_payload) {
1729 packetbuf_payload_len = fragn_max_payload;
1732 packetbuf_payload_len =
uip_len - processed_ip_out_len;
1737 LOG_INFO(
"output: fragment %d/%d (tag %d, payload %d, offset %d)\n",
1738 curr_frag + 1, fragment_count,
1739 frag_tag, packetbuf_payload_len, processed_ip_out_len);
1740 if(fragment_copy_payload_and_send(processed_ip_out_len, &dest) == 0) {
1747 LOG_ERR(
"output: Packet too large to be sent without fragmentation support; dropping packet\n");
1780 uint16_t frag_size = 0;
1782 uint8_t frag_offset = 0;
1785 #if SICSLOWPAN_CONF_FRAG 1786 uint8_t is_fragment = 0;
1787 int8_t frag_context = 0;
1790 uint16_t frag_tag = 0;
1791 uint8_t first_fragment = 0, last_fragment = 0;
1795 link_stats_input_callback(packetbuf_addr(PACKETBUF_ADDR_SENDER));
1805 LOG_WARN(
"input: empty packet\n");
1814 last_rssi = (
signed short)packetbuf_attr(PACKETBUF_ATTR_RSSI);
1816 #if SICSLOWPAN_CONF_FRAG 1822 switch((GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) >> 8) & SICSLOWPAN_DISPATCH_FRAG_MASK) {
1823 case SICSLOWPAN_DISPATCH_FRAG1:
1825 frag_size = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) & 0x07ff;
1826 frag_tag = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG);
1831 LOG_INFO(
"input: received first element of a fragmented packet (tag %d, len %d)\n",
1832 frag_tag, frag_size);
1835 frag_context = add_fragment(frag_tag, frag_size, frag_offset);
1837 if(frag_context == -1) {
1838 LOG_ERR(
"input: failed to allocate new reassembly context\n");
1842 buffer = frag_info[frag_context].first_frag;
1845 case SICSLOWPAN_DISPATCH_FRAGN:
1850 frag_offset = PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET];
1851 frag_tag = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG);
1852 frag_size = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) & 0x07ff;
1857 frag_context = add_fragment(frag_tag, frag_size, frag_offset);
1859 if(frag_context == -1) {
1860 LOG_ERR(
"input: reassembly context not found (tag %d)\n", frag_tag);
1868 if(frag_info[frag_context].reassembled_len >= frag_size) {
1877 if(is_fragment && !first_fragment) {
1887 LOG_INFO(
"input: page 1, 6LoRH\n");
1890 LOG_ERR(
"input: page %u not supported\n",
curr_page);
1895 if((PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & SICSLOWPAN_DISPATCH_IPHC_MASK) == SICSLOWPAN_DISPATCH_IPHC) {
1896 LOG_DBG(
"uncompression: IPHC dispatch\n");
1898 }
else if(PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] == SICSLOWPAN_DISPATCH_IPV6) {
1899 LOG_DBG(
"uncompression: IPV6 dispatch\n");
1909 LOG_ERR(
"uncompression: unknown dispatch: 0x%02x\n",
1910 PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & SICSLOWPAN_DISPATCH_IPHC_MASK);
1914 #if SICSLOWPAN_CONF_FRAG 1925 LOG_ERR(
"input: packet dropped due to header > total packet\n");
1930 #if SICSLOWPAN_CONF_FRAG 1932 LOG_INFO(
"input: fragment (tag %d, payload %d, offset %d) -- %u %u\n",
1941 if(req_size >
sizeof(
uip_buf)) {
1943 "input: packet dropped, minimum required IP_BUF size: %d+%d+%d+%d=%d (current size: %u)\n",
1945 packetbuf_payload_len, req_size, (
unsigned)
sizeof(
uip_buf));
1952 if(buffer != NULL) {
1958 #if SICSLOWPAN_CONF_FRAG 1961 if(first_fragment != 0) {
1967 if(last_fragment != 0) {
1968 frag_info[frag_context].reassembled_len = frag_size;
1970 copy_frags2uip(frag_context);
1978 if(!is_fragment || last_fragment) {
1980 if(is_fragment != 0 && last_fragment != 0) {
1988 LOG_INFO(
"input: received IPv6 packet with len %d\n",
1991 if(LOG_DBG_ENABLED) {
1993 LOG_DBG(
"uncompression: after (%u):",
UIP_IP_BUF->len[1]);
1994 for (ndx = 0; ndx <
UIP_IP_BUF->len[1] + 40; ndx++) {
1995 uint8_t data = ((uint8_t *) (
UIP_IP_BUF))[ndx];
1996 LOG_DBG_(
"%02x", data);
2004 callback->input_callback();
2008 #if SICSLOWPAN_CONF_FRAG 2018 sicslowpan_init(
void)
2021 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPHC 2027 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 2028 addr_contexts[0].used = 1;
2029 addr_contexts[0].number = 0;
2030 #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_0 2031 SICSLOWPAN_CONF_ADDR_CONTEXT_0;
2033 addr_contexts[0].prefix[0] = UIP_DS6_DEFAULT_PREFIX_0;
2034 addr_contexts[0].prefix[1] = UIP_DS6_DEFAULT_PREFIX_1;
2038 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 1 2042 #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_1 2044 addr_contexts[1].used = 1;
2045 addr_contexts[1].number = 1;
2046 SICSLOWPAN_CONF_ADDR_CONTEXT_1;
2047 #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_2 2049 addr_contexts[2].used = 1;
2050 addr_contexts[2].number = 2;
2051 SICSLOWPAN_CONF_ADDR_CONTEXT_2;
2054 addr_contexts[i].used = 0;
2057 addr_contexts[i].used = 0;
2066 #if SICSLOWPAN_CONF_FRAG 2072 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
Pointer to IP 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
Pointer to ICMP header.
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_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.
#define UIP_LLH_LEN
The link level header length.
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
#define MAC_MAX_PAYLOAD
Maximum available size for frame headers, link layer security-related overhead, as well as 6LoWPAN pa...
Include file for the Contiki low-layer network stack (NETSTACK)
void watchdog_periodic(void)
Writes the WDT clear sequence.
#define MAC_MAX_HEADER
Maximum size of a frame header.
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.