49 #include "contiki-lib.h"
50 #include "contiki-net.h"
53 #include "dev/watchdog.h"
56 #define DEBUG DEBUG_NONE
59 #define TRICKLE_VERBOSE 0
61 #if DEBUG && TRICKLE_VERBOSE
62 #define VERBOSE_PRINTF(...) PRINTF(__VA_ARGS__)
63 #define VERBOSE_PRINT_SEED(s) PRINT_SEED(s)
65 #define VERBOSE_PRINTF(...)
66 #define VERBOSE_PRINT_SEED(...)
73 #if ROLL_TM_SHORT_SEEDS
74 typedef union seed_id_u {
79 #define seed_is_null(s) ((s)->id == 0)
80 #define PRINT_SEED(s) PRINTF("0x%02x%02x", (s)->u8[0], (s)->u8[1])
82 typedef uip_ip6addr_t seed_id_t;
84 #define seed_is_null(s) uip_is_addr_unspecified(s)
85 #define PRINT_SEED(s) PRINT6ADDR(s)
87 #define seed_id_cmp(a, b) (memcmp((a), (b), sizeof(seed_id_t)) == 0)
88 #define seed_id_cpy(a, b) (memcpy((a), (b), sizeof(seed_id_t)))
91 struct trickle_param {
96 clock_time_t t_last_trigger;
104 uint8_t inconsistency;
112 #define TRICKLE_TIME(m, d) ((clock_time_t)((m) << (d)))
117 #define TRICKLE_IMAX(t) ((uint32_t)((t)->i_min << (t)->i_max))
124 #define TRICKLE_ACTIVE(t) ((uint32_t)(TRICKLE_IMAX(t) * t->t_active))
131 #define TRICKLE_DWELL(t) ((uint32_t)(TRICKLE_IMAX(t) * t->t_dwell))
137 #define SUPPRESSION_ENABLED(t) ((t)->k != ROLL_TM_INFINITE_REDUNDANCY)
143 #define SUPPRESSION_DISABLED(t) ((t)->k == ROLL_TM_INFINITE_REDUNDANCY)
148 #define TIMER_CONFIGURE(m) do { \
149 t[m].i_min = ROLL_TM_IMIN_##m; \
150 t[m].i_max = ROLL_TM_IMAX_##m; \
151 t[m].k = ROLL_TM_K_##m; \
152 t[m].t_active = ROLL_TM_T_ACTIVE_##m; \
153 t[m].t_dwell = ROLL_TM_T_DWELL_##m; \
154 t[m].t_last_trigger = clock_time(); \
174 #define SEQ_VAL_IS_EQ(i1, i2) ((i1) == (i2))
179 #define SEQ_VAL_IS_LT(i1, i2) \
182 ((((i1) < (i2)) && ((int16_t)((i2) - (i1)) < 0x4000)) || \
183 (((i1) > (i2)) && ((int16_t)((i1) - (i2)) > 0x4000))) \
189 #define SEQ_VAL_IS_GT(i1, i2) \
192 ((((i1) < (i2)) && ((int16_t)((i2) - (i1)) > 0x4000)) || \
193 (((i1) > (i2)) && ((int16_t)((i1) - (i2)) < 0x4000))) \
199 #define SEQ_VAL_ADD(s, n) (((s) + (n)) % 0x8000)
202 struct sliding_window {
211 #define SLIDING_WINDOW_U_BIT 0x80
212 #define SLIDING_WINDOW_M_BIT 0x40
213 #define SLIDING_WINDOW_L_BIT 0x20
214 #define SLIDING_WINDOW_B_BIT 0x10
220 #define SLIDING_WINDOW_IS_USED(w) ((w)->flags & SLIDING_WINDOW_U_BIT)
226 #define SLIDING_WINDOW_IS_USED_SET(w) ((w)->flags |= SLIDING_WINDOW_U_BIT)
232 #define SLIDING_WINDOW_IS_USED_CLR(w) ((w)->flags &= ~SLIDING_WINDOW_U_BIT)
233 #define window_free(w) SLIDING_WINDOW_IS_USED_CLR(w)
239 #define SLIDING_WINDOW_LISTED_SET(w) ((w)->flags |= SLIDING_WINDOW_L_BIT)
245 #define SLIDING_WINDOW_LISTED_CLR(w) ((w)->flags &= ~SLIDING_WINDOW_L_BIT)
251 #define SLIDING_WINDOW_IS_LISTED(w) ((w)->flags & SLIDING_WINDOW_L_BIT)
257 #define SLIDING_WINDOW_M_SET(w) ((w)->flags |= SLIDING_WINDOW_M_BIT)
263 #define SLIDING_WINDOW_M_CLR(w) ((w)->flags &= ~SLIDING_WINDOW_M_BIT)
269 #define SLIDING_WINDOW_GET_M(w) \
270 ((uint8_t)(((w)->flags & SLIDING_WINDOW_M_BIT) == SLIDING_WINDOW_M_BIT))
273 struct mcast_packet {
274 #if ROLL_TM_SHORT_SEEDS
282 struct sliding_window *sw;
288 #define MCAST_PACKET_U_BIT 0x80
289 #define MCAST_PACKET_S_BIT 0x20
290 #define MCAST_PACKET_L_BIT 0x10
293 #if ROLL_TM_SHORT_SEEDS
294 #define MCAST_PACKET_GET_SEED(p) ((seed_id_t *)&((p)->seed_id))
296 #define MCAST_PACKET_GET_SEED(p) \
297 ((seed_id_t *)&((struct uip_ip_hdr *)&(p)->buff[UIP_LLH_LEN])->srcipaddr)
304 #define MCAST_PACKET_TTL(p) \
305 (((struct uip_ip_hdr *)(p)->buff)->ttl)
311 #define MCAST_PACKET_USED_SET(p) ((p)->flags |= MCAST_PACKET_U_BIT)
317 #define MCAST_PACKET_USED_CLR(p) ((p)->flags &= ~MCAST_PACKET_U_BIT)
322 #define MCAST_PACKET_IS_USED(p) ((p)->flags & MCAST_PACKET_U_BIT)
327 #define MCAST_PACKET_MUST_SEND(p) ((p)->flags & MCAST_PACKET_S_BIT)
333 #define MCAST_PACKET_SEND_SET(p) ((p)->flags |= MCAST_PACKET_S_BIT)
339 #define MCAST_PACKET_SEND_CLR(p) ((p)->flags &= ~MCAST_PACKET_S_BIT)
345 #define MCAST_PACKET_IS_LISTED(p) ((p)->flags & MCAST_PACKET_L_BIT)
351 #define MCAST_PACKET_LISTED_SET(p) ((p)->flags |= MCAST_PACKET_L_BIT)
357 #define MCAST_PACKET_LISTED_CLR(p) ((p)->flags &= ~MCAST_PACKET_L_BIT)
363 #define MCAST_PACKET_FREE(p) ((p)->flags = 0)
366 struct sequence_list_header {
372 #define SEQUENCE_LIST_S_BIT 0x80
373 #define SEQUENCE_LIST_M_BIT 0x40
374 #define SEQUENCE_LIST_RES 0x3F
380 #define SEQUENCE_LIST_GET_M(l) \
381 ((uint8_t)(((l)->flags & SEQUENCE_LIST_M_BIT) == SEQUENCE_LIST_M_BIT))
387 #define SEQUENCE_LIST_GET_S(l) \
388 ((uint8_t)(((l)->flags & SEQUENCE_LIST_S_BIT) == SEQUENCE_LIST_S_BIT))
394 #if ROLL_TM_SHORT_SEEDS
399 #if !ROLL_TM_SHORT_SEEDS
406 #define HBHO_OPT_TYPE_TRICKLE 0x0C
407 #define HBHO_LEN_LONG_SEED 2
408 #define HBHO_LEN_SHORT_SEED 4
409 #define HBHO_TOTAL_LEN 8
414 #define HBH_GET_M(h) (((h)->flags & 0x80) == 0x80)
420 #define HBH_SET_M(h) ((h)->flags |= 0x80)
426 #define HBH_GET_SV_MSB(h) ((h)->flags & 0x7F)
429 #if ROLL_TM_CONF_DEST_ALL_NODES
430 #define roll_tm_create_dest(a) uip_create_linklocal_allnodes_mcast(a)
432 #define roll_tm_create_dest(a) uip_create_linklocal_allrouters_mcast(a)
437 static struct roll_tm_stats stats;
439 #define ROLL_TM_STATS_ADD(x) stats.x++
440 #define ROLL_TM_STATS_INIT() do { memset(&stats, 0, sizeof(stats)); } while(0)
442 #define ROLL_TM_STATS_ADD(x)
443 #define ROLL_TM_STATS_INIT()
448 static struct trickle_param t[2];
449 static struct sliding_window windows[ROLL_TM_WINS];
450 static struct mcast_packet buffered_msgs[ROLL_TM_BUFF_NUM];
454 static struct trickle_param *loctpptr;
455 static struct sequence_list_header *locslhptr;
456 static struct sliding_window *locswptr;
457 static struct sliding_window *iterswptr;
458 static struct mcast_packet *locmpptr;
459 static struct hbho_mcast *lochbhmptr;
460 static uint16_t last_seq;
464 #define UIP_DATA_BUF ((uint8_t *)&uip_buf[uip_l2_l3_hdr_len + UIP_UDPH_LEN])
465 #define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
466 #define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN])
467 #define UIP_EXT_BUF_NEXT ((uint8_t *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN + HBHO_TOTAL_LEN])
468 #define UIP_EXT_OPT_FIRST ((struct hbho_mcast *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN + 2])
469 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
470 #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
471 #define UIP_ICMP_PAYLOAD ((unsigned char *)&uip_buf[uip_l2_l3_icmp_hdr_len])
472 extern uint16_t uip_slen;
476 static void icmp_output();
477 static void window_update_bounds();
478 static void reset_trickle_timer(uint8_t);
479 static void handle_timer(
void *);
484 random_interval(clock_time_t i_min, uint8_t d)
488 VERBOSE_PRINTF(
"ROLL TM: Random [%lu, %lu)\n", (
unsigned long)min,
496 double_interval(
void *ptr)
498 struct trickle_param *param = (
struct trickle_param *)ptr;
506 offset = (int16_t)(
clock_time() - param->t_end);
509 if(param->i_current < param->i_max) {
513 param->t_start = param->t_end;
514 param->t_end = param->t_start + (param->i_min << param->i_current);
516 next = random_interval(param->i_min, param->i_current);
522 param->t_next = next;
523 ctimer_set(¶m->ct, param->t_next, handle_timer, (
void *)param);
525 VERBOSE_PRINTF(
"ROLL TM: Doubling at %lu (offset %d), Start %lu, End %lu,"
527 (
unsigned long)param->t_start,
528 (
unsigned long)param->t_end, (
unsigned long)param->t_next);
536 handle_timer(
void *ptr)
538 struct trickle_param *param;
539 clock_time_t diff_last;
540 clock_time_t diff_start;
543 param = (
struct trickle_param *)ptr;
546 }
else if(param == &t[1]) {
554 if(uip_ds6_get_link_local(ADDR_PREFERRED) ==
NULL) {
556 (
"ROLL TM: Suppressing timer processing. Stack not ready\n");
557 reset_trickle_timer(m);
561 VERBOSE_PRINTF(
"ROLL TM: M=%u Periodic at %lu, last=%lu\n",
563 (
unsigned long)param->t_last_trigger);
567 diff_last = param->t_next - param->t_last_trigger;
568 diff_start = param->t_next - param->t_start;
569 param->t_last_trigger = param->t_next;
572 (
"ROLL TM: M=%u Periodic diff from last %lu, from start %lu\n", m,
573 (
unsigned long)diff_last, (
unsigned long)diff_start);
576 for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1];
577 locmpptr >= buffered_msgs; locmpptr--) {
594 if(locmpptr->active == 0) {
595 locmpptr->active += diff_start;
596 locmpptr->dwell += diff_start;
598 locmpptr->active += diff_last;
599 locmpptr->dwell += diff_last;
602 VERBOSE_PRINTF(
"ROLL TM: M=%u Packet %u active %lu of %lu\n",
603 m, locmpptr->seq_val, locmpptr->active,
607 locmpptr->sw->count--;
608 PRINTF(
"ROLL TM: M=%u Free Packet %u (%lu > %lu), Window now at %u\n",
609 m, locmpptr->seq_val, locmpptr->dwell,
611 if(locmpptr->sw->count == 0) {
612 PRINTF(
"ROLL TM: M=%u Free Window ", m);
613 PRINT_SEED(&locmpptr->sw->seed_id);
615 window_free(locmpptr->sw);
623 PRINTF(
"ROLL TM: M=%u Periodic - Sending packet from Seed ", m);
624 PRINT_SEED(&locmpptr->sw->seed_id);
625 PRINTF(
" seq %u\n", locmpptr->seq_val);
629 UIP_MCAST6_STATS_ADD(mcast_fwd);
640 if(param->c < param->k) {
646 param->inconsistency = 0;
649 window_update_bounds();
653 if(param->t_next >= param->t_end) {
657 param->t_next = param->t_end - param->t_next;
660 (
"ROLL TM: M=%u Periodic at %lu, Interval End at %lu in %lu\n", m,
661 (
unsigned long)
clock_time(), (
unsigned long)param->t_end,
662 (
unsigned long)param->t_next);
663 ctimer_set(¶m->ct, param->t_next, double_interval, (
void *)param);
669 reset_trickle_timer(uint8_t index)
672 t[index].t_end = t[index].t_start + (t[index].i_min);
673 t[index].i_current = 0;
675 t[index].t_next = random_interval(t[index].i_min, t[index].i_current);
678 (
"ROLL TM: M=%u Reset at %lu, Start %lu, End %lu, New Interval %lu\n",
679 index, (
unsigned long)t[index].t_start, (
unsigned long)t[index].t_start,
680 (
unsigned long)t[index].t_end, (
unsigned long)t[index].t_next);
682 ctimer_set(&t[index].ct, t[index].t_next, handle_timer, (
void *)&t[index]);
685 static struct sliding_window *
688 for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows;
691 iterswptr->count = 0;
692 iterswptr->lower_bound = -1;
693 iterswptr->upper_bound = -1;
694 iterswptr->min_listed = -1;
701 static struct sliding_window *
702 window_lookup(seed_id_t *s, uint8_t m)
704 for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows;
707 VERBOSE_PRINT_SEED(&iterswptr->seed_id);
708 VERBOSE_PRINTF(
"\n");
709 if(seed_id_cmp(s, &iterswptr->seed_id) &&
718 window_update_bounds()
720 for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows;
722 iterswptr->lower_bound = -1;
725 for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1];
726 locmpptr >= buffered_msgs; locmpptr--) {
728 iterswptr = locmpptr->sw;
729 VERBOSE_PRINTF(
"ROLL TM: Update Bounds: [%d - %d] vs %u\n",
730 iterswptr->lower_bound, iterswptr->upper_bound,
732 if(iterswptr->lower_bound < 0
733 ||
SEQ_VAL_IS_LT(locmpptr->seq_val, iterswptr->lower_bound)) {
734 iterswptr->lower_bound = locmpptr->seq_val;
736 if(iterswptr->upper_bound < 0 ||
738 iterswptr->upper_bound = locmpptr->seq_val;
744 static struct mcast_packet *
747 struct sliding_window *largest = windows;
748 struct mcast_packet *rv;
750 for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows;
752 if(iterswptr->count > largest->count) {
757 if(largest->count == 1) {
762 PRINTF(
"ROLL TM: Reclaim from Seed ");
763 PRINT_SEED(&largest->seed_id);
764 PRINTF(
" M=%u, count was %u\n",
767 for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1];
768 locmpptr >= buffered_msgs; locmpptr--) {
772 PRINTF(
"ROLL TM: Reclaim seq. val %u\n", locmpptr->seq_val);
775 window_update_bounds();
776 VERBOSE_PRINTF(
"ROLL TM: Reclaim - new bounds [%u , %u]\n",
777 largest->lower_bound, largest->upper_bound);
786 static struct mcast_packet *
789 for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1];
790 locmpptr >= buffered_msgs; locmpptr--) {
801 struct sequence_list_header *sl;
803 uint16_t payload_len;
805 PRINTF(
"ROLL TM: ICMPv6 Out\n");
813 sl = (
struct sequence_list_header *)UIP_ICMP_PAYLOAD;
816 VERBOSE_PRINTF(
"ROLL TM: ICMPv6 Out - Hdr @ %p, payload @ %p\n",
UIP_ICMP_BUF, sl);
818 for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows;
821 memset(sl, 0,
sizeof(
struct sequence_list_header));
822 #if ROLL_TM_SHORT_SEEDS
823 sl->flags = SEQUENCE_LIST_S_BIT;
826 sl->flags |= SEQUENCE_LIST_M_BIT;
828 seed_id_cpy(&sl->seed_id, &iterswptr->seed_id);
830 PRINTF(
"ROLL TM: ICMPv6 Out - Seq. F=0x%02x, Seed ID=", sl->flags);
831 PRINT_SEED(&sl->seed_id);
833 buffer = (uint8_t *)sl +
sizeof(
struct sequence_list_header);
835 for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1];
836 locmpptr >= buffered_msgs; locmpptr--) {
839 if(locmpptr->sw == iterswptr) {
841 PRINTF(
", %u", locmpptr->seq_val);
842 *buffer = (uint8_t)(locmpptr->seq_val >> 8);
844 *buffer = (uint8_t)(locmpptr->seq_val & 0xFF);
849 PRINTF(
", Len=%u\n", sl->seq_len);
852 if(sl->seq_len > 0) {
853 payload_len +=
sizeof(
struct sequence_list_header) + sl->seq_len * 2;
854 sl = (
struct sequence_list_header *)buffer;
859 if(payload_len == 0) {
860 VERBOSE_PRINTF(
"ROLL TM: ICMPv6 Out - nothing to send\n");
867 UIP_IP_BUF->len[0] = (UIP_ICMPH_LEN + payload_len) >> 8;
868 UIP_IP_BUF->len[1] = (UIP_ICMPH_LEN + payload_len) & 0xff;
876 uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + payload_len;
878 VERBOSE_PRINTF(
"ROLL TM: ICMPv6 Out - %u bytes\n", payload_len);
881 ROLL_TM_STATS_ADD(icmp_out);
900 PRINTF(
"ROLL TM: Multicast I/O\n");
902 #if UIP_CONF_IPV6_CHECKS
904 PRINTF(
"ROLL TM: Mcast I/O, bad destination\n");
905 UIP_MCAST6_STATS_ADD(mcast_bad);
906 return UIP_MCAST6_DROP;
913 PRINTF(
"ROLL TM: Mcast I/O, bad source\n");
914 UIP_MCAST6_STATS_ADD(mcast_bad);
915 return UIP_MCAST6_DROP;
921 PRINTF(
"ROLL TM: Mcast I/O, bad proto\n");
922 UIP_MCAST6_STATS_ADD(mcast_bad);
923 return UIP_MCAST6_DROP;
926 if(UIP_EXT_OPT_FIRST->type != HBHO_OPT_TYPE_TRICKLE) {
927 PRINTF(
"ROLL TM: Mcast I/O, bad HBHO type\n");
928 UIP_MCAST6_STATS_ADD(mcast_bad);
929 return UIP_MCAST6_DROP;
932 lochbhmptr = UIP_EXT_OPT_FIRST;
934 PRINTF(
"ROLL TM: HBHO T=%u, L=%u, M=%u, S=0x%02x%02x\n",
935 lochbhmptr->type, lochbhmptr->len,
HBH_GET_M(lochbhmptr),
939 #if ROLL_TM_SHORT_SEEDS
941 if(lochbhmptr->len != HBHO_LEN_SHORT_SEED) {
942 PRINTF(
"ROLL TM: Mcast I/O, bad length\n");
943 UIP_MCAST6_STATS_ADD(mcast_bad);
944 return UIP_MCAST6_DROP;
948 if(lochbhmptr->len != HBHO_LEN_LONG_SEED) {
949 PRINTF(
"ROLL TM: Mcast I/O, bad length\n");
950 UIP_MCAST6_STATS_ADD(mcast_bad);
951 return UIP_MCAST6_DROP;
956 if(in == ROLL_TM_DGRAM_IN) {
957 UIP_MCAST6_STATS_ADD(mcast_in_all);
962 #if ROLL_TM_SHORT_SEEDS
963 seed_ptr = &lochbhmptr->seed_id;
969 locswptr = window_lookup(seed_ptr, m);
971 seq_val = lochbhmptr->seq_id_lsb;
977 PRINTF(
"ROLL TM: Too old\n");
978 UIP_MCAST6_STATS_ADD(mcast_dropped);
979 return UIP_MCAST6_DROP;
981 for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1];
982 locmpptr >= buffered_msgs; locmpptr--) {
984 locmpptr->sw == locswptr &&
988 PRINTF(
"ROLL TM: Seen before\n");
989 UIP_MCAST6_STATS_ADD(mcast_dropped);
990 return UIP_MCAST6_DROP;
995 PRINTF(
"ROLL TM: New message\n");
1000 locswptr = window_allocate();
1001 PRINTF(
"ROLL TM: New seed\n");
1005 PRINTF(
"ROLL TM: Failed to allocate window\n");
1006 UIP_MCAST6_STATS_ADD(mcast_dropped);
1007 return UIP_MCAST6_DROP;
1011 locmpptr = buffer_allocate();
1013 PRINTF(
"ROLL TM: Buffer allocation failed, reclaiming\n");
1014 locmpptr = buffer_reclaim();
1020 PRINTF(
"ROLL TM: Buffer reclaim failed\n");
1021 if(locswptr->count == 0) {
1022 window_free(locswptr);
1023 UIP_MCAST6_STATS_ADD(mcast_dropped);
1024 return UIP_MCAST6_DROP;
1027 #if UIP_MCAST6_STATS
1028 if(in == ROLL_TM_DGRAM_IN) {
1029 UIP_MCAST6_STATS_ADD(mcast_in_unique);
1040 seed_id_cpy(&locswptr->seed_id, seed_ptr);
1041 PRINTF(
"ROLL TM: Window for seed ");
1042 PRINT_SEED(&locswptr->seed_id);
1043 PRINTF(
" M=%u, count=%u\n",
1047 if(locswptr->count == 0) {
1048 locswptr->lower_bound = seq_val;
1049 VERBOSE_PRINTF(
"ROLL TM: New Lower Bound %u\n", locswptr->lower_bound);
1053 if(locswptr->count == 0 ||
SEQ_VAL_IS_GT(seq_val, locswptr->upper_bound)) {
1054 locswptr->upper_bound = seq_val;
1055 VERBOSE_PRINTF(
"ROLL TM: New Upper Bound %u\n", locswptr->upper_bound);
1060 memset(locmpptr, 0,
sizeof(
struct mcast_packet));
1062 locmpptr->sw = locswptr;
1064 locmpptr->seq_val = seq_val;
1067 PRINTF(
"ROLL TM: Window for seed ");
1068 PRINT_SEED(&locswptr->seed_id);
1069 PRINTF(
" M=%u, %u values within [%u , %u]\n",
1071 locswptr->lower_bound, locswptr->upper_bound);
1079 if(in == ROLL_TM_DGRAM_IN) {
1083 t[m].inconsistency = 1;
1085 PRINTF(
"ROLL TM: Inconsistency. Reset T%u\n", m);
1086 reset_trickle_timer(m);
1090 return UIP_MCAST6_ACCEPT;
1096 uint8_t inconsistency;
1101 #if UIP_CONF_IPV6_CHECKS
1103 PRINTF(
"ROLL TM: ICMPv6 In, bad source ");
1108 ROLL_TM_STATS_ADD(icmp_bad);
1114 PRINTF(
"ROLL TM: ICMPv6 In, bad destination\n");
1115 ROLL_TM_STATS_ADD(icmp_bad);
1120 PRINTF(
"ROLL TM: ICMPv6 In, bad ICMP code\n");
1121 ROLL_TM_STATS_ADD(icmp_bad);
1125 if(
UIP_IP_BUF->ttl != ROLL_TM_IP_HOP_LIMIT) {
1126 PRINTF(
"ROLL TM: ICMPv6 In, bad TTL\n");
1127 ROLL_TM_STATS_ADD(icmp_bad);
1132 PRINTF(
"ROLL TM: ICMPv6 In from ");
1136 ROLL_TM_STATS_ADD(icmp_in);
1139 for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows;
1145 for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1];
1146 locmpptr >= buffered_msgs; locmpptr--) {
1150 locslhptr = (
struct sequence_list_header *)UIP_ICMP_PAYLOAD;
1152 VERBOSE_PRINTF(
"ROLL TM: ICMPv6 In, parse from %p to %p\n",
1154 (uint8_t *)UIP_ICMP_PAYLOAD +
uip_len -
1155 uip_l2_l3_icmp_hdr_len);
1157 (
struct sequence_list_header *)((uint8_t *)UIP_ICMP_PAYLOAD +
1158 uip_len - uip_l2_l3_icmp_hdr_len)) {
1159 VERBOSE_PRINTF(
"ROLL TM: ICMPv6 In, seq hdr @ %p\n", locslhptr);
1161 if((locslhptr->flags & SEQUENCE_LIST_RES) != 0) {
1162 PRINTF(
"ROLL TM: ICMPv6 In, non-zero reserved bits\n");
1167 #if ROLL_TM_SHORT_SEEDS
1169 ROLL_TM_STATS_ADD(icmp_bad);
1174 ROLL_TM_STATS_ADD(icmp_bad);
1179 PRINTF(
"ROLL TM: ICMPv6 In, Sequence List for Seed ID ");
1180 PRINT_SEED(&locslhptr->seed_id);
1184 seq_ptr = (uint16_t *)((uint8_t *)locslhptr
1185 +
sizeof(
struct sequence_list_header));
1186 end_ptr = (uint16_t *)((uint8_t *)locslhptr
1187 +
sizeof(
struct sequence_list_header) +
1188 locslhptr->seq_len * 2);
1196 locswptr = window_lookup(&locslhptr->seed_id,
1202 locswptr->min_listed = -1;
1203 PRINTF(
"ROLL TM: ICMPv6 In, Window bounds [%u , %u]\n",
1204 locswptr->lower_bound, locswptr->upper_bound);
1205 for(; seq_ptr < end_ptr; seq_ptr++) {
1209 PRINTF(
"ROLL TM: ICMPv6 In, Check seq %u @ %p\n", val, seq_ptr);
1211 PRINTF(
"ROLL TM: Inconsistency - Advertised Seq. ID %u GT upper"
1212 " bound %u\n", val, locswptr->upper_bound);
1213 loctpptr->inconsistency = 1;
1224 for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1];
1225 locmpptr >= buffered_msgs; locmpptr--) {
1231 PRINTF(
"ROLL TM: ICMPv6 In, %u listed\n", locmpptr->seq_val);
1235 if(locswptr->min_listed == -1 ||
1237 locswptr->min_listed = val;
1244 PRINTF(
"ROLL TM: Inconsistency - ");
1245 PRINTF(
"Advertised Seq. ID %u within bounds", val);
1246 PRINTF(
" [%u, %u] but no matching entry\n",
1247 locswptr->lower_bound, locswptr->upper_bound);
1248 loctpptr->inconsistency = 1;
1257 PRINTF(
"ROLL TM: Inconsistency - Advertised window unknown to us\n");
1258 loctpptr->inconsistency = 1;
1260 locslhptr = (
struct sequence_list_header *)(((uint8_t *)locslhptr) +
1261 sizeof(
struct sequence_list_header) + (2 * locslhptr->seq_len));
1266 PRINTF(
"ROLL TM: ICMPv6 In, Check our buffer\n");
1267 for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1];
1268 locmpptr >= buffered_msgs; locmpptr--) {
1270 locswptr = locmpptr->sw;
1271 PRINTF(
"ROLL TM: ICMPv6 In, ");
1272 PRINTF(
"Check %u, Seed L: %u, This L: %u Min L: %d\n",
1280 PRINTF(
"ROLL TM: Inconsistency - Seed ID ");
1281 PRINT_SEED(&locswptr->seed_id);
1282 PRINTF(
" was not listed\n");
1283 loctpptr->inconsistency = 1;
1288 (locswptr->min_listed >= 0) &&
1290 PRINTF(
"ROLL TM: Inconsistency - ");
1291 PRINTF(
"Seq. %u was not listed but %u was\n",
1292 locmpptr->seq_val, locswptr->min_listed);
1293 loctpptr->inconsistency = 1;
1302 if(t[0].inconsistency) {
1303 reset_trickle_timer(0);
1307 if(t[1].inconsistency) {
1308 reset_trickle_timer(1);
1321 PRINTF(
"ROLL TM: Multicast Out can not add HBHO. Packet too long\n");
1326 memmove(UIP_EXT_BUF_NEXT, UIP_EXT_BUF,
uip_len - UIP_IPH_LEN);
1327 memset(UIP_EXT_BUF, 0, HBHO_TOTAL_LEN);
1330 UIP_EXT_BUF->len = 0;
1332 lochbhmptr = UIP_EXT_OPT_FIRST;
1333 lochbhmptr->type = HBHO_OPT_TYPE_TRICKLE;
1337 lochbhmptr->flags = last_seq >> 8;
1338 lochbhmptr->seq_id_lsb = last_seq & 0xFF;
1339 #if ROLL_TM_SHORT_SEEDS
1340 seed_id_cpy(&lochbhmptr->seed_id, &
uip_lladdr.addr[UIP_LLADDR_LEN - 2]);
1341 lochbhmptr->len = HBHO_LEN_SHORT_SEED;
1343 lochbhmptr->len = HBHO_LEN_LONG_SEED;
1345 lochbhmptr->padn_type = UIP_EXT_HDR_OPT_PADN;
1346 lochbhmptr->padn_len = 0;
1350 #if ROLL_TM_SET_M_BIT
1362 PRINTF(
"ROLL TM: Multicast Out, HBHO: T=%u, L=%u, M=%u, S=0x%02x%02x\n",
1363 lochbhmptr->type, lochbhmptr->len,
HBH_GET_M(lochbhmptr),
1375 if(accept(ROLL_TM_DGRAM_OUT)) {
1377 UIP_MCAST6_STATS_ADD(mcast_out);
1394 if(accept(ROLL_TM_DGRAM_IN) == UIP_MCAST6_DROP) {
1395 return UIP_MCAST6_DROP;
1399 PRINTF(
"ROLL TM: Not a group member. No further processing\n");
1400 return UIP_MCAST6_DROP;
1402 PRINTF(
"ROLL TM: Ours. Deliver to upper layers\n");
1403 UIP_MCAST6_STATS_ADD(mcast_in_ours);
1404 return UIP_MCAST6_ACCEPT;
1411 PRINTF(
"ROLL TM: ROLL Multicast - Draft #%u\n", ROLL_TM_VER);
1413 memset(windows, 0,
sizeof(windows));
1414 memset(buffered_msgs, 0,
sizeof(buffered_msgs));
1415 memset(t, 0,
sizeof(t));
1417 ROLL_TM_STATS_INIT();
1418 UIP_MCAST6_STATS_INIT(&stats);
1420 for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows;
1422 iterswptr->lower_bound = -1;
1423 iterswptr->upper_bound = -1;
1424 iterswptr->min_listed = -1;
1428 reset_trickle_timer(0);
1430 reset_trickle_timer(1);
1434 const struct uip_mcast6_driver roll_tm_driver = {