Connection-less Collector

How-To use libfixbuf with just a data buffer:

To use fixbuf independent of the transport mode, the application must create an fbInfoModel_t using fbInfoModelAlloc() and any additional, vendor-specific information elements using fbInfoModelAddElement(), fbInfoModelAddElementArray(), fbInfoModelReadXMLFile(), or fbInfoModelReadXMLData(). Next create an fbSession_t using fbSessionAlloc() and add internal templates via fbSessionAddTemplate(). The application will handle all connections and reading and simply pass fixbuf the buffer to be decoded. The buffer must contain valid IPFIX and should begin with the standard IPFIX header. Ideally, the application should provide the necessary templates before any data records to ensure that the application can decode all of the data records.

The application should NOT create an fbCollector. To create the fBuf, use fBufAllocForCollection() and set the second parameter to NULL. The application then has everything needed to start reading from the IPFIX source. Ideally, the application will read the first 4 bytes of the message first to determine the length of the next IPFIX message. The first 2 bytes are the IPFIX version (0x000A) and the third and fourth bytes are the length of the following IPFIX message (including the IPFIX message header). The application should then continue reading the length of the IPFIX message into an allocated buffer. The buffer should then be set on the fBuf by calling fBufSetBuffer(). The application will continue to call fBufNext() to receive the data records until fBufNext() returns FALSE with error code FB_ERROR_BUFSZ. However, if the fBuf is in manual mode fbufSetAutomaticMode(buf, FALSE) AND the application was reading the message length, fixbuf will first return an FB_ERROR_EOM which will signal to the application to perform another read (if the application ignores FB_ERROR_EOM errors and calls fBufNext(), fBufNext() will then return FB_ERROR_BUFSZ). This error notifies the application that there is not enough data in the buffer to read a full IPFIX message. If the application only read the size of the IPFIX message, the entire buffer should have been read. However, if the application was reading more than the IPFIX message length, additional data may remain in the buffer that belongs to the next IPFIX message. To determine how much data was left in the buffer unread, fBufRemaining() will return the length of the buffer that was not processed. That remaining data should be copied to the beginning of the buffer and the remaining IPFIX message data should be read. After each read, the application needs to call fBufSetBuffer(). Note that fBufSetBuffer() sets the collector and exporter on the fBuf to NULL. The application should clear the FB_ERROR_BUFSZ and/or FB_ERROR_EOM error when they occur using g_clear_error().

fixbuf may return the following error codes if it encounters one of the below issues. The application should determine the error and respond appropriately.

  • FB_ERROR_IPFIX
    • If the first 2 bytes != 0x000A
    • If the length in the header < 16
  • FB_ERROR_EOM
    • If the application read only the message length and the application called fBufSetAutomatic(fbuf, FALSE) (the fBuf is in manual mode). This means the remaining buffer length == 0 and the application should clear the error and perform another read
  • FB_ERROR_BUFSZ
    • If the header message length > the given buffer length
    • if the given buffer == NULL
    • If the given buffer length < 16
    • If buffer length == 0
  Example usage:
* FILE *fp;
* uint8_t buf[65535];
* ...
* rc = fread(buf, 1, 4, fp);
* if (rc > 0) {
* len = ntohs(*((uint16_t *)(buf+2)));
* rc = fread(buf+4, 1, len-4, fp);
* if (rc > 0) {
* fBufSetBuffer(fbuf, buf, rc+4);
* } else if (feof(fp))
* ....
* while (1) {
* ret = fBufNext(fbuf, (uint8_t *)rec, &len, &err);
* if (FALSE == ret) {
* if (g_error_matches(err, FB_ERROR_DOMAIN, FB_ERROR_BUFSZ)){
* rem = fBufRemaining(fbuf);
* g_clear_error(&err);
* break;
* }
* }
* }
*