23 #include "ns3/queue.h"
24 #include "ns3/simulator.h"
25 #include "ns3/ethernet-header.h"
26 #include "ns3/ethernet-trailer.h"
27 #include "ns3/llc-snap-header.h"
28 #include "ns3/boolean.h"
29 #include "ns3/uinteger.h"
30 #include "ns3/pointer.h"
31 #include "ns3/string.h"
32 #include "ns3/trace-source-accessor.h"
33 #include "ns3/channel.h"
34 #include "ns3/system-thread.h"
35 #include "ns3/mac48-address.h"
40 #include <sys/socket.h>
42 #include <sys/ioctl.h>
43 #include <net/ethernet.h>
45 #include <netinet/in.h>
46 #include <netpacket/packet.h>
47 #include <arpa/inet.h>
60 #define EMU_MAGIC 65867
67 .AddConstructor<EmuNetDevice> ()
68 .AddAttribute (
"Mtu",
"The MAC-level Maximum Transmission Unit",
71 MakeUintegerChecker<uint16_t> ())
72 .AddAttribute (
"Address",
73 "The ns-3 MAC address of this (virtual) device.",
76 MakeMac48AddressChecker ())
77 .AddAttribute (
"DeviceName",
78 "The name of the underlying real device (e.g. eth1).",
82 .AddAttribute (
"Start",
83 "The simulation time at which to spin up the device thread.",
87 .AddAttribute (
"Stop",
88 "The simulation time at which to tear down the device thread.",
92 .AddAttribute (
"EncapsulationMode",
93 "The link-layer encapsulation type to use.",
105 .AddAttribute (
"TxQueue",
106 "A queue to use as the transmit queue in the device.",
109 MakePointerChecker<Queue> ())
111 .AddAttribute (
"RxQueueSize",
"Maximum size of the read queue. "
112 "This value limits number of packets that have been read "
113 "from the network into a memory buffer but have not yet "
114 "been processed by the simulator.",
117 MakeUintegerChecker<uint32_t> ())
127 .AddTraceSource (
"MacTx",
128 "Trace source indicating a packet has arrived for transmission by this device",
130 .AddTraceSource (
"MacTxDrop",
131 "Trace source indicating a packet has been dropped by the device before transmission",
133 .AddTraceSource (
"MacPromiscRx",
134 "A packet has been received by this device, has been passed up from the physical layer "
135 "and is being forwarded up the local protocol stack. This is a promiscuous trace,",
137 .AddTraceSource (
"MacRx",
138 "A packet has been received by this device, has been passed up from the physical layer "
139 "and is being forwarded up the local protocol stack. This is a non-promiscuous trace,",
143 .AddTraceSource (
"MacRxDrop",
144 "Trace source indicating a packet was dropped before being forwarded up the stack",
156 .AddTraceSource (
"PhyTxBegin",
157 "Trace source indicating a packet has begun transmitting over the channel",
159 .AddTraceSource (
"PhyTxEnd",
160 "Trace source indicating a packet has been completely transmitted over the channel",
162 .AddTraceSource (
"PhyTxDrop",
163 "Trace source indicating a packet has been dropped by the device during transmission",
165 .AddTraceSource (
"PhyRxBegin",
166 "Trace source indicating a packet has begun being received by the device",
168 .AddTraceSource (
"PhyRxEnd",
169 "Trace source indicating a packet has been completely received by the device",
171 .AddTraceSource (
"PhyRxDrop",
172 "Trace source indicating a packet has been dropped by the device during reception",
178 .AddTraceSource (
"Sniffer",
179 "Trace source simulating a non-promiscuous packet sniffer attached to the device",
181 .AddTraceSource (
"PromiscSniffer",
182 "Trace source simulating a promiscuous packet sniffer attached to the device",
194 m_ifIndex (std::numeric_limits<uint32_t>::max ()),
196 m_isBroadcast (true),
197 m_isMulticast (false),
198 m_pendingReadCount (0)
271 NS_FATAL_ERROR (
"EmuNetDevice::StartDevice(): Device is already started");
295 bzero (&ifr,
sizeof(ifr));
296 strncpy ((
char *)ifr.ifr_name,
m_deviceName.c_str (), IFNAMSIZ);
299 int32_t rc = ioctl (
m_sock, SIOCGIFINDEX, &ifr);
302 NS_FATAL_ERROR (
"EmuNetDevice::StartDevice(): Can't get interface index");
313 struct sockaddr_ll ll;
314 bzero (&ll,
sizeof(ll));
316 ll.sll_family = AF_PACKET;
318 ll.sll_protocol = htons (ETH_P_ALL);
322 rc = bind (
m_sock, (
struct sockaddr *)&ll,
sizeof (ll));
325 NS_FATAL_ERROR (
"EmuNetDevice::StartDevice(): Can't bind to specified interface");
328 rc = ioctl (
m_sock, SIOCGIFFLAGS, &ifr);
331 NS_FATAL_ERROR (
"EmuNetDevice::StartDevice(): Can't get interface flags");
345 if ((ifr.ifr_flags & IFF_PROMISC) == 0)
349 if ((ifr.ifr_flags & IFF_BROADCAST) != IFF_BROADCAST)
357 if ((ifr.ifr_flags & IFF_MULTICAST) == IFF_MULTICAST)
368 NS_FATAL_ERROR (
"EmuNetDevice::StartDevice(): Receive thread is already running");
392 int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
395 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): Unix socket creation error, errno = " << std::strerror (errno));
401 struct sockaddr_un un;
402 memset (&un, 0,
sizeof (un));
403 un.sun_family = AF_UNIX;
404 int status = bind (sock, (
struct sockaddr*)&un,
sizeof (sa_family_t));
407 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): Could not bind(): errno = " << std::strerror (errno));
420 socklen_t len =
sizeof (un);
421 status = getsockname (sock, (
struct sockaddr*)&un, &len);
424 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): Could not getsockname(): errno = " << std::strerror (errno));
431 NS_LOG_INFO (
"Encoded Unix socket as \"" << path <<
"\"");
443 pid_t pid = ::fork ();
453 std::ostringstream oss;
455 NS_LOG_INFO (
"Parameters set to \"" << oss.str () <<
"\"");
460 status = ::execlp (EMU_SOCK_CREATOR,
469 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): Back from execlp(), errno = " << std::strerror (errno));
479 pid_t waited = waitpid (pid, &st, 0);
482 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): waitpid() fails, errno = " << std::strerror (errno));
484 NS_ASSERT_MSG (pid == waited,
"EmuNetDevice::CreateSocket(): pid mismatch");
493 int exitStatus = WEXITSTATUS (st);
496 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): socket creator exited normally with status " << exitStatus);
501 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): socket creator exited abnormally");
517 iov.iov_base = &magic;
518 iov.iov_len =
sizeof(magic);
531 size_t msg_size =
sizeof(int);
532 char control[CMSG_SPACE (msg_size)];
549 msg.msg_control = control;
550 msg.msg_controllen =
sizeof (control);
557 ssize_t bytesRead = recvmsg (sock, &msg, 0);
558 if (bytesRead !=
sizeof(
int))
560 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): Wrong byte count from socket creator");
568 struct cmsghdr *cmsg;
569 for (cmsg = CMSG_FIRSTHDR (&msg); cmsg != NULL; cmsg = CMSG_NXTHDR (&msg, cmsg))
571 if (cmsg->cmsg_level == SOL_SOCKET &&
572 cmsg->cmsg_type == SCM_RIGHTS)
581 NS_LOG_INFO (
"Got SCM_RIGHTS with correct magic " << magic);
582 int *rawSocket = (
int*)CMSG_DATA (cmsg);
583 NS_LOG_INFO (
"Got the socket from the socket creator = " << *rawSocket);
589 NS_LOG_INFO (
"Got SCM_RIGHTS, but with bad magic " << magic);
593 NS_FATAL_ERROR (
"Did not get the raw socket from the socket creator");
620 Ptr<Packet> packet = Create<Packet> (
reinterpret_cast<const uint8_t *
> (buf), len);
753 struct sockaddr_ll addr;
754 socklen_t addrSize =
sizeof (addr);
778 struct timespec time = { 0, 100000000L };
779 nanosleep (&time, NULL);
787 uint32_t bufferSize = 65536;
788 uint8_t *buf = (uint8_t *)std::malloc (bufferSize);
791 NS_FATAL_ERROR (
"EmuNetDevice::ReadThread(): malloc packet buffer failed");
795 len = recvfrom (
m_sock, buf, bufferSize, 0, (
struct sockaddr *)&addr, &addrSize);
805 NS_LOG_INFO (
"EmuNetDevice::ReadThread(): Scheduling handler");
896 NS_ASSERT_MSG (packet,
"EmuNetDevice::SendFrom(): packet zero from queue");
901 struct sockaddr_ll ll;
902 bzero (&ll,
sizeof (ll));
904 ll.sll_family = AF_PACKET;
906 ll.sll_protocol = htons (ETH_P_ALL);
916 return rc == -1 ?
false :
true;
991 bzero (&ifr,
sizeof (ifr));
994 int32_t fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_IP);
997 int32_t rc = ioctl (fd, SIOCGIFMTU, &ifr);
1000 NS_FATAL_ERROR (
"EmuNetDevice::GetMtu(): Can't ioctl SIOCGIFMTU");