From 6fc215de30f51e66e60a7c11083e2597850599e5 Mon Sep 17 00:00:00 2001 From: Ilya Maximets Date: Thu, 22 Feb 2024 16:06:32 +0100 Subject: [PATCH] ofproto-dpif-trace: Fix infinite recirculation tracing. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trace attempts to process all the recirculations. However, if there is a recirculation loop, i.e. if every recirculation generates another recirculation, this process will never stop. It will grind until the trace fills the system memory. A simple reproducer: make sandbox ovs-vsctl add-br br0 ovs-vsctl add-port br0 p1 ovs-ofctl add-flow br0 "table=0,in_port=p1,ip,actions=ct(table=0)" ovs-appctl ofproto/trace br0 in_port=p1,ip Limit the number of recirculations trace is processing with a fairly arbitrary number - 4096 (loosely based on the resubmit limit, but they are not actually related). Not adding a test for this since it's only for a trace, but also because the test may lead to OOM event in a system if the test fails, which is not nice. Fixes: e6bc8e749381 ("ofproto/trace: Add support for tracing conntrack recirculation") Reported-by: Jaime CaamaƱo Ruiz Acked-by: Simon Horman Signed-off-by: Ilya Maximets --- ofproto/ofproto-dpif-trace.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ofproto/ofproto-dpif-trace.c b/ofproto/ofproto-dpif-trace.c index b86e7fe07..87506aa78 100644 --- a/ofproto/ofproto-dpif-trace.c +++ b/ofproto/ofproto-dpif-trace.c @@ -845,17 +845,35 @@ ofproto_trace(struct ofproto_dpif *ofproto, const struct flow *flow, bool names) { struct ovs_list recirc_queue = OVS_LIST_INITIALIZER(&recirc_queue); + int recirculations = 0; + ofproto_trace__(ofproto, flow, packet, &recirc_queue, ofpacts, ofpacts_len, output, names); struct oftrace_recirc_node *recirc_node; LIST_FOR_EACH_POP (recirc_node, node, &recirc_queue) { + if (recirculations++ > 4096) { + ds_put_cstr(output, "\n\n"); + ds_put_char_multiple(output, '=', 79); + ds_put_cstr(output, "\nTrace reached the recirculation limit." + " Sopping the trace here."); + ds_put_format(output, + "\nQueued but not processed: %"PRIuSIZE + " recirculations.", + ovs_list_size(&recirc_queue) + 1); + oftrace_recirc_node_destroy(recirc_node); + break; + } ofproto_trace_recirc_node(recirc_node, next_ct_states, output); ofproto_trace__(ofproto, &recirc_node->flow, recirc_node->packet, &recirc_queue, ofpacts, ofpacts_len, output, names); oftrace_recirc_node_destroy(recirc_node); } + /* Destroy remaining recirculation nodes, if any. */ + LIST_FOR_EACH_POP (recirc_node, node, &recirc_queue) { + oftrace_recirc_node_destroy(recirc_node); + } } void