Skip to content

Commit fa2785b

Browse files
committed
Add fixed but fast csv output mode csv-fast. See #548
1 parent 87ee686 commit fa2785b

File tree

5 files changed

+118
-4
lines changed

5 files changed

+118
-4
lines changed

src/output/Makefile.am

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ AM_CPPFLAGS = -I.. -I../include -I../libnffile -I../libnfdump -I../inline $(DEPS
44
noinst_LIBRARIES = liboutput.a
55

66
liboutput_a_SOURCES = output.c output.h \
7-
output_util.c output_util.h output_csv.c output_csv.h \
8-
output_fmt.c output_fmt.h output_json.c output_json.h \
9-
output_raw.c output_raw.h
7+
output_util.c output_util.h output_raw.c output_raw.h \
8+
output_csv.c output_csv.h output_csv_fast.c \
9+
output_fmt.c output_fmt.h output_json.c output_json.h
1010

1111
EXTRA_DIST = itoa.c
1212

src/output/output.c

+2
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ static struct printmap_s {
105105
{"json", MODE_JSON, NULL, "json output"},
106106
{"json-log", MODE_JSON_LOG, NULL, "json output for logging"},
107107
{"csv", MODE_CSV, FORMAT_CSV, "csv predefined"},
108+
{"csv-fast", MODE_CSV_FAST, NULL, "csv fast predefined"},
108109
{"null", MODE_NULL, NULL, "do not print any output"},
109110

110111
// This is always the last line
@@ -119,6 +120,7 @@ static struct printerFunc_s {
119120
[MODE_FMT] = {fmt_record, fmt_prolog, fmt_epilog},
120121
[MODE_RAW] = {raw_record, raw_prolog, raw_epilog},
121122
[MODE_CSV] = {csv_record, csv_prolog, csv_epilog},
123+
[MODE_CSV_FAST] = {csv_record_fast, csv_prolog_fast, csv_epilog_fast},
122124
[MODE_JSON] = {flow_record_to_json_human, json_prolog, json_epilog},
123125
[MODE_JSON_LOG] = {flow_record_to_json_log, json_prolog, json_epilog}};
124126

src/output/output.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ typedef void (*RecordPrinter_t)(FILE *, recordHandle_t *, int);
4040
typedef void (*PrologPrinter_t)(void);
4141
typedef void (*EpilogPrinter_t)(void);
4242

43-
typedef enum { MODE_NULL = 0, MODE_RAW, MODE_FMT, MODE_CSV, MODE_JSON, MODE_JSON_LOG } outputMode_t;
43+
typedef enum { MODE_NULL = 0, MODE_RAW, MODE_FMT, MODE_CSV, MODE_CSV_FAST, MODE_JSON, MODE_JSON_LOG } outputMode_t;
4444

4545
typedef struct outputParams_s {
4646
bool printPlain;

src/output/output_csv.h

+6
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,10 @@ void csv_epilog(void);
4444

4545
void csv_record(FILE *stream, recordHandle_t *recordHandle, int tag);
4646

47+
void csv_prolog_fast(void);
48+
49+
void csv_epilog_fast(void);
50+
51+
void csv_record_fast(FILE *stream, recordHandle_t *recordHandle, int tag);
52+
4753
#endif // _OUTPUT_CSV_H

src/output/output_csv_fast.c

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Copyright (c) 2024, Peter Haag
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* * Redistributions of source code must retain the above copyright notice,
9+
* this list of conditions and the following disclaimer.
10+
* * Redistributions in binary form must reproduce the above copyright notice,
11+
* this list of conditions and the following disclaimer in the documentation
12+
* and/or other materials provided with the distribution.
13+
* * Neither the name of the author nor the names of its contributors may be
14+
* used to endorse or promote products derived from this software without
15+
* specific prior written permission.
16+
*
17+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27+
* POSSIBILITY OF SUCH DAMAGE.
28+
*
29+
*/
30+
31+
#include <arpa/inet.h>
32+
#include <inttypes.h>
33+
#include <netinet/in.h>
34+
#include <stddef.h>
35+
#include <stdint.h>
36+
#include <stdio.h>
37+
#include <string.h>
38+
#include <sys/socket.h>
39+
#include <sys/types.h>
40+
#include <time.h>
41+
42+
#include "nfxV3.h"
43+
#include "output_csv.h"
44+
#include "output_util.h"
45+
#include "util.h"
46+
47+
#define IP_STRING_LEN (INET6_ADDRSTRLEN)
48+
49+
// record counter
50+
static uint32_t recordCount;
51+
52+
void csv_prolog_fast(void) {
53+
// empty prolog
54+
recordCount = 0;
55+
printf("cnt,af,firstSeen,lastSeen,proto,srcAddr,srcPort,dstAddr,dstPort,srcAS,dstAS,input,output,flags,srcTos,packets,bytes\n");
56+
} // End of csv_prolog_fast
57+
58+
void csv_epilog_fast(void) {
59+
// empty epilog
60+
} // End of csv_epilog_fast
61+
62+
void csv_record_fast(FILE *stream, recordHandle_t *recordHandle, int tag) {
63+
EXgenericFlow_t *genericFlow = (EXgenericFlow_t *)recordHandle->extensionList[EXgenericFlowID];
64+
EXipv4Flow_t *ipv4Flow = (EXipv4Flow_t *)recordHandle->extensionList[EXipv4FlowID];
65+
EXipv6Flow_t *ipv6Flow = (EXipv6Flow_t *)recordHandle->extensionList[EXipv6FlowID];
66+
EXflowMisc_t *flowMisc = (EXflowMisc_t *)recordHandle->extensionList[EXflowMiscID];
67+
EXasRouting_t *asRouting = (EXasRouting_t *)recordHandle->extensionList[EXasRoutingID];
68+
69+
EXgenericFlow_t genericNull = {0};
70+
if (!genericFlow) genericFlow = &genericNull;
71+
72+
EXflowMisc_t miscNull = {0};
73+
if (!flowMisc) flowMisc = &miscNull;
74+
75+
EXasRouting_t asNULL = {0};
76+
if (!asRouting) asRouting = &asNULL;
77+
78+
int af = 0;
79+
char sa[IP_STRING_LEN], da[IP_STRING_LEN];
80+
if (ipv4Flow) {
81+
af = PF_INET;
82+
uint32_t src = htonl(ipv4Flow->srcAddr);
83+
uint32_t dst = htonl(ipv4Flow->dstAddr);
84+
85+
inet_ntop(AF_INET, &src, sa, sizeof(sa));
86+
inet_ntop(AF_INET, &dst, da, sizeof(da));
87+
}
88+
89+
if (ipv6Flow) {
90+
af = PF_INET6;
91+
uint64_t src[2], dst[2];
92+
src[0] = htonll(ipv6Flow->srcAddr[0]);
93+
src[1] = htonll(ipv6Flow->srcAddr[1]);
94+
dst[0] = htonll(ipv6Flow->dstAddr[0]);
95+
dst[1] = htonll(ipv6Flow->dstAddr[1]);
96+
97+
inet_ntop(AF_INET6, &src, sa, sizeof(sa));
98+
inet_ntop(AF_INET6, &dst, da, sizeof(da));
99+
}
100+
101+
fprintf(stream, "%u,%i,%" PRIu64 ",%" PRIu64 ",%u,%s,%u,%s,%u,%u,%u,%u,%u,%s,%u,%" PRIu64 ",%" PRIu64 "\n", ++recordCount, af,
102+
genericFlow->msecFirst, genericFlow->msecLast, genericFlow->proto, sa, genericFlow->srcPort, da, genericFlow->dstPort, asRouting->srcAS,
103+
asRouting->dstAS, flowMisc->input, flowMisc->output, FlagsString(genericFlow->proto == IPPROTO_TCP ? genericFlow->tcpFlags : 0),
104+
genericFlow->srcTos, genericFlow->inPackets, genericFlow->inBytes);
105+
106+
} // End of csv_record_fast

0 commit comments

Comments
 (0)