23 #include "ns3/channel.h"
24 #include "ns3/packet.h"
25 #include "ns3/ethernet-header.h"
26 #include "ns3/llc-snap-header.h"
28 #include "ns3/abort.h"
29 #include "ns3/boolean.h"
30 #include "ns3/string.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"
40 #include <sys/socket.h>
61 #include <linux/if_tun.h>
62 #include <sys/ioctl.h>
73 uint32_t bufferSize = 65536;
74 uint8_t *buf = (uint8_t *)std::malloc (bufferSize);
78 ssize_t len = read (
m_fd, buf, bufferSize);
90 #define TAP_MAGIC 95549
99 .AddConstructor<TapBridge> ()
100 .AddAttribute (
"Mtu",
"The MAC-level Maximum Transmission Unit",
104 MakeUintegerChecker<uint16_t> ())
105 .AddAttribute (
"DeviceName",
106 "The name of the tap device to create.",
109 MakeStringChecker ())
110 .AddAttribute (
"Gateway",
111 "The IP address of the default gateway to assign to the host machine, when in ConfigureLocal mode.",
114 MakeIpv4AddressChecker ())
115 .AddAttribute (
"IpAddress",
116 "The IP address to assign to the tap device, when in ConfigureLocal mode. "
117 "This address will override the discovered IP address of the simulated device.",
120 MakeIpv4AddressChecker ())
121 .AddAttribute (
"MacAddress",
122 "The MAC address to assign to the tap device, when in ConfigureLocal mode. "
123 "This address will override the discovered MAC address of the simulated device.",
126 MakeMac48AddressChecker ())
127 .AddAttribute (
"Netmask",
128 "The network mask to assign to the tap device, when in ConfigureLocal mode. "
129 "This address will override the discovered MAC address of the simulated device.",
132 MakeIpv4MaskChecker ())
133 .AddAttribute (
"Start",
134 "The simulation time at which to spin up the tap device read thread.",
138 .AddAttribute (
"Stop",
139 "The simulation time at which to tear down the tap device read thread.",
143 .AddAttribute (
"Mode",
144 "The operating and configuration mode to use.",
161 m_ns3AddressRewritten (false)
322 int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
323 NS_ABORT_MSG_IF (sock == -1,
"TapBridge::CreateTap(): Unix socket creation error, errno = " << std::strerror (errno));
328 struct sockaddr_un un;
329 memset (&un, 0,
sizeof (un));
330 un.sun_family = AF_UNIX;
331 int status = bind (sock, (
struct sockaddr*)&un,
sizeof (sa_family_t));
332 NS_ABORT_MSG_IF (status == -1,
"TapBridge::CreateTap(): Could not bind(): errno = " << std::strerror (errno));
343 socklen_t len =
sizeof (un);
344 status = getsockname (sock, (
struct sockaddr*)&un, &len);
345 NS_ABORT_MSG_IF (status == -1,
"TapBridge::CreateTap(): Could not getsockname(): errno = " << std::strerror (errno));
351 NS_LOG_INFO (
"Encoded Unix socket as \"" << path <<
"\"");
369 pid_t pid = ::fork ();
408 NS_FATAL_ERROR (
"TapBridge::CreateTap(): Tap device IP configuration requested but neither IP address nor IP netmask is provided");
413 Ipv4Mask ipv4Mask (
"255.255.255.255");
420 NS_LOG_WARN (
"Underlying bridged NetDevice has multiple IP addresses; using first one.");
443 std::ostringstream ossDeviceName;
450 std::ostringstream ossGateway;
458 std::ostringstream ossIp;
461 ossIp <<
"-i" << ipv4Address;
468 std::ostringstream ossMac;
471 ossMac <<
"-m" << mac48Address;
478 std::ostringstream ossNetmask;
481 ossNetmask <<
"-n" << ipv4Mask;
488 std::ostringstream ossMode;
503 std::ostringstream ossPath;
504 ossPath <<
"-p" << path;
508 status = ::execlp (TAP_CREATOR,
510 ossDeviceName.str ().c_str (),
511 ossGateway.str ().c_str (),
512 ossIp.str ().c_str (),
513 ossMac.str ().c_str (),
514 ossNetmask.str ().c_str (),
515 ossMode.str ().c_str (),
516 ossPath.str ().c_str (),
523 NS_FATAL_ERROR (
"TapBridge::CreateTap(): Back from execlp(), errno = " << ::strerror (errno));
533 pid_t waited = waitpid (pid, &st, 0);
534 NS_ABORT_MSG_IF (waited == -1,
"TapBridge::CreateTap(): waitpid() fails, errno = " << std::strerror (errno));
535 NS_ASSERT_MSG (pid == waited,
"TapBridge::CreateTap(): pid mismatch");
544 int exitStatus = WEXITSTATUS (st);
546 "TapBridge::CreateTap(): socket creator exited normally with status " << exitStatus);
550 NS_FATAL_ERROR (
"TapBridge::CreateTap(): socket creator exited abnormally");
568 iov.iov_base = &magic;
569 iov.iov_len =
sizeof(magic);
582 size_t msg_size =
sizeof(int);
583 char control[CMSG_SPACE (msg_size)];
600 msg.msg_control = control;
601 msg.msg_controllen =
sizeof (control);
608 ssize_t bytesRead = recvmsg (sock, &msg, 0);
609 NS_ABORT_MSG_IF (bytesRead !=
sizeof(
int),
"TapBridge::CreateTap(): Wrong byte count from socket creator");
616 struct cmsghdr *cmsg;
617 for (cmsg = CMSG_FIRSTHDR (&msg); cmsg != NULL; cmsg = CMSG_NXTHDR (&msg, cmsg))
619 if (cmsg->cmsg_level == SOL_SOCKET &&
620 cmsg->cmsg_type == SCM_RIGHTS)
629 NS_LOG_INFO (
"Got SCM_RIGHTS with correct magic " << magic);
630 int *rawSocket = (
int*)CMSG_DATA (cmsg);
631 NS_LOG_INFO (
"Got the socket from the socket creator = " << *rawSocket);
637 NS_LOG_INFO (
"Got SCM_RIGHTS, but with bad magic " << magic);
641 NS_FATAL_ERROR (
"Did not get the raw socket from the socket creator");
666 NS_LOG_INFO (
"TapBridge::ReadCallback(): Scheduling handler");
702 Ptr<Packet> packet = Create<Packet> (
reinterpret_cast<const uint8_t *
> (buf), len);
720 NS_LOG_LOGIC (
"TapBridge::ForwardToBridgedDevice: Discarding packet as unfit for ns-3 consumption");
733 "TapBridge::ForwardToBridgedDevice: Source addr is broadcast");
741 NS_LOG_LOGIC (
"Learned MacAddr is " << learnedMac <<
": setting ns-3 device to use this address");
750 NS_LOG_LOGIC (
"Forwarding packet to ns-3 device via Send()");
870 NS_ASSERT_MSG (
m_node != 0,
"TapBridge::SetBridgedDevice: Bridge not installed in a node");
871 NS_ASSERT_MSG (bridgedDevice !=
this,
"TapBridge::SetBridgedDevice: Cannot bridge to self");
876 NS_FATAL_ERROR (
"TapBridge::SetBridgedDevice: Device does not support eui 48 addresses: cannot be added to bridge.");
881 NS_FATAL_ERROR (
"TapBridge::SetBridgedDevice: Device does not support SendFrom: cannot be added to bridge.");
902 NS_LOG_LOGIC (
"Discarding packet stolen from bridged device " << device);
915 NS_LOG_FUNCTION (device << packet << protocol << src << dst << packetType);
1109 NS_FATAL_ERROR (
"TapBridge::Send: You may not call Send on a TapBridge directly");
1117 NS_FATAL_ERROR (
"TapBridge::Send: You may not call SendFrom on a TapBridge directly");