49 #include "contiki-lib.h"
50 #include "contiki-net.h"
54 #include "dev/watchdog.h"
57 #define DEBUG DEBUG_NONE
60 #define TRICKLE_VERBOSE 0
62 #if DEBUG && TRICKLE_VERBOSE
63 #define VERBOSE_PRINTF(...) PRINTF(__VA_ARGS__)
64 #define VERBOSE_PRINT_SEED(s) PRINT_SEED(s)
66 #define VERBOSE_PRINTF(...)
67 #define VERBOSE_PRINT_SEED(...)
74 #if ROLL_TM_SHORT_SEEDS
75 typedef union seed_id_u {
80 #define seed_is_null(s) ((s)->id == 0)
81 #define PRINT_SEED(s) PRINTF("0x%02x%02x", (s)->u8[0], (s)->u8[1])
83 typedef uip_ip6addr_t seed_id_t;
85 #define seed_is_null(s) uip_is_addr_unspecified(s)
86 #define PRINT_SEED(s) PRINT6ADDR(s)
88 #define seed_id_cmp(a, b) (memcmp((a), (b), sizeof(seed_id_t)) == 0)
89 #define seed_id_cpy(a, b) (memcpy((a), (b), sizeof(seed_id_t)))
92 struct trickle_param {
97 clock_time_t t_last_trigger;
105 uint8_t inconsistency;
113 #define TRICKLE_TIME(m, d) ((clock_time_t)((m) << (d)))
118 #define TRICKLE_IMAX(t) ((uint32_t)((t)->i_min << (t)->i_max))
125 #define TRICKLE_ACTIVE(t) ((uint32_t)(TRICKLE_IMAX(t) * t->t_active))
132 #define TRICKLE_DWELL(t) ((uint32_t)(TRICKLE_IMAX(t) * t->t_dwell))
138 #define SUPPRESSION_ENABLED(t) ((t)->k != ROLL_TM_INFINITE_REDUNDANCY)
144 #define SUPPRESSION_DISABLED(t) ((t)->k == ROLL_TM_INFINITE_REDUNDANCY)
149 #define TIMER_CONFIGURE(m) do { \
150 t[m].i_min = ROLL_TM_IMIN_##m; \
151 t[m].i_max = ROLL_TM_IMAX_##m; \
152 t[m].k = ROLL_TM_K_##m; \
153 t[m].t_active = ROLL_TM_T_ACTIVE_##m; \
154 t[m].t_dwell = ROLL_TM_T_DWELL_##m; \
155 t[m].t_last_trigger = clock_time(); \
175 #define SEQ_VAL_IS_EQ(i1, i2) ((i1) == (i2))
180 #define SEQ_VAL_IS_LT(i1, i2) \
183 ((((i1) < (i2)) && ((int16_t)((i2) - (i1)) < 0x4000)) || \
184 (((i1) > (i2)) && ((int16_t)((i1) - (i2)) > 0x4000))) \
190 #define SEQ_VAL_IS_GT(i1, i2) \
193 ((((i1) < (i2)) && ((int16_t)((i2) - (i1)) > 0x4000)) || \
194 (((i1) > (i2)) && ((int16_t)((i1) - (i2)) < 0x4000))) \
200 #define SEQ_VAL_ADD(s, n) (((s) + (n)) % 0x8000)
203 struct sliding_window {
212 #define SLIDING_WINDOW_U_BIT 0x80
213 #define SLIDING_WINDOW_M_BIT 0x40
214 #define SLIDING_WINDOW_L_BIT 0x20
215 #define SLIDING_WINDOW_B_BIT 0x10
221 #define SLIDING_WINDOW_IS_USED(w) ((w)->flags & SLIDING_WINDOW_U_BIT)
227 #define SLIDING_WINDOW_IS_USED_SET(w) ((w)->flags |= SLIDING_WINDOW_U_BIT)
233 #define SLIDING_WINDOW_IS_USED_CLR(w) ((w)->flags &= ~SLIDING_WINDOW_U_BIT)
234 #define window_free(w) SLIDING_WINDOW_IS_USED_CLR(w)
240 #define SLIDING_WINDOW_LISTED_SET(w) ((w)->flags |= SLIDING_WINDOW_L_BIT)
246 #define SLIDING_WINDOW_LISTED_CLR(w) ((w)->flags &= ~SLIDING_WINDOW_L_BIT)
252 #define SLIDING_WINDOW_IS_LISTED(w) ((w)->flags & SLIDING_WINDOW_L_BIT)
258 #define SLIDING_WINDOW_M_SET(w) ((w)->flags |= SLIDING_WINDOW_M_BIT)
264 #define SLIDING_WINDOW_M_CLR(w) ((w)->flags &= ~SLIDING_WINDOW_M_BIT)
270 #define SLIDING_WINDOW_GET_M(w) \
271 ((uint8_t)(((w)->flags & SLIDING_WINDOW_M_BIT) == SLIDING_WINDOW_M_BIT))
274 struct mcast_packet {
275 #if ROLL_TM_SHORT_SEEDS
283 struct sliding_window *sw;
289 #define MCAST_PACKET_U_BIT 0x80
290 #define MCAST_PACKET_S_BIT 0x20
291 #define MCAST_PACKET_L_BIT 0x10
294 #if ROLL_TM_SHORT_SEEDS
295 #define MCAST_PACKET_GET_SEED(p) ((seed_id_t *)&((p)->seed_id))
297 #define MCAST_PACKET_GET_SEED(p) \
298 ((seed_id_t *)&((struct uip_ip_hdr *)&(p)->buff[UIP_LLH_LEN])->srcipaddr)
305 #define MCAST_PACKET_TTL(p) \
306 (((struct uip_ip_hdr *)(p)->buff)->ttl)
312 #define MCAST_PACKET_USED_SET(p) ((p)->flags |= MCAST_PACKET_U_BIT)
318 #define MCAST_PACKET_USED_CLR(p) ((p)->flags &= ~MCAST_PACKET_U_BIT)
323 #define MCAST_PACKET_IS_USED(p) ((p)->flags & MCAST_PACKET_U_BIT)
328 #define MCAST_PACKET_MUST_SEND(p) ((p)->flags & MCAST_PACKET_S_BIT)
334 #define MCAST_PACKET_SEND_SET(p) ((p)->flags |= MCAST_PACKET_S_BIT)
340 #define MCAST_PACKET_SEND_CLR(p) ((p)->flags &= ~MCAST_PACKET_S_BIT)
346 #define MCAST_PACKET_IS_LISTED(p) ((p)->flags & MCAST_PACKET_L_BIT)
352 #define MCAST_PACKET_LISTED_SET(p) ((p)->flags |= MCAST_PACKET_L_BIT)
358 #define MCAST_PACKET_LISTED_CLR(p) ((p)->flags &= ~MCAST_PACKET_L_BIT)
364 #define MCAST_PACKET_FREE(p) ((p)->flags = 0)
367 struct sequence_list_header {
373 #define SEQUENCE_LIST_S_BIT 0x80
374 #define SEQUENCE_LIST_M_BIT 0x40
375 #define SEQUENCE_LIST_RES 0x3F
381 #define SEQUENCE_LIST_GET_M(l) \
382 ((uint8_t)(((l)->flags & SEQUENCE_LIST_M_BIT) == SEQUENCE_LIST_M_BIT))
388 #define SEQUENCE_LIST_GET_S(l) \
389 ((uint8_t)(((l)->flags & SEQUENCE_LIST_S_BIT) == SEQUENCE_LIST_S_BIT))
395 #if ROLL_TM_SHORT_SEEDS
400 #if !ROLL_TM_SHORT_SEEDS
407 #define HBHO_OPT_TYPE_TRICKLE 0x0C
408 #define HBHO_LEN_LONG_SEED 2
409 #define HBHO_LEN_SHORT_SEED 4
410 #define HBHO_TOTAL_LEN 8
415 #define HBH_GET_M(h) (((h)->flags & 0x80) == 0x80)
421 #define HBH_SET_M(h) ((h)->flags |= 0x80)
427 #define HBH_GET_SV_MSB(h) ((h)->flags & 0x7F)
430 #if ROLL_TM_CONF_DEST_ALL_NODES
431 #define roll_tm_create_dest(a) uip_create_linklocal_allnodes_mcast(a)
433 #define roll_tm_create_dest(a) uip_create_linklocal_allrouters_mcast(a)
438 static struct roll_tm_stats stats;
440 #define ROLL_TM_STATS_ADD(x) stats.x++
441 #define ROLL_TM_STATS_INIT() do { memset(&stats, 0, sizeof(stats)); } while(0)
443 #define ROLL_TM_STATS_ADD(x)
444 #define ROLL_TM_STATS_INIT()
449 static struct trickle_param t[2];
450 static struct sliding_window windows[ROLL_TM_WINS];
451 static struct mcast_packet buffered_msgs[ROLL_TM_BUFF_NUM];
455 static struct trickle_param *loctpptr;
456 static struct sequence_list_header *locslhptr;
457 static struct sliding_window *locswptr;
458 static struct sliding_window *iterswptr;
459 static struct mcast_packet *locmpptr;
460 static struct hbho_mcast *lochbhmptr;
461 static uint16_t last_seq;
465 #define UIP_DATA_BUF ((uint8_t *)&uip_buf[uip_l2_l3_hdr_len + UIP_UDPH_LEN])
466 #define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
467 #define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN])
468 #define UIP_EXT_BUF_NEXT ((uint8_t *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN + HBHO_TOTAL_LEN])
469 #define UIP_EXT_OPT_FIRST ((struct hbho_mcast *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN + 2])
470 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
471 #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
472 #define UIP_ICMP_PAYLOAD ((unsigned char *)&uip_buf[uip_l2_l3_icmp_hdr_len])
473 extern uint16_t uip_slen;
477 static void icmp_input(
void);
478 static void icmp_output(
void);
479 static void window_update_bounds(
void);
480 static void reset_trickle_timer(uint8_t);
481 static void handle_timer(
void *);
485 UIP_ICMP6_HANDLER_CODE_ANY, icmp_input);
490 random_interval(clock_time_t i_min, uint8_t d)
494 VERBOSE_PRINTF(
"ROLL TM: Random [%lu, %lu)\n", (
unsigned long)min,
502 double_interval(
void *ptr)
504 struct trickle_param *param = (
struct trickle_param *)ptr;
512 offset = (int16_t)(
clock_time() - param->t_end);
515 if(param->i_current < param->i_max) {
519 param->t_start = param->t_end;
520 param->t_end = param->t_start + (param->i_min << param->i_current);
522 next = random_interval(param->i_min, param->i_current);
528 param->t_next = next;
529 ctimer_set(¶m->ct, param->t_next, handle_timer, (
void *)param);
531 VERBOSE_PRINTF(
"ROLL TM: Doubling at %lu (offset %d), Start %lu, End %lu,"
533 (
unsigned long)param->t_start,
534 (
unsigned long)param->t_end, (
unsigned long)param->t_next);
542 handle_timer(
void *ptr)
544 struct trickle_param *param;
545 clock_time_t diff_last;
546 clock_time_t diff_start;
549 param = (
struct trickle_param *)ptr;
552 }
else if(param == &t[1]) {
560 if(uip_ds6_get_link_local(ADDR_PREFERRED) ==
NULL) {
562 (
"ROLL TM: Suppressing timer processing. Stack not ready\n");
563 reset_trickle_timer(m);
567 VERBOSE_PRINTF(
"ROLL TM: M=%u Periodic at %lu, last=%lu\n",
569 (
unsigned long)param->t_last_trigger);
573 diff_last = param->t_next - param->t_last_trigger;
574 diff_start = param->t_next - param->t_start;
575 param->t_last_trigger = param->t_next;
578 (
"ROLL TM: M=%u Periodic diff from last %lu, from start %lu\n", m,
579 (
unsigned long)diff_last, (
unsigned long)diff_start);
582 for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1];
583 locmpptr >= buffered_msgs; locmpptr--) {
600 if(locmpptr->active == 0) {
601 locmpptr->active += diff_start;
602 locmpptr->dwell += diff_start;
604 locmpptr->active += diff_last;
605 locmpptr->dwell += diff_last;
608 VERBOSE_PRINTF(
"ROLL TM: M=%u Packet %u active %lu of %lu\n",
609 m, locmpptr->seq_val, locmpptr->active,
613 locmpptr->sw->count--;
614 PRINTF(
"ROLL TM: M=%u Free Packet %u (%lu > %lu), Window now at %u\n",
615 m, locmpptr->seq_val, locmpptr->dwell,
617 if(locmpptr->sw->count == 0) {
618 PRINTF(
"ROLL TM: M=%u Free Window ", m);
619 PRINT_SEED(&locmpptr->sw->seed_id);
621 window_free(locmpptr->sw);
629 PRINTF(
"ROLL TM: M=%u Periodic - Sending packet from Seed ", m);
630 PRINT_SEED(&locmpptr->sw->seed_id);
631 PRINTF(
" seq %u\n", locmpptr->seq_val);
635 UIP_MCAST6_STATS_ADD(mcast_fwd);
646 if(param->c < param->k) {
652 param->inconsistency = 0;
655 window_update_bounds();
659 if(param->t_next >= param->t_end) {
663 param->t_next = param->t_end - param->t_next;
666 (
"ROLL TM: M=%u Periodic at %lu, Interval End at %lu in %lu\n", m,
667 (
unsigned long)
clock_time(), (
unsigned long)param->t_end,
668 (
unsigned long)param->t_next);
669 ctimer_set(¶m->ct, param->t_next, double_interval, (
void *)param);
675 reset_trickle_timer(uint8_t index)
678 t[index].t_end = t[index].t_start + (t[index].i_min);
679 t[index].i_current = 0;
681 t[index].t_next = random_interval(t[index].i_min, t[index].i_current);
684 (
"ROLL TM: M=%u Reset at %lu, Start %lu, End %lu, New Interval %lu\n",
685 index, (
unsigned long)t[index].t_start, (
unsigned long)t[index].t_start,
686 (
unsigned long)t[index].t_end, (
unsigned long)t[index].t_next);
688 ctimer_set(&t[index].ct, t[index].t_next, handle_timer, (
void *)&t[index]);
691 static struct sliding_window *
694 for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows;
697 iterswptr->count = 0;
698 iterswptr->lower_bound = -1;
699 iterswptr->upper_bound = -1;
700 iterswptr->min_listed = -1;
707 static struct sliding_window *
708 window_lookup(seed_id_t *s, uint8_t m)
710 for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows;
713 VERBOSE_PRINT_SEED(&iterswptr->seed_id);
714 VERBOSE_PRINTF(
"\n");
715 if(seed_id_cmp(s, &iterswptr->seed_id) &&
724 window_update_bounds()
726 for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows;
728 iterswptr->lower_bound = -1;
731 for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1];
732 locmpptr >= buffered_msgs; locmpptr--) {
734 iterswptr = locmpptr->sw;
735 VERBOSE_PRINTF(
"ROLL TM: Update Bounds: [%d - %d] vs %u\n",
736 iterswptr->lower_bound, iterswptr->upper_bound,
738 if(iterswptr->lower_bound < 0
739 ||
SEQ_VAL_IS_LT(locmpptr->seq_val, iterswptr->lower_bound)) {
740 iterswptr->lower_bound = locmpptr->seq_val;
742 if(iterswptr->upper_bound < 0 ||
744 iterswptr->upper_bound = locmpptr->seq_val;
750 static struct mcast_packet *
753 struct sliding_window *largest = windows;
754 struct mcast_packet *rv;
756 for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows;
758 if(iterswptr->count > largest->count) {
763 if(largest->count == 1) {
768 PRINTF(
"ROLL TM: Reclaim from Seed ");
769 PRINT_SEED(&largest->seed_id);
770 PRINTF(
" M=%u, count was %u\n",
773 for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1];
774 locmpptr >= buffered_msgs; locmpptr--) {
778 PRINTF(
"ROLL TM: Reclaim seq. val %u\n", locmpptr->seq_val);
781 window_update_bounds();
782 VERBOSE_PRINTF(
"ROLL TM: Reclaim - new bounds [%u , %u]\n",
783 largest->lower_bound, largest->upper_bound);
792 static struct mcast_packet *
795 for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1];
796 locmpptr >= buffered_msgs; locmpptr--) {
807 struct sequence_list_header *sl;
809 uint16_t payload_len;
811 PRINTF(
"ROLL TM: ICMPv6 Out\n");
819 sl = (
struct sequence_list_header *)UIP_ICMP_PAYLOAD;
822 VERBOSE_PRINTF(
"ROLL TM: ICMPv6 Out - Hdr @ %p, payload @ %p\n",
UIP_ICMP_BUF, sl);
824 for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows;
827 memset(sl, 0,
sizeof(
struct sequence_list_header));
828 #if ROLL_TM_SHORT_SEEDS
829 sl->flags = SEQUENCE_LIST_S_BIT;
832 sl->flags |= SEQUENCE_LIST_M_BIT;
834 seed_id_cpy(&sl->seed_id, &iterswptr->seed_id);
836 PRINTF(
"ROLL TM: ICMPv6 Out - Seq. F=0x%02x, Seed ID=", sl->flags);
837 PRINT_SEED(&sl->seed_id);
839 buffer = (uint8_t *)sl +
sizeof(
struct sequence_list_header);
841 for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1];
842 locmpptr >= buffered_msgs; locmpptr--) {
845 if(locmpptr->sw == iterswptr) {
847 PRINTF(
", %u", locmpptr->seq_val);
848 *buffer = (uint8_t)(locmpptr->seq_val >> 8);
850 *buffer = (uint8_t)(locmpptr->seq_val & 0xFF);
855 PRINTF(
", Len=%u\n", sl->seq_len);
858 if(sl->seq_len > 0) {
859 payload_len +=
sizeof(
struct sequence_list_header) + sl->seq_len * 2;
860 sl = (
struct sequence_list_header *)buffer;
865 if(payload_len == 0) {
866 VERBOSE_PRINTF(
"ROLL TM: ICMPv6 Out - nothing to send\n");
873 UIP_IP_BUF->len[0] = (UIP_ICMPH_LEN + payload_len) >> 8;
874 UIP_IP_BUF->len[1] = (UIP_ICMPH_LEN + payload_len) & 0xff;
882 uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + payload_len;
884 VERBOSE_PRINTF(
"ROLL TM: ICMPv6 Out - %u bytes\n", payload_len);
887 ROLL_TM_STATS_ADD(icmp_out);
906 PRINTF(
"ROLL TM: Multicast I/O\n");
908 #if UIP_CONF_IPV6_CHECKS
910 PRINTF(
"ROLL TM: Mcast I/O, bad destination\n");
911 UIP_MCAST6_STATS_ADD(mcast_bad);
912 return UIP_MCAST6_DROP;
919 PRINTF(
"ROLL TM: Mcast I/O, bad source\n");
920 UIP_MCAST6_STATS_ADD(mcast_bad);
921 return UIP_MCAST6_DROP;
927 PRINTF(
"ROLL TM: Mcast I/O, bad proto\n");
928 UIP_MCAST6_STATS_ADD(mcast_bad);
929 return UIP_MCAST6_DROP;
932 if(UIP_EXT_OPT_FIRST->type != HBHO_OPT_TYPE_TRICKLE) {
933 PRINTF(
"ROLL TM: Mcast I/O, bad HBHO type\n");
934 UIP_MCAST6_STATS_ADD(mcast_bad);
935 return UIP_MCAST6_DROP;
938 lochbhmptr = UIP_EXT_OPT_FIRST;
940 PRINTF(
"ROLL TM: HBHO T=%u, L=%u, M=%u, S=0x%02x%02x\n",
941 lochbhmptr->type, lochbhmptr->len,
HBH_GET_M(lochbhmptr),
945 #if ROLL_TM_SHORT_SEEDS
947 if(lochbhmptr->len != HBHO_LEN_SHORT_SEED) {
948 PRINTF(
"ROLL TM: Mcast I/O, bad length\n");
949 UIP_MCAST6_STATS_ADD(mcast_bad);
950 return UIP_MCAST6_DROP;
954 if(lochbhmptr->len != HBHO_LEN_LONG_SEED) {
955 PRINTF(
"ROLL TM: Mcast I/O, bad length\n");
956 UIP_MCAST6_STATS_ADD(mcast_bad);
957 return UIP_MCAST6_DROP;
962 if(in == ROLL_TM_DGRAM_IN) {
963 UIP_MCAST6_STATS_ADD(mcast_in_all);
968 #if ROLL_TM_SHORT_SEEDS
969 seed_ptr = &lochbhmptr->seed_id;
975 locswptr = window_lookup(seed_ptr, m);
977 seq_val = lochbhmptr->seq_id_lsb;
983 PRINTF(
"ROLL TM: Too old\n");
984 UIP_MCAST6_STATS_ADD(mcast_dropped);
985 return UIP_MCAST6_DROP;
987 for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1];
988 locmpptr >= buffered_msgs; locmpptr--) {
990 locmpptr->sw == locswptr &&
994 PRINTF(
"ROLL TM: Seen before\n");
995 UIP_MCAST6_STATS_ADD(mcast_dropped);
996 return UIP_MCAST6_DROP;
1001 PRINTF(
"ROLL TM: New message\n");
1006 locswptr = window_allocate();
1007 PRINTF(
"ROLL TM: New seed\n");
1011 PRINTF(
"ROLL TM: Failed to allocate window\n");
1012 UIP_MCAST6_STATS_ADD(mcast_dropped);
1013 return UIP_MCAST6_DROP;
1017 locmpptr = buffer_allocate();
1019 PRINTF(
"ROLL TM: Buffer allocation failed, reclaiming\n");
1020 locmpptr = buffer_reclaim();
1026 PRINTF(
"ROLL TM: Buffer reclaim failed\n");
1027 if(locswptr->count == 0) {
1028 window_free(locswptr);
1029 UIP_MCAST6_STATS_ADD(mcast_dropped);
1030 return UIP_MCAST6_DROP;
1033 #if UIP_MCAST6_STATS
1034 if(in == ROLL_TM_DGRAM_IN) {
1035 UIP_MCAST6_STATS_ADD(mcast_in_unique);
1046 seed_id_cpy(&locswptr->seed_id, seed_ptr);
1047 PRINTF(
"ROLL TM: Window for seed ");
1048 PRINT_SEED(&locswptr->seed_id);
1049 PRINTF(
" M=%u, count=%u\n",
1053 if(locswptr->count == 0) {
1054 locswptr->lower_bound = seq_val;
1055 VERBOSE_PRINTF(
"ROLL TM: New Lower Bound %u\n", locswptr->lower_bound);
1059 if(locswptr->count == 0 ||
SEQ_VAL_IS_GT(seq_val, locswptr->upper_bound)) {
1060 locswptr->upper_bound = seq_val;
1061 VERBOSE_PRINTF(
"ROLL TM: New Upper Bound %u\n", locswptr->upper_bound);
1066 memset(locmpptr, 0,
sizeof(
struct mcast_packet));
1068 locmpptr->sw = locswptr;
1070 locmpptr->seq_val = seq_val;
1073 PRINTF(
"ROLL TM: Window for seed ");
1074 PRINT_SEED(&locswptr->seed_id);
1075 PRINTF(
" M=%u, %u values within [%u , %u]\n",
1077 locswptr->lower_bound, locswptr->upper_bound);
1085 if(in == ROLL_TM_DGRAM_IN) {
1089 t[m].inconsistency = 1;
1091 PRINTF(
"ROLL TM: Inconsistency. Reset T%u\n", m);
1092 reset_trickle_timer(m);
1096 return UIP_MCAST6_ACCEPT;
1103 uint8_t inconsistency;
1108 #if UIP_CONF_IPV6_CHECKS
1110 PRINTF(
"ROLL TM: ICMPv6 In, bad source ");
1115 ROLL_TM_STATS_ADD(icmp_bad);
1121 PRINTF(
"ROLL TM: ICMPv6 In, bad destination\n");
1122 ROLL_TM_STATS_ADD(icmp_bad);
1127 PRINTF(
"ROLL TM: ICMPv6 In, bad ICMP code\n");
1128 ROLL_TM_STATS_ADD(icmp_bad);
1132 if(
UIP_IP_BUF->ttl != ROLL_TM_IP_HOP_LIMIT) {
1133 PRINTF(
"ROLL TM: ICMPv6 In, bad TTL\n");
1134 ROLL_TM_STATS_ADD(icmp_bad);
1139 PRINTF(
"ROLL TM: ICMPv6 In from ");
1143 ROLL_TM_STATS_ADD(icmp_in);
1146 for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows;
1152 for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1];
1153 locmpptr >= buffered_msgs; locmpptr--) {
1157 locslhptr = (
struct sequence_list_header *)UIP_ICMP_PAYLOAD;
1159 VERBOSE_PRINTF(
"ROLL TM: ICMPv6 In, parse from %p to %p\n",
1161 (uint8_t *)UIP_ICMP_PAYLOAD +
uip_len -
1162 uip_l2_l3_icmp_hdr_len);
1164 (
struct sequence_list_header *)((uint8_t *)UIP_ICMP_PAYLOAD +
1165 uip_len - uip_l2_l3_icmp_hdr_len)) {
1166 VERBOSE_PRINTF(
"ROLL TM: ICMPv6 In, seq hdr @ %p\n", locslhptr);
1168 if((locslhptr->flags & SEQUENCE_LIST_RES) != 0) {
1169 PRINTF(
"ROLL TM: ICMPv6 In, non-zero reserved bits\n");
1174 #if ROLL_TM_SHORT_SEEDS
1176 ROLL_TM_STATS_ADD(icmp_bad);
1181 ROLL_TM_STATS_ADD(icmp_bad);
1186 PRINTF(
"ROLL TM: ICMPv6 In, Sequence List for Seed ID ");
1187 PRINT_SEED(&locslhptr->seed_id);
1191 seq_ptr = (uint16_t *)((uint8_t *)locslhptr
1192 +
sizeof(
struct sequence_list_header));
1193 end_ptr = (uint16_t *)((uint8_t *)locslhptr
1194 +
sizeof(
struct sequence_list_header) +
1195 locslhptr->seq_len * 2);
1203 locswptr = window_lookup(&locslhptr->seed_id,
1209 locswptr->min_listed = -1;
1210 PRINTF(
"ROLL TM: ICMPv6 In, Window bounds [%u , %u]\n",
1211 locswptr->lower_bound, locswptr->upper_bound);
1212 for(; seq_ptr < end_ptr; seq_ptr++) {
1216 PRINTF(
"ROLL TM: ICMPv6 In, Check seq %u @ %p\n", val, seq_ptr);
1218 PRINTF(
"ROLL TM: Inconsistency - Advertised Seq. ID %u GT upper"
1219 " bound %u\n", val, locswptr->upper_bound);
1220 loctpptr->inconsistency = 1;
1231 for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1];
1232 locmpptr >= buffered_msgs; locmpptr--) {
1238 PRINTF(
"ROLL TM: ICMPv6 In, %u listed\n", locmpptr->seq_val);
1242 if(locswptr->min_listed == -1 ||
1244 locswptr->min_listed = val;
1251 PRINTF(
"ROLL TM: Inconsistency - ");
1252 PRINTF(
"Advertised Seq. ID %u within bounds", val);
1253 PRINTF(
" [%u, %u] but no matching entry\n",
1254 locswptr->lower_bound, locswptr->upper_bound);
1255 loctpptr->inconsistency = 1;
1264 PRINTF(
"ROLL TM: Inconsistency - Advertised window unknown to us\n");
1265 loctpptr->inconsistency = 1;
1267 locslhptr = (
struct sequence_list_header *)(((uint8_t *)locslhptr) +
1268 sizeof(
struct sequence_list_header) + (2 * locslhptr->seq_len));
1273 PRINTF(
"ROLL TM: ICMPv6 In, Check our buffer\n");
1274 for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1];
1275 locmpptr >= buffered_msgs; locmpptr--) {
1277 locswptr = locmpptr->sw;
1278 PRINTF(
"ROLL TM: ICMPv6 In, ");
1279 PRINTF(
"Check %u, Seed L: %u, This L: %u Min L: %d\n",
1287 PRINTF(
"ROLL TM: Inconsistency - Seed ID ");
1288 PRINT_SEED(&locswptr->seed_id);
1289 PRINTF(
" was not listed\n");
1290 loctpptr->inconsistency = 1;
1295 (locswptr->min_listed >= 0) &&
1297 PRINTF(
"ROLL TM: Inconsistency - ");
1298 PRINTF(
"Seq. %u was not listed but %u was\n",
1299 locmpptr->seq_val, locswptr->min_listed);
1300 loctpptr->inconsistency = 1;
1309 if(t[0].inconsistency) {
1310 reset_trickle_timer(0);
1314 if(t[1].inconsistency) {
1315 reset_trickle_timer(1);
1328 PRINTF(
"ROLL TM: Multicast Out can not add HBHO. Packet too long\n");
1333 memmove(UIP_EXT_BUF_NEXT, UIP_EXT_BUF,
uip_len - UIP_IPH_LEN);
1334 memset(UIP_EXT_BUF, 0, HBHO_TOTAL_LEN);
1337 UIP_EXT_BUF->len = 0;
1339 lochbhmptr = UIP_EXT_OPT_FIRST;
1340 lochbhmptr->type = HBHO_OPT_TYPE_TRICKLE;
1344 lochbhmptr->flags = last_seq >> 8;
1345 lochbhmptr->seq_id_lsb = last_seq & 0xFF;
1346 #if ROLL_TM_SHORT_SEEDS
1347 seed_id_cpy(&lochbhmptr->seed_id, &
uip_lladdr.addr[UIP_LLADDR_LEN - 2]);
1348 lochbhmptr->len = HBHO_LEN_SHORT_SEED;
1350 lochbhmptr->len = HBHO_LEN_LONG_SEED;
1352 lochbhmptr->padn_type = UIP_EXT_HDR_OPT_PADN;
1353 lochbhmptr->padn_len = 0;
1357 #if ROLL_TM_SET_M_BIT
1369 PRINTF(
"ROLL TM: Multicast Out, HBHO: T=%u, L=%u, M=%u, S=0x%02x%02x\n",
1370 lochbhmptr->type, lochbhmptr->len,
HBH_GET_M(lochbhmptr),
1382 if(accept(ROLL_TM_DGRAM_OUT)) {
1384 UIP_MCAST6_STATS_ADD(mcast_out);
1401 if(accept(ROLL_TM_DGRAM_IN) == UIP_MCAST6_DROP) {
1402 return UIP_MCAST6_DROP;
1405 if(!uip_ds6_is_my_maddr(&
UIP_IP_BUF->destipaddr)) {
1406 PRINTF(
"ROLL TM: Not a group member. No further processing\n");
1407 return UIP_MCAST6_DROP;
1409 PRINTF(
"ROLL TM: Ours. Deliver to upper layers\n");
1410 UIP_MCAST6_STATS_ADD(mcast_in_ours);
1411 return UIP_MCAST6_ACCEPT;
1418 PRINTF(
"ROLL TM: ROLL Multicast - Draft #%u\n", ROLL_TM_VER);
1420 memset(windows, 0,
sizeof(windows));
1421 memset(buffered_msgs, 0,
sizeof(buffered_msgs));
1422 memset(t, 0,
sizeof(t));
1424 ROLL_TM_STATS_INIT();
1425 UIP_MCAST6_STATS_INIT(&stats);
1430 for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows;
1432 iterswptr->lower_bound = -1;
1433 iterswptr->upper_bound = -1;
1434 iterswptr->min_listed = -1;
1438 reset_trickle_timer(0);
1440 reset_trickle_timer(1);
1444 const struct uip_mcast6_driver roll_tm_driver = {
uip_len
The length of the packet in the uip_buf buffer.
void tcpip_ipv6_output(void)
This function does address resolution and then calls tcpip_output.
#define MCAST_PACKET_MUST_SEND(p)
Must we send this message this pass?
#define uip_is_addr_link_local(a)
is addr (a) a link local unicast address, see RFC3513 i.e.
#define SLIDING_WINDOW_LISTED_SET(w)
Set 'Is Seen' bit for window w w: pointer to a sliding window.
CCIF uip_lladdr_t uip_lladdr
Host L2 address.
#define SUPPRESSION_DISABLED(t)
Check if suppression is disabled for trickle_param t t is a pointer to the timer. ...
This header file contains configuration directives for uIPv6 multicast support.
#define SLIDING_WINDOW_M_SET(w)
Set M bit for window w w: pointer to a sliding window.
#define SEQ_VAL_IS_LT(i1, i2)
s1 is said to be less than s2 iif SEQ_VAL_IS_LT(s1, s2) == 1
#define uip_is_addr_linklocal_allnodes_mcast(a)
Is IPv6 address a the link local all-nodes multicast address.
#define HBH_SET_M(h)
Set the Trickle Parametrization bit for a multicast HBHO header m: pointer to the HBHO header...
#define NULL
The null pointer.
uint8_t tcpip_output(const uip_lladdr_t *a)
Output packet to layer 2 The eventual parameter is the MAC address of the destination.
#define SLIDING_WINDOW_M_CLR(w)
Clear M bit for window w w: pointer to a sliding window.
#define MCAST_PACKET_LISTED_SET(p)
Set 'Is Listed' bit for message p p: pointer to a struct mcast_packet.
#define UIP_BUFSIZE
The size of the uIP packet buffer.
void uip_icmp6_register_input_handler(uip_icmp6_input_handler_t *handler)
Register a handler which can handle a specific ICMPv6 message type.
#define MCAST_PACKET_USED_SET(p)
Set 'Is Used' bit for packet p p: pointer to a packet buffer.
#define uip_is_addr_linklocal_allrouters_mcast(a)
Is IPv6 address a the link local all-routers multicast address.
#define SEQUENCE_LIST_GET_S(l)
Get the Seed ID Length for an ICMPv6 sequence list l: pointer to a sequence list structure.
#define MCAST_PACKET_SEND_CLR(p)
Clear 'Must Send' bit for message p p: pointer to a struct mcast_packet.
#define MCAST_PACKET_IS_LISTED(p)
Is the message p listed in current ICMP message? p: pointer to a struct mcast_packet.
#define HBH_GET_M(h)
Get the Trickle Parametrization for a multicast HBHO header m: pointer to the HBHO header...
#define UIP_IP_BUF
Pointer to IP header.
CCIF clock_time_t clock_time(void)
Get the current clock time.
#define UIP_LLH_LEN
The link level header length.
#define uip_is_addr_unspecified(a)
Is IPv6 address a the unspecified address a is of type uip_ipaddr_t.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
#define SLIDING_WINDOW_IS_USED(w)
Is Occupied sliding window location w w: pointer to a sliding window.
uint16_t uip_icmp6chksum(void)
Calculate the ICMP checksum of the packet in uip_buf.
void watchdog_periodic(void)
Writes the WDT clear sequence.
#define SEQUENCE_LIST_GET_M(l)
Get the Trickle Parametrization for an ICMPv6 sequence list l: pointer to a sequence list structure...
#define uip_is_addr_mcast_non_routable(a)
is address a non-routable multicast address.
#define MCAST_PACKET_IS_USED(p)
Is Occupied buffer location p.
CCIF uint16_t uip_htons(uint16_t val)
Convert a 16-bit quantity from host byte order to network byte order.
uint8_t uip_ext_len
The length of the extension headers.
#define TRICKLE_DWELL(t)
Convert Tdwell for a trickle timer to a sane clock_time_t value t is a pointer to the timer Careful o...
#define SLIDING_WINDOW_IS_LISTED(w)
Is the sliding window at location w listed in current ICMP message? w: pointer to a sliding window...
ICMPv6 echo request and error messages (RFC 4443)
#define MCAST_PACKET_FREE(p)
Free a multicast packet buffer p: pointer to a struct mcast_packet.
void uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
Source address selection, see RFC 3484.
#define UIP_ICMP_BUF
Pointer to ICMP header.
#define SLIDING_WINDOW_IS_USED_SET(w)
Set 'Is Used' bit for window w w: pointer to a sliding window.
#define SEQ_VAL_IS_EQ(i1, i2)
s1 is said to be equal s2 iif SEQ_VAL_IS_EQ(s1, s2) == 1
#define TIMER_CONFIGURE(m)
Init trickle_timer[m].
#define SEQ_VAL_ADD(s, n)
Add n to s: (s + n) modulo (2 ^ SERIAL_BITS) => ((s + n) % 0x8000)
#define SUPPRESSION_ENABLED(t)
Check if suppression is enabled for trickle_param t t is a pointer to the timer.
#define HBH_GET_SV_MSB(h)
Retrieve the Sequence Value MSB from a multicast HBHO header m: pointer to the HBHO header...
#define TRICKLE_ACTIVE(t)
Convert Tactive for a trickle timer to a sane clock_time_t value t is a pointer to the timer Careful ...
#define MCAST_PACKET_LISTED_CLR(p)
Clear 'Is Listed' bit for message p p: pointer to a struct mcast_packet.
#define UIP_PROTO_HBHO
extension headers types
A set of debugging macros.
#define ICMP6_ROLL_TM
ROLL Trickle Multicast.
#define MCAST_PACKET_TTL(p)
Get the TTL of a buffered packet p: pointer to a packet buffer.
#define SLIDING_WINDOW_LISTED_CLR(w)
Clear 'Is Seen' bit for window w w: pointer to a sliding window.
#define MCAST_PACKET_SEND_SET(p)
Set 'Must Send' bit for message p p: pointer to a struct mcast_packet.
#define TRICKLE_TIME(m, d)
Convert a timer to a sane clock_time_t value after d doublings m is a value of Imin, d is a number of doublings Careful of overflows.
unsigned short random_rand(void)
Generate the next state and return the upper part of it.
#define SLIDING_WINDOW_GET_M(w)
Retrieve trickle parametrization for sliding window at location w w: pointer to a sliding window...
Header file for IPv6 multicast according to the algorithm in the "MCAST Forwarding Using Tric...
#define SEQ_VAL_IS_GT(i1, i2)
s1 is said to be greater than s2 iif SEQ_VAL_IS_LT(s1, s2) == 1