Skip to content

Commit eefe4d9

Browse files
authored
Merge pull request #21 from CESNET/sedlak-filter
IPFIX Filter: add biflow support
2 parents 2c397b5 + e130d20 commit eefe4d9

2 files changed

Lines changed: 74 additions & 7 deletions

File tree

include/libfds/ipfix_filter.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ extern "C" {
1111

1212
typedef struct fds_ipfix_filter fds_ipfix_filter_t;
1313

14+
/**
15+
* The match result, see fds_ipfix_filter_eval_biflow
16+
*/
17+
enum fds_ipfix_filter_match {
18+
FDS_IPFIX_FILTER_NO_MATCH = 0,
19+
FDS_IPFIX_FILTER_MATCH_FWD = 1,
20+
FDS_IPFIX_FILTER_MATCH_REV = 2,
21+
FDS_IPFIX_FILTER_MATCH_BOTH = 3,
22+
};
23+
1424
/**
1525
*
1626
* Creates an IPFIX filter from an expression.
@@ -38,6 +48,20 @@ fds_ipfix_filter_create(fds_ipfix_filter_t **ipxfil, const fds_iemgr_t *iemgr, c
3848
FDS_API bool
3949
fds_ipfix_filter_eval(struct fds_ipfix_filter *ipxfil, struct fds_drec *record);
4050

51+
/**
52+
* Evaluates the IPFIX filter using the provided data record also considering biflow.
53+
*
54+
* \param[in] ipxfil The IPFIX filter
55+
* \param[in] record A data record
56+
*
57+
* \return FDS_IPFIX_FILTER_MATCH_BOTH if both directions matched
58+
* FDS_IPFIX_FILTER_MATCH_FWD if only forward direction matched
59+
* FDS_IPFIX_FILTER_MATCH_REV if only reverse direction matched
60+
* FDS_IPFIX_FILTER_NO_MATCH if no direction matched
61+
*/
62+
FDS_API enum fds_ipfix_filter_match
63+
fds_ipfix_filter_eval_biflow(struct fds_ipfix_filter *ipxfil, struct fds_drec *record);
64+
4165
/**
4266
* Destroys the IPFIX filter.
4367
*

src/ipfix_filter/ipfix_filter.c

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ struct ipxfil_lookup_table {
6969

7070
struct ipxfil_lookup_state {
7171
size_t source_idx;
72+
uint16_t find_flags; // 0, FDS_DREC_BIFLOW_FWD or FDS_DREC_BIFLOW_REV
7273
};
7374

7475
struct fds_ipfix_filter {
@@ -81,6 +82,27 @@ struct fds_ipfix_filter {
8182
struct ipxfil_lookup_state lookup_state;
8283
};
8384

85+
/**
86+
* Same as fds_drec_find, but with flags (see fds_drec_iter_init documentation).
87+
*/
88+
static int
89+
fds_drec_find_with_flags(struct fds_drec *drec, uint32_t pen, uint16_t id, uint16_t flags, struct fds_drec_field *field)
90+
{
91+
if (flags == 0) {
92+
return fds_drec_find(drec, pen, id, field);
93+
94+
} else {
95+
struct fds_drec_iter iter;
96+
fds_drec_iter_init(&iter, drec, flags);
97+
98+
int ret = fds_drec_iter_find(&iter, pen, id);
99+
if (ret != FDS_EOC) {
100+
*field = iter.field;
101+
}
102+
return ret;
103+
}
104+
}
105+
84106
/**
85107
* Calculate index of a lookup item in a lookup table
86108
*/
@@ -293,13 +315,13 @@ set_default_value(fds_filter_value_u *out_value)
293315
* Try to read the desired field from a record into a filter value
294316
*/
295317
static int
296-
read_record_field(struct fds_drec *record, const struct fds_iemgr_elem *field_def,
318+
read_record_field(struct fds_drec *record, const struct fds_iemgr_elem *field_def, uint16_t find_flags,
297319
fds_filter_value_u *out_value)
298320
{
299321
struct fds_drec_field field;
300322

301323
// The wanted field does not exist in the record
302-
if (fds_drec_find(record, field_def->scope->pen, field_def->id, &field) == FDS_EOC) {
324+
if (fds_drec_find_with_flags(record, field_def->scope->pen, field_def->id, find_flags, &field) == FDS_EOC) {
303325
return FDS_ERR_NOTFOUND;
304326
}
305327

@@ -390,13 +412,13 @@ read_record_field(struct fds_drec *record, const struct fds_iemgr_elem *field_de
390412
* Read the first source that is found in the record
391413
*/
392414
static bool
393-
read_first_of(struct fds_drec *record, const struct fds_iemgr_alias *alias, size_t *source_idx,
415+
read_first_of(struct fds_drec *record, const struct fds_iemgr_alias *alias, size_t *source_idx, uint16_t find_flags,
394416
fds_filter_value_u *out_value)
395417
{
396418
while (*source_idx < alias->sources_cnt) {
397419
const struct fds_iemgr_elem *field_def = alias->sources[*source_idx];
398420
(*source_idx)++;
399-
if (read_record_field(record, field_def, out_value) == FDS_OK) {
421+
if (read_record_field(record, field_def, find_flags, out_value) == FDS_OK) {
400422
return true;
401423
}
402424
}
@@ -427,7 +449,7 @@ data_callback(void *user_ctx, bool reset_ctx, int id, void *data, fds_filter_val
427449
case FDS_ALIAS_FIRST_OF:
428450
if (reset_ctx) {
429451
ipxfil->lookup_state.source_idx = 0;
430-
return read_first_of(rec, item->alias, &ipxfil->lookup_state.source_idx, out_value)
452+
return read_first_of(rec, item->alias, &ipxfil->lookup_state.source_idx, ipxfil->lookup_state.find_flags, out_value)
431453
? FDS_OK : FDS_ERR_NOTFOUND;
432454
}
433455
set_default_value(out_value);
@@ -437,15 +459,15 @@ data_callback(void *user_ctx, bool reset_ctx, int id, void *data, fds_filter_val
437459
if (reset_ctx) {
438460
ipxfil->lookup_state.source_idx = 0;
439461
}
440-
return read_first_of(rec, item->alias, &ipxfil->lookup_state.source_idx, out_value)
462+
return read_first_of(rec, item->alias, &ipxfil->lookup_state.source_idx, ipxfil->lookup_state.find_flags, out_value)
441463
? FDS_OK_MORE : FDS_ERR_NOTFOUND;
442464
default:
443465
assert(0);
444466
}
445467
break;
446468

447469
case IPXFIL_FIELD_LOOKUP: {
448-
int rc = read_record_field(rec, item->elem, out_value);
470+
int rc = read_record_field(rec, item->elem, ipxfil->lookup_state.find_flags, out_value);
449471
if (rc != FDS_OK) {
450472
set_default_value(out_value);
451473
}
@@ -491,9 +513,30 @@ bool
491513
fds_ipfix_filter_eval(struct fds_ipfix_filter *ipxfil, struct fds_drec *record)
492514
{
493515
ipxfil->lookup_state.source_idx = 0;
516+
ipxfil->lookup_state.find_flags = 0;
494517
return fds_filter_eval(ipxfil->filter, record);
495518
}
496519

520+
enum fds_ipfix_filter_match
521+
fds_ipfix_filter_eval_biflow(struct fds_ipfix_filter *ipxfil, struct fds_drec *record)
522+
{
523+
int result = 0;
524+
525+
ipxfil->lookup_state.source_idx = 0;
526+
ipxfil->lookup_state.find_flags = FDS_DREC_BIFLOW_FWD;
527+
if (fds_filter_eval(ipxfil->filter, record)) {
528+
result |= FDS_IPFIX_FILTER_MATCH_FWD;
529+
}
530+
531+
ipxfil->lookup_state.source_idx = 0;
532+
ipxfil->lookup_state.find_flags = FDS_DREC_BIFLOW_REV;
533+
if (fds_filter_eval(ipxfil->filter, record)) {
534+
result |= FDS_IPFIX_FILTER_MATCH_REV;
535+
}
536+
537+
return result;
538+
}
539+
497540
void
498541
fds_ipfix_filter_destroy(struct fds_ipfix_filter *ipxfil)
499542
{

0 commit comments

Comments
 (0)