219 lines
11 KiB
C++
219 lines
11 KiB
C++
#ifndef PCAPPP_MBUF_RAW_PACKET
|
|
#define PCAPPP_MBUF_RAW_PACKET
|
|
|
|
#include <time.h>
|
|
#include "Packet.h"
|
|
#include "PointerVector.h"
|
|
|
|
struct rte_mbuf;
|
|
struct rte_mempool;
|
|
|
|
/**
|
|
* \namespace pcpp
|
|
* \brief The main namespace for the PcapPlusPlus lib
|
|
*/
|
|
namespace pcpp
|
|
{
|
|
|
|
class DpdkDevice;
|
|
class KniDevice;
|
|
|
|
#define MBUFRAWPACKET_OBJECT_TYPE 1
|
|
|
|
/**
|
|
* @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;
|
|
friend class KniDevice;
|
|
static const int MBUF_DATA_SIZE;
|
|
|
|
protected:
|
|
struct rte_mbuf* m_MBuf;
|
|
struct rte_mempool* m_Mempool;
|
|
bool m_FreeMbuf;
|
|
|
|
void setMBuf(struct rte_mbuf* mBuf, timespec timestamp);
|
|
bool init(struct rte_mempool* mempool);
|
|
bool initFromRawPacket(const RawPacket* rawPacket, struct rte_mempool* mempool);
|
|
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_Mempool(NULL), m_FreeMbuf(true) { 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);
|
|
|
|
/**
|
|
* @brief Initialize an instance of this class from DpdkDevice.
|
|
* 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 attached) or if allocating an mbuf from the pool failed for some reason
|
|
*/
|
|
bool init(DpdkDevice* device);
|
|
/**
|
|
* @brief Initialize an instance of this class from KniDevice.
|
|
* Initialization includes allocating an mbuf from the pool that resides in KniDevice.
|
|
* The user should call this method only once per instance.
|
|
* Calling it more than once will result with an error
|
|
* @param[in] device The KniDevice 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 attached) or if allocating an mbuf from the pool failed for some reason
|
|
*/
|
|
bool init(KniDevice* device);
|
|
|
|
/**
|
|
* @brief Initialize an instance of this class and copies the content of a RawPacket object.
|
|
* Initialization includes allocating an mbuf from the pool that resides in provided DpdkDevice,
|
|
* and copying the data from the input RawPacket object into this mBuf.
|
|
* The user should call this method only once per instance.
|
|
* Calling it more than once will result with an error
|
|
* @param[in] rawPacket A pointer to a RawPacket object from which data will be copied
|
|
* @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 attached) or if allocating an mbuf from the pool failed for some reason
|
|
*/
|
|
bool initFromRawPacket(const RawPacket* rawPacket, DpdkDevice* device);
|
|
/**
|
|
* @brief Initialize an instance of this class and copies the content of a RawPacket object.
|
|
* Initialization includes allocating an mbuf from the pool that resides in provided KniDevice,
|
|
* and copying the data from the input RawPacket object into this mBuf.
|
|
* The user should call this method only once per instance.
|
|
* Calling it more than once will result with an error
|
|
* @param[in] rawPacket A pointer to a RawPacket object from which data will be copied
|
|
* @param[in] device The KniDevice 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 attached) or if allocating an mbuf from the pool failed for some reason
|
|
*/
|
|
bool initFromRawPacket(const RawPacket* rawPacket, KniDevice* device);
|
|
|
|
/**
|
|
* @return A pointer to the DPDK mbuf stored in this object
|
|
*/
|
|
inline rte_mbuf* getMBuf() { return m_MBuf; }
|
|
|
|
// overridden methods
|
|
|
|
/**
|
|
* @return MBufRawPacket object type
|
|
*/
|
|
virtual inline uint8_t getObjectType() const { return MBUFRAWPACKET_OBJECT_TYPE; }
|
|
|
|
/**
|
|
* 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
|
|
* @param[in] layerType The link layer type for this raw data. Default is Ethernet
|
|
* @param[in] frameLength When reading from pcap files, sometimes the captured length is different from the actual packet length. This parameter represents the packet
|
|
* length. This parameter is optional, if not set or set to -1 it is assumed both lengths are equal
|
|
* @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, timespec timestamp, LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1);
|
|
|
|
/**
|
|
* 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);
|
|
|
|
/**
|
|
* Set an indication whether to free the mbuf when done using it or not ("done using it" means setting another mbuf or class d'tor).
|
|
* Default value is true.
|
|
* @param[in] val The value to set. True means free the mbuf when done using it. Default it True
|
|
*/
|
|
inline void setFreeMbuf(bool val = true) { m_FreeMbuf = val; }
|
|
};
|
|
|
|
/**
|
|
* @typedef MBufRawPacketVector
|
|
* A vector of pointers to MBufRawPacket
|
|
*/
|
|
typedef PointerVector<MBufRawPacket> MBufRawPacketVector;
|
|
|
|
} // namespace pcpp
|
|
|
|
#endif /* PCAPPP_MBUF_RAW_PACKET */
|