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