A Discrete-Event Network Simulator
API
ipv4-click-routing.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010 Lalith Suresh
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Authors: Lalith Suresh <suresh.lalith@gmail.com>
18 */
19
20#ifdef NS3_CLICK
21
22#include "ipv4-click-routing.h"
23
24#include "ns3/ipv4-interface.h"
25#include "ns3/ipv4-l3-click-protocol.h"
26#include "ns3/log.h"
27#include "ns3/mac48-address.h"
28#include "ns3/node.h"
29#include "ns3/random-variable-stream.h"
30#include "ns3/simulator.h"
31
32#include <cstdarg>
33#include <cstdlib>
34#include <map>
35#include <string>
36
37namespace ns3
38{
39
40NS_LOG_COMPONENT_DEFINE("Ipv4ClickRouting");
41
42// Values from nsclick ExtRouter implementation
43#define INTERFACE_ID_KERNELTAP 0
44#define INTERFACE_ID_FIRST 1
45#define INTERFACE_ID_FIRST_DROP 33
46
47NS_OBJECT_ENSURE_REGISTERED(Ipv4ClickRouting);
48
49std::map<simclick_node_t*, Ptr<Ipv4ClickRouting>> Ipv4ClickRouting::m_clickInstanceFromSimNode;
50
51TypeId
53{
54 static TypeId tid = TypeId("ns3::Ipv4ClickRouting")
55 .SetParent<Ipv4RoutingProtocol>()
56 .AddConstructor<Ipv4ClickRouting>()
57 .SetGroupName("Click");
58
59 return tid;
60}
61
62Ipv4ClickRouting::Ipv4ClickRouting()
63 : m_nonDefaultName(false),
64 m_ipv4(nullptr)
65{
66 m_random = CreateObject<UniformRandomVariable>();
67 m_simNode = new simclick_node_t;
68 timerclear(&m_simNode->curtime);
69
70 AddSimNodeToClickMapping();
71}
72
73Ipv4ClickRouting::~Ipv4ClickRouting()
74{
75}
76
77void
78Ipv4ClickRouting::DoInitialize()
79{
80 uint32_t id = m_ipv4->GetObject<Node>()->GetId();
81
82 if (!m_nonDefaultName)
83 {
84 std::stringstream name;
85 name << "Node" << id;
86 m_nodeName = name.str();
87 }
88
89 NS_ASSERT(m_clickFile.length() > 0);
90
91 // Even though simclick_click_create() will halt programme execution
92 // if it is unable to initialise a Click router, we play safe
93 if (simclick_click_create(m_simNode, m_clickFile.c_str()) >= 0)
94 {
95 NS_LOG_DEBUG(m_nodeName << " has initialised a Click Router");
96 m_clickInitialised = true;
97 }
98 else
99 {
100 NS_LOG_DEBUG("Click Router Initialisation failed for " << m_nodeName);
101 m_clickInitialised = false;
102 }
103
104 NS_ASSERT(m_clickInitialised == true);
105 simclick_click_run(m_simNode);
106}
107
108void
109Ipv4ClickRouting::SetIpv4(Ptr<Ipv4> ipv4)
110{
111 m_ipv4 = ipv4;
112}
113
114Ptr<UniformRandomVariable>
115Ipv4ClickRouting::GetRandomVariable()
116{
117 return m_random;
118}
119
120void
121Ipv4ClickRouting::DoDispose()
122{
123 if (m_clickInitialised)
124 {
125 simclick_click_kill(m_simNode);
126 }
127 m_ipv4 = nullptr;
128 delete m_simNode;
129 Ipv4RoutingProtocol::DoDispose();
130}
131
132void
133Ipv4ClickRouting::SetClickFile(std::string clickfile)
134{
135 m_clickFile = clickfile;
136}
137
138void
139Ipv4ClickRouting::SetDefines(std::map<std::string, std::string> defines)
140{
141 m_defines = defines;
142}
143
144std::map<std::string, std::string>
145Ipv4ClickRouting::GetDefines()
146{
147 return m_defines;
148}
149
150void
151Ipv4ClickRouting::SetClickRoutingTableElement(std::string name)
152{
153 m_clickRoutingTableElement = name;
154}
155
156void
157Ipv4ClickRouting::SetNodeName(std::string name)
158{
159 m_nodeName = name;
160 m_nonDefaultName = true;
161}
162
163std::string
164Ipv4ClickRouting::GetNodeName()
165{
166 return m_nodeName;
167}
168
169int
170Ipv4ClickRouting::GetInterfaceId(const char* ifname)
171{
172 int retval = -1;
173
174 // The below hard coding of interface names follows the
175 // same approach as used in the original nsclick code for
176 // ns-2. The interface names map directly to what is to
177 // be used in the Click configuration files.
178 // Thus eth0 will refer to the first network device of
179 // the node, and is to be named so in the Click graph.
180 // This function is called by Click during the initialisation
181 // phase of the Click graph, during which it tries to map
182 // interface IDs to interface names. The return value
183 // corresponds to the interface ID that Click will use.
184
185 // Tap/tun devices refer to the kernel devices
186 if (strstr(ifname, "tap") || strstr(ifname, "tun"))
187 {
188 retval = 0;
189 }
190 else if (const char* devname = strstr(ifname, "eth"))
191 {
192 while (*devname && !isdigit((unsigned char)*devname))
193 {
194 devname++;
195 }
196
197 if (*devname)
198 {
199 retval = atoi(devname) + INTERFACE_ID_FIRST;
200 }
201 }
202 else if (const char* devname = strstr(ifname, "drop"))
203 {
204 while (*devname && !isdigit((unsigned char)*devname))
205 {
206 devname++;
207 }
208 if (*devname)
209 {
210 retval = atoi(devname) + INTERFACE_ID_FIRST_DROP;
211 }
212 }
213
214 // This protects against a possible inconsistency of having
215 // more interfaces defined in the Click graph
216 // for a Click node than are defined for it in
217 // the simulation script
218 if (retval >= (int)m_ipv4->GetNInterfaces())
219 {
220 return -1;
221 }
222
223 return retval;
224}
225
226bool
227Ipv4ClickRouting::IsInterfaceReady(int ifid)
228{
229 if (ifid >= 0 && ifid < (int)m_ipv4->GetNInterfaces())
230 {
231 return true;
232 }
233 else
234 {
235 return false;
236 }
237}
238
239std::string
240Ipv4ClickRouting::GetIpAddressFromInterfaceId(int ifid)
241{
242 std::stringstream addr;
243 m_ipv4->GetAddress(ifid, 0).GetLocal().Print(addr);
244
245 return addr.str();
246}
247
248std::string
249Ipv4ClickRouting::GetIpPrefixFromInterfaceId(int ifid)
250{
251 std::stringstream addr;
252 m_ipv4->GetAddress(ifid, 0).GetMask().Print(addr);
253
254 return addr.str();
255}
256
257std::string
258Ipv4ClickRouting::GetMacAddressFromInterfaceId(int ifid)
259{
260 std::stringstream addr;
261
262 Ptr<NetDevice> device = m_ipv4->GetNetDevice(ifid);
263 Address devAddr = device->GetAddress();
264 addr << Mac48Address::ConvertFrom(devAddr);
265
266 return addr.str();
267}
268
269void
270Ipv4ClickRouting::AddSimNodeToClickMapping()
271{
272 m_clickInstanceFromSimNode.insert(std::make_pair(m_simNode, this));
273}
274
275Ptr<Ipv4ClickRouting>
276Ipv4ClickRouting::GetClickInstanceFromSimNode(simclick_node_t* simnode)
277{
278 return m_clickInstanceFromSimNode[simnode];
279}
280
281struct timeval
282Ipv4ClickRouting::GetTimevalFromNow() const
283{
284 struct timeval curtime;
285 uint64_t remainder = 0;
286
287 curtime.tv_sec = Simulator::Now().GetSeconds();
288 curtime.tv_usec = Simulator::Now().GetMicroSeconds() % 1000000;
289
290 switch (Simulator::Now().GetResolution())
291 {
292 case Time::NS:
293 remainder = Simulator::Now().GetNanoSeconds() % 1000;
294 break;
295 case Time::PS:
296 remainder = Simulator::Now().GetPicoSeconds() % 1000000;
297 break;
298 case Time::FS:
299 remainder = Simulator::Now().GetFemtoSeconds() % 1000000000;
300 break;
301 default:
302 break;
303 }
304
305 if (remainder)
306 {
307 ++curtime.tv_usec;
308 if (curtime.tv_usec == 1000000)
309 {
310 ++curtime.tv_sec;
311 curtime.tv_usec = 0;
312 }
313 }
314
315 return curtime;
316}
317
318void
319Ipv4ClickRouting::RunClickEvent()
320{
321 m_simNode->curtime = GetTimevalFromNow();
322
323 NS_LOG_DEBUG("RunClickEvent at " << m_simNode->curtime.tv_sec << " "
324 << m_simNode->curtime.tv_usec << " " << Simulator::Now());
325 simclick_click_run(m_simNode);
326}
327
328void
329Ipv4ClickRouting::HandleScheduleFromClick(const struct timeval* when)
330{
331 NS_LOG_DEBUG("HandleScheduleFromClick at " << when->tv_sec << " " << when->tv_usec << " "
332 << Simulator::Now());
333
334 Time simtime =
335 Time::FromInteger(when->tv_sec, Time::S) + Time::FromInteger(when->tv_usec, Time::US);
336 Time simdelay = simtime - Simulator::Now();
337
338 Simulator::Schedule(simdelay, &Ipv4ClickRouting::RunClickEvent, this);
339}
340
341void
342Ipv4ClickRouting::HandlePacketFromClick(int ifid, int ptype, const unsigned char* data, int len)
343{
344 NS_LOG_DEBUG("HandlePacketFromClick");
345
346 // Figure out packet's destination here:
347 // If ifid == 0, then the packet's going up
348 // else, the packet's going down
349 if (ifid == 0)
350 {
351 NS_LOG_DEBUG("Incoming packet from tap0. Sending Packet up the stack.");
352 Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol>(m_ipv4);
353
354 Ptr<Packet> p = Create<Packet>(data, len);
355
356 Ipv4Header ipHeader;
357 p->RemoveHeader(ipHeader);
358
359 ipv4l3->LocalDeliver(p, ipHeader, (uint32_t)ifid);
360 }
361 else if (ifid)
362 {
363 NS_LOG_DEBUG("Incoming packet from eth" << ifid - 1 << " of type " << ptype
364 << ". Sending packet down the stack.");
365
366 Ptr<Packet> p = Create<Packet>(data, len);
367
368 DynamicCast<Ipv4L3ClickProtocol>(m_ipv4)->SendDown(p, ifid);
369 }
370}
371
372void
373Ipv4ClickRouting::SendPacketToClick(int ifid, int ptype, const unsigned char* data, int len)
374{
375 NS_LOG_FUNCTION(this << ifid);
376 m_simNode->curtime = GetTimevalFromNow();
377
378 // Since packets in ns-3 don't have global Packet ID's and Flow ID's, we
379 // feed dummy values into pinfo. This avoids the need to make changes in the Click code
380 simclick_simpacketinfo pinfo;
381 pinfo.id = 0;
382 pinfo.fid = 0;
383
384 simclick_click_send(m_simNode, ifid, ptype, data, len, &pinfo);
385}
386
387void
388Ipv4ClickRouting::Send(Ptr<Packet> p, Ipv4Address src, Ipv4Address dst)
389{
390 uint32_t ifid;
391
392 // Find out which interface holds the src address of the packet...
393 for (ifid = 0; ifid < m_ipv4->GetNInterfaces(); ifid++)
394 {
395 Ipv4Address addr = m_ipv4->GetAddress(ifid, 0).GetLocal();
396
397 if (addr == src)
398 {
399 break;
400 }
401 }
402
403 int len = p->GetSize();
404 uint8_t* buf = new uint8_t[len];
405 p->CopyData(buf, len);
406
407 // ... and send the packet on the corresponding Click interface.
408 SendPacketToClick(0, SIMCLICK_PTYPE_IP, buf, len);
409
410 delete[] buf;
411}
412
413void
414Ipv4ClickRouting::Receive(Ptr<Packet> p, Mac48Address receiverAddr, Mac48Address dest)
415{
416 NS_LOG_FUNCTION(this << p << receiverAddr << dest);
417
418 uint32_t ifid;
419
420 // Find out which device this packet was received from...
421 for (ifid = 0; ifid < m_ipv4->GetNInterfaces(); ifid++)
422 {
423 Ptr<NetDevice> device = m_ipv4->GetNetDevice(ifid);
424
425 if (Mac48Address::ConvertFrom(device->GetAddress()) == receiverAddr)
426 {
427 break;
428 }
429 }
430
431 int len = p->GetSize();
432 uint8_t* buf = new uint8_t[len];
433 p->CopyData(buf, len);
434
435 // ... and send the packet to the corresponding Click interface
436 SendPacketToClick(ifid, SIMCLICK_PTYPE_ETHER, buf, len);
437
438 delete[] buf;
439}
440
441std::string
442Ipv4ClickRouting::ReadHandler(std::string elementName, std::string handlerName)
443{
444 char* handle = simclick_click_read_handler(m_simNode,
445 elementName.c_str(),
446 handlerName.c_str(),
447 nullptr,
448 nullptr);
449 std::string ret(handle);
450
451 // This is required because Click does not free
452 // the memory allocated to the return string
453 // from simclick_click_read_handler()
454 free(handle);
455
456 return ret;
457}
458
459int
460Ipv4ClickRouting::WriteHandler(std::string elementName,
461 std::string handlerName,
462 std::string writeString)
463{
464 int r = simclick_click_write_handler(m_simNode,
465 elementName.c_str(),
466 handlerName.c_str(),
467 writeString.c_str());
468
469 // Note: There are probably use-cases for returning
470 // a write handler's error code, so don't assert.
471 // For example, the 'add' handler for IPRouteTable
472 // type elements fails if the route to be added
473 // already exists.
474
475 return r;
476}
477
478void
479Ipv4ClickRouting::SetPromisc(int ifid)
480{
481 Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol>(m_ipv4);
482 NS_ASSERT(ipv4l3);
483 ipv4l3->SetPromisc(ifid);
484}
485
486Ptr<Ipv4Route>
487Ipv4ClickRouting::RouteOutput(Ptr<Packet> p,
488 const Ipv4Header& header,
489 Ptr<NetDevice> oif,
490 Socket::SocketErrno& sockerr)
491{
492 Ptr<Ipv4Route> rtentry;
493
494 std::stringstream addr;
495 addr << "lookup ";
496 header.GetDestination().Print(addr);
497 // Probe the Click Routing Table for the required IP
498 // This returns a string of the form "InterfaceID GatewayAddr"
499 NS_LOG_DEBUG("Probe click routing table for " << addr.str());
500 std::string s = ReadHandler(m_clickRoutingTableElement, addr.str());
501 NS_LOG_DEBUG("string from click routing table: " << s);
502
503 size_t pos = s.find(' ');
504 Ipv4Address destination;
505 int interfaceId;
506 if (pos == std::string::npos)
507 {
508 // Only an interface ID is found
509 destination = Ipv4Address("0.0.0.0");
510 interfaceId = atoi(s.c_str());
511 NS_LOG_DEBUG("case 1: destination " << destination << " interfaceId " << interfaceId);
512 }
513 else
514 {
515 interfaceId = atoi(s.substr(0, pos).c_str());
516 Ipv4Address destination(s.substr(pos + 1).c_str());
517 NS_LOG_DEBUG("case 2: destination " << destination << " interfaceId " << interfaceId);
518 }
519
520 if (interfaceId != -1)
521 {
522 rtentry = Create<Ipv4Route>();
523 rtentry->SetDestination(header.GetDestination());
524 // the source address is the interface address that matches
525 // the destination address (when multiple are present on the
526 // outgoing interface, one is selected via scoping rules)
527 NS_ASSERT(m_ipv4);
528 uint32_t numOifAddresses = m_ipv4->GetNAddresses(interfaceId);
529 NS_ASSERT(numOifAddresses > 0);
530 Ipv4InterfaceAddress ifAddr;
531 if (numOifAddresses == 1)
532 {
533 ifAddr = m_ipv4->GetAddress(interfaceId, 0);
534 }
535 else
536 {
538 NS_FATAL_ERROR("XXX Not implemented yet: IP aliasing and Click");
539 }
540 rtentry->SetSource(ifAddr.GetLocal());
541 rtentry->SetGateway(destination);
542 rtentry->SetOutputDevice(m_ipv4->GetNetDevice(interfaceId));
543 sockerr = Socket::ERROR_NOTERROR;
544 NS_LOG_DEBUG("Found route to " << rtentry->GetDestination() << " via nh "
545 << rtentry->GetGateway() << " with source addr "
546 << rtentry->GetSource() << " and output dev "
547 << rtentry->GetOutputDevice());
548 }
549 else
550 {
551 NS_LOG_DEBUG("Click node " << m_nodeName << ": RouteOutput for dest="
552 << header.GetDestination() << " No route to host");
553 sockerr = Socket::ERROR_NOROUTETOHOST;
554 }
555
556 return rtentry;
557}
558
559// This method should never be called since Click handles
560// forwarding directly
561bool
562Ipv4ClickRouting::RouteInput(Ptr<const Packet> p,
563 const Ipv4Header& header,
564 Ptr<const NetDevice> idev,
565 UnicastForwardCallback ucb,
566 MulticastForwardCallback mcb,
567 LocalDeliverCallback lcb,
568 ErrorCallback ecb)
569{
570 NS_FATAL_ERROR("Click router does not have a RouteInput() interface!");
571 return false;
572}
573
574void
575Ipv4ClickRouting::PrintRoutingTable(Ptr<OutputStreamWrapper> stream, Time::Unit unit) const
576{
577 *stream->GetStream() << "\nCLICK Routing table printing is not yet implemented, skipping.\n";
578}
579
580void
581Ipv4ClickRouting::NotifyInterfaceUp(uint32_t i)
582{
583}
584
585void
586Ipv4ClickRouting::NotifyInterfaceDown(uint32_t i)
587{
588}
589
590void
591Ipv4ClickRouting::NotifyAddAddress(uint32_t interface, Ipv4InterfaceAddress address)
592{
593}
594
595void
596Ipv4ClickRouting::NotifyRemoveAddress(uint32_t interface, Ipv4InterfaceAddress address)
597{
598}
599
600} // namespace ns3
601
602using ns3::g_log;
603
604static int
605simstrlcpy(char* buf, int len, const std::string& s)
606{
607 if (len)
608 {
609 len--;
610
611 if ((unsigned)len > s.length())
612 {
613 len = s.length();
614 }
615
616 s.copy(buf, len);
617 buf[len] = '\0';
618 }
619 return 0;
620}
621
622// Sends a Packet from Click to the Simulator: Defined in simclick.h. Click
623// calls these methods.
624int
625simclick_sim_send(simclick_node_t* simnode,
626 int ifid,
627 int type,
628 const unsigned char* data,
629 int len,
630 simclick_simpacketinfo* pinfo)
631{
632 NS_LOG_DEBUG("simclick_sim_send called at " << ns3::Simulator::Now().As(ns3::Time::S) << ": "
633 << ifid << " " << type << " " << data << " "
634 << len);
635
636 if (!simnode)
637 {
638 return -1;
639 }
640
641 ns3::Ptr<ns3::Ipv4ClickRouting> clickInstance =
642 ns3::Ipv4ClickRouting::GetClickInstanceFromSimNode(simnode);
643
644 clickInstance->HandlePacketFromClick(ifid, type, data, len);
645
646 return 0;
647}
648
649// Click Service Methods: Defined in simclick.h
650int
651simclick_sim_command(simclick_node_t* simnode, int cmd, ...)
652{
653 va_list val;
654 va_start(val, cmd);
655
656 int retval = 0;
657
658 ns3::Ptr<ns3::Ipv4ClickRouting> clickInstance =
659 ns3::Ipv4ClickRouting::GetClickInstanceFromSimNode(simnode);
660 switch (cmd)
661 {
662 case SIMCLICK_VERSION: {
663 retval = 0;
664 break;
665 }
666
667 case SIMCLICK_SUPPORTS: {
668 int othercmd = va_arg(val, int);
669 retval = (othercmd >= SIMCLICK_VERSION && othercmd <= SIMCLICK_GET_DEFINES);
670 break;
671 }
672
673 case SIMCLICK_IFID_FROM_NAME: {
674 const char* ifname = va_arg(val, const char*);
675
676 retval = clickInstance->GetInterfaceId(ifname);
677
678 NS_LOG_DEBUG(clickInstance->GetNodeName()
679 << " SIMCLICK_IFID_FROM_NAME: " << ifname << " " << retval);
680 break;
681 }
682
683 case SIMCLICK_IPADDR_FROM_NAME: {
684 const char* ifname = va_arg(val, const char*);
685 char* buf = va_arg(val, char*);
686 int len = va_arg(val, int);
687
688 int ifid = clickInstance->GetInterfaceId(ifname);
689
690 if (ifid >= 0)
691 {
692 retval = simstrlcpy(buf, len, clickInstance->GetIpAddressFromInterfaceId(ifid));
693 }
694 else
695 {
696 retval = -1;
697 }
698
699 NS_LOG_DEBUG(clickInstance->GetNodeName()
700 << " SIMCLICK_IPADDR_FROM_NAME: " << ifname << " " << buf << " " << len);
701 break;
702 }
703
704 case SIMCLICK_IPPREFIX_FROM_NAME: {
705 const char* ifname = va_arg(val, const char*);
706 char* buf = va_arg(val, char*);
707 int len = va_arg(val, int);
708
709 int ifid = clickInstance->GetInterfaceId(ifname);
710
711 if (ifid >= 0)
712 {
713 retval = simstrlcpy(buf, len, clickInstance->GetIpPrefixFromInterfaceId(ifid));
714 }
715 else
716 {
717 retval = -1;
718 }
719
720 NS_LOG_DEBUG(clickInstance->GetNodeName()
721 << " SIMCLICK_IPPREFIX_FROM_NAME: " << ifname << " " << buf << " " << len);
722 break;
723 }
724
725 case SIMCLICK_MACADDR_FROM_NAME: {
726 const char* ifname = va_arg(val, const char*);
727 char* buf = va_arg(val, char*);
728 int len = va_arg(val, int);
729 int ifid = clickInstance->GetInterfaceId(ifname);
730
731 if (ifid >= 0)
732 {
733 retval = simstrlcpy(buf, len, clickInstance->GetMacAddressFromInterfaceId(ifid));
734 }
735 else
736 {
737 retval = -1;
738 }
739
740 NS_LOG_DEBUG(clickInstance->GetNodeName()
741 << " SIMCLICK_MACADDR_FROM_NAME: " << ifname << " " << buf << " " << len);
742 break;
743 }
744
745 case SIMCLICK_SCHEDULE: {
746 const struct timeval* when = va_arg(val, const struct timeval*);
747
748 clickInstance->HandleScheduleFromClick(when);
749
750 retval = 0;
751 NS_LOG_DEBUG(clickInstance->GetNodeName() << " SIMCLICK_SCHEDULE at " << when->tv_sec
752 << "s and " << when->tv_usec << "usecs.");
753
754 break;
755 }
756
757 case SIMCLICK_GET_NODE_NAME: {
758 char* buf = va_arg(val, char*);
759 int len = va_arg(val, int);
760 retval = simstrlcpy(buf, len, clickInstance->GetNodeName());
761
762 NS_LOG_DEBUG(clickInstance->GetNodeName()
763 << " SIMCLICK_GET_NODE_NAME: " << buf << " " << len);
764 break;
765 }
766
767 case SIMCLICK_IF_PROMISC: {
768 int ifid = va_arg(val, int);
769 clickInstance->SetPromisc(ifid);
770
771 retval = 0;
772 NS_LOG_DEBUG(clickInstance->GetNodeName()
773 << " SIMCLICK_IF_PROMISC: " << ifid << " " << ns3::Simulator::Now());
774 break;
775 }
776
777 case SIMCLICK_IF_READY: {
778 int ifid = va_arg(val, int); // Commented out so that optimized build works
779
780 // We're not using a ClickQueue, so we're always ready (for the timebeing)
781 retval = clickInstance->IsInterfaceReady(ifid);
782
783 NS_LOG_DEBUG(clickInstance->GetNodeName()
784 << " SIMCLICK_IF_READY: " << ifid << " " << ns3::Simulator::Now());
785 break;
786 }
787
788 case SIMCLICK_TRACE: {
789 // Used only for tracing
790 NS_LOG_DEBUG(clickInstance->GetNodeName() << " Received a call for SIMCLICK_TRACE");
791 break;
792 }
793
794 case SIMCLICK_GET_NODE_ID: {
795 // Used only for tracing
796 NS_LOG_DEBUG(clickInstance->GetNodeName() << " Received a call for SIMCLICK_GET_NODE_ID");
797 break;
798 }
799
800 case SIMCLICK_GET_RANDOM_INT: {
801 uint32_t* randomValue = va_arg(val, uint32_t*);
802 uint32_t maxValue = va_arg(val, uint32_t);
803
804 *randomValue = static_cast<uint32_t>(
805 clickInstance->GetRandomVariable()->GetValue(0.0, static_cast<double>(maxValue) + 1.0));
806 retval = 0;
807 NS_LOG_DEBUG(clickInstance->GetNodeName() << " SIMCLICK_RANDOM: " << *randomValue << " "
808 << maxValue << " " << ns3::Simulator::Now());
809 break;
810 }
811
812 case SIMCLICK_GET_DEFINES: {
813 char* buf = va_arg(val, char*);
814 size_t* size = va_arg(val, size_t*);
815 uint32_t required = 0;
816
817 // Try to fill the buffer with up to size bytes.
818 // If this is not enough space, write the required buffer size into
819 // the size variable and return an error code.
820 // Otherwise return the bytes actually writte into the buffer in size.
821
822 // Append key/value pair, separated by \0.
823 std::map<std::string, std::string> defines = clickInstance->GetDefines();
824 std::map<std::string, std::string>::const_iterator it = defines.begin();
825 while (it != defines.end())
826 {
827 size_t available = *size - required;
828 if (it->first.length() + it->second.length() + 2 <= available)
829 {
830 simstrlcpy(buf + required, available, it->first);
831 required += it->first.length() + 1;
832 available -= it->first.length() + 1;
833 simstrlcpy(buf + required, available, it->second);
834 required += it->second.length() + 1;
835 }
836 else
837 {
838 required += it->first.length() + it->second.length() + 2;
839 }
840 it++;
841 }
842 if (required > *size)
843 {
844 retval = -1;
845 }
846 else
847 {
848 retval = 0;
849 }
850 *size = required;
851 }
852 }
853
854 va_end(val);
855 return retval;
856}
857
858#endif // NS3_CLICK
static TypeId GetTypeId()
Get the type ID.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
int64_t GetNanoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:417
int64_t GetFemtoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:427
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:402
@ S
second
Definition: nstime.h:116
int64_t GetPicoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:422
int64_t GetMicroSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:412
TypeId SetGroupName(std::string groupName)
Set the group name.
Definition: type-id.cc:943
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
static void Send(Ptr< NetDevice > dev, int level, std::string emuMode)
Definition: fd-emu-send.cc:54
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:160
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:296
Length::Unit Unit
Save some typing by defining a short alias for Length::Unit.
address
Definition: first.py:40
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:850
Every class exported by the ns3 library is enclosed in the ns3 namespace.
cmd
Definition: second.py:33
uint8_t data[writeSize]
void SetIpv4(const char *deviceName, const char *ip, const char *netmask)