fd-net-device: Finalize merge of DPDK and netmap emulation features

* Handle code review comments (due to Rediet and Mohit)
* Add attribute to configure netmap sync and notify period
This commit is contained in:
Tom Henderson
2020-09-16 21:04:44 -07:00
parent 8108a52069
commit 696bc53b08
17 changed files with 140 additions and 157 deletions

View File

@@ -1,5 +1,5 @@
DPDK NetDevice
-------------------------
--------------
.. include:: replace.txt
.. highlight:: cpp
@@ -101,12 +101,12 @@ To compile DPDK from source, you need to perform the following 4 steps:
1. Download the source
######################
Head over to `DPDK Downloads <https://core.dpdk.org/download/>`_ page to get the latest stable source. (This module has been tested with version 19.11 LTS and DpdkNetDevice will only be enabled if this version is available.)
Visit the `DPDK Downloads <https://core.dpdk.org/download/>`_ page to download the latest stable source. (This module has been tested with version 19.11 LTS and DpdkNetDevice will only be enabled if this version is available.)
2. Configure DPDK as a shared library
#####################################
Goto the DPDK directory, edit ``config/common_base`` file to change following line to compile DPDK as a shared library:
In the DPDK directory, edit the ``config/common_base`` file to change the following line to compile DPDK as a shared library:
.. sourcecode:: text
@@ -116,7 +116,7 @@ Goto the DPDK directory, edit ``config/common_base`` file to change following li
3. Install the source
#####################
Refer `Installation <https://doc.dpdk.org/guides/linux_gsg/build_dpdk.html>`_ for detailed instructions.
Refer to `Installation <https://doc.dpdk.org/guides/linux_gsg/build_dpdk.html>`_ for detailed instructions.
For a 64 bit linux machine with gcc, run:
@@ -127,7 +127,7 @@ For a 64 bit linux machine with gcc, run:
4. Export DPDK Environment variables
####################################
Export following environment variables:
Export the following environment variables:
* RTE_SDK as the your DPDK source folder.
* RTE_TARGET as the build target directory.
@@ -147,7 +147,7 @@ It is advisable that you export these variables in ``.bashrc`` or similar for re
Load DPDK Drivers to kernel
===========================
Execute following:
Execute the following:
.. sourcecode:: text
@@ -229,7 +229,7 @@ it is found, a user should see:
``DpdkNetDevice`` does not use a dedicated helper class, but reuses the
``EmuFdNetDeviceHelper`` class provided in the ``fd-net-device/helper``
directory. The ``EmuFdNetDeviceHelper`` will allows us to set ``dpdkMode``
directory. The ``EmuFdNetDeviceHelper`` allows us to set ``dpdkMode``
which will launch the ``DpdkNetDevice`` instead of the ``FdNetDevice``.
.. sourcecode:: text
@@ -320,5 +320,5 @@ Examples
The following examples are provided:
* ``fd-emu-dpdk-ping.cc``: This example uses the EmuFdNetDeviceHelper in Dpdk mode to send ICMP traffic bypassing the kernel over a real channel.
* ``fd-emu-dpdk-onoff.cc``: This example allows us to measure the throughput of the ``DpdkNetDevice`` by sending traffic from the simulated node to a real device using the ``ns3::OnOffApplication`` while leveraging DPDKs fast packet processing abilities. This is achieved by saturating the channel with TCP/UDP traffic.
* ``fd-emu-ping.cc``: This example can be configured to use the EmuFdNetDeviceHelper in DPDK mode to send ICMP traffic bypassing the kernel over a real channel.
* ``fd-emu-onoff.cc``: This example can be configured to measure the throughput of the ``DpdkNetDevice`` by sending traffic from the simulated node to a real device using the ``ns3::OnOffApplication`` while leveraging DPDKs fast packet processing abilities. This is achieved by saturating the channel with TCP/UDP traffic.

View File

