14#include "ns3/config.h"
15#include "ns3/fd-net-device.h"
18#include "ns3/netmap-net-device.h"
19#include "ns3/object-factory.h"
20#include "ns3/packet.h"
21#include "ns3/simulator.h"
22#include "ns3/trace-helper.h"
23#include "ns3/uinteger.h"
31#include <net/ethernet.h>
33#include <net/netmap_user.h>
34#include <netinet/in.h>
40#include <sys/socket.h>
52#define EMU_MAGIC 65867
91 device->AggregateObject(ndqi);
92 netmapDevice->SetNetDeviceQueue(ndqi->GetTxQueue(0));
102 NS_FATAL_ERROR(
"NetmapNetDeviceHelper::SetFileDescriptor (): m_deviceName is not set");
109 int fd = socket(PF_INET, SOCK_DGRAM, 0);
116 bzero(&ifr,
sizeof(ifr));
117 strncpy((
char*)ifr.ifr_name,
m_deviceName.c_str(), IFNAMSIZ - 1);
120 int32_t rc = ioctl(fd, SIOCGIFINDEX, &ifr);
123 NS_FATAL_ERROR(
"NetmapNetDeviceHelper::SetFileDescriptor (): Can't get interface index");
126 rc = ioctl(fd, SIOCGIFFLAGS, &ifr);
129 NS_FATAL_ERROR(
"NetmapNetDeviceHelper::SetFileDescriptor (): Can't get interface flags");
143 if ((ifr.ifr_flags & IFF_PROMISC) == 0)
147 <<
" is not in promiscuous mode. Please config the interface in promiscuous "
148 "mode before to run the simulation.");
151 if ((ifr.ifr_flags & IFF_BROADCAST) != IFF_BROADCAST)
157 device->SetIsBroadcast(
false);
160 if ((ifr.ifr_flags & IFF_MULTICAST) == IFF_MULTICAST)
163 device->SetIsMulticast(
true);
174 rc = ioctl(fd, SIOCGIFMTU, &ifr);
177 NS_FATAL_ERROR(
"FdNetDevice::SetFileDescriptor (): Can't ioctl SIOCGIFMTU");
181 device->SetMtu(ifr.ifr_mtu);
200 int sock = socket(PF_UNIX, SOCK_DGRAM, 0);
204 "NetmapNetDeviceHelper::CreateFileDescriptor(): Unix socket creation error, errno = "
211 struct sockaddr_un un;
212 memset(&un, 0,
sizeof(un));
213 un.sun_family = AF_UNIX;
214 int status = bind(sock, (
struct sockaddr*)&un,
sizeof(sa_family_t));
217 NS_FATAL_ERROR(
"NetmapNetDeviceHelper::CreateFileDescriptor(): Could not bind(): errno = "
231 socklen_t len =
sizeof(un);
232 status = getsockname(sock, (
struct sockaddr*)&un, &len);
236 "NetmapNetDeviceHelper::CreateFileDescriptor(): Could not getsockname(): errno = "
244 NS_LOG_INFO(
"Encoded Unix socket as \"" << path <<
"\"");
256 pid_t pid = ::fork();
266 std::ostringstream oss;
270 NS_LOG_INFO(
"Parameters set to \"" << oss.str() <<
"\"");
275 status = ::execlp(NETMAP_DEV_CREATOR,
285 "NetmapNetDeviceHelper::CreateFileDescriptor(): Back from execlp(), status = "
286 << status <<
", errno = " << ::strerror(errno));
296 pid_t waited = waitpid(pid, &st, 0);
300 "NetmapNetDeviceHelper::CreateFileDescriptor(): waitpid() fails, errno = "
303 NS_ASSERT_MSG(pid == waited,
"NetmapNetDeviceHelper::CreateFileDescriptor(): pid mismatch");
312 int exitStatus = WEXITSTATUS(st);
315 NS_FATAL_ERROR(
"NetmapNetDeviceHelper::CreateFileDescriptor(): socket creator "
316 "exited normally with status "
323 "NetmapNetDeviceHelper::CreateFileDescriptor(): socket creator exited abnormally");
339 iov.iov_base = &magic;
340 iov.iov_len =
sizeof(magic);
353 size_t msg_size =
sizeof(int);
354 char control[CMSG_SPACE(msg_size)];
367 msg.msg_name =
nullptr;
371 msg.msg_control = control;
372 msg.msg_controllen =
sizeof(control);
379 ssize_t bytesRead = recvmsg(sock, &msg, 0);
380 if (bytesRead !=
sizeof(
int))
382 NS_FATAL_ERROR(
"NetmapNetDeviceHelper::CreateFileDescriptor(): Wrong byte count from "
391 struct cmsghdr* cmsg;
392 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg !=
nullptr; cmsg = CMSG_NXTHDR(&msg, cmsg))
394 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
403 NS_LOG_INFO(
"Got SCM_RIGHTS with correct magic " << magic);
404 int* rawSocket = (
int*)CMSG_DATA(cmsg);
405 NS_LOG_INFO(
"Got the socket from the socket creator = " << *rawSocket);
410 NS_LOG_INFO(
"Got SCM_RIGHTS, but with bad magic " << magic);
414 NS_FATAL_ERROR(
"Did not get the raw socket from the socket creator");
435 memset(&nmr, 0,
sizeof(nmr));
437 nmr.nr_version = NETMAP_API;
443 int code = ioctl(fd, NIOCREGIF, &nmr);
450 uint8_t* memory = (uint8_t*)mmap(0, nmr.nr_memsize, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
452 if (memory == MAP_FAILED)
458 struct netmap_if* nifp = NETMAP_IF(memory, nmr.nr_offset);
462 NS_FATAL_ERROR(
"Failed getting the base struct of the interface in netmap mode");
465 device->SetNetmapInterfaceRepresentation(nifp);
466 device->SetTxRingsInfo(nifp->ni_tx_rings, nmr.nr_tx_slots);
467 device->SetRxRingsInfo(nifp->ni_rx_rings, nmr.nr_rx_slots);
469 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()
Get the type ID.
Ptr< NetDevice > InstallPriv(Ptr< Node > node) const
This method creates an ns3::FdNetDevice attached to a physical network interface.
virtual int CreateFileDescriptor() const
Call out to a separate process running as suid root in order to get a raw socket.
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.
std::string GetDeviceName()
Get the device name of this device.
virtual void SetDeviceAttributes(Ptr< FdNetDevice > device) const
Sets device flags and MTU.
Smart pointer class similar to boost::intrusive_ptr.
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.
Ptr< T > CreateObjectWithAttributes(Args... args)
Allocate an Object on the heap and initialize with a set of attributes.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
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.