PcapPlusPlus
pcpp::DpdkDevice Class Reference

#include <DpdkDevice.h>

Inheritance diagram for pcpp::DpdkDevice:
pcpp::IPcapDevice

Classes

struct  DpdkDeviceConfiguration
 
struct  LinkStatus
 

Public Member Functions

int getDeviceId ()
 
std::string getDeviceName ()
 
MacAddress getMacAddress ()
 
std::string getPMDName ()
 
DpdkPMDType getPMDType ()
 
PciAddress getPciAddress ()
 
uint16_t getMtu ()
 
bool setMtu (uint16_t newMtu)
 
bool isVirtual ()
 
void getLinkStatus (LinkStatus &linkStatus)
 
uint32_t getCurrentCoreId ()
 
uint16_t getNumOfOpenedRxQueues ()
 
uint16_t getNumOfOpenedTxQueues ()
 
uint16_t getTotalNumOfRxQueues ()
 
uint16_t getTotalNumOfTxQueues ()
 
bool receivePackets (RawPacketVector &rawPacketsArr, uint16_t rxQueueId)
 
bool receivePackets (MBufRawPacket **rawPacketsArr, int &rawPacketArrLength, uint16_t rxQueueId)
 
bool receivePackets (Packet **packetsArr, int &packetsArrLength, uint16_t rxQueueId)
 
int sendPackets (const RawPacket *rawPacketsArr, int arrLength, uint16_t txQueueId=0)
 
int sendPackets (const Packet **packetsArr, int arrLength, uint16_t txQueueId=0)
 
int sendPackets (const RawPacketVector &rawPacketsVec, uint16_t txQueueId=0)
 
bool sendPacket (const uint8_t *packetData, int packetDataLength, uint16_t txQueueId=0)
 
bool sendPacket (const RawPacket &rawPacket, uint16_t txQueueId=0)
 
bool sendPacket (const Packet &packet, uint16_t txQueueId=0)
 
bool setFilter (GeneralFilter &filter)
 
bool setFilter (std::string filterAsString)
 
bool openMultiQueues (uint16_t numOfRxQueuesToOpen, uint16_t numOfTxQueuesToOpen, const DpdkDeviceConfiguration &config=DpdkDeviceConfiguration())
 
bool startCaptureSingleThread (OnDpdkPacketsArriveCallback onPacketsArrive, void *onPacketsArriveUserCookie)
 
bool startCaptureMultiThreads (OnDpdkPacketsArriveCallback onPacketsArrive, void *onPacketsArriveUserCookie, CoreMask coreMask)
 
void stopCapture ()
 
int getAmountOfFreeMbufs ()
 
int getAmountOfMbufsInUse ()
 
bool open ()
 
void close ()
 
void getStatistics (pcap_stat &stats)
 
- Public Member Functions inherited from pcpp::IPcapDevice
bool isOpened ()
 
bool setFilter (GeneralFilter &filter)
 
void clearFilter ()
 

Additional Inherited Members

- Static Public Member Functions inherited from pcpp::IPcapDevice
static bool verifyFilter (std::string filterAsString)
 
static bool matchPakcetWithFilter (std::string filterAsString, RawPacket *rawPacket)
 

Detailed Description

Encapsulates a DPDK port and enables receiving and sending packets using DPDK as well as getting interface info & status, packet statistics, etc. This class has no public c'tor as it's constructed by DpdkDeviceList during initialization.

RX/TX queues: modern NICs provide hardware load-balancing for packets. This means that each packet received by the NIC is hashed by one or more parameter (IP address, port, etc.) and goes into one of several RX queues provided by the NIC. This enables applications to work in a multi-core environment where each core can read packets from different RX queue(s). Same goes for TX queues: it's possible to write packets to different TX queues and the NIC is taking care of sending them to the network. Different NICs provide different number of RX and TX queues. DPDK supports this capability and enables the user to open the DPDK port (DpdkDevice) with a single or multiple RX and TX queues. When receiving packets the user can decide from which RX queue to read from, and when transmitting packets the user can decide to which TX queue to send them to. RX/TX queues are configured when opening the DpdkDevice (see openMultiQueues())

