mirror of
https://github.com/openvswitch/ovs
synced 2025-08-30 22:05:19 +00:00
ofproto-dpif-trace: Fix infinite recirculation tracing.
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: e6bc8e7493
("ofproto/trace: Add support for tracing conntrack recirculation")
Reported-by: Jaime Caamaño Ruiz <jcaamano@redhat.com>
Acked-by: Simon Horman <horms@ovn.org>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
This commit is contained in:
@@ -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
|
||||
|
Reference in New Issue
Block a user