Skip to content

Commit bac616c

Browse files
committed
IPFIX output: doc update (some parameter names changed), avoid flushing templates to the first IPFIX File
1 parent 808a111 commit bac616c

File tree

6 files changed

+59
-47
lines changed

6 files changed

+59
-47
lines changed

src/plugins/output/ipfix/README.rst

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ Example configuration
4141
<useLocalTime>false</useLocalTime>
4242
<windowSize>300</windowSize>
4343
<alignWindows>true</alignWindows>
44-
<skipUnknownDataSets>true</skipUnknownDataSets>
45-
<splitOnExportTime>false</splitOnExportTime>
44+
<preserveOriginal>false</preserveOriginal>
45+
<rotateOnExportTime>false</rotateOnExportTime>
4646
</params>
4747
</output>
4848
@@ -63,27 +63,36 @@ Parameters
6363
is "0", all flow will be stored into a single file. [default: 0]
6464

6565
:``alignWindows``:
66-
Align file rotation with next N minute interval (true/false). [default: true]
67-
68-
:``skipUnknownDataSets``:
69-
Specifies whether Data Sets with unknown (Options) Template should be left
70-
out from the output file. Sequence numbers and message lengths will be
71-
adjusted accordingly. [default: false]
72-
73-
:``splitOnExportTime``:
66+
Align file rotation with next N minute interval. [values: true/false,
67+
default: true]
68+
69+
:``preserveOriginal``:
70+
Preserve and store original IPFIX Messages as received by the plugin i.e.
71+
do not modify the Messages or their sequence numbers. If this option is
72+
disabled (recommended), Data Sets with unknown (Options) Templates are
73+
left out from the file and sequence numbers are adjusted accordingly
74+
(starts from 0), which should produce warning-free stream of IPFIX
75+
Messages. However, if the original IPFIX Messages are preserved, some
76+
warnings (e.g. missing (Options) Templates, unexpected sequence number,
77+
etc.) might be produced during replay and even errors might raise when
78+
there is an ODID collision and the main Transport Session is replaced.
79+
Use with caution. [values: true/false, default: false]
80+
81+
:``rotateOnExportTime``:
7482
Specifies whether files should be rotated based on IPFIX Export Time
7583
(i.e. timestamp from IPFIX Message header) instead of system time.
76-
Warning: If the plugin receives flow records from multiple exporters at time
77-
the rotation could be unsteady. [default: false]
84+
If enabled, the Export Time is used also for creating filenames.
85+
Warning: If the plugin receives flow records from multiple exporters at
86+
time the rotation could be unsteady. [default: false]
7887

7988
Note
8089
----
8190

8291
After a new IPFIX File is created, all previously seen and still valid (Options)
8392
Templates of the each ODID are written to the file once the first IPFIX Message
84-
corresponding to the ODID arrives with at least one successfully parsed data record.
85-
This is necessary so each file can be used independently of the (Options) Template
86-
definitions from previous files.
93+
corresponding to the ODID arrives with at least one successfully parsed data
94+
record. This is necessary so each file can be used independently of the
95+
(Options) Template definitions from previous files.
8796

8897
``ipfixsend2`` tool doesn't support sequential reading of multiple IPFIX Files
8998
right now. However, there is a workaround - you can merge multiple IPFIX Files

src/plugins/output/ipfix/doc/ipfixcol2-ipfix-output.7.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ IPFIX (output plugin)
77
---------------------
88

99
:Author: Michal Sedlák ([email protected])
10+
:Author: Lukáš Huták ([email protected])
1011
:Date: 2019-03-28
1112
:Copyright: Copyright © 2019 CESNET, z.s.p.o.
1213
:Version: 1.0

src/plugins/output/ipfix/src/Config.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ enum params_xml_nodes {
5050
PARAM_USE_LOCALTIME,
5151
PARAM_WINDOW_SIZE,
5252
PARAM_ALIGN_WINDOWS,
53-
PARAM_SKIP_UNKNOWN_DATASETS,
53+
PARAM_PRESERVE_ORIGINAL,
5454
PARAM_SPLIT_ON_EXPORT_TIME
5555
};
5656

@@ -61,8 +61,8 @@ static const struct fds_xml_args args_params[] = {
6161
FDS_OPTS_ELEM(PARAM_USE_LOCALTIME, "useLocalTime", FDS_OPTS_T_BOOL, FDS_OPTS_P_OPT),
6262
FDS_OPTS_ELEM(PARAM_WINDOW_SIZE, "windowSize", FDS_OPTS_T_UINT, FDS_OPTS_P_OPT),
6363
FDS_OPTS_ELEM(PARAM_ALIGN_WINDOWS, "alignWindows", FDS_OPTS_T_BOOL, FDS_OPTS_P_OPT),
64-
FDS_OPTS_ELEM(PARAM_SKIP_UNKNOWN_DATASETS, "skipUnknownDataSets", FDS_OPTS_T_BOOL, FDS_OPTS_P_OPT),
65-
FDS_OPTS_ELEM(PARAM_SPLIT_ON_EXPORT_TIME, "splitOnExportTime", FDS_OPTS_T_BOOL, FDS_OPTS_P_OPT),
64+
FDS_OPTS_ELEM(PARAM_PRESERVE_ORIGINAL, "preserveOriginal", FDS_OPTS_T_BOOL, FDS_OPTS_P_OPT),
65+
FDS_OPTS_ELEM(PARAM_SPLIT_ON_EXPORT_TIME, "rotateOnExportTime", FDS_OPTS_T_BOOL, FDS_OPTS_P_OPT),
6666
FDS_OPTS_END
6767
};
6868