Capturing packets: there are two ways to capture packets using DpdkDevice:

Sending packets: DpdkDevice has various methods for sending packets. They enable sending raw packets, parsed packets, etc. for all opened TX queues. See DpdkDevice::sendPackets()

Get interface info: DpdkDevice provides all kind of information on the interface/device such as MAC address, MTU, link status, PCI address, PMD (poll-mode-driver) used for this port, etc. In addition it provides RX/TX statistics when receiving or sending packets

Known limitations:

  • BPF filters are currently not supported by this device (as opposed to other PcapPlusPlus device types. This means that the device cannot filter packets before they get to the user
  • It's not possible to set or change NIC load-balancing method. DPDK provides this capability but it's still not supported by DpdkDevice

Member Function Documentation

void pcpp::DpdkDevice::close ( )
virtual

Close the DpdkDevice. When device is closed it's not possible work with it

Implements pcpp::IPcapDevice.

int pcpp::DpdkDevice::getAmountOfFreeMbufs ( )
Returns
The number of free mbufs in device's mbufs pool
int pcpp::DpdkDevice::getAmountOfMbufsInUse ( )
Returns
The number of mbufs currently in use in device's mbufs pool
uint32_t pcpp::DpdkDevice::getCurrentCoreId ( )
Returns
The core ID used in this context
int pcpp::DpdkDevice::getDeviceId ( )
inline
Returns
The device ID (DPDK port ID)
std::string pcpp::DpdkDevice::getDeviceName ( )
inline
Returns
The device name which is in the format of 'DPDK_[PORT-ID]'
void pcpp::DpdkDevice::getLinkStatus ( LinkStatus linkStatus)

Get the link status (link up/down, link speed and link duplex)

Parameters
[out]linkStatusA reference to object the result shall be written to
MacAddress pcpp::DpdkDevice::getMacAddress ( )
inline
Returns
The MAC address of the device (DPDK port)
uint16_t pcpp::DpdkDevice::getMtu ( )
inline
Returns
The device's maximum transmission unit (MTU) in bytes
uint16_t pcpp::DpdkDevice::getNumOfOpenedRxQueues ( )
inline
Returns
The number of RX queues currently opened for this device (as configured in openMultiQueues() )
uint16_t pcpp::DpdkDevice::getNumOfOpenedTxQueues ( )
inline
Returns
The number of TX queues currently opened for this device (as configured in openMultiQueues() )
PciAddress pcpp::DpdkDevice::getPciAddress ( )
inline
Returns
The PCI address of the device
std::string pcpp::DpdkDevice::getPMDName ( )
inline
Returns
The name of the PMD (poll mode driver) DPDK is using for this device. You can read about PMDs in the DPDK documentation: http://dpdk.org/doc/guides/prog_guide/poll_mode_drv.html
DpdkPMDType pcpp::DpdkDevice::getPMDType ( )
inline
Returns
The enum type of the PMD (poll mode driver) DPDK is using for this device. You can read about PMDs in the DPDK documentation: http://dpdk.org/doc/guides/prog_guide/poll_mode_drv.html
void pcpp::DpdkDevice::getStatistics ( pcap_stat &  stats)
virtual

Retrieve RX packet statistics from device

Todo:
pcap_stat is a poor struct that doesn't contain all the information DPDK can provide. Consider using a more extensive struct

Implements pcpp::IPcapDevice.

uint16_t pcpp::DpdkDevice::getTotalNumOfRxQueues ( )
inline
Returns
The total number of RX queues available on this device
uint16_t pcpp::DpdkDevice::getTotalNumOfTxQueues ( )
inline
Returns
The total number of TX queues available on this device
bool pcpp::DpdkDevice::isVirtual ( )
Returns
True if this device is a virtual interface (such as VMXNET3, 1G/10G virtual function, etc.), false otherwise
bool pcpp::DpdkDevice::open ( )
inlinevirtual

Overridden method from IPcapDevice. It calls openMultiQueues() with 1 RX queue and 1 TX queue. Notice opening the device only makes it ready to use, it doesn't start packet capturing. The device is opened in promiscuous mode

Returns
True if the device was opened successfully, false if device is already opened, if RX/TX queues configuration failed or of DPDK port configuration and startup failed

Implements pcpp::IPcapDevice.

bool pcpp::DpdkDevice::openMultiQueues ( uint16_t  numOfRxQueuesToOpen,
uint16_t  numOfTxQueuesToOpen,
const DpdkDeviceConfiguration config = DpdkDeviceConfiguration() 
)

Open the DPDK device. Notice opening the device only makes it ready to use, it doesn't start packet capturing. This method initializes RX and TX queues, configures the DPDK port and starts it. Call close() to close the device. The device is opened in promiscuous mode

Parameters
[in]numOfRxQueuesToOpenNumber of RX queues to setup. This number must be smaller or equal to the return value of getTotalNumOfRxQueues()
[in]numOfTxQueuesToOpenNumber of TX queues to setup. This number must be smaller or equal to the return value of getTotalNumOfTxQueues()
[in]configOptional parameter for defining special port configuration parameters such as number of receive/transmit descriptors. If not set the default parameters will be set (see DpdkDeviceConfiguration)
Returns
True if the device was opened successfully, false if device is already opened, if RX/TX queues configuration failed or of DPDK port configuration and startup failed
bool pcpp::DpdkDevice::receivePackets ( RawPacketVector rawPacketsArr,
uint16_t  rxQueueId 
)

Receive raw packets from the network

Parameters
[out]rawPacketsArrA vector where all received packets will be written into
[in]rxQueueIdThe RX queue to receive packets from
Returns
True if packets were received and no error occurred or false if device isn't opened, if device is currently capturing (using startCaptureSingleThread() or startCaptureMultiThreads() ), if rxQueueId doesn't exist on device, or if DPDK receive packets method returned an error
bool pcpp::DpdkDevice::receivePackets ( MBufRawPacket **  rawPacketsArr,
int &  rawPacketArrLength,
uint16_t  rxQueueId 
)

Receive raw packets from the network

Parameters
[out]rawPacketsArrA pointer to a non-allocated array of MBufRawPacket pointers where all received packets will be written into. The array will be allocated by this method and its length will be written into rawPacketArrLength. Notice it's the user responsibility to free the array and its content when done using it
[out]rawPacketArrLengthThe length of MBufRawPacket pointers array will be written into
[in]rxQueueIdThe RX queue to receive packets from
Returns
True if packets were received and no error occurred or false if device isn't opened, if device is currently in capture mode (using startCaptureSingleThread() or startCaptureMultiThreads() ), if rxQueueId doesn't exist on device, or if DPDK receive packets method returned an error
bool pcpp::DpdkDevice::receivePackets ( Packet **  packetsArr,
int &  packetsArrLength,
uint16_t  rxQueueId 
)

Receive parsed packets from the network

Parameters
[out]packetsArrA pointer to a non-allocated array of Packet pointers where all received packets will be written into. The array will be allocated by this method and its length will be written into packetsArrLength. Notice it's the user responsibility to free the array and its content when done using it
[out]packetsArrLengthThe length of Packet pointers array will be written into
[in]rxQueueIdThe RX queue to receive packets from
Returns
True if packets were received and no error occurred or false if device isn't opened, if device is currently capturing (using startCaptureSingleThread() or startCaptureMultiThreads() ), if rxQueueId doesn't exist on device, or if DPDK receive packets method returned an error
bool pcpp::DpdkDevice::sendPacket ( const uint8_t *  packetData,
int  packetDataLength,
uint16_t  txQueueId = 0 
)

Send packet raw data to the network. For the send packets algorithm see sendPackets(), but keep in mind this method sends only 1 packet

Parameters
[in]packetDataThe packet raw data to send
[in]packetDataLengthThe length of the raw data
[in]txQueueIdAn optional parameter which indicates to which TX queue the packet will be sent to. The default is TX queue 0
Returns
True if packet was sent successfully or false if device is not opened, TX queue isn't opened or the sending algorithm failed (for example: couldn't allocate an mbuf or DPDK returned an error)
bool pcpp::DpdkDevice::sendPacket ( const RawPacket rawPacket,
uint16_t  txQueueId = 0 
)

