/* SPDX-License-Identifier: GPL-2.0-or-later * Copyright Red Hat * Author: David Gibson * * Tracking for logical "flows" of packets. */ #include #include #include #include "util.h" #include "passt.h" #include "inany.h" #include "siphash.h" #include "flow.h" #include "tcp_conn.h" #include "flow_table.h" const char *flow_type_str[] = { [FLOW_NONE] = "", [FLOW_TCP] = "TCP connection", [FLOW_TCP_SPLICE] = "TCP connection (spliced)", }; /* Global Flow Table */ union flow flowtab[FLOW_MAX]; /** flowside_fmt - Format a flowside as a string * @fs: flowside to format * @buf: Buffer into which to store the formatted version * @size: Size of @buf * * Return: pointer to formatted string describing @fs, or NULL on error */ const char *flowside_fmt(const struct flowside *fs, char *buf, size_t size) { char ebuf[INET6_ADDRSTRLEN], fbuf[INET6_ADDRSTRLEN]; if (!inet_ntop(AF_INET6, &fs->eaddr, ebuf, sizeof(ebuf)) || !inet_ntop(AF_INET6, &fs->faddr, fbuf, sizeof(fbuf))) return NULL; snprintf(buf, size, "[%s]:%hu <-> [%s]:%hu", fbuf, fs->fport, ebuf, fs->eport); return (const char *)buf; } /** * flow_table_compact() - Perform compaction on flow table * @c: Execution context * @hole: Pointer to recently closed flow */ void flow_table_compact(struct ctx *c, union flow *hole) { union flow *from; if (FLOW_IDX(hole) == --c->flow_count) { debug("flow: table compaction: maximum index was %li (%p)", FLOW_IDX(hole), hole); memset(hole, 0, sizeof(*hole)); return; } from = flowtab + c->flow_count; memcpy(hole, from, sizeof(*hole)); switch (from->f.type) { case FLOW_TCP: tcp_tap_conn_update(c, &from->tcp, &hole->tcp); break; case FLOW_TCP_SPLICE: tcp_splice_conn_update(c, &hole->tcp_splice); break; default: die("Unexpected %s in tcp_table_compact()", FLOW_TYPE(&from->f)); } debug("flow: table compaction (%s): old index %li, new index %li, " "from: %p, to: %p", FLOW_TYPE(&from->f), FLOW_IDX(from), FLOW_IDX(hole), from, hole); memset(from, 0, sizeof(*from)); }