• gdb ovs


     

    dpif_netdev_run && pmd_thread_main  (没有启动虚拟机去连接 -chardev socket,id=char1,path=$VHOST_SOCK_DIR/vhost-user1,不会有pmd_thread_main

     执行ovs-vsctl add-port br0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuser 会触发pmd_thread_main 

     
    [root@localhost ovs]# ovs-vsctl show
    c013fe69-c1a7-40dd-833b-bef8cd04d43e
        Bridge br0
            datapath_type: netdev
            Port br0
                Interface br0
                    type: internal 
            Port dpdk1
                Interface dpdk1
                    type: dpdk
                    options: {dpdk-devargs="0000:05:00.0"}
         
    [root@localhost ovs]# 

    删除端口

     

     

     if (!netdev_is_pmd(port->netdev))

     

    Breakpoint 1, dpif_netdev_run (dpif=0x204f78a0) at lib/dpif-netdev.c:5438
    5438    {
    (gdb) bt
    #0  dpif_netdev_run (dpif=0x204f78a0) at lib/dpif-netdev.c:5438
    #1  0x000000000097d290 in dpif_run (dpif=<optimized out>) at lib/dpif.c:463
    #2  0x0000000000934c68 in type_run (type=type@entry=0x202dd910 "netdev") at ofproto/ofproto-dpif.c:370
    #3  0x000000000091eb18 in ofproto_type_run (datapath_type=<optimized out>, datapath_type@entry=0x202dd910 "netdev") at ofproto/ofproto.c:1772
    #4  0x000000000090d94c in bridge_run__ () at vswitchd/bridge.c:3242
    #5  0x0000000000913480 in bridge_run () at vswitchd/bridge.c:3307
    #6  0x000000000042469c in main (argc=11, argv=0xffffe2250958) at vswitchd/ovs-vswitchd.c:127
    (gdb) b dp_netdev_process_rxq_port
    Breakpoint 2 at 0x97851c: file lib/dpif-netdev.c, line 4441.
    (gdb) b pmd_thread_main
    Breakpoint 3 at 0x97880c: file lib/dpif-netdev.c, line 5658.
    (gdb) 
    (gdb) c
    Continuing.
    [New Thread 0xffff7c29f910 (LWP 18234)]
    
    Breakpoint 1, dpif_netdev_run (dpif=0x204f78a0) at lib/dpif-netdev.c:5438
    5438    {
    (gdb) bt
    #0  dpif_netdev_run (dpif=0x204f78a0) at lib/dpif-netdev.c:5438
    #1  0x000000000097d290 in dpif_run (dpif=<optimized out>) at lib/dpif.c:463
    #2  0x0000000000934c68 in type_run (type=type@entry=0x202dd910 "netdev") at ofproto/ofproto-dpif.c:370
    #3  0x000000000091eb18 in ofproto_type_run (datapath_type=<optimized out>, datapath_type@entry=0x202dd910 "netdev") at ofproto/ofproto.c:1772
    #4  0x000000000090d94c in bridge_run__ () at vswitchd/bridge.c:3242
    #5  0x0000000000913480 in bridge_run () at vswitchd/bridge.c:3307
    #6  0x000000000042469c in main (argc=11, argv=0xffffe2250958) at vswitchd/ovs-vswitchd.c:127
    (gdb) b dp_netdev_process_rxq_port
    Breakpoint 2 at 0x97851c: file lib/dpif-netdev.c, line 4441.
    (gdb) b pmd_thread_main
    Breakpoint 3 at 0x97880c: file lib/dpif-netdev.c, line 5658.
    (gdb) c
    Continuing.
    
    Breakpoint 2, dp_netdev_process_rxq_port (pmd=pmd@entry=0xffff75f00010, rxq=0x204f7230, port_no=0) at lib/dpif-netdev.c:4441
    4441    {
    (gdb) bt
    #0  dp_netdev_process_rxq_port (pmd=pmd@entry=0xffff75f00010, rxq=0x204f7230, port_no=0) at lib/dpif-netdev.c:4441
    #1  0x000000000097911c in dpif_netdev_run (dpif=<optimized out>) at lib/dpif-netdev.c:5469
    #2  0x000000000097d290 in dpif_run (dpif=<optimized out>) at lib/dpif.c:463
    #3  0x0000000000934c68 in type_run (type=type@entry=0x202dd910 "netdev") at ofproto/ofproto-dpif.c:370
    #4  0x000000000091eb18 in ofproto_type_run (datapath_type=<optimized out>, datapath_type@entry=0x202dd910 "netdev") at ofproto/ofproto.c:1772
    #5  0x000000000090d94c in bridge_run__ () at vswitchd/bridge.c:3242
    #6  0x0000000000913480 in bridge_run () at vswitchd/bridge.c:3307
    #7  0x000000000042469c in main (argc=11, argv=0xffffe2250958) at vswitchd/ovs-vswitchd.c:127
    (gdb) c
    Continuing.
    
    Breakpoint 2, dp_netdev_process_rxq_port (pmd=pmd@entry=0xffff75f00010, rxq=0x2052ec80, port_no=2) at lib/dpif-netdev.c:4441
    4441    {
    (gdb) bt
    #0  dp_netdev_process_rxq_port (pmd=pmd@entry=0xffff75f00010, rxq=0x2052ec80, port_no=2) at lib/dpif-netdev.c:4441
    #1  0x000000000097911c in dpif_netdev_run (dpif=<optimized out>) at lib/dpif-netdev.c:5469
    #2  0x000000000097d290 in dpif_run (dpif=<optimized out>) at lib/dpif.c:463
    #3  0x0000000000934c68 in type_run (type=type@entry=0x202dd910 "netdev") at ofproto/ofproto-dpif.c:370
    #4  0x000000000091eb18 in ofproto_type_run (datapath_type=<optimized out>, datapath_type@entry=0x202dd910 "netdev") at ofproto/ofproto.c:1772  ----执行了
    #5  0x000000000090d94c in bridge_run__ () at vswitchd/bridge.c:3242
    #6  0x0000000000913480 in bridge_run () at vswitchd/bridge.c:3307
    #7  0x000000000042469c in main (argc=11, argv=0xffffe2250958) at vswitchd/ovs-vswitchd.c:127
    (gdb) 
    (gdb) n
    4451        cycle_timer_start(&pmd->perf_stats, &timer);
    (gdb) n
    4441    {
    (gdb) n
    4447        int rem_qlen = 0, *qlen_p = NULL;
    (gdb) n
    4451        cycle_timer_start(&pmd->perf_stats, &timer);
    (gdb) n
    4441    {
    (gdb) n
    4447        int rem_qlen = 0, *qlen_p = NULL;
    (gdb) n
    4451        cycle_timer_start(&pmd->perf_stats, &timer);
    (gdb) n
    4453        pmd->ctx.last_rxq = rxq;
    (gdb) n
    4457        if (pmd_perf_metrics_enabled(pmd) && rxq->is_vhost) {
    (gdb) n
    4451        cycle_timer_start(&pmd->perf_stats, &timer);
    (gdb) n
    4457        if (pmd_perf_metrics_enabled(pmd) && rxq->is_vhost) {
    (gdb) n
    4451        cycle_timer_start(&pmd->perf_stats, &timer);
    (gdb) n
    4454        dp_packet_batch_init(&batch);
    (gdb) set print pretty on
    (gdb) p *batch
    Structure has no component named operator*.
    (gdb) p batch
    $1 = {
      count = 0, 
      trunc = false, 
      do_not_steal = false, 
      packets = {0xffff00000000, 0xa3505c <format_log_message+768>, 0x0, 0x0, 0x20, 0x1, 0xbfe3da, 0x980414 <ds_put_cstr+48>, 0xffffe22505a0, 0xffffe22505a0, 0xffffe2250570, 0xffffff80ffffffd8, 0xffffe22505a0, 0xffffe22505a0, 
        0xffffe22502a0, 0xa28468 <xclock_gettime+12>, 0xffffe22502b0, 0xa28560 <time_timespec__+212>, 0xffffe2250300, 0xa28638 <time_msec+28>, 0x202dd910, 0x204f2150, 0xffffe2250300, 0x9fb848 <ovs_mutex_lock_at+32>, 0xffff7c330f58, 
        0xbd4308, 0xffff00000000, 0xffff7e2a0c64 <malloc+88>, 0xffffe2250320, 0x978f74 <dpif_netdev_run+128>, 0xffffe2250320, 0x979100 <dpif_netdev_run+524>}
    }
    (gdb) 

    dp_netdev_process_rxq_port

    (gdb) bt
    #0  dp_netdev_process_rxq_port (pmd=pmd@entry=0xfffd546d0010, rxq=0x11c8c5d0, port_no=2) at lib/dpif-netdev.c:4480
    #1  0x0000000000978a24 in pmd_thread_main (f_=0xfffd546d0010) at lib/dpif-netdev.c:5731
    #2  0x00000000009fc5dc in ovsthread_wrapper (aux_=<optimized out>) at lib/ovs-thread.c:383
    #3  0x0000ffff95e37d38 in start_thread (arg=0xfffd4fffd510) at pthread_create.c:309
    #4  0x0000ffff95b1f690 in thread_start () from /lib64/libc.so.6
    (gdb) c
    Continuing.
    
    Breakpoint 1, dp_netdev_process_rxq_port (pmd=pmd@entry=0xfffd546d0010, rxq=0x11c8c5d0, port_no=2) at lib/dpif-netdev.c:4480
    4480            dp_netdev_input(pmd, &batch, port_no);
    (gdb) 

     

     

    dp_netdev_process_rxq_port(struct dp_netdev_pmd_thread *pmd,
                               struct netdev_rxq *rx,
                               odp_port_t port_no)
    {
        struct dp_packet_batch batch;
        int error;
    
        dp_packet_batch_init(&batch);
        cycles_count_start(pmd);
        /*通过调用netdev_class->rxq_recv从rx中收包存入batch中*/
        error = netdev_rxq_recv(rx, &batch);             
        cycles_count_end(pmd, PMD_CYCLES_POLLING);
        if (!error) {
            *recirc_depth_get() = 0;
    
            cycles_count_start(pmd);
            /*将batch中的包转入datapath中进行处理*/
            dp_netdev_input(pmd, &batch, port_no);
            cycles_count_end(pmd, PMD_CYCLES_PROCESSING);
        } 
        ...
    }

     

     

     netdev_class的实例有NETDEV_DPDK_CLASS,NETDEV_DUMMY_CLASS,NETDEV_BSD_CLASS,NETDEV_LINUX_CLASS.

    netdev_rxq_recv &netdev_class ----->netdev_dpdk_vhost_rxq_recv

     

    netdev_rxq_recv(struct netdev_rxq *rx, struct dp_packet_batch *batch,
                    int *qfill)
    {
        int retval;
    
        retval = rx->netdev->netdev_class->rxq_recv(rx, batch, qfill);
        if (!retval) {
            COVERAGE_INC(netdev_received);
        } else {
            batch->count = 0;
        }
        return retval;
    }

     

    ovs-vsctl add-port br0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuser

    static const struct netdev_class dpdk_vhost_class = {
        .type = "dpdkvhostuser",
        NETDEV_DPDK_CLASS_COMMON,
        .construct = netdev_dpdk_vhost_construct,
        .destruct = netdev_dpdk_vhost_destruct,
        .send = netdev_dpdk_vhost_send,
        .get_carrier = netdev_dpdk_vhost_get_carrier,
        .get_stats = netdev_dpdk_vhost_get_stats,
        .get_custom_stats = netdev_dpdk_get_sw_custom_stats,
        .get_status = netdev_dpdk_vhost_user_get_status,
        .reconfigure = netdev_dpdk_vhost_reconfigure,
        .rxq_recv = netdev_dpdk_vhost_rxq_recv,
        .rxq_enabled = netdev_dpdk_vhost_rxq_enabled,
    };

     

     

    dp_netdev_input

    用户态Datapath处理packet流程:
            pmd_thread_main           dpif_netdev_run
                                           /
                                         /
                    dp_netdev_process_rxq_port
                               |
                          dp_netdev_input
                               |
                         fast_path_processing
                               |
                        handle_packet_upcall
                           /             
                     (2) /                 (1)
                       /                     
      dp_netdev_execute_actions       dp_netdev_upcall
                      |                         |
             odp_execute_actions             upcall_cb(调用注册的回调函数)
                      |
                dp_execute_cb
                      |
                 netdev_send

     

    netdev_dpdk_rxq_recv

       >     >>         #1  0x00000000007d2252 in rte_eth_rx_burst (nb_pkts=32,
        >     >>
        >     >>         rx_pkts=0x7f3e4bffe7b0, queue_id=0, port_id=0 '00')
        >     >>
        >     >>             at /data1/build/dpdk-stable- rte_eth_rx_burst /x86_64-native-linuxapp-gcc/include/rte_ethdev.h:2774
        >     >>
        >     >>         #2  netdev_dpdk_rxq_recv (rxq=<optimized out>, batch=0x7f3e4bffe7a0)
        >     >>
        >     >>         at lib/netdev-dpdk.c:1664
        >     >>
        >     >>         #3  0x000000000072e571 in netdev_rxq_recv (rx=rx at entry=0x7f3e5cc4a680,
        >     >>
        >     >>         batch=batch at entry=0x7f3e4bffe7a0) at lib/netdev.c:701
        >     >>
        >     >>         #4  0x000000000070ab0e in dp_netdev_process_rxq_port
        >     >>
        >     >>         (pmd=pmd at entry=0x29e5e20, rx=0x7f3e5cc4a680, port_no=1) at
        >     >>
        >     >>         lib/dpif-netdev.c:3114
        >     >>
        >     >>         #5  0x000000000070ad76 in pmd_thread_main (f_=<optimized out>) at
        >     >>
        >     >>         lib/dpif-netdev.c:3854
        >     >>
        >     >>         #6  0x000000000077e4b4 in ovsthread_wrapper (aux_=<optimized out>) at
        >     >>
        >     >>         lib/ovs-thread.c:348
        >     >>
        >     >>         #7  0x00007f3e5fe07dc5 in start_thread (arg=0x7f3e4bfff700) at
        >     >>
        >     >>         pthread_create.c:308
        >     >>
        >     >>         #8  0x00007f3e5f3eb73d in clone () at
        >     >>
        >     >>         ../sysdeps/unix/sysv/linux/x86_64/clone.S:113
        >     >>
        >     >>         (gdb) bt

     

    dpdk_init

    (gdb) bt
    #0 0x00007f3d5f5c31d7 in raise () from /lib64/libc.so.6
    #1 0x00007f3d5f5c48c8 in abort () from /lib64/libc.so.6
    #2 0x00007f3d61184d95 in __rte_panic (
     funcname=funcname@entry=0x7f3d614846b0 <__func__.9925> "rte_eal_init",
     format=format@entry=0x7f3d61483e7c "Cannot init memory
    %.0s")
     at /usr/src/debug/openvswitch-2.6.1/dpdk16.11/lib/librte_eal/linuxapp/eal/eal_debug.c:86
    #3 0x00007f3d6128973a in rte_eal_init (argc=argc@entry=5, argv=<optimized out>)
     at /usr/src/debug/openvswitch-2.6.1/dpdk16.11/lib/librte_eal/linuxapp/eal/eal.c:814
    #4 0x00007f3d61416516 in dpdk_init__
    (ovs_other_config=ovs_other_config@entry=0x7f3d62d497f8)
     at lib/netdev-dpdk.c:3486
    #5 0x00007f3d61416b1c in dpdk_init (ovs_other_config=0x7f3d62d497f8)
     at lib/netdev-dpdk.c:3541
    #6 0x00007f3d613030e2 in bridge_run () at vswitchd/bridge.c:2918
    #7 0x00007f3d6118828d in main (argc=10, argv=0x7ffcc105a128) at vswitchd/ovsvswitchd.c:112
    (gdb)

     

     

    #0 virtio_recv_mergeable_pkts (rx_queue=0x7fbe181bcc00, rx_pkts=0x7fbdd1ffa850,
    nb_pkts=32)
     at /usr/src/debug/openvswitch-2.5.0/dpdk2.2.0/drivers/net/virtio/virtio_rxtx.c:684
    684 nb_used = VIRTQUEUE_NUSED(rxvq);
    Missing separate debuginfos, use: debuginfo-install glibc-2.17-156.el7.x86_64
    keyutils-libs-1.5.8-3.el7.x86_64 krb5-libs-1.14.1-20.el7.x86_64 libcom_err-1.42.9-
    9.el7.x86_64 libgcc-4.8.5-9.el7.x86_64 libselinux-2.5-4.el7.x86_64 openssl-libs1.0.1e-58.el7.x86_64 pcre-8.32-15.el7_2.1.x86_64 zlib-1.2.7-17.el7.x86_64
    (gdb) bt
    #0 virtio_recv_mergeable_pkts (rx_queue=0x7fbe181bcc00, rx_pkts=0x7fbdd1ffa850,
    nb_pkts=32)
     at /usr/src/debug/openvswitch-2.5.0/dpdk2.2.0/drivers/net/virtio/virtio_rxtx.c:684
    #1 0x00007fbe1d61cc6a in rte_eth_rx_burst (nb_pkts=32, rx_pkts=0x7fbdd1ffa850,
    queue_id=0,
     port_id=0 '00')
     at /usr/src/debug/openvswitch-2.5.0/dpdk-2.2.0/x86_64-native-linuxappgcc/include/rte_ethdev.h:2510
    #2 netdev_dpdk_rxq_recv (rxq_=<optimized out>, packets=0x7fbdd1ffa850,
    c=0x7fbdd1ffa84c)
     at lib/netdev-dpdk.c:1092
    #3 0x00007fbe1d592351 in netdev_rxq_recv (rx=<optimized out>,
    buffers=buffers@entry=0x7fbdd1ffa850,
     cnt=cnt@entry=0x7fbdd1ffa84c) at lib/netdev.c:654
    #4 0x00007fbe1d572536 in dp_netdev_process_rxq_port (pmd=pmd@entry=0x7fbe1ea0e730,
     rxq=<optimized out>, port=<optimized out>, port=<optimized out>) at lib/dpifnetdev.c:2594
    #5 0x00007fbe1d5728b9 in pmd_thread_main (f_=0x7fbe1ea0e730) at lib/dpifnetdev.c:2725
    #6 0x00007fbe1d5d48b6 in ovsthread_wrapper (aux_=<optimized out>) at lib/ovsthread.c:340
    #7 0x00007fbe1c733dc5 in start_thread () from /lib64/libpthread.so.0
    #8 0x00007fbe1bb2c73d in clone () from /lib64/libc.so.6

     

     

    (gdb) bt
    #0  0x0000ffff95b14e24 in poll () from /lib64/libc.so.6
    #1  0x0000000000a28780 in time_poll (pollfds=pollfds@entry=0x11c8c820, n_pollfds=11, handles=handles@entry=0x0, timeout_when=453308105, elapsed=elapsed@entry=0xffffe8e999dc) at lib/timeval.c:326
    #2  0x0000000000a12408 in poll_block () at lib/poll-loop.c:364
    #3  0x00000000004246c8 in main (argc=11, argv=0xffffe8e99be8) at vswitchd/ovs-vswitchd.c:138
    (gdb) b rte_vhost_enqueue_burst 
    Breakpoint 1 at 0x90581c
    (gdb) b rte_vhost_dequeue_burst 
    Breakpoint 2 at 0x905a3c

     

     

     

    (gdb) c
    Continuing.
    [New Thread 0xffff9333f910 (LWP 14604)]
    [New Thread 0xfffd4d62d510 (LWP 14605)]
    [Thread 0xffff9333f910 (LWP 14604) exited]
    [New Thread 0xffff9333f910 (LWP 14620)]
    [Thread 0xffff9333f910 (LWP 14620) exited]
    [New Thread 0xffff9333f910 (LWP 14621)]
    [Thread 0xffff9333f910 (LWP 14621) exited]
    [New Thread 0xffff9333f910 (LWP 14636)]
    [Thread 0xffff9333f910 (LWP 14636) exited]
    [New Thread 0xffff9333f910 (LWP 14646)]
    [Switching to Thread 0xfffd4ef1d510 (LWP 14393)]
    
    Breakpoint 2, 0x0000000000905a3c in rte_vhost_dequeue_burst ()
    (gdb) bt
    #0  0x0000000000905a3c in rte_vhost_dequeue_burst ()
    #1  0x0000000000a62d04 in netdev_dpdk_vhost_rxq_recv (rxq=<optimized out>, batch=0xfffd4ef1ca80, qfill=0x0) at lib/netdev-dpdk.c:2442
    #2  0x00000000009a440c in netdev_rxq_recv (rx=<optimized out>, batch=batch@entry=0xfffd4ef1ca80, qfill=<optimized out>) at lib/netdev.c:726
    #3  0x00000000009785bc in dp_netdev_process_rxq_port (pmd=pmd@entry=0xfffd4ef20010, rxq=0x11efe540, port_no=3) at lib/dpif-netdev.c:4461
    #4  0x0000000000978a24 in pmd_thread_main (f_=0xfffd4ef20010) at lib/dpif-netdev.c:5731
    #5  0x00000000009fc5dc in ovsthread_wrapper (aux_=<optimized out>) at lib/ovs-thread.c:383
    #6  0x0000ffff95e37d38 in start_thread (arg=0xfffd4ef1d510) at pthread_create.c:309
    #7  0x0000ffff95b1f690 in thread_start () from /lib64/libc.so.6
    (gdb) c
    Continuing.
    [Switching to Thread 0xfffd4fffd510 (LWP 14391)]
    
    Breakpoint 1, 0x000000000090581c in rte_vhost_enqueue_burst ()
    (gdb) btt
    Undefined command: "btt".  Try "help".
    (gdb) bt
    #0  0x000000000090581c in rte_vhost_enqueue_burst ()
    #1  0x0000000000a60b90 in __netdev_dpdk_vhost_send (netdev=0x19fd81a40, qid=<optimized out>, pkts=pkts@entry=0xfffd3019daf0, cnt=32) at lib/netdev-dpdk.c:2662
    #2  0x0000000000a6198c in netdev_dpdk_vhost_send (netdev=<optimized out>, qid=<optimized out>, batch=0xfffd3019dae0, concurrent_txq=<optimized out>) at lib/netdev-dpdk.c:2893
    #3  0x00000000009a478c in netdev_send (netdev=0x19fd81a40, qid=qid@entry=0, batch=batch@entry=0xfffd3019dae0, concurrent_txq=concurrent_txq@entry=true) at lib/netdev.c:893
    #4  0x000000000096fae8 in dp_netdev_pmd_flush_output_on_port (pmd=pmd@entry=0xfffd546d0010, p=p@entry=0xfffd3019dab0) at lib/dpif-netdev.c:4391
    #5  0x000000000096fdfc in dp_netdev_pmd_flush_output_packets (pmd=pmd@entry=0xfffd546d0010, force=force@entry=false) at lib/dpif-netdev.c:4431
    #6  0x00000000009787d8 in dp_netdev_pmd_flush_output_packets (force=false, pmd=0xfffd546d0010) at lib/dpif-netdev.c:4501
    #7  dp_netdev_process_rxq_port (pmd=pmd@entry=0xfffd546d0010, rxq=0x11c8c5d0, port_no=2) at lib/dpif-netdev.c:4486
    #8  0x0000000000978a24 in pmd_thread_main (f_=0xfffd546d0010) at lib/dpif-netdev.c:5731
    #9  0x00000000009fc5dc in ovsthread_wrapper (aux_=<optimized out>) at lib/ovs-thread.c:383
    #10 0x0000ffff95e37d38 in start_thread (arg=0xfffd4fffd510) at pthread_create.c:309
    #11 0x0000ffff95b1f690 in thread_start () from /lib64/libc.so.6
    (gdb) c
    Continuing.
    
    Breakpoint 1, 0x000000000090581c in rte_vhost_enqueue_burst ()
    (gdb) bt
    #0  0x000000000090581c in rte_vhost_enqueue_burst ()
    #1  0x0000000000a60b90 in __netdev_dpdk_vhost_send (netdev=0x19fd81a40, qid=<optimized out>, pkts=pkts@entry=0xfffd3019daf0, cnt=32) at lib/netdev-dpdk.c:2662
    #2  0x0000000000a6198c in netdev_dpdk_vhost_send (netdev=<optimized out>, qid=<optimized out>, batch=0xfffd3019dae0, concurrent_txq=<optimized out>) at lib/netdev-dpdk.c:2893
    #3  0x00000000009a478c in netdev_send (netdev=0x19fd81a40, qid=qid@entry=0, batch=batch@entry=0xfffd3019dae0, concurrent_txq=concurrent_txq@entry=true) at lib/netdev.c:893
    #4  0x000000000096fae8 in dp_netdev_pmd_flush_output_on_port (pmd=pmd@entry=0xfffd546d0010, p=p@entry=0xfffd3019dab0) at lib/dpif-netdev.c:4391
    #5  0x000000000096fdfc in dp_netdev_pmd_flush_output_packets (pmd=pmd@entry=0xfffd546d0010, force=force@entry=false) at lib/dpif-netdev.c:4431
    #6  0x00000000009787d8 in dp_netdev_pmd_flush_output_packets (force=false, pmd=0xfffd546d0010) at lib/dpif-netdev.c:4501
    #7  dp_netdev_process_rxq_port (pmd=pmd@entry=0xfffd546d0010, rxq=0x11c8c5d0, port_no=2) at lib/dpif-netdev.c:4486
    #8  0x0000000000978a24 in pmd_thread_main (f_=0xfffd546d0010) at lib/dpif-netdev.c:5731
    #9  0x00000000009fc5dc in ovsthread_wrapper (aux_=<optimized out>) at lib/ovs-thread.c:383
    #10 0x0000ffff95e37d38 in start_thread (arg=0xfffd4fffd510) at pthread_create.c:309
    #11 0x0000ffff95b1f690 in thread_start () from /lib64/libc.so.6

     

     

    dp_netdev_process_rxq_port(struct dp_netdev_pmd_thread *pmd,
                               struct dp_netdev_rxq *rxq,
                               odp_port_t port_no)
    {
        struct pmd_perf_stats *s = &pmd->perf_stats;
        struct dp_packet_batch batch;
        struct cycle_timer timer;
        int error;
        int batch_cnt = 0;
        int rem_qlen = 0, *qlen_p = NULL;
        uint64_t cycles;
    
        /* Measure duration for polling and processing rx burst. */
        cycle_timer_start(&pmd->perf_stats, &timer);
    
        pmd->ctx.last_rxq = rxq;
        dp_packet_batch_init(&batch);
    
        /* Fetch the rx queue length only for vhostuser ports. */
        if (pmd_perf_metrics_enabled(pmd) && rxq->is_vhost) {
            qlen_p = &rem_qlen;
        }
    
        error = netdev_rxq_recv(rxq->rx, &batch, qlen_p); //dequeue
        if (!error) {
            /* At least one packet received. */
            *recirc_depth_get() = 0;
            pmd_thread_ctx_time_update(pmd);
            batch_cnt = dp_packet_batch_size(&batch);
            if (pmd_perf_metrics_enabled(pmd)) {
                /* Update batch histogram. */
                s->current.batches++;
                histogram_add_sample(&s->pkts_per_batch, batch_cnt);
                /* Update the maximum vhost rx queue fill level. */
                if (rxq->is_vhost && rem_qlen >= 0) {
                    uint32_t qfill = batch_cnt + rem_qlen;
                    if (qfill > s->current.max_vhost_qfill) {
                        s->current.max_vhost_qfill = qfill;
                    }
                }
            }
            /* Process packet batch. */
            dp_netdev_input(pmd, &batch, port_no); //流处理
    
            /* Assign processing cycles to rx queue. */
            cycles = cycle_timer_stop(&pmd->perf_stats, &timer);
            dp_netdev_rxq_add_cycles(rxq, RXQ_CYCLES_PROC_CURR, cycles);
    
            dp_netdev_pmd_flush_output_packets(pmd, false);   // enqueue
        } else {
            /* Discard cycles. */
            cycle_timer_stop(&pmd->perf_stats, &timer);
            if (error != EAGAIN && error != EOPNOTSUPP) {
                static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
    
                VLOG_ERR_RL(&rl, "error receiving data from %s: %s",
                        netdev_rxq_get_name(rxq->rx), ovs_strerror(error));
            }
        }
    
        pmd->ctx.last_rxq = NULL;
    
        return batch_cnt;
    }

     

     

    执行 ovs-vsctl add-port br0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuser

    [New Thread 0xffff9333f910 (LWP 14604)]
    [New Thread 0xfffd4d62d510 (LWP 14605)]
    [Thread 0xffff9333f910 (LWP 14604) exited]
    [New Thread 0xffff9333f910 (LWP 14620)]
    [Thread 0xffff9333f910 (LWP 14620) exited]
    [New Thread 0xffff9333f910 (LWP 14621)]
    [Thread 0xffff9333f910 (LWP 14621) exited]
    [New Thread 0xffff9333f910 (LWP 14636)]
    [Thread 0xffff9333f910 (LWP 14636) exited]
    [New Thread 0xffff9333f910 (LWP 14646)]
    [Switching to Thread 0xfffd4ef1d510 (LWP 14393)]

     

     

     

     

     

     

     

    netdev_open

    could not create netdev dpdk1 of unknown type dpdk

    ovs-vsctl add-br br0 -- set bridge br0 datapath_type=netdev
    Breakpoint 1, netdev_open (name=0x11f01c40 "br0", type=type@entry=0x0, netdevp=netdevp@entry=0xffffe8e996c8) at lib/netdev.c:372
    372     {
    (gdb) bt
    #0  netdev_open (name=0x11f01c40 "br0", type=type@entry=0x0, netdevp=netdevp@entry=0xffffe8e996c8) at lib/netdev.c:372
    #1  0x000000000094f8a0 in xbridge_addr_create (xbridge=0x11c95dc0, xbridge=0x11c95dc0) at ofproto/ofproto-dpif-xlate.c:900
    #2  xlate_ofproto_set (ofproto=ofproto@entry=0x11eb6a80, name=0x11c88a50 "br0", dpif=0x11c8cb90, ml=0x11ecc400, stp=0x0, rstp=0x0, ms=0x0, mbridge=0x11ec9e70, sflow=sflow@entry=0x0, ipfix=ipfix@entry=0x0, 
        netflow=netflow@entry=0x0, forward_bpdu=forward_bpdu@entry=false, has_in_band=false, support=0x11c51350) at ofproto/ofproto-dpif-xlate.c:1266
    #3  0x000000000093555c in type_run (type=type@entry=0x11c96dc0 "netdev") at ofproto/ofproto-dpif.c:481
    #4  0x000000000091eb18 in ofproto_type_run (datapath_type=<optimized out>, datapath_type@entry=0x11c96dc0 "netdev") at ofproto/ofproto.c:1772
    #5  0x000000000090d94c in bridge_run__ () at vswitchd/bridge.c:3242
    #6  0x0000000000913480 in bridge_run () at vswitchd/bridge.c:3307
    #7  0x000000000042469c in main (argc=11, argv=0xffffe8e99be8) at vswitchd/ovs-vswitchd.c:127

     ovs的datapath_type有nedev和system,netdev表示用户态数据访问,system表示内核数据访问

     

    (gdb) b type_run 
    Breakpoint 1 at 0x934c28: file ofproto/ofproto-dpif.c, line 360.
    (gdb) c
    Continuing.
    
    Breakpoint 1, type_run (type=type@entry=0x20530510 "netdev") at ofproto/ofproto-dpif.c:360
    360     {
    (gdb) list
    355         return NULL;
    356     }
    357
    358     static int
    359     type_run(const char *type)
    360     {
    361         struct dpif_backer *backer;
    362
    363         backer = shash_find_data(&all_dpif_backers, type);
    364         if (!backer) {
    (gdb) n
    363         backer = shash_find_data(&all_dpif_backers, type);
    (gdb) n
    360     {
    (gdb) n
    363         backer = shash_find_data(&all_dpif_backers, type);
    (gdb) n
    360     {
    (gdb) n
    363         backer = shash_find_data(&all_dpif_backers, type);
    (gdb) n
    364         if (!backer) {
    (gdb) n
    370         if (dpif_run(backer->dpif)) {
    (gdb) set print pretty on
    (gdb) p *backer
    $1 = {
      type = 0x204f2130 "netdev", 
      refcount = 1, 
      dpif = 0x204f78a0, 
      udpif = 0x204f7940, 
      odp_to_ofport_lock = {
        lock = {
          __data = {
            __lock = 0, 
            __nr_readers = 0, 
            __readers_wakeup = 0, 
            __writer_wakeup = 0, 
            __nr_readers_queued = 0, 
            __nr_writers_queued = 0, 
            __writer = 0, 
            __shared = 0, 
            __pad1 = 0, 
            __pad2 = 0, 
            __flags = 1
          }, 
          __size = '00' <repeats 48 times>, "01000000000000", 
          __align = 0
        }, 
        where = 0xbc50c0 "<unlocked>"
      }, 
      odp_to_ofport_map = {
        buckets = 0x202acc60, 
        one = 0x0, 
        mask = 3, 
        n = 2
      }, 
      tnl_backers = {
        map = {
          buckets = 0x204f21d8, 
          one = 0x0, 
          mask = 0, 
          n = 0
        }
      }, 
      need_revalidate = 0, 
      recv_set_enable = true, 
      meter_ids = 0x20504710, 
      tp_ids = 0x20508e40, 
      ct_zones = {
        impl = {
          p = 0x10f2a40 <empty_cmap>
        }
      }, 
      ct_tps = {
        buckets = 0x204f2218, 
        one = 0x0, 
        mask = 0, 
        n = 0
      }, 
      ct_tp_kill_list = {
        prev = 0x204f2230, 
        next = 0x204f2230
      }, 
      dp_version_string = 0x2050c9a0 "<built-in>", 
    ---Type <return> to continue, or q <return> to quit---
      bt_support = {
        masked_set_action = true, 
        tnl_push_pop = true, 
        ufid = true, 
        trunc = true, 
        clone = true, 
        sample_nesting = 10, 
        ct_eventmask = true, 
        ct_clear = true, 
        max_hash_alg = 1, 
        check_pkt_len = true, 
        ct_timeout = true, 
        explicit_drop_action = true, 
        odp = {
          max_vlan_headers = 1, 
          max_mpls_depth = 3, 
          recirc = true, 
          ct_state = true, 
          ct_zone = true, 
          ct_mark = true, 
          ct_label = true, 
          ct_state_nat = true, 
          ct_orig_tuple = true, 
          ct_orig_tuple6 = true, 
          nd_ext = true
        }
      }, 
      rt_support = {
        masked_set_action = true, 
        tnl_push_pop = true, 
        ufid = true, 
        trunc = true, 
        clone = true, 
        sample_nesting = 10, 
        ct_eventmask = true, 
        ct_clear = true, 
        max_hash_alg = 1, 
        check_pkt_len = true, 
        ct_timeout = true, 
        explicit_drop_action = true, 
        odp = {
          max_vlan_headers = 1, 
          max_mpls_depth = 3, 
          recirc = true, 
          ct_state = true, 
          ct_zone = true, 
          ct_mark = true, 
          ct_label = true, 
          ct_state_nat = true, 
          ct_orig_tuple = true, 
          ct_orig_tuple6 = true, 
          nd_ext = true
        }
      }, 
      tnl_count = {
        count = 0
      }
    }
    (gdb) 
    (gdb) 
    (gdb) p backer->dpif
    $2 = (struct dpif *) 0x204f78a0
    (gdb) p *(backer->dpif)
    $3 = {
      dpif_class = 0xbd2650 <dpif_netdev_class>, 
      base_name = 0x204f73e0 "ovs-netdev", 
      full_name = 0x204f78e0 "netdev@ovs-netdev", 
      netflow_engine_type = 47 '/', 
      netflow_engine_id = 209 '321', 
      current_ms = 464123586
    }
    (gdb)

     

    dpif_class

    datapath接口实现类,每种datapath都有对应的接口实现实例。dpif有两种实现类:dpif_netlink_class、dpif_netdev_class。即system、netdev。比如,dpdk的netdevdatapath类型的实现实例dpif_netdev_class。

     

    (gdb) p *(backer->dpif)
    $3 = {
      dpif_class = 0xbd2650 <dpif_netdev_class>, 
      base_name = 0x204f73e0 "ovs-netdev", 
      full_name = 0x204f78e0 "netdev@ovs-netdev", 
      netflow_engine_type = 47 '/', 
      netflow_engine_id = 209 '321', 
      current_ms = 464123586
    }
    (gdb)

     

     

    struct dpif {
        const struct dpif_class *dpif_class;
        char *base_name;
        char *full_name;
        uint8_t netflow_engine_type;
        uint8_t netflow_engine_id;
        long long int current_ms;
    };

     

     

    struct dpif_class {
        /* Type of dpif in this class, e.g. "system", "netdev", etc.
         *
         * One of the providers should supply a "system" type, since this is
         * the type assumed if no type is specified when opening a dpif. */
        const char *type;
    
        /* Enumerates the names of all known created datapaths, if possible, into
         * 'all_dps'.  The caller has already initialized 'all_dps' and other dpif
         * classes might already have added names to it.
         *
         * This is used by the vswitch at startup, so that it can delete any
         * datapaths that are not configured.
         *
         * Some kinds of datapaths might not be practically enumerable, in which
         * case this function may be a null pointer. */
        int (*enumerate)(struct sset *all_dps);
    
        /* Returns the type to pass to netdev_open() when a dpif of class
         * 'dpif_class' has a port of type 'type', for a few special cases
         * when a netdev type differs from a port type.  For example, when
         * using the userspace datapath, a port of type "internal" needs to
         * be opened as "tap".
         *
         * Returns either 'type' itself or a string literal, which must not
         * be freed. */
        const char *(*port_open_type)(const struct dpif_class *dpif_class,
                                      const char *type);
    
        /* Attempts to open an existing dpif called 'name', if 'create' is false,
         * or to open an existing dpif or create a new one, if 'create' is true.
         *
         * 'dpif_class' is the class of dpif to open.
         *
         * If successful, stores a pointer to the new dpif in '*dpifp', which must
         * have class 'dpif_class'.  On failure there are no requirements on what
         * is stored in '*dpifp'. */
        int (*open)(const struct dpif_class *dpif_class,
                    const char *name, bool create, struct dpif **dpifp);
    
        /* Closes 'dpif' and frees associated memory. */
        void (*close)(struct dpif *dpif);
    
        /* Attempts to destroy the dpif underlying 'dpif'.
         *
         * If successful, 'dpif' will not be used again except as an argument for
         * the 'close' member function. */
        int (*destroy)(struct dpif *dpif);
    
        /* Performs periodic work needed by 'dpif', if any is necessary. */
        void (*run)(struct dpif *dpif);
    
        /* Arranges for poll_block() to wake up if the "run" member function needs
         * to be called for 'dpif'. */
        void (*wait)(struct dpif *dpif);
    
        /* Retrieves statistics for 'dpif' into 'stats'. */
        int (*get_stats)(const struct dpif *dpif, struct dpif_dp_stats *stats);
    
        /* Adds 'netdev' as a new port in 'dpif'.  If '*port_no' is not
         * UINT32_MAX, attempts to use that as the port's port number.
         *
         * If port is successfully added, sets '*port_no' to the new port's
         * port number.  Returns EBUSY if caller attempted to choose a port
         * number, and it was in use. */
        int (*port_add)(struct dpif *dpif, struct netdev *netdev,
                        uint32_t *port_no);
    
        /* Removes port numbered 'port_no' from 'dpif'. */
        int (*port_del)(struct dpif *dpif, uint32_t port_no);
    
        /* Queries 'dpif' for a port with the given 'port_no' or 'devname'.
         * If 'port' is not null, stores information about the port into
         * '*port' if successful.
         *
         * If 'port' is not null, the caller takes ownership of data in
         * 'port' and must free it with dpif_port_destroy() when it is no
         * longer needed. */
        int (*port_query_by_number)(const struct dpif *dpif, uint32_t port_no,
                                    struct dpif_port *port);
        int (*port_query_by_name)(const struct dpif *dpif, const char *devname,
                                  struct dpif_port *port);
    
        /* Returns one greater than the largest port number accepted in flow
         * actions. */
        int (*get_max_ports)(const struct dpif *dpif);
    
        /* Returns the Netlink PID value to supply in OVS_ACTION_ATTR_USERSPACE
         * actions as the OVS_USERSPACE_ATTR_PID attribute's value, for use in
         * flows whose packets arrived on port 'port_no'.
         *
         * A 'port_no' of UINT32_MAX should be treated as a special case.  The
         * implementation should return a reserved PID, not allocated to any port,
         * that the client may use for special purposes.
         *
         * The return value only needs to be meaningful when DPIF_UC_ACTION has
         * been enabled in the 'dpif''s listen mask, and it is allowed to change
         * when DPIF_UC_ACTION is disabled and then re-enabled.
         *
         * A dpif provider that doesn't have meaningful Netlink PIDs can use NULL
         * for this function.  This is equivalent to always returning 0. */
        uint32_t (*port_get_pid)(const struct dpif *dpif, uint32_t port_no);
    
        /* Attempts to begin dumping the ports in a dpif.  On success, returns 0
         * and initializes '*statep' with any data needed for iteration.  On
         * failure, returns a positive errno value. */
        int (*port_dump_start)(const struct dpif *dpif, void **statep);
    
        /* Attempts to retrieve another port from 'dpif' for 'state', which was
         * initialized by a successful call to the 'port_dump_start' function for
         * 'dpif'.  On success, stores a new dpif_port into 'port' and returns 0.
         * Returns EOF if the end of the port table has been reached, or a positive
         * errno value on error.  This function will not be called again once it
         * returns nonzero once for a given iteration (but the 'port_dump_done'
         * function will be called afterward).
         *
         * The dpif provider retains ownership of the data stored in 'port'.  It
         * must remain valid until at least the next call to 'port_dump_next' or
         * 'port_dump_done' for 'state'. */
        int (*port_dump_next)(const struct dpif *dpif, void *state,
                              struct dpif_port *port);
    
        /* Releases resources from 'dpif' for 'state', which was initialized by a
         * successful call to the 'port_dump_start' function for 'dpif'.  */
        int (*port_dump_done)(const struct dpif *dpif, void *state);
    
        /* Polls for changes in the set of ports in 'dpif'.  If the set of ports in
         * 'dpif' has changed, then this function should do one of the
         * following:
         *
         * - Preferably: store the name of the device that was added to or deleted
         *   from 'dpif' in '*devnamep' and return 0.  The caller is responsible
         *   for freeing '*devnamep' (with free()) when it no longer needs it.
         *
         * - Alternatively: return ENOBUFS, without indicating the device that was
         *   added or deleted.
         *
         * Occasional 'false positives', in which the function returns 0 while
         * indicating a device that was not actually added or deleted or returns
         * ENOBUFS without any change, are acceptable.
         *
         * If the set of ports in 'dpif' has not changed, returns EAGAIN.  May also
         * return other positive errno values to indicate that something has gone
         * wrong. */
        int (*port_poll)(const struct dpif *dpif, char **devnamep);
    
        /* Arranges for the poll loop to wake up when 'port_poll' will return a
         * value other than EAGAIN. */
        void (*port_poll_wait)(const struct dpif *dpif);
    
        /* Queries 'dpif' for a flow entry.  The flow is specified by the Netlink
         * attributes with types OVS_KEY_ATTR_* in the 'key_len' bytes starting at
         * 'key'.
         *
         * Returns 0 if successful.  If no flow matches, returns ENOENT.  On other
         * failure, returns a positive errno value.
         *
         * If 'actionsp' is nonnull, then on success '*actionsp' must be set to an
         * ofpbuf owned by the caller that contains the Netlink attributes for the
         * flow's actions.  The caller must free the ofpbuf (with ofpbuf_delete())
         * when it is no longer needed.
         *
         * If 'stats' is nonnull, then on success it must be updated with the
         * flow's statistics. */
        int (*flow_get)(const struct dpif *dpif,
                        const struct nlattr *key, size_t key_len,
                        struct ofpbuf **actionsp, struct dpif_flow_stats *stats);
    
        /* Adds or modifies a flow in 'dpif'.  The flow is specified by the Netlink
         * attributes with types OVS_KEY_ATTR_* in the 'put->key_len' bytes
         * starting at 'put->key'.  The associated actions are specified by the
         * Netlink attributes with types OVS_ACTION_ATTR_* in the
         * 'put->actions_len' bytes starting at 'put->actions'.
         *
         * - If the flow's key does not exist in 'dpif', then the flow will be
         *   added if 'put->flags' includes DPIF_FP_CREATE.  Otherwise the
         *   operation will fail with ENOENT.
         *
         *   If the operation succeeds, then 'put->stats', if nonnull, must be
         *   zeroed.
         *
         * - If the flow's key does exist in 'dpif', then the flow's actions will
         *   be updated if 'put->flags' includes DPIF_FP_MODIFY.  Otherwise the
         *   operation will fail with EEXIST.  If the flow's actions are updated,
         *   then its statistics will be zeroed if 'put->flags' includes
         *   DPIF_FP_ZERO_STATS, and left as-is otherwise.
         *
         *   If the operation succeeds, then 'put->stats', if nonnull, must be set
         *   to the flow's statistics before the update.
         */
        int (*flow_put)(struct dpif *dpif, const struct dpif_flow_put *put);
    
        /* Deletes a flow from 'dpif' and returns 0, or returns ENOENT if 'dpif'
         * does not contain such a flow.  The flow is specified by the Netlink
         * attributes with types OVS_KEY_ATTR_* in the 'del->key_len' bytes
         * starting at 'del->key'.
         *
         * If the operation succeeds, then 'del->stats', if nonnull, must be set to
         * the flow's statistics before its deletion. */
        int (*flow_del)(struct dpif *dpif, const struct dpif_flow_del *del);
    
        /* Deletes all flows from 'dpif' and clears all of its queues of received
         * packets. */
        int (*flow_flush)(struct dpif *dpif);
    
        /* Attempts to begin dumping the flows in a dpif.  On success, returns 0
         * and initializes '*statep' with any data needed for iteration.  On
         * failure, returns a positive errno value. */
        int (*flow_dump_start)(const struct dpif *dpif, void **statep);
    
        /* Attempts to retrieve another flow from 'dpif' for 'state', which was
         * initialized by a successful call to the 'flow_dump_start' function for
         * 'dpif'.  On success, updates the output parameters as described below
         * and returns 0.  Returns EOF if the end of the flow table has been
         * reached, or a positive errno value on error.  This function will not be
         * called again once it returns nonzero within a given iteration (but the
         * 'flow_dump_done' function will be called afterward).
         *
         * On success, if 'key' and 'key_len' are nonnull then '*key' and
         * '*key_len' must be set to Netlink attributes with types OVS_KEY_ATTR_*
         * representing the dumped flow's key.  If 'actions' and 'actions_len' are
         * nonnull then they should be set to Netlink attributes with types
         * OVS_ACTION_ATTR_* representing the dumped flow's actions.  If 'stats'
         * is nonnull then it should be set to the dumped flow's statistics.
         *
         * All of the returned data is owned by 'dpif', not by the caller, and the
         * caller must not modify or free it.  'dpif' must guarantee that it
         * remains accessible and unchanging until at least the next call to
         * 'flow_dump_next' or 'flow_dump_done' for 'state'. */
        int (*flow_dump_next)(const struct dpif *dpif, void *state,
                              const struct nlattr **key, size_t *key_len,
                              const struct nlattr **actions, size_t *actions_len,
                              const struct dpif_flow_stats **stats);
    
        /* Releases resources from 'dpif' for 'state', which was initialized by a
         * successful call to the 'flow_dump_start' function for 'dpif'.  */
        int (*flow_dump_done)(const struct dpif *dpif, void *state);
    
        /* Performs the 'execute->actions_len' bytes of actions in
         * 'execute->actions' on the Ethernet frame specified in 'execute->packet'
         * taken from the flow specified in the 'execute->key_len' bytes of
         * 'execute->key'.  ('execute->key' is mostly redundant with
         * 'execute->packet', but it contains some metadata that cannot be
         * recovered from 'execute->packet', such as tunnel and in_port.) */
        int (*execute)(struct dpif *dpif, const struct dpif_execute *execute);
    
        /* Executes each of the 'n_ops' operations in 'ops' on 'dpif', in the order
         * in which they are specified, placing each operation's results in the
         * "output" members documented in comments.
         *
         * This function is optional.  It is only worthwhile to implement it if
         * 'dpif' can perform operations in batch faster than individually. */
        void (*operate)(struct dpif *dpif, struct dpif_op **ops, size_t n_ops);
    
        /* Enables or disables receiving packets with dpif_recv() for 'dpif'.
         * Turning packet receive off and then back on is allowed to change Netlink
         * PID assignments (see ->port_get_pid()).  The client is responsible for
         * updating flows as necessary if it does this. */
        int (*recv_set)(struct dpif *dpif, bool enable);
    
        /* Translates OpenFlow queue ID 'queue_id' (in host byte order) into a
         * priority value used for setting packet priority. */
        int (*queue_to_priority)(const struct dpif *dpif, uint32_t queue_id,
                                 uint32_t *priority);
    
        /* Polls for an upcall from 'dpif'.  If successful, stores the upcall into
         * '*upcall', using 'buf' for storage.  Should only be called if 'recv_set'
         * has been used to enable receiving packets from 'dpif'.
         *
         * The implementation should point 'upcall->packet' and 'upcall->key' into
         * data in the caller-provided 'buf'.  If necessary to make room, the
         * implementation may expand the data in 'buf'.  (This is hardly a great
         * way to do things but it works out OK for the dpif providers that exist
         * so far.)
         *
         * This function must not block.  If no upcall is pending when it is
         * called, it should return EAGAIN without blocking. */
        int (*recv)(struct dpif *dpif, struct dpif_upcall *upcall,
                    struct ofpbuf *buf);
    
        /* Arranges for the poll loop to wake up when 'dpif' has a message queued
         * to be received with the recv member function. */
        void (*recv_wait)(struct dpif *dpif);
    
        /* Throws away any queued upcalls that 'dpif' currently has ready to
         * return. */
        void (*recv_purge)(struct dpif *dpif);
    };

     

    dpif_class注册
    dp_initialize(void)
    {
        static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
    
        if (ovsthread_once_start(&once)) {
            int i;
    
            tnl_conf_seq = seq_create();
            dpctl_unixctl_register();
            tnl_port_map_init();
            tnl_neigh_cache_init();
            route_table_init();
    
            for (i = 0; i < ARRAY_SIZE(base_dpif_classes); i++) {
                dp_register_provider(base_dpif_classes[i]);
            }
    
            ovsthread_once_done(&once);
        }
    }

     

    static const struct dpif_class *base_dpif_classes[] = {
    #if defined(__linux__) || defined(_WIN32)
        &dpif_netlink_class,
    #endif
        &dpif_netdev_class,
    };

     

    dpif_netdev_class

    const struct dpif_class dpif_netdev_class = {
        "netdev",
        true,                       /* cleanup_required */
        dpif_netdev_init,
        dpif_netdev_enumerate,
        dpif_netdev_port_open_type,
        dpif_netdev_open,
        dpif_netdev_close,
        dpif_netdev_destroy,
        dpif_netdev_run,
        dpif_netdev_wait,
        dpif_netdev_get_stats,
        NULL,                      /* set_features */
        dpif_netdev_port_add,
        dpif_netdev_port_del,
        dpif_netdev_port_set_config,
        dpif_netdev_port_query_by_number,
        dpif_netdev_port_query_by_name,
        NULL,                       /* port_get_pid */
        dpif_netdev_port_dump_start,
        dpif_netdev_port_dump_next,
        dpif_netdev_port_dump_done,
        dpif_netdev_port_poll,
        dpif_netdev_port_poll_wait,
        dpif_netdev_flow_flush,
        dpif_netdev_flow_dump_create,
        dpif_netdev_flow_dump_destroy,
        dpif_netdev_flow_dump_thread_create,
        dpif_netdev_flow_dump_thread_destroy,
        dpif_netdev_flow_dump_next,
        dpif_netdev_operate,
        NULL,                       /* recv_set */
        NULL,                       /* handlers_set */
        dpif_netdev_set_config,
        dpif_netdev_queue_to_priority,
        NULL,                       /* recv */
        NULL,                       /* recv_wait */
        NULL,                       /* recv_purge */
        dpif_netdev_register_dp_purge_cb,
        dpif_netdev_register_upcall_cb,
        dpif_netdev_enable_upcall,
        dpif_netdev_disable_upcall,
        dpif_netdev_get_datapath_version,
        dpif_netdev_ct_dump_start,
        dpif_netdev_ct_dump_next,
        dpif_netdev_ct_dump_done,
        dpif_netdev_ct_flush,
        dpif_netdev_ct_set_maxconns,
        dpif_netdev_ct_get_maxconns,
        dpif_netdev_ct_get_nconns,
        dpif_netdev_ct_set_tcp_seq_chk,
        dpif_netdev_ct_get_tcp_seq_chk,
        dpif_netdev_ct_set_limits,
        dpif_netdev_ct_get_limits,
        dpif_netdev_ct_del_limits,
        NULL,                       /* ct_set_timeout_policy */
        NULL,                       /* ct_get_timeout_policy */

    dpif_netdev_run

    (gdb) b dpif_netdev_run
    Breakpoint 1 at 0x978ef4: file lib/dpif-netdev.c, line 5438.
    (gdb) c
    Continuing.
    
    Breakpoint 1, dpif_netdev_run (dpif=0x204f78a0) at lib/dpif-netdev.c:5438
    5438    {
    (gdb) bt
    #0  dpif_netdev_run (dpif=0x204f78a0) at lib/dpif-netdev.c:5438
    #1  0x000000000097d290 in dpif_run (dpif=<optimized out>) at lib/dpif.c:463
    #2  0x0000000000934c68 in type_run (type=type@entry=0x202db460 "netdev") at ofproto/ofproto-dpif.c:370
    #3  0x000000000091eb18 in ofproto_type_run (datapath_type=<optimized out>, datapath_type@entry=0x202db460 "netdev") at ofproto/ofproto.c:1772
    #4  0x000000000090d94c in bridge_run__ () at vswitchd/bridge.c:3242
    #5  0x0000000000913480 in bridge_run () at vswitchd/bridge.c:3307
    #6  0x000000000042469c in main (argc=11, argv=0xffffe2250958) at vswitchd/ovs-vswitchd.c:127
    (gdb) 

     

    #0 0x000000000053489a in mlx5_tx_mb2mr (mb=0x7fa5d8711180, txq=0x7fa5d812cdc0) at /usr/src/debug/openvswitch-2.9.0-3.el7.tis.1.x86_64/dpdk-17.11/drivers/net/mlx5/mlx5_rxtx.h:551
    551 if (likely(txq->mp2mr[i]->start <= addr && txq->mp2mr[i]->end >= addr))
    Missing separate debuginfos, use: debuginfo-install glibc-2.17-222.el7.x86_64 keyutils-libs-1.5.8-3.el7.x86_64 krb5-libs-1.15.1-19.el7.x86_64 libcap-ng-0.7.5-4.el7.x86_64 libcom_err-1.42.9-12.el7_5.x86_64 libgcc-4.8.5-28.el7_5.1.x86_64 libibverbs-43mlnx1-1.43302.tis.1.x86_64 libnl3-3.2.28-4.el7.x86_64 libselinux-2.5-12.el7.x86_64 numactl-libs-2.0.9-7.el7.x86_64 openssl-libs-1.0.2k-12.el7.x86_64 pcre-8.32-17.el7.x86_64 zlib-1.2.7-17.el7.x86_64
    (gdb) bt
    #0 0x000000000053489a in mlx5_tx_mb2mr (mb=0x7fa5d8711180, txq=0x7fa5d812cdc0) at /usr/src/debug/openvswitch-2.9.0-3.el7.tis.1.x86_64/dpdk-17.11/drivers/net/mlx5/mlx5_rxtx.h:551
    #1 mlx5_tx_burst_mpw (dpdk_txq=<optimized out>, pkts=0x7ffffae34aa8, pkts_n=<optimized out>) at /usr/src/debug/openvswitch-2.9.0-3.el7.tis.1.x86_64/dpdk-17.11/drivers/net/mlx5/mlx5_rxtx.c:906
    #2 0x0000000000410dc5 in rte_eth_tx_burst (nb_pkts=<optimized out>, tx_pkts=0x7ffffae34aa0, queue_id=0, port_id=<optimized out>) at /usr/src/debug/openvswitch-2.9.0-3.el7.tis.1.x86_64/dpdk-17.11/x86_64-native-linuxapp-gcc/include/rte_ethdev.h:3172
    #3 netdev_dpdk_eth_tx_burst (cnt=1, pkts=0x7ffffae34aa0, qid=0, dev=0xffffffffffffef40) at lib/netdev-dpdk.c:1690
    #4 dpdk_do_tx_copy (netdev=netdev@entry=0x7fa5fffb4700, qid=qid@entry=0, batch=batch@entry=0x160daf0) at lib/netdev-dpdk.c:2089
    #5 0x00000000006ae4ab in netdev_dpdk_send__ (concurrent_txq=<optimized out>, batch=0x160daf0, qid=0, dev=<optimized out>) at lib/netdev-dpdk.c:2133
    #6 netdev_dpdk_eth_send (netdev=0x7fa5fffb4700, qid=<optimized out>, batch=0x160daf0, concurrent_txq=false) at lib/netdev-dpdk.c:2164
    #7 0x00000000005fb521 in netdev_send (netdev=<optimized out>, qid=<optimized out>, batch=batch@entry=0x160daf0, concurrent_txq=concurrent_txq@entry=false) at lib/netdev.c:791
    #8 0x00000000005cdf15 in dp_netdev_pmd_flush_output_on_port (pmd=pmd@entry=0x7fa629a74010, p=p@entry=0x160dac0) at lib/dpif-netdev.c:3216
    #9 0x00000000005ce247 in dp_netdev_pmd_flush_output_packets (pmd=pmd@entry=0x7fa629a74010, force=force@entry=false) at lib/dpif-netdev.c:3256
    #10 0x00000000005d4a68 in dp_netdev_pmd_flush_output_packets (force=false, pmd=0x7fa629a74010) at lib/dpif-netdev.c:3249
    #11 dp_netdev_process_rxq_port (pmd=pmd@entry=0x7fa629a74010, rxq=0x1682710, port_no=2) at lib/dpif-netdev.c:3292
    #12 0x00000000005d549a in dpif_netdev_run (dpif=<optimized out>) at lib/dpif-netdev.c:3940
    #13 0x0000000000592a5a in type_run (type=<optimized out>) at ofproto/ofproto-dpif.c:344
    #14 0x000000000057d651 in ofproto_type_run (datapath_type=datapath_type@entry=0x167f5b0 "netdev") at ofproto/ofproto.c:1705
    #15 0x000000000056cce5 in bridge_run__ () at vswitchd/bridge.c:2933
    #16 0x0000000000572d08 in bridge_run () at vswitchd/bridge.c:2997
    #17 0x000000000041246d in main (argc=10, argv=0x7ffffae35328) at vswitchd/ovs-vswitchd.c:119
    (gdb)

    dpif_netdev_port_add

     

     

    Breakpoint 2, dpif_netdev_port_add (dpif=0x204f78a0, netdev=0x19fd81a40, port_nop=0xffffe22502a4) at lib/dpif-netdev.c:1913
    1913    {
    (gdb) bt
    #0  dpif_netdev_port_add (dpif=0x204f78a0, netdev=0x19fd81a40, port_nop=0xffffe22502a4) at lib/dpif-netdev.c:1913
    #1  0x000000000097d508 in dpif_port_add (dpif=0x204f78a0, netdev=netdev@entry=0x19fd81a40, port_nop=port_nop@entry=0xffffe225030c) at lib/dpif.c:593
    #2  0x000000000092a714 in port_add (ofproto_=0x202de690, netdev=0x19fd81a40) at ofproto/ofproto-dpif.c:3864
    #3  0x0000000000920b40 in ofproto_port_add (ofproto=0x202de690, netdev=0x19fd81a40, ofp_portp=ofp_portp@entry=0xffffe2250400) at ofproto/ofproto.c:2070
    #4  0x000000000090e530 in iface_do_create (errp=0xffffe2250410, netdevp=0xffffe2250408, ofp_portp=0xffffe2250400, iface_cfg=0x20531860, br=0x202dd9c0) at vswitchd/bridge.c:2060
    #5  iface_create (port_cfg=0x2054ec30, iface_cfg=0x20531860, br=0x202dd9c0) at vswitchd/bridge.c:2103
    #6  bridge_add_ports__ (br=br@entry=0x202dd9c0, wanted_ports=wanted_ports@entry=0x202ddaa0, with_requested_port=with_requested_port@entry=false) at vswitchd/bridge.c:1167
    #7  0x0000000000910278 in bridge_add_ports (wanted_ports=<optimized out>, br=0x202dd9c0) at vswitchd/bridge.c:1183
    #8  bridge_reconfigure (ovs_cfg=ovs_cfg@entry=0x202e3c00) at vswitchd/bridge.c:896
    #9  0x00000000009134e0 in bridge_run () at vswitchd/bridge.c:3328
    #10 0x000000000042469c in main (argc=11, argv=0xffffe2250958) at vswitchd/ovs-vswitchd.c:127
    (gdb)

    dpdk_vhost_class && port

    static const struct netdev_class dpdk_vhost_class = {
        .type = "dpdkvhostuser",
        NETDEV_DPDK_CLASS_COMMON,
        .construct = netdev_dpdk_vhost_construct,
        .destruct = netdev_dpdk_vhost_destruct,
        .send = netdev_dpdk_vhost_send,// enqeue
        .get_carrier = netdev_dpdk_vhost_get_carrier,
        .get_stats = netdev_dpdk_vhost_get_stats,
        .get_custom_stats = netdev_dpdk_get_sw_custom_stats,
        .get_status = netdev_dpdk_vhost_user_get_status,
        .reconfigure = netdev_dpdk_vhost_reconfigure,
        .rxq_recv = netdev_dpdk_vhost_rxq_recv,  //dequeue
        .rxq_enabled = netdev_dpdk_vhost_rxq_enabled,
    };

     

     

    static int
    dpif_netdev_port_add(struct dpif *dpif, struct netdev *netdev,
                         odp_port_t *port_nop)
    {
        struct dp_netdev *dp = get_dp_netdev(dpif);
        char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
        const char *dpif_port;
        odp_port_t port_no;
        int error;
    
        ovs_mutex_lock(&dp->port_mutex);
        dpif_port = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
        if (*port_nop != ODPP_NONE) {
            port_no = *port_nop;
            error = dp_netdev_lookup_port(dp, *port_nop) ? EBUSY : 0;
        } else {
            port_no = choose_port(dp, dpif_port);
            error = port_no == ODPP_NONE ? EFBIG : 0;
        }
        if (!error) {
            *port_nop = port_no;
            error = do_add_port(dp, dpif_port, netdev_get_type(netdev), port_no);
        }
        ovs_mutex_unlock(&dp->port_mutex);
    
        return error;
    }

     

     

    (gdb) b dpif_netdev_run
    Breakpoint 1 at 0x978ef4: file lib/dpif-netdev.c, line 5438.
    (gdb) c
    Continuing.
    
    Breakpoint 1, dpif_netdev_run (dpif=0x204f78a0) at lib/dpif-netdev.c:5438
    5438    {
    (gdb) bt
    #0  dpif_netdev_run (dpif=0x204f78a0) at lib/dpif-netdev.c:5438
    #1  0x000000000097d290 in dpif_run (dpif=<optimized out>) at lib/dpif.c:463
    #2  0x0000000000934c68 in type_run (type=type@entry=0x202db460 "netdev") at ofproto/ofproto-dpif.c:370
    #3  0x000000000091eb18 in ofproto_type_run (datapath_type=<optimized out>, datapath_type@entry=0x202db460 "netdev") at ofproto/ofproto.c:1772
    #4  0x000000000090d94c in bridge_run__ () at vswitchd/bridge.c:3242
    #5  0x0000000000913480 in bridge_run () at vswitchd/bridge.c:3307
    #6  0x000000000042469c in main (argc=11, argv=0xffffe2250958) at vswitchd/ovs-vswitchd.c:127
    (gdb) delete 1
    (gdb) b dpif_netdev_port_add
    Breakpoint 2 at 0x9747c8: file lib/dpif-netdev.c, line 1913.
    (gdb) c
    Continuing.
    [New Thread 0xffff7c29f910 (LWP 17675)]
    [Thread 0xffff7c29f910 (LWP 17675) exited]
    [New Thread 0xffff7c29f910 (LWP 17677)]
    
    Breakpoint 2, dpif_netdev_port_add (dpif=0x204f78a0, netdev=0x19fd81a40, port_nop=0xffffe22502a4) at lib/dpif-netdev.c:1913
    1913    {
    (gdb) bt
    #0  dpif_netdev_port_add (dpif=0x204f78a0, netdev=0x19fd81a40, port_nop=0xffffe22502a4) at lib/dpif-netdev.c:1913
    #1  0x000000000097d508 in dpif_port_add (dpif=0x204f78a0, netdev=netdev@entry=0x19fd81a40, port_nop=port_nop@entry=0xffffe225030c) at lib/dpif.c:593
    #2  0x000000000092a714 in port_add (ofproto_=0x202de690, netdev=0x19fd81a40) at ofproto/ofproto-dpif.c:3864
    #3  0x0000000000920b40 in ofproto_port_add (ofproto=0x202de690, netdev=0x19fd81a40, ofp_portp=ofp_portp@entry=0xffffe2250400) at ofproto/ofproto.c:2070
    #4  0x000000000090e530 in iface_do_create (errp=0xffffe2250410, netdevp=0xffffe2250408, ofp_portp=0xffffe2250400, iface_cfg=0x20531860, br=0x202dd9c0) at vswitchd/bridge.c:2060
    #5  iface_create (port_cfg=0x2054ec30, iface_cfg=0x20531860, br=0x202dd9c0) at vswitchd/bridge.c:2103
    #6  bridge_add_ports__ (br=br@entry=0x202dd9c0, wanted_ports=wanted_ports@entry=0x202ddaa0, with_requested_port=with_requested_port@entry=false) at vswitchd/bridge.c:1167
    #7  0x0000000000910278 in bridge_add_ports (wanted_ports=<optimized out>, br=0x202dd9c0) at vswitchd/bridge.c:1183
    #8  bridge_reconfigure (ovs_cfg=ovs_cfg@entry=0x202e3c00) at vswitchd/bridge.c:896
    #9  0x00000000009134e0 in bridge_run () at vswitchd/bridge.c:3328
    #10 0x000000000042469c in main (argc=11, argv=0xffffe2250958) at vswitchd/ovs-vswitchd.c:127
    (gdb) n
    1914        struct dp_netdev *dp = get_dp_netdev(dpif);
    (gdb) list
    1909
    1910    static int
    1911    dpif_netdev_port_add(struct dpif *dpif, struct netdev *netdev,
    1912                         odp_port_t *port_nop)
    1913    {
    1914        struct dp_netdev *dp = get_dp_netdev(dpif);
    1915        char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
    1916        const char *dpif_port;
    1917        odp_port_t port_no;
    1918        int error;
    (gdb) set print pretty on
    (gdb) p *dp
    value has been optimized out
    (gdb) n
    1913    {
    (gdb) n
    1914        struct dp_netdev *dp = get_dp_netdev(dpif);
    (gdb) n
    1913    {
    (gdb) p *dp
    value has been optimized out
    (gdb) p *dpif
    $1 = {
      dpif_class = 0xbd2650 <dpif_netdev_class>, 
      base_name = 0x204f73e0 "ovs-netdev", 
      full_name = 0x204f78e0 "netdev@ovs-netdev", 
      netflow_engine_type = 47 '/', 
      netflow_engine_id = 209 '321', 
      current_ms = 465573501
    }
    (gdb) n
    1914        struct dp_netdev *dp = get_dp_netdev(dpif);
    (gdb) n
    1920        ovs_mutex_lock(&dp->port_mutex);
    (gdb) p *dp
    value has been optimized out
    (gdb) n
    [Thread 0xffff7c29f910 (LWP 17677) exited]
    1921        dpif_port = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
    (gdb) p *netdev
    $2 = {
      name = 0x20500a30 "vhost-user2", 
      netdev_class = 0xc090e0 <dpdk_vhost_class>, 
      auto_classified = false, 
      ol_flags = 0, 
      mtu_user_config = false, 
      ref_cnt = 1, 
      change_seq = 2, 
      reconfigure_seq = 0x2029d280, 
      last_reconfigure_seq = 16781297, 
      n_txq = 0, 
      n_rxq = 0, 
      node = 0x20533f50, 
      saved_flags_list = {
        prev = 0x19fd81a90, 
        next = 0x19fd81a90
      }, 
      flow_api = {
        p = 0x0
      }, 
      hw_info = {
        oor = false, 
        offload_count = 0, 
        pending_count = 0
      }
    }
    (gdb) n
    1922        if (*port_nop != ODPP_NONE) {
    (gdb) n
    1921        dpif_port = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
    (gdb) n
    1922        if (*port_nop != ODPP_NONE) {
    (gdb) n
    1926            port_no = choose_port(dp, dpif_port);
    (gdb) n
    1930            *port_nop = port_no;
    (gdb) n
    1931            error = do_add_port(dp, dpif_port, netdev_get_type(netdev), port_no);
    (gdb) p *netdev
    $3 = {
      name = 0x20500a30 "vhost-user2", 
      netdev_class = 0xc090e0 <dpdk_vhost_class>, 
      auto_classified = false, 
      ol_flags = 0, 
      mtu_user_config = false, 
      ref_cnt = 1, 
      change_seq = 2, 
      reconfigure_seq = 0x2029d280, 
      last_reconfigure_seq = 16781297, 
      n_txq = 0, 
      n_rxq = 0, 
      node = 0x20533f50, 
      saved_flags_list = {
        prev = 0x19fd81a90, 
        next = 0x19fd81a90
      }, 
      flow_api = {
        p = 0x0
      }, 
      hw_info = {
        oor = false, 
        offload_count = 0, 
        pending_count = 0
      }
    }
    (gdb) n
    [New Thread 0xffff7c29f910 (LWP 17711)]
    1933        ovs_mutex_unlock(&dp->port_mutex);
    (gdb) n
    1936    }
    (gdb) n
    dpif_port_add (dpif=0x204f78a0, netdev=netdev@entry=0x19fd81a40, port_nop=port_nop@entry=0xffffe225030c) at lib/dpif.c:594
    594         if (!error) {
    (gdb) n
    595             VLOG_DBG_RL(&dpmsg_rl, "%s: added %s as port %"PRIu32,
    (gdb) n
    598             if (!dpif_is_tap_port(netdev_get_type(netdev))) {
    (gdb) n
    602                 dpif_port.type = CONST_CAST(char *, netdev_get_type(netdev));
    (gdb) n
    604                 dpif_port.port_no = port_no;
    (gdb) n
    605                 netdev_ports_insert(netdev, dpif->dpif_class, &dpif_port);
    (gdb) p *netdev
    $4 = {
      name = 0x20500a30 "vhost-user2", 
      netdev_class = 0xc090e0 <dpdk_vhost_class>, 
      auto_classified = false, 
      ol_flags = 0, 
      mtu_user_config = false, 
      ref_cnt = 3, 
      change_seq = 3, 
      reconfigure_seq = 0x2029d280, 
      last_reconfigure_seq = 16781303, 
      n_txq = 1, 
      n_rxq = 1, 
      node = 0x20533f50, 
      saved_flags_list = {
        prev = 0x19fd81a90, 
        next = 0x19fd81a90
      }, 
      flow_api = {
        p = 0x0
      }, 
      hw_info = {
        oor = false, 
        offload_count = 0, 
        pending_count = 0
      }
    }
    (gdb) p dpif_port
    $5 = {
      name = 0x20500a30 "vhost-user2", 
      type = 0xffff <Address 0xffff out of bounds>, 
      port_no = 539616016
    }
    (gdb) p *(dpif->dpif_class)
    $6 = {
      type = 0xbd4548 "netdev", 
      cleanup_required = true, 
      init = 0x96cd7c <dpif_netdev_init>, 
      enumerate = 0x96f3c4 <dpif_netdev_enumerate>, 
      port_open_type = 0x96c2b4 <dpif_netdev_port_open_type>, 
      open = 0x974c00 <dpif_netdev_open>, 
      close = 0x9744b0 <dpif_netdev_close>, 
      destroy = 0x96e734 <dpif_netdev_destroy>, 
      run = 0x978ef4 <dpif_netdev_run>, 
      wait = 0x971798 <dpif_netdev_wait>, 
      get_stats = 0x96e63c <dpif_netdev_get_stats>, 
      set_features = 0x0, 
      port_add = 0x9747c8 <dpif_netdev_port_add>, 
      port_del = 0x9744f4 <dpif_netdev_port_del>, 
      port_set_config = 0x971340 <dpif_netdev_port_set_config>, 
      port_query_by_number = 0x9716b4 <dpif_netdev_port_query_by_number>, 
      port_query_by_name = 0x970af4 <dpif_netdev_port_query_by_name>, 
      port_get_pid = 0x0, 
      port_dump_start = 0x96c1d0 <dpif_netdev_port_dump_start>, 
      port_dump_next = 0x96e580 <dpif_netdev_port_dump_next>, 
      port_dump_done = 0x96c4e8 <dpif_netdev_port_dump_done>, 
      port_poll = 0x96e7f0 <dpif_netdev_port_poll>, 
      port_poll_wait = 0x96e7ac <dpif_netdev_port_poll_wait>, 
      flow_flush = 0x96f7f0 <dpif_netdev_flow_flush>, 
      flow_dump_create = 0x96c204 <dpif_netdev_flow_dump_create>, 
      flow_dump_destroy = 0x96c9d0 <dpif_netdev_flow_dump_destroy>, 
      flow_dump_thread_create = 0x96c808 <dpif_netdev_flow_dump_thread_create>, 
      flow_dump_thread_destroy = 0x96c4e4 <dpif_netdev_flow_dump_thread_destroy>, 
      flow_dump_next = 0x96ebe4 <dpif_netdev_flow_dump_next>, 
      operate = 0x97711c <dpif_netdev_operate>, 
      recv_set = 0x0, 
      handlers_set = 0x0, 
      set_config = 0x96e1a0 <dpif_netdev_set_config>, 
      queue_to_priority = 0x96c130 <dpif_netdev_queue_to_priority>, 
      recv = 0x0, 
      recv_wait = 0x0, 
      recv_purge = 0x0, 
      register_dp_purge_cb = 0x96e164 <dpif_netdev_register_dp_purge_cb>, 
      register_upcall_cb = 0x96e128 <dpif_netdev_register_upcall_cb>, 
      enable_upcall = 0x96e0f0 <dpif_netdev_enable_upcall>, 
      disable_upcall = 0x96e0b8 <dpif_netdev_disable_upcall>, 
      get_datapath_version = 0x96c1f8 <dpif_netdev_get_datapath_version>, 
      ct_dump_start = 0x96e034 <dpif_netdev_ct_dump_start>, 
      ct_dump_next = 0x96cbd8 <dpif_netdev_ct_dump_next>, 
      ct_dump_done = 0x96cba0 <dpif_netdev_ct_dump_done>, 
      ct_flush = 0x96dfdc <dpif_netdev_ct_flush>, 
      ct_set_maxconns = 0x96dfa4 <dpif_netdev_ct_set_maxconns>, 
      ct_get_maxconns = 0x96df6c <dpif_netdev_ct_get_maxconns>, 
      ct_get_nconns = 0x96df34 <dpif_netdev_ct_get_nconns>, 
      ct_set_tcp_seq_chk = 0x96def8 <dpif_netdev_ct_set_tcp_seq_chk>, 
      ct_get_tcp_seq_chk = 0x96deac <dpif_netdev_ct_get_tcp_seq_chk>, 
      ct_set_limits = 0x96ddfc <dpif_netdev_ct_set_limits>, 
      ct_get_limits = 0x96dcf0 <dpif_netdev_ct_get_limits>, 
      ct_del_limits = 0x96dc60 <dpif_netdev_ct_del_limits>, 
      ct_set_timeout_policy = 0x0, 
      ct_get_timeout_policy = 0x0, 
      ct_del_timeout_policy = 0x0, 
      ct_timeout_policy_dump_start = 0x0, 
    ---Type <return> to continue, or q <return> to quit---
      ct_timeout_policy_dump_next = 0x0, 
      ct_timeout_policy_dump_done = 0x0, 
      ct_get_timeout_policy_name = 0x0, 
      ipf_set_enabled = 0x96dc0c <dpif_netdev_ipf_set_enabled>, 
      ipf_set_min_frag = 0x96dbb8 <dpif_netdev_ipf_set_min_frag>, 
      ipf_set_max_nfrags = 0x96db74 <dpif_netdev_ipf_set_max_nfrags>, 
      ipf_get_status = 0x96db28 <dpif_netdev_ipf_get_status>, 
      ipf_dump_start = 0x96cb98 <dpif_netdev_ipf_dump_start>, 
      ipf_dump_next = 0x96dadc <dpif_netdev_ipf_dump_next>, 
      ipf_dump_done = 0x96cb90 <dpif_netdev_ipf_dump_done>, 
      meter_get_features = 0x96c1a8 <dpif_netdev_meter_get_features>, 
      meter_set = 0x96d900 <dpif_netdev_meter_set>, 
      meter_get = 0x96d718 <dpif_netdev_meter_get>, 
      meter_del = 0x96d854 <dpif_netdev_meter_del>
    }
    (gdb) 

     

    (gdb) n
    602                 dpif_port.type = CONST_CAST(char *, netdev_get_type(netdev));
    (gdb) n
    605                 netdev_ports_insert(netdev, dpif->dpif_class, &dpif_port);
    (gdb) p dpif_port.type
    $7 = 0xc0b588 "dpdkvhostuser"
    (gdb) 

     

     

    (gdb) n
    602                 dpif_port.type = CONST_CAST(char *, netdev_get_type(netdev));
    (gdb) n
    605                 netdev_ports_insert(netdev, dpif->dpif_class, &dpif_port);
    (gdb) p dpif_port.type
    $7 = 0xc0b588 "dpdkvhostuser"
    (gdb) n
    603                 dpif_port.name = CONST_CAST(char *, netdev_name);
    (gdb) n
    604                 dpif_port.port_no = port_no;
    (gdb) p dpif_port.name
    $8 = 0x20500a30 "vhost-user2"
    (gdb) n
    605                 netdev_ports_insert(netdev, dpif->dpif_class, &dpif_port);
    (gdb) p  dpif_port.port_no
    $9 = 3
    (gdb) n
    [Thread 0xffff7c29f910 (LWP 17711) exited]
    612         if (port_nop) {
    (gdb) n
    613             *port_nop = port_no;
    (gdb) n
    616     }
    (gdb) n

     

     

     

     (gdb) n
    602                 dpif_port.type = CONST_CAST(char *, netdev_get_type(netdev));
    (gdb) n
    605                 netdev_ports_insert(netdev, dpif->dpif_class, &dpif_port);
    (gdb) p dpif_port.type
    $7 = 0xc0b588 "dpdkvhostuser"
    (gdb) n
    603                 dpif_port.name = CONST_CAST(char *, netdev_name);
    (gdb) n
    604                 dpif_port.port_no = port_no;
    (gdb) p dpif_port.name
    $8 = 0x20500a30 "vhost-user2"
    (gdb) n
    605                 netdev_ports_insert(netdev, dpif->dpif_class, &dpif_port);
    (gdb) p  dpif_port.port_no
    $9 = 3
    (gdb) n
    [Thread 0xffff7c29f910 (LWP 17711) exited]
    612         if (port_nop) {
    (gdb) n
    613             *port_nop = port_no;
    (gdb) n
    616     }
    (gdb) n
    port_add (ofproto_=0x202de690, netdev=0x19fd81a40) at ofproto/ofproto-dpif.c:3865
    3865            if (error) {
    (gdb) n
    3868            if (netdev_get_tunnel_config(netdev)) {
    (gdb) n
    [New Thread 0xffff7c29f910 (LWP 17739)]
    3874        if (netdev_get_tunnel_config(netdev)) {
    (gdb) n
    3877            sset_add(&ofproto->ports, devname);
    (gdb) n
    3879        return 0;
    (gdb) n
    3880    }
    (gdb) n
    ofproto_port_add (ofproto=0x202de690, netdev=0x19fd81a40, ofp_portp=ofp_portp@entry=0xffffe2250400) at ofproto/ofproto.c:2071
    2071        if (!error) {
    (gdb) n
    2072            const char *netdev_name = netdev_get_name(netdev);
    (gdb) n
    [Thread 0xffff7c29f910 (LWP 17739) exited]
    [New Thread 0xffff7c24f910 (LWP 17740)]
    2074            simap_put(&ofproto->ofp_requests, netdev_name,
    (gdb) p netdev_name
    $10 = 0x20500a30 "vhost-user2"
    (gdb) n
    2076            error = update_port(ofproto, netdev_name);
    (gdb) n
    2078        if (ofp_portp) {
    (gdb) n
    2079            *ofp_portp = OFPP_NONE;
    (gdb) n
    2080            if (!error) {
    (gdb) n
    2083                error = ofproto_port_query_by_name(ofproto,
    (gdb) n
    [Thread 0xffff7c24f910 (LWP 17740) exited]
    [New Thread 0xffff7c29f910 (LWP 17741)]
    2086                if (!error) {
    (gdb) n
    2087                    *ofp_portp = ofproto_port.ofp_port;
    (gdb) n
    2088                    ofproto_port_destroy(&ofproto_port);
    (gdb) n
    2087                    *ofp_portp = ofproto_port.ofp_port;
    (gdb) n
    2088                    ofproto_port_destroy(&ofproto_port);
    (gdb) n
    [Thread 0xffff7c29f910 (LWP 17741) exited]
    [New Thread 0xffff7c24f910 (LWP 17742)]
    2093    }
    (gdb) n
    iface_do_create (errp=0xffffe2250410, netdevp=0xffffe2250408, ofp_portp=0xffffe2250400, iface_cfg=0x20531860, br=0x202dd9c0) at vswitchd/bridge.c:2061
    2061        if (error) {
    (gdb) n
    2072        VLOG_INFO("bridge %s: added interface %s on port %d",
    (gdb) n
    [Thread 0xffff7c24f910 (LWP 17742) exited]
    [New Thread 0xffff7c29f910 (LWP 17743)]
    2075        *netdevp = netdev;
    (gdb) n
    iface_create (port_cfg=0x2054ec30, iface_cfg=0x20531860, br=0x202dd9c0) at vswitchd/bridge.c:2111
    2111        port = port_lookup(br, port_cfg->name);
    (gdb) n
    2103        error = iface_do_create(br, iface_cfg, &ofp_port, &netdev, &errp);
    (gdb) n
    2111        port = port_lookup(br, port_cfg->name);
    (gdb) n
    2112        if (!port) {
    (gdb) n
    2113            port = port_create(br, port_cfg);
    (gdb) delete 1
    No breakpoint number 1.
    (gdb) quit
    A debugging session is active.
    
            Inferior 1 [process 17155] will be detached.
    
    Quit anyway? (y or n) y
    Detaching from program: /usr/sbin/ovs-vswitchd, process 17155
    [Inferior 1 (process 17155) detached]
    [root@localhost ovs]# 

     

     

     

     

     

     

    iface_do_create(const struct bridge *br,
                    const struct ovsrec_interface *iface_cfg,
                    ofp_port_t *ofp_portp, struct netdev **netdevp,
                    char **errp)
    {
        struct netdev *netdev = NULL;
        int error;
        const char *type;
    
        if (netdev_is_reserved_name(iface_cfg->name)) {
            VLOG_WARN("could not create interface %s, name is reserved",
                      iface_cfg->name);
            error = EINVAL;
            goto error;
        }
    
        type = ofproto_port_open_type(br->ofproto,
                                      iface_get_type(iface_cfg, br->cfg));
        error = netdev_open(iface_cfg->name, type, &netdev);
        if (error) {
            VLOG_WARN_BUF(errp, "could not open network device %s (%s)",
                          iface_cfg->name, ovs_strerror(error));
            goto error;
        }
    
        error = iface_set_netdev_config(iface_cfg, netdev, errp);
        if (error) {
            goto error;
        }

     

    netdev_dpdk_vhost_construct

    Breakpoint 1, netdev_dpdk_vhost_construct (netdev=0x19fd81a40) at lib/netdev-dpdk.c:1369
    1369    {
    (gdb) bt
    #0  netdev_dpdk_vhost_construct (netdev=0x19fd81a40) at lib/netdev-dpdk.c:1369
    #1  0x00000000009a3d60 in netdev_open (name=<optimized out>, type=0x20532350 "dpdkvhostuser", netdevp=netdevp@entry=0xffffe2250418) at lib/netdev.c:436
    #2  0x000000000090e488 in iface_do_create (errp=0xffffe2250410, netdevp=0xffffe2250408, ofp_portp=0xffffe2250400, iface_cfg=0x2052bcf0, br=0x202dd9c0) at vswitchd/bridge.c:2045
    #3  iface_create (port_cfg=0x20550ac0, iface_cfg=0x2052bcf0, br=0x202dd9c0) at vswitchd/bridge.c:2103
    #4  bridge_add_ports__ (br=br@entry=0x202dd9c0, wanted_ports=wanted_ports@entry=0x202ddaa0, with_requested_port=with_requested_port@entry=false) at vswitchd/bridge.c:1167
    #5  0x0000000000910278 in bridge_add_ports (wanted_ports=<optimized out>, br=0x202dd9c0) at vswitchd/bridge.c:1183
    #6  bridge_reconfigure (ovs_cfg=ovs_cfg@entry=0x202e3c00) at vswitchd/bridge.c:896
    #7  0x00000000009134e0 in bridge_run () at vswitchd/bridge.c:3328
    #8  0x000000000042469c in main (argc=11, argv=0xffffe2250958) at vswitchd/ovs-vswitchd.c:127
    (gdb) 
    int
    netdev_open(const char *name, const char *type, struct netdev **netdevp)
        OVS_EXCLUDED(netdev_mutex)
    {
        struct netdev *netdev;
        int error = 0;
    
        if (!name[0]) {
            /* Reject empty names.  This saves the providers having to do this.  At
             * least one screwed this up: the netdev-linux "tap" implementation
             * passed the name directly to the Linux TUNSETIFF call, which treats
             * an empty string as a request to generate a unique name. */
            return EINVAL;
        }
    
        netdev_initialize();
    
        ovs_mutex_lock(&netdev_mutex);
        netdev = shash_find_data(&netdev_shash, name);
    
        if (netdev &&
            type && type[0] && strcmp(type, netdev->netdev_class->type)) {
    
            if (netdev->auto_classified) {
                /* If this device was first created without a classification type,
                 * for example due to routing or tunneling code, and they keep a
                 * reference, a "classified" call to open will fail. In this case
                 * we remove the classless device, and re-add it below. We remove
                 * the netdev from the shash, and change the sequence, so owners of
                 * the old classless device can release/cleanup. */
                if (netdev->node) {
                    shash_delete(&netdev_shash, netdev->node);
                    netdev->node = NULL;
                    netdev_change_seq_changed(netdev);
                }
    
                netdev = NULL;
            } else {
                error = EEXIST;
            }
        }
    
        if (!netdev) {
            struct netdev_registered_class *rc;
    
            rc = netdev_lookup_class(type && type[0] ? type : "system");
            if (rc && ovs_refcount_try_ref_rcu(&rc->refcnt)) {
                netdev = rc->class->alloc();
                if (netdev) {
                    memset(netdev, 0, sizeof *netdev);
                    netdev->netdev_class = rc->class;
                    netdev->auto_classified = type && type[0] ? false : true;
                    netdev->name = xstrdup(name);
                    netdev->change_seq = 1;
                    netdev->reconfigure_seq = seq_create();
                    netdev->last_reconfigure_seq =
                        seq_read(netdev->reconfigure_seq);
                    ovsrcu_set(&netdev->flow_api, NULL);
                    netdev->hw_info.oor = false;
                    netdev->node = shash_add(&netdev_shash, name, netdev);
    
                    /* By default enable one tx and rx queue per netdev. */
                    netdev->n_txq = netdev->netdev_class->send ? 1 : 0;
                    netdev->n_rxq = netdev->netdev_class->rxq_alloc ? 1 : 0;
    
                    ovs_list_init(&netdev->saved_flags_list);
    
                    error = rc->class->construct(netdev);

    //调用construct
    if (!error) { netdev_change_seq_changed(netdev); } else { ovs_refcount_unref(&rc->refcnt); seq_destroy(netdev->reconfigure_seq); free(netdev->name); ovs_assert(ovs_list_is_empty(&netdev->saved_flags_list)); shash_delete(&netdev_shash, netdev->node); rc->class->dealloc(netdev); } } else { error = ENOMEM; } } else { VLOG_WARN("could not create netdev %s of unknown type %s", name, type); error = EAFNOSUPPORT; } } if (!error) { netdev->ref_cnt++; *netdevp = netdev; } else { *netdevp = NULL; } ovs_mutex_unlock(&netdev_mutex); return error; }

     

     

    netdev_class netdev_dpdk_class

    static struct netdev_class netdev_dpdk_class = {
        "dpdk",
        dpdk_class_init,            /* init */
        NULL,                       /* netdev_dpdk_run */
        NULL,                       /* netdev_dpdk_wait */
    
        netdev_dpdk_alloc,
        netdev_dpdk_construct,
        netdev_dpdk_destruct,
        netdev_dpdk_dealloc,
        netdev_dpdk_get_config,
        NULL,                       /* netdev_dpdk_set_config */
        NULL,                       /* get_tunnel_config */
    
        netdev_dpdk_send,           /* send */
        NULL,                       /* send_wait */
    
        netdev_dpdk_set_etheraddr,
        netdev_dpdk_get_etheraddr,
        netdev_dpdk_get_mtu,
        netdev_dpdk_set_mtu,
        netdev_dpdk_get_ifindex,
        netdev_dpdk_get_carrier,
        netdev_dpdk_get_carrier_resets,
        netdev_dpdk_set_miimon,
        netdev_dpdk_get_stats,
        netdev_dpdk_set_stats,
        netdev_dpdk_get_features,
        NULL,                       /* set_advertisements */
    
        NULL,                       /* set_policing */
        NULL,                       /* get_qos_types */
        NULL,                       /* get_qos_capabilities */
        NULL,                       /* get_qos */
        NULL,                       /* set_qos */
        NULL,                       /* get_queue */
        NULL,                       /* set_queue */
        NULL,                       /* delete_queue */
        NULL,                       /* get_queue_stats */
        NULL,                       /* queue_dump_start */
        NULL,                       /* queue_dump_next */
        NULL,                       /* queue_dump_done */
        NULL,                       /* dump_queue_stats */
    
        NULL,                       /* get_in4 */
        NULL,                       /* set_in4 */
        NULL,                       /* get_in6 */
        NULL,                       /* add_router */
        NULL,                       /* get_next_hop */
        netdev_dpdk_get_status,
        NULL,                       /* arp_lookup */
    
        netdev_dpdk_update_flags,
    
        netdev_dpdk_rxq_alloc,
        netdev_dpdk_rxq_construct,
        netdev_dpdk_rxq_destruct,
        netdev_dpdk_rxq_dealloc,
        netdev_dpdk_rxq_recv,
        NULL,                       /* rxq_wait */
        NULL,                       /* rxq_drain */
    };

     ovs-vsctl add-port br0 dpdk1 -- set Interface dpdk1 type=dpdk options:dpdk-devargs=0000:05:00.0

    (gdb) b netdev_dpdk_construct
    Breakpoint 1 at 0xa5aca0: file lib/netdev-dpdk.c, line 1467.
    (gdb) b netdev_dpdk_send
    Function "netdev_dpdk_send" not defined.
    Make breakpoint pending on future shared library load? (y or [n]) n
    (gdb) b netdev_dpdk_send
    Function "netdev_dpdk_send" not defined.
    Make breakpoint pending on future shared library load? (y or [n]) y
    Breakpoint 2 (netdev_dpdk_send) pending.
    (gdb) b  netdev_dpdk_rxq_recv
    Breakpoint 3 at 0xa62fd8: file lib/netdev-dpdk.c, line 2489.
    (gdb) c
    Continuing.
    
    Breakpoint 1, netdev_dpdk_construct (netdev=0x19fd81ec0) at lib/netdev-dpdk.c:1467
    1467    {
    (gdb) bt
    #0  netdev_dpdk_construct (netdev=0x19fd81ec0) at lib/netdev-dpdk.c:1467
    #1  0x00000000009a3d60 in netdev_open (name=<optimized out>, type=0x6ed09a0 "dpdk", netdevp=netdevp@entry=0xfffff6389b38) at lib/netdev.c:436
    #2  0x000000000090e488 in iface_do_create (errp=0xfffff6389b30, netdevp=0xfffff6389b28, ofp_portp=0xfffff6389b20, iface_cfg=0x5476680, br=0x51d29b0) at vswitchd/bridge.c:2045
    #3  iface_create (port_cfg=0x6ed09c0, iface_cfg=0x5476680, br=0x51d29b0) at vswitchd/bridge.c:2103
    #4  bridge_add_ports__ (br=br@entry=0x51d29b0, wanted_ports=wanted_ports@entry=0x51d2a90, with_requested_port=with_requested_port@entry=false) at vswitchd/bridge.c:1167
    #5  0x0000000000910278 in bridge_add_ports (wanted_ports=<optimized out>, br=0x51d29b0) at vswitchd/bridge.c:1183
    #6  bridge_reconfigure (ovs_cfg=ovs_cfg@entry=0x51d0620) at vswitchd/bridge.c:896
    #7  0x00000000009134e0 in bridge_run () at vswitchd/bridge.c:3328
    #8  0x000000000042469c in main (argc=11, argv=0xfffff638a078) at vswitchd/ovs-vswitchd.c:127
    (gdb) c
    Continuing.
    [New Thread 0xffffb43df910 (LWP 25825)]
    [Switching to Thread 0xfffd53ffd510 (LWP 19066)]
    
    Breakpoint 3, netdev_dpdk_rxq_recv (rxq=0x19fd81400, batch=0xfffd53ffca80, qfill=0x0) at lib/netdev-dpdk.c:2489
    2489    {
    (gdb) bt
    #0  netdev_dpdk_rxq_recv (rxq=0x19fd81400, batch=0xfffd53ffca80, qfill=0x0) at lib/netdev-dpdk.c:2489
    #1  0x00000000009a440c in netdev_rxq_recv (rx=<optimized out>, batch=batch@entry=0xfffd53ffca80, qfill=<optimized out>) at lib/netdev.c:726
    #2  0x00000000009785bc in dp_netdev_process_rxq_port (pmd=pmd@entry=0x5d3f680, rxq=0x51d14a0, port_no=3) at lib/dpif-netdev.c:4461
    #3  0x0000000000978a24 in pmd_thread_main (f_=0x5d3f680) at lib/dpif-netdev.c:5731
    #4  0x00000000009fc5dc in ovsthread_wrapper (aux_=<optimized out>) at lib/ovs-thread.c:383
    #5  0x0000ffffb7fd7d38 in start_thread (arg=0xfffd53ffd510) at pthread_create.c:309
    #6  0x0000ffffb7cbf690 in thread_start () from /lib64/libc.so.6
    (gdb) c
    Continuing.

     

    netdev_dpdk|INFO|vHost Device '/var/run/openvswitch/vhost-user1' has been removed

    destroy_device(int vid)
    {
        struct netdev_dpdk *dev;
        bool exists = false;
        char ifname[IF_NAME_SZ];
    
        rte_vhost_get_ifname(vid, ifname, sizeof ifname);
    
        ovs_mutex_lock(&dpdk_mutex);
        LIST_FOR_EACH (dev, list_node, &dpdk_list) {
            if (netdev_dpdk_get_vid(dev) == vid) {
    
                ovs_mutex_lock(&dev->mutex);
                dev->vhost_reconfigured = false;
                ovsrcu_index_set(&dev->vid, -1);
                memset(dev->vhost_rxq_enabled, 0,
                       dev->up.n_rxq * sizeof *dev->vhost_rxq_enabled);
                netdev_dpdk_txq_map_clear(dev);
    
                netdev_change_seq_changed(&dev->up);
                ovs_mutex_unlock(&dev->mutex);
                exists = true;
                break;
            }
        }
    
        ovs_mutex_unlock(&dpdk_mutex);
    
        if (exists) {
            /*
             * Wait for other threads to quiesce after setting the 'virtio_dev'
             * to NULL, before returning.
             */
            ovsrcu_synchronize();
            /*
             * As call to ovsrcu_synchronize() will end the quiescent state,
             * put thread back into quiescent state before returning.
             */
            ovsrcu_quiesce_start();
            VLOG_INFO("vHost Device '%s' has been removed", ifname);
        } else {
            VLOG_INFO("vHost Device '%s' not found", ifname);
        }
    }

     

  • 相关阅读:
    08 组件组合使用
    07 React 组件三大属性-----refs
    06 组件三大属性 ----- props
    05 组件三大属性----state
    04 定义组件的两种方式
    03 动态展示列表数据
    02 创建虚拟DOM的两种方式
    C++动多态和静多态
    django1.7+nginx1.4.4的static配置
    redis client API-----------python
  • 原文地址:https://www.cnblogs.com/dream397/p/14173700.html
Copyright © 2020-2023  润新知