rpl-timers.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "contiki-conf.h"
00043 #include "net/rpl/rpl-private.h"
00044 #include "lib/random.h"
00045 #include "sys/ctimer.h"
00046
00047 #define DEBUG DEBUG_NONE
00048 #include "net/uip-debug.h"
00049
00050
00051 static struct ctimer periodic_timer;
00052
00053 static void handle_periodic_timer(void *ptr);
00054 static void new_dio_interval(rpl_dag_t *dag);
00055 static void handle_dio_timer(void *ptr);
00056
00057 static uint16_t next_dis;
00058
00059
00060 static uint8_t dio_send_ok;
00061
00062
00063 static void
00064 handle_periodic_timer(void *ptr)
00065 {
00066 rpl_purge_routes();
00067 rpl_recalculate_ranks();
00068
00069
00070 #ifdef RPL_DIS_SEND
00071 next_dis++;
00072 if(rpl_get_dag(RPL_ANY_INSTANCE) == NULL && next_dis >= RPL_DIS_INTERVAL) {
00073 next_dis = 0;
00074 dis_output(NULL);
00075 }
00076 #endif
00077 ctimer_reset(&periodic_timer);
00078 }
00079
00080 static void
00081 new_dio_interval(rpl_dag_t *dag)
00082 {
00083 uint32_t time;
00084
00085
00086 time = 1UL << dag->dio_intcurrent;
00087
00088
00089 time = (time * CLOCK_SECOND) / 1000;
00090
00091 dag->dio_next_delay = time;
00092
00093
00094 time = time >> 1;
00095 time += (time * random_rand()) / RANDOM_RAND_MAX;
00096
00097
00098
00099
00100
00101
00102 dag->dio_next_delay -= time;
00103 dag->dio_send = 1;
00104
00105 #if RPL_CONF_STATS
00106
00107 dag->dio_totint++;
00108 dag->dio_totrecv += dag->dio_counter;
00109 ANNOTATE("#A rank=%u.%u(%u),stats=%d %d %d %d,color=%s\n",
00110 DAG_RANK(dag->rank, dag),
00111 (10 * (dag->rank % dag->min_hoprankinc)) / dag->min_hoprankinc,
00112 dag->version,
00113 dag->dio_totint, dag->dio_totsend,
00114 dag->dio_totrecv,dag->dio_intcurrent,
00115 dag->rank == ROOT_RANK(dag) ? "BLUE" : "ORANGE");
00116 #endif
00117
00118
00119 dag->dio_counter = 0;
00120
00121
00122 PRINTF("RPL: Scheduling DIO timer %lu ticks in future (Interval)\n", time);
00123 ctimer_set(&dag->dio_timer, time, &handle_dio_timer, dag);
00124 }
00125
00126 static void
00127 handle_dio_timer(void *ptr)
00128 {
00129 rpl_dag_t *dag;
00130
00131 dag = (rpl_dag_t *)ptr;
00132
00133 PRINTF("RPL: DIO Timer triggered\n");
00134 if(!dio_send_ok) {
00135 if(uip_ds6_get_link_local(ADDR_PREFERRED) != NULL) {
00136 dio_send_ok = 1;
00137 } else {
00138 PRINTF("RPL: Postponing DIO transmission since link local address is not ok\n");
00139 ctimer_set(&dag->dio_timer, CLOCK_SECOND, &handle_dio_timer, dag);
00140 return;
00141 }
00142 }
00143
00144 if(dag->dio_send) {
00145
00146 if(dag->dio_counter < dag->dio_redundancy) {
00147 #if RPL_CONF_STATS
00148 dag->dio_totsend++;
00149 #endif
00150 dio_output(dag, NULL);
00151 } else {
00152 PRINTF("RPL: Supressing DIO transmission (%d >= %d)\n",
00153 dag->dio_counter, dag->dio_redundancy);
00154 }
00155 dag->dio_send = 0;
00156 PRINTF("RPL: Scheduling DIO timer %u ticks in future (sent)\n",
00157 dag->dio_next_delay);
00158 ctimer_set(&dag->dio_timer, dag->dio_next_delay, handle_dio_timer, dag);
00159 } else {
00160
00161 if(dag->dio_intcurrent < dag->dio_intmin + dag->dio_intdoubl) {
00162 dag->dio_intcurrent++;
00163 PRINTF("RPL: DIO Timer interval doubled %d\n", dag->dio_intcurrent);
00164 }
00165 new_dio_interval(dag);
00166 }
00167 }
00168
00169 void
00170 rpl_reset_periodic_timer(void)
00171 {
00172 next_dis = RPL_DIS_INTERVAL - RPL_DIS_START_DELAY;
00173 ctimer_set(&periodic_timer, CLOCK_SECOND, handle_periodic_timer, NULL);
00174 }
00175
00176
00177 void
00178 rpl_reset_dio_timer(rpl_dag_t *dag, uint8_t force)
00179 {
00180
00181 if(force || dag->dio_intcurrent > dag->dio_intmin) {
00182 dag->dio_counter = 0;
00183 dag->dio_intcurrent = dag->dio_intmin;
00184 new_dio_interval(dag);
00185 }
00186 #if RPL_CONF_STATS
00187 rpl_stats.resets++;
00188 #endif
00189 }
00190
00191 static void
00192 handle_dao_timer(void *ptr)
00193 {
00194 rpl_dag_t *dag;
00195
00196 dag = (rpl_dag_t *)ptr;
00197
00198 if (!dio_send_ok && uip_ds6_get_link_local(ADDR_PREFERRED) == NULL) {
00199 PRINTF("RPL: Postpone DAO transmission... \n");
00200 ctimer_set(&dag->dao_timer, CLOCK_SECOND, handle_dao_timer, dag);
00201 return;
00202 }
00203
00204
00205
00206 if(dag->preferred_parent != NULL) {
00207 PRINTF("RPL: handle_dao_timer - sending DAO\n");
00208
00209 dao_output(dag->preferred_parent, dag->lifetime_unit * 0xffUL);
00210 } else {
00211 PRINTF("RPL: Could not find a parent to send a DAO to \n");
00212 }
00213 ctimer_stop(&dag->dao_timer);
00214 }
00215
00216 void
00217 rpl_schedule_dao(rpl_dag_t *dag)
00218 {
00219 clock_time_t expiration_time;
00220
00221 expiration_time = etimer_expiration_time(&dag->dao_timer.etimer);
00222
00223 if(!etimer_expired(&dag->dao_timer.etimer)) {
00224 PRINTF("RPL: DAO timer already scheduled\n");
00225 } else {
00226 expiration_time = DEFAULT_DAO_LATENCY / 2 +
00227 (random_rand() % (DEFAULT_DAO_LATENCY));
00228 PRINTF("RPL: Scheduling DAO timer %u ticks in the future\n",
00229 (unsigned)expiration_time);
00230 ctimer_set(&dag->dao_timer, expiration_time,
00231 handle_dao_timer, dag);
00232 }
00233 }
00234