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 
39 namespace ns3 {
40 
41 NS_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 
48 NS_OBJECT_ENSURE_REGISTERED (Ipv4ClickRouting);
49 
50 std::map < simclick_node_t *, Ptr<Ipv4ClickRouting> > Ipv4ClickRouting::m_clickInstanceFromSimNode;
51 
52 TypeId
54 {
55  static TypeId tid = TypeId ("ns3::Ipv4ClickRouting")
56  .SetParent<Ipv4RoutingProtocol> ()
57  .AddConstructor<Ipv4ClickRouting> ()
58  .SetGroupName ("Click")
59  ;
60 
61  return tid;
62 }
63 
64 Ipv4ClickRouting::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 
75 Ipv4ClickRouting::~Ipv4ClickRouting ()
76 {
77 }
78 
79 void
80 Ipv4ClickRouting::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 
110 void
111 Ipv4ClickRouting::SetIpv4 (Ptr<Ipv4> ipv4)
112 {
113  m_ipv4 = ipv4;
114 }
115 
116 Ptr<UniformRandomVariable>
117 Ipv4ClickRouting::GetRandomVariable (void)
118 {
119  return m_random;
120 }
121 
122 void
123 Ipv4ClickRouting::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 
134 void
135 Ipv4ClickRouting::SetClickFile (std::string clickfile)
136 {
137  m_clickFile = clickfile;
138 }
139 
140 void
141 Ipv4ClickRouting::SetDefines (std::map<std::string, std::string> defines)
142 {
143  m_defines = defines;
144 }
145 
146 std::map<std::string, std::string>
147 Ipv4ClickRouting::GetDefines (void)
148 {
149  return m_defines;
150 }
151 
152 void
153 Ipv4ClickRouting::SetClickRoutingTableElement (std::string name)
154 {
155  m_clickRoutingTableElement = name;
156 }
157 
158 void
159 Ipv4ClickRouting::SetNodeName (std::string name)
160 {
161  m_nodeName = name;
162  m_nonDefaultName = true;
163 }
164 
165 std::string
166 Ipv4ClickRouting::GetNodeName ()
167 {
168  return m_nodeName;
169 }
170 
171 int
172 Ipv4ClickRouting::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 intialisation
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 
228 bool
229 Ipv4ClickRouting::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 
241 std::string
242 Ipv4ClickRouting::GetIpAddressFromInterfaceId (int ifid)
243 {
244  std::stringstream addr;
245  m_ipv4->GetAddress (ifid, 0).GetLocal ().Print (addr);
246 
247  return addr.str ();
248 }
249 
250 std::string
251 Ipv4ClickRouting::GetIpPrefixFromInterfaceId (int ifid)
252 {
253  std::stringstream addr;
254  m_ipv4->GetAddress (ifid, 0).GetMask ().Print (addr);
255 
256  return addr.str ();
257 }
258 
259 std::string
260 Ipv4ClickRouting::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 
271 void
272 Ipv4ClickRouting::AddSimNodeToClickMapping ()
273 {
274  m_clickInstanceFromSimNode.insert (std::make_pair (m_simNode, this));
275 }
276 
277 Ptr<Ipv4ClickRouting>
278 Ipv4ClickRouting::GetClickInstanceFromSimNode (simclick_node_t *simnode)
279 {
280  return m_clickInstanceFromSimNode[simnode];
281 }
282 
283 struct timeval
284 Ipv4ClickRouting::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 
320 void
321 Ipv4ClickRouting::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 
330 void
331 Ipv4ClickRouting::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 
341 void
342 Ipv4ClickRouting::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 
371 void
372 Ipv4ClickRouting::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 
386 void
387 Ipv4ClickRouting::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 
412 void
413 Ipv4ClickRouting::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 
440 std::string
441 Ipv4ClickRouting::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 
454 int
455 Ipv4ClickRouting::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 
468 void
469 Ipv4ClickRouting::SetPromisc (int ifid)
470 {
471  Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol> (m_ipv4);
472  NS_ASSERT(ipv4l3);
473  ipv4l3->SetPromisc (ifid);
474 }
475 
476 Ptr<Ipv4Route>
477 Ipv4ClickRouting::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
549 bool
550 Ipv4ClickRouting::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 
559 void
560 Ipv4ClickRouting::PrintRoutingTable (Ptr<OutputStreamWrapper> stream, Time::Unit unit) const
561 {
562 }
563 
564 void
565 Ipv4ClickRouting::NotifyInterfaceUp (uint32_t i)
566 {
567 }
568 
569 void
570 Ipv4ClickRouting::NotifyInterfaceDown (uint32_t i)
571 {
572 }
573 
574 void
575 Ipv4ClickRouting::NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address)
576 {
577 }
578 
579 void
580 Ipv4ClickRouting::NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address)
581 {
582 }
583 
584 
585 } // namespace ns3
586 
587 using ns3::g_log;
588 
589 static int simstrlcpy (char *buf, int len, const std::string &s)
590 {
591  if (len)
592  {
593  len--;
594 
595  if ((unsigned) len > s.length ())
596  {
597  len = s.length ();
598  }
599 
600  s.copy (buf, len);
601  buf[len] = '\0';
602  }
603  return 0;
604 }
605 
606 // Sends a Packet from Click to the Simulator: Defined in simclick.h. Click
607 // calls these methods.
608 int simclick_sim_send (simclick_node_t *simnode,
609  int ifid, int type, const unsigned char* data, int len,
610  simclick_simpacketinfo *pinfo)
611 {
612  NS_LOG_DEBUG ("simclick_sim_send called at " << ns3::Simulator::Now ().GetSeconds () << ": " << ifid << " " << type << " " << data << " " << len);
613 
614  if (simnode == NULL)
615  {
616  return -1;
617  }
618 
619  ns3::Ptr<ns3::Ipv4ClickRouting> clickInstance = ns3::Ipv4ClickRouting::GetClickInstanceFromSimNode (simnode);
620 
621  clickInstance->HandlePacketFromClick (ifid, type, data, len);
622 
623  return 0;
624 }
625 
626 // Click Service Methods: Defined in simclick.h
627 int simclick_sim_command (simclick_node_t *simnode, int cmd, ...)
628 {
629  va_list val;
630  va_start (val, cmd);
631 
632  int retval = 0;
633 
634  ns3::Ptr<ns3::Ipv4ClickRouting> clickInstance = ns3::Ipv4ClickRouting::GetClickInstanceFromSimNode (simnode);
635  switch (cmd)
636  {
637  case SIMCLICK_VERSION:
638  {
639  retval = 0;
640  break;
641  }
642 
643  case SIMCLICK_SUPPORTS:
644  {
645  int othercmd = va_arg (val, int);
646  retval = (othercmd >= SIMCLICK_VERSION && othercmd <= SIMCLICK_GET_DEFINES);
647  break;
648  }
649 
650  case SIMCLICK_IFID_FROM_NAME:
651  {
652  const char *ifname = va_arg (val, const char *);
653 
654  retval = clickInstance->GetInterfaceId (ifname);
655 
656  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IFID_FROM_NAME: " << ifname << " " << retval);
657  break;
658  }
659 
660  case SIMCLICK_IPADDR_FROM_NAME:
661  {
662  const char *ifname = va_arg (val, const char *);
663  char *buf = va_arg (val, char *);
664  int len = va_arg (val, int);
665 
666  int ifid = clickInstance->GetInterfaceId (ifname);
667 
668  if (ifid >= 0)
669  {
670  retval = simstrlcpy (buf, len, clickInstance->GetIpAddressFromInterfaceId (ifid));
671  }
672  else
673  {
674  retval = -1;
675  }
676 
677  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IPADDR_FROM_NAME: " << ifname << " " << buf << " " << len);
678  break;
679  }
680 
681  case SIMCLICK_IPPREFIX_FROM_NAME:
682  {
683  const char *ifname = va_arg (val, const char *);
684  char *buf = va_arg (val, char *);
685  int len = va_arg (val, int);
686 
687  int ifid = clickInstance->GetInterfaceId (ifname);
688 
689  if (ifid >= 0)
690  {
691  retval = simstrlcpy (buf, len, clickInstance->GetIpPrefixFromInterfaceId (ifid));
692  }
693  else
694  {
695  retval = -1;
696  }
697 
698  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IPPREFIX_FROM_NAME: " << ifname << " " << buf << " " << len);
699  break;
700  }
701 
702  case SIMCLICK_MACADDR_FROM_NAME:
703  {
704  const char *ifname = va_arg (val, const char *);
705  char *buf = va_arg (val, char *);
706  int len = va_arg (val, int);
707  int ifid = clickInstance->GetInterfaceId (ifname);
708 
709  if (ifid >= 0)
710  {
711  retval = simstrlcpy (buf, len, clickInstance->GetMacAddressFromInterfaceId (ifid));
712  }
713  else
714  {
715  retval = -1;
716  }
717 
718  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_MACADDR_FROM_NAME: " << ifname << " " << buf << " " << len);
719  break;
720  }
721 
722  case SIMCLICK_SCHEDULE:
723  {
724  const struct timeval *when = va_arg (val, const struct timeval *);
725 
726  clickInstance->HandleScheduleFromClick (when);
727 
728  retval = 0;
729  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_SCHEDULE at " << when->tv_sec << "s and " << when->tv_usec << "usecs.");
730 
731  break;
732  }
733 
734  case SIMCLICK_GET_NODE_NAME:
735  {
736  char *buf = va_arg (val, char *);
737  int len = va_arg (val, int);
738  retval = simstrlcpy (buf, len, clickInstance->GetNodeName ());
739 
740  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_GET_NODE_NAME: " << buf << " " << len);
741  break;
742  }
743 
744  case SIMCLICK_IF_PROMISC:
745  {
746  int ifid = va_arg(val, int);
747  clickInstance->SetPromisc (ifid);
748 
749  retval = 0;
750  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IF_PROMISC: " << ifid << " " << ns3::Simulator::Now ());
751  break;
752  }
753 
754  case SIMCLICK_IF_READY:
755  {
756  int ifid = va_arg (val, int); // Commented out so that optimized build works
757 
758  // We're not using a ClickQueue, so we're always ready (for the timebeing)
759  retval = clickInstance->IsInterfaceReady (ifid);
760 
761  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IF_READY: " << ifid << " " << ns3::Simulator::Now ());
762  break;
763  }
764 
765  case SIMCLICK_TRACE:
766  {
767  // Used only for tracing
768  NS_LOG_DEBUG (clickInstance->GetNodeName () << " Received a call for SIMCLICK_TRACE");
769  break;
770  }
771 
772  case SIMCLICK_GET_NODE_ID:
773  {
774  // Used only for tracing
775  NS_LOG_DEBUG (clickInstance->GetNodeName () << " Received a call for SIMCLICK_GET_NODE_ID");
776  break;
777  }
778 
779  case SIMCLICK_GET_RANDOM_INT:
780  {
781  uint32_t *randomValue = va_arg (val, uint32_t *);
782  uint32_t maxValue = va_arg (val, uint32_t);
783 
784  *randomValue = static_cast<uint32_t> (clickInstance->GetRandomVariable ()->GetValue (0.0, static_cast<double> (maxValue) + 1.0));
785  retval = 0;
786  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_RANDOM: " << *randomValue << " " << maxValue << " " << ns3::Simulator::Now ());
787  break;
788  }
789 
790  case SIMCLICK_GET_DEFINES:
791  {
792  char *buf = va_arg (val, char *);
793  size_t *size = va_arg (val, size_t *);
794  uint32_t required = 0;
795 
796  // Try to fill the buffer with up to size bytes.
797  // If this is not enough space, write the required buffer size into
798  // the size variable and return an error code.
799  // Otherwise return the bytes actually writte into the buffer in size.
800 
801  // Append key/value pair, seperated by \0.
802  std::map<std::string, std::string> defines = clickInstance->GetDefines ();
803  std::map<std::string, std::string>::const_iterator it = defines.begin ();
804  while (it != defines.end ())
805  {
806  size_t available = *size - required;
807  if (it->first.length() + it->second.length() + 2 <= available)
808  {
809  simstrlcpy(buf + required, available, it->first);
810  required += it->first.length() + 1;
811  available -= it->first.length() + 1;
812  simstrlcpy(buf + required, available, it->second);
813  required += it->second.length() + 1;
814  }
815  else
816  {
817  required += it->first.length() + it->second.length() + 2;
818  }
819  it++;
820  }
821  if (required > *size)
822  {
823  retval = -1;
824  }
825  else
826  {
827  retval = 0;
828  }
829  *size = required;
830  }
831  }
832 
833  va_end (val);
834  return retval;
835 }
836 
837 #endif // NS3_CLICK
void SetIpv4(const char *deviceName, const char *ip, const char *netmask)
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#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
#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_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:719
int64_t GetFemtoSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:361
tuple cmd
Definition: second.py:35
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:341
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:349
uint8_t data[writeSize]
TypeId SetGroupName(std::string groupName)
Set the group name.
Definition: type-id.cc:921
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:249
int64_t GetNanoSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:353
int64_t GetPicoSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:357
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:269
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:365
tuple address
Definition: first.py:37
static TypeId GetTypeId(void)
Get the type ID.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:914