16#include "RPL_Message.h"
19static void rpl_dodag_config_option_destroy(PRPL_DODAG_CONFIG_OPTION opt);
20static PRPL_DODAG_CONFIG_OPTION rpl_dodag_config_option_copy(PRPL_DODAG_CONFIG_OPTION opt);
21static PRPL_TARGET_OPTION rpl_rpl_target_option_copy(PRPL_TARGET_OPTION target);
22static void rpl_rpl_target_option_destroy(PRPL_TARGET_OPTION target);
24static double get_rpl_packet_size_fixed(RPL_CTRL_MSG_CODE code)
28 case Destination_Advertisement_Object:
29 return RPL_CTRL_MSG_SIZE_FIXED + RPL_DAO_BASE_SIZE;
31 case Destination_Advertisement_Object_Acknowledgment:
32 return RPL_CTRL_MSG_SIZE_FIXED + RPL_DAOACK_BASE_SIZE;
34 case DODAG_Information_Object:
35 return RPL_CTRL_MSG_SIZE_FIXED + RPL_DIO_BASE_SIZE;
37 case DODAG_Information_Solicitation:
38 return RPL_CTRL_MSG_SIZE_FIXED + RPL_DIS_BASE_SIZE;
41 fnNetSimError(
"Unknow rpl msg code %d in %s\n", code, __FUNCTION__);
47static void set_option_in_msg(NetSim_PACKET* packet, RPL_OPTION_TYPE type,
void* option)
49 PRPL_CTRL_MSG msg = GET_PRPL_CTRL_MSG(packet);
50 if (msg->option_count)
51 msg->options = (PRPL_OPTION*)realloc(msg->options, (msg->option_count + 1) *
sizeof* msg->options);
53 msg->options = (PRPL_OPTION*)calloc(1,
sizeof* msg->options);
54 msg->options[msg->option_count] = (PRPL_OPTION)calloc(1,
sizeof* msg->options[msg->option_count]);
55 msg->options[msg->option_count]->option = option;
56 msg->options[msg->option_count]->type = type;
60void* get_option_from_msg(PRPL_CTRL_MSG msg, RPL_OPTION_TYPE type)
65 for (i = 0; i < msg->option_count; i++)
67 if (msg->options[i]->type == type)
68 return msg->options[i]->option;
73void** get_all_option_from_msg(PRPL_CTRL_MSG msg, RPL_OPTION_TYPE type, UINT* count)
83 for (i = 0; i < msg->option_count; i++)
85 if (msg->options[i]->type == type)
87 ret = (
void**)realloc(ret, (c + 1) *
sizeof(
void*));
88 ret[c] = msg->options[i]->option;
96void rpl_option_destroy(PRPL_OPTION option)
100 case RPLOPTION_DODAGConfiguration:
101 rpl_dodag_config_option_destroy(option->option);
103 case RPLOPTION_RPLTARGET:
104 rpl_rpl_target_option_destroy(option->option);
107 fnNetSimError(
"Unknown option %d in %s\n",
108 option->type, __FUNCTION__);
114PRPL_OPTION rpl_option_copy(PRPL_OPTION option)
116 PRPL_OPTION ret = (PRPL_OPTION)calloc(1,
sizeof* ret);
117 memcpy(ret, option,
sizeof* ret);
119 switch (option->type)
121 case RPLOPTION_DODAGConfiguration:
122 ret->option = rpl_dodag_config_option_copy(option->option);
124 case RPLOPTION_RPLTARGET:
125 ret->option = rpl_rpl_target_option_copy(option->option);
128 fnNetSimError(
"Unknown option %d in %s\n",
129 option->type, __FUNCTION__);
136static PRPL_CTRL_MSG get_icmp_rpl_msg(RPL_CTRL_MSG_CODE code)
138 PRPL_CTRL_MSG msg = (PRPL_CTRL_MSG)calloc(1,
sizeof* msg);
139 msg->Type = ICMP_TYPE_RPL;
144static void rpl_get_packet_type_sz(
char* str, RPL_CTRL_MSG_CODE code)
148 case Consistency_Check:
149 strcpy(str,
"Consistency_check");
151 case Destination_Advertisement_Object:
154 case Destination_Advertisement_Object_Acknowledgment:
155 strcpy(str,
"DAO-ACK");
157 case DODAG_Information_Object:
160 case DODAG_Information_Solicitation:
166static NetSim_PACKET* create_rpl_ctrl_msg(RPL_CTRL_MSG_CODE code,
171 NetSim_PACKET* packet = fn_NetSim_Packet_CreatePacket(NETWORK_LAYER);
172 packet->nPacketType = PacketType_Control;
173 packet->pstruNetworkData->dArrivalTime = time;
174 packet->pstruNetworkData->dOverhead = get_rpl_packet_size_fixed(code);
175 packet->pstruNetworkData->nRoutingProtocol = NW_PROTOCOL_RPL;
176 packet->pstruNetworkData->szSourceIP = IP_COPY(DEVICE_NWADDRESS(src, 1));
177 packet->pstruNetworkData->szGatewayIP = IP_COPY(DEVICE_NWADDRESS(src, 1));
179 packet->pstruNetworkData->szDestIP = IP_COPY(DEVICE_NWADDRESS(dest, 1));
181 packet->pstruNetworkData->szDestIP = GET_BROADCAST_IP(6);
182 packet->pstruNetworkData->nTTL = MAX_TTL;
183 packet->dEventTime = time;
184 packet->nControlDataType = GET_RPL_CTRL_PACKET_TYPE(code);
185 packet->nSourceId = src;
186 add_dest_to_packet(packet, dest);
187 packet->nTransmitterId = src;
189 rpl_get_packet_type_sz(packet->szPacketType, code);
191 packet->pstruNetworkData->Packet_RoutingProtocol = get_icmp_rpl_msg(code);
196static PRPL_DIO_BASE create_dio_base()
198 PRPL_DIO_BASE b = (PRPL_DIO_BASE)calloc(1,
sizeof* b);
199 b->Prf = RPL_DEFAULT_DAG_PREF;
200 b->Rank = INFINITE_RANK;
201 b->MOP = RPL_DEFAULT_MOP;
205static PRPL_DODAG_CONFIG_OPTION create_dodag_config_option()
207 PRPL_DODAG_CONFIG_OPTION o = (PRPL_DODAG_CONFIG_OPTION)calloc(1,
sizeof* o);
213static void rpl_dodag_config_option_destroy(PRPL_DODAG_CONFIG_OPTION opt)
218static PRPL_DODAG_CONFIG_OPTION rpl_dodag_config_option_copy(PRPL_DODAG_CONFIG_OPTION opt)
220 PRPL_DODAG_CONFIG_OPTION ret = (PRPL_DODAG_CONFIG_OPTION)calloc(1,
sizeof* ret);
221 memcpy(ret, opt,
sizeof* ret);
225NetSim_PACKET* create_root_dio_message(NETSIM_ID ndevId,
double time,
bool include_dodag_config,
bool include_seq_num)
227 PRPL_NODE r = GET_RPL_NODE(ndevId);
229 NetSim_PACKET* packet = create_rpl_ctrl_msg(DODAG_Information_Object, time, ndevId, 0);
230 PRPL_DIO_BASE diobase = create_dio_base();
231 SET_BASE_IN_MSG(packet, diobase);
233 if (r->root_info->dodag_id != NULL)
234 diobase->DODAGID = IP_COPY(r->root_info->dodag_id);
236 diobase->DODAGID = IP_COPY(DEVICE_NWADDRESS(ndevId,1));
238 diobase->Prf = r->root_info->dodag_pref;
239 diobase->Rank = RPL_RANK_ROOT;
240 diobase->G = r->root_info->grounded;
243 diobase->DTSN = seq_num_mapping_get(diobase->DODAGID)->seq_num;
246 diobase->RPLInstanceID = r->RPLInstanceId;
248 if (include_dodag_config)
250 PRPL_DODAG_CONFIG_OPTION opt = create_dodag_config_option();
251 set_option_in_msg(packet, RPLOPTION_DODAGConfiguration ,opt);
253 opt->DIOIntDoubl = r->root_info->dio_interval_doublings;
254 opt->DIOIntMin = r->root_info->dio_interval_min;
255 opt->DIORedun = r->root_info->dio_redundancy_constant;
256 opt->MaxRankIncrease = r->root_info->max_rank_inc;
257 opt->MinHopRankIncrease = r->root_info->min_hop_rank_inc;
263static NetSim_PACKET* create_joined_dio_message(NETSIM_ID ndevId,
double time,
bool include_dodag_config)
265 PRPL_NODE r = GET_RPL_NODE(ndevId);
267 NetSim_PACKET* packet = create_rpl_ctrl_msg(DODAG_Information_Object, time, ndevId, 0);
268 PRPL_DIO_BASE diobase = create_dio_base();
269 SET_BASE_IN_MSG(packet, diobase);
271 diobase->DODAGID = r->joined_dodag->dodag_id;
272 diobase->Prf = r->joined_dodag->dodag_pref;
273 diobase->Rank = r->joined_dodag->rank;
274 diobase->G = r->joined_dodag->grounded;
275 diobase->DTSN = r->joined_dodag->seq_num;
276 diobase->RPLInstanceID = r->RPLInstanceId;
278 if (include_dodag_config)
280 PRPL_DODAG_CONFIG_OPTION opt = create_dodag_config_option();
281 set_option_in_msg(packet, RPLOPTION_DODAGConfiguration, opt);
283 opt->DIOIntDoubl = r->joined_dodag->dio_interval_doublings;
284 opt->DIOIntMin = r->joined_dodag->dio_interval_min;
285 opt->DIORedun = r->joined_dodag->dio_redundancy_constant;
286 opt->MaxRankIncrease = r->joined_dodag->max_rank_inc;
287 opt->MinHopRankIncrease = r->joined_dodag->min_hop_rank_inc;
293NetSim_PACKET* create_current_dio_message(NETSIM_ID ndevId,
double time,
bool include_dodag_config)
295 PRPL_NODE r = GET_RPL_NODE(ndevId);
296 if (rpl_node_is_joined(r))
298 return create_joined_dio_message(ndevId, time, include_dodag_config);
300 else if (rpl_node_is_root(r))
302 return create_root_dio_message(ndevId, time, include_dodag_config, TRUE);
304 else if (rpl_node_is_poisoning(r))
306 return create_joined_dio_message(ndevId, time, include_dodag_config);
314PRPL_CTRL_MSG rpl_dio_pdu_duplicate(PRPL_CTRL_MSG dio)
316 PRPL_CTRL_MSG new_dio = (PRPL_CTRL_MSG)calloc(1,
sizeof* new_dio);
317 memcpy(new_dio, dio,
sizeof* new_dio);
319 PRPL_DIO_BASE new_base = (PRPL_DIO_BASE)calloc(1,
sizeof* new_base);
320 new_dio->Base = new_base;
321 memcpy(new_base, dio->Base,
sizeof* new_base);
323 new_dio->options = (PRPL_OPTION*)calloc(dio->option_count,
sizeof* new_dio->options);
325 for (i = 0; i < dio->option_count; i++)
327 new_dio->options[i] = (PRPL_OPTION)calloc(1,
sizeof* new_dio->options[i]);
328 new_dio->options[i]->type = dio->options[i]->type;
329 switch (new_dio->options[i]->type)
331 case RPLOPTION_DODAGConfiguration:
332 new_dio->options[i]->option = calloc(1,
sizeof(RPL_DODAG_CONFIG_OPTION));
333 memcpy(new_dio->options[i]->option, dio->options[i]->option,
sizeof(RPL_DODAG_CONFIG_OPTION));
336 fnNetSimError(
"Unknown option %d in %s\n", new_dio->options[i]->type, __FUNCTION__);
343void rpl_dio_pdu_free(PRPL_CTRL_MSG dio)
347 IP_FREE(((PRPL_DIO_BASE)dio->Base)->DODAGID);
348 free((PRPL_DIO_BASE)dio->Base);
350 for (i = 0; i < dio->option_count; i++)
352 free((PRPL_DODAG_CONFIG_OPTION)dio->options[i]->option);
353 free(dio->options[i]);
360static PRPL_DAO_BASE create_dao_base(PRPL_NODE rpl)
362 PRPL_DAO_BASE b = (PRPL_DAO_BASE)calloc(1,
sizeof* b);
363 b->RPLInstanceID = rpl->RPLInstanceId;
366 b->DAOSequence = ++rpl->DaoSequence;
370NetSim_PACKET* create_dao_message(NETSIM_ID ndevid,
double time,NETSIM_ID parent)
372 PRPL_NODE rpl = GET_RPL_NODE(ndevid);
373 NetSim_PACKET* packet = create_rpl_ctrl_msg(Destination_Advertisement_Object, time, ndevid, parent);
374 PRPL_DAO_BASE dao = create_dao_base(rpl);
375 SET_BASE_IN_MSG(packet, dao);
379void create_and_add_rpl_target_option(NetSim_PACKET* dao_pdu, UINT8 prefix_len, NETSIM_IPAddress dest)
381 PRPL_TARGET_OPTION target = (PRPL_TARGET_OPTION)calloc(1,
sizeof* target);
382 target->Type = RPLOPTION_RPLTARGET;
383 target->Option_Length = 18;
384 target->Prefix_Length = prefix_len;
385 target->Traget_Prefix = IP_COPY(dest);
386 set_option_in_msg(dao_pdu, RPLOPTION_RPLTARGET, target);
389static PRPL_TARGET_OPTION rpl_rpl_target_option_copy(PRPL_TARGET_OPTION target)
391 PRPL_TARGET_OPTION ret = (PRPL_TARGET_OPTION)calloc(1,
sizeof* ret);
392 memcpy(ret, target,
sizeof* ret);
396static void rpl_rpl_target_option_destroy(PRPL_TARGET_OPTION target)
402static PRPL_DIS_BASE create_dis_base(PRPL_NODE rpl)
404 PRPL_DIS_BASE b = (PRPL_DIS_BASE)calloc(1,
sizeof* b);
408NetSim_PACKET* create_dis_message(NETSIM_ID ndevid,
double time)
410 PRPL_NODE rpl = GET_RPL_NODE(ndevid);
411 NetSim_PACKET* packet = create_rpl_ctrl_msg(DODAG_Information_Solicitation, time, ndevid, 0);
412 PRPL_DIS_BASE dis = create_dis_base(rpl);
413 SET_BASE_IN_MSG(packet, dis);
418void rpl_node_send_msg(NETSIM_ID ndevid, NetSim_PACKET* packet)
420 NetSim_EVENTDETAILS pevent;
421 memset(&pevent, 0,
sizeof pevent);
422 pevent.dEventTime = pstruEventDetails->dEventTime;
423 pevent.dPacketSize = fnGetPacketSize(packet);
424 pevent.nDeviceId = ndevid;
425 pevent.nDeviceType = DEVICE_TYPE(ndevid);
426 pevent.nEventType = NETWORK_OUT_EVENT;
427 pevent.nPacketId = packet->nPacketId;
428 pevent.nProtocolId = NW_PROTOCOL_IPV6;
429 pevent.pPacket = packet;
430 fnpAddEvent(&pevent);
433void rpl_process_ctrl_msg()
435 switch (pstruEventDetails->pPacket->nControlDataType % 100)
437 case DODAG_Information_Object:
438 rpl_process_dio_msg();
440 case Destination_Advertisement_Object:
441 rpl_process_dao_msg();
443 case DODAG_Information_Solicitation:
444 rpl_process_dis_msg();
447 fnNetSimError(
"Unknown rpl ctrl msg %d in %s",
448 pstruEventDetails->pPacket->nControlDataType,