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 <jcaam...@redhat.com>
Signed-off-by: Ilya Maximets <i.maxim...@ovn.org>
---
 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
-- 
2.43.0

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to