Skip to content

Commit 57267d8

Browse files
committed
fdsdump: add alias field
1 parent c2020d4 commit 57267d8

File tree

2 files changed

+236
-0
lines changed

2 files changed

+236
-0
lines changed
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
/**
2+
* @file
3+
* @author Michal Sedlak <[email protected]>
4+
* @brief Alias field
5+
*
6+
* Copyright: (C) 2024 CESNET, z.s.p.o.
7+
* SPDX-License-Identifier: BSD-3-Clause
8+
*/
9+
10+
#include <aggregator/aliasField.hpp>
11+
12+
#include <algorithm>
13+
#include <map>
14+
#include <stdexcept>
15+
#include <utility>
16+
17+
namespace fdsdump {
18+
namespace aggregator {
19+
20+
static DataType
21+
get_common_data_type(const std::vector<IpfixField> &fields)
22+
{
23+
assert(!fields.empty());
24+
25+
static const std::map<std::pair<DataType, DataType>, DataType> common_type_map {
26+
{{DataType::Unsigned8, DataType::Unsigned16}, DataType::Unsigned16},
27+
{{DataType::Unsigned8, DataType::Unsigned32}, DataType::Unsigned32},
28+
{{DataType::Unsigned8, DataType::Unsigned64}, DataType::Unsigned64},
29+
{{DataType::Unsigned16, DataType::Unsigned32}, DataType::Unsigned32},
30+
{{DataType::Unsigned16, DataType::Unsigned64}, DataType::Unsigned64},
31+
{{DataType::Unsigned32, DataType::Unsigned64}, DataType::Unsigned64},
32+
33+
{{DataType::Signed8, DataType::Signed16}, DataType::Signed16},
34+
{{DataType::Signed8, DataType::Signed32}, DataType::Signed32},
35+
{{DataType::Signed8, DataType::Signed64}, DataType::Signed64},
36+
{{DataType::Signed16, DataType::Signed32}, DataType::Signed32},
37+
{{DataType::Signed16, DataType::Signed64}, DataType::Signed64},
38+
{{DataType::Signed32, DataType::Signed64}, DataType::Signed64},
39+
40+
{{DataType::IPv4Address, DataType::IPv6Address}, DataType::IPAddress},
41+
{{DataType::IPv4Address, DataType::IPAddress}, DataType::IPAddress},
42+
{{DataType::IPv6Address, DataType::IPAddress}, DataType::IPAddress},
43+
};
44+
45+
auto unify = [&](DataType a, DataType b) -> DataType {
46+
if (a == b) {
47+
return a;
48+
}
49+
50+
auto it = common_type_map.find({a, b});
51+
if (it != common_type_map.end()) {
52+
return it->second;
53+
}
54+
55+
it = common_type_map.find({b, a});
56+
if (it != common_type_map.end()) {
57+
return it->second;
58+
}
59+
60+
throw std::invalid_argument("cannot get common data type for alias fields");
61+
};
62+
63+
DataType data_type = fields.front().data_type();
64+
for (const auto &field : fields) {
65+
data_type = unify(data_type, field.data_type());
66+
}
67+
return data_type;
68+
}
69+
70+
AliasField::AliasField(const fds_iemgr_alias &alias)
71+
{
72+
if (alias.sources_cnt == 0) {
73+
throw std::invalid_argument("alias has zero source elements");
74+
}
75+
76+
for (size_t i = 0; i < alias.sources_cnt; ++i) {
77+
m_sources.push_back(IpfixField(*alias.sources[i]));
78+
}
79+
80+
DataType data_type = get_common_data_type(m_sources);
81+
set_data_type(data_type);
82+
83+
set_name(alias.name);
84+
}
85+
86+
bool
87+
AliasField::load(FlowContext &ctx, Value &value) const
88+
{
89+
for (const auto &source : m_sources) {
90+
91+
if (source.data_type() == data_type()) {
92+
if (source.load(ctx, value)) {
93+
return true;
94+
}
95+
96+
} else {
97+
Value tmp_value;
98+
99+
if (source.load(ctx, tmp_value)) {
100+
auto tmp_value_view = ValueView(source.data_type(), tmp_value);
101+
102+
switch (data_type()) {
103+
case DataType::IPAddress:
104+
value.ip = tmp_value_view.as_ip();
105+
break;
106+
case DataType::Unsigned16:
107+
value.u16 = tmp_value_view.as_u16();
108+
break;
109+
case DataType::Unsigned32:
110+
value.u32 = tmp_value_view.as_u32();
111+
break;
112+
case DataType::Unsigned64:
113+
value.u64 = tmp_value_view.as_u64();
114+
break;
115+
case DataType::Signed16:
116+
value.i16 = tmp_value_view.as_i16();
117+
break;
118+
case DataType::Signed32:
119+
value.i32 = tmp_value_view.as_i32();
120+
break;
121+
case DataType::Signed64:
122+
value.i64 = tmp_value_view.as_i64();
123+
break;
124+
default:
125+
throw std::logic_error("unexpected alias field data type");
126+
}
127+
return true;
128+
}
129+
}
130+
}
131+
132+
return false;
133+
}
134+
135+
std::string
136+
AliasField::repr() const
137+
{
138+
std::string sources = "";
139+
for (size_t i = 0; i < m_sources.size(); i++) {
140+
if (i > 0) {
141+
sources += ", ";
142+
}
143+
sources += m_sources[i].repr();
144+
}
145+
146+
return std::string("AliasField(") +
147+
+ "name=" + name() + ", data_type=" + data_type_to_str(data_type())
148+
+ ", size=" + std::to_string(size()) + ", offset=" + std::to_string(offset())
149+
+ ", sources=[" + sources + "])";
150+
}
151+
152+
bool
153+
AliasField::operator==(const AliasField &other) const
154+
{
155+
return m_sources.size() == other.m_sources.size()
156+
&& std::equal(m_sources.begin(), m_sources.end(), other.m_sources.begin());
157+
}
158+
159+
bool
160+
AliasField::operator==(const Field &other) const
161+
{
162+
if (const auto *other_alias = dynamic_cast<const AliasField *>(&other)) {
163+
return *this == *other_alias;
164+
} else {
165+
return false;
166+
}
167+
}
168+
169+
} // aggregator
170+
} // fdsdump
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* @file
3+
* @author Michal Sedlak <[email protected]>
4+
* @brief Alias field
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+
#include <aggregator/ipfixField.hpp>
14+
15+
#include <libfds.h>
16+
17+
#include <vector>
18+
19+
namespace fdsdump {
20+
namespace aggregator {
21+
22+
/**
23+
* @brief A field that is an alias mapping to other fields
24+
*/
25+
class AliasField : public Field {
26+
public:
27+
/**
28+
* @brief Create a new field based on an iemgr alias
29+
*
30+
* @param alias The iemgr alias
31+
*/
32+
AliasField(const fds_iemgr_alias &alias);
33+
34+
/**
35+
* @brief Load the value of the field flow record
36+
*
37+
* @param[in] ctx The flow record
38+
* @param[out] value The value
39+
*/
40+
virtual bool
41+
load(FlowContext &ctx, Value &value) const override;
42+
43+
/**
44+
* @brief Get a string representation of the field
45+
*/
46+
std::string
47+
repr() const override;
48+
49+
/**
50+
* @brief Check if the fields are equal
51+
*/
52+
bool
53+
operator==(const AliasField &other) const;
54+
55+
/**
56+
* @brief Check if the fields are equal
57+
*/
58+
bool
59+
operator==(const Field &other) const override;
60+
61+
private:
62+
std::vector<IpfixField> m_sources;
63+
};
64+
65+
} // aggregator
66+
} // fdsdump

0 commit comments

Comments
 (0)