A Discrete-Event Network Simulator
API
ipv4-click-routing.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010 Lalith Suresh
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Authors: Lalith Suresh <suresh.lalith@gmail.com>
18  */
19 
20 #ifdef NS3_CLICK
21 
22 #include "ipv4-click-routing.h"
23 
24 #include "ns3/ipv4-interface.h"
25 #include "ns3/ipv4-l3-click-protocol.h"
26 #include "ns3/log.h"
27 #include "ns3/mac48-address.h"
28 #include "ns3/node.h"
29 #include "ns3/random-variable-stream.h"
30 #include "ns3/simulator.h"
31 
32 #include <click/simclick.h>
33 #include <cstdarg>
34 #include <cstdlib>
35 #include <map>
36 #include <string>
37 
38 namespace ns3
39 {
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  return tid;
61 }
62 
63 Ipv4ClickRouting::Ipv4ClickRouting()
64  : m_nonDefaultName(false),
65  m_ipv4(nullptr)
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()
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 = nullptr;
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()
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 initialisation
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 << " "
333  << Simulator::Now());
334 
335  Time simtime =
336  Time::FromInteger(when->tv_sec, Time::S) + Time::FromInteger(when->tv_usec, Time::US);
337  Time simdelay = simtime - Simulator::Now();
338 
339  Simulator::Schedule(simdelay, &Ipv4ClickRouting::RunClickEvent, this);
340 }
341 
342 void
343 Ipv4ClickRouting::HandlePacketFromClick(int ifid, int ptype, const unsigned char* data, int len)
344 {
345  NS_LOG_DEBUG("HandlePacketFromClick");
346 
347  // Figure out packet's destination here:
348  // If ifid == 0, then the packet's going up
349  // else, the packet's going down
350  if (ifid == 0)
351  {
352  NS_LOG_DEBUG("Incoming packet from tap0. Sending Packet up the stack.");
353  Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol>(m_ipv4);
354 
355  Ptr<Packet> p = Create<Packet>(data, len);
356 
357  Ipv4Header ipHeader;
358  p->RemoveHeader(ipHeader);
359 
360  ipv4l3->LocalDeliver(p, ipHeader, (uint32_t)ifid);
361  }
362  else if (ifid)
363  {
364  NS_LOG_DEBUG("Incoming packet from eth" << ifid - 1 << " of type " << ptype
365  << ". Sending packet down the stack.");
366 
367  Ptr<Packet> p = Create<Packet>(data, len);
368 
369  DynamicCast<Ipv4L3ClickProtocol>(m_ipv4)->SendDown(p, ifid);
370  }
371 }
372 
373 void
374 Ipv4ClickRouting::SendPacketToClick(int ifid, int ptype, const unsigned char* data, int len)
375 {
376  NS_LOG_FUNCTION(this << ifid);
377  m_simNode->curtime = GetTimevalFromNow();
378 
379  // Since packets in ns-3 don't have global Packet ID's and Flow ID's, we
380  // feed dummy values into pinfo. This avoids the need to make changes in the Click code
381  simclick_simpacketinfo pinfo;
382  pinfo.id = 0;
383  pinfo.fid = 0;
384 
385  simclick_click_send(m_simNode, ifid, ptype, data, len, &pinfo);
386 }
387 
388 void
389 Ipv4ClickRouting::Send(Ptr<Packet> p, Ipv4Address src, Ipv4Address dst)
390 {
391  uint32_t ifid;
392 
393  // Find out which interface holds the src address of the packet...
394  for (ifid = 0; ifid < m_ipv4->GetNInterfaces(); ifid++)
395  {
396  Ipv4Address addr = m_ipv4->GetAddress(ifid, 0).GetLocal();
397 
398  if (addr == src)
399  {
400  break;
401  }
402  }
403 
404  int len = p->GetSize();
405  uint8_t* buf = new uint8_t[len];
406  p->CopyData(buf, len);
407 
408  // ... and send the packet on the corresponding Click interface.
409  SendPacketToClick(0, SIMCLICK_PTYPE_IP, buf, len);
410 
411  delete[] buf;
412 }
413 
414 void
415 Ipv4ClickRouting::Receive(Ptr<Packet> p, Mac48Address receiverAddr, Mac48Address dest)
416 {
417  NS_LOG_FUNCTION(this << p << receiverAddr << dest);
418 
419  uint32_t ifid;
420 
421  // Find out which device this packet was received from...
422  for (ifid = 0; ifid < m_ipv4->GetNInterfaces(); ifid++)
423  {
424  Ptr<NetDevice> device = m_ipv4->GetNetDevice(ifid);
425 
426  if (Mac48Address::ConvertFrom(device->GetAddress()) == receiverAddr)
427  {
428  break;
429  }
430  }
431 
432  int len = p->GetSize();
433  uint8_t* buf = new uint8_t[len];
434  p->CopyData(buf, len);
435 
436  // ... and send the packet to the corresponding Click interface
437  SendPacketToClick(ifid, SIMCLICK_PTYPE_ETHER, buf, len);
438 
439  delete[] buf;
440 }
441 
442 std::string
443 Ipv4ClickRouting::ReadHandler(std::string elementName, std::string handlerName)
444 {
445  char* handle = simclick_click_read_handler(m_simNode,
446  elementName.c_str(),
447  handlerName.c_str(),
448  nullptr,
449  nullptr);
450  std::string ret(handle);
451 
452  // This is required because Click does not free
453  // the memory allocated to the return string
454  // from simclick_click_read_handler()
455  free(handle);
456 
457  return ret;
458 }
459 
460 int
461 Ipv4ClickRouting::WriteHandler(std::string elementName,
462  std::string handlerName,
463  std::string writeString)
464 {
465  int r = simclick_click_write_handler(m_simNode,
466  elementName.c_str(),
467  handlerName.c_str(),
468  writeString.c_str());
469 
470  // Note: There are probably use-cases for returning
471  // a write handler's error code, so don't assert.
472  // For example, the 'add' handler for IPRouteTable
473  // type elements fails if the route to be added
474  // already exists.
475 
476  return r;
477 }
478 
479 void
480 Ipv4ClickRouting::SetPromisc(int ifid)
481 {
482  Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol>(m_ipv4);
483  NS_ASSERT(ipv4l3);
484  ipv4l3->SetPromisc(ifid);
485 }
486 
487 Ptr<Ipv4Route>
488 Ipv4ClickRouting::RouteOutput(Ptr<Packet> p,
489  const Ipv4Header& header,
490  Ptr<NetDevice> oif,
491  Socket::SocketErrno& sockerr)
492 {
493  Ptr<Ipv4Route> rtentry;
494 
495  std::stringstream addr;
496  addr << "lookup ";
497  header.GetDestination().Print(addr);
498  // Probe the Click Routing Table for the required IP
499  // This returns a string of the form "InterfaceID GatewayAddr"
500  NS_LOG_DEBUG("Probe click routing table for " << addr.str());
501  std::string s = ReadHandler(m_clickRoutingTableElement, addr.str());
502  NS_LOG_DEBUG("string from click routing table: " << s);
503 
504  size_t pos = s.find(' ');
505  Ipv4Address destination;
506  int interfaceId;
507  if (pos == std::string::npos)
508  {
509  // Only an interface ID is found
510  destination = Ipv4Address("0.0.0.0");
511  interfaceId = atoi(s.c_str());
512  NS_LOG_DEBUG("case 1: destination " << destination << " interfaceId " << interfaceId);
513  }
514  else
515  {
516  interfaceId = atoi(s.substr(0, pos).c_str());
517  Ipv4Address destination(s.substr(pos + 1).c_str());
518  NS_LOG_DEBUG("case 2: destination " << destination << " interfaceId " << interfaceId);
519  }
520 
521  if (interfaceId != -1)
522  {
523  rtentry = Create<Ipv4Route>();
524  rtentry->SetDestination(header.GetDestination());
525  // the source address is the interface address that matches
526  // the destination address (when multiple are present on the
527  // outgoing interface, one is selected via scoping rules)
528  NS_ASSERT(m_ipv4);
529  uint32_t numOifAddresses = m_ipv4->GetNAddresses(interfaceId);
530  NS_ASSERT(numOifAddresses > 0);
531  Ipv4InterfaceAddress ifAddr;
532  if (numOifAddresses == 1)
533  {
534  ifAddr = m_ipv4->GetAddress(interfaceId, 0);
535  }
536  else
537  {
539  NS_FATAL_ERROR("XXX Not implemented yet: IP aliasing and Click");
540  }
541  rtentry->SetSource(ifAddr.GetLocal());
542  rtentry->SetGateway(destination);
543  rtentry->SetOutputDevice(m_ipv4->GetNetDevice(interfaceId));
544  sockerr = Socket::ERROR_NOTERROR;
545  NS_LOG_DEBUG("Found route to " << rtentry->GetDestination() << " via nh "
546  << rtentry->GetGateway() << " with source addr "
547  << rtentry->GetSource() << " and output dev "
548  << rtentry->GetOutputDevice());
549  }
550  else
551  {
552  NS_LOG_DEBUG("Click node " << m_nodeName << ": RouteOutput for dest="
553  << header.GetDestination() << " No route to host");
554  sockerr = Socket::ERROR_NOROUTETOHOST;
555  }
556 
557  return rtentry;
558 }
559 
560 // This method should never be called since Click handles
561 // forwarding directly
562 bool
563 Ipv4ClickRouting::RouteInput(Ptr<const Packet> p,
564  const Ipv4Header& header,
565  Ptr<const NetDevice> idev,
566  UnicastForwardCallback ucb,
567  MulticastForwardCallback mcb,
568  LocalDeliverCallback lcb,
569  ErrorCallback ecb)
570 {
571  NS_FATAL_ERROR("Click router does not have a RouteInput() interface!");
572  return false;
573 }
574 
575 void
576 Ipv4ClickRouting::PrintRoutingTable(Ptr<OutputStreamWrapper> stream, Time::Unit unit) const
577 {
578  *stream->GetStream() << "\nCLICK Routing table printing is not yet implemented, skipping.\n";
579 }
580 
581 void
582 Ipv4ClickRouting::NotifyInterfaceUp(uint32_t i)
583 {
584 }
585 
586 void
587 Ipv4ClickRouting::NotifyInterfaceDown(uint32_t i)
588 {
589 }
590 
591 void
592 Ipv4ClickRouting::NotifyAddAddress(uint32_t interface, Ipv4InterfaceAddress address)
593 {
594 }
595 
596 void
597 Ipv4ClickRouting::NotifyRemoveAddress(uint32_t interface, Ipv4InterfaceAddress address)
598 {
599 }
600 
601 } // namespace ns3
602 
603 using ns3::g_log;
604 
605 static int
606 simstrlcpy(char* buf, int len, const std::string& s)
607 {
608  if (len)
609  {
610  len--;
611 
612  if ((unsigned)len > s.length())
613  {
614  len = s.length();
615  }
616 
617  s.copy(buf, len);
618  buf[len] = '\0';
619  }
620  return 0;
621 }
622 
623 // Sends a Packet from Click to the Simulator: Defined in simclick.h. Click
624 // calls these methods.
625 int
626 simclick_sim_send(simclick_node_t* simnode,
627  int ifid,
628  int type,
629  const unsigned char* data,
630  int len,
631  simclick_simpacketinfo* pinfo)
632 {
633  NS_LOG_DEBUG("simclick_sim_send called at " << ns3::Simulator::Now().As(ns3::Time::S) << ": "
634  << ifid << " " << type << " " << data << " "
635  << len);
636 
637  if (!simnode)
638  {
639  return -1;
640  }
641 
642  ns3::Ptr<ns3::Ipv4ClickRouting> clickInstance =
643  ns3::Ipv4ClickRouting::GetClickInstanceFromSimNode(simnode);
644 
645  clickInstance->HandlePacketFromClick(ifid, type, data, len);
646 
647  return 0;
648 }
649 
650 // Click Service Methods: Defined in simclick.h
651 int
652 simclick_sim_command(simclick_node_t* simnode, int cmd, ...)
653 {
654  va_list val;
655  va_start(val, cmd);
656 
657  int retval = 0;
658 
659  ns3::Ptr<ns3::Ipv4ClickRouting> clickInstance =
660  ns3::Ipv4ClickRouting::GetClickInstanceFromSimNode(simnode);
661  switch (cmd)
662  {
663  case SIMCLICK_VERSION: {
664  retval = 0;
665  break;
666  }
667 
668  case SIMCLICK_SUPPORTS: {
669  int othercmd = va_arg(val, int);
670  retval = (othercmd >= SIMCLICK_VERSION && othercmd <= SIMCLICK_GET_DEFINES);
671  break;
672  }
673 
674  case SIMCLICK_IFID_FROM_NAME: {
675  const char* ifname = va_arg(val, const char*);
676 
677  retval = clickInstance->GetInterfaceId(ifname);
678 
679  NS_LOG_DEBUG(clickInstance->GetNodeName()
680  << " SIMCLICK_IFID_FROM_NAME: " << ifname << " " << retval);
681  break;
682  }
683 
684  case SIMCLICK_IPADDR_FROM_NAME: {
685  const char* ifname = va_arg(val, const char*);
686  char* buf = va_arg(val, char*);
687  int len = va_arg(val, int);
688 
689  int ifid = clickInstance->GetInterfaceId(ifname);
690 
691  if (ifid >= 0)
692  {
693  retval = simstrlcpy(buf, len, clickInstance->GetIpAddressFromInterfaceId(ifid));
694  }
695  else
696  {
697  retval = -1;
698  }
699 
700  NS_LOG_DEBUG(clickInstance->GetNodeName()
701  << " SIMCLICK_IPADDR_FROM_NAME: " << ifname << " " << buf << " " << len);
702  break;
703  }
704 
705  case SIMCLICK_IPPREFIX_FROM_NAME: {
706  const char* ifname = va_arg(val, const char*);
707  char* buf = va_arg(val, char*);
708  int len = va_arg(val, int);
709 
710  int ifid = clickInstance->GetInterfaceId(ifname);
711 
712  if (ifid >= 0)
713  {
714  retval = simstrlcpy(buf, len, clickInstance->GetIpPrefixFromInterfaceId(ifid));
715  }
716  else
717  {
718  retval = -1;
719  }
720 
721  NS_LOG_DEBUG(clickInstance->GetNodeName()
722  << " SIMCLICK_IPPREFIX_FROM_NAME: " << ifname << " " << buf << " " << len);
723  break;
724  }
725 
726  case SIMCLICK_MACADDR_FROM_NAME: {
727  const char* ifname = va_arg(val, const char*);
728  char* buf = va_arg(val, char*);
729  int len = va_arg(val, int);
730  int ifid = clickInstance->GetInterfaceId(ifname);
731 
732  if (ifid >= 0)
733  {
734  retval = simstrlcpy(buf, len, clickInstance->GetMacAddressFromInterfaceId(ifid));
735  }
736  else
737  {
738  retval = -1;
739  }
740 
741  NS_LOG_DEBUG(clickInstance->GetNodeName()
742  << " SIMCLICK_MACADDR_FROM_NAME: " << ifname << " " << buf << " " << len);
743  break;
744  }
745 
746  case SIMCLICK_SCHEDULE: {
747  const struct timeval* when = va_arg(val, const struct timeval*);
748 
749  clickInstance->HandleScheduleFromClick(when);
750 
751  retval = 0;
752  NS_LOG_DEBUG(clickInstance->GetNodeName() << " SIMCLICK_SCHEDULE at " << when->tv_sec
753  << "s and " << when->tv_usec << "usecs.");
754 
755  break;
756  }
757 
758  case SIMCLICK_GET_NODE_NAME: {
759  char* buf = va_arg(val, char*);
760  int len = va_arg(val, int);
761  retval = simstrlcpy(buf, len, clickInstance->GetNodeName());
762 
763  NS_LOG_DEBUG(clickInstance->GetNodeName()
764  << " SIMCLICK_GET_NODE_NAME: " << buf << " " << len);
765  break;
766  }
767 
768  case SIMCLICK_IF_PROMISC: {
769  int ifid = va_arg(val, int);
770  clickInstance->SetPromisc(ifid);
771 
772  retval = 0;
773  NS_LOG_DEBUG(clickInstance->GetNodeName()
774  << " SIMCLICK_IF_PROMISC: " << ifid << " " << ns3::Simulator::Now());
775  break;
776  }
777 
778  case SIMCLICK_IF_READY: {
779  int ifid = va_arg(val, int); // Commented out so that optimized build works
780 
781  // We're not using a ClickQueue, so we're always ready (for the timebeing)
782  retval = clickInstance->IsInterfaceReady(ifid);
783 
784  NS_LOG_DEBUG(clickInstance->GetNodeName()
785  << " SIMCLICK_IF_READY: " << ifid << " " << ns3::Simulator::Now());
786  break;
787  }
788 
789  case SIMCLICK_TRACE: {
790  // Used only for tracing
791  NS_LOG_DEBUG(clickInstance->GetNodeName() << " Received a call for SIMCLICK_TRACE");
792  break;
793  }
794 
795  case SIMCLICK_GET_NODE_ID: {
796  // Used only for tracing
797  NS_LOG_DEBUG(clickInstance->GetNodeName() << " Received a call for SIMCLICK_GET_NODE_ID");
798  break;
799  }
800 
801  case SIMCLICK_GET_RANDOM_INT: {
802  uint32_t* randomValue = va_arg(val, uint32_t*);
803  uint32_t maxValue = va_arg(val, uint32_t);
804 
805  *randomValue = static_cast<uint32_t>(
806  clickInstance->GetRandomVariable()->GetValue(0.0, static_cast<double>(maxValue) + 1.0));
807  retval = 0;
808  NS_LOG_DEBUG(clickInstance->GetNodeName() << " SIMCLICK_RANDOM: " << *randomValue << " "
809  << maxValue << " " << ns3::Simulator::Now());
810  break;
811  }
812 
813  case SIMCLICK_GET_DEFINES: {
814  char* buf = va_arg(val, char*);
815  size_t* size = va_arg(val, size_t*);
816  uint32_t required = 0;
817 
818  // Try to fill the buffer with up to size bytes.
819  // If this is not enough space, write the required buffer size into
820  // the size variable and return an error code.
821  // Otherwise return the bytes actually written into the buffer in size.
822 
823  // Append key/value pair, separated by \0.
824  std::map<std::string, std::string> defines = clickInstance->GetDefines();
825  std::map<std::string, std::string>::const_iterator it = defines.begin();
826  while (it != defines.end())
827  {
828  size_t available = *size - required;
829  if (it->first.length() + it->second.length() + 2 <= available)
830  {
831  simstrlcpy(buf + required, available, it->first);
832  required += it->first.length() + 1;
833  available -= it->first.length() + 1;
834  simstrlcpy(buf + required, available, it->second);
835  required += it->second.length() + 1;
836  }
837  else
838  {
839  required += it->first.length() + it->second.length() + 2;
840  }
841  it++;
842  }
843  if (required > *size)
844  {
845  retval = -1;
846  }
847  else
848  {
849  retval = 0;
850  }
851  *size = required;
852  }
853  }
854 
855  va_end(val);
856  return retval;
857 }
858 
859 #endif // NS3_CLICK
static TypeId GetTypeId()
Get the type ID.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
int64_t GetNanoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:417
int64_t GetFemtoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:427
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:402
@ S
second
Definition: nstime.h:116
int64_t GetPicoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:422
int64_t GetMicroSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:412
TypeId SetGroupName(std::string groupName)
Set the group name.
Definition: type-id.cc:943
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
static void Send(Ptr< NetDevice > dev, int level, std::string emuMode)
Definition: fd-emu-send.cc:54
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#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:46
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:296
struct simclick_node simclick_node_t
Length::Unit Unit
Save some typing by defining a short alias for Length::Unit.
address
Definition: first.py:40
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:848
Every class exported by the ns3 library is enclosed in the ns3 namespace.
cmd
Definition: second.py:33
uint8_t data[writeSize]
void SetIpv4(const char *deviceName, const char *ip, const char *netmask)