Skip to content

Commit 41ea771

Browse files
committed
Core [extensions]: add incomplete implementation of extensions of Data Record [WIP]
1 parent 6ed75d8 commit 41ea771

File tree

6 files changed

+297
-21
lines changed

6 files changed

+297
-21
lines changed

include/ipfixcol2/message_ipfix.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ extern "C" {
5151

5252
#include <ipfixcol2/api.h>
5353
#include "session.h"
54-
#include "plugins.h"
5554

5655
/**
5756
* \defgroup ipxMsgIPFIX IPFIX message
@@ -105,6 +104,8 @@ struct ipx_ipfix_record {
105104
uint8_t ext[1];
106105
};
107106

107+
#include "plugins.h"
108+
108109
/**
109110
* \brief Create an empty wrapper around IPFIX (or NetFlow) Message
110111
*

include/ipfixcol2/plugins.h

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
* \file include/ipfixcol2/plugins.h
33
* \author Lukas Hutak <[email protected]>
44
* \brief IPFIXcol plugin interface and functions (header file)
5-
* \date 2018
5+
* \date 2018-2020
66
*/
77

8-
/* Copyright (C) 2018 CESNET, z.s.p.o.
8+
/* Copyright (C) 2018-2020 CESNET, z.s.p.o.
99
*
1010
* Redistribution and use in source and binary forms, with or without
1111
* modification, are permitted provided that the following conditions
@@ -49,12 +49,13 @@ extern "C" {
4949
/** Internal plugin context */
5050
typedef struct ipx_ctx ipx_ctx_t;
5151
/** Internal data structure that represents IPFIXcol record extension */
52-
typedef struct ipx_ctx_rext ipx_ctx_rext_t;
52+
typedef struct ipx_ctx_ext ipx_ctx_ext_t;
5353

5454
#include <ipfixcol2/api.h>
5555
#include <ipfixcol2/verbose.h>
5656
#include <ipfixcol2/session.h>
5757
#include <ipfixcol2/message.h>
58+
#include <ipfixcol2/message_ipfix.h>
5859

5960
/**
6061
* \defgroup pluginAPI Plugin API
@@ -397,7 +398,7 @@ IPX_API const fds_iemgr_t *
397398
ipx_ctx_iemgr_get(ipx_ctx_t *ctx);
398399

399400
/**
400-
* \brief Register an extension of Data Records (Intermediate and Output plugins ONLY!)
401+
* \brief Register an extension of Data Records (Intermediate plugins ONLY!)
401402
*
402403
* Reserve space for metadata that will be part of each Data Record. The purpose of extension
403404
* it is to add non-flow information which can be useful during record processing. For example,
@@ -406,28 +407,32 @@ ipx_ctx_iemgr_get(ipx_ctx_t *ctx);
406407
*
407408
* Structure or data type of the extension is up to the producer. Nevertheless, the producer and
408409
* all consumers must use the same. The producer is also RESPONSIBLE for filling content of the
409-
* extension to EACH Data Record in the IPFIX Message!
410+
* extension to EACH Data Record in the IPFIX Message! After filling the extension, function
411+
* ipx_ctx_ext_set_filled() must be called to mark the extension memory as filled. Otherwise,
412+
* consumers are not able get its content.
410413
*
411414
* One plugin instance can register multiple extensions.
412415
* \warning
413-
* This function can be called only during ipx_plugin_init() of Intermediate and Output plugins.
416+
* This function can be called only during ipx_plugin_init() of Intermediate plugins.
414417
* \note
415418
* Only single plugin instance at time can produce extension with the given combination
416419
* of the \p type and the \p name.
417420
* \param[in] ctx Plugin context
418421
* \param[in] type Identification of the extension type (e.g. "profiles-v1")
419422
* \param[in] name Identification of the extension name (e.g. "main_profiles")
420-
* \param[in] size Size of memory required for the extension (in bytes)
421-
* \param[out] rext Internal description of the extension
423+
* \param[in] size Non-zero size of memory required for the extension (in bytes)
424+
* \param[out] ext Internal description of the extension
422425
*
423426
* \return #IPX_OK on success
424-
* \return #IPX_ERR_ARG if the \p type or \p name are not valid (i.e. empty or NULL)
427+
* \return #IPX_ERR_ARG if the \p type or \p name are not valid (i.e. empty or NULL) or \p size
428+
* is zero.
425429
* \return #IPX_ERR_DENIED if the plugin doesn't have permission to register extension
426-
* \return #IPX_ERR_NOMEM if the maximum number of extensions has been reached
430+
* \return #IPX_ERR_EXISTS if the extension or dependency has been already registered by this plugin
431+
* \return #IPX_ERR_NOMEM if a memory allocation failure has occurred
427432
*/
428433
IPX_API int
429-
ipx_ctx_rext_producer(ipx_ctx_t *ctx, const char *type, const char *name, size_t size,
430-
ipx_ctx_rext **rext);
434+
ipx_ctx_ext_producer(ipx_ctx_t *ctx, const char *type, const char *name, size_t size,
435+
ipx_ctx_ext_t **ext);
431436

432437
/**
433438
* @brief Add dependency on an extension of Data Records (Intermediate and Output plugins ONLY!)
@@ -450,37 +455,50 @@ ipx_ctx_rext_producer(ipx_ctx_t *ctx, const char *type, const char *name, size_t
450455
* \param[in] ctx Plugin context
451456
* \param[in] type Identification of the extension type (e.g. "profiles-v1")
452457
* \param[in] name Identification of the extension name (e.g. "main_profiles")
453-
* \param[out] rext Internal description of the extension
458+
* \param[out] ext Internal description of the extension
454459
*
455460
* \return #IPX_OK on success (see notes)
456461
* \return #IPX_ERR_ARG if the \p type or \p name are not valid (i.e. empty or NULL)
457462
* \return #IPX_ERR_DENIED if the plugin doesn't have permission to register dependency
458-
* \return #IPX_ERR_NOMEM if the maximum number of extensions has been reached
463+
* \return #IPX_ERR_EXISTS if the dependency or extension has been already registered by this plugin
464+
* \return #IPX_ERR_NOMEM if a memory allocation failure has occurred
459465
*/
460466
IPX_API int
461-
ipx_ctx_rext_consumer(ipx_ctx_t *ctx, const char *type, const char *name, ipx_ctx_rext_t **rext);
467+
ipx_ctx_ext_consumer(ipx_ctx_t *ctx, const char *type, const char *name, ipx_ctx_ext_t **ext);
462468

463469
/**
464470
* \brief Get size of an extension
465471
*
466472
* Information about the extension are not available during ipx_plugin_init().
467-
* \param[in] rext Internal description of the extension
473+
* \param[in] ext Internal description of the extension
468474
* \param[out] size Size of the extension
469475
* \return #IPX_OK on success
470476
* \return #IPX_ERR_DENIED if the information is not available
471477
*/
472478
IPX_API int
473-
ipx_ctx_rext_size(ipx_ctx_rext *rext, size_t *size);
479+
ipx_ctx_ext_size(ipx_ctx_ext_t *ext, size_t *size);
474480

475481
/**
476482
* \brief Get data of an extension
477483
*
478-
* \param[in] rext Internal description of the extension
484+
* \note
485+
* In case of a consumer, the function can return NULL if the extension hasn't been filled
486+
* by the producer!
487+
* \param[in] ext Internal description of the extension
479488
* \param[in] ipx_drec Data Record with extensions
480-
* \return Pointer to the extension
489+
* \return Pointer to the extension or NULL
481490
*/
482491
IPX_API void *
483-
ipx_ctx_rext_get(ipx_ctx_rext *rext, struct ipx_ipfix_record *ipx_drec);
492+
ipx_ctx_ext_get(ipx_ctx_ext_t *ext, struct ipx_ipfix_record *ipx_drec);
493+
494+
/**
495+
* \brief Set the extension of a Data Record as filled (ONLY for the producer of the extension)
496+
*
497+
* \param[in] ext Internal description of the extension
498+
* \param[in] ipx_drec Data Record with extensions
499+
*/
500+
IPX_API void
501+
ipx_ctx_ext_set_filled(ipx_ctx_ext_t *ext, struct ipx_ipfix_record *ipx_drec);
484502

485503
/**
486504
* @}

src/core/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ set(CORE_SOURCE
2828
api.c
2929
context.c
3030
context.h
31+
extension.c
32+
extension.h
3133
fpipe.c
3234
fpipe.h
3335
message_base.c

src/core/context.c

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include <sys/prctl.h>
4848

4949
#include "context.h"
50+
#include "extension.h"
5051
#include "verbose.h"
5152
#include "utils.h"
5253
#include "fpipe.h"
@@ -150,6 +151,13 @@ struct ipx_ctx {
150151
*/
151152
unsigned int term_msg_cnt;
152153
} cfg_system; /**< System configuration */
154+
155+
struct {
156+
/** Array of extensions (producers and consumers) */
157+
struct ipx_ctx_ext *items;
158+
/** Size of extension definitions in the array */
159+
size_t items_cnt;
160+
} cfg_extension; /**< Extension configuration */
153161
};
154162

