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
00043
00044
00045
00046 #include <limits.h>
00047 #include <stdio.h>
00048
00049 #include "contiki.h"
00050 #include "lib/memb.h"
00051 #include "lib/list.h"
00052
00053 #include "net/rime/collect-neighbor.h"
00054 #include "net/rime/collect.h"
00055
00056 #ifdef COLLECT_NEIGHBOR_CONF_MAX_COLLECT_NEIGHBORS
00057 #define MAX_COLLECT_NEIGHBORS COLLECT_NEIGHBOR_CONF_MAX_COLLECT_NEIGHBORS
00058 #else
00059 #define MAX_COLLECT_NEIGHBORS 8
00060 #endif
00061
00062 #define RTMETRIC_MAX COLLECT_MAX_DEPTH
00063
00064 MEMB(collect_neighbors_mem, struct collect_neighbor, MAX_COLLECT_NEIGHBORS);
00065
00066 #define MAX_AGE 180
00067 #define MAX_LE_AGE 10
00068 #define PERIODIC_INTERVAL CLOCK_SECOND * 60
00069
00070 #define EXPECTED_CONGESTION_DURATION CLOCK_SECOND * 240
00071 #define CONGESTION_PENALTY 8 * COLLECT_LINK_ESTIMATE_UNIT
00072
00073 #define DEBUG 0
00074 #if DEBUG
00075 #include <stdio.h>
00076 #define PRINTF(...) printf(__VA_ARGS__)
00077 #else
00078 #define PRINTF(...)
00079 #endif
00080
00081
00082 static void
00083 periodic(void *ptr)
00084 {
00085 struct collect_neighbor_list *neighbor_list;
00086 struct collect_neighbor *n;
00087
00088 neighbor_list = ptr;
00089
00090
00091 for(n = list_head(neighbor_list->list); n != NULL; n = list_item_next(n)) {
00092 n->age++;
00093 n->le_age++;
00094 }
00095 for(n = list_head(neighbor_list->list); n != NULL; n = list_item_next(n)) {
00096 if(n->le_age == MAX_LE_AGE) {
00097 collect_link_estimate_new(&n->le);
00098 n->le_age = 0;
00099 }
00100 if(n->age == MAX_AGE) {
00101 memb_free(&collect_neighbors_mem, n);
00102 list_remove(neighbor_list->list, n);
00103 n = list_head(neighbor_list->list);
00104 }
00105 }
00106 ctimer_set(&neighbor_list->periodic, PERIODIC_INTERVAL,
00107 periodic, neighbor_list);
00108 }
00109
00110 void
00111 collect_neighbor_init(void)
00112 {
00113 static uint8_t initialized = 0;
00114 if(initialized == 0) {
00115 initialized = 1;
00116 memb_init(&collect_neighbors_mem);
00117 }
00118 }
00119
00120 void
00121 collect_neighbor_list_new(struct collect_neighbor_list *neighbors_list)
00122 {
00123 LIST_STRUCT_INIT(neighbors_list, list);
00124 list_init(neighbors_list->list);
00125 ctimer_set(&neighbors_list->periodic, CLOCK_SECOND, periodic, neighbors_list);
00126 }
00127
00128 struct collect_neighbor *
00129 collect_neighbor_list_find(struct collect_neighbor_list *neighbors_list,
00130 const rimeaddr_t *addr)
00131 {
00132 struct collect_neighbor *n;
00133 for(n = list_head(neighbors_list->list); n != NULL; n = list_item_next(n)) {
00134 if(rimeaddr_cmp(&n->addr, addr)) {
00135 return n;
00136 }
00137 }
00138 return NULL;
00139 }
00140
00141 int
00142 collect_neighbor_list_add(struct collect_neighbor_list *neighbors_list,
00143 const rimeaddr_t *addr, uint16_t nrtmetric)
00144 {
00145 struct collect_neighbor *n;
00146
00147 if(addr == NULL) {
00148 PRINTF("collect_neighbor_list_add: attempt to add NULL addr\n");
00149 return 0;
00150 }
00151
00152 PRINTF("collect_neighbor_add: adding %d.%d\n", addr->u8[0], addr->u8[1]);
00153
00154
00155 for(n = list_head(neighbors_list->list); n != NULL; n = list_item_next(n)) {
00156 if(rimeaddr_cmp(&n->addr, addr)) {
00157 PRINTF("collect_neighbor_add: already on list %d.%d\n",
00158 addr->u8[0], addr->u8[1]);
00159 break;
00160 }
00161 }
00162
00163
00164
00165 if(n == NULL) {
00166 PRINTF("collect_neighbor_add: not on list, allocating %d.%d\n",
00167 addr->u8[0], addr->u8[1]);
00168 n = memb_alloc(&collect_neighbors_mem);
00169 if(n != NULL) {
00170 list_add(neighbors_list->list, n);
00171 }
00172 }
00173
00174
00175
00176
00177
00178 if(n == NULL) {
00179 uint16_t worst_rtmetric;
00180 struct collect_neighbor *worst_neighbor;
00181
00182
00183
00184
00185
00186
00187 worst_rtmetric = 0;
00188 worst_neighbor = NULL;
00189
00190 for(n = list_head(neighbors_list->list);
00191 n != NULL; n = list_item_next(n)) {
00192 if(n->rtmetric > worst_rtmetric) {
00193 worst_neighbor = n;
00194 worst_rtmetric = n->rtmetric;
00195 }
00196 }
00197
00198
00199
00200 if(nrtmetric < worst_rtmetric) {
00201 n = worst_neighbor;
00202 }
00203 if(n != NULL) {
00204 PRINTF("collect_neighbor_add: not on list, not allocated, recycling %d.%d\n",
00205 n->addr.u8[0], n->addr.u8[1]);
00206 }
00207 }
00208
00209 if(n != NULL) {
00210 n->age = 0;
00211 rimeaddr_copy(&n->addr, addr);
00212 n->rtmetric = nrtmetric;
00213 collect_link_estimate_new(&n->le);
00214 n->le_age = 0;
00215 return 1;
00216 }
00217 return 0;
00218 }
00219
00220 list_t
00221 collect_neighbor_list(struct collect_neighbor_list *neighbors_list)
00222 {
00223 return neighbors_list->list;
00224 }
00225
00226 void
00227 collect_neighbor_list_remove(struct collect_neighbor_list *neighbors_list,
00228 const rimeaddr_t *addr)
00229 {
00230 struct collect_neighbor *n = collect_neighbor_list_find(neighbors_list, addr);
00231
00232 if(n != NULL) {
00233 list_remove(neighbors_list->list, n);
00234 memb_free(&collect_neighbors_mem, n);
00235 }
00236 }
00237
00238 struct collect_neighbor *
00239 collect_neighbor_list_best(struct collect_neighbor_list *neighbors_list)
00240 {
00241 int found;
00242 struct collect_neighbor *n, *best;
00243 uint16_t rtmetric;
00244
00245 rtmetric = RTMETRIC_MAX;
00246 best = NULL;
00247 found = 0;
00248
00249
00250 PRINTF("collect_neighbor_best: ");
00251
00252
00253 for(n = list_head(neighbors_list->list); n != NULL; n = list_item_next(n)) {
00254 PRINTF("%d.%d %d+%d=%d, ",
00255 n->addr.u8[0], n->addr.u8[1],
00256 n->rtmetric, collect_neighbor_link_estimate(n),
00257 collect_neighbor_rtmetric(n));
00258 if(collect_neighbor_rtmetric_link_estimate(n) < rtmetric) {
00259 rtmetric = collect_neighbor_rtmetric_link_estimate(n);
00260 best = n;
00261 }
00262 }
00263 PRINTF("\n");
00264
00265 return best;
00266 }
00267
00268 int
00269 collect_neighbor_list_num(struct collect_neighbor_list *neighbors_list)
00270 {
00271 PRINTF("collect_neighbor_num %d\n", list_length(neighbors_list->list));
00272 return list_length(neighbors_list->list);
00273 }
00274
00275 struct collect_neighbor *
00276 collect_neighbor_list_get(struct collect_neighbor_list *neighbors_list, int num)
00277 {
00278 int i;
00279 struct collect_neighbor *n;
00280
00281 PRINTF("collect_neighbor_get %d\n", num);
00282
00283 i = 0;
00284 for(n = list_head(neighbors_list->list); n != NULL; n = list_item_next(n)) {
00285 if(i == num) {
00286 PRINTF("collect_neighbor_get found %d.%d\n",
00287 n->addr.u8[0], n->addr.u8[1]);
00288 return n;
00289 }
00290 i++;
00291 }
00292 return NULL;
00293 }
00294
00295 void
00296 collect_neighbor_list_purge(struct collect_neighbor_list *neighbors_list)
00297 {
00298 while(list_head(neighbors_list->list) != NULL) {
00299 memb_free(&collect_neighbors_mem, list_pop(neighbors_list->list));
00300 }
00301 }
00302
00303 void
00304 collect_neighbor_update_rtmetric(struct collect_neighbor *n, uint16_t rtmetric)
00305 {
00306 if(n != NULL) {
00307 PRINTF("%d.%d: collect_neighbor_update %d.%d rtmetric %d\n",
00308 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00309 n->addr.u8[0], n->addr.u8[1], rtmetric);
00310 n->rtmetric = rtmetric;
00311 n->age = 0;
00312 }
00313 }
00314
00315 void
00316 collect_neighbor_tx_fail(struct collect_neighbor *n, uint16_t num_tx)
00317 {
00318 collect_link_estimate_update_tx_fail(&n->le, num_tx);
00319 n->le_age = 0;
00320 n->age = 0;
00321 }
00322
00323 void
00324 collect_neighbor_tx(struct collect_neighbor *n, uint16_t num_tx)
00325 {
00326 collect_link_estimate_update_tx(&n->le, num_tx);
00327 n->le_age = 0;
00328 n->age = 0;
00329 }
00330
00331 void
00332 collect_neighbor_rx(struct collect_neighbor *n)
00333 {
00334 collect_link_estimate_update_rx(&n->le);
00335 n->age = 0;
00336 }
00337
00338 uint16_t
00339 collect_neighbor_link_estimate(struct collect_neighbor *n)
00340 {
00341 if(collect_neighbor_is_congested(n)) {
00342
00343
00344
00345
00346 return collect_link_estimate(&n->le) + CONGESTION_PENALTY;
00347 } else {
00348 return collect_link_estimate(&n->le);
00349 }
00350 }
00351
00352 uint16_t
00353 collect_neighbor_rtmetric_link_estimate(struct collect_neighbor *n)
00354 {
00355 return n->rtmetric + collect_link_estimate(&n->le);
00356 }
00357
00358 uint16_t
00359 collect_neighbor_rtmetric(struct collect_neighbor *n)
00360 {
00361 return n->rtmetric;
00362 }
00363
00364 void
00365 collect_neighbor_set_congested(struct collect_neighbor *n)
00366 {
00367 timer_set(&n->congested_timer, EXPECTED_CONGESTION_DURATION);
00368 }
00369
00370 int
00371 collect_neighbor_is_congested(struct collect_neighbor *n)
00372 {
00373 if(timer_expired(&n->congested_timer)) {
00374 return 0;
00375 } else {
00376 return 1;
00377 }
00378 }
00379
00380