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

Generated by: LCOV version 1.14