@@ -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 */
191191static 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 ;
0 commit comments