@@ -19,7 +19,7 @@ host networking stack and gains direct access to network device.
netmap was developed by Luigi Rizzo [Rizzo2012]_ and is maintained as
an open source project on GitHub at https://github.com/luigirizzo/netmap.
The NetmapNetDevice for ns-3 [Imputato2019]_ was developed by Pasquale Imputato in the 2017-19 timeframe. The use of NetmapNetDevice requires that the
The ``NetmapNetDevice`` for |ns3| [Imputato2019]_ was developed by Pasquale Imputato in the 2017-19 timeframe. The use of NetmapNetDevice requires that the
host system has netmap support (and for best performance, the drivers
must support netmap and must be using a netmap-enabled device driver). Users
can expect that emulation support using Netmap will support higher packets
@@ -46,7 +46,7 @@ read/write methods, which have to make use of the netmap API to coordinate
the exchange of packets with the netmap rings.
In the initialization stage, the network device is switched to netmap mode,
so that ns-3 is able to send/receive packets to/from the
so that |ns3| is able to send/receive packets to/from the
real network device by writing/reading them to/from the netmap rings.
Following the design of the ``FdNetDevice``, a separate reading thread is
started during the initialization. The task of the reading thread is
@@ -68,18 +68,18 @@ amount of bytes that have been transferred to the network device.
The read method is called by the reading thread to retrieve new incoming
packets stored in the netmap receiver ring and pass them to the appropriate
ns-3 protocol handler for further processing within the simulators network
|ns3| protocol handler for further processing within the simulators network
stack. After retrieving packets, the reading thread also synchronizes
the netmap receiver ring, so that the retrieved packets can be removed
from the netmap receiver ring.
The ``NetmapNetDevice`` also specializes the write method, i.e., the method
used to transmit a packet received from the upper layer (the ns-3 traffic
used to transmit a packet received from the upper layer (the |ns3| traffic
control layer). The write method uses the netmap API to write the packet to a
free slot in the netmap
transmission ring. After writing a packet, the write method checks whether
there is enough room in the netmap transmission ring for another packet.
If not, the ``NetmapNetDevice`` stops its queue so that the ns-3 traffic
If not, the ``NetmapNetDevice`` stops its queue so that the |ns3| traffic
control layer does not attempt to send a packet that could not be stored in
the netmap transmission ring.
@@ -90,7 +90,7 @@ transmission ring. In particular, the sync thread also checks the number of
free slots in the netmap transmission ring in case the ``NetmapNetDevice``
queue is stopped. If the number of free slots exceeds a configurable value,
the sync thread restarts the ``NetmapNetDevice``
queue and wakes the associated ns-3 qdisc. The NetmapNetDevice also supports
queue and wakes the associated |ns3| qdisc. The NetmapNetDevice also supports
BQL: the write method notifies the BQL library of the amount of bytes that
have been written to the netmap transmission ring, while the sync thread
notifies the BQL library of the amount of bytes that have been removed from
@@ -110,10 +110,10 @@ Usage
The installation of netmap itself on a host machine is out of scope for
this document. Refer to the `netmap GitHub README <https://github.com/luigirizzo/netmap>`_ for instructions.
The ns-3 netmap code has only been tested on Linux; it is not clear whether
The |ns3| netmap code has only been tested on Linux; it is not clear whether
other operating systems can be supported.
If ns-3 is able to detect the presence of netmap on the system, it will
If |ns3| is able to detect the presence of netmap on the system, it will
report that:
.. sourcecode:: text
@@ -133,15 +133,21 @@ privileges.
Helpers
=======
ns-3 netmap support uses a ``NetMapNetDeviceHelper`` helper object to
install the NetmapNetDevice. In other respects, the API and use is similar
|ns3| netmap support uses a ``NetMapNetDeviceHelper`` helper object to
install the ``NetmapNetDevice``. In other respects, the API and use is similar
to that of the ``EmuFdNetDeviceHelper``.
Attributes
==========
The ``NetmapNetDevice`` does not have any specialized attributes, but
supports the ``FdNetDevice`` attributes (see the chapter on ``FdNetDevice``).
There is one attribute specialized to ``NetmapNetDevice``, named
``SyncAndNotifyQueuePeriod``. This value takes an integer number of
microseconds, and is used as the period of time after which the device
syncs the netmap ring and notifies queue status. The value should be
close to the interrupt coalescence period of the real device. Users
may want to tune this parameter for their own system; it should be
a compromise between CPU usage and accuracy in the ring sync (if it is
too high, the device goes into starvation and lower throughput occurs).
Output
======

View File

@@ -55,9 +55,9 @@
// | |
// +----------------------------+
//
// This example is aimed at measuring the throughput of the FdNetDevice (NetmapNetDevice)
// when using the EmuFdNetDeviceHelper (NetmapNetDeviceHelper). This is achieved by saturating
// the channel with TCP or UDP traffic. Then the throughput can be obtained from
// This example is aimed at measuring the throughput of the FdNetDevice
// when using the EmuFdNetDeviceHelper. This is achieved by saturating
// the channel with TCP traffic. Then the throughput can be obtained from
// the generated .pcap files.
//
// To run this example you will need two hosts (client & server).

View File

@@ -18,14 +18,15 @@
* Author: Pasquale Imputato <p.imputato@gmail.com>
*/
/*
/*
* This example builds a node with a device in emulation mode in {raw, netmap}.
* The aim is to measure the maximum tx rate in pps achievable with NetmapNetDevice and FdNetDevice on a specific machine.
* The aim is to measure the maximum tx rate in pps achievable with
* NetmapNetDevice and FdNetDevice on a specific machine.
* The emulated device must be connected and in promiscuous mode.
*
* If you run emulation in netmap mode, you need before to load the netmap.ko module.
* The user is in charge to configure and build netmap separately.
*
* If you run emulation in netmap mode, you need before to load the
* netmap.ko module. The user is responsible for configuring and building
* netmap separately.
*/
#include "ns3/abort.h"
@@ -46,25 +47,24 @@ using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("NetmapEmulationSendExample");
// this function sends a number packets by means the SendFrom method or
// the Write method (depending from the level value) of a FdNetDevice or of a NetmapNetDevice
// (depending from the emulation mode value).
// This function sends a number of packets by means of the SendFrom method or
// the Write method (depending on the level value) of a FdNetDevice or
// of a NetmapNetDevice (depending on the emulation mode value).
static void
Send (Ptr<NetDevice> dev, int level, std::string emuMode)
{
Ptr<FdNetDevice> device = DynamicCast<FdNetDevice> (dev);
int packets = 10000000;
Mac48Address sender = Mac48Address("00:00:00:aa:00:01");
Mac48Address receiver = Mac48Address("ff:ff:ff:ff:ff:ff");
Mac48Address sender = Mac48Address ("00:00:00:aa:00:01");
Mac48Address receiver = Mac48Address ("ff:ff:ff:ff:ff:ff");
int packetsSize = 64;
Ptr<Packet> packet = Create<Packet> (packetsSize);
EthernetHeader header;
ssize_t len = (size_t) packet->GetSize ();
uint8_t *buffer = (uint8_t*)malloc (len);
packet->CopyData (buffer, len);
@@ -79,13 +79,12 @@ Send (Ptr<NetDevice> dev, int level, std::string emuMode)
ndq = ndqi->GetTxQueue (0);
}
std::cout << ((level == 0) ? "Writing" : "Sending") << std::endl;
// period to print the stats
std::chrono::milliseconds period (1000);
auto t1 = std::chrono::high_resolution_clock::now();
auto t1 = std::chrono::high_resolution_clock::now ();
while (packets > 0)
{
@@ -118,38 +117,27 @@ Send (Ptr<NetDevice> dev, int level, std::string emuMode)
sent++;
}
auto t2 = std::chrono::high_resolution_clock::now();
auto t2 = std::chrono::high_resolution_clock::now ();
if (t2 - t1 >= period)
{
// print stats
std::chrono::duration<double, std::milli> dur = (t2 - t1); // in ms
double estimatedThr = ((sent - failed) * packetsSize * 8) / 1000000; // in Mbps
std::cout << sent << " packets sent in "<< dur.count () << " ms, failed " << failed <<" (" << estimatedThr << " Mbps estimanted throughput)" << std::endl ;
std::cout << sent << " packets sent in " << dur.count () << " ms, failed " << failed << " (" << estimatedThr << " Mbps estimated throughput)" << std::endl;
sent = 0;
failed = 0;
t1 = std::chrono::high_resolution_clock::now();
t1 = std::chrono::high_resolution_clock::now ();
}
packets--;
}
}
int
main (int argc, char *argv[])
{
NS_LOG_INFO ("Emu Send Example");
std::string deviceName ("eno1");
int level = 0;
std::string localAddress ("1.2.3.4");
std::string localGateway ("1.2.3.4");
#ifdef HAVE_PACKET_H
std::string emuMode ("raw");
@@ -160,18 +148,10 @@ main (int argc, char *argv[])
CommandLine cmd;
cmd.AddValue ("deviceName", "Device name", deviceName);
cmd.AddValue ("level", "Enable send (1) or write (0) level test", level);
cmd.AddValue ("localIp", "Local IP address (dotted decimal only please)", localAddress);
cmd.AddValue ("gateway", "Gateway address (dotted decimal only please)", localGateway);
cmd.AddValue ("emuMode", "Emulation mode in {raw, netmap}", emuMode);
cmd.Parse (argc, argv);
Ipv4Address localIp (localAddress.c_str ());
NS_ABORT_MSG_IF (localIp == "1.2.3.4", "You must change the local IP address before running this example");
Ipv4Mask localMask (localGateway.c_str ());
NS_ABORT_MSG_IF (localMask == "1.2.3.4", "You must change the local mask before running this example");
GlobalValue::Bind ("SimulatorImplementationType", StringValue ("ns3::RealtimeSimulatorImpl"));
GlobalValue::Bind ("ChecksumEnabled", BooleanValue (true));
@@ -209,16 +189,6 @@ main (int argc, char *argv[])
Ptr<NetDevice> device = devices.Get (0);
device->SetAttribute ("Address", Mac48AddressValue (Mac48Address::Allocate ()));
// NS_LOG_INFO ("Add Internet Stack");
// InternetStackHelper internetStackHelper;
// internetStackHelper.Install (node);
// TrafficControlHelper tch;
// tch.SetRootQueueDisc ("ns3::PfifoFastQueueDisc");
// tch.Install (devices);
Simulator::Schedule (Seconds (3), &Send, device, level, emuMode);
NS_LOG_INFO ("Run Emulation.");

View File

@@ -31,12 +31,13 @@
* 1 Gbps access incoming link | | 100 Mbps bottleneck outgoing link
* ----------------------------------- -----------------------------------
*
* This example builds a node with two interfaces in emulation mode in {raw, netmap}.
* The aim is to explore different qdiscs behaviours on the backlog of a device emulated bottleneck side.
*
* If you run emulation in netmap mode, you need before to load the netmap.ko module.
* The user is in charge to configure and build netmap separately.
*
* This example builds a node with two interfaces in emulation mode in
* either {raw, netmap}. The aim is to explore different qdiscs behaviours
* on the backlog of a device emulated bottleneck side.
*
* If you run emulation in netmap mode, you need before to load the
* netmap.ko module. The user is responsible for configuring and building
* netmap separately.
*/
#include "ns3/abort.h"
@@ -56,8 +57,8 @@ void
TcPacketsInQueue (Ptr<QueueDisc> q, Ptr<OutputStreamWrapper> stream)
{
Simulator::Schedule (Seconds (0.001), &TcPacketsInQueue, q, stream);
*stream->GetStream () << Simulator::Now ().GetSeconds () << " backlog " << q->GetNPackets () << "p " << q->GetNBytes () << "b "<< " dropped "
<< q->GetStats ().nTotalDroppedPackets << "p " << q->GetStats ().nTotalDroppedBytes << "b " << std::endl;
*stream->GetStream () << Simulator::Now ().GetSeconds () << " backlog " << q->GetNPackets () << "p " << q->GetNBytes () << "b " << " dropped "
<< q->GetStats ().nTotalDroppedPackets << "p " << q->GetStats ().nTotalDroppedBytes << "b " << std::endl;
}
#ifdef HAVE_NETMAP_USER_H
@@ -65,7 +66,7 @@ void
Inflight (Ptr<NetmapNetDevice> dev, Ptr<OutputStreamWrapper> stream)
{
Simulator::Schedule (Seconds (0.001), &Inflight, dev, stream);
*stream->GetStream () << dev->GetBytesInNetmapTxRing () << std::endl;
*stream->GetStream () << dev->GetBytesInNetmapTxRing () << std::endl;
}
#endif

View File

@@ -66,8 +66,8 @@ NS_LOG_COMPONENT_DEFINE ("EmuFdNetDeviceHelper");
EmuFdNetDeviceHelper::EmuFdNetDeviceHelper ()
{
m_deviceName = "undefined";
m_dpdkMode = false;
m_hostQdiscBypass = false;
m_dpdkMode = false;
}
void
@@ -76,6 +76,11 @@ EmuFdNetDeviceHelper::SetDeviceName (std::string deviceName)
m_deviceName = deviceName;
}
void
EmuFdNetDeviceHelper::HostQdiscBypass (bool hostQdiscBypass)
{
m_hostQdiscBypass = hostQdiscBypass;
}
void
EmuFdNetDeviceHelper::SetDpdkMode (int argc, char **argv)
{
@@ -93,12 +98,6 @@ EmuFdNetDeviceHelper::SetDpdkMode (int argc, char **argv)
#endif
}
void
EmuFdNetDeviceHelper::HostQdiscBypass (bool hostQdiscBypass)
{
m_hostQdiscBypass = hostQdiscBypass;
}
std::string
EmuFdNetDeviceHelper::GetDeviceName (void)
{

View File

@@ -69,20 +69,15 @@ public:
void HostQdiscBypass (bool hostQdiscBypass);
/**
* Set the device in Dpdk mode.
* Set the device in DPDK mode.
*
* \param argc Dpdk EAL args count.
* \param argv Dpdk EAL args list.
*/
void SetDpdkMode (int argc, char **argv);
/**
* \brief Request host qdisc bypass
* \param hostQdiscBypass to enable host qdisc bypass
*/
void HostQdiscBypass (bool hostQdiscBypass);
protected:
/**
* This method creates an ns3::FdNetDevice attached to a physical network
* interface
@@ -105,26 +100,25 @@ protected:
virtual int CreateFileDescriptor (void) const;
/**
* The unix/linux name of the underlying device (e.g., eth0)
* The Unix/Linux name of the underlying device (e.g., eth0)
*/
std::string m_deviceName;
bool m_hostQdiscBypass;
/**
* The dpdk mode of the device.
* The DPDK mode of the device.
*/
bool m_dpdkMode;
/**
* Dpdk EAL arguements count.
* DPDK EAL arguments count.
*/
int m_ealArgc;
/**
* Dpdk EAL arguements list.
* DPDK EAL arguments list.
*/
char **m_ealArgv;
bool m_hostQdiscBypass;
};
} // namespace ns3

