Skip to content

Commit 465dca4

Browse files
committed
UniRec output plugin: added internal implementation of link/dir_bit_field
1 parent 2d2f119 commit 465dca4

File tree

7 files changed

+405
-55
lines changed

7 files changed

+405
-55
lines changed

extra_plugins/output/unirec/README.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,12 +242,15 @@ discarded. Otherwise, the value is saturated.
242242
To see conversion warnings, add the UniRec field to ``<uniRecFormat>`` and run the collector
243243
with increased verbosity level i.e. ``ipfixcol2 -v``.
244244

245-
Note
246-
----
245+
Notes
246+
-----
247247

248248
Bidirectional flows are not currently supported by UniRec, therefore, biflow records are
249249
automatically split into two unidirectional flow records during conversion.
250250

251251
When multiple IPFIX Information Elements are mapped to the same UniRec field and those IPFIX fields
252252
are present in an IPFIX record, the last field occurrence (in the appropriate IPFIX Template)
253253
is converted to the UniRec field.
254+
255+
TODO: describe "link_bit_field" + "dir_bit_field"
256+

extra_plugins/output/unirec/config/unirec-elements.txt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
# ("eXXidYY" where XX is Private Enterprise Number and YY is field ID)
1111
#
1212
# See ipfixcol2-unirec-output(1) for details
13+
#
14+
# Note:
15+
# IPFIX IEs "_internal_dbf_" and "_internal_lbf_" represents internal
16+
# conversion functions of UniRec plugin.
1317

1418
#UNIREC NAME UNIREC TYPE IPFIX IEs DESCRIPTION
1519
# --- Basic fields ---
@@ -21,12 +25,12 @@ PROTOCOL uint8 e0id4 # Transport protoc
2125
TCP_FLAGS uint8 e0id6 # TCP flags
2226
BYTES uint64 e0id1 # Number of bytes in flow
2327
PACKETS uint32 e0id2 # Number of packets in flow
24-
TIME_FIRST time e0id152 # Time of the first packet of a flow
25-
TIME_LAST time e0id153 # Time of the last packet of a flow
26-
DIR_BIT_FIELD uint8 e0id10 # Bit field used for determining incoming/outgoing flow (1 => Incoming, 0 => Outgoing)
27-
LINK_BIT_FIELD uint64 e0id405 # Bit field of links on which was flow seen
2828
TTL uint8 e0id192 # IP time to live
2929
TOS uint8 e0id5 # IP type of service
30+
TIME_FIRST time e0id150,e0id152,e0id154,e0id156 # Time of the first packet of a flow
31+
TIME_LAST time e0id151,e0id153,e0id155,e0id157 # Time of the last packet of a flow
32+
DIR_BIT_FIELD uint8 _internal_dbf_ # Bit field used for determining incoming/outgoing flow (1 => Incoming, 0 => Outgoing)
33+
LINK_BIT_FIELD uint64 _internal_lbf_ # Bit field of links on which was flow seen
3034

3135
# --- DNS specific fields ---
3236
DNS_ANSWERS uint16 e8057id0 # DNS answers

extra_plugins/output/unirec/src/map.c

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ map_rec_add(map_t *map, const struct map_rec *rec)
189189
* \return Pointer to the definition or NULL (unknown or invalid IE specifier)
190190
*/
191191
static const struct fds_iemgr_elem *
192-
map_elem_get(const fds_iemgr_t *mgr, const char *elem)
192+
map_elem_get_ipfix(const fds_iemgr_t *mgr, const char *elem)
193193
{
194194
const struct fds_iemgr_elem *res;
195195

@@ -211,6 +211,23 @@ map_elem_get(const fds_iemgr_t *mgr, const char *elem)
211211
return fds_iemgr_elem_find_id(mgr, ipfix_en, ipfix_id);
212212
}
213213