@@ -71,7 +71,7 @@ void Config::set_defaults() {
7171
use_localtime = false;
7272
window_size = 0;
7373
align_windows = true;
74-
skip_unknown_datasets = false;
74+
preserve_original = false;
7575
split_on_export_time = false;
7676
}
7777

@@ -96,9 +96,9 @@ void Config::parse_params(fds_xml_ctx_t *params)
9696
assert(content->type == FDS_OPTS_T_BOOL);
9797
align_windows = content->val_bool;
9898
break;
99-
case PARAM_SKIP_UNKNOWN_DATASETS:
99+
case PARAM_PRESERVE_ORIGINAL:
100100
assert(content->type == FDS_OPTS_T_BOOL);
101-
skip_unknown_datasets = content->val_bool;
101+
preserve_original = content->val_bool;
102102
break;
103103
case PARAM_SPLIT_ON_EXPORT_TIME:
104104
assert(content->type == FDS_OPTS_T_BOOL);

src/plugins/output/ipfix/src/Config.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ class Config {
7474
uint64_t window_size;
7575
/// Rotate files on multiple of time interval
7676
bool align_windows;
77-
/// Skip Data Sets with undefined templates
78-
bool skip_unknown_datasets;
77+
/// Preserve original IPFIX Message (i.e. don't skip Data Sets with undefined templates)
78+
bool preserve_original;
7979
/// Split on IPFIX Export Time instead on system time
8080
bool split_on_export_time;
8181

src/plugins/output/ipfix/src/IPFIXOutput.cpp

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -70,22 +70,23 @@ IPFIXOutput::should_start_new_file(std::time_t current_time)
7070
return false;
7171
}
7272

73-
uint32_t time_difference = current_time - file_start_time;
74-
if (time_difference >= config->window_size) {
75-
return true;
76-
} else {
77-
return false;
78-
}
73+
return (current_time >= file_start_time + time_t(config->window_size));
7974
}
8075