View File

@@ -55,12 +55,6 @@ FdNetDeviceHelper::SetAttribute (std::string n1, const AttributeValue &v1)
m_deviceFactory.Set (n1, v1);
}
void
FdNetDeviceHelper::SetTypeId (std::string type)
{
m_deviceFactory.SetTypeId (type);
}
void
FdNetDeviceHelper::EnablePcapInternal (std::string prefix, Ptr<NetDevice> nd, bool promiscuous, bool explicitFilename)
{

View File

@@ -51,12 +51,12 @@ main (int argc, char *argv[])
{
switch (c)
{
case 'v':
gVerbose = true;
break;
case 'p':
path = optarg;
break;
case 'v':
gVerbose = true;
break;
case 'p':
path = optarg;
break;
}
}

View File

@@ -87,7 +87,7 @@ NetmapNetDeviceHelper::InstallPriv (Ptr<Node> node) const
{
Ptr<NetDevice> d = FdNetDeviceHelper::InstallPriv (node);
Ptr<FdNetDevice> device = d->GetObject<FdNetDevice> ();
SetDeviceAttributes (device);
int fd = CreateFileDescriptor ();
@@ -96,8 +96,8 @@ NetmapNetDeviceHelper::InstallPriv (Ptr<Node> node) const
// Aggregate NetDeviceQueueInterface object
Ptr<NetDeviceQueueInterface> ndqi = CreateObjectWithAttributes<NetDeviceQueueInterface> (
"TxQueuesType", TypeIdValue (NetDeviceQueueLock::GetTypeId ()),
"NTxQueues", UintegerValue (1));
"TxQueuesType", TypeIdValue (NetDeviceQueueLock::GetTypeId ()),
"NTxQueues", UintegerValue (1));
device->AggregateObject (ndqi);
netmapDevice->SetNetDeviceQueue (ndqi->GetTxQueue (0));
@@ -156,7 +156,7 @@ NetmapNetDeviceHelper::SetDeviceAttributes (Ptr<FdNetDevice> device) const
NS_FATAL_ERROR ("NetmapNetDeviceHelper::SetFileDescriptor (): "
<< m_deviceName.c_str ()
<< " is not in promiscuous mode. Please config the interface in promiscuous "
"mode before to run the simulation.");
"mode before to run the simulation.");
}
if ((ifr.ifr_flags & IFF_BROADCAST) != IFF_BROADCAST)

