passt/flow.h
David Gibson 3af5e9fdba icmp: Store ping socket information in flow table
Currently icmp_id_map[][] stores information about ping sockets in a
bespoke structure.  Move the same information into new types of flow
in the flow table.  To match that change, replace the existing ICMP
timer with a flow-based timer for expiring ping sockets.  This has the
advantage that we only need to scan the active flows, not all possible
ids.

We convert icmp_id_map[][] to point to the flow table entries, rather
than containing its own information.  We do still use that array for
locating the right ping flows, rather than using a "flow native" form
of lookup for the time being.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
[sbrivio: Update id_sock description in comment to icmp_ping_new()]
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
2024-03-12 01:34:45 +01:00

101 lines
2.7 KiB
C

/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright Red Hat
* Author: David Gibson <david@gibson.dropbear.id.au>
*
* Tracking for logical "flows" of packets.
*/
#ifndef FLOW_H
#define FLOW_H
#define FLOW_TIMER_INTERVAL 1000 /* ms */
/**
* enum flow_type - Different types of packet flows we track
*/
enum flow_type {
/* Represents an invalid or unused flow */
FLOW_TYPE_NONE = 0,
/* A TCP connection between a socket and tap interface */
FLOW_TCP,
/* A TCP connection between a host socket and ns socket */
FLOW_TCP_SPLICE,
/* ICMP echo requests from guest to host and matching replies back */
FLOW_PING4,
/* ICMPv6 echo requests from guest to host and matching replies back */
FLOW_PING6,
FLOW_NUM_TYPES,
};
extern const char *flow_type_str[];
#define FLOW_TYPE(f) \
((f)->type < FLOW_NUM_TYPES ? flow_type_str[(f)->type] : "?")
extern const uint8_t flow_proto[];
#define FLOW_PROTO(f) \
((f)->type < FLOW_NUM_TYPES ? flow_proto[(f)->type] : 0)
/**
* struct flow_common - Common fields for packet flows
* @type: Type of packet flow
*/
struct flow_common {
uint8_t type;
};
#define FLOW_INDEX_BITS 17 /* 128k - 1 */
#define FLOW_MAX MAX_FROM_BITS(FLOW_INDEX_BITS)
#define FLOW_TABLE_PRESSURE 30 /* % of FLOW_MAX */
#define FLOW_FILE_PRESSURE 30 /* % of c->nofile */
union flow *flow_start(union flow *flow, enum flow_type type,
unsigned iniside);
#define FLOW_START(flow_, t_, var_, i_) \
(&flow_start((flow_), (t_), (i_))->var_)
/**
* struct flow_sidx - ID for one side of a specific flow
* @side: Side referenced (0 or 1)
* @flow: Index of flow referenced
*/
typedef struct flow_sidx {
unsigned side :1;
unsigned flow :FLOW_INDEX_BITS;
} flow_sidx_t;
static_assert(sizeof(flow_sidx_t) <= sizeof(uint32_t),
"flow_sidx_t must fit within 32 bits");
#define FLOW_SIDX_NONE ((flow_sidx_t){ .flow = FLOW_MAX })
/**
* flow_sidx_eq() - Test if two sidx values are equal
* @a, @b: sidx values
*
* Return: true iff @a and @b refer to the same side of the same flow
*/
static inline bool flow_sidx_eq(flow_sidx_t a, flow_sidx_t b)
{
return (a.flow == b.flow) && (a.side == b.side);
}
union flow;
void flow_init(void);
void flow_defer_handler(const struct ctx *c, const struct timespec *now);
void flow_log_(const struct flow_common *f, int pri, const char *fmt, ...)
__attribute__((format(printf, 3, 4)));
#define flow_log(f_, pri, ...) flow_log_(&(f_)->f, (pri), __VA_ARGS__)
#define flow_dbg(f, ...) flow_log((f), LOG_DEBUG, __VA_ARGS__)
#define flow_err(f, ...) flow_log((f), LOG_ERR, __VA_ARGS__)
#define flow_trace(f, ...) \
do { \
if (log_trace) \
flow_dbg((f), __VA_ARGS__); \
} while (0)
#endif /* FLOW_H */