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