Send a raw packet to the network. For the send packets algorithm see sendPackets(), but keep in mind this method sends only 1 packet

Parameters
[in]rawPacketThe raw packet to send
[in]txQueueIdAn optional parameter which indicates to which TX queue the packet will be sent to. The default is TX queue 0
Returns
True if packet was sent successfully or false if device is not opened, TX queue isn't opened or the sending algorithm failed (for example: couldn't allocate an mbuf or DPDK returned an error)
bool pcpp::DpdkDevice::sendPacket ( const Packet packet,
uint16_t  txQueueId = 0 
)

Send a parsed packet to the network. For the send packets algorithm see sendPackets(), but keep in mind this method sends only 1 packet

Parameters
[in]packetThe parsed packet to send
[in]txQueueIdAn optional parameter which indicates to which TX queue the packet will be sent on. The default is TX queue 0
Returns
True if packet was sent successfully or false if device is not opened, TX queue isn't opened or the sending algorithm failed (for example: couldn't allocate an mbuf or DPDK returned an error)
int pcpp::DpdkDevice::sendPackets ( const RawPacket rawPacketsArr,
int  arrLength,
uint16_t  txQueueId = 0 
)

Send an array of raw packets to the network.

The sending algorithm works as follows: the algorithm tries to allocate a group of mbufs from the device mbuf pool. For each mbuf allocated a raw packet data is copied to the mbuf. This means that the packets sent as input to this method aren't affected (aren't freed, changed, or anything like that). The algorithm will continue allocating mbufs until: no more raw packets to send; OR cannot allocate mbufs because mbug pool is empty; OR number of allocated mbufs is higher than a threshold of 80% of total TX descriptors. When one of these happen the algorithm will try to send the mbufs it already got through DPDK API. DPDK will free these mbufs after sending them. Then the algorithm will try to allocate mbufs again and send them again until no more raw packets are left to send to send or mbuf allocation failed 3 times in a raw. Raw packets that are bigger than the size of an mbuf or with length 0 will be skipped. Same goes for raw packets whose data could not be copied to the allocated mbuf for some reason. An appropriate error will be printed for each such packet

