A Discrete-Event Network Simulator
API
tap-bridge.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009 University of Washington
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 
18 #include "tap-bridge.h"
19 
20 #include "tap-encode-decode.h"
21 
22 #include "ns3/abort.h"
23 #include "ns3/boolean.h"
24 #include "ns3/channel.h"
25 #include "ns3/enum.h"
26 #include "ns3/ethernet-header.h"
27 #include "ns3/fd-reader.h"
28 #include "ns3/ipv4.h"
29 #include "ns3/llc-snap-header.h"
30 #include "ns3/log.h"
31 #include "ns3/node.h"
32 #include "ns3/packet.h"
33 #include "ns3/realtime-simulator-impl.h"
34 #include "ns3/simulator.h"
35 #include "ns3/string.h"
36 #include "ns3/uinteger.h"
37 
38 #include <cerrno>
39 #include <cstdlib>
40 #include <limits>
41 #include <net/if.h>
42 #include <sys/ioctl.h>
43 #include <sys/socket.h>
44 #include <sys/stat.h>
45 #include <sys/un.h>
46 #include <sys/wait.h>
47 #include <unistd.h>
48 
49 namespace ns3
50 {
51 
52 NS_LOG_COMPONENT_DEFINE("TapBridge");
53 
54 FdReader::Data
56 {
57  NS_LOG_FUNCTION(this);
58 
59  uint32_t bufferSize = 65536;
60  auto buf = (uint8_t*)std::malloc(bufferSize);
61  NS_ABORT_MSG_IF(buf == nullptr, "malloc() failed");
62 
63  NS_LOG_LOGIC("Calling read on tap device fd " << m_fd);
64  ssize_t len = read(m_fd, buf, bufferSize);
65  if (len <= 0)
66  {
67  NS_LOG_INFO("TapBridgeFdReader::DoRead(): done");
68  std::free(buf);
69  buf = nullptr;
70  len = 0;
71  }
72 
73  return FdReader::Data(buf, len);
74 }
75 
76 #define TAP_MAGIC 95549
77 
79 
80 TypeId
82 {
83  static TypeId tid =
84  TypeId("ns3::TapBridge")
86  .SetGroupName("TapBridge")
87  .AddConstructor<TapBridge>()
88  .AddAttribute("Mtu",
89  "The MAC-level Maximum Transmission Unit",
90  UintegerValue(0),
92  MakeUintegerChecker<uint16_t>())
93  .AddAttribute("DeviceName",
94  "The name of the tap device to create.",
95  StringValue(""),
98  .AddAttribute("Gateway",
99  "The IP address of the default gateway to assign to the host machine, "
100  "when in ConfigureLocal mode.",
101  Ipv4AddressValue("255.255.255.255"),
102  MakeIpv4AddressAccessor(&TapBridge::m_tapGateway),
103  MakeIpv4AddressChecker())
104  .AddAttribute(
105  "IpAddress",
106  "The IP address to assign to the tap device, when in ConfigureLocal mode. "
107  "This address will override the discovered IP address of the simulated device.",
108  Ipv4AddressValue("255.255.255.255"),
109  MakeIpv4AddressAccessor(&TapBridge::m_tapIp),
110  MakeIpv4AddressChecker())
111  .AddAttribute(
112  "MacAddress",
113  "The MAC address to assign to the tap device, when in ConfigureLocal mode. "
114  "This address will override the discovered MAC address of the simulated device.",
115  Mac48AddressValue(Mac48Address("ff:ff:ff:ff:ff:ff")),
116  MakeMac48AddressAccessor(&TapBridge::m_tapMac),
117  MakeMac48AddressChecker())
118  .AddAttribute(
119  "Netmask",
120  "The network mask to assign to the tap device, when in ConfigureLocal mode. "
121  "This address will override the discovered MAC address of the simulated device.",
122  Ipv4MaskValue("255.255.255.255"),
123  MakeIpv4MaskAccessor(&TapBridge::m_tapNetmask),
124  MakeIpv4MaskChecker())
125  .AddAttribute("Start",
126  "The simulation time at which to spin up the tap device read thread.",
127  TimeValue(Seconds(0.)),
129  MakeTimeChecker())
130  .AddAttribute("Stop",
131  "The simulation time at which to tear down the tap device read thread.",
132  TimeValue(Seconds(0.)),
134  MakeTimeChecker())
135  .AddAttribute("Mode",
136  "The operating and configuration mode to use.",
138  MakeEnumAccessor<Mode>(&TapBridge::SetMode),
140  "ConfigureLocal",
141  USE_LOCAL,
142  "UseLocal",
143  USE_BRIDGE,
144  "UseBridge"))
145  .AddAttribute("Verbose",
146  "Enable verbose output from tap-creator child process",
147  BooleanValue(false),
150  return tid;
151 }
152 
154  : m_node(nullptr),
155  m_ifIndex(0),
156  m_sock(-1),
157  m_startEvent(),
158  m_stopEvent(),
159  m_fdReader(nullptr),
160  m_ns3AddressRewritten(false)
161 {
162  NS_LOG_FUNCTION(this);
163  m_packetBuffer = new uint8_t[65536];
164  Start(m_tStart);
165 }
166 
168 {
169  NS_LOG_FUNCTION(this);
170 
171  StopTapDevice();
172 
173  delete[] m_packetBuffer;
174  m_packetBuffer = nullptr;
175 
176  m_bridgedDevice = nullptr;
177 }
178 
179 void
181 {
182  NS_LOG_FUNCTION(this);
184 }
185 
186 void
188 {
189  NS_LOG_FUNCTION(this << tStart);
190 
191  //
192  // Cancel any pending start event and schedule a new one at some relative time in the future.
193  //
196 }
197 
198 void
200 {
201  NS_LOG_FUNCTION(this << tStop);
202  //
203  // Cancel any pending stop event and schedule a new one at some relative time in the future.
204  //
207 }
208 
209 void
211 {
212  NS_LOG_FUNCTION(this);
213 
214  NS_ABORT_MSG_IF(m_sock != -1, "TapBridge::StartTapDevice(): Tap is already started");
215 
216  //
217  // A similar story exists for the node ID. We can't just naively do a
218  // GetNode ()->GetId () since GetNode is going to give us a Ptr<Node> which
219  // is reference counted. We need to stash away the node ID for use in the
220  // read thread.
221  //
222  m_nodeId = GetNode()->GetId();
223 
224  //
225  // Spin up the tap bridge and start receiving packets.
226  //
227  NS_LOG_LOGIC("Creating tap device");
228 
229  //
230  // Call out to a separate process running as suid root in order to get the
231  // tap device allocated and set up. We do this to avoid having the entire
232  // simulation running as root. If this method returns, we'll have a socket
233  // waiting for us in m_sock that we can use to talk to the newly created
234  // tap device.
235  //
236  CreateTap();
237 
238  // Declare the link up
239  NotifyLinkUp();
240 
241  //
242  // Now spin up a read thread to read packets from the tap device.
243  //
244  NS_ABORT_MSG_IF(m_fdReader, "TapBridge::StartTapDevice(): Receive thread is already running");
245  NS_LOG_LOGIC("Spinning up read thread");
246 
247  m_fdReader = Create<TapBridgeFdReader>();
249 }
250 
251 void
253 {
254  NS_LOG_FUNCTION(this);
255 
256  if (m_fdReader)
257  {
258  m_fdReader->Stop();
259  m_fdReader = nullptr;
260  }
261 
262  if (m_sock != -1)
263  {
264  close(m_sock);
265  m_sock = -1;
266  }
267 }
268 
269 void
271 {
272  NS_LOG_FUNCTION(this);
273 
274  //
275  // The TapBridge has three distinct operating modes. At this point, the
276  // differences revolve around who is responsible for creating and configuring
277  // the underlying network tap that we use. In ConfigureLocal mode, the
278  // TapBridge has the responsibility for creating and configuring the TAP.
279  //
280  // In UseBridge or UseLocal modes, the user will provide us a configuration
281  // and we have to adapt to it. For example, in UseLocal mode, the user will
282  // be configuring a tap device outside the scope of the ns-3 simulation and
283  // will be expecting us to work with it. The user will do something like:
284  //
285  // sudo ip tuntap add mode tap tap0
286  // sudo ip address add 10.1.1.1/24 dev tap0
287  // sudo ip link set dev tap0 address 00:00:00:00:00:01 up
288  //
289  // The user will then set the "Mode" Attribute of the TapBridge to "UseLocal"
290  // and the "DeviceName" Attribute to "tap0" in this case.
291  //
292  // In ConfigureLocal mode, the user is asking the TapBridge to do the
293  // configuration and create a TAP with the provided "DeviceName" with which
294  // the user can later do what she wants. We need to extract values for the
295  // MAC address, IP address, net mask, etc, from the simulation itself and
296  // use them to initialize corresponding values on the created tap device.
297  //
298  // In UseBridge mode, the user is asking us to use an existing tap device
299  // has been included in an OS bridge. She is asking us to take the simulated
300  // net device and logically add it to the existing bridge. We expect that
301  // the user has done something like:
302  //
303  // sudo ip link add mybridge type bridge
304  // sudo ip tuntap add mode tap mytap
305  // sudo ip link set dev mytap address 00:00:00:00:00:01 up
306  // sudo ip link set dev mytap master mybridge
307  // sudo ip link set dev ... master mybridge
308  // sudo ip address add 10.1.1.1/24 dev mybridge
309  // sudo ip link set dev mybridge up
310  //
311  // The bottom line at this point is that we want to either create or use a
312  // tap device on the host based on the verb part "Use" or "Configure" of the
313  // operating mode. Unfortunately for us you have to have root privileges to
314  // do either. Instead of running the entire simulation as root, we decided
315  // to make a small program who's whole reason for being is to run as suid
316  // root and do what it takes to create the tap. We're just going to pass
317  // off the configuration information to that program and let it deal with
318  // the situation.
319  //
320  // We're going to fork and exec that program soon, but first we need to have
321  // a socket to talk to it with. So we create a local interprocess (Unix)
322  // socket for that purpose.
323  //
324  int sock = socket(PF_UNIX, SOCK_DGRAM, 0);
326  sock == -1,
327  "TapBridge::CreateTap(): Unix socket creation error, errno = " << std::strerror(errno));
328 
329  //
330  // Bind to that socket and let the kernel allocate an endpoint
331  //
332  struct sockaddr_un un;
333  memset(&un, 0, sizeof(un));
334  un.sun_family = AF_UNIX;
335  int status = bind(sock, (struct sockaddr*)&un, sizeof(sa_family_t));
336  NS_ABORT_MSG_IF(status == -1,
337  "TapBridge::CreateTap(): Could not bind(): errno = " << std::strerror(errno));
338  NS_LOG_INFO("Created Unix socket");
339  NS_LOG_INFO("sun_family = " << un.sun_family);
340  NS_LOG_INFO("sun_path = " << un.sun_path);
341 
342  //
343  // We have a socket here, but we want to get it there -- to the program we're
344  // going to exec. What we'll do is to do a getsockname and then encode the
345  // resulting address information as a string, and then send the string to the
346  // program as an argument. So we need to get the sock name.
347  //
348  socklen_t len = sizeof(un);
349  status = getsockname(sock, (struct sockaddr*)&un, &len);
351  status == -1,
352  "TapBridge::CreateTap(): Could not getsockname(): errno = " << std::strerror(errno));
353 
354  //
355  // Now encode that socket name (family and path) as a string of hex digits
356  //
357  std::string path = TapBufferToString((uint8_t*)&un, len);
358  NS_LOG_INFO("Encoded Unix socket as \"" << path << "\"");
359 
360  //
361  // Tom Goff reports the possibility of a deadlock when trying to acquire the
362  // python GIL here. He says that this might be due to trying to access Python
363  // objects after fork() without calling PyOS_AfterFork() to properly reset
364  // Python state (including the GIL). Originally these next three lines were
365  // done after the fork, but were moved here to work around the deadlock.
366  //
368  Ptr<Node> n = nd->GetNode();
369  Ptr<Ipv4> ipv4 = n->GetObject<Ipv4>();
370 
371  //
372  // Fork and exec the process to create our socket. If we're us (the parent)
373  // we wait for the child (the creator) to complete and read the socket it
374  // created and passed back using the ancillary data mechanism.
375  //
376  pid_t pid = ::fork();
377  if (pid == 0)
378  {
379  NS_LOG_DEBUG("Child process");
380 
381  //
382  // build a command line argument from the encoded endpoint string that
383  // the socket creation process will use to figure out how to respond to
384  // the (now) parent process. We're going to have to give this program
385  // quite a bit of information.
386  //
387  // -d<device-name> The name of the tap device we want to create;
388  // -g<gateway-address> The IP address to use as the default gateway;
389  // -i<IP-address> The IP address to assign to the new tap device;
390  // -m<MAC-address> The MAC-48 address to assign to the new tap device;
391  // -n<network-mask> The network mask to assign to the new tap device;
392  // -o<operating mode> The operating mode of the bridge (1=ConfigureLocal, 2=UseLocal,
393  // 3=UseBridge) -p<path> the path to the unix socket described above.
394  //
395  // Example tap-creator -dnewdev -g1.2.3.2 -i1.2.3.1 -m08:00:2e:00:01:23 -n255.255.255.0 -o1
396  // -pblah
397  //
398  // We want to get as much of this stuff automagically as possible.
399  //
400  // For CONFIGURE_LOCAL mode only:
401  // <IP-address> is the IP address we are going to set in the newly
402  // created Tap device on the Linux host. At the point in the simulation
403  // where devices are coming up, we should have all of our IP addresses
404  // assigned. That means that we can find the IP address to assign to
405  // the new Tap device from the IP address associated with the bridged
406  // net device.
407  //
408 
409  bool wantIp = (m_mode == CONFIGURE_LOCAL);
410 
411  if (wantIp && (!ipv4) && m_tapIp.IsBroadcast() && m_tapNetmask == Ipv4Mask::GetOnes())
412  {
413  NS_FATAL_ERROR("TapBridge::CreateTap(): Tap device IP configuration requested but "
414  "neither IP address nor IP netmask is provided");
415  }
416 
417  // Some stub values to make tap-creator happy
418  Ipv4Address ipv4Address("255.255.255.255");
419  Ipv4Mask ipv4Mask("255.255.255.255");
420 
421  if (ipv4)
422  {
423  uint32_t index = ipv4->GetInterfaceForDevice(nd);
424  if (ipv4->GetNAddresses(index) > 1)
425  {
426  NS_LOG_WARN(
427  "Underlying bridged NetDevice has multiple IP addresses; using first one.");
428  }
429  ipv4Address = ipv4->GetAddress(index, 0).GetLocal();
430 
431  //
432  // The net mask is sitting right there next to the ipv4 address.
433  //
434  ipv4Mask = ipv4->GetAddress(index, 0).GetMask();
435  }
436 
437  //
438  // The MAC address should also already be assigned and waiting for us in
439  // the bridged net device.
440  //
441  Address address = nd->GetAddress();
443 
444  //
445  // The device-name is something we may want the system to make up in
446  // every case. We also rely on it being configured via an Attribute
447  // through the helper. By default, it is set to the empty string
448  // which tells the system to make up a device name such as "tap123".
449  //
450  std::ostringstream ossDeviceName;
451  ossDeviceName << "-d" << m_tapDeviceName;
452 
453  //
454  // The gateway-address is something we can't derive, so we rely on it
455  // being configured via an Attribute through the helper.
456  //
457  std::ostringstream ossGateway;
458  ossGateway << "-g" << m_tapGateway;
459 
460  //
461  // For flexibility, we do allow a client to override any of the values
462  // above via attributes, so only use our found values if the Attribute
463  // is not equal to its default value (empty string or broadcast address).
464  //
465  std::ostringstream ossIp;
466  if (m_tapIp.IsBroadcast())
467  {
468  ossIp << "-i" << ipv4Address;
469  }
470  else
471  {
472  ossIp << "-i" << m_tapIp;
473  }
474 
475  std::ostringstream ossMac;
476  if (m_tapMac.IsBroadcast())
477  {
478  ossMac << "-m" << mac48Address;
479  }
480  else
481  {
482  ossMac << "-m" << m_tapMac;
483  }
484 
485  std::ostringstream ossNetmask;
487  {
488  ossNetmask << "-n" << ipv4Mask;
489  }
490  else
491  {
492  ossNetmask << "-n" << m_tapNetmask;
493  }
494 
495  std::ostringstream ossMode;
496  ossMode << "-o";
497  if (m_mode == CONFIGURE_LOCAL)
498  {
499  ossMode << "1";
500  }
501  else if (m_mode == USE_LOCAL)
502  {
503  ossMode << "2";
504  }
505  else
506  {
507  ossMode << "3";
508  }
509 
510  std::ostringstream ossVerbose;
511  if (m_verbose)
512  {
513  ossVerbose << "-v";
514  }
515 
516  std::ostringstream ossPath;
517  ossPath << "-p" << path;
518 
519  NS_LOG_DEBUG("Executing: " << TAP_CREATOR << " " << ossDeviceName.str() << " "
520  << ossGateway.str() << " " << ossIp.str() << " " << ossMac.str()
521  << " " << ossNetmask.str() << " " << ossMode.str() << " "
522  << ossPath.str() << " " << ossVerbose.str());
523 
524  //
525  // Execute the socket creation process image.
526  //
527  status = ::execlp(TAP_CREATOR,
528  TAP_CREATOR, // argv[0] (filename)
529  ossDeviceName.str().c_str(), // argv[1] (-d<device name>)
530  ossGateway.str().c_str(), // argv[2] (-g<gateway>)
531  ossIp.str().c_str(), // argv[3] (-i<IP address>)
532  ossMac.str().c_str(), // argv[4] (-m<MAC address>)
533  ossNetmask.str().c_str(), // argv[5] (-n<net mask>)
534  ossMode.str().c_str(), // argv[6] (-o<operating mode>)
535  ossPath.str().c_str(), // argv[7] (-p<path>)
536  ossVerbose.str().c_str(), // argv[8] (-v)
537  (char*)nullptr);
538 
539  //
540  // If the execlp successfully completes, it never returns. If it returns it failed or the
541  // OS is broken. In either case, we bail.
542  //
543  NS_FATAL_ERROR("TapBridge::CreateTap(): Back from execlp(), status = "
544  << status << " errno = " << ::strerror(errno));
545  }
546  else
547  {
548  NS_LOG_DEBUG("Parent process");
549  //
550  // We're the process running the emu net device. We need to wait for the
551  // socket creator process to finish its job.
552  //
553  int st;
554  pid_t waited = waitpid(pid, &st, 0);
556  waited == -1,
557  "TapBridge::CreateTap(): waitpid() fails, errno = " << std::strerror(errno));
558  NS_ASSERT_MSG(pid == waited, "TapBridge::CreateTap(): pid mismatch");
559 
560  //
561  // Check to see if the socket creator exited normally and then take a
562  // look at the exit code. If it bailed, so should we. If it didn't
563  // even exit normally, we bail too.
564  //
565  if (WIFEXITED(st))
566  {
567  int exitStatus = WEXITSTATUS(st);
568  NS_ABORT_MSG_IF(exitStatus != 0,
569  "TapBridge::CreateTap(): socket creator exited normally with status "
570  << exitStatus);
571  }
572  else if (WIFSIGNALED(st))
573  {
574  NS_FATAL_ERROR("TapBridge::CreateTap(): socket creator exited with signal "
575  << WTERMSIG(st));
576  }
577  else
578  {
579  NS_FATAL_ERROR("TapBridge::CreateTap(): socket creator exited abnormally");
580  }
581 
582  //
583  // At this point, the socket creator has run successfully and should
584  // have created our tap device, initialized it with the information we
585  // passed and sent it back to the socket address we provided. A socket
586  // (fd) we can use to talk to this tap device should be waiting on the
587  // Unix socket we set up to receive information back from the creator
588  // program. We've got to do a bunch of grunt work to get at it, though.
589  //
590  // The struct iovec below is part of a scatter-gather list. It describes a
591  // buffer. In this case, it describes a buffer (an integer) that will
592  // get the data that comes back from the socket creator process. It will
593  // be a magic number that we use as a consistency/sanity check.
594  //
595  struct iovec iov;
596  uint32_t magic;
597  iov.iov_base = &magic;
598  iov.iov_len = sizeof(magic);
599 
600  //
601  // The CMSG macros you'll see below are used to create and access control
602  // messages (which is another name for ancillary data). The ancillary
603  // data is made up of pairs of struct cmsghdr structures and associated
604  // data arrays.
605  //
606  // First, we're going to allocate a buffer on the stack to receive our
607  // data array (that contains the socket). Sometimes you'll see this called
608  // an "ancillary element" but the msghdr uses the control message termimology
609  // so we call it "control."
610  //
611  size_t msg_size = sizeof(int);
612  char control[CMSG_SPACE(msg_size)];
613 
614  //
615  // There is a msghdr that is used to minimize the number of parameters
616  // passed to recvmsg (which we will use to receive our ancillary data).
617  // This structure uses terminology corresponding to control messages, so
618  // you'll see msg_control, which is the pointer to the ancillary data and
619  // controllen which is the size of the ancillary data array.
620  //
621  // So, initialize the message header that describes the ancillary/control
622  // data we expect to receive and point it to buffer.
623  //
624  struct msghdr msg;
625  msg.msg_name = nullptr;
626  msg.msg_namelen = 0;
627  msg.msg_iov = &iov;
628  msg.msg_iovlen = 1;
629  msg.msg_control = control;
630  msg.msg_controllen = sizeof(control);
631  msg.msg_flags = 0;
632 
633  //
634  // Now we can actually receive the interesting bits from the tap
635  // creator process. Lots of pain to get four bytes.
636  //
637  ssize_t bytesRead = recvmsg(sock, &msg, 0);
638  NS_ABORT_MSG_IF(bytesRead != sizeof(int),
639  "TapBridge::CreateTap(): Wrong byte count from socket creator");
640 
641  //
642  // There may be a number of message headers/ancillary data arrays coming in.
643  // Let's look for the one with a type SCM_RIGHTS which indicates it's the
644  // one we're interested in.
645  //
646  struct cmsghdr* cmsg;
647  for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr; cmsg = CMSG_NXTHDR(&msg, cmsg))
648  {
649  if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
650  {
651  //
652  // This is the type of message we want. Check to see if the magic
653  // number is correct and then pull out the socket we care about if
654  // it matches
655  //
656  if (magic == TAP_MAGIC)
657  {
658  NS_LOG_INFO("Got SCM_RIGHTS with correct magic " << magic);
659  int* rawSocket = (int*)CMSG_DATA(cmsg);
660  NS_LOG_INFO("Got the socket from the socket creator = " << *rawSocket);
661  m_sock = *rawSocket;
662  break;
663  }
664  else
665  {
666  NS_LOG_INFO("Got SCM_RIGHTS, but with bad magic " << magic);
667  }
668  }
669  }
670  if (cmsg == nullptr)
671  {
672  NS_FATAL_ERROR("Did not get the raw socket from the socket creator");
673  }
674 
675  if (m_mode == USE_BRIDGE)
676  {
677  //
678  // Set the ns-3 device's mac address to the overlying container's
679  // mac address
680  //
681  struct ifreq s;
682  memset(&s, 0, sizeof(struct ifreq));
683  strncpy(s.ifr_name, m_tapDeviceName.c_str(), IFNAMSIZ - 1);
684 
685  NS_LOG_INFO("Trying to get MacAddr of " << m_tapDeviceName);
686  int ioctlResult = ioctl(sock, SIOCGIFHWADDR, &s);
687  if (ioctlResult == 0)
688  {
689  Mac48Address learnedMac;
690  learnedMac.CopyFrom((uint8_t*)s.ifr_hwaddr.sa_data);
691  NS_LOG_INFO("Learned Tap device MacAddr is "
692  << learnedMac << ": setting ns-3 device to use this address");
693  m_bridgedDevice->SetAddress(learnedMac);
694  m_ns3AddressRewritten = true;
695  }
696 
698  {
699  NS_LOG_INFO("Cannot get MacAddr of Tap device: "
700  << m_tapDeviceName
701  << " while in USE_LOCAL/USE_BRIDGE mode: " << std::strerror(errno));
702  NS_LOG_INFO("Underlying ns-3 device will continue to use default address, what can "
703  "lead to connectivity errors");
704  }
705  }
706  }
707 
708  close(sock);
709 }
710 
711 void
712 TapBridge::ReadCallback(uint8_t* buf, ssize_t len)
713 {
714  NS_LOG_FUNCTION(this << buf << len);
715 
716  NS_ASSERT_MSG(buf != nullptr, "invalid buf argument");
717  NS_ASSERT_MSG(len > 0, "invalid len argument");
718 
719  //
720  // It's important to remember that we're in a completely different thread
721  // than the simulator is running in. We need to synchronize with that
722  // other thread to get the packet up into ns-3. What we will need to do
723  // is to schedule a method to deal with the packet using the multithreaded
724  // simulator we are most certainly running. However, I just said it -- we
725  // are talking about two threads here, so it is very, very dangerous to do
726  // any kind of reference counting on a shared object. Just don't do it.
727  // So what we're going to do is pass the buffer allocated on the heap
728  // into the ns-3 context thread where it will create the packet.
729  //
730 
731  NS_LOG_INFO("TapBridge::ReadCallback(): Received packet on node " << m_nodeId);
732  NS_LOG_INFO("TapBridge::ReadCallback(): Scheduling handler");
734  Seconds(0.0),
735  MakeEvent(&TapBridge::ForwardToBridgedDevice, this, buf, len));
736 }
737 
738 void
739 TapBridge::ForwardToBridgedDevice(uint8_t* buf, ssize_t len)
740 {
741  NS_LOG_FUNCTION(this << buf << len);
742 
743  //
744  // There are three operating modes for the TapBridge
745  //
746  // CONFIGURE_LOCAL means that ns-3 will create and configure a tap device
747  // and we are expected to use it. The tap device and the ns-3 net device
748  // will have the same MAC address by definition. Thus Send and SendFrom
749  // are equivalent in this case. We use Send to allow all ns-3 devices to
750  // participate in this mode.
751  //
752  // USE_LOCAL mode tells us that we have got to USE a pre-created tap device
753  // that will have a different MAC address from the ns-3 net device. We
754  // also enforce the requirement that there will only be one MAC address
755  // bridged on the Linux side so we can use Send (instead of SendFrom) in
756  // the linux to ns-3 direction. Again, all ns-3 devices can participate
757  // in this mode.
758  //
759  // USE_BRIDGE mode tells us that we are logically extending a Linux bridge
760  // on which lies our tap device. In this case there may be many linux
761  // net devices on the other side of the bridge and so we must use SendFrom
762  // to preserve the possibly many source addresses. Thus, ns-3 devices
763  // must support SendFrom in order to be considered for USE_BRIDGE mode.
764  //
765 
766  //
767  // First, create a packet out of the byte buffer we received and free that
768  // buffer.
769  //
770  Ptr<Packet> packet = Create<Packet>(reinterpret_cast<const uint8_t*>(buf), len);
771  std::free(buf);
772  buf = nullptr;
773 
774  //
775  // Make sure the packet we received is reasonable enough for the rest of the
776  // system to handle and get it ready to be injected directly into an ns-3
777  // device. What should come back is a packet with the Ethernet header
778  // (and possibly an LLC header as well) stripped off.
779  //
780  Address src;
781  Address dst;
782  uint16_t type;
783 
784  NS_LOG_LOGIC("Received packet from tap device");
785 
786  Ptr<Packet> p = Filter(packet, &src, &dst, &type);
787  if (!p)
788  {
789  NS_LOG_LOGIC(
790  "TapBridge::ForwardToBridgedDevice: Discarding packet as unfit for ns-3 consumption");
791  return;
792  }
793 
794  NS_LOG_LOGIC("Pkt source is " << src);
795  NS_LOG_LOGIC("Pkt destination is " << dst);
796  NS_LOG_LOGIC("Pkt LengthType is " << type);
797  if (m_mode == USE_LOCAL)
798  {
799  //
800  // Packets we are going to forward should not be from a broadcast src
801  //
802  NS_ASSERT_MSG(Mac48Address::ConvertFrom(src) != Mac48Address("ff:ff:ff:ff:ff:ff"),
803  "TapBridge::ForwardToBridgedDevice: Source addr is broadcast");
805  {
806  //
807  // Set the ns-3 device's mac address to the overlying container's
808  // mac address
809  //
810  Mac48Address learnedMac = Mac48Address::ConvertFrom(src);
811  NS_LOG_LOGIC("Learned MacAddr is " << learnedMac
812  << ": setting ns-3 device to use this address");
813  m_bridgedDevice->SetAddress(Mac48Address::ConvertFrom(learnedMac));
814  m_ns3AddressRewritten = true;
815  }
816  //
817  // If we are operating in USE_LOCAL mode, we may be attached to an ns-3
818  // device that does not support bridging (SupportsSendFrom returns false).
819  // But, since the mac addresses are now aligned, we can call Send()
820  //
821  NS_LOG_LOGIC("Forwarding packet to ns-3 device via Send()");
822  m_bridgedDevice->Send(packet, dst, type);
823  return;
824  }
825 
826  //
827  // If we are operating in USE_BRIDGE mode, we have the
828  // situation described below:
829  //
830  // Other Device <-bridge-> Tap Device <-bridge-> ns3 device
831  // Mac Addr A Mac Addr B Mac Addr C
832  //
833  // In Linux, "Other Device" and "Tap Device" are bridged together. By this
834  // we mean that a user has sone something in Linux like:
835  //
836  // ip link add mybridge type bridge
837  // ip link set dev other-device master mybridge
838  // ip link set dev tap-device master mybridge
839  //
840  // In USE_BRIDGE mode, we want to logically extend this Linux behavior to the
841  // simulated ns3 device and make it appear as if it is connected to the Linux
842  // subnet. As you may expect, this means that we need to act like a real
843  // Linux bridge and take all packets that come from "Tap Device" and ask
844  // "ns3 Device" to send them down its directly connected network. Just like
845  // in a normal everyday bridge we need to call SendFrom in order to preserve
846  // the original packet's from address.
847  //
848  // If we are operating in CONFIGURE_LOCAL mode, we simply simply take all packets
849  // that come from "Tap Device" and ask "ns3 Device" to send them down its
850  // directly connected network. A normal bridge would need to call SendFrom
851  // in order to preserve the original from address, but in CONFIGURE_LOCAL mode
852  // the tap device and the ns-3 device have the same MAC address by definition so
853  // we can call Send.
854  //
855  NS_LOG_LOGIC("Forwarding packet");
856 
857  if (m_mode == USE_BRIDGE)
858  {
859  m_bridgedDevice->SendFrom(packet, src, dst, type);
860  }
861  else
862  {
864  "TapBridge::ForwardToBridgedDevice(): Internal error");
865  m_bridgedDevice->Send(packet, dst, type);
866  }
867 }
868 
871 {
872  NS_LOG_FUNCTION(this << p);
873  uint32_t pktSize;
874 
875  //
876  // We have a candidate packet for injection into ns-3. We expect that since
877  // it came over a socket that provides Ethernet packets, it should be big
878  // enough to hold an EthernetHeader. If it can't, we signify the packet
879  // should be filtered out by returning 0.
880  //
881  pktSize = p->GetSize();
882  EthernetHeader header(false);
883  if (pktSize < header.GetSerializedSize())
884  {
885  return nullptr;
886  }
887 
888  uint32_t headerSize = p->PeekHeader(header);
889  p->RemoveAtStart(headerSize);
890 
891  NS_LOG_LOGIC("Pkt source is " << header.GetSource());
892  NS_LOG_LOGIC("Pkt destination is " << header.GetDestination());
893  NS_LOG_LOGIC("Pkt LengthType is " << header.GetLengthType());
894 
895  //
896  // If the length/type is less than 1500, it corresponds to a length
897  // interpretation packet. In this case, it is an 802.3 packet and
898  // will also have an 802.2 LLC header. If greater than 1500, we
899  // find the protocol number (Ethernet type) directly.
900  //
901  if (header.GetLengthType() <= 1500)
902  {
903  *src = header.GetSource();
904  *dst = header.GetDestination();
905 
906  pktSize = p->GetSize();
907  LlcSnapHeader llc;
908  if (pktSize < llc.GetSerializedSize())
909  {
910  return nullptr;
911  }
912 
913  p->RemoveHeader(llc);
914  *type = llc.GetType();
915  }
916  else
917  {
918  *src = header.GetSource();
919  *dst = header.GetDestination();
920  *type = header.GetLengthType();
921  }
922 
923  //
924  // What we give back is a packet without the Ethernet header (nor the
925  // possible llc/snap header) on it. We think it is ready to send on
926  // out the bridged net device.
927  //
928  return p;
929 }
930 
933 {
934  NS_LOG_FUNCTION(this);
935  return m_bridgedDevice;
936 }
937 
938 void
940 {
941  NS_LOG_FUNCTION(this << bridgedDevice);
942 
943  NS_ASSERT_MSG(m_node, "TapBridge::SetBridgedDevice: Bridge not installed in a node");
944  NS_ASSERT_MSG(bridgedDevice != this, "TapBridge::SetBridgedDevice: Cannot bridge to self");
945  NS_ASSERT_MSG(!m_bridgedDevice, "TapBridge::SetBridgedDevice: Already bridged");
946 
947  if (!Mac48Address::IsMatchingType(bridgedDevice->GetAddress()))
948  {
949  NS_FATAL_ERROR("TapBridge::SetBridgedDevice: Device does not support eui 48 addresses: "
950  "cannot be added to bridge.");
951  }
952 
953  if (m_mode == USE_BRIDGE && !bridgedDevice->SupportsSendFrom())
954  {
955  NS_FATAL_ERROR("TapBridge::SetBridgedDevice: Device does not support SendFrom: cannot be "
956  "added to bridge.");
957  }
958 
959  //
960  // We need to disconnect the bridged device from the internet stack on our
961  // node to ensure that only one stack responds to packets inbound over the
962  // bridged device. That one stack lives outside ns-3 so we just blatantly
963  // steal the device callbacks.
964  //
965  // N.B This can be undone if someone does a RegisterProtocolHandler later
966  // on this node.
967  //
968  bridgedDevice->SetReceiveCallback(MakeCallback(&TapBridge::DiscardFromBridgedDevice, this));
969  bridgedDevice->SetPromiscReceiveCallback(
971  m_bridgedDevice = bridgedDevice;
972 }
973 
974 bool
976  Ptr<const Packet> packet,
977  uint16_t protocol,
978  const Address& src)
979 {
980  NS_LOG_FUNCTION(this << device << packet << protocol << src);
981  NS_LOG_LOGIC("Discarding packet stolen from bridged device " << device);
982  return true;
983 }
984 
985 bool
987  Ptr<const Packet> packet,
988  uint16_t protocol,
989  const Address& src,
990  const Address& dst,
991  PacketType packetType)
992 {
993  NS_LOG_FUNCTION(this << device << packet << protocol << src << dst << packetType);
994  NS_ASSERT_MSG(device == m_bridgedDevice,
995  "TapBridge::SetBridgedDevice: Received packet from unexpected device");
996  NS_LOG_DEBUG("Packet UID is " << packet->GetUid());
997 
998  //
999  // There are three operating modes for the TapBridge
1000  //
1001  // CONFIGURE_LOCAL means that ns-3 will create and configure a tap device
1002  // and we are expected to use it. The tap device and the ns-3 net device
1003  // will have the same MAC address by definition.
1004  //
1005  // USE_LOCAL mode tells us that we have got to USE a pre-created tap device
1006  // that will have a different MAC address from the ns-3 net device. In this
1007  // case we will be spoofing the MAC address of a received packet to match
1008  // the single allowed address on the Linux side.
1009  //
1010  // USE_BRIDGE mode tells us that we are logically extending a Linux bridge
1011  // on which lies our tap device.
1012  //
1013 
1014  if (m_mode == CONFIGURE_LOCAL && packetType == PACKET_OTHERHOST)
1015  {
1016  //
1017  // We hooked the promiscuous mode protocol handler so we could get the
1018  // destination address of the actual packet. This means we will be
1019  // getting PACKET_OTHERHOST packets (not broadcast, not multicast, not
1020  // unicast to the ns-3 net device, but to some other address). In
1021  // CONFIGURE_LOCAL mode we are not interested in these packets since they
1022  // don't refer to the single MAC address shared by the ns-3 device and
1023  // the TAP device. If, however, we are in USE_LOCAL or USE_BRIDGE mode,
1024  // we want to act like a bridge and forward these PACKET_OTHERHOST
1025  // packets.
1026  //
1027  return true;
1028  }
1029 
1032 
1033  Ptr<Packet> p = packet->Copy();
1034  EthernetHeader header = EthernetHeader(false);
1035  header.SetSource(from);
1036  header.SetDestination(to);
1037 
1038  header.SetLengthType(protocol);
1039  p->AddHeader(header);
1040 
1041  NS_LOG_LOGIC("Writing packet to Linux host");
1042  NS_LOG_LOGIC("Pkt source is " << header.GetSource());
1043  NS_LOG_LOGIC("Pkt destination is " << header.GetDestination());
1044  NS_LOG_LOGIC("Pkt LengthType is " << header.GetLengthType());
1045  NS_LOG_LOGIC("Pkt size is " << p->GetSize());
1046 
1047  NS_ASSERT_MSG(p->GetSize() <= 65536,
1048  "TapBridge::ReceiveFromBridgedDevice: Packet too big " << p->GetSize());
1049  p->CopyData(m_packetBuffer, p->GetSize());
1050 
1051  uint32_t bytesWritten = write(m_sock, m_packetBuffer, p->GetSize());
1052  NS_ABORT_MSG_IF(bytesWritten != p->GetSize(),
1053  "TapBridge::ReceiveFromBridgedDevice(): Write error.");
1054 
1055  NS_LOG_LOGIC("End of receive packet handling on node " << m_node->GetId());
1056  return true;
1057 }
1058 
1059 void
1060 TapBridge::SetIfIndex(const uint32_t index)
1061 {
1062  NS_LOG_FUNCTION(this << index);
1063  m_ifIndex = index;
1064 }
1065 
1066 uint32_t
1068 {
1069  NS_LOG_FUNCTION(this);
1070  return m_ifIndex;
1071 }
1072 
1075 {
1076  NS_LOG_FUNCTION(this);
1077  return nullptr;
1078 }
1079 
1080 void
1082 {
1083  NS_LOG_FUNCTION(this << address);
1085 }
1086 
1087 Address
1089 {
1090  NS_LOG_FUNCTION(this);
1091  return m_address;
1092 }
1093 
1094 void
1096 {
1097  NS_LOG_FUNCTION(this << mode);
1098  m_mode = mode;
1099 }
1100 
1103 {
1104  NS_LOG_FUNCTION(this);
1105  return m_mode;
1106 }
1107 
1108 bool
1109 TapBridge::SetMtu(const uint16_t mtu)
1110 {
1111  NS_LOG_FUNCTION(this << mtu);
1112  m_mtu = mtu;
1113  return true;
1114 }
1115 
1116 uint16_t
1118 {
1119  NS_LOG_FUNCTION(this);
1120  return m_mtu;
1121 }
1122 
1123 void
1125 {
1126  NS_LOG_FUNCTION(this);
1127  if (!m_linkUp)
1128  {
1129  m_linkUp = true;
1131  }
1132 }
1133 
1134 bool
1136 {
1137  NS_LOG_FUNCTION(this);
1138  return m_linkUp;
1139 }
1140 
1141 void
1143 {
1144  NS_LOG_FUNCTION(this);
1146 }
1147 
1148 bool
1150 {
1151  NS_LOG_FUNCTION(this);
1152  return true;
1153 }
1154 
1155 Address
1157 {
1158  NS_LOG_FUNCTION(this);
1159  return Mac48Address("ff:ff:ff:ff:ff:ff");
1160 }
1161 
1162 bool
1164 {
1165  NS_LOG_FUNCTION(this);
1166  return true;
1167 }
1168 
1169 Address
1171 {
1172  NS_LOG_FUNCTION(this << multicastGroup);
1173  Mac48Address multicast = Mac48Address::GetMulticast(multicastGroup);
1174  return multicast;
1175 }
1176 
1177 bool
1179 {
1180  NS_LOG_FUNCTION(this);
1181  return false;
1182 }
1183 
1184 bool
1186 {
1187  NS_LOG_FUNCTION(this);
1188  //
1189  // Returning false from IsBridge in a device called TapBridge may seem odd
1190  // at first glance, but this test is for a device that bridges ns-3 devices
1191  // together. The Tap bridge doesn't do that -- it bridges an ns-3 device to
1192  // a Linux device. This is a completely different story.
1193  //
1194  return false;
1195 }
1196 
1197 bool
1198 TapBridge::Send(Ptr<Packet> packet, const Address& dst, uint16_t protocol)
1199 {
1200  NS_LOG_FUNCTION(this << packet << dst << protocol);
1201  NS_FATAL_ERROR("TapBridge::Send: You may not call Send on a TapBridge directly");
1202  return false;
1203 }
1204 
1205 bool
1206 TapBridge::SendFrom(Ptr<Packet> packet, const Address& src, const Address& dst, uint16_t protocol)
1207 {
1208  NS_LOG_FUNCTION(this << packet << src << dst << protocol);
1209  NS_FATAL_ERROR("TapBridge::Send: You may not call SendFrom on a TapBridge directly");
1210  return false;
1211 }
1212 
1213 Ptr<Node>
1215 {
1216  NS_LOG_FUNCTION(this);
1217  return m_node;
1218 }
1219 
1220 void
1222 {
1223  NS_LOG_FUNCTION(this);
1224  m_node = node;
1225 }
1226 
1227 bool
1229 {
1230  NS_LOG_FUNCTION(this);
1231  return true;
1232 }
1233 
1234 void
1236 {
1237  NS_LOG_FUNCTION(this);
1238  m_rxCallback = cb;
1239 }
1240 
1241 void
1243 {
1244  NS_LOG_FUNCTION(this);
1245  m_promiscRxCallback = cb;
1246 }
1247 
1248 bool
1250 {
1251  NS_LOG_FUNCTION(this);
1252  return true;
1253 }
1254 
1255 Address
1257 {
1258  NS_LOG_FUNCTION(this << addr);
1259  return Mac48Address::GetMulticast(addr);
1260 }
1261 
1262 } // namespace ns3
a polymophic address class
Definition: address.h:101
Hold variables of type enum.
Definition: enum.h:62
Packet header for Ethernet.
uint16_t GetLengthType() const
uint32_t GetSerializedSize() const override
void SetDestination(Mac48Address destination)
Mac48Address GetDestination() const
void SetLengthType(uint16_t size)
void SetSource(Mac48Address source)
Mac48Address GetSource() const
int m_fd
The file descriptor to read from.
Definition: fd-reader.h:135
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
bool IsBroadcast() const
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:80
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:257
static Ipv4Mask GetOnes()
Describes an IPv6 address.
Definition: ipv6-address.h:49
Header for the LLC/SNAP encapsulation.
uint16_t GetType()
Return the Ethertype.
uint32_t GetSerializedSize() const override
an EUI-48 address
Definition: mac48-address.h:46
static Mac48Address GetMulticast(Ipv4Address address)
static bool IsMatchingType(const Address &address)
void CopyFrom(const uint8_t buffer[6])
static Mac48Address ConvertFrom(const Address &address)
bool IsBroadcast() const
Network layer to device interface.
Definition: net-device.h:98
PacketType
Packet types are used as they are in Linux.
Definition: net-device.h:300
@ PACKET_OTHERHOST
Packet addressed to someone else.
Definition: net-device.h:307
uint32_t GetId() const
Definition: node.cc:117
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:352
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
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
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:384
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:305
uint64_t GetUid() const
Returns the packet's Uid.
Definition: packet.cc:412
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 void Cancel(const EventId &id)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
Definition: simulator.cc:285
static void ScheduleWithContext(uint32_t context, const Time &delay, FUNC f, Ts &&... args)
Schedule an event with the given context.
Definition: simulator.h:588
Hold variables of type string.
Definition: string.h:56
FdReader::Data DoRead() override
The read implementation.
Definition: tap-bridge.cc:55
A bridge to make it appear that a real host process is connected to an ns-3 net device.
Definition: tap-bridge.h:109
void SetBridgedNetDevice(Ptr< NetDevice > bridgedDevice)
Set the ns-3 net device to bridge.
Definition: tap-bridge.cc:939
bool ReceiveFromBridgedDevice(Ptr< NetDevice > device, Ptr< const Packet > packet, uint16_t protocol, const Address &src, const Address &dst, PacketType packetType)
Receives a packet from a bridged Device.
Definition: tap-bridge.cc:986
void CreateTap()
Call out to a separate process running as suid root in order to get our tap device created.
Definition: tap-bridge.cc:270
void SetIfIndex(const uint32_t index) override
Definition: tap-bridge.cc:1060
uint32_t m_nodeId
a copy of the node id so the read thread doesn't have to GetNode() in in order to find the node ID.
Definition: tap-bridge.h:455
static TypeId GetTypeId()
Get the type ID.
Definition: tap-bridge.cc:81
bool m_ns3AddressRewritten
Whether the MAC address of the underlying ns-3 device has already been rewritten is stored in this va...
Definition: tap-bridge.h:443
void AddLinkChangeCallback(Callback< void > callback) override
Definition: tap-bridge.cc:1142
uint8_t * m_packetBuffer
A 64K buffer to hold packet data while it is being sent.
Definition: tap-bridge.h:448
bool m_linkUp
Flag indicating whether or not the link is up.
Definition: tap-bridge.h:462
Address GetAddress() const override
Definition: tap-bridge.cc:1088
TracedCallback m_linkChangeCallbacks
Callbacks to fire if the link changes state (up or down).
Definition: tap-bridge.h:474
void SetMode(TapBridge::Mode mode)
Set the operating mode of this device.
Definition: tap-bridge.cc:1095
NetDevice::PromiscReceiveCallback m_promiscRxCallback
Callback used to hook the promiscuous packet receive callback of the TapBridge ns-3 net device.
Definition: tap-bridge.h:341
~TapBridge() override
Definition: tap-bridge.cc:167
void SetReceiveCallback(NetDevice::ReceiveCallback cb) override
Definition: tap-bridge.cc:1235
bool SendFrom(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber) override
Definition: tap-bridge.cc:1206
int m_sock
The socket (actually interpreted as fd) to use to talk to the Tap device on the real internet host.
Definition: tap-bridge.h:362
void StopTapDevice()
Tear down the device.
Definition: tap-bridge.cc:252
Address GetBroadcast() const override
Definition: tap-bridge.cc:1156
uint32_t m_ifIndex
The ns-3 interface index of this TapBridge net device.
Definition: tap-bridge.h:351
bool DiscardFromBridgedDevice(Ptr< NetDevice > device, Ptr< const Packet > packet, uint16_t protocol, const Address &src)
Receives a packet from a bridged Device.
Definition: tap-bridge.cc:975
bool NeedsArp() const override
Definition: tap-bridge.cc:1228
void SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb) override
Definition: tap-bridge.cc:1242
NetDevice::ReceiveCallback m_rxCallback
Callback used to hook the standard packet receive callback of the TapBridge ns-3 net device.
Definition: tap-bridge.h:330
Mac48Address m_address
The (unused) MAC address of the TapBridge net device.
Definition: tap-bridge.h:394
void Start(Time tStart)
Set a start time for the device.
Definition: tap-bridge.cc:187
bool SetMtu(const uint16_t mtu) override
Definition: tap-bridge.cc:1109
bool IsLinkUp() const override
Definition: tap-bridge.cc:1135
bool IsPointToPoint() const override
Return true if the net device is on a point-to-point link.
Definition: tap-bridge.cc:1178
bool IsBridge() const override
Return true if the net device is acting as a bridge.
Definition: tap-bridge.cc:1185
Ptr< TapBridgeFdReader > m_fdReader
Includes the ns-3 read thread used to do blocking reads on the fd corresponding to the host device.
Definition: tap-bridge.h:380
uint16_t m_mtu
The common mtu to use for the net devices.
Definition: tap-bridge.h:356
void ReadCallback(uint8_t *buf, ssize_t len)
Callback to process packets that are read.
Definition: tap-bridge.cc:712
Ipv4Address m_tapIp
The IP address to use as the device IP on the host.
Definition: tap-bridge.h:420
Ipv4Mask m_tapNetmask
The network mask to assign to the device created on the host.
Definition: tap-bridge.h:433
bool m_verbose
Flag indicating whether or not the link is up.
Definition: tap-bridge.h:469
bool SupportsSendFrom() const override
Definition: tap-bridge.cc:1249
void StartTapDevice()
Spin up the device.
Definition: tap-bridge.cc:210
Ptr< Packet > Filter(Ptr< Packet > packet, Address *src, Address *dst, uint16_t *type)
The host we are bridged to is in the evil real world.
Definition: tap-bridge.cc:870
Mode m_mode
The operating mode of the bridge.
Definition: tap-bridge.h:386
Ptr< Node > m_node
Pointer to the (ghost) Node to which we are connected.
Definition: tap-bridge.h:346
EventId m_stopEvent
The ID of the ns-3 event used to schedule the tear down of the underlying host Tap device and ns-3 re...
Definition: tap-bridge.h:374
void ForwardToBridgedDevice(uint8_t *buf, ssize_t len)
Forward a packet received from the tap device to the bridged ns-3 device.
Definition: tap-bridge.cc:739
void Stop(Time tStop)
Set a stop time for the device.
Definition: tap-bridge.cc:199
void NotifyLinkUp()
Notifies that the link is up and ready.
Definition: tap-bridge.cc:1124
Ptr< NetDevice > m_bridgedDevice
The ns-3 net device to which we are bridging.
Definition: tap-bridge.h:438
bool IsBroadcast() const override
Definition: tap-bridge.cc:1149
Mode
Enumeration of the operating modes supported in the class.
Definition: tap-bridge.h:122
@ USE_BRIDGE
ns-3 uses a pre-created tap, and bridges to a bridging net device
Definition: tap-bridge.h:126
@ USE_LOCAL
ns-3 uses a pre-created tap, without configuring it
Definition: tap-bridge.h:125
@ CONFIGURE_LOCAL
ns-3 creates and configures tap device
Definition: tap-bridge.h:124
void SetAddress(Address address) override
Set the address of this interface.
Definition: tap-bridge.cc:1081
Ptr< Node > GetNode() const override
Definition: tap-bridge.cc:1214
EventId m_startEvent
The ID of the ns-3 event used to schedule the start up of the underlying host Tap device and ns-3 rea...
Definition: tap-bridge.h:368
bool IsMulticast() const override
Definition: tap-bridge.cc:1163
Time m_tStart
Time to start spinning up the device.
Definition: tap-bridge.h:399
Ipv4Address m_tapGateway
The IP address to use as the device default gateway on the host.
Definition: tap-bridge.h:415
TapBridge::Mode GetMode()
Get the operating mode of this device.
Definition: tap-bridge.cc:1102
Ptr< NetDevice > GetBridgedNetDevice()
Get the bridged net device.
Definition: tap-bridge.cc:932
Time m_tStop
Time to start tearing down the device.
Definition: tap-bridge.h:404
void SetNode(Ptr< Node > node) override
Definition: tap-bridge.cc:1221
std::string m_tapDeviceName
The name of the device to create on the host.
Definition: tap-bridge.h:410
Address GetMulticast(Ipv4Address multicastGroup) const override
Make and return a MAC multicast address using the provided multicast group.
Definition: tap-bridge.cc:1170
void DoDispose() override
Call out to a separate process running as suid root in order to get our tap device created.
Definition: tap-bridge.cc:180
uint16_t GetMtu() const override
Definition: tap-bridge.cc:1117
bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber) override
Definition: tap-bridge.cc:1198
Ptr< Channel > GetChannel() const override
Definition: tap-bridge.cc:1074
uint32_t GetIfIndex() const override
Definition: tap-bridge.cc:1067
Mac48Address m_tapMac
The MAC address to use as the hardware address on the host; only used in UseLocal mode.
Definition: tap-bridge.h:428
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
void ConnectWithoutContext(const CallbackBase &callback)
Append a Callback to the chain (without a context).
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
Hold an unsigned integer type.
Definition: uinteger.h:45
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#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_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
EventImpl * MakeEvent(void(*f)())
Make an EventImpl from a function pointer taking varying numbers of arguments.
Definition: make-event.cc:36
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
address
Definition: first.py:47
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1414
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704
Ptr< const AttributeChecker > MakeEnumChecker(T v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition: enum.h:194
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
Ptr< const AttributeChecker > MakeStringChecker()
Definition: string.cc:30
Ptr< const AttributeAccessor > MakeStringAccessor(T1 a1)
Definition: string.h:57
std::string TapBufferToString(uint8_t *buffer, uint32_t len)
Convert a byte buffer to a string containing a hex representation of the buffer.
A structure representing data read.
Definition: fd-reader.h:91
#define TAP_MAGIC
Definition: tap-bridge.cc:76
uint32_t pktSize
packet size used for the simulation (in bytes)