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