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 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 
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  *stream->GetStream () << "\nCLICK Routing table printing is not yet implemented, skipping.\n";
563 }
564 
565 void
566 Ipv4ClickRouting::NotifyInterfaceUp (uint32_t i)
567 {
568 }
569 
570 void
571 Ipv4ClickRouting::NotifyInterfaceDown (uint32_t i)
572 {
573 }
574 
575 void
576 Ipv4ClickRouting::NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address)
577 {
578 }
579 
580 void
581 Ipv4ClickRouting::NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address)
582 {
583 }
584 
585 
586 } // namespace ns3
587 
588 using ns3::g_log;
589 
590 static 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.
609 int 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
628 int 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)