Parameters
[in]rawPacketsArrA pointer to an array of raw packets
[in]arrLengthThe length of the array
[in]txQueueIdAn optional parameter which indicates to which TX queue the packets will be sent to. The default is TX queue 0
Returns
The number of packets successfully sent. If device is not opened or TX queue isn't open, 0 will be returned
int pcpp::DpdkDevice::sendPackets ( const Packet **  packetsArr,
int  arrLength,
uint16_t  txQueueId = 0 
)

Send an array of parsed packets to the network. For the send packets algorithm see sendPackets()

Parameters
[in]packetsArrA pointer to an array of parsed packet pointers
[in]arrLengthThe length of the array
[in]txQueueIdAn optional parameter which indicates to which TX queue the packets will be sent to. The default is TX queue 0
Returns
The number of packets successfully sent. If device is not opened or TX queue isn't open, 0 will be returned
int pcpp::DpdkDevice::sendPackets ( const RawPacketVector rawPacketsVec,
uint16_t  txQueueId = 0 
)

Send a vector of raw packets to the network. For the send packets algorithm see sendPackets()

Parameters
[in]rawPacketsVecThe vector of raw packet
[in]txQueueIdAn optional parameter which indicates to which TX queue the packets will be sent to. The default is TX queue 0
Returns
The number of packets successfully sent. If device is not opened or TX queue isn't open, 0 will be returned
bool pcpp::DpdkDevice::setFilter ( GeneralFilter filter)

