<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:PMingLiU;
panose-1:2 2 5 0 0 0 0 0 0 0;}
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:"\@PMingLiU";
panose-1:2 1 6 1 0 1 1 1 1 1;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
font-size:10.0pt;
font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
span.EmailStyle19
{mso-style-type:personal-reply;
font-family:"Calibri",sans-serif;
color:windowtext;}
.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;
mso-ligatures:none;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></style>
</head>
<body lang="EN-US" link="blue" vlink="purple" style="word-wrap:break-word">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt">Please ignore, will send v3.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt;color:black">From:
</span></b><span style="font-size:12.0pt;color:black">William Tu <witu@nvidia.com><br>
<b>Date: </b>Wednesday, May 24, 2023 at 9:32 AM<br>
<b>To: </b>kernel-team@lists.ubuntu.com <kernel-team@lists.ubuntu.com><br>
<b>Cc: </b>Bodong Wang <bodong@nvidia.com>, Vladimir Sokolovsky <vlad@nvidia.com>, dann.frazier@canonical.com <dann.frazier@canonical.com>, Paul Blakey <paulb@nvidia.com>, William Tu <witu@nvidia.com>, Chris Mi <cmi@nvidia.com><br>
<b>Subject: </b>[SRU][F:linux-bluefield][PATCH v2 1/1] net: openvswitch: fix race on port output<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:11.0pt">From: Felix Huettner <felix.huettner@mail.schwarz><br>
<br>
BugLink: <a href="https://bugs.launchpad.net/bugs/2020606">https://bugs.launchpad.net/bugs/2020606</a><br>
<br>
assume the following setup on a single machine:<br>
1. An openvswitch instance with one bridge and default flows<br>
2. two network namespaces "server" and "client"<br>
3. two ovs interfaces "server" and "client" on the bridge<br>
4. for each ovs interface a veth pair with a matching name and 32 rx and<br>
tx queues<br>
5. move the ends of the veth pairs to the respective network namespaces<br>
6. assign ip addresses to each of the veth ends in the namespaces (needs<br>
to be the same subnet)<br>
7. start some http server on the server network namespace<br>
8. test if a client in the client namespace can reach the http server<br>
<br>
when following the actions below the host has a chance of getting a cpu<br>
stuck in a infinite loop:<br>
1. send a large amount of parallel requests to the http server (around<br>
3000 curls should work)<br>
2. in parallel delete the network namespace (do not delete interfaces or<br>
stop the server, just kill the namespace)<br>
<br>
there is a low chance that this will cause the below kernel cpu stuck<br>
message. If this does not happen just retry.<br>
Below there is also the output of bpftrace for the functions mentioned<br>
in the output.<br>
<br>
The series of events happening here is:<br>
1. the network namespace is deleted calling<br>
`unregister_netdevice_many_notify` somewhere in the process<br>
2. this sets first `NETREG_UNREGISTERING` on both ends of the veth and<br>
then runs `synchronize_net`<br>
3. it then calls `call_netdevice_notifiers` with `NETDEV_UNREGISTER`<br>
4. this is then handled by `dp_device_event` which calls<br>
`ovs_netdev_detach_dev` (if a vport is found, which is the case for<br>
the veth interface attached to ovs)<br>
5. this removes the rx_handlers of the device but does not prevent<br>
packages to be sent to the device<br>
6. `dp_device_event` then queues the vport deletion to work in<br>
background as a ovs_lock is needed that we do not hold in the<br>
unregistration path<br>
7. `unregister_netdevice_many_notify` continues to call<br>
`netdev_unregister_kobject` which sets `real_num_tx_queues` to 0<br>
8. port deletion continues (but details are not relevant for this issue)<br>
9. at some future point the background task deletes the vport<br>
<br>
If after 7. but before 9. a packet is send to the ovs vport (which is<br>
not deleted at this point in time) which forwards it to the<br>
`dev_queue_xmit` flow even though the device is unregistering.<br>
In `skb_tx_hash` (which is called in the `dev_queue_xmit`) path there is<br>
a while loop (if the packet has a rx_queue recorded) that is infinite if<br>
`dev->real_num_tx_queues` is zero.<br>
<br>
To prevent this from happening we update `do_output` to handle devices<br>
without carrier the same as if the device is not found (which would<br>
be the code path after 9. is done).<br>
<br>
Additionally we now produce a warning in `skb_tx_hash` if we will hit<br>
the infinite loop.<br>
<br>
bpftrace (first word is function name):<br>
<br>
__dev_queue_xmit server: real_num_tx_queues: 1, cpu: 2, pid: 28024, tid: 28024, skb_addr: 0xffff9edb6f207000, reg_state: 1<br>
netdev_core_pick_tx server: addr: 0xffff9f0a46d4a000 real_num_tx_queues: 1, cpu: 2, pid: 28024, tid: 28024, skb_addr: 0xffff9edb6f207000, reg_state: 1<br>
dp_device_event server: real_num_tx_queues: 1 cpu 9, pid: 21024, tid: 21024, event 2, reg_state: 1<br>
synchronize_rcu_expedited: cpu 9, pid: 21024, tid: 21024<br>
synchronize_rcu_expedited: cpu 9, pid: 21024, tid: 21024<br>
synchronize_rcu_expedited: cpu 9, pid: 21024, tid: 21024<br>
synchronize_rcu_expedited: cpu 9, pid: 21024, tid: 21024<br>
dp_device_event server: real_num_tx_queues: 1 cpu 9, pid: 21024, tid: 21024, event 6, reg_state: 2<br>
ovs_netdev_detach_dev server: real_num_tx_queues: 1 cpu 9, pid: 21024, tid: 21024, reg_state: 2<br>
netdev_rx_handler_unregister server: real_num_tx_queues: 1, cpu: 9, pid: 21024, tid: 21024, reg_state: 2<br>
synchronize_rcu_expedited: cpu 9, pid: 21024, tid: 21024<br>
netdev_rx_handler_unregister ret server: real_num_tx_queues: 1, cpu: 9, pid: 21024, tid: 21024, reg_state: 2<br>
dp_device_event server: real_num_tx_queues: 1 cpu 9, pid: 21024, tid: 21024, event 27, reg_state: 2<br>
dp_device_event server: real_num_tx_queues: 1 cpu 9, pid: 21024, tid: 21024, event 22, reg_state: 2<br>
dp_device_event server: real_num_tx_queues: 1 cpu 9, pid: 21024, tid: 21024, event 18, reg_state: 2<br>
netdev_unregister_kobject: real_num_tx_queues: 1, cpu: 9, pid: 21024, tid: 21024<br>
synchronize_rcu_expedited: cpu 9, pid: 21024, tid: 21024<br>
ovs_vport_send server: real_num_tx_queues: 0, cpu: 2, pid: 28024, tid: 28024, skb_addr: 0xffff9edb6f207000, reg_state: 2<br>
__dev_queue_xmit server: real_num_tx_queues: 0, cpu: 2, pid: 28024, tid: 28024, skb_addr: 0xffff9edb6f207000, reg_state: 2<br>
netdev_core_pick_tx server: addr: 0xffff9f0a46d4a000 real_num_tx_queues: 0, cpu: 2, pid: 28024, tid: 28024, skb_addr: 0xffff9edb6f207000, reg_state: 2<br>
broken device server: real_num_tx_queues: 0, cpu: 2, pid: 28024, tid: 28024<br>
ovs_dp_detach_port server: real_num_tx_queues: 0 cpu 9, pid: 9124, tid: 9124, reg_state: 2<br>
synchronize_rcu_expedited: cpu 9, pid: 33604, tid: 33604<br>
<br>
stuck message:<br>
<br>
watchdog: BUG: soft lockup - CPU#5 stuck for 26s! [curl:1929279]<br>
Modules linked in: veth pktgen bridge stp llc ip_set_hash_net nft_counter xt_set nft_compat nf_tables ip_set_hash_ip ip_set nfnetlink_cttimeout nfnetlink openvswitch nsh nf_conncount nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 tls binfmt_misc nls_iso8859_1
input_leds joydev serio_raw dm_multipath scsi_dh_rdac scsi_dh_emc scsi_dh_alua sch_fq_codel drm efi_pstore virtio_rng ip_tables x_tables autofs4 btrfs blake2b_generic zstd_compress raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx xor
raid6_pq libcrc32c raid1 raid0 multipath linear hid_generic usbhid hid crct10dif_pclmul crc32_pclmul ghash_clmulni_intel aesni_intel virtio_net ahci net_failover crypto_simd cryptd psmouse libahci virtio_blk failover<br>
CPU: 5 PID: 1929279 Comm: curl Not tainted 5.15.0-67-generic #74-Ubuntu<br>
Hardware name: OpenStack Foundation OpenStack Nova, BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014<br>
RIP: 0010:netdev_pick_tx+0xf1/0x320<br>
Code: 00 00 8d 48 ff 0f b7 c1 66 39 ca 0f 86 e9 01 00 00 45 0f b7 ff 41 39 c7 0f 87 5b 01 00 00 44 29 f8 41 39 c7 0f 87 4f 01 00 00 <eb> f2 0f 1f 44 00 00 49 8b 94 24 28 04 00 00 48 85 d2 0f 84 53 01<br>
RSP: 0018:ffffb78b40298820 EFLAGS: 00000246<br>
RAX: 0000000000000000 RBX: ffff9c8773adc2e0 RCX: 000000000000083f<br>
RDX: 0000000000000000 RSI: ffff9c8773adc2e0 RDI: ffff9c870a25e000<br>
RBP: ffffb78b40298858 R08: 0000000000000001 R09: 0000000000000000<br>
R10: 0000000000000000 R11: 0000000000000000 R12: ffff9c870a25e000<br>
R13: ffff9c870a25e000 R14: ffff9c87fe043480 R15: 0000000000000000<br>
FS: 00007f7b80008f00(0000) GS:ffff9c8e5f740000(0000) knlGS:0000000000000000<br>
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033<br>
CR2: 00007f7b80f6a0b0 CR3: 0000000329d66000 CR4: 0000000000350ee0<br>
Call Trace:<br>
<IRQ><br>
netdev_core_pick_tx+0xa4/0xb0<br>
__dev_queue_xmit+0xf8/0x510<br>
? __bpf_prog_exit+0x1e/0x30<br>
dev_queue_xmit+0x10/0x20<br>
ovs_vport_send+0xad/0x170 [openvswitch]<br>
do_output+0x59/0x180 [openvswitch]<br>
do_execute_actions+0xa80/0xaa0 [openvswitch]<br>
? kfree+0x1/0x250<br>
? kfree+0x1/0x250<br>
? kprobe_perf_func+0x4f/0x2b0<br>
? flow_lookup.constprop.0+0x5c/0x110 [openvswitch]<br>
ovs_execute_actions+0x4c/0x120 [openvswitch]<br>
ovs_dp_process_packet+0xa1/0x200 [openvswitch]<br>
? ovs_ct_update_key.isra.0+0xa8/0x120 [openvswitch]<br>
? ovs_ct_fill_key+0x1d/0x30 [openvswitch]<br>
? ovs_flow_key_extract+0x2db/0x350 [openvswitch]<br>
ovs_vport_receive+0x77/0xd0 [openvswitch]<br>
? __htab_map_lookup_elem+0x4e/0x60<br>
? bpf_prog_680e8aff8547aec1_kfree+0x3b/0x714<br>
? trace_call_bpf+0xc8/0x150<br>
? kfree+0x1/0x250<br>
? kfree+0x1/0x250<br>
? kprobe_perf_func+0x4f/0x2b0<br>
? kprobe_perf_func+0x4f/0x2b0<br>
? __mod_memcg_lruvec_state+0x63/0xe0<br>
netdev_port_receive+0xc4/0x180 [openvswitch]<br>
? netdev_port_receive+0x180/0x180 [openvswitch]<br>
netdev_frame_hook+0x1f/0x40 [openvswitch]<br>
__netif_receive_skb_core.constprop.0+0x23d/0xf00<br>
__netif_receive_skb_one_core+0x3f/0xa0<br>
__netif_receive_skb+0x15/0x60<br>
process_backlog+0x9e/0x170<br>
__napi_poll+0x33/0x180<br>
net_rx_action+0x126/0x280<br>
? ttwu_do_activate+0x72/0xf0<br>
__do_softirq+0xd9/0x2e7<br>
? rcu_report_exp_cpu_mult+0x1b0/0x1b0<br>
do_softirq+0x7d/0xb0<br>
</IRQ><br>
<TASK><br>
__local_bh_enable_ip+0x54/0x60<br>
ip_finish_output2+0x191/0x460<br>
__ip_finish_output+0xb7/0x180<br>
ip_finish_output+0x2e/0xc0<br>
ip_output+0x78/0x100<br>
? __ip_finish_output+0x180/0x180<br>
ip_local_out+0x5e/0x70<br>
__ip_queue_xmit+0x184/0x440<br>
? tcp_syn_options+0x1f9/0x300<br>
ip_queue_xmit+0x15/0x20<br>
__tcp_transmit_skb+0x910/0x9c0<br>
? __mod_memcg_state+0x44/0xa0<br>
tcp_connect+0x437/0x4e0<br>
? ktime_get_with_offset+0x60/0xf0<br>
tcp_v4_connect+0x436/0x530<br>
__inet_stream_connect+0xd4/0x3a0<br>
? kprobe_perf_func+0x4f/0x2b0<br>
? aa_sk_perm+0x43/0x1c0<br>
inet_stream_connect+0x3b/0x60<br>
__sys_connect_file+0x63/0x70<br>
__sys_connect+0xa6/0xd0<br>
? setfl+0x108/0x170<br>
? do_fcntl+0xe8/0x5a0<br>
__x64_sys_connect+0x18/0x20<br>
do_syscall_64+0x5c/0xc0<br>
? __x64_sys_fcntl+0xa9/0xd0<br>
? exit_to_user_mode_prepare+0x37/0xb0<br>
? syscall_exit_to_user_mode+0x27/0x50<br>
? do_syscall_64+0x69/0xc0<br>
? __sys_setsockopt+0xea/0x1e0<br>
? exit_to_user_mode_prepare+0x37/0xb0<br>
? syscall_exit_to_user_mode+0x27/0x50<br>
? __x64_sys_setsockopt+0x1f/0x30<br>
? do_syscall_64+0x69/0xc0<br>
? irqentry_exit+0x1d/0x30<br>
? exc_page_fault+0x89/0x170<br>
entry_SYSCALL_64_after_hwframe+0x61/0xcb<br>
RIP: 0033:0x7f7b8101c6a7<br>
Code: 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 2a 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 51 c3 48 83 ec 18 89 54 24 0c 48 89 34 24 89<br>
RSP: 002b:00007ffffd6b2198 EFLAGS: 00000246 ORIG_RAX: 000000000000002a<br>
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f7b8101c6a7<br>
RDX: 0000000000000010 RSI: 00007ffffd6b2360 RDI: 0000000000000005<br>
RBP: 0000561f1370d560 R08: 00002795ad21d1ac R09: 0030312e302e302e<br>
R10: 00007ffffd73f080 R11: 0000000000000246 R12: 0000561f1370c410<br>
R13: 0000000000000000 R14: 0000000000000005 R15: 0000000000000000<br>
</TASK><br>
<br>
Fixes: 7f8a436eaa2c ("openvswitch: Add conntrack action")<br>
Co-developed-by: Luca Czesla <luca.czesla@mail.schwarz><br>
Signed-off-by: Luca Czesla <luca.czesla@mail.schwarz><br>
Signed-off-by: Felix Huettner <felix.huettner@mail.schwarz><br>
Reviewed-by: Eric Dumazet <edumazet@google.com><br>
Reviewed-by: Simon Horman <simon.horman@corigine.com><br>
Link: <a href="https://lore.kernel.org/r/ZC0pBXBAgh7c76CA@kernel-bug-kernel-bug">
https://lore.kernel.org/r/ZC0pBXBAgh7c76CA@kernel-bug-kernel-bug</a><br>
Signed-off-by: Jakub Kicinski <kuba@kernel.org><br>
(cherry picked from commit 066b86787fa3d97b7aefb5ac0a99a22dad2d15f8)<br>
Signed-off-by: William Tu <witu@nvidia.com><br>
---<br>
v2: separate focal and jammy<br>
---<br>
net/core/dev.c | 1 +<br>
net/openvswitch/actions.c | 2 +-<br>
2 files changed, 2 insertions(+), 1 deletion(-)<br>
<br>
diff --git a/net/core/dev.c b/net/core/dev.c<br>
index 88a5b3cc8861..97f7ace43f80 100644<br>
--- a/net/core/dev.c<br>
+++ b/net/core/dev.c<br>
@@ -3176,6 +3176,7 @@ static u16 skb_tx_hash(const struct net_device *dev,<br>
}<br>
<br>
if (skb_rx_queue_recorded(skb)) {<br>
+ DEBUG_NET_WARN_ON_ONCE(qcount == 0);<br>
hash = skb_get_rx_queue(skb);<br>
if (hash >= qoffset)<br>
hash -= qoffset;<br>
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c<br>
index aca6e2b599c8..ba0acc171418 100644<br>
--- a/net/openvswitch/actions.c<br>
+++ b/net/openvswitch/actions.c<br>
@@ -913,7 +913,7 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,<br>
{<br>
struct vport *vport = ovs_vport_rcu(dp, out_port);<br>
<br>
- if (likely(vport)) {<br>
+ if (likely(vport && netif_carrier_ok(vport->dev))) {<br>
u16 mru = OVS_CB(skb)->mru;<br>
u32 cutlen = OVS_CB(skb)->cutlen;<br>
<br>
-- <br>
2.34.1<o:p></o:p></span></p>
</div>
</div>
</body>
</html>