LCOV - code coverage report
Current view: top level - root/contrail/vrouter/dpdk - vr_uvhost_util.c (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 66 77 85.7 %
Date: 2026-08-03 02:19:58 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * vr_uvhost_util.c - utils for 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_uvhost_util.h"
      10             : 
      11             : typedef struct uvh_fd_s {
      12             :     int uvh_fd;
      13             :     void *uvh_fd_arg;
      14             :     uvh_fd_handler_t uvh_fd_fn;
      15             : } uvh_fd_t;
      16             : 
      17             : /* Global variables */
      18             : static uvh_fd_t uvh_rfds[MAX_UVHOST_FDS];
      19             : static uvh_fd_t uvh_wfds[MAX_UVHOST_FDS];
      20             : 
      21             : /*
      22             :  * vr_uvhost_log - logs user space vhost messages to a file.
      23             :  */
      24             : void
      25        8452 : vr_uvhost_log(const char *format, ...)
      26             : {
      27             :     va_list args;
      28             : 
      29        8452 :     if (RTE_LOGTYPE_UVHOST & rte_logs.type) {
      30        8452 :         char buf[VR_DPDK_STR_BUF_SZ] = "UVHOST: ";
      31             : 
      32        8452 :         strncat(buf, format, sizeof(buf) - strlen(buf) - 1);
      33        8452 :         buf[sizeof(buf) - 1] = '\0';
      34             : 
      35        8452 :         va_start(args, format);
      36        8452 :         rte_vlog(RTE_LOG_INFO, RTE_LOGTYPE_UVHOST, buf, args);
      37        8452 :         va_end(args);
      38             :     }
      39        8452 : }
      40             : 
      41             : /*
      42             :  * vr_uvhost_del_fd - deletes a FD from the read/write list that the
      43             :  * user space vhost server is listening on. fd_type indicates if it
      44             :  * is a read/write socket. The FD passed in will be closed.
      45             :  *
      46             :  * Returns 0 on success, -1 otherwise.
      47             :  */
      48             : int
      49         596 : vr_uvhost_del_fd(int fd, uvh_fd_type_t fd_type)
      50             : {
      51             :     int i;
      52             :     uvh_fd_t *fds;
      53             : 
      54             :     RTE_LOG_DP(DEBUG, UVHOST, "Deleting FD %d...\n", fd);
      55         596 :     if (fd_type == UVH_FD_READ) {
      56         596 :         fds = uvh_rfds;
      57           0 :     } else if (fd_type == UVH_FD_WRITE) {
      58           0 :         fds = uvh_wfds;
      59             :     } else {
      60           0 :         return -1;
      61             :     }
      62             : 
      63        3608 :     for (i = 0; i < MAX_UVHOST_FDS; i++) {
      64        3608 :         if (fds[i].uvh_fd == fd) {
      65         596 :             break;
      66             :         }
      67             :     }
      68             : 
      69         596 :     if (i == MAX_UVHOST_FDS) {
      70             :         /* The descriptor could be deleted on read error, so no need to
      71             :          * print the error message.
      72             :          */
      73           0 :         return -1;
      74             :     }
      75             : 
      76         596 :     fds[i].uvh_fd = -1;
      77         596 :     fds[i].uvh_fd_arg = NULL;
      78             : 
      79         596 :     close(fd);
      80             : 
      81         596 :     return 0;
      82             : }
      83             : 
      84             : /*
      85             :  * vr_uvhost_del_fds_by_arg - deletes all FDs from the read/write lists matching
      86             :  * the given argument (pointer to a client). All the FDs found will be closed.
      87             :  *
      88             :  * Returns 0 on success, -1 otherwise.
      89             :  */
      90             : int
      91         166 : vr_uvhost_del_fds_by_arg(void *arg)
      92             : {
      93             :     int i;
      94             : 
      95      723096 :     for (i = 0; i < MAX_UVHOST_FDS; i++) {
      96      722930 :         if (uvh_rfds[i].uvh_fd > 0 && uvh_rfds[i].uvh_fd_arg == arg)
      97         181 :             vr_uvhost_del_fd(uvh_rfds[i].uvh_fd, UVH_FD_READ);
      98      722930 :         if (uvh_wfds[i].uvh_fd > 0 && uvh_wfds[i].uvh_fd_arg == arg)
      99           0 :             vr_uvhost_del_fd(uvh_wfds[i].uvh_fd, UVH_FD_WRITE);
     100             :     }
     101             : 
     102         166 :     return 0;
     103             : }
     104             : 
     105             : /*
     106             :  * vr_uvhost_add_fd - adds the specified FD into the read/write list that
     107             :  * the user space vhost server is waiting on. The type indicates if it
     108             :  * is a read/write socket and the handler is the function that is called when
     109             :  * there is an event on the socket.
     110             :  *
     111             :  * Returns 0 on success, -1 otherwise.
     112             :  */
     113             : int
     114        1294 : vr_uvhost_add_fd(int fd, uvh_fd_type_t fd_type, void *fd_handler_arg,
     115             :                  uvh_fd_handler_t fd_handler)
     116             : {
     117             :     int i;
     118             :     uvh_fd_t *fds;
     119             : 
     120             :     RTE_LOG_DP(DEBUG, UVHOST, "Adding FD %d...\n", fd);
     121        1294 :     if (fd_type == UVH_FD_READ) {
     122        1294 :         fds = uvh_rfds;
     123           0 :     } else if (fd_type == UVH_FD_WRITE) {
     124           0 :         fds = uvh_wfds;
     125             :     } else {
     126           0 :         return -1;
     127             :     }
     128             : 
     129        7094 :     for (i = 0; i < MAX_UVHOST_FDS; i++) {
     130        7094 :         if (fds[i].uvh_fd == fd || fds[i].uvh_fd == -1) {
     131        1294 :             fds[i].uvh_fd = fd;
     132        1294 :             fds[i].uvh_fd_arg = fd_handler_arg;
     133        1294 :             fds[i].uvh_fd_fn = fd_handler;
     134             : 
     135        1294 :             return 0;
     136             :         }
     137             :     }
     138             : 
     139           0 :     vr_uvhost_log("Error adding FD %d: no room for a new FD\n", fd);
     140             : 
     141           0 :     return -1;
     142             : }
     143             : 
     144             : /*
     145             :  * vr_uvhost_fds_init - initializes the read and write fds before
     146             :  * we enter the poll loop.
     147             :  */
     148             : void
     149          53 : vr_uvhost_fds_init(void)
     150             : {
     151             :     int i;
     152             : 
     153      230868 :     for (i = 0; i < MAX_UVHOST_FDS; i++) {
     154      230815 :         uvh_rfds[i].uvh_fd = -1;
     155      230815 :         uvh_wfds[i].uvh_fd = -1;
     156             :     }
     157             : 
     158          53 :     return;
     159             : }
     160             : 
     161             : /*
     162             :  * vr_uvh_call_fd_handlers_internal - call the handler associated with the 
     163             :  * given fd. 
     164             :  *
     165             :  * Returns 0 on success, -1 otherwise.
     166             :  */
     167             : static int
     168        4000 : vr_uvh_call_fd_handlers_internal(uvh_fd_t *fd_arr, int fd)
     169             : {
     170        4000 :     int i, ret = 0;
     171             : 
     172       21562 :     for (i = 0; i < MAX_UVHOST_FDS; i++) {
     173       21562 :         if (fd_arr[i].uvh_fd != fd) {
     174       17562 :             continue;
     175             :         }
     176             : 
     177        4000 :         ret = fd_arr[i].uvh_fd_fn(fd_arr[i].uvh_fd, fd_arr[i].uvh_fd_arg);
     178        4000 :         if (ret) {
     179         221 :             return -1;
     180             :         } else {
     181        3779 :             return 0;
     182             :         }
     183             :     }
     184             : 
     185           0 :     return -1;
     186             : }
     187             : 
     188             : /*
     189             :  * vr_uvh_call_fd_handlers - call the handler for each FD that is set upon
     190             :  * return from poll().
     191             :  *
     192             :  * Returns nothing.
     193             :  */
     194             : void
     195        3889 : vr_uvh_call_fd_handlers(struct pollfd *fds, nfds_t nfds)
     196             : {
     197             :     unsigned int i;
     198             :     int ret;
     199             : 
     200       31270 :     for (i = 0; i < nfds; i++) {
     201       27381 :         if (fds[i].fd >= 0) {
     202       27381 :             if (fds[i].revents & POLLIN) {
     203        4000 :                 ret = vr_uvh_call_fd_handlers_internal(uvh_rfds, fds[i].fd);
     204        4000 :                 if (ret) {
     205         221 :                     vr_uvhost_del_fd(fds[i].fd, UVH_FD_READ);
     206             :                 }
     207             :             }
     208             :         }
     209             :     }
     210             : 
     211        3889 :     return;
     212             : }
     213             : 
     214             : /*
     215             :  * vr_uvh_init_pollfds - initializes the array to pass to poll based on the
     216             :  * state of the fds.
     217             :  *
     218             :  * Returns nothing.
     219             :  */
     220             : void
     221        3942 : vr_uvh_init_pollfds(struct pollfd *fds, nfds_t *nfds)
     222             : {
     223        3942 :     unsigned int i, count = 0;
     224             : 
     225    17171352 :     for (i = 0; i < MAX_UVHOST_FDS; i++) {
     226    17167410 :         if (uvh_rfds[i].uvh_fd != -1) {
     227       27621 :             fds[count].fd = uvh_rfds[i].uvh_fd;
     228       27621 :             fds[count].events = POLLIN;
     229       27621 :             count++;
     230             :         }
     231             :     }
     232             : 
     233        3942 :     *nfds = count;
     234             : 
     235        3942 :     return;
     236             : }

Generated by: LCOV version 1.14