Overridden method from IPcapDevice. BPF filters are currently not implemented for DpdkDevice

Returns
Always false with a "Filters aren't supported in DPDK device" error message
bool pcpp::DpdkDevice::setFilter ( std::string  filterAsString)
virtual

Overridden method from IPcapDevice. BPF filters are currently not implemented for DpdkDevice

Returns
Always false with a "Filters aren't supported in DPDK device" error message

Reimplemented from pcpp::IPcapDevice.

bool pcpp::DpdkDevice::setMtu ( uint16_t  newMtu)

Set a new maximum transmission unit (MTU) for this device

Parameters
[in]newMtuThe new MTU in bytes
Returns
True if MTU was set successfully, false if operation failed or if PMD doesn't support changing the MTU
bool pcpp::DpdkDevice::startCaptureMultiThreads ( OnDpdkPacketsArriveCallback  onPacketsArrive,
void *  onPacketsArriveUserCookie,
CoreMask  coreMask 
)

This method does exactly what startCaptureSingleThread() does, but with more than one RX queue / capturing thread. It's called with a core mask as a parameter and creates a packet capture thread on every core. Each capturing thread is assigned with a specific RX queue. This method assumes all cores in the core-mask are available and there are enough opened RX queues to match for each thread. If these assumptions are not true an error is returned. After invoking all threads, all of them run in an endless loop and try to capture packets from their designated RX queues. Each time a burst of packets is captured the callback is invoked with the user cookie and the thread ID that captured the packets

Parameters
[in]onPacketsArriveThe user callback which will be invoked each time a burst of packets is captured by the device
[in]onPacketsArriveUserCookieThe user callback is invoked with this cookie as a parameter. It can be used to pass information from the user application to the callback
coreMaskThe core-mask for creating the cpature threads
Returns
True if all capture threads started successfully or false if device is already in capture mode, not all cores in the core-mask are available to DPDK, there are not enough opened RX queues to match all cores in the core-mask, or if thread invocation failed. In all of these cases an appropriate error message will be printed
bool pcpp::DpdkDevice::startCaptureSingleThread ( OnDpdkPacketsArriveCallback  onPacketsArrive,
void *  onPacketsArriveUserCookie 
)

There are two ways to capture packets using DpdkDevice: one of them is using worker threads (see DpdkDeviceList::startDpdkWorkerThreads() ) and the other way is setting a callback which is invoked each time a burst of packets is captured. This method implements the second way. After invoking this method the DpdkDevice enters capture mode and starts capturing packets. This method assumes there is only 1 RX queue opened for this device, otherwise an error is returned. It then allocates a core and creates 1 thread that runs in an endless loop and tries to capture packets using DPDK. Each time a burst of packets is captured the user callback is invoked with the user cookie as a parameter. This loop continues until stopCapture() is called. Notice: since the callback is invoked for every packet burst using this method can be slower than using worker threads. On the other hand, it's a simpler way comparing to worker threads

Parameters
[in]onPacketsArriveThe user callback which will be invoked each time a packet burst is captured by the device
[in]onPacketsArriveUserCookieThe user callback is invoked with this cookie as a parameter. It can be used to pass information from the user application to the callback
Returns
True if capture thread started successfully or false if device is already in capture mode, number of opened RX queues isn't equal to 1, if the method couldn't find an available core to allocate for the capture thread, or if thread invocation failed. In all of these cases an appropriate error message will be printed
void pcpp::DpdkDevice::stopCapture ( )

If device is in capture mode started by invoking startCaptureSingleThread() or startCaptureMultiThreads(), this method will stop all capturing threads and set the device to non-capturing mode