mirror of
https://github.com/openvswitch/ovs
synced 2025-08-31 14:25:26 +00:00
dpif-netdev: Fix dp_netdev_pmd_remove_flow().
After removing a flow from the dpcls classifier there might still be readers who have access to the flow, until the next grace period. Setting flow->cr.mask to NULL can cause concurrent readers to crash, so this commit avoids doing it. The crash can be reproduced, for example, by invoking an operation that cause datapath flows to be deleted (such as `ovs-appctl upcall/enable-megaflows`) while traffic is running. I think the assignment was intended just as a safety measure to catch race conditions, and it should be safe to remove. Here's a stack trace of a possible crash: Program terminated with signal SIGSEGV, Segmentation fault. rule=0x7f3ae8006190) at ../lib/dpif-netdev.c:4156 4156 if (OVS_UNLIKELY((value & *maskp++) != *keyp++)) { (gdb) bt rule=0x7f3ae8006190) at ../lib/dpif-netdev.c:4156 rules=0x7f3afa3f2e40, cnt=<optimized out>) at ../lib/dpif-netdev.c:4225 (pmd=pmd@entry=0x7f3afa3fc010, packets=packets@entry=0x7f3afa3fa420, cnt=cnt@entry=32, keys=keys@entry=0x7f3afa3f6428, batches=batches@entry=0x7f3afa3f4118, n_batches=n_batches@entry=0x7f3afa3fa3b0) at ../lib/dpif-netdev.c:3483 (pmd=pmd@entry=0x7f3afa3fc010, packets=packets@entry=0x7f3afa3fa420, cnt=<optimized out>, md_is_valid=md_is_valid@entry=false, port_no=<optimized out>) at ../lib/dpif-netdev.c:3625 cnt=<optimized out>, packets=0x7f3afa3fa420, pmd=0x7f3afa3fc010) at ../lib/dpif-netdev.c:3642 rxq=<optimized out>, port=<optimized out>, port=<optimized out>) at ../lib/dpif-netdev.c:2574 ../lib/dpif-netdev.c:2693 ../lib/ovs-thread.c:340 pthread_create.c:312 ../sysdeps/unix/sysv/linux/x86_64/clone.S:111 Fixes: 361d808dd9e4("flow: Split miniflow's map.") CC: Jarno Rajahalme <jarno@ovn.org> Signed-off-by: Daniele Di Proietto <diproiettod@vmware.com> Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
This commit is contained in:
@@ -1444,8 +1444,6 @@ dp_netdev_pmd_remove_flow(struct dp_netdev_pmd_thread *pmd,
|
||||
struct cmap_node *node = CONST_CAST(struct cmap_node *, &flow->node);
|
||||
|
||||
dpcls_remove(&pmd->cls, &flow->cr);
|
||||
flow->cr.mask = NULL; /* Accessing rule's mask after this is not safe. */
|
||||
|
||||
cmap_remove(&pmd->flow_table, node, dp_netdev_flow_hash(&flow->ufid));
|
||||
flow->dead = true;
|
||||
|
||||
|
Reference in New Issue
Block a user