LCOV - code coverage report
Current view: top level - drivers/net/virtio/virtio_user - vhost_user.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 394 0.0 %
Date: 2024-04-01 19:00:53 Functions: 0 29 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 190 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2016 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <sys/socket.h>
       6                 :            : #include <sys/types.h>
       7                 :            : #include <sys/stat.h>
       8                 :            : #include <unistd.h>
       9                 :            : #include <fcntl.h>
      10                 :            : #include <sys/un.h>
      11                 :            : #include <stdlib.h>
      12                 :            : #include <string.h>
      13                 :            : #include <errno.h>
      14                 :            : 
      15                 :            : #include <rte_alarm.h>
      16                 :            : #include <rte_string_fns.h>
      17                 :            : #include <rte_fbarray.h>
      18                 :            : 
      19                 :            : #include "vhost.h"
      20                 :            : #include "virtio_user_dev.h"
      21                 :            : 
      22                 :            : struct vhost_user_data {
      23                 :            :         int vhostfd;
      24                 :            :         int listenfd;
      25                 :            :         uint64_t protocol_features;
      26                 :            : };
      27                 :            : 
      28                 :            : #ifndef VHOST_USER_F_PROTOCOL_FEATURES
      29                 :            : #define VHOST_USER_F_PROTOCOL_FEATURES 30
      30                 :            : #endif
      31                 :            : 
      32                 :            : /** Protocol features. */
      33                 :            : #ifndef VHOST_USER_PROTOCOL_F_MQ
      34                 :            : #define VHOST_USER_PROTOCOL_F_MQ 0
      35                 :            : #endif
      36                 :            : 
      37                 :            : #ifndef VHOST_USER_PROTOCOL_F_REPLY_ACK
      38                 :            : #define VHOST_USER_PROTOCOL_F_REPLY_ACK 3
      39                 :            : #endif
      40                 :            : 
      41                 :            : #ifndef VHOST_USER_PROTOCOL_F_STATUS
      42                 :            : #define VHOST_USER_PROTOCOL_F_STATUS 16
      43                 :            : #endif
      44                 :            : 
      45                 :            : #define VHOST_USER_SUPPORTED_PROTOCOL_FEATURES          \
      46                 :            :         (1ULL << VHOST_USER_PROTOCOL_F_MQ |               \
      47                 :            :          1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK |        \
      48                 :            :          1ULL << VHOST_USER_PROTOCOL_F_STATUS)
      49                 :            : 
      50                 :            : /* The version of the protocol we support */
      51                 :            : #define VHOST_USER_VERSION    0x1
      52                 :            : 
      53                 :            : #define VHOST_MEMORY_MAX_NREGIONS 8
      54                 :            : struct vhost_memory {
      55                 :            :         uint32_t nregions;
      56                 :            :         uint32_t padding;
      57                 :            :         struct vhost_memory_region regions[VHOST_MEMORY_MAX_NREGIONS];
      58                 :            : };
      59                 :            : 
      60                 :            : enum vhost_user_request {
      61                 :            :         VHOST_USER_NONE = 0,
      62                 :            :         VHOST_USER_GET_FEATURES = 1,
      63                 :            :         VHOST_USER_SET_FEATURES = 2,
      64                 :            :         VHOST_USER_SET_OWNER = 3,
      65                 :            :         VHOST_USER_RESET_OWNER = 4,
      66                 :            :         VHOST_USER_SET_MEM_TABLE = 5,
      67                 :            :         VHOST_USER_SET_LOG_BASE = 6,
      68                 :            :         VHOST_USER_SET_LOG_FD = 7,
      69                 :            :         VHOST_USER_SET_VRING_NUM = 8,
      70                 :            :         VHOST_USER_SET_VRING_ADDR = 9,
      71                 :            :         VHOST_USER_SET_VRING_BASE = 10,
      72                 :            :         VHOST_USER_GET_VRING_BASE = 11,
      73                 :            :         VHOST_USER_SET_VRING_KICK = 12,
      74                 :            :         VHOST_USER_SET_VRING_CALL = 13,
      75                 :            :         VHOST_USER_SET_VRING_ERR = 14,
      76                 :            :         VHOST_USER_GET_PROTOCOL_FEATURES = 15,
      77                 :            :         VHOST_USER_SET_PROTOCOL_FEATURES = 16,
      78                 :            :         VHOST_USER_GET_QUEUE_NUM = 17,
      79                 :            :         VHOST_USER_SET_VRING_ENABLE = 18,
      80                 :            :         VHOST_USER_SET_STATUS = 39,
      81                 :            :         VHOST_USER_GET_STATUS = 40,
      82                 :            : };
      83                 :            : 
      84                 :            : struct vhost_user_msg {
      85                 :            :         enum vhost_user_request request;
      86                 :            : 
      87                 :            : #define VHOST_USER_VERSION_MASK     0x3
      88                 :            : #define VHOST_USER_REPLY_MASK       (0x1 << 2)
      89                 :            : #define VHOST_USER_NEED_REPLY_MASK  (0x1 << 3)
      90                 :            :         uint32_t flags;
      91                 :            :         uint32_t size; /* the following payload size */
      92                 :            :         union {
      93                 :            : #define VHOST_USER_VRING_IDX_MASK   0xff
      94                 :            : #define VHOST_USER_VRING_NOFD_MASK  (0x1 << 8)
      95                 :            :                 uint64_t u64;
      96                 :            :                 struct vhost_vring_state state;
      97                 :            :                 struct vhost_vring_addr addr;
      98                 :            :                 struct vhost_memory memory;
      99                 :            :         } payload;
     100                 :            : } __rte_packed;
     101                 :            : 
     102                 :            : #define VHOST_USER_HDR_SIZE offsetof(struct vhost_user_msg, payload.u64)
     103                 :            : #define VHOST_USER_PAYLOAD_SIZE \
     104                 :            :         (sizeof(struct vhost_user_msg) - VHOST_USER_HDR_SIZE)
     105                 :            : 
     106                 :            : static int
     107                 :          0 : vhost_user_write(int fd, struct vhost_user_msg *msg, int *fds, int fd_num)
     108                 :          0 : {
     109                 :            :         int r;
     110                 :            :         struct msghdr msgh;
     111                 :            :         struct iovec iov;
     112                 :          0 :         size_t fd_size = fd_num * sizeof(int);
     113         [ #  # ]:          0 :         char control[CMSG_SPACE(fd_size)];
     114                 :            :         struct cmsghdr *cmsg;
     115                 :            : 
     116                 :            :         memset(&msgh, 0, sizeof(msgh));
     117                 :            :         memset(control, 0, sizeof(control));
     118                 :            : 
     119                 :          0 :         iov.iov_base = (uint8_t *)msg;
     120                 :          0 :         iov.iov_len = VHOST_USER_HDR_SIZE + msg->size;
     121                 :            : 
     122                 :          0 :         msgh.msg_iov = &iov;
     123                 :          0 :         msgh.msg_iovlen = 1;
     124                 :          0 :         msgh.msg_control = control;
     125                 :          0 :         msgh.msg_controllen = sizeof(control);
     126                 :            : 
     127         [ #  # ]:          0 :         cmsg = CMSG_FIRSTHDR(&msgh);
     128                 :          0 :         cmsg->cmsg_len = CMSG_LEN(fd_size);
     129                 :          0 :         cmsg->cmsg_level = SOL_SOCKET;
     130                 :          0 :         cmsg->cmsg_type = SCM_RIGHTS;
     131                 :          0 :         memcpy(CMSG_DATA(cmsg), fds, fd_size);
     132                 :            : 
     133                 :            :         do {
     134                 :          0 :                 r = sendmsg(fd, &msgh, 0);
     135   [ #  #  #  # ]:          0 :         } while (r < 0 && errno == EINTR);
     136                 :            : 
     137         [ #  # ]:          0 :         if (r < 0)
     138                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to send msg: %s", strerror(errno));
     139                 :            : 
     140                 :          0 :         return r;
     141                 :            : }
     142                 :            : 
     143                 :            : static int
     144         [ #  # ]:          0 : vhost_user_read(int fd, struct vhost_user_msg *msg)
     145                 :            : {
     146                 :            :         uint32_t valid_flags = VHOST_USER_REPLY_MASK | VHOST_USER_VERSION;
     147                 :            :         int ret, sz_hdr = VHOST_USER_HDR_SIZE, sz_payload;
     148                 :            : 
     149                 :          0 :         ret = recv(fd, (void *)msg, sz_hdr, 0);
     150         [ #  # ]:          0 :         if (ret < 0) {
     151                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to recv msg header: %s", strerror(errno));
     152                 :          0 :                 return -1;
     153         [ #  # ]:          0 :         } else if (ret < sz_hdr) {
     154                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to recv msg hdr: %d instead of %d.",
     155                 :            :                             ret, sz_hdr);
     156                 :          0 :                 return -1;
     157                 :            :         }
     158                 :            : 
     159                 :            :         /* validate msg flags */
     160         [ #  # ]:          0 :         if (msg->flags != (valid_flags)) {
     161                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to recv msg: flags 0x%x instead of 0x%x.",
     162                 :            :                             msg->flags, valid_flags);
     163                 :          0 :                 return -1;
     164                 :            :         }
     165                 :            : 
     166                 :          0 :         sz_payload = msg->size;
     167                 :            : 
     168         [ #  # ]:          0 :         if ((size_t)sz_payload > sizeof(msg->payload)) {
     169                 :          0 :                 PMD_DRV_LOG(ERR, "Payload size overflow, header says %d but max %zu",
     170                 :            :                                 sz_payload, sizeof(msg->payload));
     171                 :          0 :                 return -1;
     172                 :            :         }
     173                 :            : 
     174         [ #  # ]:          0 :         if (sz_payload) {
     175         [ #  # ]:          0 :                 ret = recv(fd, (void *)((char *)msg + sz_hdr), sz_payload, 0);
     176         [ #  # ]:          0 :                 if (ret < 0) {
     177                 :          0 :                         PMD_DRV_LOG(ERR, "Failed to recv msg payload: %s", strerror(errno));
     178                 :          0 :                         return -1;
     179         [ #  # ]:          0 :                 } else if (ret < sz_payload) {
     180                 :          0 :                         PMD_DRV_LOG(ERR, "Failed to recv msg payload: %d instead of %u.",
     181                 :            :                                 ret, msg->size);
     182                 :          0 :                         return -1;
     183                 :            :                 }
     184                 :            :         }
     185                 :            : 
     186                 :            :         return 0;
     187                 :            : }
     188                 :            : 
     189                 :            : static int
     190                 :          0 : vhost_user_check_reply_ack(struct virtio_user_dev *dev, struct vhost_user_msg *msg)
     191                 :            : {
     192                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     193                 :          0 :         enum vhost_user_request req = msg->request;
     194                 :            :         int ret;
     195                 :            : 
     196         [ #  # ]:          0 :         if (!(msg->flags & VHOST_USER_NEED_REPLY_MASK))
     197                 :            :                 return 0;
     198                 :            : 
     199                 :          0 :         ret = vhost_user_read(data->vhostfd, msg);
     200         [ #  # ]:          0 :         if (ret < 0) {
     201                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to read reply-ack");
     202                 :          0 :                 return -1;
     203                 :            :         }
     204                 :            : 
     205         [ #  # ]:          0 :         if (req != msg->request) {
     206                 :          0 :                 PMD_DRV_LOG(ERR, "Unexpected reply-ack request type (%d)", msg->request);
     207                 :          0 :                 return -1;
     208                 :            :         }
     209                 :            : 
     210         [ #  # ]:          0 :         if (msg->size != sizeof(msg->payload.u64)) {
     211                 :          0 :                 PMD_DRV_LOG(ERR, "Unexpected reply-ack payload size (%u)", msg->size);
     212                 :          0 :                 return -1;
     213                 :            :         }
     214                 :            : 
     215         [ #  # ]:          0 :         if (msg->payload.u64) {
     216                 :          0 :                 PMD_DRV_LOG(ERR, "Slave replied NACK to request type (%d)", msg->request);
     217                 :          0 :                 return -1;
     218                 :            :         }
     219                 :            : 
     220                 :            :         return 0;
     221                 :            : }
     222                 :            : 
     223                 :            : static int
     224                 :          0 : vhost_user_set_owner(struct virtio_user_dev *dev)
     225                 :            : {
     226                 :            :         int ret;
     227                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     228                 :          0 :         struct vhost_user_msg msg = {
     229                 :            :                 .request = VHOST_USER_SET_OWNER,
     230                 :            :                 .flags = VHOST_USER_VERSION,
     231                 :            :         };
     232                 :            : 
     233                 :          0 :         ret = vhost_user_write(data->vhostfd, &msg, NULL, 0);
     234         [ #  # ]:          0 :         if (ret < 0) {
     235                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to set owner");
     236                 :          0 :                 return -1;
     237                 :            :         }
     238                 :            : 
     239                 :            :         return 0;
     240                 :            : }
     241                 :            : 
     242                 :            : static int
     243                 :          0 : vhost_user_get_protocol_features(struct virtio_user_dev *dev, uint64_t *features)
     244                 :            : {
     245                 :            :         int ret;
     246                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     247                 :          0 :         struct vhost_user_msg msg = {
     248                 :            :                 .request = VHOST_USER_GET_PROTOCOL_FEATURES,
     249                 :            :                 .flags = VHOST_USER_VERSION,
     250                 :            :         };
     251                 :            : 
     252                 :          0 :         ret = vhost_user_write(data->vhostfd, &msg, NULL, 0);
     253         [ #  # ]:          0 :         if (ret < 0)
     254                 :          0 :                 goto err;
     255                 :            : 
     256                 :          0 :         ret = vhost_user_read(data->vhostfd, &msg);
     257         [ #  # ]:          0 :         if (ret < 0)
     258                 :          0 :                 goto err;
     259                 :            : 
     260         [ #  # ]:          0 :         if (msg.request != VHOST_USER_GET_PROTOCOL_FEATURES) {
     261                 :          0 :                 PMD_DRV_LOG(ERR, "Unexpected request type (%d)", msg.request);
     262                 :          0 :                 goto err;
     263                 :            :         }
     264                 :            : 
     265         [ #  # ]:          0 :         if (msg.size != sizeof(*features)) {
     266                 :          0 :                 PMD_DRV_LOG(ERR, "Unexpected payload size (%u)", msg.size);
     267                 :          0 :                 goto err;
     268                 :            :         }
     269                 :            : 
     270                 :          0 :         *features = msg.payload.u64;
     271                 :            : 
     272                 :          0 :         return 0;
     273                 :          0 : err:
     274                 :          0 :         PMD_DRV_LOG(ERR, "Failed to get backend protocol features");
     275                 :            : 
     276                 :          0 :         return -1;
     277                 :            : }
     278                 :            : 
     279                 :            : static int
     280                 :          0 : vhost_user_set_protocol_features(struct virtio_user_dev *dev, uint64_t features)
     281                 :            : {
     282                 :            :         int ret;
     283                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     284                 :          0 :         struct vhost_user_msg msg = {
     285                 :            :                 .request = VHOST_USER_SET_PROTOCOL_FEATURES,
     286                 :            :                 .flags = VHOST_USER_VERSION,
     287                 :            :                 .size = sizeof(features),
     288                 :            :                 .payload.u64 = features,
     289                 :            :         };
     290                 :            : 
     291                 :          0 :         ret = vhost_user_write(data->vhostfd, &msg, NULL, 0);
     292         [ #  # ]:          0 :         if (ret < 0) {
     293                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to set protocol features");
     294                 :          0 :                 return -1;
     295                 :            :         }
     296                 :            : 
     297                 :            :         return 0;
     298                 :            : }
     299                 :            : 
     300                 :            : static int
     301                 :          0 : vhost_user_get_features(struct virtio_user_dev *dev, uint64_t *features)
     302                 :            : {
     303                 :            :         int ret;
     304                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     305                 :          0 :         struct vhost_user_msg msg = {
     306                 :            :                 .request = VHOST_USER_GET_FEATURES,
     307                 :            :                 .flags = VHOST_USER_VERSION,
     308                 :            :         };
     309                 :            : 
     310                 :          0 :         ret = vhost_user_write(data->vhostfd, &msg, NULL, 0);
     311         [ #  # ]:          0 :         if (ret < 0)
     312                 :          0 :                 goto err;
     313                 :            : 
     314                 :          0 :         ret = vhost_user_read(data->vhostfd, &msg);
     315         [ #  # ]:          0 :         if (ret < 0)
     316                 :          0 :                 goto err;
     317                 :            : 
     318         [ #  # ]:          0 :         if (msg.request != VHOST_USER_GET_FEATURES) {
     319                 :          0 :                 PMD_DRV_LOG(ERR, "Unexpected request type (%d)", msg.request);
     320                 :          0 :                 goto err;
     321                 :            :         }
     322                 :            : 
     323         [ #  # ]:          0 :         if (msg.size != sizeof(*features)) {
     324                 :          0 :                 PMD_DRV_LOG(ERR, "Unexpected payload size (%u)", msg.size);
     325                 :          0 :                 goto err;
     326                 :            :         }
     327                 :            : 
     328                 :          0 :         *features = msg.payload.u64;
     329                 :            : 
     330         [ #  # ]:          0 :         if (!(*features & (1ULL << VHOST_USER_F_PROTOCOL_FEATURES)))
     331                 :            :                 return 0;
     332                 :            : 
     333                 :            :         /* Negotiate protocol features */
     334                 :          0 :         ret = vhost_user_get_protocol_features(dev, &data->protocol_features);
     335         [ #  # ]:          0 :         if (ret < 0)
     336                 :          0 :                 goto err;
     337                 :            : 
     338                 :          0 :         data->protocol_features &= VHOST_USER_SUPPORTED_PROTOCOL_FEATURES;
     339                 :            : 
     340                 :          0 :         ret = vhost_user_set_protocol_features(dev, data->protocol_features);
     341         [ #  # ]:          0 :         if (ret < 0)
     342                 :          0 :                 goto err;
     343                 :            : 
     344         [ #  # ]:          0 :         if (!(data->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_MQ)))
     345                 :          0 :                 dev->unsupported_features |= (1ull << VIRTIO_NET_F_MQ);
     346                 :            : 
     347                 :            :         return 0;
     348                 :          0 : err:
     349                 :          0 :         PMD_DRV_LOG(ERR, "Failed to get backend features");
     350                 :            : 
     351                 :          0 :         return -1;
     352                 :            : }
     353                 :            : 
     354                 :            : static int
     355                 :          0 : vhost_user_set_features(struct virtio_user_dev *dev, uint64_t features)
     356                 :            : {
     357                 :            :         int ret;
     358                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     359                 :          0 :         struct vhost_user_msg msg = {
     360                 :            :                 .request = VHOST_USER_SET_FEATURES,
     361                 :            :                 .flags = VHOST_USER_VERSION,
     362                 :            :                 .size = sizeof(features),
     363                 :            :                 .payload.u64 = features,
     364                 :            :         };
     365                 :            : 
     366                 :          0 :         msg.payload.u64 |= dev->device_features & (1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
     367                 :            : 
     368                 :          0 :         ret = vhost_user_write(data->vhostfd, &msg, NULL, 0);
     369         [ #  # ]:          0 :         if (ret < 0) {
     370                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to set features");
     371                 :          0 :                 return -1;
     372                 :            :         }
     373                 :            : 
     374                 :            :         return 0;
     375                 :            : }
     376                 :            : 
     377                 :            : struct walk_arg {
     378                 :            :         struct vhost_memory *vm;
     379                 :            :         int *fds;
     380                 :            :         int region_nr;
     381                 :            : };
     382                 :            : 
     383                 :            : static int
     384                 :          0 : update_memory_region(const struct rte_memseg_list *msl __rte_unused,
     385                 :            :                 const struct rte_memseg *ms, void *arg)
     386                 :            : {
     387                 :            :         struct walk_arg *wa = arg;
     388                 :            :         struct vhost_memory_region *mr;
     389                 :            :         uint64_t start_addr, end_addr;
     390                 :            :         size_t offset;
     391                 :            :         int i, fd;
     392                 :            : 
     393                 :          0 :         fd = rte_memseg_get_fd_thread_unsafe(ms);
     394         [ #  # ]:          0 :         if (fd < 0) {
     395                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to get fd, ms=%p rte_errno=%d",
     396                 :            :                         ms, rte_errno);
     397                 :          0 :                 return -1;
     398                 :            :         }
     399                 :            : 
     400         [ #  # ]:          0 :         if (rte_memseg_get_fd_offset_thread_unsafe(ms, &offset) < 0) {
     401                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to get offset, ms=%p rte_errno=%d",
     402                 :            :                         ms, rte_errno);
     403                 :          0 :                 return -1;
     404                 :            :         }
     405                 :            : 
     406                 :          0 :         start_addr = (uint64_t)(uintptr_t)ms->addr;
     407                 :          0 :         end_addr = start_addr + ms->len;
     408                 :            : 
     409         [ #  # ]:          0 :         for (i = 0; i < wa->region_nr; i++) {
     410         [ #  # ]:          0 :                 if (wa->fds[i] != fd)
     411                 :            :                         continue;
     412                 :            : 
     413                 :          0 :                 mr = &wa->vm->regions[i];
     414                 :            : 
     415         [ #  # ]:          0 :                 if (mr->userspace_addr + mr->memory_size < end_addr)
     416                 :          0 :                         mr->memory_size = end_addr - mr->userspace_addr;
     417                 :            : 
     418         [ #  # ]:          0 :                 if (mr->userspace_addr > start_addr) {
     419                 :          0 :                         mr->userspace_addr = start_addr;
     420                 :          0 :                         mr->guest_phys_addr = start_addr;
     421                 :            :                 }
     422                 :            : 
     423         [ #  # ]:          0 :                 if (mr->mmap_offset > offset)
     424                 :          0 :                         mr->mmap_offset = offset;
     425                 :            : 
     426                 :          0 :                 PMD_DRV_LOG(DEBUG, "index=%d fd=%d offset=0x%" PRIx64
     427                 :            :                         " addr=0x%" PRIx64 " len=%" PRIu64, i, fd,
     428                 :            :                         mr->mmap_offset, mr->userspace_addr,
     429                 :            :                         mr->memory_size);
     430                 :            : 
     431                 :          0 :                 return 0;
     432                 :            :         }
     433                 :            : 
     434         [ #  # ]:          0 :         if (i >= VHOST_MEMORY_MAX_NREGIONS) {
     435                 :          0 :                 PMD_DRV_LOG(ERR, "Too many memory regions");
     436                 :          0 :                 return -1;
     437                 :            :         }
     438                 :            : 
     439                 :          0 :         mr = &wa->vm->regions[i];
     440                 :          0 :         wa->fds[i] = fd;
     441                 :            : 
     442                 :          0 :         mr->guest_phys_addr = start_addr;
     443                 :          0 :         mr->userspace_addr = start_addr;
     444                 :          0 :         mr->memory_size = ms->len;
     445                 :          0 :         mr->mmap_offset = offset;
     446                 :            : 
     447                 :          0 :         PMD_DRV_LOG(DEBUG, "index=%d fd=%d offset=0x%" PRIx64
     448                 :            :                 " addr=0x%" PRIx64 " len=%" PRIu64, i, fd,
     449                 :            :                 mr->mmap_offset, mr->userspace_addr,
     450                 :            :                 mr->memory_size);
     451                 :            : 
     452                 :          0 :         wa->region_nr++;
     453                 :            : 
     454                 :          0 :         return 0;
     455                 :            : }
     456                 :            : 
     457                 :            : static int
     458                 :          0 : vhost_user_set_memory_table(struct virtio_user_dev *dev)
     459                 :            : {
     460                 :            :         struct walk_arg wa;
     461                 :            :         int fds[VHOST_MEMORY_MAX_NREGIONS];
     462                 :            :         int ret, fd_num;
     463                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     464                 :          0 :         struct vhost_user_msg msg = {
     465                 :            :                 .request = VHOST_USER_SET_MEM_TABLE,
     466                 :            :                 .flags = VHOST_USER_VERSION,
     467                 :            :         };
     468                 :            : 
     469         [ #  # ]:          0 :         if (data->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK))
     470                 :          0 :                 msg.flags |= VHOST_USER_NEED_REPLY_MASK;
     471                 :            : 
     472                 :          0 :         wa.region_nr = 0;
     473                 :          0 :         wa.vm = &msg.payload.memory;
     474                 :          0 :         wa.fds = fds;
     475                 :            : 
     476                 :            :         /*
     477                 :            :          * The memory lock has already been taken by memory subsystem
     478                 :            :          * or virtio_user_start_device().
     479                 :            :          */
     480                 :          0 :         ret = rte_memseg_walk_thread_unsafe(update_memory_region, &wa);
     481         [ #  # ]:          0 :         if (ret < 0)
     482                 :          0 :                 goto err;
     483                 :            : 
     484                 :          0 :         fd_num = wa.region_nr;
     485                 :          0 :         msg.payload.memory.nregions = wa.region_nr;
     486                 :          0 :         msg.payload.memory.padding = 0;
     487                 :            : 
     488                 :            :         msg.size = sizeof(msg.payload.memory.nregions);
     489                 :            :         msg.size += sizeof(msg.payload.memory.padding);
     490                 :          0 :         msg.size += fd_num * sizeof(struct vhost_memory_region);
     491                 :            : 
     492                 :          0 :         ret = vhost_user_write(data->vhostfd, &msg, fds, fd_num);
     493         [ #  # ]:          0 :         if (ret < 0)
     494                 :          0 :                 goto err;
     495                 :            : 
     496                 :          0 :         return vhost_user_check_reply_ack(dev, &msg);
     497                 :          0 : err:
     498                 :          0 :         PMD_DRV_LOG(ERR, "Failed to set memory table");
     499                 :          0 :         return -1;
     500                 :            : }
     501                 :            : 
     502                 :            : static int
     503                 :          0 : vhost_user_set_vring(struct virtio_user_dev *dev, enum vhost_user_request req,
     504                 :            :                 struct vhost_vring_state *state)
     505                 :            : {
     506                 :            :         int ret;
     507                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     508                 :          0 :         struct vhost_user_msg msg = {
     509                 :            :                 .request = req,
     510                 :            :                 .flags = VHOST_USER_VERSION,
     511                 :            :                 .size = sizeof(*state),
     512                 :            :                 .payload.state = *state,
     513                 :            :         };
     514                 :            : 
     515                 :          0 :         ret = vhost_user_write(data->vhostfd, &msg, NULL, 0);
     516         [ #  # ]:          0 :         if (ret < 0) {
     517                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to set vring state (request %d)", req);
     518                 :          0 :                 return -1;
     519                 :            :         }
     520                 :            : 
     521                 :            :         return 0;
     522                 :            : }
     523                 :            : 
     524                 :            : static int
     525                 :            : vhost_user_set_vring_enable(struct virtio_user_dev *dev, struct vhost_vring_state *state)
     526                 :            : {
     527                 :          0 :         return vhost_user_set_vring(dev, VHOST_USER_SET_VRING_ENABLE, state);
     528                 :            : }
     529                 :            : 
     530                 :            : static int
     531                 :          0 : vhost_user_set_vring_num(struct virtio_user_dev *dev, struct vhost_vring_state *state)
     532                 :            : {
     533                 :          0 :         return vhost_user_set_vring(dev, VHOST_USER_SET_VRING_NUM, state);
     534                 :            : }
     535                 :            : 
     536                 :            : static int
     537                 :          0 : vhost_user_set_vring_base(struct virtio_user_dev *dev, struct vhost_vring_state *state)
     538                 :            : {
     539                 :          0 :         return vhost_user_set_vring(dev, VHOST_USER_SET_VRING_BASE, state);
     540                 :            : }
     541                 :            : 
     542                 :            : static int
     543                 :          0 : vhost_user_get_vring_base(struct virtio_user_dev *dev, struct vhost_vring_state *state)
     544                 :            : {
     545                 :            :         int ret;
     546                 :            :         struct vhost_user_msg msg;
     547                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     548                 :          0 :         unsigned int index = state->index;
     549                 :            : 
     550                 :          0 :         ret = vhost_user_set_vring(dev, VHOST_USER_GET_VRING_BASE, state);
     551         [ #  # ]:          0 :         if (ret < 0) {
     552                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to send request");
     553                 :          0 :                 goto err;
     554                 :            :         }
     555                 :            : 
     556                 :          0 :         ret = vhost_user_read(data->vhostfd, &msg);
     557         [ #  # ]:          0 :         if (ret < 0) {
     558                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to read reply");
     559                 :          0 :                 goto err;
     560                 :            :         }
     561                 :            : 
     562         [ #  # ]:          0 :         if (msg.request != VHOST_USER_GET_VRING_BASE) {
     563                 :          0 :                 PMD_DRV_LOG(ERR, "Unexpected request type (%d)", msg.request);
     564                 :          0 :                 goto err;
     565                 :            :         }
     566                 :            : 
     567         [ #  # ]:          0 :         if (msg.size != sizeof(*state)) {
     568                 :          0 :                 PMD_DRV_LOG(ERR, "Unexpected payload size (%u)", msg.size);
     569                 :          0 :                 goto err;
     570                 :            :         }
     571                 :            : 
     572         [ #  # ]:          0 :         if (msg.payload.state.index != index) {
     573                 :          0 :                 PMD_DRV_LOG(ERR, "Unexpected ring index (%u)", state->index);
     574                 :          0 :                 goto err;
     575                 :            :         }
     576                 :            : 
     577                 :          0 :         *state = msg.payload.state;
     578                 :            : 
     579                 :          0 :         return 0;
     580                 :          0 : err:
     581                 :          0 :         PMD_DRV_LOG(ERR, "Failed to get vring base");
     582                 :          0 :         return -1;
     583                 :            : }
     584                 :            : 
     585                 :            : static int
     586                 :          0 : vhost_user_set_vring_file(struct virtio_user_dev *dev, enum vhost_user_request req,
     587                 :            :                 struct vhost_vring_file *file)
     588                 :            : {
     589                 :            :         int ret;
     590                 :          0 :         int fd = file->fd;
     591                 :            :         int num_fd = 0;
     592                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     593                 :          0 :         struct vhost_user_msg msg = {
     594                 :            :                 .request = req,
     595                 :            :                 .flags = VHOST_USER_VERSION,
     596                 :            :                 .size = sizeof(msg.payload.u64),
     597                 :          0 :                 .payload.u64 = file->index & VHOST_USER_VRING_IDX_MASK,
     598                 :            :         };
     599                 :            : 
     600         [ #  # ]:          0 :         if (fd >= 0)
     601                 :            :                 num_fd++;
     602                 :            :         else
     603                 :          0 :                 msg.payload.u64 |= VHOST_USER_VRING_NOFD_MASK;
     604                 :            : 
     605                 :          0 :         ret = vhost_user_write(data->vhostfd, &msg, &fd, num_fd);
     606         [ #  # ]:          0 :         if (ret < 0) {
     607                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to set vring file (request %d)", req);
     608                 :          0 :                 return -1;
     609                 :            :         }
     610                 :            : 
     611                 :            :         return 0;
     612                 :            : }
     613                 :            : 
     614                 :            : static int
     615                 :          0 : vhost_user_set_vring_call(struct virtio_user_dev *dev, struct vhost_vring_file *file)
     616                 :            : {
     617                 :          0 :         return vhost_user_set_vring_file(dev, VHOST_USER_SET_VRING_CALL, file);
     618                 :            : }
     619                 :            : 
     620                 :            : static int
     621                 :          0 : vhost_user_set_vring_kick(struct virtio_user_dev *dev, struct vhost_vring_file *file)
     622                 :            : {
     623                 :          0 :         return vhost_user_set_vring_file(dev, VHOST_USER_SET_VRING_KICK, file);
     624                 :            : }
     625                 :            : 
     626                 :            : 
     627                 :            : static int
     628                 :          0 : vhost_user_set_vring_addr(struct virtio_user_dev *dev, struct vhost_vring_addr *addr)
     629                 :            : {
     630                 :            :         int ret;
     631                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     632                 :          0 :         struct vhost_user_msg msg = {
     633                 :            :                 .request = VHOST_USER_SET_VRING_ADDR,
     634                 :            :                 .flags = VHOST_USER_VERSION,
     635                 :            :                 .size = sizeof(*addr),
     636                 :            :                 .payload.addr = *addr,
     637                 :            :         };
     638                 :            : 
     639                 :          0 :         ret = vhost_user_write(data->vhostfd, &msg, NULL, 0);
     640         [ #  # ]:          0 :         if (ret < 0) {
     641                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to send vring addresses");
     642                 :          0 :                 return -1;
     643                 :            :         }
     644                 :            : 
     645                 :            :         return 0;
     646                 :            : }
     647                 :            : 
     648                 :            : static int
     649                 :          0 : vhost_user_get_status(struct virtio_user_dev *dev, uint8_t *status)
     650                 :            : {
     651                 :            :         int ret;
     652                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     653                 :          0 :         struct vhost_user_msg msg = {
     654                 :            :                 .request = VHOST_USER_GET_STATUS,
     655                 :            :                 .flags = VHOST_USER_VERSION,
     656                 :            :         };
     657                 :            : 
     658                 :            :         /*
     659                 :            :          * If features have not been negotiated, we don't know if the backend
     660                 :            :          * supports protocol features
     661                 :            :          */
     662         [ #  # ]:          0 :         if (!(dev->status & VIRTIO_CONFIG_STATUS_FEATURES_OK))
     663                 :            :                 return -ENOTSUP;
     664                 :            : 
     665                 :            :         /* Status protocol feature requires protocol features support */
     666         [ #  # ]:          0 :         if (!(dev->device_features & (1ULL << VHOST_USER_F_PROTOCOL_FEATURES)))
     667                 :            :                 return -ENOTSUP;
     668                 :            : 
     669         [ #  # ]:          0 :         if (!(data->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_STATUS)))
     670                 :            :                 return -ENOTSUP;
     671                 :            : 
     672                 :          0 :         ret = vhost_user_write(data->vhostfd, &msg, NULL, 0);
     673         [ #  # ]:          0 :         if (ret < 0) {
     674                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to send request");
     675                 :          0 :                 goto err;
     676                 :            :         }
     677                 :            : 
     678                 :          0 :         ret = vhost_user_read(data->vhostfd, &msg);
     679         [ #  # ]:          0 :         if (ret < 0) {
     680                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to recv request");
     681                 :          0 :                 goto err;
     682                 :            :         }
     683                 :            : 
     684         [ #  # ]:          0 :         if (msg.request != VHOST_USER_GET_STATUS) {
     685                 :          0 :                 PMD_DRV_LOG(ERR, "Unexpected request type (%d)", msg.request);
     686                 :          0 :                 goto err;
     687                 :            :         }
     688                 :            : 
     689         [ #  # ]:          0 :         if (msg.size != sizeof(msg.payload.u64)) {
     690                 :          0 :                 PMD_DRV_LOG(ERR, "Unexpected payload size (%u)", msg.size);
     691                 :          0 :                 goto err;
     692                 :            :         }
     693                 :            : 
     694                 :          0 :         *status = (uint8_t)msg.payload.u64;
     695                 :            : 
     696                 :          0 :         return 0;
     697                 :          0 : err:
     698                 :          0 :         PMD_DRV_LOG(ERR, "Failed to get device status");
     699                 :          0 :         return -1;
     700                 :            : }
     701                 :            : 
     702                 :            : static int
     703                 :          0 : vhost_user_set_status(struct virtio_user_dev *dev, uint8_t status)
     704                 :            : {
     705                 :            :         int ret;
     706                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     707                 :          0 :         struct vhost_user_msg msg = {
     708                 :            :                 .request = VHOST_USER_SET_STATUS,
     709                 :            :                 .flags = VHOST_USER_VERSION,
     710                 :            :                 .size = sizeof(msg.payload.u64),
     711                 :            :                 .payload.u64 = status,
     712                 :            :         };
     713                 :            : 
     714                 :            :         /*
     715                 :            :          * If features have not been negotiated, we don't know if the backend
     716                 :            :          * supports protocol features
     717                 :            :          */
     718         [ #  # ]:          0 :         if (!(dev->status & VIRTIO_CONFIG_STATUS_FEATURES_OK))
     719                 :            :                 return -ENOTSUP;
     720                 :            : 
     721                 :            :         /* Status protocol feature requires protocol features support */
     722         [ #  # ]:          0 :         if (!(dev->device_features & (1ULL << VHOST_USER_F_PROTOCOL_FEATURES)))
     723                 :            :                 return -ENOTSUP;
     724                 :            : 
     725         [ #  # ]:          0 :         if (!(data->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_STATUS)))
     726                 :            :                 return -ENOTSUP;
     727                 :            : 
     728         [ #  # ]:          0 :         if (data->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK))
     729                 :          0 :                 msg.flags |= VHOST_USER_NEED_REPLY_MASK;
     730                 :            : 
     731                 :          0 :         ret = vhost_user_write(data->vhostfd, &msg, NULL, 0);
     732         [ #  # ]:          0 :         if (ret < 0) {
     733                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to send get status request");
     734                 :          0 :                 return -1;
     735                 :            :         }
     736                 :            : 
     737                 :          0 :         return vhost_user_check_reply_ack(dev, &msg);
     738                 :            : }
     739                 :            : 
     740                 :            : #define MAX_VIRTIO_USER_BACKLOG 1
     741                 :            : static int
     742                 :          0 : vhost_user_start_server(struct virtio_user_dev *dev, struct sockaddr_un *un)
     743                 :            : {
     744                 :            :         int ret;
     745                 :            :         int flag;
     746                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     747                 :          0 :         int fd = data->listenfd;
     748                 :            : 
     749                 :          0 :         ret = bind(fd, (struct sockaddr *)un, sizeof(*un));
     750         [ #  # ]:          0 :         if (ret < 0) {
     751                 :          0 :                 PMD_DRV_LOG(ERR, "failed to bind to %s: %s; remove it and try again",
     752                 :            :                             dev->path, strerror(errno));
     753                 :          0 :                 return -1;
     754                 :            :         }
     755                 :          0 :         ret = listen(fd, MAX_VIRTIO_USER_BACKLOG);
     756         [ #  # ]:          0 :         if (ret < 0)
     757                 :            :                 return -1;
     758                 :            : 
     759                 :          0 :         PMD_DRV_LOG(NOTICE, "(%s) waiting for client connection...", dev->path);
     760                 :          0 :         data->vhostfd = accept(fd, NULL, NULL);
     761         [ #  # ]:          0 :         if (data->vhostfd < 0) {
     762                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to accept initial client connection (%s)",
     763                 :            :                                 strerror(errno));
     764                 :          0 :                 return -1;
     765                 :            :         }
     766                 :            : 
     767                 :          0 :         flag = fcntl(fd, F_GETFL);
     768         [ #  # ]:          0 :         if (fcntl(fd, F_SETFL, flag | O_NONBLOCK) < 0) {
     769                 :          0 :                 PMD_DRV_LOG(ERR, "fcntl failed, %s", strerror(errno));
     770                 :          0 :                 return -1;
     771                 :            :         }
     772                 :            : 
     773                 :            :         return 0;
     774                 :            : }
     775                 :            : 
     776                 :            : static int
     777                 :          0 : vhost_user_server_disconnect(struct virtio_user_dev *dev)
     778                 :            : {
     779                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     780                 :            : 
     781         [ #  # ]:          0 :         if (data->vhostfd < 0) {
     782                 :          0 :                 PMD_DRV_LOG(ERR, "(%s) Expected valid Vhost FD", dev->path);
     783                 :          0 :                 return -1;
     784                 :            :         }
     785                 :            : 
     786                 :          0 :         close(data->vhostfd);
     787                 :          0 :         data->vhostfd = -1;
     788                 :            : 
     789                 :          0 :         return 0;
     790                 :            : }
     791                 :            : 
     792                 :            : static int
     793                 :          0 : vhost_user_server_reconnect(struct virtio_user_dev *dev)
     794                 :            : {
     795                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     796                 :            :         int fd;
     797                 :            : 
     798                 :          0 :         fd = accept(data->listenfd, NULL, NULL);
     799         [ #  # ]:          0 :         if (fd < 0)
     800                 :            :                 return -1;
     801                 :            : 
     802                 :          0 :         data->vhostfd = fd;
     803                 :            : 
     804                 :          0 :         return 0;
     805                 :            : }
     806                 :            : 
     807                 :            : /**
     808                 :            :  * Set up environment to talk with a vhost user backend.
     809                 :            :  *
     810                 :            :  * @return
     811                 :            :  *   - (-1) if fail;
     812                 :            :  *   - (0) if succeed.
     813                 :            :  */
     814                 :            : static int
     815                 :          0 : vhost_user_setup(struct virtio_user_dev *dev)
     816                 :            : {
     817                 :            :         int fd;
     818                 :            :         int flag;
     819                 :            :         struct sockaddr_un un;
     820                 :            :         struct vhost_user_data *data;
     821                 :            : 
     822                 :          0 :         data = malloc(sizeof(*data));
     823         [ #  # ]:          0 :         if (!data) {
     824                 :          0 :                 PMD_DRV_LOG(ERR, "(%s) Failed to allocate Vhost-user data", dev->path);
     825                 :          0 :                 return -1;
     826                 :            :         }
     827                 :            : 
     828                 :            :         memset(data, 0, sizeof(*data));
     829                 :            : 
     830                 :          0 :         dev->backend_data = data;
     831                 :            : 
     832                 :          0 :         data->vhostfd = -1;
     833                 :          0 :         data->listenfd = -1;
     834                 :            : 
     835                 :          0 :         fd = socket(AF_UNIX, SOCK_STREAM, 0);
     836         [ #  # ]:          0 :         if (fd < 0) {
     837                 :          0 :                 PMD_DRV_LOG(ERR, "socket() error, %s", strerror(errno));
     838                 :          0 :                 goto err_data;
     839                 :            :         }
     840                 :            : 
     841                 :          0 :         flag = fcntl(fd, F_GETFD);
     842         [ #  # ]:          0 :         if (flag == -1)
     843                 :          0 :                 PMD_DRV_LOG(WARNING, "fcntl get fd failed, %s", strerror(errno));
     844         [ #  # ]:          0 :         else if (fcntl(fd, F_SETFD, flag | FD_CLOEXEC) < 0)
     845                 :          0 :                 PMD_DRV_LOG(WARNING, "fcntl set fd failed, %s", strerror(errno));
     846                 :            : 
     847                 :            :         memset(&un, 0, sizeof(un));
     848                 :          0 :         un.sun_family = AF_UNIX;
     849         [ #  # ]:          0 :         strlcpy(un.sun_path, dev->path, sizeof(un.sun_path));
     850                 :            : 
     851         [ #  # ]:          0 :         if (dev->is_server) {
     852                 :          0 :                 data->listenfd = fd;
     853         [ #  # ]:          0 :                 if (vhost_user_start_server(dev, &un) < 0) {
     854                 :          0 :                         PMD_DRV_LOG(ERR, "virtio-user startup fails in server mode");
     855                 :          0 :                         goto err_socket;
     856                 :            :                 }
     857                 :            :         } else {
     858         [ #  # ]:          0 :                 if (connect(fd, (struct sockaddr *)&un, sizeof(un)) < 0) {
     859                 :          0 :                         PMD_DRV_LOG(ERR, "connect error, %s", strerror(errno));
     860                 :          0 :                         goto err_socket;
     861                 :            :                 }
     862                 :          0 :                 data->vhostfd = fd;
     863                 :            :         }
     864                 :            : 
     865                 :            :         return 0;
     866                 :            : 
     867                 :          0 : err_socket:
     868                 :          0 :         close(fd);
     869                 :          0 : err_data:
     870                 :          0 :         free(data);
     871                 :          0 :         dev->backend_data = NULL;
     872                 :            : 
     873                 :          0 :         return -1;
     874                 :            : }
     875                 :            : 
     876                 :            : static int
     877                 :          0 : vhost_user_destroy(struct virtio_user_dev *dev)
     878                 :            : {
     879                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     880                 :            : 
     881         [ #  # ]:          0 :         if (!data)
     882                 :            :                 return 0;
     883                 :            : 
     884         [ #  # ]:          0 :         if (data->vhostfd >= 0) {
     885                 :          0 :                 close(data->vhostfd);
     886                 :          0 :                 data->vhostfd = -1;
     887                 :            :         }
     888                 :            : 
     889         [ #  # ]:          0 :         if (data->listenfd >= 0) {
     890                 :          0 :                 close(data->listenfd);
     891                 :            :                 data->listenfd = -1;
     892                 :            :         }
     893                 :            : 
     894                 :          0 :         free(data);
     895                 :          0 :         dev->backend_data = NULL;
     896                 :            : 
     897                 :          0 :         return 0;
     898                 :            : }
     899                 :            : 
     900                 :            : static int
     901                 :          0 : vhost_user_enable_queue_pair(struct virtio_user_dev *dev,
     902                 :            :                              uint16_t pair_idx,
     903                 :            :                              int enable)
     904                 :            : {
     905                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     906                 :            :         int i;
     907                 :            : 
     908         [ #  # ]:          0 :         if (data->vhostfd < 0)
     909                 :            :                 return 0;
     910                 :            : 
     911         [ #  # ]:          0 :         if (dev->qp_enabled[pair_idx] == enable)
     912                 :            :                 return 0;
     913                 :            : 
     914         [ #  # ]:          0 :         for (i = 0; i < 2; ++i) {
     915                 :          0 :                 struct vhost_vring_state state = {
     916                 :          0 :                         .index = pair_idx * 2 + i,
     917                 :            :                         .num = enable,
     918                 :            :                 };
     919                 :            : 
     920         [ #  # ]:          0 :                 if (vhost_user_set_vring_enable(dev, &state))
     921                 :          0 :                         return -1;
     922                 :            :         }
     923                 :            : 
     924                 :          0 :         dev->qp_enabled[pair_idx] = enable;
     925                 :          0 :         return 0;
     926                 :            : }
     927                 :            : 
     928                 :            : static int
     929                 :          0 : vhost_user_get_backend_features(uint64_t *features)
     930                 :            : {
     931                 :          0 :         *features = 1ULL << VHOST_USER_F_PROTOCOL_FEATURES;
     932                 :            : 
     933                 :          0 :         return 0;
     934                 :            : }
     935                 :            : 
     936                 :            : static int
     937                 :          0 : vhost_user_update_link_state(struct virtio_user_dev *dev)
     938                 :            : {
     939                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     940                 :            :         char buf[128];
     941                 :            : 
     942         [ #  # ]:          0 :         if (data->vhostfd >= 0) {
     943                 :            :                 int r;
     944                 :            : 
     945                 :          0 :                 r = recv(data->vhostfd, buf, 128, MSG_PEEK | MSG_DONTWAIT);
     946   [ #  #  #  #  :          0 :                 if (r == 0 || (r < 0 && errno != EAGAIN)) {
                   #  # ]
     947                 :          0 :                         dev->net_status &= (~VIRTIO_NET_S_LINK_UP);
     948                 :          0 :                         PMD_DRV_LOG(ERR, "virtio-user port %u is down", dev->hw.port_id);
     949                 :            : 
     950                 :            :                         /* This function could be called in the process
     951                 :            :                          * of interrupt handling, callback cannot be
     952                 :            :                          * unregistered here, set an alarm to do it.
     953                 :            :                          */
     954                 :          0 :                         rte_eal_alarm_set(1,
     955                 :            :                                 virtio_user_dev_delayed_disconnect_handler,
     956                 :            :                                 (void *)dev);
     957                 :            :                 } else {
     958                 :          0 :                         dev->net_status |= VIRTIO_NET_S_LINK_UP;
     959                 :            :                 }
     960         [ #  # ]:          0 :         } else if (dev->is_server) {
     961                 :          0 :                 dev->net_status &= (~VIRTIO_NET_S_LINK_UP);
     962         [ #  # ]:          0 :                 if (virtio_user_dev_server_reconnect(dev) >= 0)
     963                 :          0 :                         dev->net_status |= VIRTIO_NET_S_LINK_UP;
     964                 :            :         }
     965                 :            : 
     966                 :          0 :         return 0;
     967                 :            : }
     968                 :            : 
     969                 :            : static int
     970                 :          0 : vhost_user_get_intr_fd(struct virtio_user_dev *dev)
     971                 :            : {
     972                 :          0 :         struct vhost_user_data *data = dev->backend_data;
     973                 :            : 
     974   [ #  #  #  # ]:          0 :         if (dev->is_server && data->vhostfd == -1)
     975                 :          0 :                 return data->listenfd;
     976                 :            : 
     977                 :          0 :         return data->vhostfd;
     978                 :            : }
     979                 :            : 
     980                 :            : struct virtio_user_backend_ops virtio_ops_user = {
     981                 :            :         .setup = vhost_user_setup,
     982                 :            :         .destroy = vhost_user_destroy,
     983                 :            :         .get_backend_features = vhost_user_get_backend_features,
     984                 :            :         .set_owner = vhost_user_set_owner,
     985                 :            :         .get_features = vhost_user_get_features,
     986                 :            :         .set_features = vhost_user_set_features,
     987                 :            :         .set_memory_table = vhost_user_set_memory_table,
     988                 :            :         .set_vring_num = vhost_user_set_vring_num,
     989                 :            :         .set_vring_base = vhost_user_set_vring_base,
     990                 :            :         .get_vring_base = vhost_user_get_vring_base,
     991                 :            :         .set_vring_call = vhost_user_set_vring_call,
     992                 :            :         .set_vring_kick = vhost_user_set_vring_kick,
     993                 :            :         .set_vring_addr = vhost_user_set_vring_addr,
     994                 :            :         .get_status = vhost_user_get_status,
     995                 :            :         .set_status = vhost_user_set_status,
     996                 :            :         .enable_qp = vhost_user_enable_queue_pair,
     997                 :            :         .update_link_state = vhost_user_update_link_state,
     998                 :            :         .server_disconnect = vhost_user_server_disconnect,
     999                 :            :         .server_reconnect = vhost_user_server_reconnect,
    1000                 :            :         .get_intr_fd = vhost_user_get_intr_fd,
    1001                 :            : };

Generated by: LCOV version 1.14