.conntrack status (ct_status)
[options="header"]
|==================
-|Keyword| Value
-|expected|
-1
-|seen-reply|
-2
-|assured|
-4
-|confirmed|
-8
-|snat|
-16
-|dnat|
-32
-|dying|
-512
+|Keyword| Value | Description
+|expected|1| Expected connection; conntrack helper set it up
+|seen-reply|2| Conntrack has seen packets in both directions
+|assured| 4 |Conntrack entry will not be removed if hash table is full
+|confirmed | 8 | Initial packet processed
+|snat| 16 | Original source address differs from reply destination
+|dnat| 32 | Original destination differs from reply source
+|seq-adjust| 64 | tcp sequence number rewrite due to conntrack helper or synproxy
+|snat-done| 128 | tried to find matching snat/masquerade rule
+|dnat-done| 256 | tried to find matching dnat/redirect rule
+|dying| 512 | Connection about to be deleted
+|fixed-timeout | 1024 | entry expires even if traffic is active
+|helper | 8192 | connection is monitored by conntrack helper
+|offload | 16384 | connection is offloaded to a flow table
+|hw-offload | 32768 | connection is offloaded to hardware
|================
.conntrack event bits (ct_event)
/* Connection has fixed timeout. */
IPS_FIXED_TIMEOUT_BIT = 10,
IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
+
+ /* Conntrack is a fake untracked entry. Obsolete and not used anymore */
+ IPS_UNTRACKED_BIT = 12,
+ IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT),
+
+ /* Conntrack got a helper explicitly attached (ruleset, ctnetlink). */
+ IPS_HELPER_BIT = 13,
+ IPS_HELPER = (1 << IPS_HELPER_BIT),
+
+ /* Conntrack has been offloaded to flow table. */
+ IPS_OFFLOAD_BIT = 14,
+ IPS_OFFLOAD = (1 << IPS_OFFLOAD_BIT),
+
+ /* Conntrack has been offloaded to hardware. */
+ IPS_HW_OFFLOAD_BIT = 15,
+ IPS_HW_OFFLOAD = (1 << IPS_HW_OFFLOAD_BIT),
};
/* Connection tracking event types */
SYMBOL("confirmed", IPS_CONFIRMED),
SYMBOL("snat", IPS_SRC_NAT),
SYMBOL("dnat", IPS_DST_NAT),
+ SYMBOL("seq-adjust", IPS_SEQ_ADJUST),
+ SYMBOL("snat-done", IPS_SRC_NAT_DONE),
+ SYMBOL("dnat-done", IPS_DST_NAT_DONE),
SYMBOL("dying", IPS_DYING),
+ SYMBOL("fixed-timeout", IPS_FIXED_TIMEOUT),
+ SYMBOL("helper", IPS_HELPER_BIT),
+ SYMBOL("offload", IPS_OFFLOAD_BIT),
+ SYMBOL("hw-offload", IPS_HW_OFFLOAD_BIT),
SYMBOL_LIST_END
},
};
}
}
+static struct expr *trace_alloc_list(const struct datatype *dtype,
+ enum byteorder byteorder,
+ unsigned int len, const void *data)
+{
+ struct expr *list_expr;
+ unsigned int i;
+ mpz_t value;
+ uint32_t v;
+
+ if (len != sizeof(v))
+ return constant_expr_alloc(&netlink_location,
+ dtype, byteorder,
+ len * BITS_PER_BYTE, data);
+
+ list_expr = list_expr_alloc(&netlink_location);
+
+ mpz_init2(value, 32);
+ mpz_import_data(value, data, byteorder, len);
+ v = mpz_get_uint32(value);
+ if (v == 0) {
+ mpz_clear(value);
+ return NULL;
+ }
+
+ for (i = 0; i < 32; i++) {
+ uint32_t bitv = v & (1 << i);
+
+ if (bitv == 0)
+ continue;
+
+ compound_expr_add(list_expr,
+ constant_expr_alloc(&netlink_location,
+ dtype, byteorder,
+ len * BITS_PER_BYTE,
+ &bitv));
+ }
+
+ mpz_clear(value);
+ return list_expr;
+}
+
+static void trace_print_ct_expr(const struct nftnl_trace *nlt, unsigned int attr,
+ enum nft_ct_keys key, struct output_ctx *octx)
+{
+ struct expr *lhs, *rhs, *rel;
+ const void *data;
+ uint32_t len;
+
+ data = nftnl_trace_get_data(nlt, attr, &len);
+ lhs = ct_expr_alloc(&netlink_location, key, -1);
+
+ switch (key) {
+ case NFT_CT_STATUS:
+ rhs = trace_alloc_list(lhs->dtype, lhs->byteorder, len, data);
+ if (!rhs) {
+ expr_free(lhs);
+ return;
+ }
+ rel = binop_expr_alloc(&netlink_location, OP_IMPLICIT, lhs, rhs);
+ break;
+ case NFT_CT_DIRECTION:
+ case NFT_CT_STATE:
+ case NFT_CT_ID:
+ /* fallthrough */
+ default:
+ rhs = constant_expr_alloc(&netlink_location,
+ lhs->dtype, lhs->byteorder,
+ len * BITS_PER_BYTE, data);
+ rel = relational_expr_alloc(&netlink_location, OP_IMPLICIT, lhs, rhs);
+ break;
+ }
+
+ expr_print(rel, octx);
+ nft_print(octx, " ");
+ expr_free(rel);
+}
+
+static void trace_print_ct(const struct nftnl_trace *nlt,
+ struct output_ctx *octx)
+{
+ bool ct = nftnl_trace_is_set(nlt, NFTNL_TRACE_CT_STATE);
+
+ if (!ct)
+ return;
+
+ trace_print_hdr(nlt, octx);
+
+ nft_print(octx, "conntrack: ");
+
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_CT_DIRECTION))
+ trace_print_ct_expr(nlt, NFTNL_TRACE_CT_DIRECTION,
+ NFT_CT_DIRECTION, octx);
+
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_CT_STATE))
+ trace_print_ct_expr(nlt, NFTNL_TRACE_CT_STATE,
+ NFT_CT_STATE, octx);
+
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_CT_STATUS))
+ trace_print_ct_expr(nlt, NFTNL_TRACE_CT_STATUS,
+ NFT_CT_STATUS, octx);
+
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_CT_ID))
+ trace_print_ct_expr(nlt, NFTNL_TRACE_CT_ID,
+ NFT_CT_ID, octx);
+
+ nft_print(octx, "\n");
+}
+
static void trace_print_packet(const struct nftnl_trace *nlt,
struct output_ctx *octx)
{
uint32_t nfproto;
struct stmt *stmt, *next;
+ trace_print_ct(nlt, octx);
trace_print_hdr(nlt, octx);
nft_print(octx, "packet: ");