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