View File

@@ -47,8 +47,7 @@ public:
NetmapNetDeviceHelper ();
virtual ~NetmapNetDeviceHelper ()
{
}
{}
/**
* \brief Get the device name of this device.

View File

@@ -473,4 +473,18 @@ DpdkNetDevice::Write (uint8_t *buffer, size_t length)
return length;
}
void
DpdkNetDevice::DoFinishStoppingDevice (void)
{
CriticalSection cs (m_pendingReadMutex);
while (!m_pendingQueue.empty ())
{
std::pair<uint8_t *, ssize_t> next = m_pendingQueue.front ();
m_pendingQueue.pop ();
FreeBuffer (next.first);
}
}
} // namespace ns3

View File

@@ -52,23 +52,23 @@ public:
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId(void);
static TypeId GetTypeId (void);
/**
* Constructor for the DpdkNetDevice.
*/
DpdkNetDevice();
DpdkNetDevice ();
/**
* Destructor for the DpdkNetDevice.
*/
~DpdkNetDevice();
~DpdkNetDevice ();
/**
* Check the link status of all ports in up to 9s
* and print them finally
*/
void CheckAllPortsLinkStatus(void);
void CheckAllPortsLinkStatus (void);
/**
* Initialize Dpdk.
@@ -77,42 +77,42 @@ public:
* \param argc Dpdk EAL args count.
* \param argv Dpdk EAL args list.
*/
void InitDpdk(int argc, char **argv);
void InitDpdk (int argc, char **argv);
/**
* Set device name.
*
* \param deviceName The device name.
*/
void SetDeviceName(std::string deviceName);
void SetDeviceName (std::string deviceName);
/**
* A signal handler for SIGINT and SIGTERM signals.
*
* \param signum The signal number.
*/
static void SignalHandler(int signum);
static void SignalHandler (int signum);
/**
* A function to handle rx & tx operations.
*/
static int LaunchCore(void *arg);
static int LaunchCore (void *arg);
/**
* Transmit packets in burst from the tx_buffer to the nic.
*/
void HandleTx();
void HandleTx ();
/**
* Receive packets in burst from the nic to the rx_buffer.
*/
void HandleRx();
void HandleRx ();
/**
* Check the status of the link.
* \return Status of the link - up/down as true/false.
*/
bool IsLinkUp(void) const;
bool IsLinkUp (void) const;
/**
* Free the given packet buffer.
@@ -122,7 +122,7 @@ public:
/**
* Allocate packet buffer.
*/
virtual uint8_t* AllocateBuffer(size_t len);
virtual uint8_t* AllocateBuffer (size_t len);
protected:
/**
@@ -131,7 +131,7 @@ protected:
* \param length The data length.
* \return The size of data written.
*/
ssize_t Write(uint8_t *buffer, size_t length);
ssize_t Write (uint8_t *buffer, size_t length);
/**
* The port number of the device to be used.
@@ -144,6 +144,7 @@ protected:
std::string m_deviceName;
private:
void DoFinishStoppingDevice (void);
/**
* Condition variable for Dpdk to stop
*/
@@ -202,4 +203,4 @@ private:
} //
#endif /* DPDK_NET_DEVICE_H */
#endif /* DPDK_NET_DEVICE_H */

