Note: This bug is displayed in read-only format because the product is no longer active in Red Hat Bugzilla.
The FDP team is no longer accepting new bugs in Bugzilla. Please report your issues under FDP project in Jira. Thanks.

Bug 2182541

Summary: ovs-appctl dpctl/dump-flows hung
Product: Red Hat Enterprise Linux Fast Datapath Reporter: qding
Component: openvswitch3.1Assignee: Eelco Chaudron <echaudro>
Status: CLOSED ERRATA QA Contact: qding
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: FDP 23.CCC: ctrautma, echaudro, fleitner, jhsiao, mleitner, ralongi, tredaelli
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: openvswitch3.1-3.1.0-28.el8fdp Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2023-07-06 20:05:16 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 2172625    

Comment 1 Eelco Chaudron 2023-03-31 11:18:32 UTC
Can you isolate the issue to a simple reproducer that I can use to further investigate?

If not can you explain the full steps so I can replicate this manually?

Comment 2 qding 2023-03-31 14:31:43 UTC
(In reply to Eelco Chaudron from comment #1)
> Can you isolate the issue to a simple reproducer that I can use to further
> investigate?
> 
> If not can you explain the full steps so I can replicate this manually?

I will try to find a simple reproducer and give you an answer next week.

Comment 7 Eelco Chaudron 2023-04-19 15:49:53 UTC
Looking at the setup available I noticed that for some reason the lock is "unlocked" based on the OVS addition, but some threads are waiting for read/write access.

* 1    Thread 0x7f2775b5ec00 (LWP 2710833) 0x00007f27757364ff in pthread_rwlock_wrlock () from /lib64/libpthread.so.0
  3    Thread 0x7f277017b700 (LWP 2710838) 0x00007f2775735ec9 in pthread_rwlock_rdlock () from /lib64/libpthread.so.0
  40   Thread 0x7f27575fa700 (LWP 2710875) 0x00007f2775735ec9 in pthread_rwlock_rdlock () from /lib64/libpthread.so.0
  44   Thread 0x7f2756df6700 (LWP 2710879) 0x00007f2775735ec9 in pthread_rwlock_rdlock () from /lib64/libpthread.so.0
  48   Thread 0x7f27565f2700 (LWP 2710883) 0x00007f2775735ec9 in pthread_rwlock_rdlock () from /lib64/libpthread.so.0
  49   Thread 0x7f27563f1700 (LWP 2710884) 0x00007f2775735ec9 in pthread_rwlock_rdlock () from /lib64/libpthread.so.0

All are waiting for the same netdev_hmap_rwlock, lock. However, the lock looks free / but there are working readers (I do not know the internals of pthread).

(gdb) p netdev_hmap_rwlock
$3 = {lock = {__data = {__readers = 30, __writers = 0, __wrphase_futex = 2, __writers_futex = 1, __pad3 = 0, __pad4 = 0, __cur_writer = 0, __shared = 0, __rwelision = 0 '\000', __pad1 = "\000\000\000\000\000\000", __pad2 = 0, __flags = 2}, 
    __size = "\036\000\000\000\000\000\000\000\002\000\000\000\001", '\000' <repeats 35 times>, "\002\000\000\000\000\000\000", __align = 30}, where = 0x55f8b5f7b1fa "<unlocked>"}

Looked like to me there is some imbalance between lock/unlock. However, I could not find any in the code. I added some logging and I found some read-lock nesting:

     netdev_ports_flow_get()
       It takes the read lock, while it walks all the ports
       in the port_to_netdev hmap and calls:
       - netdev_flow_get() which will call:
         - netdev_tc_flow_get() which will call:
           - netdev_ifindex_to_odp_port()
              This function also takes the same read lock to
              walk the ifindex_to_port hmap.

However in theory this is not a problem, as you are allowed to take the read lock multiple times. I tried some simple code to see if it's a problem on the DUT, and it's not:

```
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

pthread_rwlock_t  rwlock = PTHREAD_RWLOCK_INITIALIZER;

void *read_thread_func(void *ptr)
{
    while(1) {
        pthread_rwlock_rdlock(&rwlock);
        pthread_rwlock_rdlock(&rwlock);
        pthread_rwlock_wrlock(&rwlock);
        printf("read_thread\n");
        pthread_rwlock_unlock(&rwlock);
        pthread_rwlock_unlock(&rwlock);
        pthread_rwlock_unlock(&rwlock);
        sleep(1);
    }
    return NULL;
}

int main()
{
    pthread_t read_thread;

    pthread_create(&read_thread, NULL, read_thread_func, NULL);

    while(1) {
        pthread_rwlock_wrlock(&rwlock);
        printf("a\n");
        pthread_rwlock_unlock(&rwlock);
        sleep(1);
    }
    return 0;
}
```

Just in case I split up the read lock in multiple locks to avoid the recursion of the read lock. I'll run it for some time to see if it fixes the problem or not.

Comment 8 Eelco Chaudron 2023-04-19 15:51:36 UTC
oops, cut/paste an experiment code the while code should not have the write lock, so it should be:

while(1) {
        pthread_rwlock_rdlock(&rwlock);
        pthread_rwlock_rdlock(&rwlock);
        pthread_rwlock_rdlock(&rwlock);
        printf("read_thread\n");
        pthread_rwlock_unlock(&rwlock);
        pthread_rwlock_unlock(&rwlock);
        pthread_rwlock_unlock(&rwlock);
        sleep(1);
    }

Comment 9 Eelco Chaudron 2023-04-19 17:09:58 UTC
(In reply to Eelco Chaudron from comment #7)

> All are waiting for the same netdev_hmap_rwlock, lock. However, the lock
> looks free / but there are working readers (I do not know the internals of
> thread).

Ignore this part, as this is not true. The 'where' value is reset on each unlock...

Comment 10 Eelco Chaudron 2023-04-20 07:26:54 UTC
So the problem is with the way OVS initialises the rw locks. It's per design, see the ovs-thread.h file.

The problem happens when the recursive read lock happens when a write lock is waiting. The following code will cause the issue:

```
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

pthread_rwlock_t  rwlock = PTHREAD_RWLOCK_INITIALIZER;

void *read_thread_func(void *ptr)
{
    while(1) {
        printf("Getting first read lock\n");
        pthread_rwlock_rdlock(&rwlock);
        printf("Got first read lock!\n");
        sleep(10);
        printf("Getting second read lock\n");
        pthread_rwlock_rdlock(&rwlock);
        printf("Got second read lock!\n");
        sleep(5);
        printf("Unlock 2nd read lock\n");
        pthread_rwlock_unlock(&rwlock);
        printf("2nd read unlocked\n");
        printf("Unlock 1st read lock\n");
        pthread_rwlock_unlock(&rwlock);
        printf("1st read unlocked\n");
        sleep(1);
        break;
    }
    return NULL;
}

int main()
{
    int error;
    pthread_t read_thread;

    pthread_create(&read_thread, NULL, read_thread_func, NULL);

    pthread_rwlockattr_t attr;
    pthread_rwlockattr_init(&attr);
    pthread_rwlockattr_setkind_np(
        &attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
    error = pthread_rwlock_init(&rwlock, &attr);
    pthread_rwlockattr_destroy(&attr);

    sleep(2);
    printf("Getting write lock\n");
    pthread_rwlock_wrlock(&rwlock);
    printf("Got write lock\n");
    sleep(1);
    printf("Unlock write lock\n");
    pthread_rwlock_unlock(&rwlock);
    printf("Write unlocked\n");
    sleep(5);
    return 0;
}
```

I will prepare an OVS patch to fix the problem.

Comment 11 Eelco Chaudron 2023-04-20 07:47:09 UTC
A patch was sent upstream to address this problem:

https://patchwork.ozlabs.org/project/openvswitch/patch/168197633909.1845473.12868417804926632801.stgit@ebuild.local/

Comment 12 Eelco Chaudron 2023-05-09 14:32:15 UTC
A v2 was sent for the #11 mentioned patch:

https://patchwork.ozlabs.org/project/openvswitch/patch/168364258097.4336.10159074711651103545.stgit@ebuild.local/

Comment 13 ovs-bugzilla 2023-05-11 00:44:12 UTC
* Wed May 10 2023 Open vSwitch CI <ovs-ci> - 3.1.0-28
- Merging upstream branch-3.1 [RH git: d7b0d724f2]
    Commit list:
    9e27e8fe81 netdev-offload: Fix deadlock/recursive use of the netdev_hmap_rwlock rwlock. (#2182541)
    087439e416 ofproto-dpif-xlate: Fix use-after-free when xlate_actions().

Comment 20 errata-xmlrpc 2023-07-06 20:05:16 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (openvswitch3.1 bug fix and enhancement update), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2023:3994