DESERT 3.5.1
Loading...
Searching...
No Matches
uwicrp-module-node.cpp
Go to the documentation of this file.
1//
2// Copyright (c) 2017 Regents of the SIGNET lab, University of Padova.
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions
7// are met:
8// 1. Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10// 2. Redistributions in binary form must reproduce the above copyright
11// notice, this list of conditions and the following disclaimer in the
12// documentation and/or other materials provided with the distribution.
13// 3. Neither the name of the University of Padova (SIGNET lab) nor the
14// names of its contributors may be used to endorse or promote products
15// derived from this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28//
29
40#include "uwicrp-module-node.h"
41
42extern packet_t PT_UWICRP_ACK;
43extern packet_t PT_UWICRP_STATUS;
44extern packet_t PT_UWICRP_DATA;
45
49static class UwIcrpNodeModuleClass : public TclClass
50{
51public:
53 : TclClass("Module/UW/ICRPNode")
54 {
55 }
56
57 TclObject *
58 create(int, const char *const *)
59 {
60 return (new UwIcrpNode());
61 }
63
67
68void
70{
71 module->ackLost();
72} /* AckWaiting::expire */
73
75 : ipAddr_(0)
76 , printDebug_(0)
77 , timer_ack_waiting_(10)
78 , ackwaitingTmr_(this)
79{
80 bind("printDebug_", &printDebug_);
81 bind("maxvaliditytime_", &max_validity_time_);
82 bind("timer_ack_waiting_", &timer_ack_waiting_);
84 cout.precision(2);
85 cout.setf(ios::floatfield, ios::fixed);
86 for (int i = 0; i < HOP_TABLE_LENGTH; i++) {
88 route_table[i].hopcount = INT_MAX;
90 route_table[i].next_hop = -1;
91 route_table[i].isValid = false;
92 }
93}
94
98
99int
101{
102 return Module::recvSyncClMsg(m);
103}
104
105int
107{
108 if (m->type() == UWIP_CLMSG_SEND_ADDR) {
110 ipAddr_ = m_->getAddr();
111 }
112 return Module::recvAsyncClMsg(m);
113}
114
115void
117{
118 if (ipAddr_ == 0) {
119 UWIPClMsgReqAddr *m = new UWIPClMsgReqAddr(getId());
120 sendSyncClMsgDown(m);
121 }
122}
123
124void
126{
127 if (i < HOP_TABLE_LENGTH) {
129 route_table[i].hopcount = INT_MAX;
131 route_table[i].next_hop = -1;
132 route_table[i].isValid = false;
133 }
134}
135
136void
138{
139 for (int i = 0; i < HOP_TABLE_LENGTH; i++) {
141 route_table[i].hopcount = INT_MAX;
143 route_table[i].next_hop = -1;
144 route_table[i].isValid = false;
145 }
146}
147
148int
149UwIcrpNode::command(int argc, const char *const *argv)
150{
151 Tcl &tcl = Tcl::instance();
152
153 if (argc == 2) {
154 if (strcasecmp(argv[1], "initialize") == 0) {
155 this->initialize();
156 return TCL_OK;
157 } else if (strcasecmp(argv[1], "clearhops") == 0) {
158 this->clearAllRouteTable();
159 return TCL_OK;
160 } else if (strcasecmp(argv[1], "printhops") == 0) {
161 this->printHopTable();
162 return TCL_OK;
163 } else if (strcasecmp(argv[1], "getackheadersize") == 0) {
164 tcl.resultf("%d", this->getAckPktHeaderSize());
165 return TCL_OK;
166 } else if (strcasecmp(argv[1], "getdataheadersize") == 0) {
167 tcl.resultf("%d", this->getDataPktHeaderSize());
168 return TCL_OK;
169 } else if (strcasecmp(argv[1], "getstatusheadersize") == 0) {
170 tcl.resultf("%d", this->getStatusPktHeaderSize());
171 return TCL_OK;
172 } else if (strcasecmp(argv[1], "getackpktcount") == 0) {
173 tcl.resultf("%lu", numberofackpkt_);
174 return TCL_OK;
175 } else if (strcasecmp(argv[1], "getdatapktcount") == 0) {
176 tcl.resultf("%lu", numberofdatapkt_);
177 return TCL_OK;
178 } else if (strcasecmp(argv[1], "getstatuspktcount") == 0) {
179 tcl.resultf("%lu", numberofstatuspkt_);
180 return TCL_OK;
181 }
182 } else if (argc == 3) {
183 if (strcasecmp(argv[1], "ipsink") == 0) {
184 ipSink_ = static_cast<uint8_t>(atoi(argv[2]));
185 if (ipSink_ == 0) {
186 fprintf(stderr, "0 is not a valid IP address");
187 return TCL_ERROR;
188 }
189 if (printDebug_)
190 cout << "-> Node linked with Sink: " << printIP(ipSink_)
191 << endl;
192 return TCL_OK;
193 } else if (strcasecmp(argv[1], "addr") == 0) {
194 ipAddr_ = static_cast<uint8_t>(atoi(argv[2]));
195 return TCL_OK;
196 if (ipAddr_ == 0) {
197 fprintf(stderr, "0 is not a valid IP address");
198 return TCL_ERROR;
199 }
200 return TCL_OK;
201 }
202 }
203 return Module::command(argc, argv);
204}
205
206void
208{
209 hdr_cmn *ch = HDR_CMN(p);
210 hdr_uwip *iph = HDR_UWIP(p);
211 hdr_uwicrp_data *icrp_datah;
212 hdr_uwicrp_status *icrp_statush;
213
214 if (!ch->error()) {
215 // Checks the packet type
216 if (ch->ptype_ == PT_UWICRP_STATUS) {
217 icrp_statush = HDR_UWICRP_STATUS(p);
218 } else {
219 icrp_datah = HDR_UWICRP_DATA(p);
220 }
221 if (ch->direction() == hdr_cmn::UP) {
222 if (ch->ptype_ == PT_UWICRP_STATUS) {
223 if (iph->daddr() ==
224 ipAddr_) { // The packet is for me, process it and drop
225 if (printDebug_ > 10)
226 cout << "@" << Scheduler::instance().clock()
227 << " -> N: " << this->printIP(ipAddr_)
228 << " - CP: " << ch->uid()
229 << " - UP - Status Packet for me." << endl;
230 this->addRouteEntry(p);
231 Packet::free(p);
232 return;
233 } else { // This node has to forward the status packet to the
234 // next hop
235 if (printDebug_ > 10)
236 cout << "@" << Scheduler::instance().clock()
237 << " -> N: " << this->printIP(ipAddr_)
238 << " - CP: " << ch->uid()
239 << " - UP - Status Packet, process and forward it."
240 << endl;
241 // Add the entry
242 this->addRouteEntry(p);
243 // Forward the packet
244 Packet *p_new = Packet::alloc();
245 p_new = p->copy();
246 hdr_cmn *ch_new = HDR_CMN(p_new);
247 hdr_uwicrp_status *icrp_statush_new =
248 HDR_UWICRP_STATUS(p_new);
249 ch_new->prev_hop_ = ipAddr_;
250 ch_new->next_hop() =
251 icrp_statush_new->list_of_hops()
252 [--icrp_statush_new
253 ->pointer_to_list_of_hops()]; // TODO: check
255 sendDown(p_new);
256 Packet::free(p);
257 return;
258 }
259 } else if (ch->ptype_ == PT_UWICRP_ACK) {
260 if (iph->daddr() == ipAddr_) {
261 ackwaitingTmr_.force_cancel();
262 }
263 } else { // Data packet to forward
264 if (iph->daddr() != ipAddr_) { // The destination (sink) must be
265 // different from my IP, this is
266 // a node
267 if (printDebug_ > 10)
268 cout << "@" << Scheduler::instance().clock()
269 << " -> N: " << this->printIP(ipAddr_)
270 << " - CP: " << ch->uid()
271 << " - UP - Data Packet Received." << endl;
272 if (ch->next_hop() != UWIP_BROADCAST) { // The packet wasn't
273 // sent in bcast by
274 // the source
275 if (this->addIpInList(p, ipAddr_)) { // The IP of the
276 // current node is
277 // now in the list
278 int pointer_ = this->findInRouteTable(ipSink_);
279 if (pointer_ != -1 &&
280 route_table[pointer_].next_hop !=
281 0) { // I have a valid next hop
282 ch->next_hop() = route_table[pointer_].next_hop;
284 } else { // Otherwise send the packet in broadcast
285 ch->next_hop() = UWIP_BROADCAST;
286 }
287 if (printDebug_ > 10)
288 cout << "@" << Scheduler::instance().clock()
289 << " -> N: " << this->printIP(ipAddr_)
290 << " - CP: " << ch->uid()
291 << " - UP - Data Packet to Forward - IP "
292 "inserted."
293 << endl;
294 this->sendBackAck(p);
295 ch->prev_hop_ = ipAddr_;
297 sendDown(p);
298 return;
299 } else {
300 Packet::free(p);
301 return;
302 }
303 } else { // The packet was sent in bcast by the source: add
304 // my IP to the list and forward it in bcast
305 if (!this->isIpInList(p, ipAddr_)) { // If my IP is not
306 // already in the
307 // list
308 if (this->addIpInList(p,
309 ipAddr_)) { // The IP of the current
310 // node is now in the list
311 ch->prev_hop_ = ipAddr_;
312 ch->next_hop() = UWIP_BROADCAST;
313 if (printDebug_ > 10)
314 cout << "@" << Scheduler::instance().clock()
315 << " -> N: " << this->printIP(ipAddr_)
316 << " - CP: " << ch->uid()
317 << " - UP - Data Packet in Bcast to "
318 "Forward - IP inserted."
319 << endl;
321 sendDown(p);
322 return;
323 } else {
324 Packet::free(p);
325 return;
326 }
327 } else {
328 if (printDebug_ > 10)
329 cout << "@" << Scheduler::instance().clock()
330 << " -> N: " << this->printIP(ipAddr_)
331 << " - CP: " << ch->uid()
332 << " - UP - Data Packet already processed "
333 "-> Discard it."
334 << endl;
335 Packet::free(p);
336 return;
337 }
338 }
339 } else {
340 Packet::free(p);
341 return;
342 }
343 }
344 } else if (ch->direction() ==
345 hdr_cmn::DOWN) { // The node received a packet from an
346 // application, it has to send it to the right
347 // destination
348 Packet *p_new = Packet::alloc();
349 p_new = p->copy();
350 this->initPkt(p_new);
351 hdr_cmn *ch_new = HDR_CMN(p_new);
352 // Do I have a path to the sink?
353 int pointer_ = this->findInRouteTable(ipSink_);
354 if (pointer_ != -1 && route_table[pointer_].next_hop != 0) {
355 if (ch->next_hop() != 0) {
356 ch_new->next_hop() = route_table[pointer_].next_hop;
358 }
359 }
360 if (printDebug_ > 10)
361 cout << "@" << Scheduler::instance().clock()
362 << " -> N: " << this->printIP(ipAddr_)
363 << " - CP: " << ch->uid()
364 << " - DOWN - New Data Packet. Next hop: "
365 << printIP(ch_new->next_hop()) << endl;
367 sendDown(p_new);
368 Packet::free(p);
369 return;
370 } else {
371 if (printDebug_ > 10)
372 cout << "@" << Scheduler::instance().clock()
373 << " -> N: " << this->printIP(ipAddr_)
374 << " - P: " << ch->uid()
375 << " - ??? - NO_DIRECTION - Garbage." << endl;
376 Packet::free(p);
377 return;
378 }
379 }
380}
381
382void
384{
385 // Common header.
386 hdr_cmn *ch = HDR_CMN(p);
387 // ch->uid() = 0; // Set by the Application above.
388 // ch->ptype() = 0; // Set by the Application above.
389 // ch->size() = 0; // Look Down;
390 ch->direction() = hdr_cmn::DOWN;
391 // ch->next_hop() = 0; // Set by SuwIPRoutingNode::forwardDataPacket.
392 ch->next_hop() = UWIP_BROADCAST;
393 ch->prev_hop_ = ipAddr_;
394
395 // IP Header.
396 hdr_uwip *iph = HDR_UWIP(p);
397 iph->daddr() = ipSink_; // The destination is always the Sink associated.
398 // iph->dport() = 0; // Set by the Application above.
399 // iph->saddr() = 0; // Set by IPModule
400 // iph->sport() = 0; // Set by the Application above.
401 // iph->ttl() = 0; // Set by IPModule
402
403 // Data header.
404 hdr_uwicrp_data *icrpdatah = HDR_UWICRP_DATA(p);
405 icrpdatah->list_of_hops()[0] = ipAddr_;
406 icrpdatah->list_of_hops_length()++;
407 icrpdatah->pointer_to_list_of_hops() = 0;
408
409 ch->size() += sizeof(hdr_uwicrp_data);
410 ch->timestamp() = Scheduler::instance().clock();
411}
412
413void
415{
416 // FIX this: it works only with one sink!
417 // This version doesn't take count of new best routes, it always override
418 // the olds
419 hdr_cmn *ch = HDR_CMN(p);
420 hdr_uwip *iph = HDR_UWIP(p);
421 hdr_uwicrp_status *icrp_statush = HDR_UWICRP_STATUS(p);
422 if (route_table[0].destination !=
423 0) { // I have already a route to the destination
424 int new_nop_count_ = icrp_statush->list_of_hops_length() -
425 icrp_statush->pointer_to_list_of_hops();
426 if (route_table[0].isValid == false ||
427 new_nop_count_ <=
428 route_table[0]
429 .hopcount) { // I have to update the old route
430 route_table[0].destination = iph->saddr();
431 route_table[0].hopcount = icrp_statush->list_of_hops_length() -
432 icrp_statush->pointer_to_list_of_hops();
433 route_table[0].isValid = true;
434 route_table[0].creationtime = Scheduler::instance().clock();
435 route_table[0].next_hop = ch->prev_hop_;
436 }
437 } else { // I don't have any route to the destination, save it
438 route_table[0].destination = iph->saddr();
439 route_table[0].hopcount = icrp_statush->list_of_hops_length() -
440 icrp_statush->pointer_to_list_of_hops();
441 route_table[0].isValid = true;
442 route_table[0].creationtime = Scheduler::instance().clock();
443 route_table[0].next_hop = ch->prev_hop_;
444 }
445 return;
446}
447
448int
450{
451 for (int i = 0; i < HOP_TABLE_LENGTH; i++) {
452 if (route_table[i].creationtime != 0) {
453 if ((Scheduler::instance().clock() - route_table[i].creationtime) >
455 this->clearRouteTable(i);
456 }
457 }
458 if (route_table[i].destination == ip_ && route_table[i].isValid) {
459 route_table[i].creationtime = Scheduler::instance().clock();
460 return i;
461 }
462 }
463 return -1;
464}
465
466bool
467UwIcrpNode::isIpInList(Packet *p, nsaddr_t ip_)
468{
469 hdr_uwicrp_data *icrp_datah = HDR_UWICRP_DATA(p);
470 if (icrp_datah->list_of_hops_length() == 0)
471 return false;
472 else if (icrp_datah->list_of_hops_length() > 0) {
473 for (int i = 0; i < icrp_datah->list_of_hops_length(); i++)
474 if (icrp_datah->list_of_hops()[i] == ip_)
475 return true;
476 }
477 return false;
478}
479
480bool
481UwIcrpNode::addIpInList(Packet *p, nsaddr_t ip_)
482{
483 hdr_uwicrp_data *icrp_datah = HDR_UWICRP_DATA(p);
484 if (icrp_datah->list_of_hops_length() <
485 MAX_HOP_NUMBER) { // Ok, I can add another IP
486 icrp_datah->list_of_hops()[icrp_datah->list_of_hops_length()] = ip_;
487 icrp_datah->pointer_to_list_of_hops()++;
488 icrp_datah->list_of_hops_length()++;
489 return true;
490 } else { // The list if full: stop!
491 return false;
492 }
493}
494
495void
497{
498 for (int i = 0; i < HOP_TABLE_LENGTH; i++) {
499 if (route_table[i].isValid) {
500 cout << "Routing table node: " << this->printIP(ipAddr_) << endl;
501 cout << i << " : " << '\t'
502 << this->printIP(route_table[i].destination) << '\t'
503 << "next hop: " << this->printIP(route_table[i].next_hop)
504 << '\t' << "hop count: " << route_table[i].hopcount << endl;
505 }
506 }
507}
508
509string
510UwIcrpNode::printIP(const uint8_t _ip)
511{
512 std::stringstream out;
513 out << "0.0.0." << ((_ip & 0x000000ff));
514 return out.str();
515}
516
517nsaddr_t
518UwIcrpNode::str2addr(const char *str)
519{
520 int level[4] = {0, 0, 0, 0};
521 char tmp[20];
522 strncpy(tmp, str, 19);
523 tmp[19] = '\0';
524 char *p = strtok(tmp, ".");
525 for (int i = 0; p && i < 4; p = strtok(NULL, "."), i++) {
526 level[i] = atoi(p);
527 if (level[i] > 255)
528 level[i] = 255;
529 else if (level[i] < 0)
530 level[i] = 0;
531 }
532 nsaddr_t addr = 0;
533 for (int i = 0; i < 4; i++) {
534 addr += (level[i] << 8 * (3 - i));
535 }
536 return addr;
537}
538
539void
541{
542 hdr_cmn *ch = HDR_CMN(p);
543
544 Packet *p_ack = Packet::alloc();
545 this->initPktAck(p_ack);
546
547 hdr_cmn *ch_ack = HDR_CMN(p_ack);
548 hdr_uwip *iph_ack = HDR_UWIP(p_ack);
549
550 ch_ack->next_hop() = ch->prev_hop_;
551 iph_ack->daddr() = ch->prev_hop_;
552
554 sendDown(p_ack);
555} /* UwIcrpNode::sendBackAck */
556
557void
559{
560 // Common header.
561 hdr_cmn *ch = HDR_CMN(p);
562 ch->ptype() = PT_UWICRP_ACK;
563 // ch->size() = 0; // Look down.
564 ch->direction() = hdr_cmn::DOWN;
565 ch->next_hop() = UWIP_BROADCAST;
566 ch->prev_hop_ = ipAddr_;
567
568 // IP header.
569 hdr_uwip *iph = HDR_UWIP(p);
570 iph->daddr() = UWIP_BROADCAST; // A path search packet is sent in broadcast.
571 // iph->dport() = 0; // Not needed: no applications above.
572 // iph->saddr() = 0; // Set by IPModule.
573 // iph->sport() = 0; // Not needed: no applications above.
574
575 ch->size() += sizeof(hdr_uwicrp_ack);
576 ch->timestamp() = Scheduler::instance().clock();
577} /* UwIcrpNode::initPktAck */
578
579void
virtual void expire(Event *e)
Class that manages cross layer messages that require the IP of the node.
Definition uwip-clmsg.h:57
Class used to answer to UWIPClMsgReqAddr cross layer messages.
Definition uwip-clmsg.h:68
nsaddr_t getAddr()
Adds the module for UwIcrpNodeModuleClass in ns2.
TclObject * create(int, const char *const *)
UwIcrpNode class is used to represent the routing layer of a node.
virtual void clearAllRouteTable()
Clears completely the routing table of the node.
virtual void addRouteEntry(Packet *)
Adds the information received from a Status packet in the routing table of the node.
virtual void sendBackAck(const Packet *p)
Creates an ack packet after the reception a data packet received correctly.
nsaddr_t str2addr(const char *)
Returns a nsaddr_t address from an IP written as a string in the form "x.x.x.x".
uint8_t ipSink_
IP of the sink associated.
virtual string printIP(const uint8_t)
Return a string with an IP in the classic form "x.x.x.x" converting an ns2 nsaddr_t address.
virtual void ackLost()
Resets all the routing information because the lost of an ack.
double max_validity_time_
Maximum validity time of a route.
virtual void initPktAck(Packet *p)
Initializes an Ack packet (previously allocated).
static const int getStatusPktHeaderSize()
Returns the size in byte of a hdr_uwicrp_status packet header.
virtual int command(int, const char *const *)
TCL command interpreter.
static long numberofstatuspkt_
Comulative number of Status packets processed by UwIcrpNode objects.
virtual bool addIpInList(Packet *, nsaddr_t)
Adds an IP passed as argument in the header of a Data packet passed as argument.
virtual void initialize()
Initializes a UwIcrpNode node.
uint8_t ipAddr_
IP of the current node.
static long numberofackpkt_
Comulative number of Ack packets processed by UwIcrpNode objects.
static const int getAckPktHeaderSize()
Returns the size in byte of a hdr_uwicrp_ack packet header.
routing_table_entry route_table[HOP_TABLE_LENGTH]
Node routing table.
virtual int recvAsyncClMsg(ClMessage *)
Initializes a UwIcrpSink node.
AckWaiting ackwaitingTmr_
AckWaiting object.
virtual void initPkt(Packet *)
Initializes a Data packet (previously allocated).
static long numberofdatapkt_
Comulative number of Data packets processed by UwIcrpNode objects.
virtual bool isIpInList(Packet *, nsaddr_t)
Checks if a specific IP is in the header of the packet passed as argument.
virtual void printHopTable()
Prints in the stdout the routing table of the current node.
virtual int findInRouteTable(nsaddr_t)
Seeks for an entry in the routing table that contains information to a specific address passed as arg...
static const int getDataPktHeaderSize()
Returns the size in byte of a hdr_uwicrp_data packet header.
UwIcrpNode()
Constructor of UwIcrpNode class.
~UwIcrpNode()
Destructor of UwIcrpNode class.
virtual int recvSyncClMsg(ClMessage *)
Cross-Layer messages synchronous interpreter.
virtual void recv(Packet *)
Performs the reception of packets from upper and lower layers.
int printDebug_
Flag to enable or disable dirrefent levels of debug.
virtual void clearRouteTable(const int &)
Removes a specific entry in the routing table of the node.
double timer_ack_waiting_
Ack waiting timer.
hdr_uwicrp_ack describes acks packets used by UWICRP.
hdr_uwicrp_data describes data packets used by UWICRP
int & pointer_to_list_of_hops()
Reference to the pointer_to_list_of_hops_ variable.
int & list_of_hops_length()
Reference to the list_of_hops_length_ variable.
nsaddr_t * list_of_hops()
Pointer to the list_of_hops_ variable.
hdr_uwicrp_status describes status packets used by UWICRP
int & list_of_hops_length()
Reference to the list_of_hops_length_ variable.
nsaddr_t * list_of_hops()
Pointer to the list_of_hops_ variable.
int & pointer_to_list_of_hops()
Reference to the pointer_to_list_of_hops_ variable.
hdr_uwip describes UWIP packets.
Definition uwip-module.h:70
uint8_t & daddr()
Reference to the daddr_ variable.
uint8_t & saddr()
Reference to the saddr_ variable.
Definition uwip-module.h:95
double creationtime
Creation Time of the packet.
nsaddr_t destination
Address of the destination.
nsaddr_t next_hop
Address of the next hop.
bool isValid
Flag to check the validity of the packet.
int hopcount
Hop count.
static const int HOP_TABLE_LENGTH
Maximum length of the routing table of a node FOR UWICRP.
static const int MAX_HOP_NUMBER
Maximum number of hops contained in a SUN Path Establishment packet.
#define HDR_UWICRP_DATA(p)
#define HDR_UWICRP_STATUS(p)
UwIcrpNodeModuleClass class_module_uwicrp_node
Provides a module for nodes that needs a simple and dynamic routing protocol.
static const uint8_t UWIP_BROADCAST
Variable used to represent a broadcast UWIP.
Definition uwip-module.h:62
#define HDR_UWIP(P)
Definition uwip-module.h:58