#ifdef USE_PF_RING
#define LOG_MODULE PcapLogModulePfRingDevice
#include "PfRingDevice.h"
#include "EthLayer.h"
#include "VlanLayer.h"
#include "Logger.h"
#include <errno.h>
#include <pfring.h>
#include <pthread.h>
#include <chrono>
#define DEFAULT_PF_RING_SNAPLEN 1600
namespace pcpp
{
PfRingDevice::PfRingDevice(const char* deviceName) : m_MacAddress(MacAddress::Zero)
{
m_NumOfOpenedRxChannels = 0;
m_DeviceOpened = false;
m_DeviceName = std::string(deviceName);
m_InterfaceIndex = -1;
m_StopThread = true;
m_OnPacketsArriveCallback = NULL;
m_OnPacketsArriveUserCookie = NULL;
m_ReentrantMode = false;
m_HwClockEnabled = false;
m_DeviceMTU = 0;
m_IsFilterCurrentlySet = false;
m_PfRingDescriptors = new pfring*[MAX_NUM_RX_CHANNELS];
}
PfRingDevice::~PfRingDevice()
{
close();
delete [] m_PfRingDescriptors;
}
bool PfRingDevice::open()
{
if (m_DeviceOpened)
{
PCPP_LOG_ERROR("Device already opened");
return false;
}
m_NumOfOpenedRxChannels = 0;
PCPP_LOG_DEBUG("Trying to open device [" << m_DeviceName << "]");
int res = openSingleRxChannel(m_DeviceName.c_str(), &m_PfRingDescriptors[0]);
if (res == 0)
{
PCPP_LOG_DEBUG("Succeeded opening device [" << m_DeviceName << "]");
m_NumOfOpenedRxChannels = 1;
m_DeviceOpened = true;
return true;
}
else if (res == 1)
PCPP_LOG_ERROR("Couldn't open a ring on device [" << m_DeviceName << "]");
else if (res == 2)
PCPP_LOG_ERROR("Unable to enable ring for device [" << m_DeviceName << "]");
return false;
}
bool PfRingDevice::openSingleRxChannel(uint8_t channelId)
{
uint8_t channelIds[1] = { channelId };
return openMultiRxChannels(channelIds, 1);
}
int PfRingDevice::openSingleRxChannel(const char* deviceName, pfring** ring)
{
if (m_DeviceOpened)
{
PCPP_LOG_ERROR("Device already opened");
return false;
}
uint32_t flags = PF_RING_PROMISC | PF_RING_HW_TIMESTAMP | PF_RING_DNA_SYMMETRIC_RSS;
*ring = pfring_open(deviceName, DEFAULT_PF_RING_SNAPLEN, flags);
if (*ring == NULL)
{
return 1;
}
PCPP_LOG_DEBUG("pfring_open Succeeded for device [" << m_DeviceName << "]");
if (getIsHwClockEnable())
{
setPfRingDeviceClock(*ring);
PCPP_LOG_DEBUG("H/W clock set for device [" << m_DeviceName << "]");
}
if (pfring_enable_rss_rehash(*ring) < 0 || pfring_enable_ring(*ring) < 0)
{
pfring_close(*ring);
return 2;
}
PCPP_LOG_DEBUG("pfring enabled for device [" << m_DeviceName << "]");
return 0;
}
bool PfRingDevice::setPfRingDeviceClock(pfring* ring)
{
struct timespec ltime;
if (clock_gettime(CLOCK_REALTIME, <ime) != 0)
{
PCPP_LOG_ERROR("Could not set pfring devices clock, clock_gettime failed");
return false;
}
if (pfring_set_device_clock(ring, <ime) < 0)
{
PCPP_LOG_DEBUG("Could not set pfring devices clock, pfring_set_device_clock failed");
return false;
}
return true;
}
bool PfRingDevice::openMultiRxChannels(const uint8_t* channelIds, int numOfChannelIds)
{
if (m_DeviceOpened)
{
PCPP_LOG_ERROR("Device already opened");
return false;
}
uint8_t totalChannels = getTotalNumOfRxChannels();
for (int i = 0; i < numOfChannelIds; i++)
{
uint8_t channelId = channelIds[i];
if (channelId >= totalChannels)
{
PCPP_LOG_ERROR("Trying to open the device with a RX channel that doesn't exist. Total RX channels are [" << (int)totalChannels << "], tried to open channel [" << (int)channelId << "]");
return false;
}
}
m_NumOfOpenedRxChannels = 0;
for (int i = 0; i < numOfChannelIds; i++)
{
uint8_t channelId = channelIds[i];
std::ostringstream ringNameStream;
ringNameStream << m_DeviceName << "@" << (int)channelId;
std::string ringName = ringNameStream.str();
PCPP_LOG_DEBUG("Trying to open device [" << m_DeviceName << "] on channel [" << channelId << "]. Channel name [" << ringName << "]");
int res = openSingleRxChannel(ringName.c_str(), &m_PfRingDescriptors[i]);
if (res == 0)
{
PCPP_LOG_DEBUG("Succeeded opening device [" << m_DeviceName << "] on channel [" << channelId << "]. Channel name [" << ringName << "]");
m_NumOfOpenedRxChannels++;
continue;
}
else if (res == 1)
PCPP_LOG_ERROR("Couldn't open a ring on channel [" << (int)channelId << "] for device [" << m_DeviceName << "]");
else if (res == 2)
PCPP_LOG_ERROR("Unable to enable ring on channel [" << (int)channelId << "] for device [" << m_DeviceName << "]");
break;
}
if (m_NumOfOpenedRxChannels < numOfChannelIds)
{
for (int i = 0; i < m_NumOfOpenedRxChannels-1; i++)
{
pfring_close(m_PfRingDescriptors[i]);
}
m_NumOfOpenedRxChannels = 0;
return false;
}
m_DeviceOpened = true;
return true;
}
bool PfRingDevice::openMultiRxChannels(uint8_t numOfRxChannelsToOpen, ChannelDistribution dist)
{
if (m_DeviceOpened)
{
PCPP_LOG_ERROR("Device already opened");
return false;
}
m_NumOfOpenedRxChannels = 0;
if (numOfRxChannelsToOpen > MAX_NUM_RX_CHANNELS)
{
PCPP_LOG_ERROR("Cannot open more than [" << MAX_NUM_RX_CHANNELS << "] channels");
return false;
}
uint32_t flags = PF_RING_PROMISC | PF_RING_REENTRANT | PF_RING_HW_TIMESTAMP | PF_RING_DNA_SYMMETRIC_RSS;
uint8_t numOfRxChannelsOnNIC = getTotalNumOfRxChannels();
PCPP_LOG_DEBUG("NIC has " << (int)numOfRxChannelsOnNIC << " RX channels");
uint8_t numOfRingsPerRxChannel = numOfRxChannelsToOpen / numOfRxChannelsOnNIC;
uint8_t remainderRings = numOfRxChannelsToOpen % numOfRxChannelsOnNIC;
cluster_type clusterType = (dist == RoundRobin) ? cluster_round_robin : cluster_per_flow;
int ringsOpen = 0;
for (uint8_t channelId = 0; channelId < numOfRxChannelsOnNIC; channelId++)
{
if (numOfRingsPerRxChannel == 0 && remainderRings == 0)
break;
std::ostringstream ringName;
ringName << m_DeviceName << "@" << (int)channelId;
for (uint8_t ringId = 0; ringId < numOfRingsPerRxChannel; ringId++)
{
m_PfRingDescriptors[ringsOpen] = pfring_open(ringName.str().c_str(), DEFAULT_PF_RING_SNAPLEN, flags);
if (m_PfRingDescriptors[ringsOpen] == NULL)
{
PCPP_LOG_ERROR("Couldn't open a ring on channel [" << (int)channelId << "]");
break;
}
if (pfring_set_cluster(m_PfRingDescriptors[ringsOpen], channelId+1, clusterType) < 0)
{
PCPP_LOG_ERROR("Couldn't set ring [" << (int)ringId << "] in channel [" << (int)channelId << "] to the cluster [" << (int)(channelId+1) << "]");
break;
}
ringsOpen++;
}
if (remainderRings > 0)
{
m_PfRingDescriptors[ringsOpen] = pfring_open(ringName.str().c_str(), DEFAULT_PF_RING_SNAPLEN, flags);
if (m_PfRingDescriptors[ringsOpen] == NULL)
{
PCPP_LOG_ERROR("Couldn't open a ring on channel [" << (int)channelId << "]");
break;
}
if (pfring_set_cluster(m_PfRingDescriptors[ringsOpen], channelId+1, clusterType) < 0)
{
PCPP_LOG_ERROR("Couldn't set ring [" << (int)(numOfRingsPerRxChannel+1) << "] in channel [" << (int)channelId << "] to the cluster [" << (int)(channelId+1) << "]");
break;
}
ringsOpen++;
remainderRings--;
PCPP_LOG_DEBUG("Opened " << (int)(numOfRingsPerRxChannel+1) << " rings on channel [" << (int)channelId << "]");
}
else
PCPP_LOG_DEBUG("Opened " << (int)numOfRingsPerRxChannel << " rings on channel [" << (int)channelId << "]");
}
if (ringsOpen < numOfRxChannelsToOpen)
{
for (uint8_t i = 0; i < ringsOpen; i++)
pfring_close(m_PfRingDescriptors[i]);
return false;
}
if (getIsHwClockEnable())
{
for (int i = 0; i < ringsOpen; i++)
{
if (setPfRingDeviceClock(m_PfRingDescriptors[i]))
PCPP_LOG_DEBUG("H/W clock set for device [" << m_DeviceName << "]");
}
}
for (int i = 0; i < ringsOpen; i++)
{
if (pfring_enable_rss_rehash(m_PfRingDescriptors[i]) < 0 || pfring_enable_ring(m_PfRingDescriptors[i]) < 0)
{
PCPP_LOG_ERROR("Unable to enable ring [" << i << "] for device [" << m_DeviceName << "]");
for (int j = 0; j <ringsOpen; j++)
pfring_close(m_PfRingDescriptors[j]);
return false;
}
}
m_NumOfOpenedRxChannels = ringsOpen;
m_DeviceOpened = true;
return true;
}
uint8_t PfRingDevice::getTotalNumOfRxChannels() const
{
if (m_NumOfOpenedRxChannels > 0)
{
uint8_t res = pfring_get_num_rx_channels(m_PfRingDescriptors[0]);
return res;
}
else
{
uint32_t flags = PF_RING_PROMISC | PF_RING_REENTRANT | PF_RING_HW_TIMESTAMP | PF_RING_DNA_SYMMETRIC_RSS;
pfring* ring = pfring_open(m_DeviceName.c_str(), DEFAULT_PF_RING_SNAPLEN, flags);
uint8_t res = pfring_get_num_rx_channels(ring);
pfring_close(ring);
return res;
}
}
SystemCore PfRingDevice::getCurrentCoreId() const
{
return SystemCores::IdToSystemCore[sched_getcpu()];
}
bool PfRingDevice::setFilter(std::string filterAsString)
{
if (!m_DeviceOpened)
{
PCPP_LOG_ERROR("Device not opened");
return false;
}
for (int i = 0; i < m_NumOfOpenedRxChannels; i++)
{
int res = pfring_set_bpf_filter(m_PfRingDescriptors[i], (char*)filterAsString.c_str());
if(res < 0)
{
if (res == PF_RING_ERROR_NOT_SUPPORTED)
PCPP_LOG_ERROR("BPF filtering isn't supported on current PF_RING version. Please re-compile PF_RING with the --enable-bpf flag");
else
PCPP_LOG_ERROR("Couldn't set filter '" << filterAsString << "'");
return false;
}
}
m_IsFilterCurrentlySet = true;
PCPP_LOG_DEBUG("Successfully set filter '" << filterAsString << "'");
return true;
}
bool PfRingDevice::clearFilter()
{
if (!m_IsFilterCurrentlySet)
return true;
for (int i = 0; i < m_NumOfOpenedRxChannels; i++)
{
int res = pfring_remove_bpf_filter(m_PfRingDescriptors[i]);
if(res < 0)
{
PCPP_LOG_ERROR("Couldn't remove filter");
return false;
}
}
m_IsFilterCurrentlySet = false;
PCPP_LOG_DEBUG("Successfully removed filter from all open RX channels");
return true;
}
bool PfRingDevice::isFilterCurrentlySet() const
{
return m_IsFilterCurrentlySet;
}
void PfRingDevice::close()
{
for (int i = 0; i < m_NumOfOpenedRxChannels; i++)
pfring_close(m_PfRingDescriptors[i]);
m_DeviceOpened = false;
clearCoreConfiguration();
m_NumOfOpenedRxChannels = 0;
m_IsFilterCurrentlySet = false;
PCPP_LOG_DEBUG("Device [" << m_DeviceName << "] closed");
}
bool PfRingDevice::initCoreConfigurationByCoreMask(CoreMask coreMask)
{
int i = 0;
int numOfCores = getNumOfCores();
clearCoreConfiguration();
while ((coreMask != 0) && (i < numOfCores))
{
if (coreMask & 1)
{
m_CoreConfiguration[i].IsInUse = true;
}
coreMask = coreMask >> 1;
i++;
}
if (coreMask != 0) {
PCPP_LOG_ERROR("Trying to use a core [" << i << "] that doesn't exist while machine has " << numOfCores << " cores");
clearCoreConfiguration();
return false;
}
return true;
}
bool PfRingDevice::startCaptureMultiThread(OnPfRingPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie, CoreMask coreMask)
{
if (!m_StopThread)
{
PCPP_LOG_ERROR("Device already capturing. Cannot start 2 capture sessions at the same time");
return false;
}
if (!initCoreConfigurationByCoreMask(coreMask))
return false;
if (m_NumOfOpenedRxChannels != getCoresInUseCount())
{
PCPP_LOG_ERROR("Cannot use a different number of channels and cores. Opened " << m_NumOfOpenedRxChannels << " channels but set " << getCoresInUseCount() << " cores in core mask");
clearCoreConfiguration();
return false;
}
std::mutex mutex;
std::condition_variable cond;
int startThread = 0;
m_StopThread = false;
int rxChannel = 0;
for (int coreId = 0; coreId < MAX_NUM_OF_CORES; coreId++)
{
if (!m_CoreConfiguration[coreId].IsInUse)
continue;
m_ReentrantMode = true;
m_OnPacketsArriveCallback = onPacketsArrive;
m_OnPacketsArriveUserCookie = onPacketsArriveUserCookie;
m_CoreConfiguration[coreId].Channel = m_PfRingDescriptors[rxChannel++];
m_CoreConfiguration[coreId].RxThread = std::thread(&pcpp::PfRingDevice::captureThreadMain, this, &cond, &mutex, &startThread);
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(coreId, &cpuset);
int err = pthread_setaffinity_np(m_CoreConfiguration[coreId].RxThread.native_handle(), sizeof(cpu_set_t), &cpuset);
if(err != 0)
{
PCPP_LOG_ERROR("Error while binding thread to core " << coreId << ": errno=" << err);
startThread = 1;
clearCoreConfiguration();
return false;
}
}
startThread = 2;
cond.notify_all();
return true;
}
bool PfRingDevice::startCaptureSingleThread(OnPfRingPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie)
{
if (!m_StopThread)
{
PCPP_LOG_ERROR("Device already capturing. Cannot start 2 capture sessions at the same time");
return false;
}
if (m_NumOfOpenedRxChannels != 1)
{
PCPP_LOG_ERROR("Cannot start capturing on a single thread when more than 1 RX channel is opened");
return false;
}
PCPP_LOG_DEBUG("Trying to start capturing on a single thread for device [" << m_DeviceName << "]");
clearCoreConfiguration();
m_OnPacketsArriveCallback = onPacketsArrive;
m_OnPacketsArriveUserCookie = onPacketsArriveUserCookie;
m_StopThread = false;
m_ReentrantMode = false;
std::mutex mutex;
std::condition_variable cond;
int startThread = 0;
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(0, &cpuset);
m_CoreConfiguration[0].IsInUse = true;
m_CoreConfiguration[0].Channel = m_PfRingDescriptors[0];
m_CoreConfiguration[0].RxThread = std::thread(&pcpp::PfRingDevice::captureThreadMain, this, &cond, &mutex, &startThread);
m_CoreConfiguration[0].IsAffinitySet = false;
int err = pthread_setaffinity_np(m_CoreConfiguration[0].RxThread.native_handle(), sizeof(cpu_set_t), &cpuset);
if(err != 0)
{
startThread = 1;
PCPP_LOG_ERROR("Error while binding thread to core 0: errno=" << err);
clearCoreConfiguration();
return false;
}
startThread = 2;
cond.notify_all();
PCPP_LOG_DEBUG("Capturing started for device [" << m_DeviceName << "]");
return true;
}
void PfRingDevice::stopCapture()
{
PCPP_LOG_DEBUG("Trying to stop capturing on device [" << m_DeviceName << "]");
m_StopThread = true;
for (int coreId = 0; coreId < MAX_NUM_OF_CORES; coreId++)
{
if (!m_CoreConfiguration[coreId].IsInUse)
continue;
m_CoreConfiguration[coreId].RxThread.join();
PCPP_LOG_DEBUG("Thread on core [" << coreId << "] stopped");
}
PCPP_LOG_DEBUG("All capturing threads stopped");
}
void PfRingDevice::captureThreadMain(std::condition_variable* startCond, std::mutex* startMutex, const int* startState)
{
while (*startState == 0)
{
std::unique_lock<std::mutex> lock(*startMutex);
startCond->wait_for(lock, std::chrono::milliseconds(100));
}
if (*startState == 1)
{
return;
}
int coreId = this->getCurrentCoreId().Id;
pfring* ring = NULL;
PCPP_LOG_DEBUG("Starting capture thread " << coreId);
ring = this->m_CoreConfiguration[coreId].Channel;
if (ring == NULL)
{
PCPP_LOG_ERROR("Couldn't find ring for core " << coreId << ". Exiting capture thread");
return;
}
while (!this->m_StopThread)
{
uint8_t* buffer = NULL;
uint32_t bufferLen = 0;
if (this->m_ReentrantMode)
{
uint8_t tempBuffer[PCPP_MAX_PACKET_SIZE];
buffer = tempBuffer;
bufferLen = PCPP_MAX_PACKET_SIZE;
}
struct pfring_pkthdr pktHdr;
int recvRes = pfring_recv(ring, &buffer, bufferLen, &pktHdr, 0);
if (recvRes > 0)
{
RawPacket rawPacket(buffer, pktHdr.caplen, pktHdr.ts, false);
this->m_OnPacketsArriveCallback(&rawPacket, 1, coreId, this, this->m_OnPacketsArriveUserCookie);
}
else if (recvRes < 0)
{
PCPP_LOG_ERROR("pfring_recv returned an error: [Err=" << recvRes << "]");
}
}
PCPP_LOG_DEBUG("Exiting capture thread " << coreId);
}
void PfRingDevice::getThreadStatistics(SystemCore core, PfRingStats& stats) const
{
pfring* ring = NULL;
uint8_t coreId = core.Id;
ring = m_CoreConfiguration[coreId].Channel;
if (ring != NULL)
{
pfring_stat tempStats;
if (pfring_stats(ring, &tempStats) < 0)
{
PCPP_LOG_ERROR("Can't retrieve statistics for core [" << (int)coreId << "], pfring_stats failed");
return;
}
stats.drop = (uint64_t)tempStats.drop;
stats.recv = (uint64_t)tempStats.recv;
}
else
{
PCPP_LOG_ERROR("Core [" << (int)coreId << "] is not in use, can't retrieve statistics");
}
}
void PfRingDevice::getCurrentThreadStatistics(PfRingStats& stats) const
{
getThreadStatistics(getCurrentCoreId(), stats);
}
void PfRingDevice::getStatistics(PfRingStats& stats) const
{
stats.drop = 0;
stats.recv = 0;
for (int coreId = 0; coreId < MAX_NUM_OF_CORES; coreId++)
{
if (!m_CoreConfiguration[coreId].IsInUse)
continue;
PfRingStats tempStat = {};
getThreadStatistics(SystemCores::IdToSystemCore[coreId], tempStat);
stats.drop += tempStat.drop;
stats.recv += tempStat.recv;
if (!m_CoreConfiguration[coreId].IsAffinitySet)
break;
}
}
void PfRingDevice::clearCoreConfiguration()
{
for (int i = 0; i < MAX_NUM_OF_CORES; i++)
m_CoreConfiguration[i].clear();
}
int PfRingDevice::getCoresInUseCount() const
{
int res = 0;
for (int i = 0; i < MAX_NUM_OF_CORES; i++)
if (m_CoreConfiguration[i].IsInUse)
res++;
return res;
}
void PfRingDevice::setPfRingDeviceAttributes()
{
if (m_InterfaceIndex > -1)
return;
pfring* ring = NULL;
bool closeRing = false;
if (m_NumOfOpenedRxChannels > 0)
ring = m_PfRingDescriptors[0];
else
{
uint32_t flags = PF_RING_PROMISC | PF_RING_DNA_SYMMETRIC_RSS;
ring = pfring_open(m_DeviceName.c_str(), DEFAULT_PF_RING_SNAPLEN, flags);
closeRing = true;
}
if (ring == NULL)
{
PCPP_LOG_ERROR("Could not open a pfring for setting device attributes: MAC address, interface index and HW clock");
return;
}
uint8_t macAddress[6];
if (pfring_get_bound_device_address(ring, macAddress) < 0)
PCPP_LOG_ERROR("Unable to read the device MAC address for interface '" << m_DeviceName << "'");
else
m_MacAddress = MacAddress(macAddress);
if (pfring_get_bound_device_ifindex(ring, &m_InterfaceIndex) < 0)
PCPP_LOG_ERROR("Unable to read interface index of device");
m_HwClockEnabled = setPfRingDeviceClock(ring);
int mtu = pfring_get_mtu_size(ring);
if (mtu < 0)
PCPP_LOG_ERROR("Could not get MTU. pfring_get_mtu_size returned an error: " << mtu);
else
m_DeviceMTU = mtu + sizeof(ether_header) + sizeof(vlan_header);
if (Logger::getInstance().isDebugEnabled(PcapLogModulePfRingDevice))
{
std::string hwEnabled = (m_HwClockEnabled ? "enabled" : "disabled");
PCPP_LOG_DEBUG("Capturing from " << m_DeviceName << " [" << m_MacAddress << "][ifIndex: " << m_InterfaceIndex << "][MTU: " << m_DeviceMTU << "], HW clock " << hwEnabled);
}
if (closeRing)
pfring_close(ring);
}
bool PfRingDevice::sendData(const uint8_t* packetData, int packetDataLength, bool flushTxQueues)
{
if (!m_DeviceOpened)
{
PCPP_LOG_ERROR("Device is not opened. Cannot send packets");
return false;
}
uint8_t flushTxAsUint = (flushTxQueues? 1 : 0);
#define MAX_TRIES 5
int tries = 0;
int res = 0;
while (tries < MAX_TRIES)
{
if (packetDataLength > m_DeviceMTU)
packetDataLength = m_DeviceMTU;
res = pfring_send(m_PfRingDescriptors[0], (char*)packetData, packetDataLength, flushTxAsUint);
if (res == -1 && errno == ENOBUFS)
{
tries++;
PCPP_LOG_DEBUG("Try #" << tries << ": Got ENOBUFS (write buffer full) error while sending packet. Sleeping 20 usec and trying again");
usleep(2000);
}
else
break;
}
if (tries >= MAX_TRIES)
{
PCPP_LOG_ERROR("Tried to send data " << MAX_TRIES << " times but write buffer is full");
return false;
}
if (res < 0)
{
if (res == -1)
PCPP_LOG_ERROR("Error sending packet: Linux errno: " << strerror(errno) << " [" << errno << "]");
else
PCPP_LOG_ERROR("Error sending packet: pfring_send returned an error: " << res << " , errno: " << strerror(errno)<< " [" << errno << "]");
return false;
} else if (res != packetDataLength)
{
PCPP_LOG_ERROR("Couldn't send all bytes, only " << res << " bytes out of " << packetDataLength << " bytes were sent");
return false;
}
return true;
}
bool PfRingDevice::sendPacket(const uint8_t* packetData, int packetDataLength)
{
return sendData(packetData, packetDataLength, true);
}
bool PfRingDevice::sendPacket(const RawPacket& rawPacket)
{
return sendData(rawPacket.getRawData(), rawPacket.getRawDataLen(), true);
}
bool PfRingDevice::sendPacket(const Packet& packet)
{
return sendData(packet.getRawPacketReadOnly()->getRawData(), packet.getRawPacketReadOnly()->getRawDataLen(), true);
}
int PfRingDevice::sendPackets(const RawPacket* rawPacketsArr, int arrLength)
{
int packetsSent = 0;
for (int i = 0; i < arrLength; i++)
{
if (!sendData(rawPacketsArr[i].getRawData(), rawPacketsArr[i].getRawDataLen(), false))
break;
else
packetsSent++;
}
pfring_flush_tx_packets(m_PfRingDescriptors[0]);
PCPP_LOG_DEBUG(packetsSent << " out of " << arrLength << " raw packets were sent successfully");
return packetsSent;
}
int PfRingDevice::sendPackets(const Packet** packetsArr, int arrLength)
{
int packetsSent = 0;
for (int i = 0; i < arrLength; i++)
{
if (!sendData(packetsArr[i]->getRawPacketReadOnly()->getRawData(), packetsArr[i]->getRawPacketReadOnly()->getRawDataLen(), false))
break;
else
packetsSent++;
}
pfring_flush_tx_packets(m_PfRingDescriptors[0]);
PCPP_LOG_DEBUG(packetsSent << " out of " << arrLength << " packets were sent successfully");
return packetsSent;
}
int PfRingDevice::sendPackets(const RawPacketVector& rawPackets)
{
int packetsSent = 0;
for (RawPacketVector::ConstVectorIterator iter = rawPackets.begin(); iter != rawPackets.end(); iter++)
{
if (!sendData((*iter)->getRawData(), (*iter)->getRawDataLen(), false))
break;
else
packetsSent++;
}
pfring_flush_tx_packets(m_PfRingDescriptors[0]);
PCPP_LOG_DEBUG(packetsSent << " out of " << rawPackets.size() << " raw packets were sent successfully");
return packetsSent;
}
PfRingDevice::CoreConfiguration::CoreConfiguration()
: Channel(NULL), IsInUse(false), IsAffinitySet(true)
{
}
void PfRingDevice::CoreConfiguration::clear()
{
Channel = NULL;
IsInUse = false;
IsAffinitySet = true;
}
}
#endif