155163
ipx_ctx_t *
@@ -177,6 +185,9 @@ ipx_ctx_create(const char *name, const struct ipx_ctx_callbacks *callbacks)
177185
ctx->cfg_system.msg_mask_allowed = IPX_MSG_IPFIX | IPX_MSG_SESSION;
178186
ctx->cfg_system.term_msg_cnt = 1; // By default, wait for 1 termination message
179187

188+
ctx->cfg_extension.items = NULL;
189+
ctx->cfg_extension.items_cnt = 0;
190+
180191
if (callbacks == NULL) {
181192
// Dummy context for testing
182193
ctx->permissions = IPX_CP_MSG_PASS;
@@ -215,6 +226,13 @@ ipx_ctx_destroy(ipx_ctx_t *ctx)
215226
ctx->pipeline.dst = tmp;
216227
}
217228

229+
// Destroy all extensions
230+
for (size_t idx = 0; idx < ctx->cfg_extension.items_cnt; ++idx) {
231+
struct ipx_ctx_ext *ext = &ctx->cfg_extension.items[idx];
232+
ipx_ctx_ext_destroy(ext);
233+
}
234+
free(ctx->cfg_extension.items);
235+
218236
free(ctx->name);
219237
free(ctx);
220238
}
@@ -358,6 +376,108 @@ ipx_ctx_ring_dst_set(ipx_ctx_t *ctx, ipx_ring_t *ring)
358376
}
359377