View File

@@ -618,8 +618,8 @@ FdNetDevice::SendFrom (Ptr<Packet> packet, const Address& src, const Address& de
AddPIHeader (buffer, len);
}
ssize_t written = Write (buffer, len);
free (buffer);
ssize_t written = Write(buffer, len);
FreeBuffer (buffer);
if (written == -1 || (size_t) written != len)
{
@@ -635,7 +635,8 @@ FdNetDevice::Write (uint8_t *buffer, size_t length)
{
NS_LOG_FUNCTION (this << buffer << length);
return write (m_fd, buffer, length);
uint32_t ret = write (m_fd, buffer, length);
return ret;
}
void

View File

@@ -198,6 +198,12 @@ public:
protected:
virtual void DoDispose (void);
/**
* Get the associated file descriptor.
* \return the associated file descriptor
*/
int GetFileDescriptor (void) const;
/**
* Allocate packet buffer.
*/
@@ -212,11 +218,6 @@ protected:
* Callback to invoke when a new frame is received
*/
void ReceiveCallback (uint8_t *buf, ssize_t len);
/**
* Get the associated file descriptor.
* \return the associated file descriptor
*/
int GetFileDescriptor (void) const;
/**
* Mutex to increase pending read counter.

View File

@@ -20,6 +20,7 @@
#include "netmap-net-device.h"
#include "ns3/system-thread.h"
#include "ns3/uinteger.h"
#include <sys/ioctl.h>
#include <unistd.h>
@@ -31,19 +32,17 @@ TypeId
NetDeviceQueueLock::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::NetDeviceQueueLock")
.SetParent<NetDeviceQueue> ()
.SetGroupName ("Network")
.AddConstructor<NetDeviceQueueLock> ();
.SetParent<NetDeviceQueue> ()
.SetGroupName ("Network")
.AddConstructor<NetDeviceQueueLock> ();
return tid;
}
NetDeviceQueueLock::NetDeviceQueueLock ()
{
}
{}
NetDeviceQueueLock::~NetDeviceQueueLock ()
{
}
{}
bool
NetDeviceQueueLock::IsStopped (void) const
@@ -95,10 +94,10 @@ NetDeviceQueueLock::NotifyTransmittedBytes (uint32_t bytes)
}
NetmapNetDeviceFdReader::NetmapNetDeviceFdReader ()
: m_bufferSize (65536), // Defaults to maximum TCP window size
m_nifp (nullptr)
{
}
: m_bufferSize (65536),
// Defaults to maximum TCP window size
m_nifp (nullptr)
{}
void
NetmapNetDeviceFdReader::SetBufferSize (uint32_t bufferSize)
@@ -171,9 +170,14 @@ TypeId
NetmapNetDevice::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::NetmapNetDevice")
.SetParent<FdNetDevice> ()
.SetGroupName ("FdNetDevice")
.AddConstructor<NetmapNetDevice> ();
.SetParent<FdNetDevice> ()
.SetGroupName ("FdNetDevice")
.AddConstructor<NetmapNetDevice> ()
.AddAttribute ("SyncAndNotifyQueuePeriod",
"The period of time (in number of us) after which the device syncs the netmap ring and notifies queue status.",
UintegerValue (50),
MakeUintegerAccessor (&NetmapNetDevice::m_syncAndNotifyQueuePeriod),
MakeUintegerChecker<uint8_t> ());
return tid;
}
@@ -337,9 +341,7 @@ NetmapNetDevice::SyncAndNotifyQueue ()
}
}
// we use a period to sync, check and notify of 200 us; it is a value close to the interrupt coalescence
// period of a real device
usleep (200);
usleep (m_syncAndNotifyQueuePeriod);
NS_LOG_DEBUG ("Space in the netmap ring of " << nm_ring_space (txring) << " packets");
}

View File

@@ -99,7 +99,7 @@ private:
/**
* \ingroup fd-net-device
*
*
* \brief This class performs the actual data reading from the netmap ring.
*/
class NetmapNetDeviceFdReader : public FdReader
@@ -212,6 +212,7 @@ private:
uint32_t m_totalQueuedBytes; //!< Total queued bytes
Ptr<SystemThread> m_syncAndNotifyQueueThread; //!< Thread used to perform the flow control
std::atomic<bool> m_syncAndNotifyQueueThreadRun; //!< Running flag of the flow control thread
uint8_t m_syncAndNotifyQueuePeriod; //!< The period of time in us after which the device syncs the netmap ring and notifies queue status
};
} // namespace ns3