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

Generated by: LCOV version 1.14