You can create new process or input plugins for ipfixprobe if they are not implemented.
Process plugin
ℹ️ Replace ““_PLUGIN_NAME_”” and _plugin_name_ with plugin name with respected cases.
1️⃣ Create a new directory in src/plugins/process with the name of your plugin, and inside create src directory and CMakeList.txt file.
2️⃣ Add files _plugin_name_.cpp and _plugin_name_.hpp to src directory.
3️⃣ Copy content CMakeList.txt from another process plugin and modify it for your plugin.
➡️ The final file structure should look like this:
src/plugins/process/_plugin_name_/
├── src/
│ ├── _plugin_name_.cpp
│ └── _plugin_name_.h
├── CMakeLists.txt
└── README.md
4️⃣ Add directory to CMakeList.txt in src/plugins/process. (add this: add_subdirectory(_plugin_name_))
5️⃣ Implement process plugin event functions:
- pre_create : Is called before the creation of a new flow from the initial packet.
- post_create : Is called after the flow is created, takes the newly created flow and the initial packet.
- pre_update : Is called when the incoming packet belongs to the existing flow, before the data from the packet is added to the flow.
- post_update : Is called after the data of the packet is added to the flow.
- pre_export : Is called right before the flow is exported.
6️⃣ Implement _PLUGIN_NAME__UNIREC_TEMPLATE, IPFIX__PLUGIN_NAME__TEMPLATE, and fill_ipfix, fill_unirec functions.
7️⃣ Add IPFIX__PLUGIN_NAME__TEMPLATE to ipfix-elements.hpp.
➡️ Here is boilerplate source code for .cpp and .hpp files. (Use the already implemented process plugins as inspiration)
⚠️ If you do NOT modify pre_create, post_create, pre_update, post_update, pre_export functions, please remove them from _plugin_name_.cpp and _plugin_name_.hpp
#include "_PLUGIN_NAME_.hpp"
#include <iostream>
#include <ipfixprobe/pluginFactory/pluginManifest.hpp>
#include <ipfixprobe/pluginFactory/pluginRegistrar.hpp>
namespace ipxp {
static const PluginManifest _plugin_name_PluginManifest = {
.name = "_plugin_name_",
.description = "description",
.pluginVersion = "1.0.0",
.apiVersion = "1.0.0",
.usage =
[]() {
OptionsParser parser("_plugin_name_", "description");
parser.usage(std::cout);
},
};
_PLUGIN_NAME_Plugin::_PLUGIN_NAME_Plugin(const std::string& params, int pluginID)
: ProcessPlugin(pluginID)
{
(void) params;
}
_PLUGIN_NAME_Plugin::~_PLUGIN_NAME_Plugin()
{
close();
}
void _PLUGIN_NAME_Plugin::init(const char* params)
{
(void) params;
}
void _PLUGIN_NAME_Plugin::close() {}
ProcessPlugin* _PLUGIN_NAME_Plugin::copy()
{
return new _PLUGIN_NAME_Plugin(*this);
}
int _PLUGIN_NAME_Plugin::pre_create(Packet& pkt)
{
(void) pkt;
return 0;
}
int _PLUGIN_NAME_Plugin::post_create(Flow& rec, const Packet& pkt)
{
(void) rec;
(void) pkt;
return 0;
}
int _PLUGIN_NAME_Plugin::pre_update(Flow& rec, Packet& pkt)
{
(void) rec;
(void) pkt;
return 0;
}
int _PLUGIN_NAME_Plugin::post_update(Flow& rec, const Packet& pkt)
{
(void) rec;
(void) pkt;
return 0;
}
void _PLUGIN_NAME_Plugin::pre_export(Flow& rec)
{
(void) rec;
}
static const PluginRegistrar<_PLUGIN_NAME_Plugin, ProcessPluginFactory>
_plugin_name_Registrar(_plugin_name_PluginManifest);
} // namespace ipxp
#pragma once
#include <sstream>
#include <string>
#ifdef WITH_NEMEA
#include "fields.h"
#endif
#include <ipfixprobe/flowifc.hpp>
#include <ipfixprobe/ipfix-elements.hpp>
#include <ipfixprobe/packet.hpp>
#include <ipfixprobe/processPlugin.hpp>
namespace ipxp {
#define _PLUGIN_NAME__UNIREC_TEMPLATE \
"IP_TTL,IP_TTL_REV,..." //example fields
// See https://github.com/CESNET/Nemea-Framework/tree/master/unirec for help with unirec fields.
UR_FIELDS(
// uint8 IP_TTL, //example fields
// uint8 IP_TTL_REV,
// ---
)
/**
* \brief Flow record extension header for storing parsed BASICPLUS packets.
*/
struct RecordExt_PLUGIN_NAME_ : public RecordExt {
// ---
RecordExt_PLUGIN_NAME_(int pluginID)
: RecordExt(pluginID)
{
// initialize any internal state if needed
// --
}
#ifdef WITH_NEMEA
virtual void fill_unirec(ur_template_t* tmplt, void* record)
{
// Fill UniRec fields here
// ---
}
const char* get_unirec_tmplt() const { return _PLUGIN_NAME__UNIREC_TEMPLATE; }
#endif
virtual int fill_ipfix(uint8_t* buffer, int size)
{
// Fill IPFIX fields here
// --
}
const char** get_ipfix_tmplt() const
{
//need to add template to ipfix-elements.hpp
static const char* ipfix_tmplt[] = {IPFIX__PLUGIN_NAME__TEMPLATE(IPFIX_FIELD_NAMES) nullptr};
return ipfix_tmplt;
}
std::string get_text() const
{
std::ostringstream out;
// Generate string representation
return out.str();
}
};
class _PLUGIN_NAME_Plugin : public ProcessPlugin {
public:
_PLUGIN_NAME_Plugin(const std::string& params, int pluginID);
~_PLUGIN_NAME_Plugin();
void init(const char* params);
void close();
OptionsParser* get_parser() const
{
return new OptionsParser("_plugin_name_", "description");
}
std::string get_name() const { return "_plugin_name_"; }
RecordExt* get_ext() const { return new RecordExt_PLUGIN_NAME_(m_pluginID); }
ProcessPlugin* copy();
int pre_create(Packet& pkt);
int post_create(Flow& rec, const Packet& pkt);
int pre_update(Flow& rec, Packet& pkt);
int post_update(Flow& rec, const Packet& pkt);
void pre_export(Flow& rec);
};
} // namespace ipxp
⚠️ To use ipfixprobe with the new plugin as systemd, you need to add it to schema.json and config2args.py in the init/ directory.
Input Plugin
ℹ️ Replace _PLUGIN_NAME_ and _plugin_name_ with plugin name with respected cases.
1️⃣ Create a new directory in src/plugins/input with the name of your plugin, and inside create a src directory and CMakeList.txt file.
2️⃣ Add files _plugin_name_.cpp and _plugin_name_.hpp to src directory.
3️⃣ Copy content CMakeList.txt from another process plugin and modify it for your plugin.
➡️ The final file structure should look like this:
src/plugins/input/_plugin_name_/
├── src/
│ ├── _plugin_name_.cpp
│ └── _plugin_name_.h
├── CMakeLists.txt
└── README.md
4️⃣ Add directory to CMakeList.txt in src/plugins/input. (add this: add_subdirectory(_plugin_name_))
5️⃣ Implement process plugin event functions (init, close), and input plugin method get to receive new packets.
6️⃣ Implement handling command-line arguments.
➡️ Here is boilerplate source code for .cpp and .hpp files. (Use the already implemented input plugins as inspiration)
#include "_plugin_name_.hpp"
#include "parser.hpp"
#include <ipfixprobe/pluginFactory/pluginManifest.hpp>
#include <ipfixprobe/pluginFactory/pluginRegistrar.hpp>
namespace ipxp {
static const PluginManifest _plugin_name_PluginManifest = {
.name = "_plugin_name_",
.description = "description",
.pluginVersion = "1.0.0",
.apiVersion = "1.0.0",
.usage =
[]() {
_PLUGIN_NAME_OptParser parser;
parser.usage(std::cout);
},
};
_PLUGIN_NAME_Reader::_PLUGIN_NAME_Reader(const std::string& params)
// init parameters here
{
init(params.c_str());
}
_PLUGIN_NAME_Reader::~_PLUGIN_NAME_Reader()
{
close();
}
void _PLUGIN_NAME_Reader::init(const char* params)
{
_PLUGIN_NAME_OptParser parser;
try {
parser.parse(params);
} catch (ParserError& e) {
throw PluginError(e.what());
}
// implement initilization
}
void _PLUGIN_NAME_Reader::close()
{
//---
}
InputPlugin::Result _PLUGIN_NAME_Reader::get(PacketBlock& packets)
{
(void) packets;
// ---
}
static const PluginRegistrar<_PLUGIN_NAME_Reader, InputPluginFactory> _plugin_name_Registrar(_plugin_name_PluginManifest);
} // namespace ipxp
#pragma once
#include <ipfixprobe/inputPlugin.hpp>
#include <ipfixprobe/options.hpp>
#include <ipfixprobe/packet.hpp>
#include <ipfixprobe/utils.hpp>
namespace ipxp {
class _PLUGIN_NAME_OptParser : public OptionsParser {
public:
//define options
_PLUGIN_NAME_OptParser()
: OptionsParser("_plugin_name_", "description")
//init options
{
register_option(
"short_name",
"long_name",
"type",
"description",
[this](const char* arg) {
//handle arg
return true; //false
},
OptionFlags::_OPTION_ //RequiredArgument, OptionalArgument, NoArgument
);
// add more here
}
};
class _PLUGIN_NAME_Reader : public InputPlugin {
public:
_PLUGIN_NAME_Reader(const std::string& params);
~_PLUGIN_NAME_Reader();
void init(const char* params);
void close();
OptionsParser* get_parser() const { return new _PLUGIN_NAME_OptParser(); }
std::string get_name() const { return "_plugin_name_"; }
InputPlugin::Result get(PacketBlock& packets);
private:
//private functions
};
} // namespace ipxp
⚠️ To use ipfixprobe with the new plugin as systemd, you need to add it to schema.json and config2args.py in the init/ directory.