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 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  ;
59 
60  return tid;
61 }
62 
63 Ipv4ClickRouting::Ipv4ClickRouting ()
64  : m_nonDefaultName (false),
65  m_ipv4 (0)
66 {
67  m_random = CreateObject<UniformRandomVariable> ();
68  m_simNode = new simclick_node_t;
69  timerclear (&m_simNode->curtime);
70 
71  AddSimNodeToClickMapping ();
72 }
73 
74 Ipv4ClickRouting::~Ipv4ClickRouting ()
75 {
76 }
77 
78 void
79 Ipv4ClickRouting::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 
109 void
110 Ipv4ClickRouting::SetIpv4 (Ptr<Ipv4> ipv4)
111 {
112  m_ipv4 = ipv4;
113 }
114 
115 Ptr<UniformRandomVariable>
116 Ipv4ClickRouting::GetRandomVariable (void)
117 {
118  return m_random;
119 }
120 
121 void
122 Ipv4ClickRouting::DoDispose ()
123 {
124  if (m_clickInitialised)
125  {
126  simclick_click_kill (m_simNode);
127  }
128  m_ipv4 = 0;
129  delete m_simNode;
130  Ipv4RoutingProtocol::DoDispose ();
131 }
132 
133 void
134 Ipv4ClickRouting::SetClickFile (std::string clickfile)
135 {
136  m_clickFile = clickfile;
137 }
138 
139 void
140 Ipv4ClickRouting::SetDefines (std::map<std::string, std::string> defines)
141 {
142  m_defines = defines;
143 }
144 
145 std::map<std::string, std::string>
146 Ipv4ClickRouting::GetDefines (void)
147 {
148  return m_defines;
149 }
150 
151 void
152 Ipv4ClickRouting::SetClickRoutingTableElement (std::string name)
153 {
154  m_clickRoutingTableElement = name;
155 }
156 
157 void
158 Ipv4ClickRouting::SetNodeName (std::string name)
159 {
160  m_nodeName = name;
161  m_nonDefaultName = true;
162 }
163 
164 std::string
165 Ipv4ClickRouting::GetNodeName ()
166 {
167  return m_nodeName;
168 }
169 
170 int
171 Ipv4ClickRouting::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 intialisation
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 
227 bool
228 Ipv4ClickRouting::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 
240 std::string
241 Ipv4ClickRouting::GetIpAddressFromInterfaceId (int ifid)
242 {
243  std::stringstream addr;
244  m_ipv4->GetAddress (ifid, 0).GetLocal ().Print (addr);
245 
246  return addr.str ();
247 }
248 
249 std::string
250 Ipv4ClickRouting::GetIpPrefixFromInterfaceId (int ifid)
251 {
252  std::stringstream addr;
253  m_ipv4->GetAddress (ifid, 0).GetMask ().Print (addr);
254 
255  return addr.str ();
256 }
257 
258 std::string
259 Ipv4ClickRouting::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 
270 void
271 Ipv4ClickRouting::AddSimNodeToClickMapping ()
272 {
273  m_clickInstanceFromSimNode.insert (std::make_pair (m_simNode, this));
274 }
275 
276 Ptr<Ipv4ClickRouting>
277 Ipv4ClickRouting::GetClickInstanceFromSimNode (simclick_node_t *simnode)
278 {
279  return m_clickInstanceFromSimNode[simnode];
280 }
281 
282 struct timeval
283 Ipv4ClickRouting::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 
319 void
320 Ipv4ClickRouting::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 
329 void
330 Ipv4ClickRouting::HandleScheduleFromClick (const struct timeval *when)
331 {
332  NS_LOG_DEBUG ("HandleScheduleFromClick at " << when->tv_sec << " " << when->tv_usec << " " << Simulator::Now ());
333 
334  Time simtime = Time::FromInteger(when->tv_sec, Time::S) + Time::FromInteger(when->tv_usec, Time::US);
335  Time simdelay = simtime - Simulator::Now();
336 
337  Simulator::Schedule (simdelay, &Ipv4ClickRouting::RunClickEvent, this);
338 }
339 
340 void
341 Ipv4ClickRouting::HandlePacketFromClick (int ifid, int ptype, const unsigned char* data, int len)
342 {
343  NS_LOG_DEBUG ("HandlePacketFromClick");
344 
345  // Figure out packet's destination here:
346  // If ifid == 0, then the packet's going up
347  // else, the packet's going down
348  if (ifid == 0)
349  {
350  NS_LOG_DEBUG ("Incoming packet from tap0. Sending Packet up the stack.");
351  Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol> (m_ipv4);
352 
353  Ptr<Packet> p = Create<Packet> (data, len);
354 
355  Ipv4Header ipHeader;
356  p->RemoveHeader (ipHeader);
357 
358  ipv4l3->LocalDeliver (p, ipHeader, (uint32_t) ifid);
359  }
360  else if (ifid)
361  {
362  NS_LOG_DEBUG ("Incoming packet from eth" << ifid - 1 << " of type " << ptype << ". Sending packet down the stack.");
363 
364  Ptr<Packet> p = Create<Packet> (data, len);
365 
366  DynamicCast<Ipv4L3ClickProtocol> (m_ipv4)->SendDown (p, ifid);
367  }
368 }
369 
370 void
371 Ipv4ClickRouting::SendPacketToClick (int ifid, int ptype, const unsigned char* data, int len)
372 {
373  NS_LOG_FUNCTION (this << ifid);
374  m_simNode->curtime = GetTimevalFromNow ();
375 
376  // Since packets in ns-3 don't have global Packet ID's and Flow ID's, we
377  // feed dummy values into pinfo. This avoids the need to make changes in the Click code
378  simclick_simpacketinfo pinfo;
379  pinfo.id = 0;
380  pinfo.fid = 0;
381 
382  simclick_click_send (m_simNode,ifid,ptype,data,len,&pinfo);
383 }
384 
385 void
386 Ipv4ClickRouting::Send (Ptr<Packet> p, Ipv4Address src, Ipv4Address dst)
387 {
388  uint32_t ifid;
389 
390  // Find out which interface holds the src address of the packet...
391  for (ifid = 0; ifid < m_ipv4->GetNInterfaces (); ifid++)
392  {
393  Ipv4Address addr = m_ipv4->GetAddress (ifid, 0).GetLocal ();
394 
395  if (addr == src)
396  {
397  break;
398  }
399  }
400 
401  int len = p->GetSize ();
402  uint8_t *buf = new uint8_t [len];
403  p->CopyData (buf, len);
404 
405  // ... and send the packet on the corresponding Click interface.
406  SendPacketToClick (0, SIMCLICK_PTYPE_IP, buf, len);
407 
408  delete [] buf;
409 }
410 
411 void
412 Ipv4ClickRouting::Receive (Ptr<Packet> p, Mac48Address receiverAddr, Mac48Address dest)
413 {
414  NS_LOG_FUNCTION (this << p << receiverAddr << dest);
415 
416  uint32_t ifid;
417 
418  // Find out which device this packet was received from...
419  for (ifid = 0; ifid < m_ipv4->GetNInterfaces (); ifid++)
420  {
421  Ptr<NetDevice> device = m_ipv4->GetNetDevice (ifid);
422 
423  if (Mac48Address::ConvertFrom (device->GetAddress ()) == receiverAddr)
424  {
425  break;
426  }
427  }
428 
429  int len = p->GetSize ();
430  uint8_t *buf = new uint8_t [len];
431  p->CopyData (buf, len);
432 
433  // ... and send the packet to the corresponding Click interface
434  SendPacketToClick (ifid, SIMCLICK_PTYPE_ETHER, buf, len);
435 
436  delete [] buf;
437 }
438 
439 std::string
440 Ipv4ClickRouting::ReadHandler (std::string elementName, std::string handlerName)
441 {
442  char *handle = simclick_click_read_handler (m_simNode, elementName.c_str (), handlerName.c_str (), 0, 0);
443  std::string ret (handle);
444 
445  // This is required because Click does not free
446  // the memory allocated to the return string
447  // from simclick_click_read_handler()
448  free(handle);
449 
450  return ret;
451 }
452 
453 int
454 Ipv4ClickRouting::WriteHandler (std::string elementName, std::string handlerName, std::string writeString)
455 {
456  int r = simclick_click_write_handler (m_simNode, elementName.c_str (), handlerName.c_str (), writeString.c_str ());
457 
458  // Note: There are probably use-cases for returning
459  // a write handler's error code, so don't assert.
460  // For example, the 'add' handler for IPRouteTable
461  // type elements fails if the route to be added
462  // already exists.
463 
464  return r;
465 }
466 
467 void
468 Ipv4ClickRouting::SetPromisc (int ifid)
469 {
470  Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol> (m_ipv4);
471  NS_ASSERT(ipv4l3);
472  ipv4l3->SetPromisc (ifid);
473 }
474 
475 Ptr<Ipv4Route>
476 Ipv4ClickRouting::RouteOutput (Ptr<Packet> p, const Ipv4Header &header, Ptr<NetDevice> oif, Socket::SocketErrno &sockerr)
477 {
478  Ptr<Ipv4Route> rtentry;
479 
480  std::stringstream addr;
481  addr << "lookup ";
482  header.GetDestination ().Print (addr);
483  // Probe the Click Routing Table for the required IP
484  // This returns a string of the form "InterfaceID GatewayAddr"
485  std::string s = ReadHandler (m_clickRoutingTableElement, addr.str ());
486 
487  int pos = s.find (" ");
488 
489  int interfaceId = atoi (s.substr (0, pos).c_str ());
490  Ipv4Address destination (s.substr (pos + 1).c_str ());
491 
492  if (interfaceId != -1)
493  {
494  rtentry = Create<Ipv4Route> ();
495  rtentry->SetDestination (header.GetDestination ());
496  // the source address is the interface address that matches
497  // the destination address (when multiple are present on the
498  // outgoing interface, one is selected via scoping rules)
499  NS_ASSERT (m_ipv4);
500  uint32_t numOifAddresses = m_ipv4->GetNAddresses (interfaceId);
501  NS_ASSERT (numOifAddresses > 0);
502  Ipv4InterfaceAddress ifAddr;
503  if (numOifAddresses == 1)
504  {
505  ifAddr = m_ipv4->GetAddress (interfaceId, 0);
506  }
507  else
508  {
510  NS_FATAL_ERROR ("XXX Not implemented yet: IP aliasing and Click");
511  }
512  rtentry->SetSource (ifAddr.GetLocal ());
513  rtentry->SetGateway (destination);
514  rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceId));
515  sockerr = Socket::ERROR_NOTERROR;
516  NS_LOG_DEBUG ("Found route to " << rtentry->GetDestination ()
517  << " via nh " << rtentry->GetGateway ()
518  << " with source addr " << rtentry->GetSource ()
519  << " and output dev " << rtentry->GetOutputDevice ());
520  }
521  else
522  {
523  NS_LOG_DEBUG ("Click node " << m_nodeName
524  << ": RouteOutput for dest=" << header.GetDestination ()
525  << " No route to host");
526  sockerr = Socket::ERROR_NOROUTETOHOST;
527  }
528 
529  return rtentry;
530 }
531 
532 // This method should never be called since Click handles
533 // forwarding directly
534 bool
535 Ipv4ClickRouting::RouteInput (Ptr<const Packet> p, const Ipv4Header &header,
536  Ptr<const NetDevice> idev, UnicastForwardCallback ucb,
537  MulticastForwardCallback mcb, LocalDeliverCallback lcb,
538  ErrorCallback ecb)
539 {
540  NS_FATAL_ERROR ("Click router does not have a RouteInput() interface!");
541  return false;
542 }
543 
544 void
545 Ipv4ClickRouting::PrintRoutingTable (Ptr<OutputStreamWrapper> stream) const
546 {
547 }
548 
549 void
550 Ipv4ClickRouting::NotifyInterfaceUp (uint32_t i)
551 {
552 }
553 
554 void
555 Ipv4ClickRouting::NotifyInterfaceDown (uint32_t i)
556 {
557 }
558 
559 void
560 Ipv4ClickRouting::NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address)
561 {
562 }
563 
564 void
565 Ipv4ClickRouting::NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address)
566 {
567 }
568 
569 
570 } // namespace ns3
571 
572 static int simstrlcpy (char *buf, int len, const std::string &s)
573 {
574  if (len)
575  {
576  len--;
577 
578  if ((unsigned) len > s.length ())
579  {
580  len = s.length ();
581  }
582 
583  s.copy (buf, len);
584  buf[len] = '\0';
585  }
586  return 0;
587 }
588 
589 // Sends a Packet from Click to the Simulator: Defined in simclick.h. Click
590 // calls these methods.
591 int simclick_sim_send (simclick_node_t *simnode,
592  int ifid, int type, const unsigned char* data, int len,
593  simclick_simpacketinfo *pinfo)
594 {
595  NS_LOG_DEBUG ("simclick_sim_send called at " << ns3::Simulator::Now ().GetSeconds () << ": " << ifid << " " << type << " " << data << " " << len);
596 
597  if (simnode == NULL)
598  {
599  return -1;
600  }
601 
602  ns3::Ptr<ns3::Ipv4ClickRouting> clickInstance = ns3::Ipv4ClickRouting::GetClickInstanceFromSimNode (simnode);
603 
604  clickInstance->HandlePacketFromClick (ifid, type, data, len);
605 
606  return 0;
607 }
608 
609 // Click Service Methods: Defined in simclick.h
610 int simclick_sim_command (simclick_node_t *simnode, int cmd, ...)
611 {
612  va_list val;
613  va_start (val, cmd);
614 
615  int retval = 0;
616 
617  ns3::Ptr<ns3::Ipv4ClickRouting> clickInstance = ns3::Ipv4ClickRouting::GetClickInstanceFromSimNode (simnode);
618  switch (cmd)
619  {
620  case SIMCLICK_VERSION:
621  {
622  retval = 0;
623  break;
624  }
625 
626  case SIMCLICK_SUPPORTS:
627  {
628  int othercmd = va_arg (val, int);
629  retval = (othercmd >= SIMCLICK_VERSION && othercmd <= SIMCLICK_GET_DEFINES);
630  break;
631  }
632 
633  case SIMCLICK_IFID_FROM_NAME:
634  {
635  const char *ifname = va_arg (val, const char *);
636 
637  retval = clickInstance->GetInterfaceId (ifname);
638 
639  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IFID_FROM_NAME: " << ifname << " " << retval);
640  break;
641  }
642 
643  case SIMCLICK_IPADDR_FROM_NAME:
644  {
645  const char *ifname = va_arg (val, const char *);
646  char *buf = va_arg (val, char *);
647  int len = va_arg (val, int);
648 
649  int ifid = clickInstance->GetInterfaceId (ifname);
650 
651  if (ifid >= 0)
652  {
653  retval = simstrlcpy (buf, len, clickInstance->GetIpAddressFromInterfaceId (ifid));
654  }
655  else
656  {
657  retval = -1;
658  }
659 
660  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IPADDR_FROM_NAME: " << ifname << " " << buf << " " << len);
661  break;
662  }
663 
664  case SIMCLICK_IPPREFIX_FROM_NAME:
665  {
666  const char *ifname = va_arg (val, const char *);
667  char *buf = va_arg (val, char *);
668  int len = va_arg (val, int);
669 
670  int ifid = clickInstance->GetInterfaceId (ifname);
671 
672  if (ifid >= 0)
673  {
674  retval = simstrlcpy (buf, len, clickInstance->GetIpPrefixFromInterfaceId (ifid));
675  }
676  else
677  {
678  retval = -1;
679  }
680 
681  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IPPREFIX_FROM_NAME: " << ifname << " " << buf << " " << len);
682  break;
683  }
684 
685  case SIMCLICK_MACADDR_FROM_NAME:
686  {
687  const char *ifname = va_arg (val, const char *);
688  char *buf = va_arg (val, char *);
689  int len = va_arg (val, int);
690  int ifid = clickInstance->GetInterfaceId (ifname);
691 
692  if (ifid >= 0)
693  {
694  retval = simstrlcpy (buf, len, clickInstance->GetMacAddressFromInterfaceId (ifid));
695  }
696  else
697  {
698  retval = -1;
699  }
700 
701  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_MACADDR_FROM_NAME: " << ifname << " " << buf << " " << len);
702  break;
703  }
704 
705  case SIMCLICK_SCHEDULE:
706  {
707  const struct timeval *when = va_arg (val, const struct timeval *);
708 
709  clickInstance->HandleScheduleFromClick (when);
710 
711  retval = 0;
712  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_SCHEDULE at " << when->tv_sec << "s and " << when->tv_usec << "usecs.");
713 
714  break;
715  }
716 
717  case SIMCLICK_GET_NODE_NAME:
718  {
719  char *buf = va_arg (val, char *);
720  int len = va_arg (val, int);
721  retval = simstrlcpy (buf, len, clickInstance->GetNodeName ());
722 
723  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_GET_NODE_NAME: " << buf << " " << len);
724  break;
725  }
726 
727  case SIMCLICK_IF_PROMISC:
728  {
729  int ifid = va_arg(val, int);
730  clickInstance->SetPromisc (ifid);
731 
732  retval = 0;
733  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IF_PROMISC: " << ifid << " " << ns3::Simulator::Now ());
734  break;
735  }
736 
737  case SIMCLICK_IF_READY:
738  {
739  int ifid = va_arg (val, int); // Commented out so that optimized build works
740 
741  // We're not using a ClickQueue, so we're always ready (for the timebeing)
742  retval = clickInstance->IsInterfaceReady (ifid);
743 
744  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IF_READY: " << ifid << " " << ns3::Simulator::Now ());
745  break;
746  }
747 
748  case SIMCLICK_TRACE:
749  {
750  // Used only for tracing
751  NS_LOG_DEBUG (clickInstance->GetNodeName () << " Received a call for SIMCLICK_TRACE");
752  break;
753  }
754 
755  case SIMCLICK_GET_NODE_ID:
756  {
757  // Used only for tracing
758  NS_LOG_DEBUG (clickInstance->GetNodeName () << " Received a call for SIMCLICK_GET_NODE_ID");
759  break;
760  }
761 
762  case SIMCLICK_GET_RANDOM_INT:
763  {
764  uint32_t *randomValue = va_arg (val, uint32_t *);
765  uint32_t maxValue = va_arg (val, uint32_t);
766 
767  *randomValue = static_cast<uint32_t> (clickInstance->GetRandomVariable ()->GetValue (0.0, static_cast<double> (maxValue) + 1.0));
768  retval = 0;
769  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_RANDOM: " << *randomValue << " " << maxValue << " " << ns3::Simulator::Now ());
770  break;
771  }
772 
773  case SIMCLICK_GET_DEFINES:
774  {
775  char *buf = va_arg (val, char *);
776  size_t *size = va_arg (val, size_t *);
777  uint32_t required = 0;
778 
779  // Try to fill the buffer with up to size bytes.
780  // If this is not enough space, write the required buffer size into
781  // the size variable and return an error code.
782  // Otherwise return the bytes actually writte into the buffer in size.
783 
784  // Append key/value pair, seperated by \0.
785  std::map<std::string, std::string> defines = clickInstance->GetDefines ();
786  std::map<std::string, std::string>::const_iterator it = defines.begin ();
787  while (it != defines.end ())
788  {
789  size_t available = *size - required;
790  if (it->first.length() + it->second.length() + 2 <= available)
791  {
792  simstrlcpy(buf + required, available, it->first);
793  required += it->first.length() + 1;
794  available -= it->first.length() + 1;
795  simstrlcpy(buf + required, available, it->second);
796  required += it->second.length() + 1;
797  }
798  else
799  {
800  required += it->first.length() + it->second.length() + 2;
801  }
802  it++;
803  }
804  if (required > *size)
805  {
806  retval = -1;
807  }
808  else
809  {
810  retval = 0;
811  }
812  *size = required;
813  }
814  }
815  return retval;
816 }
817 
818 #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:60
#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 the class in the ns-3 factory.
Definition: object-base.h:38
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:61
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:95
int64_t GetFemtoSeconds(void) const
Definition: nstime.h:313
double GetSeconds(void) const
Definition: nstime.h:272
int64_t GetMicroSeconds(void) const
Definition: nstime.h:289
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:297
int64_t GetPicoSeconds(void) const
Definition: nstime.h:305
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:213
tuple address
Definition: first.py:37
static TypeId GetTypeId(void)
Get the type ID.
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610