From: Numan Siddique <[email protected]> The netdev-offload-tc module uses a flow's recirc_id (a uint32_t) as the TC flower chain ID during offloading. However, the kernel's TC implementation reserves the upper 4 bits of the chain index for extended action opcodes. If a recirc_id exceeds (2^28 - 1), the kernel rejects the flow offload with EINVAL. This patch caps the maximum recirc_id to (2^28 - 1) to prevent these failures.
This limit is sufficiently high that it is unlikely to impact the number of active datapath flows in practice. Reported-at: https://mail.openvswitch.org/pipermail/ovs-dev/2025-November/427485.html Suggested-by: Ilya Maximets <[email protected]> Suggested-by: Eelco Chaudron <[email protected]> Signed-off-by: Numan Siddique <[email protected]> --- v2 -> v3 ------- - Addressed review comments from v2. ofproto/ofproto-dpif-rid.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/ofproto/ofproto-dpif-rid.c b/ofproto/ofproto-dpif-rid.c index f01468025..1f9746f93 100644 --- a/ofproto/ofproto-dpif-rid.c +++ b/ofproto/ofproto-dpif-rid.c @@ -38,6 +38,11 @@ static uint32_t next_id OVS_GUARDED_BY(mutex) = 1; /* Possible next free id. */ #define RECIRC_POOL_STATIC_IDS 1024 +/* Limit recirc_id to 28 bits for TC compatibility. recirc_id is used + * as chain id in TC offload and kernel's TC implementation reserves + * the upper 4 bits of the chain index for extended action opcodes. */ +#define RECIRC_ID_MAX_VALUE ((UINT32_C(1) << 28) - 1) + static void recirc_id_node_free(struct recirc_id_node *); /* This should be called by the revalidator once at each round (every 500ms or @@ -227,8 +232,8 @@ frozen_state_free(struct frozen_state *state) } /* Allocate a unique recirculation id for the given set of flow metadata. - * The ID space is 2^^32, so there should never be a situation in which all - * the IDs are used up. We loop until we find a free one. */ + * The ID space is limited to (2^28 - 1), so there should never be a situation + * in which all the IDs are used up. We loop until we find a free one. */ static struct recirc_id_node * recirc_alloc_id__(const struct frozen_state *state, uint32_t hash) { @@ -247,7 +252,7 @@ recirc_alloc_id__(const struct frozen_state *state, uint32_t hash) RECIRC_POOL_STATIC_IDS IDs on the later rounds, though, as some of the initial allocations may be for long term uses (like bonds). */ node->id = next_id++; - if (OVS_UNLIKELY(!node->id)) { + if (OVS_UNLIKELY(!node->id || node->id > RECIRC_ID_MAX_VALUE)) { next_id = RECIRC_POOL_STATIC_IDS + 1; node->id = next_id++; } -- 2.52.0 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