214+
/**
215+
* \brief Get the type of internal function
216+
* \param[in] elem Identification of an internal function to find
217+
* \return Function identifier or ::MAP_SRC_INVALID in case or failure
218+
*/
219+
static enum MAP_SRC
220+
map_elem_get_internal(const char *elem)
221+
{
222+
if (strcmp(elem, "_internal_lbf_") == 0) {
223+
return MAP_SRC_INTERNAL_LBF;
224+
} else if (strcmp(elem, "_internal_dbf_") == 0) {
225+
return MAP_SRC_INTERNAL_DBF;
226+
} else {
227+
return MAP_SRC_INVALID;
228+
}
229+
}
230+
214231
/**
215232
* \brief Parse list of IPFIX IE and add mapping records to the database
216233
* \param[in] map Mapping database
@@ -259,20 +276,33 @@ map_load_line_ie_defs(map_t *map, char *ur_name, int ur_type, char *ur_type_str,
259276
}
260277

261278
// Parse IPFIX specifier
262-
const struct fds_iemgr_elem *elem_def = map_elem_get(map->iemgr, subtoken);
263-
if (!elem_def) {
264-
snprintf(map->err_buffer, ERR_SIZE, "Line %zu: IPFIX specifier '%s' is invalid or "
265-
"a definition of the Information Element is missing! For more information, see "
266-
"the plugin documentation.", line_id, subtoken);
267-
rc = IPX_ERR_FORMAT;
268-
break;
279+
const struct fds_iemgr_elem *elem_def = map_elem_get_ipfix(map->iemgr, subtoken);
280+
if (elem_def != NULL) {
281+
// Store the "IPFIX element" record
282+
rec.ipfix.source = MAP_SRC_IPFIX;
283+
rec.ipfix.def = elem_def;
284+
rec.ipfix.id = elem_def->id;
285+
rec.ipfix.en = elem_def->scope->pen;
286+
rc = map_rec_add(map, &rec);
287+
continue;
288+
}
289+
290+
enum MAP_SRC fn_id = map_elem_get_internal(subtoken);
291+
if (fn_id != MAP_SRC_INVALID) {
292+
// Store the "Internal function" record
293+
rec.ipfix.source = fn_id;
294+
rec.ipfix.def = NULL;
295+
rec.ipfix.id = 0;
296+
rec.ipfix.en = 0;
297+
rc = map_rec_add(map, &rec);
298+
continue;
269299
}
270300

271-
// Store the record
272-
rec.ipfix.def = elem_def;
273-
rec.ipfix.id = elem_def->id;
274-
rec.ipfix.en = elem_def->scope->pen;
275-
rc = map_rec_add(map, &rec);
301+
snprintf(map->err_buffer, ERR_SIZE, "Line %zu: IPFIX specifier '%s' is invalid or "
302+
"a definition of the Information Element is missing! For more information, see "
303+
"the plugin documentation.", line_id, subtoken);
304+
rc = IPX_ERR_FORMAT;
305+
break;
276306
}
277307

278308
free(defs_cpy);
@@ -374,6 +404,10 @@ map_sort_fn(const void *p1, const void *p2)
374404
struct map_rec *rec1 = *(struct map_rec **) p1;
375405
struct map_rec *rec2 = *(struct map_rec **) p2;
376406

407+
if (rec1->ipfix.source != rec2->ipfix.source) {
408+
return (rec1->ipfix.source < rec2->ipfix.source) ? (-1) : 1;
409+
}
410+
377411
// Primary sort by PEN
378412
if (rec1->ipfix.en != rec2->ipfix.en) {
379413
return (rec1->ipfix.en < rec2->ipfix.en) ? (-1) : 1;
@@ -455,6 +489,11 @@ map_load(map_t *map, const char *file)
455489
for (size_t i = 1; i < map->rec_size; i++) {
456490
// Records are sorted, therefore, the same IPFIX IEs should be next to each other
457491
const struct map_rec *rec_now = map->rec_array[i];
492+
if (rec_prev->ipfix.source != MAP_SRC_IPFIX || rec_now->ipfix.source != MAP_SRC_IPFIX) {
493+
rec_prev = rec_now;
494+
continue;
495+
}
496+
458497
if (rec_prev->ipfix.en != rec_now->ipfix.en || rec_prev->ipfix.id != rec_now->ipfix.id) {
459498
rec_prev = rec_now;
460499
continue;

extra_plugins/output/unirec/src/map.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,27 @@
4949
/** Internal map type */
5050
typedef struct map_s map_t;
5151

52+
/** Source field */
53+
enum MAP_SRC {
54+
/** Invalid (internal value) */
55+
MAP_SRC_INVALID,
56+
/** IPFIX field */
57+
MAP_SRC_IPFIX,
58+
/** Internal "link bit field" converter */
59+
MAP_SRC_INTERNAL_LBF,
60+
/** Internal "dir bit field" converter */
61+
MAP_SRC_INTERNAL_DBF
62+
};
63+
5264
/** IPFIX-to-UniRec mapping record */
5365
struct map_rec {
5466
struct {
67+
/**
68+
* \brief Data source
69+
* \note If the field is not ::MAP_SRC_IPFIX, parameters en, id and def are NOT defined!
70+
*/
71+
enum MAP_SRC source;
72+
5573
/** Private Enterprise Number */
5674
uint32_t en;
5775
/** Information Element ID */

0 commit comments

Comments
 (0)