16#include "RPL_Message.h"
18static bool dio_pdu_dodag_config_changed(PRPL_CTRL_MSG c1, PRPL_CTRL_MSG c2)
20 PRPL_DODAG_CONFIG_OPTION d1 = get_option_from_msg(c1, RPLOPTION_DODAGConfiguration);
21 PRPL_DODAG_CONFIG_OPTION d2 = get_option_from_msg(c2, RPLOPTION_DODAGConfiguration);
29 return memcmp(d1, d2,
sizeof* d1);
32static bool dio_pdu_changed(PRPL_NEIGHBOR neighbor, PRPL_CTRL_MSG dio_pdu)
34 if (neighbor->lastDIOMSG == NULL)
40 PRPL_CTRL_MSG msg = dio_pdu;
41 PRPL_DIO_BASE b = msg->Base;
42 PRPL_DIO_BASE lb = ((PRPL_CTRL_MSG)neighbor->lastDIOMSG)->Base;
44 bool base_changed = (IP_COMPARE(lb->DODAGID, b->DODAGID)) ||
45 (lb->Prf != b->Prf) ||
46 (lb->DTSN != b->DTSN) ||
47 (lb->Rank != b->Rank) ||
49 (lb->MOP != b->MOP) ||
50 (lb->RPLInstanceID != b->RPLInstanceID) ||
51 (lb->Version_Number != b->Version_Number);
53 bool dodag_config_changed = dio_pdu_dodag_config_changed(neighbor->lastDIOMSG,
56 return base_changed || dodag_config_changed;
60void start_dio_poisoning(NETSIM_ID d)
62 PRPL_NODE rpl = GET_RPL_NODE(d);
64 rpl_delete_all_route(d);
66 rpl_node_remove_all_parents(d);
67 rpl->joined_dodag->pref_parent = NULL;
69 forget_neighbor_messages(rpl);
71 rpl->joined_dodag->rank = INFINITE_RANK;
72 rpl->joined_dodag->lowest_rank = INFINITE_RANK;
73 rpl->poison_count_so_far = 0;
78PRPL_CTRL_MSG get_preferred_dodag_dio_pdu(NETSIM_ID d,
bool *same,
double time)
80 PRPL_NODE rpl = GET_RPL_NODE(d);
81 NetSim_PACKET* root_packet = create_root_dio_message(d, time, FALSE, FALSE);
82 PRPL_CTRL_MSG root_dio_pdu = root_packet->pstruNetworkData->Packet_RoutingProtocol;
83 PRPL_CTRL_MSG best_dio_pdu = root_dio_pdu;
84 PRPL_DIO_BASE best_dio_base = root_dio_pdu->Base;
85 root_packet->pstruNetworkData->Packet_RoutingProtocol = NULL;
86 fn_NetSim_Packet_FreePacket(root_packet);
88 PRPL_NEIGHBOR old_pref_parent = rpl_node_is_joined(rpl) ? rpl->joined_dodag->pref_parent : NULL;
91 for (i = 0; i < rpl->neighbor_count; i++)
93 PRPL_NEIGHBOR neighbor = rpl->neighbor_list[i];
95 if (neighbor->lastDIOMSG == NULL)
100 PRPL_OPTION dodag_config_suboption = get_option_from_msg(neighbor->lastDIOMSG,RPLOPTION_DODAGConfiguration);
101 if (dodag_config_suboption == NULL)
105 PRPL_DIO_BASE diobase = neighbor->lastDIOMSG->Base;
107 if (diobase->Rank >= INFINITE_RANK)
112 if (rpl_node_is_joined(rpl) &&
113 IP_COMPARE(diobase->DODAGID, rpl->joined_dodag->dodag_id) == 0 &&
114 diobase->Rank >= rpl->joined_dodag->rank)
120 if (!best_dio_base->G && diobase->G)
122 best_dio_pdu = neighbor->lastDIOMSG;
123 best_dio_base = best_dio_pdu->Base;
125 else if (best_dio_base->G == diobase->G)
127 if (best_dio_base->Prf < diobase->Prf)
129 best_dio_pdu = neighbor->lastDIOMSG;
130 best_dio_base = best_dio_pdu->Base;
132 else if (best_dio_base->Prf == diobase->Prf)
134 if (best_dio_base->DTSN < diobase->DTSN)
136 best_dio_pdu = neighbor->lastDIOMSG;
137 best_dio_base = best_dio_pdu->Base;
143 if (best_dio_pdu != root_dio_pdu)
145 rpl_dio_pdu_free(root_dio_pdu);
147 if (rpl_node_is_joined(rpl) || rpl_node_is_poisoning(rpl))
149 *same = (IP_COMPARE(rpl->joined_dodag->dodag_id, best_dio_base->DODAGID) == 0) &&
150 (rpl->joined_dodag->seq_num == best_dio_base->DTSN);
160 print_rpl_log(
"node '%d': no preferable DODAG iterations around", d);
163 if (old_pref_parent != NULL &&
164 old_pref_parent->lastDIOMSG != NULL)
166 PRPL_DIO_BASE diobase = old_pref_parent->lastDIOMSG->Base;
167 if (diobase->G == best_dio_base->G &&
168 diobase->Prf == best_dio_base->Prf)
170 *same = ((IP_COMPARE(rpl->joined_dodag->dodag_id, diobase->DODAGID) == 0) &&
171 rpl->joined_dodag->seq_num == diobase->DTSN);
173 best_dio_pdu = old_pref_parent->lastDIOMSG;
174 best_dio_base = best_dio_pdu->Base;
176 rpl_dio_pdu_free(root_dio_pdu);
182 rpl_dio_pdu_free(root_dio_pdu);
184 *same = rpl_node_is_root(rpl);
191void rpl_process_dio_msg()
193 NETSIM_ID d = pstruEventDetails->nDeviceId;
194 PRPL_CTRL_MSG dioPdu = GET_PRPL_CTRL_MSG(pstruEventDetails->pPacket);
195 NETSIM_ID r = pstruEventDetails->pPacket->nTransmitterId;
196 PRPL_NODE drpl = GET_RPL_NODE(d);
197 PRPL_NODE rrpl = GET_RPL_NODE(r);
198 PRPL_DIO_BASE diobase = dioPdu->Base;
200 PRPL_NEIGHBOR neighbor = rpl_find_neighbor(d, r);
202 if (dio_pdu_changed(neighbor, dioPdu))
206 if (rpl_node_is_joined(drpl))
208 if (IP_COMPARE(drpl->joined_dodag->dodag_id, diobase->DODAGID) == 0 &&
209 drpl->joined_dodag->rank < diobase->Rank &&
210 !rpl_node_has_parent(d, r) &&
211 !rpl_node_has_sibling(d, r))
214 neighbor->lastDIOMSG = NULL;
218 else if (rpl_node_is_root(drpl))
220 if (IP_COMPARE(drpl->root_info->dodag_id, diobase->DODAGID) == 0)
223 neighbor->lastDIOMSG = NULL;
228 print_rpl_log(
"node '%d': received a new/modified message from node '%d' with dodag_id = '%s'",
229 d, r, RPL_IP_TO_STR(diobase->DODAGID));
232 bool dodag_config_changed = dio_pdu_dodag_config_changed(neighbor->lastDIOMSG, dioPdu);
234 update_neighbor_dio_message(neighbor, dioPdu);
239 if (rpl_node_is_joined(drpl))
241 if ((drpl->joined_dodag->pref_parent == neighbor) &&
242 (((PRPL_DIO_BASE)neighbor->lastDIOMSG->Base)->Rank == INFINITE_RANK))
244 start_dio_poisoning(d);
252 PRPL_CTRL_MSG preferred_dodag_pdu = get_preferred_dodag_dio_pdu(d, &same, pstruEventDetails->dEventTime);
254 if (rpl_node_is_isolated(drpl))
256 if (preferred_dodag_pdu != NULL)
258 PRPL_DIO_BASE b = preferred_dodag_pdu->Base;
259 print_rpl_log(
"node '%d': was isolated, now found dodag_id = '%s'",
260 d, RPL_IP_TO_STR(b->DODAGID));
261 join_dodag_iteration(d, preferred_dodag_pdu);
262 choose_parents_and_siblings(d);
269 else if (rpl_node_is_root(drpl))
271 if (preferred_dodag_pdu != NULL)
273 PRPL_DIO_BASE b = preferred_dodag_pdu->Base;
274 print_rpl_log(
"node '%d': was root of dodag_id = '%s', now found a better one with dodag_id = '%s'",
275 d, drpl->root_info->dodag_id, b->DODAGID);
277 join_dodag_iteration(d, preferred_dodag_pdu);
278 choose_parents_and_siblings(d);
285 else if (rpl_node_is_poisoning(drpl))
289 else if (rpl_node_is_joined(drpl))
293 if (preferred_dodag_pdu != NULL)
295 PRPL_DIO_BASE b = preferred_dodag_pdu->Base;
296 print_rpl_log(
"node '%d': was member of dodag_id = '%s', now found a better one with dodag_id = '%s'",
297 d, drpl->joined_dodag->dodag_id, b->DODAGID);
299 join_dodag_iteration(d, preferred_dodag_pdu);
300 choose_parents_and_siblings(d);
304 print_rpl_log(
"node '%d': was member of dodag_id = '%s', now starting own root",
305 d, drpl->joined_dodag->dodag_id);
311 PRPL_DIO_BASE dbase = neighbor->lastDIOMSG->Base;
313 if (IP_COMPARE(dbase->DODAGID, drpl->joined_dodag->dodag_id) == 0)
315 print_rpl_log(
"node '%d': '%d' sent a modified DIO message and is a member of dodag_id = '%s', reevaluating our neighbors",
316 d, r, RPL_IP_TO_STR(drpl->joined_dodag->dodag_id));
318 choose_parents_and_siblings(d);
322 print_rpl_log(
"node '%d': remaining in dodag_id = '%s'", d, RPL_IP_TO_STR(drpl->joined_dodag->dodag_id));
326 if (dodag_config_changed && rpl_node_has_parent(d, r))
328 update_dodag_config(d, dioPdu);
334 fnNetSimError(
"node '%d': not root, not joined, not poisoning and not isolated either, what are we anyway?", d);
339void rpl_dio_msg_copy(
const NetSim_PACKET* destPacket,
const NetSim_PACKET* srcPacket)
341 PRPL_CTRL_MSG srpl = srcPacket->pstruNetworkData->Packet_RoutingProtocol;
342 PRPL_CTRL_MSG drpl = rpl_dio_pdu_duplicate(srpl);
343 destPacket->pstruNetworkData->Packet_RoutingProtocol = drpl;
346void rpl_dio_msg_destroy(NetSim_PACKET* packet)
348 PRPL_CTRL_MSG srpl = packet->pstruNetworkData->Packet_RoutingProtocol;
349 rpl_dio_pdu_free(srpl);
350 packet->pstruNetworkData->Packet_RoutingProtocol = NULL;