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 #include "ipv4-click-routing.h"
21 
22 #include "ipv4-l3-click-protocol.h"
23 
24 #include "ns3/ipv4-interface.h"
25 #include "ns3/log.h"
26 #include "ns3/mac48-address.h"
27 #include "ns3/node.h"
28 #include "ns3/random-variable-stream.h"
29 #include "ns3/simulator.h"
30 
31 #include <click/simclick.h>
32 #include <cstdarg>
33 #include <cstdlib>
34 #include <map>
35 #include <string>
36 
37 namespace ns3
38 {
39 
40 NS_LOG_COMPONENT_DEFINE("Ipv4ClickRouting");
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")
56  .AddConstructor<Ipv4ClickRouting>()
57  .SetGroupName("Click");
58 
59  return tid;
60 }
61 
63  : m_nonDefaultName(false),
64  m_ipv4(nullptr)
65 {
66  m_random = CreateObject<UniformRandomVariable>();
68  timerclear(&m_simNode->curtime);
69 
71 }
72 
74 {
75 }
76 
77 void
79 {
80  uint32_t id = m_ipv4->GetObject<Node>()->GetId();
81 
82  if (!m_nonDefaultName)
83  {
84  std::stringstream name;
85  name << "Node" << id;
86  m_nodeName = name.str();
87  }
88 
89  NS_ASSERT(!m_clickFile.empty());
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
110 {
111  m_ipv4 = ipv4;
112 }
113 
116 {
117  return m_random;
118 }
119 
120 void
122 {
123  if (m_clickInitialised)
124  {
125  simclick_click_kill(m_simNode);
126  }
127  m_ipv4 = nullptr;
128  delete m_simNode;
130 }
131 
132 void
133 Ipv4ClickRouting::SetClickFile(std::string clickfile)
134 {
135  m_clickFile = clickfile;
136 }
137 
138 void
139 Ipv4ClickRouting::SetDefines(std::map<std::string, std::string> defines)
140 {
141  m_defines = defines;
142 }
143 
144 std::map<std::string, std::string>
146 {
147  return m_defines;
148 }
149 
150 void
152 {
154 }
155 
156 void
158 {
159  m_nodeName = name;
160  m_nonDefaultName = true;
161 }
162 
163 std::string
165 {
166  return m_nodeName;
167 }
168 
169 int
171 {
172  int retval = -1;
173 
174  // The below hard coding of interface names follows the
175  // same approach as used in the original nsclick code for
176  // ns-2. The interface names map directly to what is to
177  // be used in the Click configuration files.
178  // Thus eth0 will refer to the first network device of
179  // the node, and is to be named so in the Click graph.
180  // This function is called by Click during the initialisation
181  // phase of the Click graph, during which it tries to map
182  // interface IDs to interface names. The return value
183  // corresponds to the interface ID that Click will use.
184 
185  // Tap/tun devices refer to the kernel devices
186  if (strstr(ifname, "tap") || strstr(ifname, "tun"))
187  {
188  retval = 0;
189  }
190  else if (const char* devname = strstr(ifname, "eth"))
191  {
192  while (*devname && !isdigit((unsigned char)*devname))
193  {
194  devname++;
195  }
196 
197  if (*devname)
198  {
199  retval = atoi(devname) + INTERFACE_ID_FIRST;
200  }
201  }
202  else if (const char* devname = strstr(ifname, "drop"))
203  {
204  while (*devname && !isdigit((unsigned char)*devname))
205  {
206  devname++;
207  }
208  if (*devname)
209  {
210  retval = atoi(devname) + INTERFACE_ID_FIRST_DROP;
211  }
212  }
213 
214  // This protects against a possible inconsistency of having
215  // more interfaces defined in the Click graph
216  // for a Click node than are defined for it in
217  // the simulation script
218  if (retval >= (int)m_ipv4->GetNInterfaces())
219  {
220  return -1;
221  }
222 
223  return retval;
224 }
225 
226 bool
228 {
229  return ifid >= 0 && ifid < static_cast<int>(m_ipv4->GetNInterfaces());
230 }
231 
232 std::string
234 {
235  std::stringstream addr;
236  m_ipv4->GetAddress(ifid, 0).GetLocal().Print(addr);
237 
238  return addr.str();
239 }
240 
241 std::string
243 {
244  std::stringstream addr;
245  m_ipv4->GetAddress(ifid, 0).GetMask().Print(addr);
246 
247  return addr.str();
248 }
249 
250 std::string
252 {
253  std::stringstream addr;
254 
255  Ptr<NetDevice> device = m_ipv4->GetNetDevice(ifid);
256  Address devAddr = device->GetAddress();
257  addr << Mac48Address::ConvertFrom(devAddr);
258 
259  return addr.str();
260 }
261 
262 void
264 {
265  m_clickInstanceFromSimNode.insert(std::make_pair(m_simNode, this));
266 }
267 
270 {
271  return m_clickInstanceFromSimNode[simnode];
272 }
273 
274 struct timeval
275 Ipv4ClickRouting::GetTimevalFromNow() const
276 {
277  struct timeval curtime;
278  uint64_t remainder = 0;
279 
280  Time now = Simulator::Now();
281 
282  curtime.tv_sec = now.GetSeconds();
283  curtime.tv_usec = now.GetMicroSeconds() % 1000000;
284 
285  switch (Time::GetResolution())
286  {
287  case Time::NS:
288  remainder = now.GetNanoSeconds() % 1000;
289  break;
290  case Time::PS:
291  remainder = now.GetPicoSeconds() % 1000000;
292  break;
293  case Time::FS:
294  remainder = now.GetFemtoSeconds() % 1000000000;
295  break;
296  default:
297  break;
298  }
299 
300  if (remainder)
301  {
302  ++curtime.tv_usec;
303  if (curtime.tv_usec == 1000000)
304  {
305  ++curtime.tv_sec;
306  curtime.tv_usec = 0;
307  }
308  }
309 
310  return curtime;
311 }
312 
313 void
315 {
316  m_simNode->curtime = GetTimevalFromNow();
317 
318  NS_LOG_DEBUG("RunClickEvent at " << m_simNode->curtime.tv_sec << " "
319  << m_simNode->curtime.tv_usec << " " << Simulator::Now());
320  simclick_click_run(m_simNode);
321 }
322 
323 void
324 Ipv4ClickRouting::HandleScheduleFromClick(const struct timeval* when)
325 {
326  NS_LOG_DEBUG("HandleScheduleFromClick at " << when->tv_sec << " " << when->tv_usec << " "
327  << Simulator::Now());
328 
329  Time simtime =
330  Time::FromInteger(when->tv_sec, Time::S) + Time::FromInteger(when->tv_usec, Time::US);
331  Time simdelay = simtime - Simulator::Now();
332 
334 }
335 
336 void
337 Ipv4ClickRouting::HandlePacketFromClick(int ifid, int ptype, const unsigned char* data, int len)
338 {
339  NS_LOG_DEBUG("HandlePacketFromClick");
340 
341  // Figure out packet's destination here:
342  // If ifid == 0, then the packet's going up
343  // else, the packet's going down
344  if (ifid == 0)
345  {
346  NS_LOG_DEBUG("Incoming packet from tap0. Sending Packet up the stack.");
347  Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol>(m_ipv4);
348 
349  Ptr<Packet> p = Create<Packet>(data, len);
350 
351  Ipv4Header ipHeader;
352  p->RemoveHeader(ipHeader);
353 
354  ipv4l3->LocalDeliver(p, ipHeader, (uint32_t)ifid);
355  }
356  else if (ifid)
357  {
358  NS_LOG_DEBUG("Incoming packet from eth" << ifid - 1 << " of type " << ptype
359  << ". Sending packet down the stack.");
360 
361  Ptr<Packet> p = Create<Packet>(data, len);
362 
363  DynamicCast<Ipv4L3ClickProtocol>(m_ipv4)->SendDown(p, ifid);
364  }
365 }
366 
367 void
368 Ipv4ClickRouting::SendPacketToClick(int ifid, int ptype, const unsigned char* data, int len)
369 {
370  NS_LOG_FUNCTION(this << ifid);
371  m_simNode->curtime = GetTimevalFromNow();
372 
373  // Since packets in ns-3 don't have global Packet ID's and Flow ID's, we
374  // feed dummy values into pinfo. This avoids the need to make changes in the Click code
375  simclick_simpacketinfo pinfo;
376  pinfo.id = 0;
377  pinfo.fid = 0;
378 
379  simclick_click_send(m_simNode, ifid, ptype, data, len, &pinfo);
380 }
381 
382 void
384 {
385  uint32_t ifid;
386 
387  // Find out which interface holds the src address of the packet...
388  for (ifid = 0; ifid < m_ipv4->GetNInterfaces(); ifid++)
389  {
390  Ipv4Address addr = m_ipv4->GetAddress(ifid, 0).GetLocal();
391 
392  if (addr == src)
393  {
394  break;
395  }
396  }
397 
398  int len = p->GetSize();
399  auto buf = new uint8_t[len];
400  p->CopyData(buf, len);
401 
402  // ... and send the packet on the corresponding Click interface.
403  SendPacketToClick(0, SIMCLICK_PTYPE_IP, buf, len);
404 
405  delete[] buf;
406 }
407 
408 void
410 {
411  NS_LOG_FUNCTION(this << p << receiverAddr << dest);
412 
413  uint32_t ifid;
414 
415  // Find out which device this packet was received from...
416  for (ifid = 0; ifid < m_ipv4->GetNInterfaces(); ifid++)
417  {
418  Ptr<NetDevice> device = m_ipv4->GetNetDevice(ifid);
419 
420  if (Mac48Address::ConvertFrom(device->GetAddress()) == receiverAddr)
421  {
422  break;
423  }
424  }
425 
426  int len = p->GetSize();
427  auto buf = new uint8_t[len];
428  p->CopyData(buf, len);
429 
430  // ... and send the packet to the corresponding Click interface
431  SendPacketToClick(ifid, SIMCLICK_PTYPE_ETHER, buf, len);
432 
433  delete[] buf;
434 }
435 
436 std::string
437 Ipv4ClickRouting::ReadHandler(std::string elementName, std::string handlerName)
438 {
439  char* handle = simclick_click_read_handler(m_simNode,
440  elementName.c_str(),
441  handlerName.c_str(),
442  nullptr,
443  nullptr);
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,
456  std::string handlerName,
457  std::string writeString)
458 {
459  int r = simclick_click_write_handler(m_simNode,
460  elementName.c_str(),
461  handlerName.c_str(),
462  writeString.c_str());
463 
464  // Note: There are probably use-cases for returning
465  // a write handler's error code, so don't assert.
466  // For example, the 'add' handler for IPRouteTable
467  // type elements fails if the route to be added
468  // already exists.
469 
470  return r;
471 }
472 
473 void
475 {
476  Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol>(m_ipv4);
477  NS_ASSERT(ipv4l3);
478  ipv4l3->SetPromisc(ifid);
479 }
480 
483  const Ipv4Header& header,
484  Ptr<NetDevice> oif,
485  Socket::SocketErrno& sockerr)
486 {
487  Ptr<Ipv4Route> rtentry;
488 
489  std::stringstream addr;
490  addr << "lookup ";
491  header.GetDestination().Print(addr);
492  // Probe the Click Routing Table for the required IP
493  // This returns a string of the form "InterfaceID GatewayAddr"
494  NS_LOG_DEBUG("Probe click routing table for " << addr.str());
495  std::string s = ReadHandler(m_clickRoutingTableElement, addr.str());
496  NS_LOG_DEBUG("string from click routing table: " << s);
497 
498  size_t pos = s.find(' ');
499  Ipv4Address destination;
500  int interfaceId;
501  if (pos == std::string::npos)
502  {
503  // Only an interface ID is found
504  destination = Ipv4Address("0.0.0.0");
505  interfaceId = atoi(s.c_str());
506  NS_LOG_DEBUG("case 1: destination " << destination << " interfaceId " << interfaceId);
507  }
508  else
509  {
510  interfaceId = atoi(s.substr(0, pos).c_str());
511  Ipv4Address destination(s.substr(pos + 1).c_str());
512  NS_LOG_DEBUG("case 2: destination " << destination << " interfaceId " << interfaceId);
513  }
514 
515  if (interfaceId != -1)
516  {
517  rtentry = Create<Ipv4Route>();
518  rtentry->SetDestination(header.GetDestination());
519  // the source address is the interface address that matches
520  // the destination address (when multiple are present on the
521  // outgoing interface, one is selected via scoping rules)
522  NS_ASSERT(m_ipv4);
523  uint32_t numOifAddresses = m_ipv4->GetNAddresses(interfaceId);
524  NS_ASSERT(numOifAddresses > 0);
525  Ipv4InterfaceAddress ifAddr;
526  if (numOifAddresses == 1)
527  {
528  ifAddr = m_ipv4->GetAddress(interfaceId, 0);
529  }
530  else
531  {
533  NS_FATAL_ERROR("XXX Not implemented yet: IP aliasing and Click");
534  }
535  rtentry->SetSource(ifAddr.GetLocal());
536  rtentry->SetGateway(destination);
537  rtentry->SetOutputDevice(m_ipv4->GetNetDevice(interfaceId));
538  sockerr = Socket::ERROR_NOTERROR;
539  NS_LOG_DEBUG("Found route to " << rtentry->GetDestination() << " via nh "
540  << rtentry->GetGateway() << " with source addr "
541  << rtentry->GetSource() << " and output dev "
542  << rtentry->GetOutputDevice());
543  }
544  else
545  {
546  NS_LOG_DEBUG("Click node " << m_nodeName << ": RouteOutput for dest="
547  << header.GetDestination() << " No route to host");
548  sockerr = Socket::ERROR_NOROUTETOHOST;
549  }
550 
551  return rtentry;
552 }
553 
554 // This method should never be called since Click handles
555 // forwarding directly
556 bool
558  const Ipv4Header& header,
560  const UnicastForwardCallback& ucb,
561  const MulticastForwardCallback& mcb,
562  const LocalDeliverCallback& lcb,
563  const ErrorCallback& ecb)
564 {
565  NS_FATAL_ERROR("Click router does not have a RouteInput() interface!");
566  return false;
567 }
568 
569 void
571 {
572  *stream->GetStream() << "\nCLICK Routing table printing is not yet implemented, skipping.\n";
573 }
574 
575 void
577 {
578 }
579 
580 void
582 {
583 }
584 
585 void
587 {
588 }
589 
590 void
592 {
593 }
594 
595 } // namespace ns3
596 
597 using ns3::g_log;
598 
599 static int
600 simstrlcpy(char* buf, int len, const std::string& s)
601 {
602  if (len)
603  {
604  len--;
605 
606  if ((unsigned)len > s.length())
607  {
608  len = s.length();
609  }
610 
611  s.copy(buf, len);
612  buf[len] = '\0';
613  }
614  return 0;
615 }
616 
617 // Sends a Packet from Click to the Simulator: Defined in simclick.h. Click
618 // calls these methods.
619 int
621  int ifid,
622  int type,
623  const unsigned char* data,
624  int len,
625  simclick_simpacketinfo* pinfo)
626 {
627  NS_LOG_DEBUG("simclick_sim_send called at " << ns3::Simulator::Now().As(ns3::Time::S) << ": "
628  << ifid << " " << type << " " << data << " "
629  << len);
630 
631  if (!simnode)
632  {
633  return -1;
634  }
635 
636  ns3::Ptr<ns3::Ipv4ClickRouting> clickInstance =
638 
639  clickInstance->HandlePacketFromClick(ifid, type, data, len);
640 
641  return 0;
642 }
643 
644 // Click Service Methods: Defined in simclick.h
645 int
647 {
648  va_list val;
649  va_start(val, cmd);
650 
651  int retval = 0;
652 
653  ns3::Ptr<ns3::Ipv4ClickRouting> clickInstance =
655  switch (cmd)
656  {
657  case SIMCLICK_VERSION: {
658  retval = 0;
659  break;
660  }
661 
662  case SIMCLICK_SUPPORTS: {
663  int othercmd = va_arg(val, int);
664  retval = (othercmd >= SIMCLICK_VERSION && othercmd <= SIMCLICK_GET_DEFINES);
665  break;
666  }
667 
668  case SIMCLICK_IFID_FROM_NAME: {
669  const char* ifname = va_arg(val, const char*);
670 
671  retval = clickInstance->GetInterfaceId(ifname);
672 
673  NS_LOG_DEBUG(clickInstance->GetNodeName()
674  << " SIMCLICK_IFID_FROM_NAME: " << ifname << " " << retval);
675  break;
676  }
677 
678  case SIMCLICK_IPADDR_FROM_NAME: {
679  const char* ifname = va_arg(val, const char*);
680  char* buf = va_arg(val, char*);
681  int len = va_arg(val, int);
682 
683  int ifid = clickInstance->GetInterfaceId(ifname);
684 
685  if (ifid >= 0)
686  {
687  retval = simstrlcpy(buf, len, clickInstance->GetIpAddressFromInterfaceId(ifid));
688  }
689  else
690  {
691  retval = -1;
692  }
693 
694  NS_LOG_DEBUG(clickInstance->GetNodeName()
695  << " SIMCLICK_IPADDR_FROM_NAME: " << ifname << " " << buf << " " << len);
696  break;
697  }
698 
699  case SIMCLICK_IPPREFIX_FROM_NAME: {
700  const char* ifname = va_arg(val, const char*);
701  char* buf = va_arg(val, char*);
702  int len = va_arg(val, int);
703 
704  int ifid = clickInstance->GetInterfaceId(ifname);
705 
706  if (ifid >= 0)
707  {
708  retval = simstrlcpy(buf, len, clickInstance->GetIpPrefixFromInterfaceId(ifid));
709  }
710  else
711  {
712  retval = -1;
713  }
714 
715  NS_LOG_DEBUG(clickInstance->GetNodeName()
716  << " SIMCLICK_IPPREFIX_FROM_NAME: " << ifname << " " << buf << " " << len);
717  break;
718  }
719 
720  case SIMCLICK_MACADDR_FROM_NAME: {
721  const char* ifname = va_arg(val, const char*);
722  char* buf = va_arg(val, char*);
723  int len = va_arg(val, int);
724  int ifid = clickInstance->GetInterfaceId(ifname);
725 
726  if (ifid >= 0)
727  {
728  retval = simstrlcpy(buf, len, clickInstance->GetMacAddressFromInterfaceId(ifid));
729  }
730  else
731  {
732  retval = -1;
733  }
734 
735  NS_LOG_DEBUG(clickInstance->GetNodeName()
736  << " SIMCLICK_MACADDR_FROM_NAME: " << ifname << " " << buf << " " << len);
737  break;
738  }
739 
740  case SIMCLICK_SCHEDULE: {
741  const struct timeval* when = va_arg(val, const struct timeval*);
742 
743  clickInstance->HandleScheduleFromClick(when);
744 
745  retval = 0;
746  NS_LOG_DEBUG(clickInstance->GetNodeName() << " SIMCLICK_SCHEDULE at " << when->tv_sec
747  << "s and " << when->tv_usec << "usecs.");
748 
749  break;
750  }
751 
752  case SIMCLICK_GET_NODE_NAME: {
753  char* buf = va_arg(val, char*);
754  int len = va_arg(val, int);
755  retval = simstrlcpy(buf, len, clickInstance->GetNodeName());
756 
757  NS_LOG_DEBUG(clickInstance->GetNodeName()
758  << " SIMCLICK_GET_NODE_NAME: " << buf << " " << len);
759  break;
760  }
761 
762  case SIMCLICK_IF_PROMISC: {
763  int ifid = va_arg(val, int);
764  clickInstance->SetPromisc(ifid);
765 
766  retval = 0;
767  NS_LOG_DEBUG(clickInstance->GetNodeName()
768  << " SIMCLICK_IF_PROMISC: " << ifid << " " << ns3::Simulator::Now());
769  break;
770  }
771 
772  case SIMCLICK_IF_READY: {
773  int ifid = va_arg(val, int); // Commented out so that optimized build works
774 
775  // We're not using a ClickQueue, so we're always ready (for the timebeing)
776  retval = clickInstance->IsInterfaceReady(ifid);
777 
778  NS_LOG_DEBUG(clickInstance->GetNodeName()
779  << " SIMCLICK_IF_READY: " << ifid << " " << ns3::Simulator::Now());
780  break;
781  }
782 
783  case SIMCLICK_TRACE: {
784  // Used only for tracing
785  NS_LOG_DEBUG(clickInstance->GetNodeName() << " Received a call for SIMCLICK_TRACE");
786  break;
787  }
788 
789  case SIMCLICK_GET_NODE_ID: {
790  // Used only for tracing
791  NS_LOG_DEBUG(clickInstance->GetNodeName() << " Received a call for SIMCLICK_GET_NODE_ID");
792  break;
793  }
794 
795  case SIMCLICK_GET_RANDOM_INT: {
796  uint32_t* randomValue = va_arg(val, uint32_t*);
797  uint32_t maxValue = va_arg(val, uint32_t);
798 
799  *randomValue = static_cast<uint32_t>(
800  clickInstance->GetRandomVariable()->GetValue(0.0, static_cast<double>(maxValue) + 1.0));
801  retval = 0;
802  NS_LOG_DEBUG(clickInstance->GetNodeName() << " SIMCLICK_RANDOM: " << *randomValue << " "
803  << maxValue << " " << ns3::Simulator::Now());
804  break;
805  }
806 
807  case SIMCLICK_GET_DEFINES: {
808  char* buf = va_arg(val, char*);
809  size_t* size = va_arg(val, size_t*);
810  uint32_t required = 0;
811 
812  // Try to fill the buffer with up to size bytes.
813  // If this is not enough space, write the required buffer size into
814  // the size variable and return an error code.
815  // Otherwise return the bytes actually written into the buffer in size.
816 
817  // Append key/value pair, separated by \0.
818  std::map<std::string, std::string> defines = clickInstance->GetDefines();
819 
820  for (auto it = defines.begin(); it != defines.end(); it++)
821  {
822  size_t available = *size - required;
823  if (it->first.length() + it->second.length() + 2 <= available)
824  {
825  simstrlcpy(buf + required, available, it->first);
826  required += it->first.length() + 1;
827  available -= it->first.length() + 1;
828  simstrlcpy(buf + required, available, it->second);
829  required += it->second.length() + 1;
830  }
831  else
832  {
833  required += it->first.length() + it->second.length() + 2;
834  }
835  }
836  if (required > *size)
837  {
838  retval = -1;
839  }
840  else
841  {
842  retval = 0;
843  }
844  *size = required;
845  }
846  }
847 
848  va_end(val);
849  return retval;
850 }
a polymophic address class
Definition: address.h:101
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
void Print(std::ostream &os) const
Print this address to the given output stream.
Class to allow a node to use Click for external routing.
void SetDefines(std::map< std::string, std::string > defines)
Click defines to be used by the node's Click Instance.
bool RouteInput(Ptr< const Packet > p, const Ipv4Header &header, Ptr< const NetDevice > idev, const UnicastForwardCallback &ucb, const MulticastForwardCallback &mcb, const LocalDeliverCallback &lcb, const ErrorCallback &ecb) override
Route an input packet (to be forwarded or locally delivered)
std::string GetIpAddressFromInterfaceId(int ifid)
Provides for SIMCLICK_IPADDR_FROM_NAME.
void RunClickEvent()
This method has to be scheduled every time Click calls SIMCLICK_SCHEDULE.
Ipv4ClickRouting()
Constructor.
simclick_node_t * m_simNode
Pointer to the simclick node.
bool IsInterfaceReady(int ifid)
Provides for SIMCLICK_IF_READY.
int WriteHandler(std::string elementName, std::string handlerName, std::string writeString)
Write Handler interface for a node's Click Elements.
void AddSimNodeToClickMapping()
Used internally in DoInitialize () to Add a mapping to m_clickInstanceFromSimNode mapping.
bool m_clickInitialised
Whether click has been initialized.
void NotifyAddAddress(uint32_t interface, Ipv4InterfaceAddress address) override
void SetPromisc(int ifid)
Sets an interface to run on promiscuous mode.
void DoDispose() override
Destructor implementation.
std::string m_nodeName
Name of the node.
void DoInitialize() override
Initialize() implementation.
std::string GetMacAddressFromInterfaceId(int ifid)
Provides for SIMCLICK_MACADDR_FROM_NAME.
void NotifyRemoveAddress(uint32_t interface, Ipv4InterfaceAddress address) override
bool m_nonDefaultName
Whether a non-default name has been set.
void Send(Ptr< Packet > p, Ipv4Address src, Ipv4Address dest)
Allow a higher layer to send data through Click.
Ptr< Ipv4 > m_ipv4
Pointer to the IPv4 object.
void NotifyInterfaceDown(uint32_t interface) override
struct timeval GetTimevalFromNow() const
Get current simulation time as a timeval.
std::map< std::string, std::string > GetDefines()
Provides for SIMCLICK_GET_DEFINES.
Ptr< Ipv4Route > RouteOutput(Ptr< Packet > p, const Ipv4Header &header, Ptr< NetDevice > oif, Socket::SocketErrno &sockerr) override
Query routing cache for an existing route, for an outbound packet.
void SetClickFile(std::string clickfile)
Click configuration file to be used by the node's Click Instance.
Ptr< UniformRandomVariable > m_random
Uniform random variable.
int GetInterfaceId(const char *ifname)
Provides for SIMCLICK_IFID_FROM_NAME.
void SetIpv4(Ptr< Ipv4 > ipv4) override
Set the Ipv4 instance to be used.
std::map< std::string, std::string > m_defines
Defines for .click configuration file parsing.
void SendPacketToClick(int ifid, int type, const unsigned char *data, int len)
Sends a packet to Click.
static Ptr< Ipv4ClickRouting > GetClickInstanceFromSimNode(simclick_node_t *simnode)
Allows the Click service methods, which reside outside Ipv4ClickRouting, to get the required Ipv4Clic...
void PrintRoutingTable(Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S) const override
Print the Routing Table entries.
std::string m_clickFile
Name of .click configuration file.
std::string ReadHandler(std::string elementName, std::string handlerName)
Read Handler interface for a node's Click Elements.
static TypeId GetTypeId()
Get type ID.
void HandleScheduleFromClick(const struct timeval *when)
Schedules simclick_click_run to run at the given time.
static std::map< simclick_node_t *, Ptr< Ipv4ClickRouting > > m_clickInstanceFromSimNode
Provide a mapping between the node reference used by Click and the corresponding Ipv4ClickRouting ins...
std::string GetIpPrefixFromInterfaceId(int ifid)
Provides for SIMCLICK_IPPREFIX_FROM_NAME.
void HandlePacketFromClick(int ifid, int type, const unsigned char *data, int len)
Receives a packet from Click.
void SetClickRoutingTableElement(std::string name)
Name of the routing table element being used by Click.
void SetNodeName(std::string name)
Name of the node as to be used by Click.
Ptr< UniformRandomVariable > GetRandomVariable()
Get the uniform random variable.
void Receive(Ptr< Packet > p, Mac48Address receiverAddr, Mac48Address dest)
Allow a lower layer to send data to Click.
std::string GetNodeName()
Provides for SIMCLICK_GET_NODE_NAME.
void NotifyInterfaceUp(uint32_t interface) override
std::string m_clickRoutingTableElement
Name of the routing table element.
Packet header for IPv4.
Definition: ipv4-header.h:34
Ipv4Address GetDestination() const
Definition: ipv4-header.cc:316
a class to store IPv4 address information on an interface
Ipv4Address GetLocal() const
Get the local address.
Abstract base class for IPv4 routing protocols.
an EUI-48 address
Definition: mac48-address.h:46
static Mac48Address ConvertFrom(const Address &address)
A network Node.
Definition: node.h:57
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:352
std::ostream * GetStream()
Return a pointer to an ostream previously set in the wrapper.
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:400
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:84
@ ERROR_NOROUTETOHOST
Definition: socket.h:95
@ ERROR_NOTERROR
Definition: socket.h:85
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetNanoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:418
int64_t GetFemtoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:428
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
static Unit GetResolution()
Definition: time.cc:408
Unit
The unit to use to interpret a number representing time.
Definition: nstime.h:111
@ US
microsecond
Definition: nstime.h:118
@ PS
picosecond
Definition: nstime.h:120
@ FS
femtosecond
Definition: nstime.h:121
@ S
second
Definition: nstime.h:116
@ NS
nanosecond
Definition: nstime.h:119
int64_t GetPicoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:423
static Time FromInteger(uint64_t value, Unit unit)
Create a Time equal to value in unit unit.
Definition: nstime.h:499
int64_t GetMicroSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:413
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
double GetValue(double min, double max)
Get the next random value drawn from the distribution.
#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
int simclick_sim_send(simclick_node_t *simnode, int ifid, int type, const unsigned char *data, int len, simclick_simpacketinfo *pinfo)
int simclick_sim_command(simclick_node_t *simnode, int cmd,...)
#define INTERFACE_ID_FIRST
#define INTERFACE_ID_FIRST_DROP
static int simstrlcpy(char *buf, int len, const std::string &s)
struct simclick_node simclick_node_t
address
Definition: first.py:47
Every class exported by the ns3 library is enclosed in the ns3 namespace.
cmd
Definition: second.py:40
uint8_t data[writeSize]