You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by al...@apache.org on 2017/11/14 01:48:23 UTC
[09/25] nifi-minifi-cpp git commit: MINIFICPP-250: Initial
implementation fo CapturePacket Processor that uses lipcap.
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c0a788b3/thirdparty/pcap++/Pcap++/header/DpdkDevice.h
----------------------------------------------------------------------
diff --git a/thirdparty/pcap++/Pcap++/header/DpdkDevice.h b/thirdparty/pcap++/Pcap++/header/DpdkDevice.h
new file mode 100644
index 0000000..ac77a0f
--- /dev/null
+++ b/thirdparty/pcap++/Pcap++/header/DpdkDevice.h
@@ -0,0 +1,747 @@
+#ifndef PCAPPP_DPDK_DEVICE
+#define PCAPPP_DPDK_DEVICE
+
+#include <pthread.h>
+#include <MacAddress.h>
+#include <SystemUtils.h>
+#include <RawPacket.h>
+#include <PcapLiveDevice.h>
+
+/**
+ * @file
+ * This file and DpdkDeviceList.h provide PcapPlusPlus C++ wrapper for DPDK (stands for data-plan development kit). What is
+ * DPDK? as quoting from http://dpdk.org: "DPDK is a set of libraries and drivers for fast packet processing... These libraries can be used to:
+ * receive and send packets within the minimum number of CPU cycles (usually less than 80 cycles)... develop fast packet capture algorithms
+ * (tcpdump-like)... run third-party fast path stacks... Some packet processing functions have been benchmarked up to hundreds million
+ * frames per second, using 64-byte packets with a PCIe NIC"<BR>
+ * As DPDK API is written in C, PcapPlusPlus wraps the main functionality in a C++ easy-to-use classes which should have minimum affect
+ * on performance and packet processing rate. In addition it brings DPDK to the PcapPlusPlus framework and API so you can use DPDK
+ * together with other PcapPlusPlus features such as packet parsing and editing, etc.<BR>
+ * So how DPDK basically works? in order to boost packet processing performance on a commodity server DPDK is bypassing the Linux kernel.
+ * All the packet processing activity happens in the user space so basically packets are delivered from NIC hardware queues directly
+ * to user-space shared memory without going through the kernel. In addition DPDK uses polling instead of handling interrupts for each
+ * arrived packet (as interupts create some delays). Other methods to boost packets processing implemented by DPDK are using Hugepages to
+ * decrease the size of TLB that results in a much faster virtual to physical page conversion, thread affinity to bind threads to a
+ * specific core, lock-free user-space multi-core synchronization using rings data structures and NUMA awareness to avoid expensive data
+ * transfers between sockets.<BR>
+ * Not every NIC supports kernel-bypass capabilities so DPDK cannot work with any NIC. The list of supported NICs are in DPDK's web-site
+ * http://dpdk.org/doc/nics . For each such NIC the DPDK framework provides a module that called poll-mode-driver (PMD in short) that
+ * enables this NIC to the working with DPDK. PcapPlusPlus wasn't tested with most PMDs but all of them should theoretically work as
+ * PcapPlusPlus doesn't change the PMD behavior<BR>
+ * DPDK has another basic data-structure called mbuf. An mbuf is DPDK wrapper struct for network packets. When working with packets
+ * in DPDK you actually work with mbufs. The mbuf contains the packet data (obviously) but also some metadata on the packet such
+ * as the DPDK port it was captured on, packet ref-count (which allows it to be referenced by several objects), etc. One important
+ * concept is that DPDK doesn't allocate mbufs on-the-fly but uses mbuf pools. These pools is allocated on application startup and
+ * used throughout the application. The goal of this, of course, is increasing packet processing performance as allocating memory has
+ * its cost. So pool size is important and varies between applications. For example: an application that stores packets in memory
+ * has to have a large pool of mbufs so mbufs doesn't run-out. PcapPlusPlus enables to choose the pool size at startup<BR>
+ * <BR>
+ * PcapPlusPlus main wrapper classes for DPDK are:
+ * - DpdkDevice - a class that wraps a DPDK port and provides all capabilities of receiving and sending packets to this port
+ * - DpdkDeviceList - a singleton class that initializes the DPDK infrastructure and creates DpdkDevice instances to all available ports.
+ * In addition it allows starting and stopping of worker threads
+ * - MBufRawPacket - a child class to RawPacket which customizes it for working with mbuf
+ * - In addition PcapPlusPlus provides a shell script to initialize DPDK prerequisites: setup-dpdk.sh. This is an easy-to-use script
+ * that sets up huge-pages, loads DPDK kernel module and sets up the NICs that will be used by DPDK. This script must run before an
+ * application that uses DPDK runs. If you forgot to run it the application will fail with an appropriate error that will remind
+ *
+ * DPDK initialization using PcapPlusPlus:
+ * - Before application runs: run the setup-dpdk.sh script
+ * - On application startup call DpdkDeviceList#initDpdk() static method to initialize DPDK infrastructure and DpdkDevice instances
+ * - Open the relevant DpdkDevice(s)
+ * - Send & receive packets...
+ */
+
+struct rte_mbuf;
+struct rte_mempool;
+struct rte_eth_conf;
+
+/**
+* \namespace pcpp
+* \brief The main namespace for the PcapPlusPlus lib
+*/
+namespace pcpp
+{
+
+ class DpdkDeviceList;
+ class DpdkDevice;
+
+ /**
+ * An enum describing all PMD (poll mode driver) types supported by DPDK. For more info about these PMDs please visit the DPDK web-site
+ */
+ enum DpdkPMDType {
+ /** Unknown PMD type */
+ PMD_UNKNOWN,
+ /** Link Bonding for 1GbE and 10GbE ports to allow the aggregation of multiple (slave) NICs into a single logical interface*/
+ PMD_BOND,
+ /** Intel E1000 PMD */
+ PMD_E1000EM,
+ /** Intel 1GbE PMD */
+ PMD_IGB,
+ /** Intel 1GbE virtual function PMD */
+ PMD_IGBVF,
+ /** Cisco enic (UCS Virtual Interface Card) PMD */
+ PMD_ENIC,
+ /** Intel fm10k PMD */
+ PMD_FM10K,
+ /** Intel 40GbE PMD */
+ PMD_I40E,
+ /** Intel 40GbE virtual function PMD */
+ PMD_I40EVF,
+ /** Intel 10GbE PMD */
+ PMD_IXGBE,
+ /** Intel 10GbE virtual function PMD */
+ PMD_IXGBEVF,
+ /** Mellanox ConnectX-3, ConnectX-3 Pro PMD */
+ PMD_MLX4,
+ /** Null PMD */
+ PMD_NULL,
+ /** pcap file PMD */
+ PMD_PCAP,
+ /** ring-based (memory) PMD */
+ PMD_RING,
+ /** VirtIO PMD */
+ PMD_VIRTIO,
+ /** VMWare VMXNET3 PMD */
+ PMD_VMXNET3,
+ /** Xen Project PMD */
+ PMD_XENVIRT,
+ /** AF_PACKET PMD */
+ PMD_AF_PACKET
+ };
+
+ class DpdkDevice;
+
+ /**
+ * @class MBufRawPacket
+ * A class that inherits RawPacket and wraps DPDK's mbuf object (see some info about mbuf in DpdkDevice.h) but is
+ * compatible with PcapPlusPlus framework. Using MBufRawPacket is be almost similar to using RawPacket, the implementation
+ * differences are encapsulated in the class implementation. For example: user can create and manipulate a Packet object from
+ * MBufRawPacket the same way it is done with RawPacket; User can use PcapFileWriterDevice to save MBufRawPacket to pcap the
+ * same way it's used with RawPacket; etc.<BR>
+ * The main difference is that RawPacket contains a pointer to the data itself and MBufRawPacket is holding a pointer to an mbuf
+ * object which contains a pointer to the data. This implies that MBufRawPacket without an mbuf allocated to it is not usable.
+ * Getting instances of MBufRawPacket can be done in one to the following ways:
+ * - Receiving packets from DpdkDevice. In this case DpdkDevice takes care of getting the mbuf from DPDK and wrapping it with
+ * MBufRawPacket
+ * - Creating MBufRawPacket from scratch (in order to send it with DpdkDevice, for example). In this case the user should call
+ * the init() method after constructing the object in order to allocate a new mbuf from DPDK port pool (encapsulated by DpdkDevice)
+ *
+ * Limitations of this class:
+ * - Currently chained mbufs are not supported. An mbuf has the capability to be linked to another mbuf and create a linked list
+ * of mbufs. This is good for Jumbo packets or other uses. MBufRawPacket doesn't support this capability so there is no way to
+ * access the mbufs linked to the mbuf wrapped by MBufRawPacket instance. I hope I'll be able to add this support in the future
+ */
+ class MBufRawPacket : public RawPacket
+ {
+ friend class DpdkDevice;
+
+ private:
+ struct rte_mbuf* m_MBuf;
+ DpdkDevice* m_Device;
+
+ void setMBuf(struct rte_mbuf* mBuf, timeval timestamp);
+ public:
+
+ /**
+ * A default c'tor for this class. Constructs an instance of this class without an mbuf attached to it. In order to allocate
+ * an mbuf the user should call the init() method. Without calling init() the instance of this class is not usable.
+ * This c'tor can be used for initializing an array of MBufRawPacket (which requires an empty c'tor)
+ */
+ MBufRawPacket() : RawPacket(), m_MBuf(NULL), m_Device(NULL) { m_DeleteRawDataAtDestructor = false; }
+
+ /**
+ * A d'tor for this class. Once called it frees the mbuf attached to it (returning it back to the mbuf pool it was allocated from)
+ */
+ virtual ~MBufRawPacket();
+
+ /**
+ * A copy c'tor for this class. The copy c'tor allocates a new mbuf from the same pool the original mbuf was
+ * allocated from, attaches the new mbuf to this instance of MBufRawPacket and copies the data from the original mbuf
+ * to the new mbuf
+ * @param[in] other The MBufRawPacket instance to copy from
+ */
+ MBufRawPacket(const MBufRawPacket& other);
+
+ /**
+ * Initialize an instance of this class. Initialization includes allocating an mbuf from the pool that resides in DpdkDevice.
+ * The user should call this method only once per instance. Calling it more than once will result with an error
+ * @param[in] device The DpdkDevice which has the pool to allocate the mbuf from
+ * @return True if initialization succeeded and false if this method was already called for this instance (and an mbuf is
+ * already attched) or if allocating an mbuf from the pool failed for some reason
+ */
+ bool init(DpdkDevice* device);
+
+ // overridden methods
+
+ /**
+ * An assignment operator for this class. Copies the data from the mbuf attached to the other MBufRawPacket to the mbuf
+ * attached to this instance. If instance is not initialized (meaning no mbuf is attached) nothing will be copied and
+ * instance will remain uninitialized (also, an error will be printed)
+ * @param[in] other The MBufRawPacket to assign data from
+ */
+ MBufRawPacket& operator=(const MBufRawPacket& other);
+
+ /**
+ * Set raw data to the mbuf by copying the data to it. In order to stay compatible with the ancestor method
+ * which takes control of the data pointer and frees it when RawPacket is destroyed, this method frees this pointer right away after
+ * data is copied to the mbuf. So when using this method please notice that after it's called pRawData memory is free, don't
+ * use this pointer again. In addition, if raw packet isn't initialized (mbuf is NULL), this method will call the init() method
+ * @param[in] pRawData A pointer to the new raw data
+ * @param[in] rawDataLen The new raw data length in bytes
+ * @param[in] timestamp The timestamp packet was received by the NIC
+ * @return True if raw data was copied to the mbuf successfully, false if rawDataLen is larger than mbuf max size, if initialization
+ * failed or if copying the data to the mbuf failed. In all of these cases an error will be printed to log
+ */
+ bool setRawData(const uint8_t* pRawData, int rawDataLen, timeval timestamp);
+
+ /**
+ * Clears the object and frees the mbuf
+ */
+ void clear();
+
+ /**
+ * Append packet data at the end of current data. This method uses the same mbuf already allocated and tries to append more space and
+ * copy the data to it. If MBufRawPacket is not initialize (mbuf is NULL) or mbuf append failed an error is printed to log
+ * @param[in] dataToAppend A pointer to the data to append
+ * @param[in] dataToAppendLen Length in bytes of dataToAppend
+ */
+ void appendData(const uint8_t* dataToAppend, size_t dataToAppendLen);
+
+ /**
+ * Insert raw data at some index of the current data and shift the remaining data to the end. This method uses the
+ * same mbuf already allocated and tries to append more space to it. Then it just copies dataToAppend at the relevant index and shifts
+ * the remaining data to the end. If MBufRawPacket is not initialize (mbuf is NULL) or mbuf append failed an error is printed to log
+ * @param[in] atIndex The index to insert the new data to
+ * @param[in] dataToInsert A pointer to the new data to insert
+ * @param[in] dataToInsertLen Length in bytes of dataToInsert
+ */
+ void insertData(int atIndex, const uint8_t* dataToInsert, size_t dataToInsertLen);
+
+ /**
+ * Remove certain number of bytes from current raw data buffer. All data after the removed bytes will be shifted back. This method
+ * uses the mbuf already allocated and tries to trim space from it
+ * @param[in] atIndex The index to start removing bytes from
+ * @param[in] numOfBytesToRemove Number of bytes to remove
+ * @return True if all bytes were removed successfully, or false if MBufRawPacket is not initialize (mbuf is NULL), mbuf trim
+ * failed or logatIndex+numOfBytesToRemove is out-of-bounds of the raw data buffer. In all of these cases an error is printed to log
+ */
+ bool removeData(int atIndex, size_t numOfBytesToRemove);
+
+ /**
+ * This overridden method,in contrast to its ancestor RawPacket#reallocateData() doesn't need to do anything because mbuf is already
+ * allocated to its maximum extent. So it only performs a check to verify the size after re-allocation doesn't exceed mbuf max size
+ * @param[in] newBufferLength The new buffer length as required by the user
+ * @return True if new size is larger than current size but smaller than mbuf max size, false otherwise
+ */
+ bool reallocateData(size_t newBufferLength);
+ };
+
+ /**
+ * @typedef OnDpdkPacketsArriveCallback
+ * A callback that is called when a burst of packets are captured by DpdkDevice
+ * @param[in] packets A pointer to an array of MBufRawPacket
+ * @param[in] numOfPackets The length of the array
+ * @param[in] threadId The thread/core ID who captured the packets
+ * @param[in] device A pointer to the DpdkDevice who captured the packets
+ * @param[in] userCookie The user cookie assigned by the user in DpdkDevice#startCaptureSingleThread() or DpdkDevice#startCaptureMultiThreads
+ */
+ typedef void (*OnDpdkPacketsArriveCallback)(MBufRawPacket* packets, uint32_t numOfPackets, uint8_t threadId, DpdkDevice* device, void* userCookie);
+
+ /**
+ * @class PciAddress
+ * A class representing a PCI address
+ */
+ class PciAddress
+ {
+ public:
+ /**
+ * Default c'tor that initializes all PCI address fields to 0 (until set otherwise, address will look like: 0000:00:00.0)
+ */
+ PciAddress() { domain = 0; bus = 0; devid = 0; function = 0; }
+
+ /**
+ * A c'tor that initializes all PCI address fields
+ * @param[in] domain Device domain
+ * @param[in] bus Device bus id
+ * @param[in] devid Device ID
+ * @param[in] function Device function
+ */
+ PciAddress(uint16_t domain, uint8_t bus, uint8_t devid, uint8_t function)
+ {
+ this->domain = domain;
+ this->bus = bus;
+ this->devid = devid;
+ this->function = function;
+ }
+
+ /** Device domain */
+ uint16_t domain;
+ /** Device bus id */
+ uint8_t bus;
+ /** Device ID */
+ uint8_t devid;
+ /** Device function */
+ uint8_t function;
+
+ /**
+ * @return The string format of the PCI address (xxxx:xx:xx.x)
+ */
+ std::string toString()
+ {
+ char pciString[15];
+ snprintf(pciString, 15, "%04x:%02x:%02x.%x", domain, bus, devid, function);
+ return std::string(pciString);
+ }
+
+ /**
+ * Comparison operator overload. Two PCI addresses are equal if all of their address parts (domain, bus, devid, function) are equal
+ */
+ bool operator==(const PciAddress &other) const
+ {
+ return (domain == other.domain && bus == other.bus && devid == other.devid && function == other.function);
+ }
+ };
+
+
+ /**
+ * @class DpdkDevice
+ * 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.<BR>
+ *
+ * __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())<BR>
+ *
+ * __Capturing packets__: there are two ways to capture packets using DpdkDevice:
+ * - using worker threads (see DpdkDeviceList#startDpdkWorkerThreads() ). When using this method the worker should use the
+ * DpdkDevice#receivePackets() methods to get packets from the DpdkDevice
+ * - by setting a callback which is invoked each time a burst of packets arrives. For more details see
+ * DpdkDevice#startCaptureSingleThread()
+ *
+ * __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()<BR>
+ *
+ * __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<BR>
+ *
+ * __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
+ */
+ class DpdkDevice : public IPcapDevice
+ {
+ friend class DpdkDeviceList;
+ friend class MBufRawPacket;
+ public:
+
+ /**
+ * @struct DpdkDeviceConfiguration
+ * A struct that contains user configurable parameters for opening a DpdkDevice. All of these parameters have default values so
+ * the user doesn't have to use these parameters or understand exactly what is their effect
+ */
+ struct DpdkDeviceConfiguration
+ {
+ /**
+ * When configuring a DPDK RX queue, DPDK creates descriptors it will use for receiving packets from the network to this RX queue.
+ * This parameter enables to configure the number of descriptors that will be created for each RX queue
+ */
+ uint16_t receiveDescriptorsNumber;
+
+ /**
+ * When configuring a DPDK TX queue, DPDK creates descriptors it will use for transmitting packets to the network through this TX queue.
+ * This parameter enables to configure the number of descriptors that will be created for each TX queue
+ */
+ uint16_t transmitDescriptorsNumber;
+
+ /**
+ * A c'tor for this strcut
+ * @param[in] receiveDescriptorsNumber An optional parameter for defining the number of RX descriptors that will be allocated for each RX queue.
+ * Default value is 128
+ * @param[in] transmitDescriptorsNumber An optional parameter for defining the number of TX descriptors that will be allocated for each TX queue.
+ * Default value is 512
+ */
+ DpdkDeviceConfiguration(uint16_t receiveDescriptorsNumber = 128, uint16_t transmitDescriptorsNumber = 512)
+ {
+ this->receiveDescriptorsNumber = receiveDescriptorsNumber;
+ this->transmitDescriptorsNumber = transmitDescriptorsNumber;
+ }
+ };
+
+ /**
+ * @struct LinkStatus
+ * A struct that contains the link status of a DpdkDevice (DPDK port). Returned from DpdkDevice#getLinkStatus()
+ */
+ struct LinkStatus
+ {
+ /** Enum for describing link duplex */
+ enum LinkDuplex
+ {
+ /** Full duplex */
+ FULL_DUPLEX,
+ /** Half duplex */
+ HALF_DUPLEX
+ };
+
+ /** True if link is up, false if it's down */
+ bool linkUp;
+ /** Link speed in Mbps (for example: 10Gbe will show 10000) */
+ int linkSpeedMbps;
+ /** Link duplex (half/full duplex) */
+ LinkDuplex linkDuplex;
+ };
+
+ virtual ~DpdkDevice() {}
+
+ /**
+ * @return The device ID (DPDK port ID)
+ */
+ inline int getDeviceId() { return m_Id; }
+ /**
+ * @return The device name which is in the format of 'DPDK_[PORT-ID]'
+ */
+ inline std::string getDeviceName() { return std::string(m_DeviceName); }
+
+ /**
+ * @return The MAC address of the device (DPDK port)
+ */
+ inline MacAddress getMacAddress() { return m_MacAddress; }
+
+ /**
+ * @return 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
+ */
+ inline std::string getPMDName() { return m_PMDName; }
+
+ /**
+ * @return 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
+ */
+ inline DpdkPMDType getPMDType() { return m_PMDType; }
+
+ /**
+ * @return The PCI address of the device
+ */
+ inline PciAddress getPciAddress() { return m_PciAddress; }
+
+ /**
+ * @return The device's maximum transmission unit (MTU) in bytes
+ */
+ inline uint16_t getMtu() { return m_DeviceMtu; }
+
+ /**
+ * Set a new maximum transmission unit (MTU) for this device
+ * @param[in] newMtu The new MTU in bytes
+ * @return True if MTU was set successfully, false if operation failed or if PMD doesn't support changing the MTU
+ */
+ bool setMtu(uint16_t newMtu);
+
+ /**
+ * @return True if this device is a virtual interface (such as VMXNET3, 1G/10G virtual function, etc.), false otherwise
+ */
+ bool isVirtual();
+
+ /**
+ * Get the link status (link up/down, link speed and link duplex)
+ * @param[out] linkStatus A reference to object the result shall be written to
+ */
+ void getLinkStatus(LinkStatus& linkStatus);
+
+ /**
+ * @return The core ID used in this context
+ */
+ uint32_t getCurrentCoreId();
+
+ /**
+ * @return The number of RX queues currently opened for this device (as configured in openMultiQueues() )
+ */
+ uint16_t getNumOfOpenedRxQueues() { return m_NumOfRxQueuesOpened; }
+
+ /**
+ * @return The number of TX queues currently opened for this device (as configured in openMultiQueues() )
+ */
+ uint16_t getNumOfOpenedTxQueues() { return m_NumOfTxQueuesOpened; }
+
+ /**
+ * @return The total number of RX queues available on this device
+ */
+ uint16_t getTotalNumOfRxQueues() { return m_TotalAvailableRxQueues; }
+
+ /**
+ * @return The total number of TX queues available on this device
+ */
+ uint16_t getTotalNumOfTxQueues() { return m_TotalAvailableTxQueues; }
+
+
+ /**
+ * Receive raw packets from the network
+ * @param[out] rawPacketsArr A vector where all received packets will be written into
+ * @param[in] rxQueueId The RX queue to receive packets from
+ * @return 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 receivePackets(RawPacketVector& rawPacketsArr, uint16_t rxQueueId);
+
+ /**
+ * Receive raw packets from the network
+ * @param[out] rawPacketsArr A 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
+ * @param[out] rawPacketArrLength The length of MBufRawPacket pointers array will be written into
+ * @param[in] rxQueueId The RX queue to receive packets from
+ * @return 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 receivePackets(MBufRawPacket** rawPacketsArr, int& rawPacketArrLength, uint16_t rxQueueId);
+
+ /**
+ * Receive parsed packets from the network
+ * @param[out] packetsArr A 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
+ * @param[out] packetsArrLength The length of Packet pointers array will be written into
+ * @param[in] rxQueueId The RX queue to receive packets from
+ * @return 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 receivePackets(Packet** packetsArr, int& packetsArrLength, uint16_t rxQueueId);
+
+ /**
+ * Send an array of raw packets to the network.<BR><BR>
+ * 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
+ * @param[in] rawPacketsArr A pointer to an array of raw packets
+ * @param[in] arrLength The length of the array
+ * @param[in] txQueueId An optional parameter which indicates to which TX queue the packets will be sent to. The default is
+ * TX queue 0
+ * @return The number of packets successfully sent. If device is not opened or TX queue isn't open, 0 will be returned
+ */
+ int sendPackets(const RawPacket* rawPacketsArr, int arrLength, uint16_t txQueueId = 0);
+
+ /**
+ * Send an array of parsed packets to the network. For the send packets algorithm see sendPackets()
+ * @param[in] packetsArr A pointer to an array of parsed packet pointers
+ * @param[in] arrLength The length of the array
+ * @param[in] txQueueId An optional parameter which indicates to which TX queue the packets will be sent to. The default is
+ * TX queue 0
+ * @return The number of packets successfully sent. If device is not opened or TX queue isn't open, 0 will be returned
+ */
+ int sendPackets(const Packet** packetsArr, int arrLength, uint16_t txQueueId = 0);
+
+ /**
+ * Send a vector of raw packets to the network. For the send packets algorithm see sendPackets()
+ * @param[in] rawPacketsVec The vector of raw packet
+ * @param[in] txQueueId An optional parameter which indicates to which TX queue the packets will be sent to. The default is
+ * TX queue 0
+ * @return The number of packets successfully sent. If device is not opened or TX queue isn't open, 0 will be returned
+ */
+ int sendPackets(const RawPacketVector& rawPacketsVec, 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
+ * @param[in] packetData The packet raw data to send
+ * @param[in] packetDataLength The length of the raw data
+ * @param[in] txQueueId An optional parameter which indicates to which TX queue the packet will be sent to. The default is
+ * TX queue 0
+ * @return 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 sendPacket(const uint8_t* packetData, int packetDataLength, 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
+ * @param[in] rawPacket The raw packet to send
+ * @param[in] txQueueId An optional parameter which indicates to which TX queue the packet will be sent to. The default is
+ * TX queue 0
+ * @return 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 sendPacket(const RawPacket& rawPacket, 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
+ * @param[in] packet The parsed packet to send
+ * @param[in] txQueueId An optional parameter which indicates to which TX queue the packet will be sent on. The default is
+ * TX queue 0
+ * @return 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 sendPacket(const Packet& packet, uint16_t txQueueId = 0);
+
+ /**
+ * Overridden method from IPcapDevice. __BPF filters are currently not implemented for DpdkDevice__
+ * @return Always false with a "Filters aren't supported in DPDK device" error message
+ */
+ bool setFilter(GeneralFilter& filter);
+
+ /**
+ * Overridden method from IPcapDevice. __BPF filters are currently not implemented for DpdkDevice__
+ * @return Always false with a "Filters aren't supported in DPDK device" error message
+ */
+ bool setFilter(std::string filterAsString);
+
+ /**
+ * 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
+ * @param[in] numOfRxQueuesToOpen Number of RX queues to setup. This number must be smaller or equal to the return value of getTotalNumOfRxQueues()
+ * @param[in] numOfTxQueuesToOpen Number of TX queues to setup. This number must be smaller or equal to the return value of getTotalNumOfTxQueues()
+ * @param[in] config Optional 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)
+ * @return 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 openMultiQueues(uint16_t numOfRxQueuesToOpen, uint16_t numOfTxQueuesToOpen, const DpdkDeviceConfiguration& config = DpdkDeviceConfiguration());
+
+ /**
+ * 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
+ * @param[in] onPacketsArrive The user callback which will be invoked each time a packet burst is captured by the device
+ * @param[in] onPacketsArriveUserCookie The user callback is invoked with this cookie as a parameter. It can be used to pass
+ * information from the user application to the callback
+ * @return 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
+ */
+ bool startCaptureSingleThread(OnDpdkPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie);
+
+ /**
+ * 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
+ * @param[in] onPacketsArrive The user callback which will be invoked each time a burst of packets is captured by the device
+ * @param[in] onPacketsArriveUserCookie The user callback is invoked with this cookie as a parameter. It can be used to pass
+ * information from the user application to the callback
+ * @param coreMask The core-mask for creating the cpature threads
+ * @return 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 startCaptureMultiThreads(OnDpdkPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie, CoreMask coreMask);
+
+ /**
+ * 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
+ */
+ void stopCapture();
+
+ /**
+ * @return The number of free mbufs in device's mbufs pool
+ */
+ int getAmountOfFreeMbufs();
+
+ /**
+ * @return The number of mbufs currently in use in device's mbufs pool
+ */
+ int getAmountOfMbufsInUse();
+
+ //overridden methods
+
+ /**
+ * 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
+ * @return 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 open() { return openMultiQueues(1, 1); };
+
+ /**
+ * Close the DpdkDevice. When device is closed it's not possible work with it
+ */
+ void close();
+
+ /**
+ * 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
+ */
+ void getStatistics(pcap_stat& stats);
+
+ private:
+
+ struct DpdkCoreConfiguration
+ {
+ int RxQueueId;
+ bool IsCoreInUse;
+
+ void clear() { RxQueueId = -1; IsCoreInUse = false; }
+
+ DpdkCoreConfiguration() : RxQueueId(-1), IsCoreInUse(false) {}
+ };
+
+ DpdkDevice(int port, uint32_t mBufPoolSize);
+ bool initMemPool(struct rte_mempool*& memPool, const char* mempoolName, uint32_t mBufPoolSize);
+
+ bool configurePort(uint8_t numOfRxQueues, uint8_t numOfTxQueues);
+ bool initQueues(uint8_t numOfRxQueuesToInit, uint8_t numOfTxQueuesToInit);
+ bool startDevice();
+
+ static int dpdkCaptureThreadMain(void *ptr);
+
+ void clearCoreConfiguration();
+ bool initCoreConfigurationByCoreMask(CoreMask coreMask);
+ int getCoresInUseCount();
+
+ void setDeviceInfo();
+
+ typedef RawPacket* (*packetIterator)(void* packetStorage, int index);
+ int sendPacketsInner(uint16_t txQueueId, void* packetStorage, packetIterator iter, int arrLength);
+
+ char m_DeviceName[30];
+ DpdkPMDType m_PMDType;
+ std::string m_PMDName;
+ PciAddress m_PciAddress;
+
+ DpdkDeviceConfiguration m_Config;
+
+ int m_Id;
+ MacAddress m_MacAddress;
+ uint16_t m_DeviceMtu;
+ struct rte_mempool* m_MBufMempool;
+ struct rte_mbuf* m_mBufArray[256];
+ DpdkCoreConfiguration m_CoreConfiguration[MAX_NUM_OF_CORES];
+ uint16_t m_TotalAvailableRxQueues;
+ uint16_t m_TotalAvailableTxQueues;
+ uint16_t m_NumOfRxQueuesOpened;
+ uint16_t m_NumOfTxQueuesOpened;
+ OnDpdkPacketsArriveCallback m_OnPacketsArriveCallback;
+ void* m_OnPacketsArriveUserCookie;
+ bool m_StopThread;
+
+ bool m_WasOpened;
+
+ // RSS key used by the NIC for load balancing the packets between cores
+ static uint8_t m_RSSKey[40];
+ };
+
+} // namespace pcpp
+
+#endif /* PCAPPP_DPDK_DEVICE */
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c0a788b3/thirdparty/pcap++/Pcap++/header/DpdkDeviceList.h
----------------------------------------------------------------------
diff --git a/thirdparty/pcap++/Pcap++/header/DpdkDeviceList.h b/thirdparty/pcap++/Pcap++/header/DpdkDeviceList.h
new file mode 100644
index 0000000..8a7b8fd
--- /dev/null
+++ b/thirdparty/pcap++/Pcap++/header/DpdkDeviceList.h
@@ -0,0 +1,198 @@
+#ifndef PCAPPP_DPDK_DEVICE_LIST
+#define PCAPPP_DPDK_DEVICE_LIST
+
+#include <SystemUtils.h>
+#include <DpdkDevice.h>
+#include <Logger.h>
+#include <vector>
+
+/**
+ * @file
+ * For details about PcapPlusPlus support for DPDK see DpdkDevice.h file description
+ */
+
+/**
+* \namespace pcpp
+* \brief The main namespace for the PcapPlusPlus lib
+*/
+namespace pcpp
+{
+
+ /**
+ * @class DpdkWorkerThread
+ * There are two ways to capture packets using DpdkDevice: one of them is using worker threads and the other way is using
+ * a callback which is invoked on each a burst of packets are captured (see DpdkDevice#startCaptureSingleThread() ). This class
+ * is a base class for implementing workers. A worker is basically a class that is activated by DpdkDeviceList#startDpdkWorkerThreads()
+ * and runs on a designated core. When it runs it can do whatever the user wants it to do. The most common use it running in an
+ * endless loop and receive, analyze and send packets using one or more DpdkDevice instances. It can do all kinds of processing for
+ * these packets. The only restriction for a worker class is that it must implement the 3 abstract methods stated in this class-interface
+ * for start running, stop running and get the core ID the worker is running on.
+ */
+ class DpdkWorkerThread
+ {
+ public:
+ /**
+ * A virtual d'tor. Can be overridden by child class if needed
+ */
+ virtual ~DpdkWorkerThread() {}
+
+ /**
+ * An abstract method that must be implemented by child class. It's the indication for the worker to start running
+ * @param[in] coreId The core ID the worker is running on (should be returned in getCoreId() )
+ * @return True if all went well or false otherwise
+ */
+ virtual bool run(uint32_t coreId) = 0;
+
+ /**
+ * An abstract method that must be implemented by child class. It's the indication for the worker to stop running. After
+ * this method is called the caller expects the worker to stop running as fast as possible
+ */
+ virtual void stop() = 0;
+
+ /**
+ * An abstract method that must be implemented by child class. Get the core ID the worker is running on (as sent to the run() method
+ * as a parameter)
+ * @return The core ID the worker is running on
+ */
+ virtual uint32_t getCoreId() = 0;
+ };
+
+
+ /**
+ * @class DpdkDeviceList
+ * A singleton class that encapsulates DPDK initialization and holds the list of DpdkDevice instances. As it's a singleton, it has only
+ * one active instance doesn't have a public c'tor. This class has several main uses:
+ * - it contains the initDpdk() static method which initializes the DPDK infrastructure. It should be called once in every application at
+ * its startup process
+ * - it contains the list of DpdkDevice instances and enables access to them
+ * - it has methods to start and stop worker threads. See more details in startDpdkWorkerThreads()
+ */
+ class DpdkDeviceList
+ {
+ private:
+ bool m_IsInitialized;
+ static bool m_IsDpdkInitialized;
+ static uint32_t m_MBufPoolSizePerDevice;
+ static CoreMask m_CoreMask;
+ std::vector<DpdkDevice*> m_DpdkDeviceList;
+ std::vector<DpdkWorkerThread*> m_WorkerThreads;
+
+ DpdkDeviceList();
+
+ inline bool isInitialized() { return (m_IsInitialized && m_IsDpdkInitialized); }
+ bool initDpdkDevices(uint32_t mBufPoolSizePerDevice);
+ static bool verifyHugePagesAndDpdkDriver();
+
+ static int dpdkWorkerThreadStart(void *ptr);
+ public:
+
+ ~DpdkDeviceList();
+
+ /**
+ * As DpdkDeviceList is a singleton, this is the static getter to retrieve its instance. Note that if the static method
+ * initDpdk() was not called or returned false this instance won't be initialized and DpdkDevices won't be initialized either
+ * @return The singleton instance of DpdkDeviceList
+ */
+ static inline DpdkDeviceList& getInstance()
+ {
+ static DpdkDeviceList instance;
+ if (!instance.isInitialized())
+ instance.initDpdkDevices(DpdkDeviceList::m_MBufPoolSizePerDevice);
+
+ return instance;
+ }
+
+ /**
+ * A static method that has to be called once at the startup of every application that uses DPDK. It does several things:
+ * - verifies huge-pages are set and DPDK kernel module is loaded (these are set by the setup-dpdk.sh external script that
+ * has to be run before application is started)
+ * - initializes the DPDK infrastructure
+ * - creates DpdkDevice instances for all ports available for DPDK
+ *
+ * @param[in] coreMask The cores to initialize DPDK with. After initialization, DPDK will only be able to use these cores
+ * for its work. The core mask should have a bit set for every core to use. For example: if the user want to use cores 1,2
+ * the core mask should be 6 (binary: 110)
+ * @param[in] mBufPoolSizePerDevice The mbuf pool size each DpdkDevice will have. This has to be a number which is a power of 2
+ * minus 1, for example: 1023 (= 2^10-1) or 4,294,967,295 (= 2^32-1), etc. This is a DPDK limitation, not PcapPlusPlus.
+ * The size of the mbuf pool size dictates how many packets can be handled by the application at the same time. For example: if
+ * pool size is 1023 it means that no more than 1023 packets can be handled or stored in application memory at every point in time
+ * @return True if initialization succeeded or false if huge-pages or DPDK kernel driver are not loaded, if mBufPoolSizePerDevice
+ * isn't power of 2 minus 1, if DPDK infra initialization failed or if DpdkDevice initialization failed. Anyway, if this method
+ * returned false it's impossible to use DPDK with PcapPlusPlus. You can get some more details about mbufs and pools in
+ * DpdkDevice.h file description or in DPDK web site
+ */
+ static bool initDpdk(CoreMask coreMask, uint32_t mBufPoolSizePerDevice);
+
+ /**
+ * Get a DpdkDevice by port ID
+ * @param[in] portId The port ID
+ * @return A pointer to the DpdkDevice or NULL if no such device is found
+ */
+ DpdkDevice* getDeviceByPort(int portId);
+
+ /**
+ * Get a DpdkDevice by port PCI address
+ * @param[in] pciAddr The port PCI address
+ * @return A pointer to the DpdkDevice or NULL if no such device is found
+ */
+ DpdkDevice* getDeviceByPciAddress(const PciAddress& pciAddr);
+
+ /**
+ * @return A vector of all DpdkDevice instances
+ */
+ inline const std::vector<DpdkDevice*>& getDpdkDeviceList() { return m_DpdkDeviceList; }
+
+ /**
+ * @return DPDK master core which is the core that initializes the application
+ */
+ SystemCore getDpdkMasterCore();
+
+ /**
+ * Change the log level of all modules of DPDK
+ * @param[in] logLevel The log level to set. LoggerPP#Normal is RTE_LOG_NOTICE and LoggerPP#Debug is RTE_LOG_DEBUG
+ */
+ void setDpdkLogLevel(LoggerPP::LogLevel logLevel);
+
+ /**
+ * @return The current DPDK log level. RTE_LOG_NOTICE and lower are considered as LoggerPP#Normal. RTE_LOG_INFO or RTE_LOG_DEBUG
+ * are considered as LoggerPP#Debug
+ */
+ LoggerPP::LogLevel getDpdkLogLevel();
+
+ /**
+ * Order DPDK to write all its logs to a file
+ * @param[in] logFile The file to write to
+ * @return True if action succeeded, false otherwise
+ */
+ bool writeDpdkLogToFile(FILE* logFile);
+
+ /**
+ * There are two ways to capture packets using DpdkDevice: one of them is using worker threads and the other way is setting
+ * a callback which is invoked each time a burst of packets is captured (see DpdkDevice#startCaptureSingleThread() ). This
+ * method implements the first way. See a detailed description of workers in DpdkWorkerThread class description. This method
+ * gets a vector of workers (classes that implement the DpdkWorkerThread interface) and a core mask and starts a worker thread
+ * on each core (meaning - call the worker's DpdkWorkerThread#run() method). Workers usually run in an endless loop and will
+ * be ordered to stop by calling stopDpdkWorkerThreads().<BR>
+ * Note that number of cores in the core mask must be equal to the number of workers. In addition it's impossible to run a
+ * worker thread on DPDK master core, so the core mask shouldn't include the master core (you can find the master core by
+ * calling getDpdkMasterCore() ).
+ * @param[in] coreMask The bitmask of cores to run worker threads on. This list shouldn't include DPDK master core
+ * @param[in] workerThreadsVec A vector of worker instances to run (classes who implement the DpdkWorkerThread interface).
+ * Number of workers in this vector must be equal to the number of cores in the core mask. Notice that the instances of
+ * DpdkWorkerThread shouldn't be freed until calling stopDpdkWorkerThreads() as these instances are running
+ * @return True if all worker threads started successfully or false if: DPDK isn't initialized (initDpdk() wasn't called or
+ * returned false), number of cores differs from number of workers, core mask includes DPDK master core or if one of the
+ * worker threads couldn't be run
+ */
+ bool startDpdkWorkerThreads(CoreMask coreMask, std::vector<DpdkWorkerThread*>& workerThreadsVec);
+
+ /**
+ * Assuming worker threads are running, this method orders them to stop by calling DpdkWorkerThread#stop(). Then it waits until
+ * they stop running
+ */
+ void stopDpdkWorkerThreads();
+ };
+
+} // namespace pcpp
+
+#endif /* PCAPPP_DPDK_DEVICE_LIST */
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c0a788b3/thirdparty/pcap++/Pcap++/header/NetworkUtils.h
----------------------------------------------------------------------
diff --git a/thirdparty/pcap++/Pcap++/header/NetworkUtils.h b/thirdparty/pcap++/Pcap++/header/NetworkUtils.h
new file mode 100644
index 0000000..15aec85
--- /dev/null
+++ b/thirdparty/pcap++/Pcap++/header/NetworkUtils.h
@@ -0,0 +1,90 @@
+#ifndef PCAPPP_NETWORK_UTILS
+#define PCAPPP_NETWORK_UTILS
+
+#include "MacAddress.h"
+#include "IpAddress.h"
+#include "PcapLiveDevice.h"
+
+
+/// @file
+
+/**
+* \namespace pcpp
+* \brief The main namespace for the PcapPlusPlus lib
+*/
+namespace pcpp
+{
+
+ /**
+ * @class NetworkUtils
+ * This class bundles several network utilities that are very common and useful. These utilities use Pcap++ and Packet++ packet
+ * crafting and processing capabilities. This class is a singleton and can be access by getInstance() only
+ */
+ class NetworkUtils
+ {
+ public:
+
+ /**
+ * The access method to the singleton
+ * @return The singleton instance of this class
+ */
+ static NetworkUtils& getInstance()
+ {
+ static NetworkUtils instance;
+ return instance;
+ }
+
+ /**
+ * Default timeout used for several utilities. Currently set to 5 seconds
+ */
+ static const int DefaultTimeout;
+
+ /**
+ * Resolve the MAC address for a given IPv4 address. It's done using the ARP protocol: send an ARP request and interpret the response
+ * @param[in] ipAddr The IPv4 address to resolve MAC address to
+ * @param[in] device The interface to send and receive the ARP packets on
+ * @param[out] arpResponseTimeMS An output parameter that will contain the time in milliseconds that took the ARP response to arrive
+ * @param[in] sourceMac An optional parameter to set the source MAC address that will be sent with the ARP request
+ * if this parameter isn't set or set with MacAddress#Zero the MAC address of the interface will be used
+ * @param[in] sourceIP An optional parameter to set the source IPv4 address that will be sent with the ARP request
+ * if this parameter isn't set or set with IPv4Address#Zero the default IPv4 address of the interface will be used
+ * @param[in] arpTimeout An optional parameter to set the timeout to wait for the ARP response to return.
+ * If this parameter isn't set or set with a number smaller than 0, a default timeout of 5 seconds will be set
+ * @return The resolved MAC address or MacAddress#Zero if an error occurred or address could not be resolved. Errors will be printed
+ * to log
+ */
+ MacAddress getMacAddress(IPv4Address ipAddr, PcapLiveDevice* device, double& arpResponseTimeMS,
+ MacAddress sourceMac = MacAddress::Zero, IPv4Address sourceIP = IPv4Address::Zero, int arpTimeout = -1);
+
+
+ /**
+ * Resolve an IPv4 address for a given hostname. Resolving is done in multiple phases: first resolving the LAN gateway MAC address
+ * (or default gateway if a gateway isn't provided) using ARP protocol (by using NetworkUtils#getMacAddress() ). Then a DNS request
+ * is sent to a DNS server (if specified) or to the LAN gateway (if DNS server is not specified). The DNS response is decoded and
+ * the IPv4 address is determined. In addition the method outputs the time it took the DNS response to arrive and the DNS TTL
+ * written on the DNS response. If DNS response doesn't contain an IPv4 address resolving an IPv4Address#Zero will be returned.
+ * @param[in] hostname The hostname to resolve
+ * @param[in] device The interface to send and receive packets on
+ * @param[out] dnsResponseTimeMS When method returns successfully will contain the time it took to receive the DNS response
+ * (in milli-seconds)
+ * @param[out] dnsTTL When method returns successfully will contain The DNS TTL written in the DNS response
+ * @param[in] dnsTimeout An optional parameter to specify the timeout to wait for a DNS response. If not specified the default timeout
+ * is 5 sec
+ * @param[in] dnsServerIP An optional parameter to specify the DNS server IP to send the DNS request to. If not specified
+ * or specified with IPv4Address#Zero the DNS request will be sent to the default DNS server configured in the system
+ * @param[in] gatewayIP An optional parameter to specify the LAN gateway to send the DNS request through. If not specified
+ * or specified with IPv4Address#Zero the interface's default gateway will be used
+ * @return The resolved IPv4 address or IPv4Address#Zero if something went wrong (in this case an error will be printed to log)
+ */
+ IPv4Address getIPv4Address(std::string hostname, PcapLiveDevice* device, double& dnsResponseTimeMS, uint32_t& dnsTTL,
+ int dnsTimeout = -1, IPv4Address dnsServerIP = IPv4Address::Zero, IPv4Address gatewayIP = IPv4Address::Zero);
+
+ private:
+
+ // private c'tor
+ NetworkUtils() {}
+ };
+
+} // namespace pcpp
+
+#endif /* PCAPPP_NETWORK_UTILS */
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c0a788b3/thirdparty/pcap++/Pcap++/header/PcapDevice.h
----------------------------------------------------------------------
diff --git a/thirdparty/pcap++/Pcap++/header/PcapDevice.h b/thirdparty/pcap++/Pcap++/header/PcapDevice.h
new file mode 100644
index 0000000..3cb4ff9
--- /dev/null
+++ b/thirdparty/pcap++/Pcap++/header/PcapDevice.h
@@ -0,0 +1,101 @@
+#ifndef PCAPPP_DEVICE
+#define PCAPPP_DEVICE
+
+#include <RawPacket.h>
+#include <PcapFilter.h>
+#include <PointerVector.h>
+#include <pcap.h>
+
+/// @file
+
+/**
+* \namespace pcpp
+* \brief The main namespace for the PcapPlusPlus lib
+*/
+namespace pcpp
+{
+
+ /** A vector of pointers to RawPacket */
+ typedef PointerVector<RawPacket> RawPacketVector;
+
+ /**
+ * @class IPcapDevice
+ * An abstract class representing all possible packet capturing devices: files, libPcap, WinPcap, RemoteCapture, PF_RING, etc.
+ * This class cannot obviously be instantiated
+ */
+ class IPcapDevice
+ {
+ protected:
+ pcap_t* m_PcapDescriptor;
+ bool m_DeviceOpened;
+
+ // c'tor should not be public
+ IPcapDevice() { m_DeviceOpened = false; m_PcapDescriptor = NULL; }
+
+ public:
+ virtual ~IPcapDevice();
+
+ /**
+ * Open the device
+ * @return True if device was opened successfully, false otherwise
+ */
+ virtual bool open() = 0;
+
+ /**
+ * Close the device
+ */
+ virtual void close() = 0;
+
+ /**
+ * @return True if the file is opened, false otherwise
+ */
+ inline bool isOpened() { return m_DeviceOpened; }
+
+ /**
+ * Get statistics from device:
+ * - pcap_stat#ps_recv: number of packets received
+ * - pcap_stat#ps_drop: number of packets dropped
+ * - pcap_stat#ps_ifdorp: number of packets dropped by interface
+ * @param[out] stats The stats struct where stats are returned
+ */
+ virtual void getStatistics(pcap_stat& stats) = 0;
+
+ /**
+ * Set a filter for the device. When implemented by the device, only packets that match the filter will be received
+ * @param[in] filter The filter to be set in PcapPlusPlus' GeneralFilter format
+ * @return True if filter set successfully, false otherwise
+ */
+ bool setFilter(GeneralFilter& filter);
+
+ /**
+ * Set a filter for the device. When implemented by the device, only packets that match the filter will be received
+ * @param[in] filterAsString The filter to be set in Berkeley Packet Filter (BPF) syntax (http://biot.com/capstats/bpf.html)
+ * @return True if filter set successfully, false otherwise
+ */
+ virtual bool setFilter(std::string filterAsString);
+
+ /**
+ * Clear the filter currently set on device
+ */
+ void clearFilter();
+
+ /**
+ * Verify a filter is valid
+ * @param[in] filterAsString The filter in Berkeley Packet Filter (BPF) syntax (http://biot.com/capstats/bpf.html)
+ * @return True if the filter is valid or false otherwise
+ */
+ static bool verifyFilter(std::string filterAsString);
+
+ /**
+ * Match a raw packet with a given BPF filter. Notice this method is static which means you don't need any device instance
+ * in order to perform this match
+ * @param[in] filterAsString The BPF filter
+ * @param[in] rawPacket A pointer to the raw packet to match the BPF filter with
+ * @return True if raw packet matches the BPF filter or false otherwise
+ */
+ static bool matchPakcetWithFilter(std::string filterAsString, RawPacket* rawPacket);
+ };
+
+} // namespace pcpp
+
+#endif
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c0a788b3/thirdparty/pcap++/Pcap++/header/PcapFileDevice.h
----------------------------------------------------------------------
diff --git a/thirdparty/pcap++/Pcap++/header/PcapFileDevice.h b/thirdparty/pcap++/Pcap++/header/PcapFileDevice.h
new file mode 100644
index 0000000..337ae58
--- /dev/null
+++ b/thirdparty/pcap++/Pcap++/header/PcapFileDevice.h
@@ -0,0 +1,480 @@
+#ifndef PCAPPP_FILE_DEVICE
+#define PCAPPP_FILE_DEVICE
+
+#include <PcapDevice.h>
+#include <RawPacket.h>
+
+/// @file
+
+/**
+* \namespace pcpp
+* \brief The main namespace for the PcapPlusPlus lib
+*/
+namespace pcpp
+{
+
+ /**
+ * @class IFileDevice
+ * An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for all file devices
+ */
+ class IFileDevice : public IPcapDevice
+ {
+ protected:
+ char* m_FileName;
+
+ IFileDevice(const char* fileName);
+ virtual ~IFileDevice();
+
+ public:
+
+ /**
+ * @return The name of the file
+ */
+ std::string getFileName();
+
+
+ //override methods
+
+ /**
+ * Close the file
+ */
+ virtual void close();
+ };
+
+
+ /**
+ * @class IFileReaderDevice
+ * An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for file reader devices
+ */
+ class IFileReaderDevice : public IFileDevice
+ {
+ protected:
+ uint32_t m_NumOfPacketsRead;
+ uint32_t m_NumOfPacketsNotParsed;
+
+ /**
+ * A constructor for this class that gets the pcap full path file name to open. Notice that after calling this constructor the file
+ * isn't opened yet, so reading packets will fail. For opening the file call open()
+ * @param[in] fileName The full path of the file to read
+ */
+ IFileReaderDevice(const char* fileName);
+
+ public:
+
+ /**
+ * A destructor for this class
+ */
+ virtual ~IFileReaderDevice() {}
+
+ /**
+ * @return The file size in bytes
+ */
+ uint64_t getFileSize();
+
+ virtual bool getNextPacket(RawPacket& rawPacket) = 0;
+
+ /**
+ * A static method that creates an instance of the reader best fit to read the file. It decides by the file extension: for .pcapng
+ * files it returns an instance of PcapNgFileReaderDevice and for all other extensions it returns an instance of PcapFileReaderDevice
+ * @param[in] fileName The file name to open
+ * @return An instance of the reader to read the file. Notice you should free this instance when done using it
+ */
+ static IFileReaderDevice* getReader(const char* fileName);
+ };
+
+
+ /**
+ * @class PcapFileReaderDevice
+ * A class for opening a pcap file in read-only mode. This class enable to open the file and read all packets, packet-by-packet
+ */
+ class PcapFileReaderDevice : public IFileReaderDevice
+ {
+ private:
+ LinkLayerType m_PcapLinkLayerType;
+
+ // private copy c'tor
+ PcapFileReaderDevice(const PcapFileReaderDevice& other);
+ PcapFileReaderDevice& operator=(const PcapFileReaderDevice& other);
+
+ public:
+ /**
+ * A constructor for this class that gets the pcap full path file name to open. Notice that after calling this constructor the file
+ * isn't opened yet, so reading packets will fail. For opening the file call open()
+ * @param[in] fileName The full path of the file to read
+ */
+ PcapFileReaderDevice(const char* fileName);
+
+ /**
+ * A destructor for this class
+ */
+ virtual ~PcapFileReaderDevice() {}
+
+ /**
+ * @return The link layer type of this file
+ */
+ LinkLayerType getLinkLayerType();
+
+
+ //overridden methods
+
+ /**
+ * Read the next packet from the file. Before using this method please verify the file is opened using open()
+ * @param[out] rawPacket A reference for an empty RawPacket where the packet will be written
+ * @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an error log will be printed)
+ * or if reached end-of-file
+ */
+ bool getNextPacket(RawPacket& rawPacket);
+
+ /**
+ * Open the file name which path was specified in the constructor in a read-only mode
+ * @return True if file was opened successfully or if file is already opened. False if opening the file failed for some reason (for example:
+ * file path does not exist)
+ */
+ bool open();
+
+ /**
+ * Get statistics of packets read so far. In the pcap_stat struct, only ps_recv member is relevant. The rest of the members will contain 0
+ * @param[out] stats The stats struct where stats are returned
+ */
+ void getStatistics(pcap_stat& stats);
+ };
+
+
+ /**
+ * @class PcapNgFileReaderDevice
+ * A class for opening a pcap-ng file in read-only mode. This class enable to open the file and read all packets, packet-by-packet
+ */
+ class PcapNgFileReaderDevice : public IFileReaderDevice
+ {
+ private:
+ void* m_LightPcapNg;
+ struct bpf_program m_Bpf;
+ bool m_BpfInitialized;
+ int m_BpfLinkType;
+ std::string m_CurFilter;
+
+ // private copy c'tor
+ PcapNgFileReaderDevice(const PcapNgFileReaderDevice& other);
+ PcapNgFileReaderDevice& operator=(const PcapNgFileReaderDevice& other);
+
+ bool matchPacketWithFilter(const uint8_t* packetData, size_t packetLen, timeval packetTimestamp, uint16_t linkType);
+
+ public:
+ /**
+ * A constructor for this class that gets the pcap-ng full path file name to open. Notice that after calling this constructor the file
+ * isn't opened yet, so reading packets will fail. For opening the file call open()
+ * @param[in] fileName The full path of the file to read
+ */
+ PcapNgFileReaderDevice(const char* fileName);
+
+ /**
+ * A destructor for this class
+ */
+ virtual ~PcapNgFileReaderDevice() { close(); }
+
+ /**
+ * The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string specifying the
+ * operating system that was used for capturing the packets. This method reads this string from the metadata (if exists) and
+ * returns it
+ * @return The operating system string if exists, or an empty string otherwise
+ */
+ std::string getOS();
+
+ /**
+ * The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string specifying the
+ * hardware that was used for capturing the packets. This method reads this string from the metadata (if exists) and
+ * returns it
+ * @return The hardware string if exists, or an empty string otherwise
+ */
+ std::string getHardware();
+
+ /**
+ * The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string specifying the
+ * capture application that was used for capturing the packets. This method reads this string from the metadata (if exists) and
+ * returns it
+ * @return The capture application string if exists, or an empty string otherwise
+ */
+ std::string getCaptureApplication();
+
+ /**
+ * The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string containing a user-defined
+ * comment (can be any string). This method reads this string from the metadata (if exists) and
+ * returns it
+ * @return The comment written inside the file if exists, or an empty string otherwise
+ */
+ std::string getCaptureFileComment();
+
+ /**
+ * The pcap-ng format allows storing a user-defined comment for every packet (besides the comment per-file). This method reads
+ * the next packet and the comment attached to it (if such comment exists), and returns them both
+ * @param[out] rawPacket A reference for an empty RawPacket where the packet will be written
+ * @param[out] packetComment The comment attached to the packet or an empty string if no comment exists
+ * @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an error log will be printed)
+ * or if reached end-of-file
+ */
+ bool getNextPacket(RawPacket& rawPacket, std::string& packetComment);
+
+ //overridden methods
+
+ /**
+ * Read the next packet from the file. Before using this method please verify the file is opened using open()
+ * @param[out] rawPacket A reference for an empty RawPacket where the packet will be written
+ * @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an error log will be printed)
+ * or if reached end-of-file
+ */
+ bool getNextPacket(RawPacket& rawPacket);
+
+ /**
+ * Open the file name which path was specified in the constructor in a read-only mode
+ * @return True if file was opened successfully or if file is already opened. False if opening the file failed for some reason (for example:
+ * file path does not exist)
+ */
+ bool open();
+
+ /**
+ * Get statistics of packets read so far. In the pcap_stat struct, only ps_recv member is relevant. The rest of the members will contain 0
+ * @param[out] stats The stats struct where stats are returned
+ */
+ void getStatistics(pcap_stat& stats);
+
+ /**
+ * Set a filter for PcapNG reader device. Only packets that match the filter will be received
+ * @param[in] filterAsString The filter to be set in Berkeley Packet Filter (BPF) syntax (http://biot.com/capstats/bpf.html)
+ * @return True if filter set successfully, false otherwise
+ */
+ bool setFilter(std::string filterAsString);
+
+ /**
+ * Close the pacp-ng file
+ */
+ void close();
+ };
+
+
+ /**
+ * @class IFileWriterDevice
+ * An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for file writer devices
+ */
+ class IFileWriterDevice : public IFileDevice
+ {
+ protected:
+ uint32_t m_NumOfPacketsWritten;
+ uint32_t m_NumOfPacketsNotWritten;
+
+ IFileWriterDevice(const char* fileName);
+
+ public:
+
+ /**
+ * A destructor for this class
+ */
+ virtual ~IFileWriterDevice() {}
+
+ virtual bool writePacket(RawPacket const& packet) = 0;
+
+ virtual bool writePackets(const RawPacketVector& packets) = 0;
+
+ using IFileDevice::open;
+ virtual bool open(bool appendMode) = 0;
+ };
+
+
+ /**
+ * @class PcapFileWriterDevice
+ * A class for opening a pcap file for writing or create a new pcap file and write packets to it. This class adds
+ * a unique capability that isn't supported in WinPcap and in older libpcap versions which is to open a pcap file
+ * in append mode where packets are written at the end of the pcap file instead of running it over
+ */
+ class PcapFileWriterDevice : public IFileWriterDevice
+ {
+ private:
+ pcap_dumper_t* m_PcapDumpHandler;
+ LinkLayerType m_PcapLinkLayerType;
+ bool m_AppendMode;
+ FILE* m_File;
+
+ // private copy c'tor
+ PcapFileWriterDevice(const PcapFileWriterDevice& other);
+ PcapFileWriterDevice& operator=(const PcapFileWriterDevice& other);
+
+ void closeFile();
+
+ public:
+ /**
+ * A constructor for this class that gets the pcap full path file name to open for writing or create. Notice that after calling this
+ * constructor the file isn't opened yet, so writing packets will fail. For opening the file call open()
+ * @param[in] fileName The full path of the file
+ * @param[in] linkLayerType The link layer type all packet in this file will be based on. The default is Ethernet
+ */
+ PcapFileWriterDevice(const char* fileName, LinkLayerType linkLayerType = LINKTYPE_ETHERNET);
+
+ /**
+ * A destructor for this class
+ */
+ ~PcapFileWriterDevice();
+
+ /**
+ * Write a RawPacket to the file. Before using this method please verify the file is opened using open(). This method won't change the
+ * written packet
+ * @param[in] packet A reference for an existing RawPcket to write to the file
+ * @return True if a packet was written successfully. False will be returned if the file isn't opened
+ * or if the packet link layer type is different than the one defined for the file
+ * (in all cases, an error will be printed to log)
+ */
+ bool writePacket(RawPacket const& packet);
+
+ /**
+ * Write multiple RawPacket to the file. Before using this method please verify the file is opened using open(). This method won't change
+ * the written packets or the RawPacketVector instance
+ * @param[in] packets A reference for an existing RawPcketVector, all of its packets will be written to the file
+ * @return True if all packets were written successfully to the file. False will be returned if the file isn't opened (also, an error
+ * log will be printed) or if at least one of the packets wasn't written successfully to the file
+ */
+ bool writePackets(const RawPacketVector& packets);
+
+ //override methods
+
+ /**
+ * Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be
+ * overwritten, meaning all its current content will be deleted
+ * @return True if file was opened/created successfully or if file is already opened. False if opening the file failed for some reason
+ * (an error will be printed to log)
+ */
+ virtual bool open();
+
+ /**
+ * Same as open(), but enables to open the file in append mode in which packets will be appended to the file
+ * instead of overwrite its current content. In append mode file must exist, otherwise opening will fail
+ * @param[in] appendMode A boolean indicating whether to open the file in append mode or not. If set to false
+ * this method will act exactly like open(). If set to true, file will be opened in append mode
+ * @return True of managed to open the file successfully. In case appendMode is set to true, false will be returned
+ * if file wasn't found or couldn't be read, if file type is not pcap, or if link type specified in c'tor is
+ * different from current file link type. In case appendMode is set to false, please refer to open() for return
+ * values
+ */
+ bool open(bool appendMode);
+
+ /**
+ * Flush and close the pacp file
+ */
+ virtual void close();
+
+ /**
+ * Get statistics of packets written so far. In the pcap_stat struct, only ps_recv member is relevant. The rest of the members will contain 0
+ * @param[out] stats The stats struct where stats are returned
+ */
+ virtual void getStatistics(pcap_stat& stats);
+ };
+
+
+ /**
+ * @class PcapNgFileWriterDevice
+ * A class for opening a pcap-ng file for writing or creating a new pcap-ng file and write packets to it. This class adds
+ * unique capabilities such as writing metadata attributes into the file header, adding comments per packet and opening
+ * the file in append mode where packets are added to a file instead of overriding it. This capabilities are part of the
+ * pcap-ng standard but aren't supported in most tools and libraries
+ */
+ class PcapNgFileWriterDevice : public IFileWriterDevice
+ {
+ private:
+
+ void* m_LightPcapNg;
+
+ // private copy c'tor
+ PcapNgFileWriterDevice(const PcapFileWriterDevice& other);
+ PcapNgFileWriterDevice& operator=(const PcapNgFileWriterDevice& other);
+
+ public:
+
+ /**
+ * A constructor for this class that gets the pcap-ng full path file name to open for writing or create. Notice that after calling this
+ * constructor the file isn't opened yet, so writing packets will fail. For opening the file call open()
+ * @param[in] fileName The full path of the file
+ */
+ PcapNgFileWriterDevice(const char* fileName);
+
+ /**
+ * A destructor for this class
+ */
+ virtual ~PcapNgFileWriterDevice() { close(); }
+
+ /**
+ * Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be
+ * overwritten, meaning all its current content will be deleted. As opposed to open(), this method also allows writing several
+ * metadata attributes that will be stored in the header of the file
+ * @param[in] os A string describing the operating system that was used to capture the packets. If this string is empty or null it
+ * will be ignored
+ * @param[in] hardware A string describing the hardware that was used to capture the packets. If this string is empty or null it
+ * will be ignored
+ * @param[in] captureApp A string describing the application that was used to capture the packets. If this string is empty or null it
+ * will be ignored
+ * @param[in] fileComment A string containing a user-defined comment that will be part of the metadata of the file.
+ * If this string is empty or null it will be ignored
+ * @return True if file was opened/created successfully or if file is already opened. False if opening the file failed for some reason
+ * (an error will be printed to log)
+ */
+ bool open(const char* os, const char* hardware, const char* captureApp, const char* fileComment);
+
+ /**
+ * The pcap-ng format allows adding a user-defined comment for each stored packet. This method writes a RawPacket to the file and
+ * adds a comment to it. Before using this method please verify the file is opened using open(). This method won't change the
+ * written packet or the input comment
+ * @param[in] packet A reference for an existing RawPcket to write to the file
+ * @param[in] comment The comment to be written for the packet. If this string is empty or null it will be ignored
+ * @return True if a packet was written successfully. False will be returned if the file isn't opened (an error will be printed to log)
+ */
+ bool writePacket(RawPacket const& packet, const char* comment);
+
+ //overridden methods
+
+ /**
+ * Write a RawPacket to the file. Before using this method please verify the file is opened using open(). This method won't change the
+ * written packet
+ * @param[in] packet A reference for an existing RawPcket to write to the file
+ * @return True if a packet was written successfully. False will be returned if the file isn't opened (an error will be printed to log)
+ */
+ bool writePacket(RawPacket const& packet);
+
+ /**
+ * Write multiple RawPacket to the file. Before using this method please verify the file is opened using open(). This method won't change
+ * the written packets or the RawPacketVector instance
+ * @param[in] packets A reference for an existing RawPcketVector, all of its packets will be written to the file
+ * @return True if all packets were written successfully to the file. False will be returned if the file isn't opened (also, an error
+ * log will be printed) or if at least one of the packets wasn't written successfully to the file
+ */
+ bool writePackets(const RawPacketVector& packets);
+
+ /**
+ * Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be
+ * overwritten, meaning all its current content will be deleted
+ * @return True if file was opened/created successfully or if file is already opened. False if opening the file failed for some reason
+ * (an error will be printed to log)
+ */
+ bool open();
+
+ /**
+ * Same as open(), but enables to open the file in append mode in which packets will be appended to the file
+ * instead of overwrite its current content. In append mode file must exist, otherwise opening will fail
+ * @param[in] appendMode A boolean indicating whether to open the file in append mode or not. If set to false
+ * this method will act exactly like open(). If set to true, file will be opened in append mode
+ * @return True of managed to open the file successfully. In case appendMode is set to true, false will be returned
+ * if file wasn't found or couldn't be read, if file type is not pcap-ng. In case appendMode is set to false, please refer to open()
+ * for return values
+ */
+ bool open(bool appendMode);
+
+ /**
+ * Flush and close the pacp-ng file
+ */
+ void close();
+
+ /**
+ * Get statistics of packets written so far. In the pcap_stat struct, only ps_recv member is relevant. The rest of the members will contain 0
+ * @param[out] stats The stats struct where stats are returned
+ */
+ void getStatistics(pcap_stat& stats);
+ };
+
+}// namespace pcpp
+
+#endif