Skip to content

Commit 2fd87bc

Browse files
committed
++
1 parent b9bd047 commit 2fd87bc

File tree

254 files changed

+30480
-8466
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

254 files changed

+30480
-8466
lines changed

include/ipfixprobe/flowifc.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848

4949
#include <string>
5050

51-
#include <arpa/inet.h>
51+
//#include <arpa/inet.h>
5252

5353
namespace ipxp {
5454

include/ipfixprobe/packet.hpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@ struct Packet : public Record {
5151
uint16_t ethertype;
5252

5353
uint16_t ip_len; /**< Length of IP header + its payload */
54-
uint16_t tcp_window;
55-
uint64_t tcp_options;
56-
uint32_t tcp_mss;
5754
uint16_t ip_payload_len; /**< Length of IP payload */
5855
uint8_t ip_version;
5956
uint8_t ip_ttl;

include/ipfixprobe/parser-stats.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#include <ipfixprobe/packet.hpp>
3333
#include <telemetry.hpp>
3434

35+
#include "ipProtocol.hpp"
36+
3537
namespace ipxp {
3638

3739
static constexpr std::size_t MAX_VLAN_ID = 4096;
@@ -132,9 +134,9 @@ struct VlanStats {
132134
ipv6_bytes += pkt.packet_len;
133135
}
134136

135-
if (pkt.ip_proto == IPPROTO_TCP) {
137+
if (pkt.ip_proto == IPProtocol::TCP) {
136138
tcp_packets++;
137-
} else if (pkt.ip_proto == IPPROTO_UDP) {
139+
} else if (pkt.ip_proto == IPProtocol::UDP) {
138140
udp_packets++;
139141
}
140142

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
project(ipfixprobe-process-basicplus VERSION 1.0.0 DESCRIPTION "ipfixprobe-process-basicplus plugin")
2+
3+
add_library(ipfixprobe-process-basicplus MODULE
4+
src/basicplus.cpp
5+
src/basicplus.hpp
6+
)
7+
8+
set_target_properties(ipfixprobe-process-basicplus PROPERTIES
9+
CXX_VISIBILITY_PRESET hidden
10+
VISIBILITY_INLINES_HIDDEN YES
11+
)
12+
13+
target_link_libraries(ipfixprobe-process-basicplus PRIVATE
14+
ipfixprobe-output-ipfix
15+
)
16+
17+
target_include_directories(ipfixprobe-process-basicplus PRIVATE
18+
${CMAKE_SOURCE_DIR}/include/
19+
)
20+
21+
if(ENABLE_NEMEA)
22+
target_link_libraries(ipfixprobe-process-basicplus PRIVATE
23+
-Wl,--whole-archive ipfixprobe-nemea-fields -Wl,--no-whole-archive
24+
unirec::unirec
25+
trap::trap
26+
)
27+
endif()
28+
29+
install(TARGETS ipfixprobe-process-basicplus
30+
LIBRARY DESTINATION "${INSTALL_DIR_LIB}/ipfixprobe/process/"
31+
)

src/plugins/process/basicPlus/README.md

Whitespace-only changes.
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/**
2+
* @file
3+
* @brief Plugin for parsing basicplus traffic.
4+
* @author Jiri Havranek <[email protected]>
5+
* @author Pavel Siska <[email protected]>
6+
* @author Damir Zainullin <[email protected]>
7+
* @date 2025
8+
*
9+
* Provides a plugin that extracts basic IP and TCP fields from packets,
10+
* stores them in per-flow plugin data, and exposes fields via FieldManager.
11+
*
12+
* @copyright Copyright (c) 2025 CESNET, z.s.p.o.
13+
*/
14+
15+
#include "basicPlus.hpp"
16+
17+
#include <iostream>
18+
19+
#include <pluginManifest.hpp>
20+
#include <pluginRegistrar.hpp>
21+
#include <pluginFactory.hpp>
22+
#include <fieldSchema.hpp>
23+
#include <fieldManager.hpp>
24+
#include <tcpData.hpp>
25+
26+
namespace ipxp {
27+
28+
static const PluginManifest basicPlusPluginManifest = {
29+
.name = "basicplus",
30+
.description = "Basicplus process plugin for parsing basicplus traffic.",
31+
.pluginVersion = "1.0.0",
32+
.apiVersion = "1.0.0",
33+
.usage =
34+
[]() {
35+
/*OptionsParser parser(
36+
"basicplus",
37+
"Extend basic fields with TTL, TCP window, options, MSS and SYN size");
38+
parser.usage(std::cout);*/
39+
},
40+
};
41+
42+
43+
static FieldSchema createBasicPlusSchema(FieldManager& fieldManager, FieldHandlers<BasicPlusFields>& handlers)
44+
{
45+
FieldSchema schema = fieldManager.createFieldSchema("basicplus");
46+
47+
auto [ipTTLField, ipTTLRevField] = schema.addScalarDirectionalFields(
48+
"IP_TTL", "IP_TTL_REV",
49+
[](const void* context) { return reinterpret_cast<const BasicPlusData*>(context)->ipTTL[Direction::Forward]; },
50+
[](const void* context) { return reinterpret_cast<const BasicPlusData*>(context)->ipTTL[Direction::Reverse]; }
51+
);
52+
handlers.insert(BasicPlusFields::IP_TTL, ipTTLField);
53+
handlers.insert(BasicPlusFields::IP_TTL_REV, ipTTLRevField);
54+
55+
auto [ipFlagField, ipFlagRevField] = schema.addScalarDirectionalFields(
56+
"IP_FLG", "IP_FLG_REV",
57+
[](const void* context) { return reinterpret_cast<const BasicPlusData*>(context)->ipFlag[Direction::Forward]; },
58+
[](const void* context) { return reinterpret_cast<const BasicPlusData*>(context)->ipFlag[Direction::Reverse]; }
59+
);
60+
handlers.insert(BasicPlusFields::IP_FLG, ipFlagField);
61+
handlers.insert(BasicPlusFields::IP_FLG_REV, ipFlagRevField);
62+
63+
auto [tcpWinField, tcpWinRevField] = schema.addScalarDirectionalFields(
64+
"TCP_WIN", "TCP_WIN_REV",
65+
[](const void* context) { return reinterpret_cast<const BasicPlusData*>(context)->tcpWindow[Direction::Forward]; },
66+
[](const void* context) { return reinterpret_cast<const BasicPlusData*>(context)->tcpWindow[Direction::Reverse]; }
67+
);
68+
handlers.insert(BasicPlusFields::TCP_WIN, tcpWinField);
69+
handlers.insert(BasicPlusFields::TCP_WIN_REV, tcpWinRevField);
70+
71+
auto [tcpOptField, tcpOptRevField] = schema.addScalarDirectionalFields(
72+
"TCP_OPT", "TCP_OPT_REV",
73+
[](const void* context) { return reinterpret_cast<const BasicPlusData*>(context)->tcpOption[Direction::Forward]; },
74+
[](const void* context) { return reinterpret_cast<const BasicPlusData*>(context)->tcpOption[Direction::Reverse]; }
75+
);
76+
handlers.insert(BasicPlusFields::TCP_OPT, tcpOptField);
77+
handlers.insert(BasicPlusFields::TCP_OPT_REV, tcpOptRevField);
78+
79+
auto [tcpMSSField, tcpMSSRevField] = schema.addScalarDirectionalFields(
80+
"TCP_MSS", "TCP_MSS_REV",
81+
[](const void* context) { return reinterpret_cast<const BasicPlusData*>(context)->tcpMSS[Direction::Forward]; },
82+
[](const void* context) { return reinterpret_cast<const BasicPlusData*>(context)->tcpMSS[Direction::Reverse]; }
83+
);
84+
handlers.insert(BasicPlusFields::TCP_MSS, tcpMSSField);
85+
handlers.insert(BasicPlusFields::TCP_MSS_REV, tcpMSSRevField);
86+
87+
handlers.insert(BasicPlusFields::TCP_SYN_SIZE, schema.addScalarField("TCP_SYN_SIZE", [](const void* context) {
88+
return static_cast<const BasicPlusData*>(context)->tcpSynSize;
89+
}));
90+
91+
return schema;
92+
}
93+
94+
BasicPlusPlugin::BasicPlusPlugin([[maybe_unused]]const std::string& params, FieldManager& fieldManager)
95+
{
96+
createBasicPlusSchema(fieldManager, m_fieldHandlers);
97+
}
98+
99+
PluginInitResult BasicPlusPlugin::onInit(const FlowContext& flowContext, void* pluginContext)
100+
{
101+
auto* pluginData = std::construct_at(reinterpret_cast<BasicPlusData*>(pluginContext));
102+
103+
pluginData->ipTTL[Direction::Forward] = flowContext.packet.ip_ttl;
104+
m_fieldHandlers[BasicPlusFields::IP_TTL].setAsAvailable(flowContext.flowRecord);
105+
106+
pluginData->ipFlag[Direction::Forward] = flowContext.packet.ip_flags;
107+
m_fieldHandlers[BasicPlusFields::IP_FLG].setAsAvailable(flowContext.flowRecord);
108+
109+
constexpr std::size_t TCP = 6;
110+
if (flowContext.packet.ip_proto != TCP) {
111+
return {
112+
.constructionState = ConstructionState::Constructed,
113+
.updateRequirement = UpdateRequirement::RequiresUpdate,
114+
.flowAction = FlowAction::NoAction,
115+
};
116+
}
117+
118+
pluginData->tcpWindow[Direction::Forward] = flowContext.packet.tcp_window;
119+
m_fieldHandlers[BasicPlusFields::TCP_WIN].setAsAvailable(flowContext.flowRecord);
120+
121+
pluginData->tcpOption[Direction::Forward] = flowContext.packet.tcp_options;
122+
m_fieldHandlers[BasicPlusFields::TCP_OPT].setAsAvailable(flowContext.flowRecord);
123+
124+
pluginData->tcpMSS[Direction::Forward] = flowContext.packet.tcp_mss;
125+
m_fieldHandlers[BasicPlusFields::TCP_MSS].setAsAvailable(flowContext.flowRecord);
126+
127+
if (TCPFlags(flowContext.packet.tcp_flags).bitfields.synchronize) { // check if SYN packet
128+
pluginData->tcpSynSize = flowContext.packet.ip_len;
129+
m_fieldHandlers[BasicPlusFields::TCP_SYN_SIZE].setAsAvailable(flowContext.flowRecord);
130+
}
131+
132+
return {
133+
.constructionState = ConstructionState::Constructed,
134+
.updateRequirement = UpdateRequirement::RequiresUpdate,
135+
.flowAction = FlowAction::NoAction,
136+
};
137+
}
138+
139+
PluginUpdateResult BasicPlusPlugin::onUpdate(const FlowContext& flowContext, void* pluginContext)
140+
{
141+
auto* pluginData = reinterpret_cast<BasicPlusData*>(pluginContext);
142+
143+
pluginData->ipTTL[flowContext.packet.source_pkt]
144+
= std::min(pluginData->ipTTL[flowContext.packet.source_pkt], flowContext.packet.ip_ttl);
145+
146+
constexpr std::size_t TCP = 6;
147+
if (flowContext.packet.ip_proto != TCP) {
148+
return {
149+
.updateRequirement = UpdateRequirement::RequiresUpdate,
150+
.flowAction = FlowAction::NoAction,
151+
};
152+
}
153+
154+
pluginData->tcpOption[flowContext.packet.source_pkt] |= flowContext.packet.tcp_options;
155+
156+
if (flowContext.packet.source_pkt == Direction::Forward) {
157+
return {
158+
.updateRequirement = UpdateRequirement::RequiresUpdate,
159+
.flowAction = FlowAction::NoAction,
160+
};
161+
}
162+
163+
pluginData->ipTTL[Direction::Reverse] = flowContext.packet.ip_ttl;
164+
m_fieldHandlers[BasicPlusFields::IP_TTL_REV].setAsAvailable(flowContext.flowRecord);
165+
166+
pluginData->ipFlag[Direction::Reverse] = flowContext.packet.ip_flags;
167+
m_fieldHandlers[BasicPlusFields::IP_FLG_REV].setAsAvailable(flowContext.flowRecord);
168+
169+
pluginData->tcpWindow[Direction::Reverse] = flowContext.packet.tcp_window;
170+
m_fieldHandlers[BasicPlusFields::TCP_WIN_REV].setAsAvailable(flowContext.flowRecord);
171+
172+
pluginData->tcpOption[Direction::Reverse] = flowContext.packet.tcp_options;
173+
m_fieldHandlers[BasicPlusFields::TCP_OPT_REV].setAsAvailable(flowContext.flowRecord);
174+
175+
pluginData->tcpMSS[Direction::Reverse] = flowContext.packet.tcp_mss;
176+
m_fieldHandlers[BasicPlusFields::TCP_MSS_REV].setAsAvailable(flowContext.flowRecord);
177+
178+
return {
179+
.updateRequirement = UpdateRequirement::NoUpdateNeeded,
180+
.flowAction = FlowAction::NoAction,
181+
};
182+
}
183+
184+
void BasicPlusPlugin::onDestroy(void* pluginContext)
185+
{
186+
std::destroy_at(reinterpret_cast<BasicPlusData*>(pluginContext));
187+
}
188+
189+
PluginDataMemoryLayout BasicPlusPlugin::getDataMemoryLayout() const noexcept
190+
{
191+
return {
192+
.size = sizeof(BasicPlusData),
193+
.alignment = alignof(BasicPlusData),
194+
};
195+
}
196+
197+
static const PluginRegistrar<BasicPlusPlugin, PluginFactory<ProcessPlugin, const std::string&, FieldManager&>>
198+
basicPlusRegistrar(basicPlusPluginManifest);
199+
200+
} // namespace ipxp
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/**
2+
* @file
3+
* @brief Plugin for parsing basicplus traffic.
4+
* @author Jiri Havranek <[email protected]>
5+
* @author Pavel Siska <[email protected]>
6+
* @author Damir Zainullin <[email protected]>
7+
* @date 2025
8+
*
9+
* Provides a plugin that extracts basic IP and TCP fields from packets,
10+
* stores them in per-flow plugin data, and exposes fields via FieldManager.
11+
*
12+
* @copyright Copyright (c) 2025 CESNET, z.s.p.o.
13+
*/
14+
15+
#pragma once
16+
17+
#include <sstream>
18+
#include <string>
19+
20+
#include <processPlugin.hpp>
21+
#include <fieldManager.hpp>
22+
#include <fieldHandlersEnum.hpp>
23+
24+
#include "basicPlusData.hpp"
25+
#include "basicPlusFields.hpp"
26+
27+
namespace ipxp {
28+
29+
/**
30+
* @class BasicPlusPlugin
31+
* @brief A plugin for collecting basic statistics about the flow: IP TTL, flags, TCP window, options, MSS and SYN length.
32+
*/
33+
class BasicPlusPlugin : public ProcessPlugin {
34+
public:
35+
/**
36+
* @brief Constructs the BasicPlus plugin.
37+
*
38+
* @param parameters Plugin parameters as a string (currently unused).
39+
* @param fieldManager Reference to the FieldManager for field registration.
40+
*/
41+
BasicPlusPlugin(const std::string& params, FieldManager& manager);
42+
43+
/**
44+
* @brief Initializes plugin data for a new flow.
45+
*
46+
* Constructs `BasicPlusData` in `pluginContext` and initializes it with
47+
* the first packet's IP TTL and flags. If flow is TCP also adds MSS, options
48+
* and window. If TCP SYN packet, also adds SYN length.
49+
*
50+
* @param flowContext Contextual information about the flow to fill new record.
51+
* @param pluginContext Pointer to pre-allocated memory to create record.
52+
* @return Result of the initialization process.
53+
*/
54+
PluginInitResult onInit(const FlowContext& flowContext, void* pluginContext) override;
55+
56+
/**
57+
* @brief Updates plugin data with values from new packet.
58+
*
59+
* Updates `BasicPlusData` to obtain minimum IP TTL and TCP options cumulative
60+
* from `pluginContext`. Also updates same fields as `onInit` from reverse direction.
61+
*
62+
* @param flowContext Contextual information about the flow to be updated.
63+
* @param pluginContext Pointer to `BasicPlusData`.
64+
* @return Result of the update, may not require new packets if both directions are observed.
65+
*/
66+
PluginUpdateResult onUpdate(const FlowContext& flowContext, void* pluginContext) override;
67+
68+
/**
69+
* @brief Cleans up and destroys `BasicPlusData`.
70+
* @param pluginContext Pointer to `BasicPlusData`.
71+
*/
72+
void onDestroy(void* pluginContext) override;
73+
74+
/**
75+
* @brief Provides the memory layout of `BasicPlusData`.
76+
* @return Memory layout description for the plugin data.
77+
*/
78+
PluginDataMemoryLayout getDataMemoryLayout() const noexcept override;
79+
80+
private:
81+
FieldHandlers<BasicPlusFields> m_fieldHandlers;
82+
};
83+
84+
} // namespace ipxp
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* @file
3+
* @brief Export data of basicplus plugin.
4+
* @author Damir Zainullin <[email protected]>
5+
* @date 2025
6+
*
7+
* @copyright Copyright (c) 2025 CESNET, z.s.p.o.
8+
*/
9+
10+
#pragma once
11+
12+
#include <directionalField.hpp>
13+
14+
namespace ipxp
15+
{
16+
17+
/**
18+
* @struct BasicPlusExport
19+
* @brief Structure representing extended basic flow export fields.
20+
*
21+
* Contains directional fields for various IP and TCP header values, as well as
22+
* additional TCP-specific metrics.
23+
*/
24+
struct BasicPlusData {
25+
DirectionalField<uint8_t> ipTTL; ///< Directional IP Time-To-Live value
26+
DirectionalField<uint8_t> ipFlag; ///< Directional IP flag value
27+
DirectionalField<uint16_t> tcpWindow; ///< Directional TCP window size
28+
DirectionalField<uint64_t> tcpOption; ///< Directional TCP option value
29+
DirectionalField<uint32_t> tcpMSS; ///< Directional TCP Maximum Segment Size
30+
uint16_t tcpSynSize{0}; ///< Size of TCP SYN packet
31+
};
32+
33+
} // namespace ipxp
34+

0 commit comments

Comments
 (0)