24 #include "ns3/abort.h"
25 #include "ns3/config.h"
26 #include "ns3/fd-net-device.h"
28 #include "ns3/names.h"
29 #include "ns3/object-factory.h"
30 #include "ns3/packet.h"
31 #include "ns3/simulator.h"
32 #include "ns3/trace-helper.h"
33 #include "ns3/netmap-net-device.h"
34 #include "ns3/uinteger.h"
36 #include <arpa/inet.h>
42 #include <net/ethernet.h>
44 #include <netinet/in.h>
50 #include <sys/socket.h>
52 #include <sys/ioctl.h>
59 #include <net/netmap_user.h>
65 #define EMU_MAGIC 65867
102 device->AggregateObject (ndqi);
103 netmapDevice->SetNetDeviceQueue (ndqi->GetTxQueue (0));
114 NS_FATAL_ERROR (
"NetmapNetDeviceHelper::SetFileDescriptor (): m_deviceName is not set");
121 int fd = socket (PF_INET, SOCK_DGRAM, 0);
127 bzero (&ifr,
sizeof(ifr));
128 strncpy ((
char *)ifr.ifr_name,
m_deviceName.c_str (), IFNAMSIZ - 1);
131 int32_t rc = ioctl (fd, SIOCGIFINDEX, &ifr);
134 NS_FATAL_ERROR (
"NetmapNetDeviceHelper::SetFileDescriptor (): Can't get interface index");
137 rc = ioctl (fd, SIOCGIFFLAGS, &ifr);
140 NS_FATAL_ERROR (
"NetmapNetDeviceHelper::SetFileDescriptor (): Can't get interface flags");
154 if ((ifr.ifr_flags & IFF_PROMISC) == 0)
158 <<
" is not in promiscuous mode. Please config the interface in promiscuous "
159 "mode before to run the simulation.");
162 if ((ifr.ifr_flags & IFF_BROADCAST) != IFF_BROADCAST)
168 device->SetIsBroadcast (
false);
171 if ((ifr.ifr_flags & IFF_MULTICAST) == IFF_MULTICAST)
174 device->SetIsMulticast (
true);
185 rc = ioctl (fd, SIOCGIFMTU, &ifr);
188 NS_FATAL_ERROR (
"FdNetDevice::SetFileDescriptor (): Can't ioctl SIOCGIFMTU");
192 device->SetMtu (ifr.ifr_mtu);
212 int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
215 NS_FATAL_ERROR (
"NetmapNetDeviceHelper::CreateFileDescriptor(): Unix socket creation error, errno = " << strerror (errno));
221 struct sockaddr_un un;
222 memset (&un, 0,
sizeof (un));
223 un.sun_family = AF_UNIX;
224 int status = bind (sock, (
struct sockaddr*)&un,
sizeof (sa_family_t));
227 NS_FATAL_ERROR (
"NetmapNetDeviceHelper::CreateFileDescriptor(): Could not bind(): errno = " << strerror (errno));
240 socklen_t len =
sizeof (un);
241 status = getsockname (sock, (
struct sockaddr*)&un, &len);
244 NS_FATAL_ERROR (
"NetmapNetDeviceHelper::CreateFileDescriptor(): Could not getsockname(): errno = " << strerror (errno));
251 NS_LOG_INFO (
"Encoded Unix socket as \"" << path <<
"\"");
263 pid_t pid = ::fork ();
273 std::ostringstream oss;
279 NS_LOG_INFO (
"Parameters set to \"" << oss.str () <<
"\"");
284 status = ::execlp (NETMAP_DEV_CREATOR,
293 NS_FATAL_ERROR (
"NetmapNetDeviceHelper::CreateFileDescriptor(): Back from execlp(), status = " <<
294 status <<
", errno = " << ::strerror (errno));
304 pid_t waited = waitpid (pid, &st, 0);
307 NS_FATAL_ERROR (
"NetmapNetDeviceHelper::CreateFileDescriptor(): waitpid() fails, errno = " << strerror (errno));
309 NS_ASSERT_MSG (pid == waited,
"NetmapNetDeviceHelper::CreateFileDescriptor(): pid mismatch");
318 int exitStatus = WEXITSTATUS (st);
321 NS_FATAL_ERROR (
"NetmapNetDeviceHelper::CreateFileDescriptor(): socket creator exited normally with status " << exitStatus);
326 NS_FATAL_ERROR (
"NetmapNetDeviceHelper::CreateFileDescriptor(): socket creator exited abnormally");
342 iov.iov_base = &magic;
343 iov.iov_len =
sizeof(magic);
356 size_t msg_size =
sizeof(int);
357 char control[CMSG_SPACE (msg_size)];
374 msg.msg_control = control;
375 msg.msg_controllen =
sizeof (control);
382 ssize_t bytesRead = recvmsg (sock, &msg, 0);
383 if (bytesRead !=
sizeof(
int))
385 NS_FATAL_ERROR (
"NetmapNetDeviceHelper::CreateFileDescriptor(): Wrong byte count from socket creator");
393 struct cmsghdr *cmsg;
394 for (cmsg = CMSG_FIRSTHDR (&msg); cmsg != NULL; cmsg = CMSG_NXTHDR (&msg, cmsg))
396 if (cmsg->cmsg_level == SOL_SOCKET
397 && cmsg->cmsg_type == SCM_RIGHTS)
406 NS_LOG_INFO (
"Got SCM_RIGHTS with correct magic " << magic);
407 int *rawSocket = (
int*)CMSG_DATA (cmsg);
408 NS_LOG_INFO (
"Got the socket from the socket creator = " << *rawSocket);
413 NS_LOG_INFO (
"Got SCM_RIGHTS, but with bad magic " << magic);
417 NS_FATAL_ERROR (
"Did not get the raw socket from the socket creator");
438 memset (&nmr, 0,
sizeof (nmr));
440 nmr.nr_version = NETMAP_API;
446 int code = ioctl (fd, NIOCREGIF, &nmr);
453 uint8_t *memory = (uint8_t *) mmap (0, nmr.nr_memsize, PROT_WRITE | PROT_READ,
456 if (memory == MAP_FAILED)
462 struct netmap_if *nifp = NETMAP_IF (memory, nmr.nr_offset);
466 NS_FATAL_ERROR (
"Failed getting the base struct of the interface in netmap mode");
469 device->SetNetmapInterfaceRepresentation (nifp);
470 device->SetTxRingsInfo (nifp->ni_tx_rings, nmr.nr_tx_slots);
471 device->SetRxRingsInfo (nifp->ni_rx_rings, nmr.nr_rx_slots);
473 device->SetFileDescriptor (fd);
virtual Ptr< NetDevice > InstallPriv(Ptr< Node > node) const
This method creates an ns3::FdNetDevice and associates it to a node.
void SetTypeId(std::string type)
Set the TypeId of the Objects to be created by this helper.
a NetDevice to read/write network traffic from/into a file descriptor.
static TypeId GetTypeId(void)
Get the type ID.
std::string GetDeviceName(void)
Get the device name of this device.
Ptr< NetDevice > InstallPriv(Ptr< Node > node) const
This method creates an ns3::FdNetDevice attached to a physical network interface.
void SetDeviceName(std::string deviceName)
Set the device name of this device.
std::string m_deviceName
The unix/linux name of the underlying device (e.g., eth0)
void SwitchInNetmapMode(int fd, Ptr< NetmapNetDevice > device) const
Switch the fd in netmap mode.
virtual int CreateFileDescriptor(void) const
Call out to a separate process running as suid root in order to get a raw socket.
virtual void SetDeviceAttributes(Ptr< FdNetDevice > device) const
Sets device flags and MTU.
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
AttributeValue implementation for TypeId.
Hold an unsigned integer type.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::string BufferToString(uint8_t *buffer, uint32_t len)
Convert a byte buffer to a string containing a hex representation of the buffer.
ns3::StringValue attribute value declarations.