11#if PC_ENABLE_FLOW_EXPORT
17size_t flow_v5_write_header(uint8_t *buf,
size_t cap,
const FlowV5Header *h)
19 if (!buf || !h || cap < FLOW_V5_HEADER_SIZE)
29 p +=
pc_wr32be(buf + p, h->flow_sequence);
30 buf[p++] = h->engine_type;
31 buf[p++] = h->engine_id;
32 p +=
pc_wr16be(buf + p, h->sampling_interval);
36size_t flow_v5_write_record(uint8_t *buf,
size_t cap,
const FlowV5Record *r)
38 if (!buf || !r || cap < FLOW_V5_RECORD_SIZE)
55 buf[p++] = r->tcp_flags;
60 buf[p++] = r->src_mask;
61 buf[p++] = r->dst_mask;
69static void w_u16(FlowWriter *w, uint16_t v)
75 if (w->pos + 2 > w->cap)
83static void w_u32(FlowWriter *w, uint32_t v)
89 if (w->pos + 4 > w->cap)
97static void w_bytes(FlowWriter *w,
const uint8_t *p,
size_t n)
103 if (w->pos + n > w->cap)
108 memcpy(w->buf + w->pos, p, n);
113static void w_zero(FlowWriter *w,
size_t n)
119 if (w->pos + n > w->cap)
124 memset(w->buf + w->pos, 0, n);
128static void patch16(FlowWriter *w,
size_t off, uint16_t v)
133bool flow_ipfix_begin(FlowWriter *w, uint8_t *buf,
size_t cap, uint32_t export_time, uint32_t seq, uint32_t domain_id)
148 w_u32(w, export_time);
154bool flow_v9_begin(FlowWriter *w, uint8_t *buf,
size_t cap, uint32_t sys_uptime, uint32_t unix_secs, uint32_t seq,
170 w_u32(w, sys_uptime);
177bool flow_export_template(FlowWriter *w, uint16_t template_id,
const FlowField *fields,
size_t field_count)
179 if (!w || !fields || field_count == 0)
185 flow_export_data_end(w);
187 size_t set_off = w->pos;
188 w_u16(w, w->version == 9 ? 0 : 2);
190 w_u16(w, template_id);
191 w_u16(w, (uint16_t)field_count);
192 for (
size_t i = 0; i < field_count; i++)
194 w_u16(w, fields[i].type);
195 w_u16(w, fields[i].length);
199 patch16(w, set_off + 2, (uint16_t)(w->pos - set_off));
205bool flow_export_data_begin(FlowWriter *w, uint16_t template_id)
207 if (!w || template_id < 256)
213 flow_export_data_end(w);
215 w->set_start = w->pos;
216 w_u16(w, template_id);
221bool flow_export_data_record(FlowWriter *w,
const uint8_t *record,
size_t len)
223 if (!w || !w->set_start || !record || len == 0)
227 w_bytes(w, record, len);
235bool flow_export_data_end(FlowWriter *w)
237 if (!w || !w->set_start)
243 size_t set_len = w->pos - w->set_start;
244 w_zero(w, (4 - (set_len & 3)) & 3);
248 patch16(w, w->set_start + 2, (uint16_t)(w->pos - w->set_start));
254size_t flow_export_finish(FlowWriter *w)
262 flow_export_data_end(w);
270 patch16(w, 2, w->records);
278 patch16(w, 2, (uint16_t)w->pos);
Fixed-width integer serializers into a raw uint8_t* buffer - one source of truth.
size_t pc_wr16be(uint8_t *p, uint16_t v)
Write v big-endian at p.
size_t pc_wr32be(uint8_t *p, uint32_t v)
Write v big-endian at p.
Flow-record export codec (PC_ENABLE_FLOW_EXPORT) - zero-heap exporter-side builders for NetFlow v5,...