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/mac48-address.h"
28 #include "ns3/ipv4-interface.h"
29 #include "ns3/ipv4-l3-click-protocol.h"
30 
31 #include "ipv4-click-routing.h"
32 #include <string>
33 #include <map>
34 
35 #include <cstdlib>
36 #include <cstdarg>
37 
38 NS_LOG_COMPONENT_DEFINE ("Ipv4ClickRouting");
39 
40 namespace ns3 {
41 
42 // Values from nsclick ExtRouter implementation
43 #define INTERFACE_ID_KERNELTAP 0
44 #define INTERFACE_ID_FIRST 1
45 #define INTERFACE_ID_FIRST_DROP 33
46 
47 NS_OBJECT_ENSURE_REGISTERED (Ipv4ClickRouting);
48 
49 std::map < simclick_node_t *, Ptr<Ipv4ClickRouting> > Ipv4ClickRouting::m_clickInstanceFromSimNode;
50 
51 TypeId
53 {
54  static TypeId tid = TypeId ("ns3::Ipv4ClickRouting")
55  .SetParent<Ipv4RoutingProtocol> ()
56  .AddConstructor<Ipv4ClickRouting> ()
57  ;
58 
59  return tid;
60 }
61 
62 Ipv4ClickRouting::Ipv4ClickRouting ()
63  : m_nonDefaultName (false),
64  m_ipv4 (0)
65 {
66 }
67 
68 Ipv4ClickRouting::~Ipv4ClickRouting ()
69 {
70 }
71 
72 void
73 Ipv4ClickRouting::DoStart ()
74 {
75  uint32_t id = m_ipv4->GetObject<Node> ()->GetId ();
76 
77  if (!m_nonDefaultName)
78  {
79  std::stringstream name;
80  name << "Node" << id;
81  m_nodeName = name.str ();
82  }
83 
84  m_simNode = new simclick_node_t;
85  timerclear (&m_simNode->curtime);
86 
87  AddSimNodeToClickMapping ();
88 
89  NS_ASSERT (m_clickFile.length () > 0);
90 
91  // Even though simclick_click_create() will halt programme execution
92  // if it is unable to initialise a Click router, we play safe
93  if (simclick_click_create (m_simNode, m_clickFile.c_str ()) >= 0)
94  {
95  NS_LOG_DEBUG (m_nodeName << " has initialised a Click Router");
96  m_clickInitialised = true;
97  }
98  else
99  {
100  NS_LOG_DEBUG ("Click Router Initialisation failed for " << m_nodeName);
101  m_clickInitialised = false;
102  }
103 
104  NS_ASSERT (m_clickInitialised == true);
105  simclick_click_run (m_simNode);
106 }
107 
108 void
109 Ipv4ClickRouting::SetIpv4 (Ptr<Ipv4> ipv4)
110 {
111  m_ipv4 = ipv4;
112 }
113 
114 void
115 Ipv4ClickRouting::DoDispose ()
116 {
117  if (m_clickInitialised)
118  {
119  simclick_click_kill (m_simNode);
120  }
121  m_ipv4 = 0;
122  delete m_simNode;
123  Ipv4RoutingProtocol::DoDispose ();
124 }
125 
126 void
127 Ipv4ClickRouting::SetClickFile (std::string clickfile)
128 {
129  m_clickFile = clickfile;
130 }
131 
132 void
133 Ipv4ClickRouting::SetClickRoutingTableElement (std::string name)
134 {
135  m_clickRoutingTableElement = name;
136 }
137 
138 void
139 Ipv4ClickRouting::SetNodeName (std::string name)
140 {
141  m_nodeName = name;
142  m_nonDefaultName = true;
143 }
144 
145 std::string
146 Ipv4ClickRouting::GetNodeName ()
147 {
148  return m_nodeName;
149 }
150 
151 int
152 Ipv4ClickRouting::GetInterfaceId (const char *ifname)
153 {
154  int retval = -1;
155 
156  // The below hard coding of interface names follows the
157  // same approach as used in the original nsclick code for
158  // ns-2. The interface names map directly to what is to
159  // be used in the Click configuration files.
160  // Thus eth0 will refer to the first network device of
161  // the node, and is to be named so in the Click graph.
162  // This function is called by Click during the intialisation
163  // phase of the Click graph, during which it tries to map
164  // interface IDs to interface names. The return value
165  // corresponds to the interface ID that Click will use.
166 
167  // Tap/tun devices refer to the kernel devices
168  if (strstr (ifname, "tap") || strstr (ifname, "tun"))
169  {
170  retval = 0;
171  }
172  else if (const char *devname = strstr (ifname, "eth"))
173  {
174  while (*devname && !isdigit ((unsigned char) *devname))
175  {
176  devname++;
177  }
178 
179  if (*devname)
180  {
181  retval = atoi (devname) + INTERFACE_ID_FIRST;
182  }
183  }
184  else if (const char *devname = strstr (ifname, "drop"))
185  {
186  while (*devname && !isdigit ((unsigned char) *devname))
187  {
188  devname++;
189  }
190  if (*devname)
191  {
192  retval = atoi (devname) + INTERFACE_ID_FIRST_DROP;
193  }
194  }
195 
196  // This protects against a possible inconsistency of having
197  // more interfaces defined in the Click graph
198  // for a Click node than are defined for it in
199  // the simulation script
200  if (retval >= (int) m_ipv4->GetNInterfaces ())
201  {
202  return -1;
203  }
204 
205  return retval;
206 }
207 
208 bool
209 Ipv4ClickRouting::IsInterfaceReady (int ifid)
210 {
211  if (ifid >= 0 && ifid < (int) m_ipv4->GetNInterfaces ())
212  {
213  return true;
214  }
215  else
216  {
217  return false;
218  }
219 }
220 
221 std::string
222 Ipv4ClickRouting::GetIpAddressFromInterfaceId (int ifid)
223 {
224  std::stringstream addr;
225  m_ipv4->GetAddress (ifid, 0).GetLocal ().Print (addr);
226 
227  return addr.str ();
228 }
229 
230 std::string
231 Ipv4ClickRouting::GetIpPrefixFromInterfaceId (int ifid)
232 {
233  std::stringstream addr;
234  m_ipv4->GetAddress (ifid, 0).GetMask ().Print (addr);
235 
236  return addr.str ();
237 }
238 
239 std::string
240 Ipv4ClickRouting::GetMacAddressFromInterfaceId (int ifid)
241 {
242  std::stringstream addr;
243 
244  Ptr<NetDevice> device = m_ipv4->GetNetDevice (ifid);
245  Address devAddr = device->GetAddress ();
246  addr << Mac48Address::ConvertFrom (devAddr);
247 
248  return addr.str ();
249 }
250 
251 void
252 Ipv4ClickRouting::AddSimNodeToClickMapping ()
253 {
254  m_clickInstanceFromSimNode.insert (std::make_pair (m_simNode, this));
255 }
256 
257 Ptr<Ipv4ClickRouting>
258 Ipv4ClickRouting::GetClickInstanceFromSimNode (simclick_node_t *simnode)
259 {
260  return m_clickInstanceFromSimNode[simnode];
261 }
262 
263 struct timeval
264 Ipv4ClickRouting::GetTimevalFromNow () const
265 {
266  struct timeval curtime;
267  uint64_t remainder = 0;
268 
269  curtime.tv_sec = Simulator::Now ().GetSeconds ();
270  curtime.tv_usec = Simulator::Now ().GetMicroSeconds () % 1000000;
271 
272  switch (Simulator::Now ().GetResolution())
273  {
274  case Time::NS:
275  remainder = Simulator::Now ().GetNanoSeconds () % 1000;
276  break;
277  case Time::PS:
278  remainder = Simulator::Now ().GetPicoSeconds () % 1000000;
279  break;
280  case Time::FS:
281  remainder = Simulator::Now ().GetFemtoSeconds () % 1000000000;
282  break;
283  default:
284  break;
285  }
286 
287  if (remainder)
288  {
289  ++curtime.tv_usec;
290  if (curtime.tv_usec == 1000000)
291  {
292  ++curtime.tv_sec;
293  curtime.tv_usec = 0;
294  }
295  }
296 
297  return curtime;
298 }
299 
300 void
301 Ipv4ClickRouting::RunClickEvent ()
302 {
303  m_simNode->curtime = GetTimevalFromNow ();
304 
305  NS_LOG_DEBUG ("RunClickEvent at " << m_simNode->curtime.tv_sec << " " <<
306  m_simNode->curtime.tv_usec << " " << Simulator::Now ());
307  simclick_click_run (m_simNode);
308 }
309 
310 void
311 Ipv4ClickRouting::HandleScheduleFromClick (const struct timeval *when)
312 {
313  NS_LOG_DEBUG ("HandleScheduleFromClick at " << when->tv_sec << " " << when->tv_usec << " " << Simulator::Now ());
314 
315  Time simtime = Time::FromInteger(when->tv_sec, Time::S) + Time::FromInteger(when->tv_usec, Time::US);
316  Time simdelay = simtime - Simulator::Now();
317 
318  Simulator::Schedule (simdelay, &Ipv4ClickRouting::RunClickEvent, this);
319 }
320 
321 void
322 Ipv4ClickRouting::HandlePacketFromClick (int ifid, int ptype, const unsigned char* data, int len)
323 {
324  NS_LOG_DEBUG ("HandlePacketFromClick");
325 
326  // Figure out packet's destination here:
327  // If ifid == 0, then the packet's going up
328  // else, the packet's going down
329  if (ifid == 0)
330  {
331  NS_LOG_DEBUG ("Incoming packet from tap0. Sending Packet up the stack.");
332  Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol> (m_ipv4);
333 
334  Ptr<Packet> p = Create<Packet> (data, len);
335 
336  Ipv4Header ipHeader;
337  p->RemoveHeader (ipHeader);
338 
339  ipv4l3->LocalDeliver (p, ipHeader, (uint32_t) ifid);
340  }
341  else if (ifid)
342  {
343  NS_LOG_DEBUG ("Incoming packet from eth" << ifid - 1 << " of type " << ptype << ". Sending packet down the stack.");
344 
345  Ptr<Packet> p = Create<Packet> (data, len);
346 
347  DynamicCast<Ipv4L3ClickProtocol> (m_ipv4)->SendDown (p, ifid);
348  }
349 }
350 
351 void
352 Ipv4ClickRouting::SendPacketToClick (int ifid, int ptype, const unsigned char* data, int len)
353 {
354  NS_LOG_FUNCTION (this << ifid);
355  m_simNode->curtime = GetTimevalFromNow ();
356 
357  // Since packets in ns-3 don't have global Packet ID's and Flow ID's, we
358  // feed dummy values into pinfo. This avoids the need to make changes in the Click code
359  simclick_simpacketinfo pinfo;
360  pinfo.id = 0;
361  pinfo.fid = 0;
362 
363  simclick_click_send (m_simNode,ifid,ptype,data,len,&pinfo);
364 }
365 
366 void
367 Ipv4ClickRouting::Send (Ptr<Packet> p, Ipv4Address src, Ipv4Address dst)
368 {
369  uint32_t ifid;
370 
371  // Find out which interface holds the src address of the packet...
372  for (ifid = 0; ifid < m_ipv4->GetNInterfaces (); ifid++)
373  {
374  Ipv4Address addr = m_ipv4->GetAddress (ifid, 0).GetLocal ();
375 
376  if (addr == src)
377  {
378  break;
379  }
380  }
381 
382  int len = p->GetSize ();
383  uint8_t *buf = new uint8_t [len];
384  p->CopyData (buf, len);
385 
386  // ... and send the packet on the corresponding Click interface.
387  SendPacketToClick (0, SIMCLICK_PTYPE_IP, buf, len);
388 
389  delete [] buf;
390 }
391 
392 void
393 Ipv4ClickRouting::Receive (Ptr<Packet> p, Mac48Address receiverAddr, Mac48Address dest)
394 {
395  NS_LOG_FUNCTION (this << p << receiverAddr << dest);
396 
397  uint32_t ifid;
398 
399  // Find out which device this packet was received from...
400  for (ifid = 0; ifid < m_ipv4->GetNInterfaces (); ifid++)
401  {
402  Ptr<NetDevice> device = m_ipv4->GetNetDevice (ifid);
403 
404  if (Mac48Address::ConvertFrom (device->GetAddress ()) == receiverAddr)
405  {
406  break;
407  }
408  }
409 
410  int len = p->GetSize ();
411  uint8_t *buf = new uint8_t [len];
412  p->CopyData (buf, len);
413 
414  // ... and send the packet to the corresponding Click interface
415  SendPacketToClick (ifid, SIMCLICK_PTYPE_ETHER, buf, len);
416 
417  delete [] buf;
418 }
419 
420 std::string
421 Ipv4ClickRouting::ReadHandler (std::string elementName, std::string handlerName)
422 {
423  char *handle = simclick_click_read_handler (m_simNode, elementName.c_str (), handlerName.c_str (), 0, 0);
424  std::string ret (handle);
425 
426  // This is required because Click does not free
427  // the memory allocated to the return string
428  // from simclick_click_read_handler()
429  free(handle);
430 
431  return ret;
432 }
433 
434 int
435 Ipv4ClickRouting::WriteHandler (std::string elementName, std::string handlerName, std::string writeString)
436 {
437  int r = simclick_click_write_handler (m_simNode, elementName.c_str (), handlerName.c_str (), writeString.c_str ());
438 
439  // Note: There are probably use-cases for returning
440  // a write handler's error code, so don't assert.
441  // For example, the 'add' handler for IPRouteTable
442  // type elements fails if the route to be added
443  // already exists.
444 
445  return r;
446 }
447 
448 void
449 Ipv4ClickRouting::SetPromisc (int ifid)
450 {
451  Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol> (m_ipv4);
452  NS_ASSERT(ipv4l3);
453  ipv4l3->SetPromisc (ifid);
454 }
455 
456 Ptr<Ipv4Route>
457 Ipv4ClickRouting::RouteOutput (Ptr<Packet> p, const Ipv4Header &header, Ptr<NetDevice> oif, Socket::SocketErrno &sockerr)
458 {
459  Ptr<Ipv4Route> rtentry;
460 
461  std::stringstream addr;
462  addr << "lookup ";
463  header.GetDestination ().Print (addr);
464  // Probe the Click Routing Table for the required IP
465  // This returns a string of the form "InterfaceID GatewayAddr"
466  std::string s = ReadHandler (m_clickRoutingTableElement, addr.str ());
467 
468  int pos = s.find (" ");
469 
470  int interfaceId = atoi (s.substr (0, pos).c_str ());
471  Ipv4Address destination (s.substr (pos + 1).c_str ());
472 
473  if (interfaceId != -1)
474  {
475  rtentry = Create<Ipv4Route> ();
476  rtentry->SetDestination (header.GetDestination ());
477  // the source address is the interface address that matches
478  // the destination address (when multiple are present on the
479  // outgoing interface, one is selected via scoping rules)
480  NS_ASSERT (m_ipv4);
481  uint32_t numOifAddresses = m_ipv4->GetNAddresses (interfaceId);
482  NS_ASSERT (numOifAddresses > 0);
483  Ipv4InterfaceAddress ifAddr;
484  if (numOifAddresses == 1)
485  {
486  ifAddr = m_ipv4->GetAddress (interfaceId, 0);
487  }
488  else
489  {
490  NS_FATAL_ERROR ("XXX Not implemented yet: IP aliasing and Click");
491  }
492  rtentry->SetSource (ifAddr.GetLocal ());
493  rtentry->SetGateway (destination);
494  rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceId));
495  sockerr = Socket::ERROR_NOTERROR;
496  NS_LOG_DEBUG ("Found route to " << rtentry->GetDestination ()
497  << " via nh " << rtentry->GetGateway ()
498  << " with source addr " << rtentry->GetSource ()
499  << " and output dev " << rtentry->GetOutputDevice ());
500  }
501  else
502  {
503  NS_LOG_DEBUG ("Click node " << m_nodeName
504  << ": RouteOutput for dest=" << header.GetDestination ()
505  << " No route to host");
506  sockerr = Socket::ERROR_NOROUTETOHOST;
507  }
508 
509  return rtentry;
510 }
511 
512 // This method should never be called since Click handles
513 // forwarding directly
514 bool
515 Ipv4ClickRouting::RouteInput (Ptr<const Packet> p, const Ipv4Header &header,
516  Ptr<const NetDevice> idev, UnicastForwardCallback ucb,
517  MulticastForwardCallback mcb, LocalDeliverCallback lcb,
518  ErrorCallback ecb)
519 {
520  NS_FATAL_ERROR ("Click router does not have a RouteInput() interface!");
521  return false;
522 }
523 
524 void
525 Ipv4ClickRouting::PrintRoutingTable (Ptr<OutputStreamWrapper> stream) const
526 {
527 }
528 
529 void
530 Ipv4ClickRouting::NotifyInterfaceUp (uint32_t i)
531 {
532 }
533 
534 void
535 Ipv4ClickRouting::NotifyInterfaceDown (uint32_t i)
536 {
537 }
538 
539 void
540 Ipv4ClickRouting::NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address)
541 {
542 }
543 
544 void
545 Ipv4ClickRouting::NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address)
546 {
547 }
548 
549 
550 } // namespace ns3
551 
552 static int simstrlcpy (char *buf, int len, const std::string &s)
553 {
554  if (len)
555  {
556  len--;
557 
558  if ((unsigned) len > s.length ())
559  {
560  len = s.length ();
561  }
562 
563  s.copy (buf, len);
564  buf[len] = '\0';
565  }
566  return 0;
567 }
568 
569 // Sends a Packet from Click to the Simulator: Defined in simclick.h. Click
570 // calls these methods.
571 int simclick_sim_send (simclick_node_t *simnode,
572  int ifid, int type, const unsigned char* data, int len,
573  simclick_simpacketinfo *pinfo)
574 {
575  NS_LOG_DEBUG ("simclick_sim_send called at " << ns3::Simulator::Now ().GetSeconds () << ": " << ifid << " " << type << " " << data << " " << len);
576 
577  if (simnode == NULL)
578  {
579  return -1;
580  }
581 
582  ns3::Ptr<ns3::Ipv4ClickRouting> clickInstance = ns3::Ipv4ClickRouting::GetClickInstanceFromSimNode (simnode);
583 
584  clickInstance->HandlePacketFromClick (ifid, type, data, len);
585 
586  return 0;
587 }
588 
589 // Click Service Methods: Defined in simclick.h
590 int simclick_sim_command (simclick_node_t *simnode, int cmd, ...)
591 {
592  va_list val;
593  va_start (val, cmd);
594 
595  int retval = 0;
596 
597  ns3::Ptr<ns3::Ipv4ClickRouting> clickInstance = ns3::Ipv4ClickRouting::GetClickInstanceFromSimNode (simnode);
598  switch (cmd)
599  {
600  case SIMCLICK_VERSION:
601  {
602  retval = 0;
603  break;
604  }
605 
606  case SIMCLICK_SUPPORTS:
607  {
608  int othercmd = va_arg (val, int);
609  retval = (othercmd >= SIMCLICK_VERSION && othercmd <= SIMCLICK_GET_NODE_ID);
610  break;
611  }
612 
613  case SIMCLICK_IFID_FROM_NAME:
614  {
615  const char *ifname = va_arg (val, const char *);
616 
617  retval = clickInstance->GetInterfaceId (ifname);
618 
619  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IFID_FROM_NAME: " << ifname << " " << retval);
620  break;
621  }
622 
623  case SIMCLICK_IPADDR_FROM_NAME:
624  {
625  const char *ifname = va_arg (val, const char *);
626  char *buf = va_arg (val, char *);
627  int len = va_arg (val, int);
628 
629  int ifid = clickInstance->GetInterfaceId (ifname);
630 
631  if (ifid >= 0)
632  {
633  retval = simstrlcpy (buf, len, clickInstance->GetIpAddressFromInterfaceId (ifid));
634  }
635  else
636  {
637  retval = -1;
638  }
639 
640  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IPADDR_FROM_NAME: " << ifname << " " << buf << " " << len);
641  break;
642  }
643 
644  case SIMCLICK_IPPREFIX_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->GetIpPrefixFromInterfaceId (ifid));
655  }
656  else
657  {
658  retval = -1;
659  }
660 
661  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IPPREFIX_FROM_NAME: " << ifname << " " << buf << " " << len);
662  break;
663  }
664 
665  case SIMCLICK_MACADDR_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  int ifid = clickInstance->GetInterfaceId (ifname);
671 
672  if (ifid >= 0)
673  {
674  retval = simstrlcpy (buf, len, clickInstance->GetMacAddressFromInterfaceId (ifid));
675  }
676  else
677  {
678  retval = -1;
679  }
680 
681  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_MACADDR_FROM_NAME: " << ifname << " " << buf << " " << len);
682  break;
683  }
684 
685  case SIMCLICK_SCHEDULE:
686  {
687  const struct timeval *when = va_arg (val, const struct timeval *);
688 
689  clickInstance->HandleScheduleFromClick (when);
690 
691  retval = 0;
692  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_SCHEDULE at " << when->tv_sec << "s and " << when->tv_usec << "usecs.");
693 
694  break;
695  }
696 
697  case SIMCLICK_GET_NODE_NAME:
698  {
699  char *buf = va_arg (val, char *);
700  int len = va_arg (val, int);
701  retval = simstrlcpy (buf, len, clickInstance->GetNodeName ());
702 
703  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_GET_NODE_NAME: " << buf << " " << len);
704  break;
705  }
706 
707  case SIMCLICK_IF_PROMISC:
708  {
709  int ifid = va_arg(val, int);
710  clickInstance->SetPromisc (ifid);
711 
712  retval = 0;
713  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IF_PROMISC: " << ifid << " " << ns3::Simulator::Now ());
714  break;
715  }
716 
717  case SIMCLICK_IF_READY:
718  {
719  int ifid = va_arg (val, int); // Commented out so that optimized build works
720 
721  // We're not using a ClickQueue, so we're always ready (for the timebeing)
722  retval = clickInstance->IsInterfaceReady (ifid);
723 
724  NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IF_READY: " << ifid << " " << ns3::Simulator::Now ());
725  break;
726  }
727 
728  case SIMCLICK_TRACE:
729  {
730  // Used only for tracing
731  NS_LOG_DEBUG (clickInstance->GetNodeName () << " Received a call for SIMCLICK_TRACE");
732  break;
733  }
734 
735  case SIMCLICK_GET_NODE_ID:
736  {
737  // Used only for tracing
738  NS_LOG_DEBUG (clickInstance->GetNodeName () << " Received a call for SIMCLICK_GET_NODE_ID");
739  break;
740  }
741  }
742  return retval;
743 }
744 
745 #endif // NS3_CLICK