libraries/pcappp/include/pcapplusplus/PfRingDevice.h

349 lines
13 KiB
C++

#ifndef PCAPPP_PF_RING_DEVICE
#define PCAPPP_PF_RING_DEVICE
#include "Device.h"
#include "MacAddress.h"
#include "SystemUtils.h"
#include "Packet.h"
#include <pthread.h>
/// @file
// forward declaration of PF_RING structs
struct __pfring;
typedef struct __pfring pfring;
/**
* \namespace pcpp
* \brief The main namespace for the PcapPlusPlus lib
*/
namespace pcpp
{
class PfRingDevice;
typedef void (*OnPfRingPacketsArriveCallback)(RawPacket* packets, uint32_t numOfPackets, uint8_t threadId, PfRingDevice* device, void* userCookie);
/**
* @class PfRingDevice
* A class representing a PF_RING port
*/
class PfRingDevice : public IDevice, public IFilterableDevice
{
friend class PfRingDeviceList;
private:
struct CoreConfiguration
{
pthread_t RxThread;
pfring* Channel;
bool IsInUse;
bool IsAffinitySet;
CoreConfiguration();
void clear();
};
pfring** m_PfRingDescriptors;
uint8_t m_NumOfOpenedRxChannels;
std::string m_DeviceName;
int m_InterfaceIndex;
MacAddress m_MacAddress;
int m_DeviceMTU;
CoreConfiguration m_CoreConfiguration[MAX_NUM_OF_CORES];
bool m_StopThread;
OnPfRingPacketsArriveCallback m_OnPacketsArriveCallback;
void* m_OnPacketsArriveUserCookie;
bool m_ReentrantMode;
bool m_HwClockEnabled;
bool m_IsFilterCurrentlySet;
PfRingDevice(const char* deviceName);
bool initCoreConfigurationByCoreMask(CoreMask coreMask);
static void* captureThreadMain(void *ptr);
int openSingleRxChannel(const char* deviceName, pfring** ring);
bool getIsHwClockEnable() { setPfRingDeviceAttributes(); return m_HwClockEnabled; }
bool setPfRingDeviceClock(pfring* ring);
void clearCoreConfiguration();
int getCoresInUseCount() const;
void setPfRingDeviceAttributes();
bool sendData(const uint8_t* packetData, int packetDataLength, bool flushTxQueues);
public:
/**
* An enum representing the type of packet distribution between different RX channels
*/
enum ChannelDistribution
{
/**
* Packets are distributed between channels in a round-robin manner
*/
RoundRobin,
/**
* Packets are distributed between channels per flow (each flow goes for different channel)
*/
PerFlow
};
/**
* @struct PfRingStats
* A container for PfRingDevice statistics
*/
struct PfRingStats
{
/** Number of packets received */
uint64_t recv;
/** Number of packets dropped */
uint64_t drop;
};
/**
* A destructor for PfRingDevice class
*/
~PfRingDevice();
/**
* Get the MAC address of the current device
* @return The MAC address of the current device
*/
MacAddress getMacAddress() { setPfRingDeviceAttributes(); return m_MacAddress; }
/**
* Get PF_RING interface index of the current device
* @return PF_RING interface index of the current device
*/
int getInterfaceIndex() { setPfRingDeviceAttributes(); return m_InterfaceIndex; }
/**
* Get MTU of the current device
* @return Upon success return the device MTU, 0 otherwise
*/
int getMtu() { setPfRingDeviceAttributes(); return m_DeviceMTU; }
/**
* Return true if device supports hardware timestamping. If it does, this feature will be automatically set
* for this device. You can read more about this in PF_RING documentation
* @return True if device supports hardware timestamping, false otherwise
*/
bool isHwClockEnabledForDevice() { setPfRingDeviceAttributes(); return m_HwClockEnabled; }
/**
* Gets the interface name (e.g eth0, eth1, etc.)
* @return The interface name
*/
std::string getDeviceName() const { return m_DeviceName; }
/**
* Start single-threaded capturing with callback. Works with open() or openSingleRxChannel().
* @param[in] onPacketsArrive A callback to call whenever a packet arrives
* @param[in] onPacketsArriveUserCookie A cookie that will be delivered to onPacketsArrive callback on every packet
* @return True if this action succeeds, false otherwise
*/
bool startCaptureSingleThread(OnPfRingPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie);
/**
* Start multi-threaded (multi-core) capturing with callback. Works with openMultiRxChannels().
* This method will return an error if the number of opened channels is different than the number of threads/cores
* requested
* @param[in] onPacketsArrive A callback to call whenever a packet arrives
* @param[in] onPacketsArriveUserCookie A cookie that will be delivered to onPacketsArrive callback on every packet
* @param[in] coreMask The cores to be used as mask. For example:
* @return True if this action succeeds, false otherwise
*/
bool startCaptureMultiThread(OnPfRingPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie, CoreMask coreMask);
/**
* Stops capturing packets (works will all type of startCapture*)
*/
void stopCapture();
/**
* Opens a single RX channel (=RX queue) on this interface. All packets will be received on a single thread
* without core affinity. If the channel ID requested doesn't exist on this interface, the method will fail
* (return false)
* @param[in] channelId The requested channel ID
* @return True if this action succeeds, false otherwise
*/
bool openSingleRxChannel(uint8_t channelId);
/**
* Opens a set of RX channels (=RX queues) on this interface, identified by their IDs. All packets will be received on a single thread
* without core affinity. If one of the channel IDs requested doesn't exist on this interface, the method will fail
* (return false)
* @param[in] channelIds An array of channel IDs
* @param[in] numOfChannelIds The channel ID array size
* @return True if this action succeeds, false otherwise
*/
bool openMultiRxChannels(const uint8_t* channelIds, int numOfChannelIds);
/**
* Opens numOfRxChannelsToOpen RX channels. If numOfRxChannelsToOpen is larger than available RX queues for this
* interface than a number of RX channels will be opened on each RX queue. For example: if the user asks for 10
* RX channels but the interface has only 4 RX queues, then 3 RX channels will be opened for RX-queue0 and RX-queue2,
* and 2 RX channels will be opened for RX-queue2 and RX-queue3.
* Packets will be distributed between different RX queues on per-flow manner, but within multiple RX channels in
* the same RX queue packet will be distributed according to distribution requested by "dist"
* @param[in] numOfRxChannelsToOpen Number of RX channels to open
* @param[in] dist Distribution method
* @return True if this action succeeds, false otherwise
*/
bool openMultiRxChannels(uint8_t numOfRxChannelsToOpen, ChannelDistribution dist);
/**
* Gets the number of RX channels currently open. RX channels aren't necessary interface's RX queues
* because in some cases the user asks to open several channels on the same queue. For example: if the user uses
* openMultiRxChannels() and asks to open 8 channels but interface has only 4 RX queues, 2 channels will be
* opened for each RX queue
* @return Number of opened RX channels
*/
uint8_t getNumOfOpenedRxChannels() const { return m_NumOfOpenedRxChannels; }
/**
* Gets the total number of RX channels (RX queues) this interface has
* @return The number of RX channels (queues) for this interface
*/
uint8_t getTotalNumOfRxChannels() const;
/**
* Gets the core used in the current thread context
* @return The system core used in the current thread context
*/
SystemCore getCurrentCoreId() const;
/**
* Get the statistics of a specific thread/core (=RX channel)
* @param[in] core The requested core
* @param[out] stats A reference for the stats object where the stats are written. Current values will be overridden
*/
void getThreadStatistics(SystemCore core, PfRingStats& stats) const;
/**
* Get the statistics of the current thread/core (=RX channel)
* @param[out] stats A reference for the stats object where the stats are written. Current values will be overridden
*/
void getCurrentThreadStatistics(PfRingStats& stats) const;
/**
* Get the statistics for the entire device. If more than 1 RX channel is opened, this method aggregates the stats
* of all channels
* @param[out] stats A reference for the stats object where the stats are written. Current values will be overridden
*/
void getStatistics(PfRingStats& stats) const;
/**
* Return true if filter is currently set
* @return True if filter is currently set, false otherwise
*/
bool isFilterCurrentlySet() const;
/**
* Send a raw packet. This packet must be fully specified (the MAC address up)
* and it will be transmitted as-is without any further manipulation.
* This method doesn't change or manipulate the data in any way (hence the "const" declaration).
* Note this method flushes the TX queues after the data is sent. So if you want to send several packets
* In the burst please use sendPackets()
* @param[in] rawPacket The raw packet to send
* @return True if raw packet was sent completely, false otherwise
*/
bool sendPacket(const RawPacket& rawPacket);
/**
* Send raw data. This data must be a valid and fully specified packet (the MAC address up);
* it will be transmitted as-is without any further manipulation.
* This method doesn't change or manipulate the data in any way (hence the "const" declaration).
* Note this method flushes the TX queues after the data is sent. So if you want to send several packets
* in the burst please use sendPackets()
* @param[in] packetData The raw data to send
* @param[in] packetDataLength the length of packetData
* @return True if raw packet was sent completely, false otherwise
*
*/
bool sendPacket(const uint8_t* packetData, int packetDataLength);
/**
* Send a packet. This packet must be fully specified (the MAC address up)
* and it will be transmitted as-is without any further manipulation.
* This method doesn't change or manipulate the data in any way (hence the "const" declaration).
* Note this method flushes the TX queues after the data is sent. So if you want to send several packets
* In the burst please use sendPackets()
* @param[in] packet The packet to send
* @return True if raw packet was sent completely, false otherwise
*/
bool sendPacket(const Packet& packet);
/**
* Send raw packets. All raw packets must be fully specified (the MAC address up)
* and it will be transmitted as-is without any further manipulation.
* This method doesn't change or manipulate the raw packets data in any way (hence the "const" declaration).
* This method flushes the TX queues only when the last packet is sent
* @param[in] rawPacketsArr The RawPacket array
* @param[in] arrLength RawPacket array length
* @return Number of packets that were sent completely
*/
int sendPackets(const RawPacket* rawPacketsArr, int arrLength);
/**
* Send packets. All packets must be fully specified (the MAC address up)
* and it will be transmitted as-is without any further manipulation.
* This method doesn't change or manipulate the packets data in any way (hence the "const" declaration).
* This method flushes the TX queues only when the last packet is sent
* @param[in] packetsArr An array of pointers to Packet objects
* @param[in] arrLength Packet pointers array length
* @return Number of packets that were sent completely
*/
int sendPackets(const Packet** packetsArr, int arrLength);
/**
* Send all raw packets pointed by the RawPacketVector. All packets must be fully specified (the MAC address up)
* and it will be transmitted as-is without any further manipulation.
* This method doesn't change or manipulate the packets data in any way (hence the "const" declaration).
* This method flushes the TX queues only when the last packet is sent
* @param[in] rawPackets The raw packet vector
* @return Number of raw packets that were sent completely
*/
int sendPackets(const RawPacketVector& rawPackets);
// implement abstract methods
/**
* Opens the entire device (including all RX channels/queues on this interface). All packets will be received
* on a single thread without core affinity
* @return True if this action succeeds, false otherwise
*/
bool open();
/**
* Closes all RX channels currently opened in device
*/
void close();
using IFilterableDevice::setFilter;
/**
* Sets a BPF filter to the device
* @param[in] filterAsString The BPF filter in string format
*/
bool setFilter(std::string filterAsString);
/**
* Remove a filter if currently set
* @return True if filter was removed successfully or if no filter was set, false otherwise
*/
bool clearFilter();
};
} // namespace pcpp
#endif /* PCAPPP_PF_RING_DEVICE */