Skip to content

Commit fc31188

Browse files
numansiddiqueigsilya
authored andcommitted
ofproto-dpif: Limit recirc_id to 28 bits for TC compatibility.
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 <i.maximets@ovn.org> Suggested-by: Eelco Chaudron <echaudro@redhat.com> Acked-by: Eelco Chaudron <echaudro@redhat.com> Signed-off-by: Numan Siddique <numans@ovn.org> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
1 parent 916ec33 commit fc31188

File tree

1 file changed

+8
-3
lines changed

1 file changed

+8
-3
lines changed

ofproto/ofproto-dpif-rid.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ static uint32_t next_id OVS_GUARDED_BY(mutex) = 1; /* Possible next free id. */
3838

3939
#define RECIRC_POOL_STATIC_IDS 1024
4040

41+
/* Limit recirc_id to 28 bits for TC compatibility. recirc_id is used
42+
* as chain id in TC offload and kernel's TC implementation reserves
43+
* the upper 4 bits of the chain index for extended action opcodes. */
44+
#define RECIRC_ID_MAX_VALUE ((UINT32_C(1) << 28) - 1)
45+
4146
static void recirc_id_node_free(struct recirc_id_node *);
4247

4348
/* 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)
227232
}
228233

229234
/* Allocate a unique recirculation id for the given set of flow metadata.
230-
* The ID space is 2^^32, so there should never be a situation in which all
231-
* the IDs are used up. We loop until we find a free one. */
235+
* The ID space is limited to (2^28 - 1), so there should never be a situation
236+
* in which all the IDs are used up. We loop until we find a free one. */
232237
static struct recirc_id_node *
233238
recirc_alloc_id__(const struct frozen_state *state, uint32_t hash)
234239
{
@@ -247,7 +252,7 @@ recirc_alloc_id__(const struct frozen_state *state, uint32_t hash)
247252
RECIRC_POOL_STATIC_IDS IDs on the later rounds, though, as some of
248253
the initial allocations may be for long term uses (like bonds). */
249254
node->id = next_id++;
250-
if (OVS_UNLIKELY(!node->id)) {
255+
if (OVS_UNLIKELY(!node->id || node->id > RECIRC_ID_MAX_VALUE)) {
251256
next_id = RECIRC_POOL_STATIC_IDS + 1;
252257
node->id = next_id++;
253258
}

0 commit comments

Comments
 (0)