LCOV - code coverage report
Current view: top level - root/contrail/vrouter/dpdk - vr_uvhost.c (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 48 72 66.7 %
Date: 2026-08-03 02:19:58 Functions: 3 4 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * vr_uvhost.c - implements a user-space vhost server that peers with
       3             :  * the vhost client inside qemu (version 2.1 and later).
       4             :  *
       5             :  * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
       6             :  */
       7             : 
       8             : #include "vr_dpdk.h"
       9             : #include "vr_dpdk_usocket.h"
      10             : #include "vr_uvhost.h"
      11             : #include "vr_uvhost_client.h"
      12             : #include "vr_uvhost_msg.h"
      13             : #include "vr_uvhost_util.h"
      14             : 
      15             : #include <pthread.h>
      16             : #include <stdint.h>
      17             : #include <unistd.h>
      18             : #include <linux/vhost.h>
      19             : #include <sys/eventfd.h>
      20             : #include <sys/socket.h>
      21             : #include <sys/stat.h>
      22             : #include <sys/types.h>
      23             : #include <sys/un.h>
      24             : 
      25             : #include <rte_errno.h>
      26             : 
      27             : /* Global variables */
      28             : vr_uvh_exit_callback_t vr_uvhost_exit_fn;
      29             : struct pollfd pollfds[MAX_UVHOST_FDS];
      30             : 
      31             : /*
      32             :  * vr_uvhost_init - initializes the user space vhost server and waits
      33             :  * for messages from the netlink thread or qemu clients. The netlink thread
      34             :  * sends messages on a UNIX pipe in order to specify the names of the UNIX
      35             :  * domain socket on which a qemu client will connect. Once this message is
      36             :  * received, the vhost server creates the UNIX domain socket and includes it
      37             :  * in the list of fds it waits on.
      38             :  *
      39             :  * Returns 0 on success, error otherwise.
      40             :  */
      41             : int
      42           0 : vr_uvhost_init(pthread_t *th, vr_uvh_exit_callback_t exit_fn)
      43             : {
      44           0 :     if (pthread_create(th, NULL, vr_uvhost_start, NULL)) {
      45           0 :         return -1;
      46             :     }
      47             : 
      48           0 :     vr_uvhost_exit_fn = exit_fn;
      49           0 :     return 0;
      50             : }
      51             : 
      52             : /*
      53             :  * vr_uvhost_exit - exits the user space vhost server thread. Also forces
      54             :  * other threads in the process to exit by calling the process exit
      55             :  * callback.
      56             :  *
      57             :  * Returns nothing.
      58             :  */
      59             : static void
      60          53 : vr_uvhost_exit(void)
      61             : {
      62          53 :     vr_uvhost_exit_fn();
      63             : 
      64          53 :     return;
      65             : }
      66             : 
      67             : void
      68          53 : vr_uvhost_wakeup(void)
      69             : {
      70          53 :     if (likely(vr_dpdk.uvhost_event_fd > 0)) {
      71          53 :         eventfd_write(vr_dpdk.uvhost_event_fd, 1);
      72             :     }
      73          53 : }
      74             : 
      75             : /*
      76             :  * vr_uvhost_start - starts the user space vhost server
      77             :  *
      78             :  * Returns NULL if an error occurs. Otherwise, it runs forever.
      79             :  */
      80             : void *
      81          53 : vr_uvhost_start(void *arg)
      82             : {
      83          53 :     int s = 0, ret, err;
      84             :     struct sockaddr_un sun;
      85             :     nfds_t nfds;
      86             : 
      87          53 :     vr_uvhost_client_init();
      88             : 
      89          53 :     vr_uvhost_log("Starting uvhost server...\n");
      90          53 :     vr_dpdk.uvhost_event_fd = eventfd(0, 0);
      91          53 :     if (vr_dpdk.uvhost_event_fd == -1) {
      92           0 :         vr_uvhost_log("    error creating event FD: %s (%d)\n",
      93           0 :                         rte_strerror(errno), errno);
      94           0 :         goto error;
      95             :     }
      96          53 :     vr_uvhost_log("    server event FD is %d\n", vr_dpdk.uvhost_event_fd);
      97             : 
      98          53 :     s = socket(AF_UNIX, SOCK_SEQPACKET, 0);
      99          53 :     if (s == -1) {
     100           0 :         vr_uvhost_log("    error creating server socket: %s (%d)\n",
     101           0 :                         rte_strerror(errno), errno);
     102           0 :         goto error;
     103             :     }
     104          53 :     vr_uvhost_log("    server socket FD is %d\n", s);
     105             : 
     106          53 :     memset(&sun, 0, sizeof(sun));
     107          53 :     sun.sun_family = AF_UNIX;
     108          53 :     strncpy(sun.sun_path, vr_socket_dir, sizeof(sun.sun_path) - 1);
     109          53 :     strncat(sun.sun_path, "/"VR_UVH_NL_SOCK_NAME, sizeof(sun.sun_path)
     110          53 :         - strlen(sun.sun_path) - 1);
     111             : 
     112          53 :     mkdir(vr_socket_dir, VR_DEF_SOCKET_DIR_MODE);
     113          53 :     unlink(sun.sun_path);
     114          53 :     ret = bind(s, (struct sockaddr *) &sun, sizeof(sun));
     115          53 :     if (ret == -1) {
     116           0 :         vr_uvhost_log("    error binding server FD %d to %s: %s (%d)\n",
     117           0 :                         s, sun.sun_path, rte_strerror(errno), errno);
     118           0 :         goto error;
     119             :     }
     120             : 
     121          53 :     if (listen(s, 1) == -1) {
     122           0 :         vr_uvhost_log("    error listening server socket FD %d: %s (%d)\n",
     123           0 :                         s, rte_strerror(errno), errno);
     124           0 :         goto error;
     125             :     }
     126             : 
     127          53 :     vr_uvhost_fds_init();
     128             : 
     129          53 :     if (vr_uvhost_add_fd(vr_dpdk.uvhost_event_fd, UVH_FD_READ, NULL, NULL)) {
     130           0 :         vr_uvhost_log("    error adding server event FD %d\n",
     131             :                       vr_dpdk.uvhost_event_fd);
     132           0 :         goto error;
     133             :     }
     134          53 :     if (vr_uvhost_add_fd(s, UVH_FD_READ, NULL, vr_uvh_nl_listen_handler)) {
     135           0 :         vr_uvhost_log("    error adding server socket FD %d\n", s);
     136           0 :         goto error;
     137             :     }
     138             : 
     139             :     while (1) {
     140        3942 :         vr_uvh_init_pollfds(pollfds, &nfds);
     141             : 
     142        3942 :         rcu_thread_offline();
     143        3942 :         if (poll(pollfds, nfds, -1) < 0) {
     144           0 :             vr_uvhost_log("    error polling FDs: %s (%d)\n",
     145           0 :                             rte_strerror(errno), errno);
     146           0 :             goto error;
     147             :         }
     148             : 
     149        3942 :         if (vr_dpdk_is_stop_flag_set())
     150          53 :             break;
     151             : 
     152        3889 :         rcu_thread_online();
     153             : 
     154        3889 :         vr_uvh_call_fd_handlers(pollfds, nfds);
     155             :     }
     156             : 
     157          53 : error:
     158             : 
     159          53 :     err = errno;
     160          53 :     if (s) {
     161          53 :         close(s);
     162          53 :         unlink(sun.sun_path);
     163             :     }
     164          53 :     if (vr_dpdk.uvhost_event_fd > 0) {
     165          53 :         close(vr_dpdk.uvhost_event_fd);
     166          53 :         vr_dpdk.uvhost_event_fd = 0;
     167             :     }
     168             : 
     169          53 :     vr_uvhost_exit();
     170          53 :     errno = err;
     171             : 
     172          53 :     return NULL;
     173             : }
     174             : 

Generated by: LCOV version 1.14