25 #include "ns3/net-device-queue-interface.h"
26 #include "ns3/simulator.h"
27 #include "ns3/uinteger.h"
31 #include <rte_common.h>
32 #include <rte_cycles.h>
34 #include <rte_ethdev.h>
35 #include <rte_malloc.h>
37 #include <rte_mempool.h>
39 #include <sys/ioctl.h>
41 #include <sys/signal.h>
57 TypeId(
"ns3::DpdkNetDevice")
59 .SetGroupName(
"FdNetDevice")
61 .AddAttribute(
"TxTimeout",
62 "The time to wait before transmitting burst from Tx buffer.",
66 .AddAttribute(
"MaxRxBurst",
70 MakeUintegerChecker<uint32_t>())
71 .AddAttribute(
"MaxTxBurst",
75 MakeUintegerChecker<uint32_t>())
76 .AddAttribute(
"MempoolCacheSize",
77 "Size of mempool cache.",
80 MakeUintegerChecker<uint32_t>())
81 .AddAttribute(
"NbRxDesc",
82 "Number of Rx descriptors.",
85 MakeUintegerChecker<uint16_t>())
86 .AddAttribute(
"NbTxDesc",
87 "Number of Tx descriptors.",
90 MakeUintegerChecker<uint16_t>());
106 rte_eal_wait_lcore(1);
124 #define CHECK_INTERVAL 100
125 #define MAX_CHECK_TIME 90
127 uint8_t printFlag = 0;
128 struct rte_eth_link link;
132 uint8_t allPortsUp = 1;
142 memset(&link, 0,
sizeof(link));
147 if (link.link_status)
153 printf(
"Port %d Link Down\n",
m_portId);
158 if (link.link_status == ETH_LINK_DOWN)
187 if (signum == SIGINT || signum == SIGTERM)
189 printf(
"\n\nSignal %d received, preparing to exit...\n", signum);
207 for (uint16_t i = 0; i <
m_rxBuffer->length; i++)
209 struct rte_mbuf* pkt =
nullptr;
217 uint8_t* buf = rte_pktmbuf_mtod(pkt, uint8_t*);
218 size_t length = pkt->data_len;
230 lcoreId = rte_lcore_id();
258 command.append(
"dpdk-devbind.py --force ");
259 command.append(
"--bind=");
260 command.append(dpdkDriver);
263 printf(
"Executing: %s\n", command.c_str());
264 if (system(command.c_str()))
266 rte_exit(EXIT_FAILURE,
"Execution failed - bye\n");
273 int ret = rte_eal_init(argc, argv);
276 rte_exit(EXIT_FAILURE,
"Invalid EAL arguments\n");
283 unsigned nbPorts = rte_eth_dev_count_avail();
286 rte_exit(EXIT_FAILURE,
"No Ethernet ports - bye\n");
292 rte_exit(EXIT_FAILURE,
"Cannot get port id - bye\n");
296 unsigned int nbLcores = 2;
303 m_mempool = rte_pktmbuf_pool_create(
"mbuf_pool",
307 RTE_MBUF_DEFAULT_BUF_SIZE,
312 rte_exit(EXIT_FAILURE,
"Cannot init mbuf pool\n");
316 static struct rte_eth_conf portConf = {};
317 portConf.rxmode = {};
318 portConf.rxmode.split_hdr_size = 0;
319 portConf.txmode = {};
320 portConf.txmode.mq_mode = ETH_MQ_TX_NONE;
322 struct rte_eth_rxconf reqConf;
323 struct rte_eth_txconf txqConf;
324 struct rte_eth_conf localPortConf = portConf;
325 struct rte_eth_dev_info devInfo;
328 rte_eth_dev_info_get(
m_portId, &devInfo);
329 if (devInfo.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
331 localPortConf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE;
333 ret = rte_eth_dev_configure(
m_portId, 1, 1, &localPortConf);
336 rte_exit(EXIT_FAILURE,
"Cannot configure device: err=%d, port=%u\n", ret,
m_portId);
342 rte_exit(EXIT_FAILURE,
343 "Cannot adjust number of descriptors: err=%d, port=%u\n",
350 reqConf = devInfo.default_rxconf;
351 reqConf.offloads = localPortConf.rxmode.offloads;
352 ret = rte_eth_rx_queue_setup(
m_portId,
360 rte_exit(EXIT_FAILURE,
"rte_eth_rx_queue_setup:err=%d, port=%u\n", ret,
m_portId);
365 txqConf = devInfo.default_txconf;
366 txqConf.offloads = localPortConf.txmode.offloads;
371 rte_exit(EXIT_FAILURE,
"rte_eth_tx_queue_setup:err=%d, port=%u\n", ret,
m_portId);
375 m_txBuffer = (rte_eth_dev_tx_buffer*)rte_zmalloc_socket(
"tx_buffer",
380 m_rxBuffer = (rte_eth_dev_tx_buffer*)rte_zmalloc_socket(
"rx_buffer",
386 rte_exit(EXIT_FAILURE,
"Cannot allocate buffer for rx/tx on port %u\n",
m_portId);
396 rte_exit(EXIT_FAILURE,
"rte_eth_dev_start:err=%d, port=%u\n", ret,
m_portId);
399 rte_eth_promiscuous_enable(
m_portId);
404 rte_eal_mp_remote_launch(
LaunchCore,
this, CALL_MASTER);
410 struct rte_mbuf* pkt = rte_pktmbuf_alloc(
m_mempool);
415 uint8_t* buf = rte_pktmbuf_mtod(pkt, uint8_t*);
422 struct rte_mbuf* pkt;
428 pkt = (
struct rte_mbuf*)RTE_PTR_SUB(buf,
sizeof(
struct rte_mbuf) + RTE_PKTMBUF_HEADROOM);
430 rte_pktmbuf_free(pkt);
436 struct rte_mbuf** pkt =
new struct rte_mbuf*[1];
445 pkt[0] = (
struct rte_mbuf*)RTE_PTR_SUB(buffer,
sizeof(
struct rte_mbuf) + RTE_PKTMBUF_HEADROOM);
447 pkt[0]->pkt_len = length;
448 pkt[0]->data_len = length;
a NetDevice to read/write network traffic from/into a Dpdk enabled port.
static int LaunchCore(void *arg)
A function to handle rx & tx operations.
virtual void FreeBuffer(uint8_t *buf)
Free the given packet buffer.
bool IsLinkUp() const
Check the status of the link.
uint32_t m_maxRxPktBurst
Size of Rx burst.
void InitDpdk(int argc, char **argv, std::string dpdkDriver)
Initialize Dpdk.
void SetDeviceName(std::string deviceName)
Set device name.
void HandleTx()
Transmit packets in burst from the tx_buffer to the nic.
static void SignalHandler(int signum)
A signal handler for SIGINT and SIGTERM signals.
~DpdkNetDevice()
Destructor for the DpdkNetDevice.
struct rte_eth_dev_tx_buffer * m_txBuffer
Buffer to handle burst transmission.
struct rte_eth_dev_tx_buffer * m_rxBuffer
Buffer to handle burst reception.
uint32_t m_maxTxPktBurst
Size of Tx burst.
static TypeId GetTypeId()
Get the type ID.
EventId m_txEvent
Event for stale packet transmission.
std::string m_deviceName
The device name;.
void DoFinishStoppingDevice()
Complete additional actions, if any, to tear down the device.
static volatile bool m_forceQuit
Condition variable for Dpdk to stop.
uint16_t m_nbTxDesc
Number of Tx descriptors.
uint16_t m_nbRxDesc
Number of Rx descriptors.
struct rte_mempool * m_mempool
Packet memory pool.
void CheckAllPortsLinkStatus()
Check the link status of all ports in up to 9s and print them finally.
uint16_t m_portId
The port number of the device to be used.
virtual uint8_t * AllocateBuffer(size_t len)
Allocate packet buffer.
DpdkNetDevice()
Constructor for the DpdkNetDevice.
void HandleRx()
Receive packets in burst from the nic to the rx_buffer.
Time m_txTimeout
The time to wait before transmitting burst from Tx buffer.
ssize_t Write(uint8_t *buffer, size_t length)
Write packet data to device.
uint32_t m_mempoolCacheSize
Mempool cache size.
a NetDevice to read/write network traffic from/into a file descriptor.
std::mutex m_pendingReadMutex
Mutex to increase pending read counter.
std::queue< std::pair< uint8_t *, ssize_t > > m_pendingQueue
Number of packets that were received and scheduled for read but not yet read.
Callback< bool, Ptr< NetDevice >, Ptr< const Packet >, uint16_t, const Address & > ReceiveCallback
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static void Cancel(const EventId &id)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
AttributeValue implementation for Time.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Hold an unsigned integer type.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#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.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.