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