360378

379+
// -------------------------------------------------------------------------------------------------
380+
381+
/**
382+
* @brief Create a new extension record
383+
*
384+
* First, make sure that the extension hasn't been previously added. Then append a new
385+
* (uninitialized) record to the array of extensions.
386+
*
387+
* @param[in] ctx Plugin context
388+
* @param[in] type Identification of extension type
389+
* @param[in] name Identification of extension name
390+
* @return #IPX_OK on success
391+
* @return #IPX_ERR_EXISTS if the extension has been already defined
392+
* @return #IPX_ERR_ARG if @p type or @p name are not valid strings
393+
* @return #IPX_ERR_NOMEM in case of a memory allocation error
394+
*/
395+
static int
396+
ipx_ctx_ext_create(ipx_ctx_t *ctx, const char *type, const char *name)
397+
{
398+
size_t new_size, alloc_size;
399+
struct ipx_ctx_ext *new_items = NULL;
400+
401+
if (!type || !name) {
402+
return IPX_ERR_ARG;
403+
}
404+
405+
// Try to find it
406+
for (size_t idx = 0; idx < ctx->cfg_extension.items_cnt; ++idx) {
407+
const struct ipx_ctx_ext *rec = &ctx->cfg_extension.items[idx];
408+
if (strcmp(type, rec->data_type) != 0 || strcmp(name, rec->data_name) != 0) {
409+
continue;
410+
}
411+
412+
return IPX_ERR_EXISTS;
413+
}
414+
415+
// Create a new record
416+
new_size = ctx->cfg_extension.items_cnt + 1U;
417+
alloc_size = new_size * sizeof(struct ipx_ctx_ext);
418+
new_items = realloc(ctx->cfg_extension.items, alloc_size);
419+
if (!new_items) {
420+
IPX_CTX_ERROR(ctx, "%s(): Memory allocation failed", __func__);
421+
return IPX_ERR_NOMEM;
422+
}
423+
424+
ctx->cfg_extension.items = new_items;
425+
ctx->cfg_extension.items_cnt = new_size;
426+
return IPX_OK;
427+
}
428+
429+
int
430+
ipx_ctx_ext_producer(ipx_ctx_t *ctx, const char *type, const char *name, size_t size,
431+
ipx_ctx_ext_t **ext)
432+
{
433+
struct ipx_ctx_ext *rec = NULL;
434+
int rc = IPX_OK;
435+
436+
// Check permissions (only intermediate plugins during initialization)
437+
if (ctx->type != IPX_PT_INTERMEDIATE || ctx->state != IPX_CS_NEW) {
438+
return IPX_ERR_DENIED;
439+
}
440+
441+
if ((rc = ipx_ctx_ext_create(ctx, type, name)) != IPX_OK) {
442+
return rc;
443+
}
444+
445+
rec = &ctx->cfg_extension.items[ctx->cfg_extension.items_cnt - 1];
446+
if ((rc = ipx_ctx_ext_init(rec, IPX_EXTENSION_PRODUCER, type, name, size)) != IPX_OK) {
447+
ctx->cfg_extension.items_cnt--; // The added extension is not valid!
448+
return rc;
449+
}
450+
451+
*ext = rec;
452+
return IPX_OK;
453+
}
454+
455+
int
456+
ipx_ctx_ext_consumer(ipx_ctx_t *ctx, const char *type, const char *name, ipx_ctx_ext_t **ext)
457+
{
458+
struct ipx_ctx_ext *rec = NULL;
459+
int rc = IPX_OK;
460+
461+
// Check permissions (only intermediate and output plugins during initialization) + duplicities
462+
if ((ctx->type != IPX_PT_INTERMEDIATE && ctx->type != IPX_PT_OUTPUT)
463+
|| ctx->state != IPX_CS_NEW) {
464+
return IPX_ERR_DENIED;
465+
}
466+
467+
if ((rc = ipx_ctx_ext_create(ctx, type, name)) != IPX_OK) {
468+
return rc;
469+
}
470+
471+
rec = &ctx->cfg_extension.items[ctx->cfg_extension.items_cnt - 1];
472+
if ((rc = ipx_ctx_ext_init(rec, IPX_EXTENSION_CONSUMER, type, name, 0)) != IPX_OK) {
473+
ctx->cfg_extension.items_cnt--; // The added extension is not valid!
474+
return rc;
475+
}
476+
477+
*ext = rec;
478+
return IPX_OK;
479+
}
480+
361481
// -------------------------------------------------------------------------------------------------
362482

