NetSim Source Code Help v14.4
All 13 Components
 
Loading...
Searching...
No Matches
DIO.c
1/************************************************************************************
2* Copyright (C) 2023 *
3* TETCOS, Bangalore. India *
4* *
5* Tetcos owns the intellectual property rights in the Product and its content. *
6* The copying, redistribution, reselling or publication of any or all of the *
7* Product or its content without express prior written consent of Tetcos is *
8* prohibited. Ownership and / or any other right relating to the software and all *
9* intellectual property rights therein shall remain at all times with Tetcos. *
10* *
11* Author: Shashi Kant Suman *
12* *
13* ---------------------------------------------------------------------------------*/
14#include "main.h"
15#include "RPL.h"
16#include "RPL_Message.h"
17
18static bool dio_pdu_dodag_config_changed(PRPL_CTRL_MSG c1, PRPL_CTRL_MSG c2)
19{
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);
22
23 if (!d2)
24 return FALSE;
25
26 if (!d1)
27 return true;
28
29 return memcmp(d1, d2, sizeof* d1);
30}
31
32static bool dio_pdu_changed(PRPL_NEIGHBOR neighbor, PRPL_CTRL_MSG dio_pdu)
33{
34 if (neighbor->lastDIOMSG == NULL)
35 {
36 return TRUE;
37 }
38 else
39 {
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;
43
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) ||
48 (lb->G != b->G) ||
49 (lb->MOP != b->MOP) ||
50 (lb->RPLInstanceID != b->RPLInstanceID) ||
51 (lb->Version_Number != b->Version_Number);
52
53 bool dodag_config_changed = dio_pdu_dodag_config_changed(neighbor->lastDIOMSG,
54 msg);
55
56 return base_changed || dodag_config_changed;
57 }
58}
59
60void start_dio_poisoning(NETSIM_ID d)
61{
62 PRPL_NODE rpl = GET_RPL_NODE(d);
63 /* forget about all DIO routes */
64 rpl_delete_all_route(d);
65
66 rpl_node_remove_all_parents(d);
67 rpl->joined_dodag->pref_parent = NULL;
68
69 forget_neighbor_messages(rpl);
70
71 rpl->joined_dodag->rank = INFINITE_RANK;
72 rpl->joined_dodag->lowest_rank = INFINITE_RANK;
73 rpl->poison_count_so_far = 0;
74
75 rpl_trickle_reset(d);
76}
77
78PRPL_CTRL_MSG get_preferred_dodag_dio_pdu(NETSIM_ID d, bool *same,double time)
79{
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);
87
88 PRPL_NEIGHBOR old_pref_parent = rpl_node_is_joined(rpl) ? rpl->joined_dodag->pref_parent : NULL;
89
90 UINT16 i;
91 for (i = 0; i < rpl->neighbor_count; i++)
92 {
93 PRPL_NEIGHBOR neighbor = rpl->neighbor_list[i];
94
95 if (neighbor->lastDIOMSG == NULL)
96 { /* ignore neighbors who haven't sent any DIO */
97 continue;
98 }
99
100 PRPL_OPTION dodag_config_suboption = get_option_from_msg(neighbor->lastDIOMSG,RPLOPTION_DODAGConfiguration);
101 if (dodag_config_suboption == NULL)
102 { /* ignore neighbors for whom no DODAG config info is available */
103 continue;
104 }
105 PRPL_DIO_BASE diobase = neighbor->lastDIOMSG->Base;
106
107 if (diobase->Rank >= INFINITE_RANK)
108 { /* ignore neighbors that started poisoning */
109 continue;
110 }
111
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)
115 { /* ignore neighbors of our DODAG with greater or equal rank */
116
117 continue;
118 }
119
120 if (!best_dio_base->G && diobase->G)
121 {
122 best_dio_pdu = neighbor->lastDIOMSG;
123 best_dio_base = best_dio_pdu->Base;
124 }
125 else if (best_dio_base->G == diobase->G)
126 {
127 if (best_dio_base->Prf < diobase->Prf)
128 {
129 best_dio_pdu = neighbor->lastDIOMSG;
130 best_dio_base = best_dio_pdu->Base;
131 }
132 else if (best_dio_base->Prf == diobase->Prf)
133 {
134 if (best_dio_base->DTSN < diobase->DTSN)
135 {
136 best_dio_pdu = neighbor->lastDIOMSG;
137 best_dio_base = best_dio_pdu->Base;
138 }
139 }
140 }
141 }
142
143 if (best_dio_pdu != root_dio_pdu)
144 {
145 rpl_dio_pdu_free(root_dio_pdu);
146
147 if (rpl_node_is_joined(rpl) || rpl_node_is_poisoning(rpl))
148 {
149 *same = (IP_COMPARE(rpl->joined_dodag->dodag_id, best_dio_base->DODAGID) == 0) &&
150 (rpl->joined_dodag->seq_num == best_dio_base->DTSN);
151 }
152 else
153 {
154 *same = FALSE;
155 }
156 return best_dio_pdu;
157 }
158 else
159 {
160 print_rpl_log("node '%d': no preferable DODAG iterations around", d);
161 /* give priority to the former parent, to follow him if necessary */
162
163 if (old_pref_parent != NULL &&
164 old_pref_parent->lastDIOMSG != NULL)
165 {
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)
169 {
170 *same = ((IP_COMPARE(rpl->joined_dodag->dodag_id, diobase->DODAGID) == 0) &&
171 rpl->joined_dodag->seq_num == diobase->DTSN);
172
173 best_dio_pdu = old_pref_parent->lastDIOMSG;
174 best_dio_base = best_dio_pdu->Base;
175
176 rpl_dio_pdu_free(root_dio_pdu);
177 return best_dio_pdu;
178 }
179 }
180 else
181 {
182 rpl_dio_pdu_free(root_dio_pdu);
183
184 *same = rpl_node_is_root(rpl);
185 return NULL;
186 }
187 }
188 return NULL;
189}
190
191void rpl_process_dio_msg()
192{
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;
199
200 PRPL_NEIGHBOR neighbor = rpl_find_neighbor(d, r);
201
202 if (dio_pdu_changed(neighbor, dioPdu))
203 {
204
205 /* ignore messages from members of our DODAG which are neither parents nor siblings and emit a greater rank than us */
206 if (rpl_node_is_joined(drpl))
207 {
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))
212 {
213
214 neighbor->lastDIOMSG = NULL; /* make sure we "forgot" the last message for this neighbor */
215 return;
216 }
217 }
218 else if (rpl_node_is_root(drpl))
219 {
220 if (IP_COMPARE(drpl->root_info->dodag_id, diobase->DODAGID) == 0)
221 {
222
223 neighbor->lastDIOMSG = NULL; /* make sure we "forgot" the last message for this */
224 return;
225 }
226 }
227
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));
230
231
232 bool dodag_config_changed = dio_pdu_dodag_config_changed(neighbor->lastDIOMSG, dioPdu);
233
234 update_neighbor_dio_message(neighbor, dioPdu);
235
236 /*
237 * If we get poison from the preferred parent, we propagate the poisoning mechanism
238 */
239 if (rpl_node_is_joined(drpl))
240 {
241 if ((drpl->joined_dodag->pref_parent == neighbor) &&
242 (((PRPL_DIO_BASE)neighbor->lastDIOMSG->Base)->Rank == INFINITE_RANK))
243 {
244 start_dio_poisoning(d);
245 return;
246 }
247 }
248 /* end of poisoning procedure */
249
250
251 bool same;
252 PRPL_CTRL_MSG preferred_dodag_pdu = get_preferred_dodag_dio_pdu(d, &same, pstruEventDetails->dEventTime);
253
254 if (rpl_node_is_isolated(drpl))
255 {
256 if (preferred_dodag_pdu != NULL)
257 {
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);
263 }
264 else
265 {
266 /* don't start as root, since we were configured to start as isolated */
267 }
268 }
269 else if (rpl_node_is_root(drpl))
270 {
271 if (preferred_dodag_pdu != NULL)
272 {
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);
276
277 join_dodag_iteration(d, preferred_dodag_pdu);
278 choose_parents_and_siblings(d);
279 }
280 else
281 {
282 /* we're already root */
283 }
284 }
285 else if (rpl_node_is_poisoning(drpl))
286 {
287 /* we ignore everything in this temporary state */
288 }
289 else if (rpl_node_is_joined(drpl))
290 {
291 if (!same)
292 {
293 if (preferred_dodag_pdu != NULL)
294 {
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);
298
299 join_dodag_iteration(d, preferred_dodag_pdu);
300 choose_parents_and_siblings(d);
301 }
302 else
303 {
304 print_rpl_log("node '%d': was member of dodag_id = '%s', now starting own root",
305 d, drpl->joined_dodag->dodag_id);
306 start_as_root(d);
307 }
308 }
309 else
310 {
311 PRPL_DIO_BASE dbase = neighbor->lastDIOMSG->Base;
312 /* a new member of our DODAG is a potential parent/sibling, need to reevaluate our neighbors */
313 if (IP_COMPARE(dbase->DODAGID, drpl->joined_dodag->dodag_id) == 0)
314 {
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));
317
318 choose_parents_and_siblings(d);
319 }
320 else
321 {
322 print_rpl_log("node '%d': remaining in dodag_id = '%s'", d, RPL_IP_TO_STR(drpl->joined_dodag->dodag_id));
323 }
324
325 /* consider dodag config updates, but only from parents */
326 if (dodag_config_changed && rpl_node_has_parent(d, r))
327 {
328 update_dodag_config(d, dioPdu);
329 }
330 }
331 }
332 else
333 { /* this should never happen */
334 fnNetSimError("node '%d': not root, not joined, not poisoning and not isolated either, what are we anyway?", d);
335 }
336 }
337}
338
339void rpl_dio_msg_copy(const NetSim_PACKET* destPacket, const NetSim_PACKET* srcPacket)
340{
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;
344}
345
346void rpl_dio_msg_destroy(NetSim_PACKET* packet)
347{
348 PRPL_CTRL_MSG srpl = packet->pstruNetworkData->Packet_RoutingProtocol;
349 rpl_dio_pdu_free(srpl);
350 packet->pstruNetworkData->Packet_RoutingProtocol = NULL;
351}