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 #include #include 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 #include #ifdef WITH_NEMEA #include "fields.h" #endif #include #include #include #include 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 #include 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 #include #include #include 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.