A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 NS_LOG_COMPONENT_DEFINE ("Ipv4ClickRouting");
40 
41 namespace ns3 {
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 
51 std::map < simclick_node_t *, Ptr<Ipv4ClickRouting> > Ipv4ClickRouting::m_clickInstanceFromSimNode;
52 
53 TypeId
55 {
56  static TypeId tid = TypeId ("ns3::Ipv4ClickRouting")
57  .SetParent<Ipv4RoutingProtocol> ()
58  .AddConstructor<Ipv4ClickRouting> ()
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  std::string s = ReadHandler (m_clickRoutingTableElement, addr.str ());
487 
488  int pos = s.find (" ");
489 
490  int interfaceId = atoi (s.substr (0, pos).c_str ());
491  Ipv4Address destination (s.substr (pos + 1).c_str ());
492 
493  if (interfaceId != -1)
494  {
495  rtentry = Create<Ipv4Route> ();
496  rtentry->SetDestination (header.GetDestination ());
497  // the source address is the interface address that matches
498  // the destination address (when multiple are present on the
499  // outgoing interface, one is selected via scoping rules)
500  NS_ASSERT (m_ipv4);
501  uint32_t numOifAddresses = m_ipv4->GetNAddresses (interfaceId);
502  NS_ASSERT (numOifAddresses > 0);
503  Ipv4InterfaceAddress ifAddr;
504  if (numOifAddresses == 1)
505  {
506  ifAddr = m_ipv4->GetAddress (interfaceId, 0);
507  }
508  else
509  {
511  NS_FATAL_ERROR ("XXX Not implemented yet: IP aliasing and Click");
512  }
513  rtentry->SetSource (ifAddr.GetLocal ());
514  rtentry->SetGateway (destination);
515  rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceId));
516  sockerr = Socket::ERROR_NOTERROR;
517  NS_LOG_DEBUG ("Found route to " << rtentry->GetDestination ()
518  << " via nh " << rtentry->GetGateway ()
519  << " with source addr " << rtentry->GetSource ()
520  << " and output dev " << rtentry->GetOutputDevice ());
521  }
522  else
523  {
524  NS_LOG_DEBUG ("Click node " << m_nodeName
525  << ": RouteOutput for dest=" << header.GetDestination ()
526  << " No route to host");
527  sockerr = Socket::ERROR_NOROUTETOHOST;
528  }
529 
530  return rtentry;
531 }
532 
533 // This method should never be called since Click handles
534 // forwarding directly
535 bool
536 Ipv4ClickRouting::RouteInput (Ptr<const Packet> p, const Ipv4Header &header,
537  Ptr<const NetDevice> idev, UnicastForwardCallback ucb,
538  MulticastForwardCallback mcb, LocalDeliverCallback lcb,
539  ErrorCallback ecb)
540 {
541  NS_FATAL_ERROR ("Click router does not have a RouteInput() interface!");
542  return false;
543 }
544 
545 void
546 Ipv4ClickRouting::PrintRoutingTable (Ptr<OutputStreamWrapper> stream) const
547 {
548 }
549 
550 void
551 Ipv4ClickRouting::NotifyInterfaceUp (uint32_t i)
552 {
553 }
554 
555 void
556 Ipv4ClickRouting::NotifyInterfaceDown (uint32_t i)
557 {
558 }
559 
560 void
561 Ipv4ClickRouting::NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address)
562 {
563 }
564 
565 void
566 Ipv4ClickRouting::NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address)
567 {
568 }
569 
570 
571 } // namespace ns3
572 
573 static int simstrlcpy (char *buf, int len, const std::string &s)
574 {
575  if (len)
576  {
577  len--;
578 
579  if ((unsigned) len > s.length ())
580  {
581  len = s.length ();
582  }
583 
584  s.copy (buf, len);
585  buf[len] = '\0';
586  }
587  return 0;
588 }
589 
590 // Sends a Packet from Click to the Simulator: Defined in simclick.h. Click
591 // calls these methods.
592 int simclick_sim_send (simclick_node_t *simnode,
593  int ifid, int type, const unsigned char* data, int len,
594  simclick_simpacketinfo *pinfo)
595 {
596  NS_LOG_DEBUG ("simclick_sim_send called at " << ns3::Simulator::Now ().GetSeconds () << ": " << ifid << " " << type << " " << data << " " << len);
597 
598  if (simnode == NULL)
599  {
600  return -1;
601  }
602 
603  ns3::Ptr<ns3::Ipv4ClickRouting> clickInstance = ns3::Ipv4ClickRouting::GetClickInstanceFromSimNode (simnode);
604 
605  clickInstance->HandlePacketFromClick (ifid, type, data, len);
606 
607  return 0;
608 }
609 
610 // Click Service Methods: Defined in simclick.h
611 int simclick_sim_command (simclick_node_t *simnode, int cmd, ...)
612 {
613  va_list val;
614  va_start (val, cmd);
615 
616  int retval = 0;
617 
618  ns3::Ptr<ns3::Ipv4ClickRouting> clickInstance = ns3::Ipv4ClickRouting::GetClickInstanceFromSimNode (simnode);
619  switch (cmd)
620  {
621  case SIMCLICK_VERSION:
622  {
623  retval = 0;
624  break;
625  }
626 
627  case SIMCLICK_SUPPORTS:
628  {
629  int othercmd = va_arg (val, int);
630  retval = (othercmd >= SIMCLICK_VERSION && othercmd <= SIMCLICK_GET_DEFINES);
631  break;
632  }
633 
634  case SIMCLICK_IFID_FROM_NAME:
635  {
636  const char *ifname = va_arg (val, const char *);
637 
638  retval = clickInstance->GetInterfaceId (ifname);
639 
640  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IFID_FROM_NAME: " << ifname << " " << retval);
641  break;
642  }
643 
644  case SIMCLICK_IPADDR_FROM_NAME:
645  {
646  const char *ifname = va_arg (val, const char *);
647  char *buf = va_arg (val, char *);
648  int len = va_arg (val, int);
649 
650  int ifid = clickInstance->GetInterfaceId (ifname);
651 
652  if (ifid >= 0)
653  {
654  retval = simstrlcpy (buf, len, clickInstance->GetIpAddressFromInterfaceId (ifid));
655  }
656  else
657  {
658  retval = -1;
659  }
660 
661  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IPADDR_FROM_NAME: " << ifname << " " << buf << " " << len);
662  break;
663  }
664 
665  case SIMCLICK_IPPREFIX_FROM_NAME:
666  {
667  const char *ifname = va_arg (val, const char *);
668  char *buf = va_arg (val, char *);
669  int len = va_arg (val, int);
670 
671  int ifid = clickInstance->GetInterfaceId (ifname);
672 
673  if (ifid >= 0)
674  {
675  retval = simstrlcpy (buf, len, clickInstance->GetIpPrefixFromInterfaceId (ifid));
676  }
677  else
678  {
679  retval = -1;
680  }
681 
682  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IPPREFIX_FROM_NAME: " << ifname << " " << buf << " " << len);
683  break;
684  }
685 
686  case SIMCLICK_MACADDR_FROM_NAME:
687  {
688  const char *ifname = va_arg (val, const char *);
689  char *buf = va_arg (val, char *);
690  int len = va_arg (val, int);
691  int ifid = clickInstance->GetInterfaceId (ifname);
692 
693  if (ifid >= 0)
694  {
695  retval = simstrlcpy (buf, len, clickInstance->GetMacAddressFromInterfaceId (ifid));
696  }
697  else
698  {
699  retval = -1;
700  }
701 
702  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_MACADDR_FROM_NAME: " << ifname << " " << buf << " " << len);
703  break;
704  }
705 
706  case SIMCLICK_SCHEDULE:
707  {
708  const struct timeval *when = va_arg (val, const struct timeval *);
709 
710  clickInstance->HandleScheduleFromClick (when);
711 
712  retval = 0;
713  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_SCHEDULE at " << when->tv_sec << "s and " << when->tv_usec << "usecs.");
714 
715  break;
716  }
717 
718  case SIMCLICK_GET_NODE_NAME:
719  {
720  char *buf = va_arg (val, char *);
721  int len = va_arg (val, int);
722  retval = simstrlcpy (buf, len, clickInstance->GetNodeName ());
723 
724  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_GET_NODE_NAME: " << buf << " " << len);
725  break;
726  }
727 
728  case SIMCLICK_IF_PROMISC:
729  {
730  int ifid = va_arg(val, int);
731  clickInstance->SetPromisc (ifid);
732 
733  retval = 0;
734  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IF_PROMISC: " << ifid << " " << ns3::Simulator::Now ());
735  break;
736  }
737 
738  case SIMCLICK_IF_READY:
739  {
740  int ifid = va_arg (val, int); // Commented out so that optimized build works
741 
742  // We're not using a ClickQueue, so we're always ready (for the timebeing)
743  retval = clickInstance->IsInterfaceReady (ifid);
744 
745  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IF_READY: " << ifid << " " << ns3::Simulator::Now ());
746  break;
747  }
748 
749  case SIMCLICK_TRACE:
750  {
751  // Used only for tracing
752  NS_LOG_DEBUG (clickInstance->GetNodeName () << " Received a call for SIMCLICK_TRACE");
753  break;
754  }
755 
756  case SIMCLICK_GET_NODE_ID:
757  {
758  // Used only for tracing
759  NS_LOG_DEBUG (clickInstance->GetNodeName () << " Received a call for SIMCLICK_GET_NODE_ID");
760  break;
761  }
762 
763  case SIMCLICK_GET_RANDOM_INT:
764  {
765  uint32_t *randomValue = va_arg (val, uint32_t *);
766  uint32_t maxValue = va_arg (val, uint32_t);
767 
768  *randomValue = static_cast<uint32_t> (clickInstance->GetRandomVariable ()->GetValue (0.0, static_cast<double> (maxValue) + 1.0));
769  retval = 0;
770  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_RANDOM: " << *randomValue << " " << maxValue << " " << ns3::Simulator::Now ());
771  break;
772  }
773 
774  case SIMCLICK_GET_DEFINES:
775  {
776  char *buf = va_arg (val, char *);
777  size_t *size = va_arg (val, size_t *);
778  uint32_t required = 0;
779 
780  // Try to fill the buffer with up to size bytes.
781  // If this is not enough space, write the required buffer size into
782  // the size variable and return an error code.
783  // Otherwise return the bytes actually writte into the buffer in size.
784 
785  // Append key/value pair, seperated by \0.
786  std::map<std::string, std::string> defines = clickInstance->GetDefines ();
787  std::map<std::string, std::string>::const_iterator it = defines.begin ();
788  while (it != defines.end ())
789  {
790  size_t available = *size - required;
791  if (it->first.length() + it->second.length() + 2 <= available)
792  {
793  simstrlcpy(buf + required, available, it->first);
794  required += it->first.length() + 1;
795  available -= it->first.length() + 1;
796  simstrlcpy(buf + required, available, it->second);
797  required += it->second.length() + 1;
798  }
799  else
800  {
801  required += it->first.length() + it->second.length() + 2;
802  }
803  it++;
804  }
805  if (required > *size)
806  {
807  retval = -1;
808  }
809  else
810  {
811  retval = 0;
812  }
813  *size = required;
814  }
815  }
816  return retval;
817 }
818 
819 #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:59
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:345
#define NS_ASSERT(condition)
Definition: assert.h:64
NS_OBJECT_ENSURE_REGISTERED(NullMessageSimulatorImpl)
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:171
int64_t GetFemtoSeconds(void) const
Definition: nstime.h:315
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
double GetSeconds(void) const
Definition: nstime.h:274
int64_t GetMicroSeconds(void) const
Definition: nstime.h:291
uint8_t data[writeSize]
Ptr< SampleEmitter > s
static Time Now(void)
Return the "current simulation time".
Definition: simulator.cc:180
int64_t GetNanoSeconds(void) const
Definition: nstime.h:299
int64_t GetPicoSeconds(void) const
Definition: nstime.h:307
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
#define NS_LOG_DEBUG(msg)
Definition: log.h:289
tuple address
Definition: first.py:37
static TypeId GetTypeId(void)
Get the type ID.
TypeId SetParent(TypeId tid)
Definition: type-id.cc:611