From: Numan Siddique <[email protected]>

netdev-offload-tc when offloading a flow to tc, uses the flow's
recirc_id as flower chain id.  recirc_id is of type 'uint32_t'.
Kernel tc reserves the upper nibble (4 bits) of the tc flower's
chain index for extended action opcode [1].  If a flow's recirc_id
value is greater than 268,435,455 (2^28), kernel returns
EINVAL when ovs-vswitchd tries to offload the flow.

This commit fixes this offload issue by setting the maximum
value of recirc id to 2^28. 2^28 is a fairly big number and
we should not have that many active datapath flows at a time.

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]>
---
 ofproto/ofproto-dpif-rid.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/ofproto/ofproto-dpif-rid.c b/ofproto/ofproto-dpif-rid.c
index f01468025..09f8a84f1 100644
--- a/ofproto/ofproto-dpif-rid.c
+++ b/ofproto/ofproto-dpif-rid.c
@@ -38,6 +38,13 @@ static uint32_t next_id OVS_GUARDED_BY(mutex) = 1; /* 
Possible next free id. */
 
 #define RECIRC_POOL_STATIC_IDS 1024
 
+/* Limit the recirc_ic maximum value to 268435455 (which is 2^^28).
+ * When kernel tc offload is enabled, we use the recirc_id as
+ * the chain id and kernel limits the chain id maximum value
+ * to 2^^28.
+ */
+#define RECIRC_ID_MAX_VALUE 268435455
+
 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 +234,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, 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 +254,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

Reply via email to