16#include "RPL_Message.h"
19PRPL_NEIGHBOR rpl_find_neighbor(NETSIM_ID d, NETSIM_ID r)
21 PRPL_NODE rpl = GET_RPL_NODE(d);
23 for (i = 0; i < rpl->neighbor_count; i++)
25 if (rpl->neighbor_list[i]->nodeId == r)
26 return rpl->neighbor_list[i];
31static void add_neighbor(NETSIM_ID d, NETSIM_ID r)
33 PRPL_NODE rpl = GET_RPL_NODE(d);
34 if (rpl->neighbor_count)
35 rpl->neighbor_list = (PRPL_NEIGHBOR*)realloc(rpl->neighbor_list,(rpl->neighbor_count + 1)* (
sizeof* rpl->neighbor_list));
37 rpl->neighbor_list = (PRPL_NEIGHBOR*)calloc(1,
sizeof* rpl->neighbor_list);
38 PRPL_NEIGHBOR neighbor = (PRPL_NEIGHBOR)calloc(1,
sizeof* neighbor);
40 rpl->neighbor_list[rpl->neighbor_count] = neighbor;
41 rpl->neighbor_count++;
44void rpl_add_to_neighbor_list()
46 NETSIM_ID d = pstruEventDetails->nDeviceId;
47 NETSIM_ID r = pstruEventDetails->pPacket->nTransmitterId;
49 if (is_rpl_configured(d) && is_rpl_configured(r))
51 PRPL_NODE rpl = GET_RPL_NODE(d);
52 PRPL_NEIGHBOR neighbor = rpl_find_neighbor(d, r);
58void update_neighbor_dio_message(PRPL_NEIGHBOR neighbor, PRPL_CTRL_MSG dio_pdu)
60 rpl_dio_pdu_free(neighbor->lastDIOMSG);
61 neighbor->lastDIOMSG = rpl_dio_pdu_duplicate(dio_pdu);
64void rpl_node_add_parent(NETSIM_ID d, PRPL_NEIGHBOR parent)
66 PRPL_NODE rpl = GET_RPL_NODE(d);
67 if (!rpl->joined_dodag)
68 fnNetSimError(
"joined_dodag is null for %d device in %s\n", d, __FUNCTION__);
70 PRPL_DODAG dodag = rpl->joined_dodag;
72 dodag->parent_list = (PRPL_NEIGHBOR*)realloc(dodag->parent_list, (dodag->parent_count + 1) *
sizeof(PRPL_NEIGHBOR));
73 dodag->parent_list[dodag->parent_count++] = parent;
76PRPL_NEIGHBOR rpl_node_find_parent(NETSIM_ID d, NETSIM_ID parent)
78 PRPL_NODE drpl = GET_RPL_NODE(d);
79 if (drpl->joined_dodag == NULL)
82 PRPL_DODAG dodag = drpl->joined_dodag;
85 for (i = 0; i < dodag->parent_count; i++)
87 if (dodag->parent_list[i]->nodeId == parent)
88 return dodag->parent_list[i];
94void rpl_node_remove_all_parents(NETSIM_ID d)
96 PRPL_NODE rpl = GET_RPL_NODE(d);
98 for (i = 0; i < rpl->joined_dodag->parent_count; i++)
101 rpl->joined_dodag->parent_list[i] = NULL;
103 rpl->joined_dodag->parent_list = NULL;
104 rpl->joined_dodag->parent_count = 0;
107void forget_neighbor_messages(PRPL_NODE rpl)
110 for (i = 0; i < rpl->neighbor_count; i++)
112 PRPL_NEIGHBOR neighbor = rpl->neighbor_list[i];
114 if (neighbor->lastDIOMSG != NULL)
116 rpl_dio_pdu_free(neighbor->lastDIOMSG);
117 neighbor->lastDIOMSG = NULL;
122void rpl_node_add_sibling(NETSIM_ID d, PRPL_NEIGHBOR sibling)
124 PRPL_NODE rpl = GET_RPL_NODE(d);
126 if (!rpl->joined_dodag)
127 fnNetSimError(
"joined_dodag is null for %d in %s\n", d, __FUNCTION__);
129 PRPL_DODAG dodag = rpl->joined_dodag;
131 dodag->sibling_list = (PRPL_NEIGHBOR*)realloc(dodag->sibling_list, (dodag->sibling_count + 1) *
sizeof(PRPL_NEIGHBOR));
132 dodag->sibling_list[dodag->sibling_count++] = sibling;
135PRPL_NEIGHBOR rpl_node_find_sibling(NETSIM_ID d, NETSIM_ID sibling)
137 PRPL_NODE drpl = GET_RPL_NODE(d);
138 if (drpl->joined_dodag == NULL)
141 PRPL_DODAG dodag = drpl->joined_dodag;
144 for (i = 0; i < dodag->sibling_count; i++)
146 if (dodag->sibling_list[i]->nodeId == sibling)
147 return dodag->sibling_list[i];
153void rpl_node_remove_all_siblings(NETSIM_ID d)
155 PRPL_NODE rpl = GET_RPL_NODE(d);
156 if (!rpl->joined_dodag)
157 fnNetSimError(
"joined_dodag is null for %d device in %s\n", d, __FUNCTION__);
159 PRPL_DODAG dodag = rpl->joined_dodag;
161 if (dodag->sibling_list != NULL)
163 free(dodag->sibling_list);
164 dodag->sibling_list = NULL;
167 dodag->sibling_count = 0;
170static UINT16 compute_candidate_rank(NETSIM_ID d, PRPL_NEIGHBOR neighbor)
172 if (neighbor->nodeId == 0)
173 return INFINITE_RANK;
175 double send_link_quality = fn_NetSim_stack_get_link_quality(d, 1, neighbor->nodeId, 1);
176 double receive_link_quality = fn_NetSim_stack_get_link_quality(neighbor->nodeId, 1, d, 1);
177 double link_quality = (send_link_quality + receive_link_quality) / 2;
181 UINT16 rank = (UINT16)((RPL_MAXIMUM_RANK_INCREMENT - RPL_MINIMUM_RANK_INCREMENT) * pow((1 - link_quality), 2) + RPL_MINIMUM_RANK_INCREMENT);
183 PRPL_DIO_BASE Base = neighbor->lastDIOMSG->Base;
186 return rank > INFINITE_RANK ? INFINITE_RANK : rank;
189void choose_parents_and_siblings(NETSIM_ID d)
191 PRPL_NODE rpl = GET_RPL_NODE(d);
193 if (!rpl->joined_dodag)
194 fnNetSimError(
"joined_dodag is null for %d device in %s\n", d, __FUNCTION__);
196 PRPL_DODAG dodag = rpl->joined_dodag;
199 rpl_delete_all_route(d);
201 rpl_node_remove_all_parents(d);
202 rpl_node_remove_all_siblings(d);
204 INT16 best_rank_index = -1;
206 UINT16* matching_ranks = (UINT16*)calloc(rpl->neighbor_count,
sizeof* matching_ranks);
209 for (i = 0; i < rpl->neighbor_count; i++)
211 PRPL_NEIGHBOR neighbor = rpl->neighbor_list[i];
213 matching_ranks[i] = INFINITE_RANK;
215 if (neighbor->lastDIOMSG == NULL)
220 PRPL_DIO_BASE nBase = neighbor->lastDIOMSG->Base;
222 if (IP_COMPARE(nBase->DODAGID, dodag->dodag_id) != 0)
227 if (nBase->DTSN != dodag->seq_num)
232 if (nBase->Rank >= INFINITE_RANK)
237 if (nBase->Rank > dodag->rank)
239 rpl_dio_pdu_free(neighbor->lastDIOMSG);
240 neighbor->lastDIOMSG = NULL;
244 matching_ranks[i] = compute_candidate_rank(d, neighbor);
246 if (best_rank_index == -1)
252 if (matching_ranks[i] < matching_ranks[best_rank_index])
258 if (best_rank_index == -1)
260 print_rpl_log(
"node '%d': no valid neighbors left in dodag_id = '%s'", d, RPL_IP_TO_STR(dodag->dodag_id));
262 PRPL_CTRL_MSG preferred_dodag_pdu = get_preferred_dodag_dio_pdu(d, &same, pstruEventDetails->dEventTime);
264 if (preferred_dodag_pdu != NULL && !same)
266 join_dodag_iteration(d, preferred_dodag_pdu);
267 choose_parents_and_siblings(d);
271 start_dio_poisoning(d);
277 UINT16 best_rank = matching_ranks[best_rank_index];
278 if (best_rank - dodag->lowest_rank > dodag->max_rank_inc || best_rank >= INFINITE_RANK)
280 print_rpl_log(
"node '%d': in dodag_id = '%s', new rank (%d) would exceed the limit (%d + %d)",
281 d, RPL_IP_TO_STR(dodag->dodag_id), best_rank, dodag->lowest_rank, dodag->max_rank_inc);
283 if (rpl->joined_dodag->pref_parent != NULL &&
284 rpl->joined_dodag->pref_parent->lastDIOMSG != NULL &&
285 ((PRPL_DIO_BASE)rpl->joined_dodag->pref_parent->lastDIOMSG)->Rank < INFINITE_RANK)
288 print_rpl_log(
"node '%d': following parent on dodag_id = '%s'",
289 d, ((PRPL_DIO_BASE)rpl->joined_dodag->pref_parent->lastDIOMSG)->DODAGID);
291 join_dodag_iteration(d, rpl->joined_dodag->pref_parent->lastDIOMSG);
292 choose_parents_and_siblings(d);
296 print_rpl_log(
"node '%d': couldn't follow preferred parent, need to poison", d);
297 start_dio_poisoning(d);
302 dodag->rank = best_rank;
303 if (best_rank < dodag->lowest_rank)
304 dodag->lowest_rank = best_rank;
307 NETSIM_ID old_pref_parent = ((dodag->pref_parent == NULL) ? (0) : (dodag->pref_parent->nodeId));
308 dodag->pref_parent = rpl->neighbor_list[best_rank_index];
309 if (dodag->pref_parent->nodeId != old_pref_parent)
311 NetSim_EVENTDETAILS pevent;
312 memset(&pevent, 0,
sizeof pevent);
313 pevent.dEventTime = pstruEventDetails->dEventTime;
314 pevent.nDeviceId = d;
315 pevent.nDeviceType = DEVICE_TYPE(d);
316 pevent.nEventType = TIMER_EVENT;
317 pevent.nProtocolId = NW_PROTOCOL_RPL;
318 pevent.nSubEventType = RPL_NEW_PREF_PARENT;
319 fnpAddEvent(&pevent);
321 rpl_add_route_to_parent(d, dodag->pref_parent->nodeId);
323 for (i = 0; i < rpl->neighbor_count; i++)
325 PRPL_NEIGHBOR neighbor = rpl->neighbor_list[i];
327 if (matching_ranks[i] >= INFINITE_RANK)
329 if (neighbor->lastDIOMSG != NULL)
331 rpl_dio_pdu_free(neighbor->lastDIOMSG);
332 neighbor->lastDIOMSG = NULL;
337 PRPL_DIO_BASE dbase = neighbor->lastDIOMSG->Base;
339 if (dbase->Rank < best_rank)
341 rpl_node_add_parent(d, neighbor);
343 else if (dbase->Rank == best_rank)
345 rpl_node_add_sibling(d, neighbor);
349 if (neighbor->lastDIOMSG != NULL)
351 rpl_dio_pdu_free(neighbor->lastDIOMSG);
352 neighbor->lastDIOMSG = NULL;
359 char parent_list_str[256];
360 char sibling_list_str[256];
362 dodag = rpl->joined_dodag;
364 parent_list_str[0] =
'\0';
365 for (i = 0; i < dodag->parent_count; i++)
367 PRPL_NEIGHBOR neighbor = dodag->parent_list[i];
369 if (neighbor == dodag->pref_parent)
372 sprintf(sz,
"(%d)", neighbor->nodeId);
373 strcat(parent_list_str, sz);
378 sprintf(sz,
"%d", neighbor->nodeId);
379 strcat(parent_list_str, sz);
382 if (i < dodag->parent_count - 1)
384 strcat(parent_list_str,
", ");
388 sibling_list_str[0] =
'\0';
389 for (i = 0; i < dodag->sibling_count; i++)
391 PRPL_NEIGHBOR neighbor = dodag->sibling_list[i];
394 sprintf(sz,
"%d", neighbor->nodeId);
395 strcat(sibling_list_str, sz);
396 if (i < dodag->sibling_count - 1)
398 strcat(sibling_list_str,
", ");
401 print_rpl_log(
"node '%d': chosen parents and siblings in dodag_id = '%s': new rank = %d, parents = [%s], siblings = [%s]",
402 d, RPL_IP_TO_STR(dodag->dodag_id), dodag->rank, parent_list_str, sibling_list_str);
407void free_all_neighbor(PRPL_NODE rpl)
410 for (i = 0; i < rpl->neighbor_count; i++)
412 PRPL_NEIGHBOR n = rpl->neighbor_list[i];
415 rpl->neighbor_count = 0;