363483
/**

src/core/extension.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
2+
#include "extension.h"
3+
#include <ipfixcol2/plugins.h>
4+
#include <stdlib.h>
5+
#include <string.h>
6+
7+
int
8+
ipx_ctx_ext_size(ipx_ctx_ext_t *ext, size_t *size)
9+
{
10+
if (!ext->mask) {
11+
// Mask is not filled -> initialization hasn't been completed yet
12+
return IPX_ERR_DENIED;
13+
}
14+
15+
*size = ext->size;
16+
return IPX_OK;
17+
}
18+
19+
void *
20+
ipx_ctx_ext_get(ipx_ctx_ext_t *ext, struct ipx_ipfix_record *ipx_drec)
21+
{
22+
if (ext->etype == IPX_EXTENSION_CONSUMER) {
23+
// TODO: check if the memory has been filled (only for consumers)
24+
return NULL;
25+
}
26+
27+
return (ipx_drec->ext + ext->offset);
28+
}
29+
30+
void
31+
ipx_ctx_ext_set_filled(ipx_ctx_ext_t *ext, struct ipx_ipfix_record *ipx_drec)
32+
{
33+
if (ext->etype != IPX_EXTENSION_PRODUCER) {
34+
return; // Not allowed!
35+
}
36+
37+
// TODO: label the extension as filled!
38+
}
39+
40+
int
41+
ipx_ctx_ext_init(struct ipx_ctx_ext *ext, enum ipx_extension etype, const char *data_type,
42+
const char *data_name, size_t size)
43+
{
44+
// Check parameters
45+
if (!data_name || !data_type || strlen(data_type) == 0 || strlen(data_name) == 0) {
46+
return IPX_ERR_ARG;
47+
}
48+
if (etype != IPX_EXTENSION_CONSUMER && etype != IPX_EXTENSION_PRODUCER) {
49+
return IPX_ERR_ARG;
50+
}
51+
if (etype == IPX_EXTENSION_PRODUCER && size == 0) {
52+
return IPX_ERR_ARG;
53+
}
54+
55+
ext->etype = etype;
56+
ext->size = (etype == IPX_EXTENSION_PRODUCER) ? size : 0;
57+
ext->data_type = strdup(data_type);
58+
ext->data_name = strdup(data_name);
59+
if (!ext->data_type || !ext->data_name) {
60+
free(ext->data_type);
61+
free(ext->data_name);
62+
return IPX_ERR_NOMEM;
63+
}
64+
65+
ext->offset = 0;
66+
ext->mask = 0;
67+
return IPX_OK;
68+
}
69+
70+
void
71+
ipx_ctx_ext_destroy(struct ipx_ctx_ext *ext)
72+
{
73+
free(ext->data_name);
74+
free(ext->data_type);
75+
}
76+

0 commit comments

Comments
 (0)