8176
/**
82-
* @brief Create a new output file
83-
* @param[in] current_time Current export time
84-
* @throw runtime_error if the file cannot be created
77+
* \brief Create a new output file
78+
* \param[in] current_time Current export time
79+
* \throw runtime_error if the file cannot be created
8580
*/
8681
void
8782
IPFIXOutput::new_file(const std::time_t current_time)
8883
{
84+
// Require (Options) Templates definitions to be added (only if this is not the first file)
85+
bool add_tmplts = (output_file != nullptr);
86+
87+
// Close the previous file, if exists
88+
close_file();
89+
8990
// Get the timestamp of the file to create
9091
if (config->align_windows) {
9192
// Round down to the nearest multiple of window size
@@ -98,7 +99,7 @@ IPFIXOutput::new_file(const std::time_t current_time)
9899
std::tm *ts_res = config->use_localtime
99100
? localtime_r(&file_start_time, &ts_now)
100101
: gmtime_r(&file_start_time, &ts_now);
101-
if (ts_res == NULL) {
102+
if (ts_res == nullptr) {
102103
// An error has occurred
103104
const char *err_str;
104105
ipx_strerror(errno, err_str);
@@ -141,7 +142,7 @@ IPFIXOutput::new_file(const std::time_t current_time)
141142

142143
// Consider all Templates as undefined
143144
for (auto &odid_pair : odid_contexts) {
144-
odid_pair.second.needs_to_write_templates = true;
145+
odid_pair.second.needs_to_write_templates = add_tmplts;
145146
}
146147

147148
IPX_CTX_INFO(plugin_context, "New output file created: %s", filename);
@@ -221,7 +222,7 @@ write_templates_cb(const struct fds_template *tmplt, void *data)
221222
assert(tmplt->type == FDS_TYPE_TEMPLATE || tmplt->type == FDS_TYPE_TEMPLATE_OPTS);
222223

223224
auto *ctx = reinterpret_cast<struct write_templates_aux *>(data);
224-
constexpr size_t MSG_SIZE = 1400; // Create only IPFIX Message with at most this length // TODO
225+
constexpr size_t MSG_SIZE = 1400; // Create only IPFIX Message with at most this length
225226

226227
// First, check if the template can fit into the current message
227228
size_t size_needed = 0;
@@ -317,13 +318,15 @@ IPFIXOutput::get_odid(uint32_t odid, const ipx_session *session)
317318
{
318319
auto *odid_ctx = &odid_contexts[odid];
319320
if (odid_ctx->session == nullptr) {
320-
// Grant right to this Transport Session to write into thw file with the given ODID...
321+
// Grant this Transport Session access to write into the file with the given ODID...
321322
odid_ctx->session = session;
323+
IPX_CTX_INFO(plugin_context, "[ODID: %" PRIu32 "] '%s' has been granted access to write to "
324+
"the file with the given ODID.", odid, session->ident);
322325
return odid_ctx;
323326
}
324327

325328
if (odid_ctx->session == session) {
326-
// This is already known Transport Session with right to write into the file
329+
// This is already known Transport Session with access to write into the file
327330
return odid_ctx;
328331
}
329332

@@ -376,7 +379,6 @@ IPFIXOutput::on_ipfix_message(ipx_msg_ipfix *message)
376379
assert(time_now >= 0 && sizeof(time_now) >= sizeof(msg_etime));
377380

378381
if (should_start_new_file(time_now)) {
379-
close_file();
380382
new_file(time_now); // This will make sure that templates will be written to the file
381383
}
382384

@@ -390,13 +392,13 @@ IPFIXOutput::on_ipfix_message(ipx_msg_ipfix *message)
390392

391393
// Write all (Options) Templates, if required
392394
if (tsnap != nullptr && odid_context->needs_to_write_templates) {
393-
uint32_t new_sn = (config->skip_unknown_datasets) ? odid_context->sequence_number : msg_seq;
395+
uint32_t new_sn = (config->preserve_original) ? msg_seq : odid_context->sequence_number;
394396
write_templates(tsnap, msg_odid, msg_etime, new_sn);
395397
odid_context->needs_to_write_templates = false;
396398
}
397399

398400
// If we don't have to look for unknown Data Sets, just copy the whole message -> FAST PATH
399-
if (!config->skip_unknown_datasets) {
401+
if (config->preserve_original) {
400402
std::fwrite(msg_hdr, msg_size, 1, output_file);
401403
return;
402404
}
@@ -477,7 +479,7 @@ IPFIXOutput::remove_session(const struct ipx_session *session)
477479
{
478480
auto it = odid_contexts.begin();
479481
while (it != odid_contexts.end()) {
480-
// Has this session right to write to the file?
482+
// Has this session access to write to the file?
481483
struct odid_context_s &ctx = it->second;
482484
if (ctx.session != session) {
483485
// Remove it from colliding sessions, if present
@@ -488,7 +490,7 @@ IPFIXOutput::remove_session(const struct ipx_session *session)
488490

489491
// This is the Transport Session with rights to write to the file with given ODID
490492
if (ctx.colliding_sessions.empty()) {
491-
// Only session in the context -> remove whole context
493+
// Only session in the context -> remove the whole context
492494
it = odid_contexts.erase(it);
493495
continue;
494496
}
@@ -516,7 +518,7 @@ IPFIXOutput::on_session_message(ipx_msg_session *message)
516518

517519
case IPX_MSG_SESSION_CLOSE:
518520
// Free up ODIDs used by this session allowing them to be used again
519-
remove_session(session); // TODO: consider blocking ODID until new file is started + reset seqnum!
521+
remove_session(session);
520522
break;
521523
}
522524
}

src/plugins/output/ipfix/src/IPFIXOutputPlugin.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,11 @@ ipx_plugin_init(ipx_ctx_t *ctx, const char *params)
9090
ipx_ctx_private_set(ctx, instance);
9191

9292
} catch (std::exception &ex) {
93-
IPX_CTX_ERROR(ctx, "IPFIXOutput plugin: %s", ex.what());
93+
IPX_CTX_ERROR(ctx, "%s", ex.what());
9494
return IPX_ERR_DENIED;
9595

9696
} catch (...) {
97-
IPX_CTX_ERROR(ctx, "IPFIXOutput plugin: Unexpected exception has occurred!", '\0');
97+
IPX_CTX_ERROR(ctx, "Unexpected exception has occurred!", '\0');
9898
return IPX_ERR_DENIED;
9999
}
100100

@@ -127,11 +127,11 @@ ipx_plugin_process(ipx_ctx_t *ctx, void *cfg, ipx_msg_t *msg)
127127
}
128128

129129
} catch (std::exception &ex) {
130-
IPX_CTX_ERROR(ctx, "IPFIXOutput plugin: %s", ex.what());
130+
IPX_CTX_ERROR(ctx, "%s", ex.what());
131131
return IPX_ERR_DENIED;
132132

133133
} catch (...) {
134-
IPX_CTX_ERROR(ctx, "IPFIXOutput plugin: Unexpected exception has occurred!", '\0');
134+
IPX_CTX_ERROR(ctx, "Unexpected exception has occurred!", '\0');
135135
return IPX_ERR_DENIED;
136136
}
137137

0 commit comments

Comments
 (0)