Skip to content

Commit e0f1343

Browse files
committed
fdsdump: add fields with in/out directions, e.g. in/out bytes for ip
1 parent 0c41275 commit e0f1343

File tree

2 files changed

+307
-0
lines changed

2 files changed

+307
-0
lines changed
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
/**
2+
* @file
3+
* @author Michal Sedlak <[email protected]>
4+
* @brief In/out fields
5+
*
6+
* Copyright: (C) 2024 CESNET, z.s.p.o.
7+
* SPDX-License-Identifier: BSD-3-Clause
8+
*/
9+
10+
#include <aggregator/extraFields.hpp>
11+
#include <aggregator/inOutField.hpp>
12+
#include <aggregator/viewFactory.hpp>
13+
14+
namespace fdsdump {
15+
namespace aggregator {
16+
17+
InOutKeyField::InOutKeyField(
18+
std::unique_ptr<Field> in_field, std::unique_ptr<Field> out_field) :
19+
m_in_field(std::move(in_field)),
20+
m_out_field(std::move(out_field))
21+
{
22+
if (m_in_field->data_type() != m_out_field->data_type()) {
23+
throw std::invalid_argument("in and out field not of same type");
24+
}
25+
26+
set_data_type(m_in_field->data_type());
27+
set_name(m_in_field->name());
28+
}
29+
30+
bool
31+
InOutKeyField::load(FlowContext &ctx, Value &value) const
32+
{
33+
switch (ctx.view_dir) {
34+
case ViewDirection::In:
35+
return m_in_field->load(ctx, value);
36+
case ViewDirection::Out:
37+
return m_out_field->load(ctx, value);
38+
case ViewDirection::None:
39+
assert(0);
40+
}
41+
return false;
42+
}
43+
44+
std::string
45+
InOutKeyField::repr() const
46+
{
47+
return std::string("InOutKeyField(") +
48+
+ "name=" + name() + ", data_type=" + data_type_to_str(data_type())
49+
+ ", size=" + std::to_string(size()) + ", offset=" + std::to_string(offset())
50+
+ ", in=" + m_in_field->repr() + ", out=" + m_out_field->repr() + ")";
51+
}
52+
53+
bool
54+
InOutKeyField::operator==(const InOutKeyField &other) const
55+
{
56+
return *m_in_field.get() == *other.m_in_field.get()
57+
&& *m_out_field.get() == *other.m_out_field.get();
58+
}
59+
60+
bool
61+
InOutKeyField::operator==(const Field &other) const
62+
{
63+
if (const auto *other_inout = dynamic_cast<const InOutKeyField *>(&other)) {
64+
return *this == *other_inout;
65+
}
66+
return false;
67+
}
68+
69+
std::unique_ptr<Field>
70+
InOutKeyField::create_from(const Field &field)
71+
{
72+
std::unique_ptr<Field> new_field;
73+
74+
if (field == ViewFactory::create_key_field("ip")) {
75+
new_field.reset(new InOutKeyField(
76+
ViewFactory::create_key_field("dstip"),
77+
ViewFactory::create_key_field("srcip")));
78+
79+
} else if (field == ViewFactory::create_key_field("ip4")) {
80+
new_field.reset(new InOutKeyField(
81+
ViewFactory::create_key_field("iana:destinationIPv4Address"),
82+
ViewFactory::create_key_field("iana:sourceIPv4Address")));
83+
84+
} else if (field == ViewFactory::create_key_field("ip6")) {
85+
new_field.reset(new InOutKeyField(
86+
ViewFactory::create_key_field("iana:destinationIPv6Address"),
87+
ViewFactory::create_key_field("iana:sourceIPv6Address")));
88+
89+
} else if (field == ViewFactory::create_key_field("port")) {
90+
new_field.reset(new InOutKeyField(
91+
ViewFactory::create_key_field("dstport"),
92+
ViewFactory::create_key_field("srcport")));
93+
94+
} else if (const auto *subnet_field = dynamic_cast<const SubnetField *>(&field)) {
95+
auto inner = InOutKeyField::create_from(*subnet_field->m_source_field.get());
96+
new_field.reset(new SubnetField(std::move(inner), subnet_field->m_prefix_len));
97+
}
98+
99+
return new_field;
100+
}
101+
102+
103+
InOutValueField::InOutValueField(std::unique_ptr<Field> field, ViewDirection dir) :
104+
m_field(std::move(field)),
105+
m_dir(dir)
106+
{
107+
assert(m_dir == ViewDirection::In || m_dir == ViewDirection::Out);
108+
set_data_type(m_field->data_type());
109+
set_name((m_dir == ViewDirection::In ? "in " : "out ") + m_field->name());
110+
}
111+
112+
void
113+
InOutValueField::init(Value &value) const
114+
{
115+
m_field->init(value);
116+
}
117+
118+
bool
119+
InOutValueField::aggregate(FlowContext &ctx, Value &aggregated_value) const
120+
{
121+
if (m_dir == ctx.view_dir) {
122+
return m_field->aggregate(ctx, aggregated_value);
123+
}
124+
return true;
125+
}
126+
127+
void
128+
InOutValueField::merge(Value &value, const Value &other) const
129+
{
130+
m_field->merge(value, other);
131+
}
132+
133+
std::string
134+
InOutValueField::repr() const
135+
{
136+
std::string dir;
137+
if (m_dir == ViewDirection::None) {
138+
dir = "None";
139+
} else if (m_dir == ViewDirection::In) {
140+
dir = "In";
141+
} else if (m_dir == ViewDirection::Out) {
142+
dir = "Out";
143+
}
144+
return std::string("InOutValueField(") +
145+
+ "name=" + name() + ", data_type=" + data_type_to_str(data_type())
146+
+ ", size=" + std::to_string(size()) + ", offset=" + std::to_string(offset())
147+
+ ", dir=" + dir
148+
+ ", field=" + m_field->repr() + ")";
149+
}
150+
151+
bool
152+
InOutValueField::operator==(const InOutValueField &other) const
153+
{
154+
return *m_field.get() == *other.m_field.get();
155+
}
156+
157+
bool
158+
InOutValueField::operator==(const Field &other) const
159+
{
160+
if (const auto *other_inout = dynamic_cast<const InOutValueField *>(&other)) {
161+
return *this == *other_inout;
162+
}
163+
return false;
164+
}
165+
166+
} // aggregator
167+
} // fdsdump
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/**
2+
* @file
3+
* @author Michal Sedlak <[email protected]>
4+
* @brief In/out fields
5+
*
6+
* Copyright: (C) 2024 CESNET, z.s.p.o.
7+
* SPDX-License-Identifier: BSD-3-Clause
8+
*/
9+
10+
#pragma once
11+
12+
#include <aggregator/field.hpp>
13+
14+
#include <memory>
15+
16+
namespace fdsdump {
17+
namespace aggregator {
18+
19+
/**
20+
* @brief A special key field providing a view on a value from both in/out directions,
21+
* e.g. in/out bytes of an IP address
22+
*/
23+
class InOutKeyField : public Field {
24+
public:
25+
/**
26+
* @brief Create an instance of a InOutKeyField
27+
*
28+
* @param in_field The source field in the In direction
29+
* @param out_field The source field in the Out direction
30+
*/
31+
InOutKeyField(std::unique_ptr<Field> in_field, std::unique_ptr<Field> out_field);
32+
33+
/**
34+
* @brief Load the value of the field flow record
35+
*
36+
* @param[in] ctx The flow record
37+
* @param[out] value The value
38+
*/
39+
bool
40+
load(FlowContext &ctx, Value &value) const override;
41+
42+
/**
43+
* @brief Get a string representation of the field
44+
*/
45+
std::string
46+
repr() const override;
47+
48+
/**
49+
* @brief Check if the fields are equal
50+
*/
51+
bool
52+
operator==(const InOutKeyField &other) const;
53+
54+
/**
55+
* @brief Check if the fields are equal
56+
*/
57+
bool
58+
operator==(const Field &other) const override;
59+
60+
/**
61+
* @brief Create the an in/out field from a non-in/out source field
62+
*/
63+
static std::unique_ptr<Field>
64+
create_from(const Field &field);
65+
66+
private:
67+
std::unique_ptr<Field> m_in_field;
68+
std::unique_ptr<Field> m_out_field;
69+
};
70+
71+
/**
72+
* @brief A special value field providing a view on a value from both in/out directions,
73+
* e.g. in/out bytes of an IP address
74+
*/
75+
class InOutValueField : public Field {
76+
public:
77+
/**
78+
* @brief Create an instance of a InOutValueField
79+
*
80+
* @param field The source aggregation field
81+
* @param dir The direction in which to aggregate the field
82+
*/
83+
InOutValueField(std::unique_ptr<Field> field, ViewDirection dir);
84+
85+
/**
86+
* @brief Initialize the value with the default value
87+
*
88+
* @param The value
89+
*/
90+
void
91+
init(Value &value) const override;
92+
93+
/**
94+
* @brief Aggregate the value retrieved from the provided flow record into the provided
95+
* aggregated value
96+
*
97+
* @param ctx The flow record to retrieve the value that will be aggregated from
98+
* @param aggregated_value The currently accumulated value that the retrieved value will be
99+
* aggregated towards
100+
*
101+
* @return true if the field was found in the flow record and the aggregated value was updated,
102+
* false otherwise
103+
*/
104+
bool
105+
aggregate(FlowContext &ctx, Value &aggregated_value) const override;
106+
107+
/**
108+
* @brief Merge one value with another
109+
*
110+
* @param value The value that will be updated with the result of the merge
111+
* @param other The value to merge onto the first value
112+
*/
113+
void
114+
merge(Value &value, const Value &other) const override;
115+
116+
/**
117+
* @brief Get a string representation of the field
118+
*/
119+
std::string
120+
repr() const override;
121+
122+
/**
123+
* @brief Check if the fields are equal
124+
*/
125+
bool
126+
operator==(const InOutValueField &other) const;
127+
128+
/**
129+
* @brief Check if the fields are equal
130+
*/
131+
bool
132+
operator==(const Field &other) const override;
133+
134+
private:
135+
std::unique_ptr<Field> m_field;
136+
ViewDirection m_dir;
137+
};
138+
139+
} // aggregator
140+
} // fdsdump

0 commit comments

Comments
 (0)