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 <string.h> 12 #include <errno.h> 13 14 #include <rte_string_fns.h> 15 #include <rte_fbarray.h> 16 17 #include "vhost.h" 18 #include "virtio_user_dev.h" 19 20 /* The version of the protocol we support */ 21 #define VHOST_USER_VERSION 0x1 22 23 #define VHOST_MEMORY_MAX_NREGIONS 8 24 struct vhost_memory { 25 uint32_t nregions; 26 uint32_t padding; 27 struct vhost_memory_region regions[VHOST_MEMORY_MAX_NREGIONS]; 28 }; 29 30 enum vhost_user_request { 31 VHOST_USER_NONE = 0, 32 VHOST_USER_GET_FEATURES = 1, 33 VHOST_USER_SET_FEATURES = 2, 34 VHOST_USER_SET_OWNER = 3, 35 VHOST_USER_RESET_OWNER = 4, 36 VHOST_USER_SET_MEM_TABLE = 5, 37 VHOST_USER_SET_LOG_BASE = 6, 38 VHOST_USER_SET_LOG_FD = 7, 39 VHOST_USER_SET_VRING_NUM = 8, 40 VHOST_USER_SET_VRING_ADDR = 9, 41 VHOST_USER_SET_VRING_BASE = 10, 42 VHOST_USER_GET_VRING_BASE = 11, 43 VHOST_USER_SET_VRING_KICK = 12, 44 VHOST_USER_SET_VRING_CALL = 13, 45 VHOST_USER_SET_VRING_ERR = 14, 46 VHOST_USER_GET_PROTOCOL_FEATURES = 15, 47 VHOST_USER_SET_PROTOCOL_FEATURES = 16, 48 VHOST_USER_GET_QUEUE_NUM = 17, 49 VHOST_USER_SET_VRING_ENABLE = 18, 50 VHOST_USER_SET_STATUS = 39, 51 VHOST_USER_GET_STATUS = 40, 52 VHOST_USER_MAX 53 }; 54 55 struct vhost_user_msg { 56 enum vhost_user_request request; 57 58 #define VHOST_USER_VERSION_MASK 0x3 59 #define VHOST_USER_REPLY_MASK (0x1 << 2) 60 #define VHOST_USER_NEED_REPLY_MASK (0x1 << 3) 61 uint32_t flags; 62 uint32_t size; /* the following payload size */ 63 union { 64 #define VHOST_USER_VRING_IDX_MASK 0xff 65 #define VHOST_USER_VRING_NOFD_MASK (0x1 << 8) 66 uint64_t u64; 67 struct vhost_vring_state state; 68 struct vhost_vring_addr addr; 69 struct vhost_memory memory; 70 } payload; 71 int fds[VHOST_MEMORY_MAX_NREGIONS]; 72 } __rte_packed; 73 74 #define VHOST_USER_HDR_SIZE offsetof(struct vhost_user_msg, payload.u64) 75 #define VHOST_USER_PAYLOAD_SIZE \ 76 (sizeof(struct vhost_user_msg) - VHOST_USER_HDR_SIZE) 77 78 static int 79 vhost_user_write(int fd, struct vhost_user_msg *msg, int *fds, int fd_num) 80 { 81 int r; 82 struct msghdr msgh; 83 struct iovec iov; 84 size_t fd_size = fd_num * sizeof(int); 85 char control[CMSG_SPACE(fd_size)]; 86 struct cmsghdr *cmsg; 87 88 memset(&msgh, 0, sizeof(msgh)); 89 memset(control, 0, sizeof(control)); 90 91 iov.iov_base = (uint8_t *)msg; 92 iov.iov_len = VHOST_USER_HDR_SIZE + msg->size; 93 94 msgh.msg_iov = &iov; 95 msgh.msg_iovlen = 1; 96 msgh.msg_control = control; 97 msgh.msg_controllen = sizeof(control); 98 99 cmsg = CMSG_FIRSTHDR(&msgh); 100 cmsg->cmsg_len = CMSG_LEN(fd_size); 101 cmsg->cmsg_level = SOL_SOCKET; 102 cmsg->cmsg_type = SCM_RIGHTS; 103 memcpy(CMSG_DATA(cmsg), fds, fd_size); 104 105 do { 106 r = sendmsg(fd, &msgh, 0); 107 } while (r < 0 && errno == EINTR); 108 109 if (r < 0) 110 PMD_DRV_LOG(ERR, "Failed to send msg: %s", strerror(errno)); 111 112 return r; 113 } 114 115 static int 116 vhost_user_read(int fd, struct vhost_user_msg *msg) 117 { 118 uint32_t valid_flags = VHOST_USER_REPLY_MASK | VHOST_USER_VERSION; 119 int ret, sz_hdr = VHOST_USER_HDR_SIZE, sz_payload; 120 121 ret = recv(fd, (void *)msg, sz_hdr, 0); 122 if (ret < sz_hdr) { 123 PMD_DRV_LOG(ERR, "Failed to recv msg hdr: %d instead of %d.", 124 ret, sz_hdr); 125 goto fail; 126 } 127 128 /* validate msg flags */ 129 if (msg->flags != (valid_flags)) { 130 PMD_DRV_LOG(ERR, "Failed to recv msg: flags %x instead of %x.", 131 msg->flags, valid_flags); 132 goto fail; 133 } 134 135 sz_payload = msg->size; 136 137 if ((size_t)sz_payload > sizeof(msg->payload)) 138 goto fail; 139 140 if (sz_payload) { 141 ret = recv(fd, (void *)((char *)msg + sz_hdr), sz_payload, 0); 142 if (ret < sz_payload) { 143 PMD_DRV_LOG(ERR, 144 "Failed to recv msg payload: %d instead of %d.", 145 ret, msg->size); 146 goto fail; 147 } 148 } 149 150 return 0; 151 152 fail: 153 return -1; 154 } 155 156 static int 157 vhost_user_check_reply_ack(struct virtio_user_dev *dev, struct vhost_user_msg *msg) 158 { 159 enum vhost_user_request req = msg->request; 160 int ret; 161 162 if (!(msg->flags & VHOST_USER_NEED_REPLY_MASK)) 163 return 0; 164 165 ret = vhost_user_read(dev->vhostfd, msg); 166 if (ret < 0) { 167 PMD_DRV_LOG(ERR, "Failed to read reply-ack"); 168 return -1; 169 } 170 171 if (req != msg->request) { 172 PMD_DRV_LOG(ERR, "Unexpected reply-ack request type (%d)", msg->request); 173 return -1; 174 } 175 176 if (msg->size != sizeof(msg->payload.u64)) { 177 PMD_DRV_LOG(ERR, "Unexpected reply-ack payload size (%u)", msg->size); 178 return -1; 179 } 180 181 if (msg->payload.u64) { 182 PMD_DRV_LOG(ERR, "Slave replied NACK to request type (%d)", msg->request); 183 return -1; 184 } 185 186 return 0; 187 } 188 189 static int 190 vhost_user_set_owner(struct virtio_user_dev *dev) 191 { 192 int ret; 193 struct vhost_user_msg msg = { 194 .request = VHOST_USER_SET_OWNER, 195 .flags = VHOST_USER_VERSION, 196 }; 197 198 ret = vhost_user_write(dev->vhostfd, &msg, NULL, 0); 199 if (ret < 0) { 200 PMD_DRV_LOG(ERR, "Failed to set owner"); 201 return -1; 202 } 203 204 return 0; 205 } 206 207 static int 208 vhost_user_get_features(struct virtio_user_dev *dev, uint64_t *features) 209 { 210 int ret; 211 struct vhost_user_msg msg = { 212 .request = VHOST_USER_GET_FEATURES, 213 .flags = VHOST_USER_VERSION, 214 }; 215 216 ret = vhost_user_write(dev->vhostfd, &msg, NULL, 0); 217 if (ret < 0) 218 goto err; 219 220 ret = vhost_user_read(dev->vhostfd, &msg); 221 if (ret < 0) 222 goto err; 223 224 if (msg.request != VHOST_USER_GET_FEATURES) { 225 PMD_DRV_LOG(ERR, "Unexpected request type (%d)", msg.request); 226 goto err; 227 } 228 229 if (msg.size != sizeof(*features)) { 230 PMD_DRV_LOG(ERR, "Unexpected payload size (%u)", msg.size); 231 goto err; 232 } 233 234 *features = msg.payload.u64; 235 236 return 0; 237 err: 238 PMD_DRV_LOG(ERR, "Failed to get backend features"); 239 240 return -1; 241 } 242 243 static int 244 vhost_user_set_features(struct virtio_user_dev *dev, uint64_t features) 245 { 246 int ret; 247 struct vhost_user_msg msg = { 248 .request = VHOST_USER_SET_FEATURES, 249 .flags = VHOST_USER_VERSION, 250 .size = sizeof(features), 251 .payload.u64 = features, 252 }; 253 254 msg.payload.u64 |= dev->device_features & (1ULL << VHOST_USER_F_PROTOCOL_FEATURES); 255 256 ret = vhost_user_write(dev->vhostfd, &msg, NULL, 0); 257 if (ret < 0) { 258 PMD_DRV_LOG(ERR, "Failed to set features"); 259 return -1; 260 } 261 262 return 0; 263 } 264 265 static int 266 vhost_user_get_protocol_features(struct virtio_user_dev *dev, uint64_t *features) 267 { 268 int ret; 269 struct vhost_user_msg msg = { 270 .request = VHOST_USER_GET_PROTOCOL_FEATURES, 271 .flags = VHOST_USER_VERSION, 272 }; 273 274 ret = vhost_user_write(dev->vhostfd, &msg, NULL, 0); 275 if (ret < 0) 276 goto err; 277 278 ret = vhost_user_read(dev->vhostfd, &msg); 279 if (ret < 0) 280 goto err; 281 282 if (msg.request != VHOST_USER_GET_PROTOCOL_FEATURES) { 283 PMD_DRV_LOG(ERR, "Unexpected request type (%d)", msg.request); 284 goto err; 285 } 286 287 if (msg.size != sizeof(*features)) { 288 PMD_DRV_LOG(ERR, "Unexpected payload size (%u)", msg.size); 289 goto err; 290 } 291 292 *features = msg.payload.u64; 293 294 return 0; 295 err: 296 PMD_DRV_LOG(ERR, "Failed to get backend protocol features"); 297 298 return -1; 299 } 300 301 static int 302 vhost_user_set_protocol_features(struct virtio_user_dev *dev, uint64_t features) 303 { 304 int ret; 305 struct vhost_user_msg msg = { 306 .request = VHOST_USER_SET_PROTOCOL_FEATURES, 307 .flags = VHOST_USER_VERSION, 308 .size = sizeof(features), 309 .payload.u64 = features, 310 }; 311 312 ret = vhost_user_write(dev->vhostfd, &msg, NULL, 0); 313 if (ret < 0) { 314 PMD_DRV_LOG(ERR, "Failed to set protocol features"); 315 return -1; 316 } 317 318 return 0; 319 } 320 321 struct walk_arg { 322 struct vhost_memory *vm; 323 int *fds; 324 int region_nr; 325 }; 326 327 static int 328 update_memory_region(const struct rte_memseg_list *msl __rte_unused, 329 const struct rte_memseg *ms, void *arg) 330 { 331 struct walk_arg *wa = arg; 332 struct vhost_memory_region *mr; 333 uint64_t start_addr, end_addr; 334 size_t offset; 335 int i, fd; 336 337 fd = rte_memseg_get_fd_thread_unsafe(ms); 338 if (fd < 0) { 339 PMD_DRV_LOG(ERR, "Failed to get fd, ms=%p rte_errno=%d", 340 ms, rte_errno); 341 return -1; 342 } 343 344 if (rte_memseg_get_fd_offset_thread_unsafe(ms, &offset) < 0) { 345 PMD_DRV_LOG(ERR, "Failed to get offset, ms=%p rte_errno=%d", 346 ms, rte_errno); 347 return -1; 348 } 349 350 start_addr = (uint64_t)(uintptr_t)ms->addr; 351 end_addr = start_addr + ms->len; 352 353 for (i = 0; i < wa->region_nr; i++) { 354 if (wa->fds[i] != fd) 355 continue; 356 357 mr = &wa->vm->regions[i]; 358 359 if (mr->userspace_addr + mr->memory_size < end_addr) 360 mr->memory_size = end_addr - mr->userspace_addr; 361 362 if (mr->userspace_addr > start_addr) { 363 mr->userspace_addr = start_addr; 364 mr->guest_phys_addr = start_addr; 365 } 366 367 if (mr->mmap_offset > offset) 368 mr->mmap_offset = offset; 369 370 PMD_DRV_LOG(DEBUG, "index=%d fd=%d offset=0x%" PRIx64 371 " addr=0x%" PRIx64 " len=%" PRIu64, i, fd, 372 mr->mmap_offset, mr->userspace_addr, 373 mr->memory_size); 374 375 return 0; 376 } 377 378 if (i >= VHOST_MEMORY_MAX_NREGIONS) { 379 PMD_DRV_LOG(ERR, "Too many memory regions"); 380 return -1; 381 } 382 383 mr = &wa->vm->regions[i]; 384 wa->fds[i] = fd; 385 386 mr->guest_phys_addr = start_addr; 387 mr->userspace_addr = start_addr; 388 mr->memory_size = ms->len; 389 mr->mmap_offset = offset; 390 391 PMD_DRV_LOG(DEBUG, "index=%d fd=%d offset=0x%" PRIx64 392 " addr=0x%" PRIx64 " len=%" PRIu64, i, fd, 393 mr->mmap_offset, mr->userspace_addr, 394 mr->memory_size); 395 396 wa->region_nr++; 397 398 return 0; 399 } 400 401 static int 402 vhost_user_set_memory_table(struct virtio_user_dev *dev) 403 { 404 struct walk_arg wa; 405 int fds[VHOST_MEMORY_MAX_NREGIONS]; 406 int ret, fd_num; 407 struct vhost_user_msg msg = { 408 .request = VHOST_USER_SET_MEM_TABLE, 409 .flags = VHOST_USER_VERSION, 410 }; 411 412 if (dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK)) 413 msg.flags |= VHOST_USER_NEED_REPLY_MASK; 414 415 wa.region_nr = 0; 416 wa.vm = &msg.payload.memory; 417 wa.fds = fds; 418 419 /* 420 * The memory lock has already been taken by memory subsystem 421 * or virtio_user_start_device(). 422 */ 423 ret = rte_memseg_walk_thread_unsafe(update_memory_region, &wa); 424 if (ret < 0) 425 goto err; 426 427 fd_num = wa.region_nr; 428 msg.payload.memory.nregions = wa.region_nr; 429 msg.payload.memory.padding = 0; 430 431 msg.size = sizeof(msg.payload.memory.nregions); 432 msg.size += sizeof(msg.payload.memory.padding); 433 msg.size += fd_num * sizeof(struct vhost_memory_region); 434 435 ret = vhost_user_write(dev->vhostfd, &msg, fds, fd_num); 436 if (ret < 0) 437 goto err; 438 439 return vhost_user_check_reply_ack(dev, &msg); 440 err: 441 PMD_DRV_LOG(ERR, "Failed to set memory table"); 442 return -1; 443 } 444 445 static int 446 vhost_user_set_vring(struct virtio_user_dev *dev, enum vhost_user_request req, 447 struct vhost_vring_state *state) 448 { 449 int ret; 450 struct vhost_user_msg msg = { 451 .request = req, 452 .flags = VHOST_USER_VERSION, 453 .size = sizeof(*state), 454 .payload.state = *state, 455 }; 456 457 ret = vhost_user_write(dev->vhostfd, &msg, NULL, 0); 458 if (ret < 0) { 459 PMD_DRV_LOG(ERR, "Failed to set vring state (request %d)", req); 460 return -1; 461 } 462 463 return 0; 464 } 465 466 static int 467 vhost_user_set_vring_enable(struct virtio_user_dev *dev, struct vhost_vring_state *state) 468 { 469 return vhost_user_set_vring(dev, VHOST_USER_SET_VRING_ENABLE, state); 470 } 471 472 static int 473 vhost_user_set_vring_num(struct virtio_user_dev *dev, struct vhost_vring_state *state) 474 { 475 return vhost_user_set_vring(dev, VHOST_USER_SET_VRING_NUM, state); 476 } 477 478 static int 479 vhost_user_set_vring_base(struct virtio_user_dev *dev, struct vhost_vring_state *state) 480 { 481 return vhost_user_set_vring(dev, VHOST_USER_SET_VRING_BASE, state); 482 } 483 484 static int 485 vhost_user_get_vring_base(struct virtio_user_dev *dev, struct vhost_vring_state *state) 486 { 487 int ret; 488 struct vhost_user_msg msg; 489 unsigned int index = state->index; 490 491 ret = vhost_user_set_vring(dev, VHOST_USER_GET_VRING_BASE, state); 492 if (ret < 0) { 493 PMD_DRV_LOG(ERR, "Failed to send request"); 494 goto err; 495 } 496 497 ret = vhost_user_read(dev->vhostfd, &msg); 498 if (ret < 0) { 499 PMD_DRV_LOG(ERR, "Failed to read reply"); 500 goto err; 501 } 502 503 if (msg.request != VHOST_USER_GET_VRING_BASE) { 504 PMD_DRV_LOG(ERR, "Unexpected request type (%d)", msg.request); 505 goto err; 506 } 507 508 if (msg.size != sizeof(*state)) { 509 PMD_DRV_LOG(ERR, "Unexpected payload size (%u)", msg.size); 510 goto err; 511 } 512 513 if (msg.payload.state.index != index) { 514 PMD_DRV_LOG(ERR, "Unexpected ring index (%u)", state->index); 515 goto err; 516 } 517 518 *state = msg.payload.state; 519 520 return 0; 521 err: 522 PMD_DRV_LOG(ERR, "Failed to get vring base"); 523 return -1; 524 } 525 526 static int 527 vhost_user_set_vring_file(struct virtio_user_dev *dev, enum vhost_user_request req, 528 struct vhost_vring_file *file) 529 { 530 int ret; 531 int fd = file->fd; 532 int num_fd = 0; 533 struct vhost_user_msg msg = { 534 .request = req, 535 .flags = VHOST_USER_VERSION, 536 .size = sizeof(msg.payload.u64), 537 .payload.u64 = file->index & VHOST_USER_VRING_IDX_MASK, 538 }; 539 540 if (fd >= 0) 541 num_fd++; 542 else 543 msg.payload.u64 |= VHOST_USER_VRING_NOFD_MASK; 544 545 ret = vhost_user_write(dev->vhostfd, &msg, &fd, num_fd); 546 if (ret < 0) { 547 PMD_DRV_LOG(ERR, "Failed to set vring file (request %d)", req); 548 return -1; 549 } 550 551 return 0; 552 } 553 554 static int 555 vhost_user_set_vring_call(struct virtio_user_dev *dev, struct vhost_vring_file *file) 556 { 557 return vhost_user_set_vring_file(dev, VHOST_USER_SET_VRING_CALL, file); 558 } 559 560 static int 561 vhost_user_set_vring_kick(struct virtio_user_dev *dev, struct vhost_vring_file *file) 562 { 563 return vhost_user_set_vring_file(dev, VHOST_USER_SET_VRING_KICK, file); 564 } 565 566 567 static int 568 vhost_user_set_vring_addr(struct virtio_user_dev *dev, struct vhost_vring_addr *addr) 569 { 570 int ret; 571 struct vhost_user_msg msg = { 572 .request = VHOST_USER_SET_VRING_ADDR, 573 .flags = VHOST_USER_VERSION, 574 .size = sizeof(*addr), 575 .payload.addr = *addr, 576 }; 577 578 ret = vhost_user_write(dev->vhostfd, &msg, NULL, 0); 579 if (ret < 0) { 580 PMD_DRV_LOG(ERR, "Failed to send vring addresses"); 581 return -1; 582 } 583 584 return 0; 585 } 586 587 static int 588 vhost_user_get_status(struct virtio_user_dev *dev, uint8_t *status) 589 { 590 int ret; 591 struct vhost_user_msg msg = { 592 .request = VHOST_USER_GET_STATUS, 593 .flags = VHOST_USER_VERSION, 594 }; 595 596 /* 597 * If features have not been negotiated, we don't know if the backend 598 * supports protocol features 599 */ 600 if (!(dev->status & VIRTIO_CONFIG_STATUS_FEATURES_OK)) 601 return -ENOTSUP; 602 603 /* Status protocol feature requires protocol features support */ 604 if (!(dev->device_features & (1ULL << VHOST_USER_F_PROTOCOL_FEATURES))) 605 return -ENOTSUP; 606 607 if (!(dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_STATUS))) 608 return -ENOTSUP; 609 610 ret = vhost_user_write(dev->vhostfd, &msg, NULL, 0); 611 if (ret < 0) { 612 PMD_DRV_LOG(ERR, "Failed to send request"); 613 goto err; 614 } 615 616 ret = vhost_user_read(dev->vhostfd, &msg); 617 if (ret < 0) { 618 PMD_DRV_LOG(ERR, "Failed to recv request"); 619 goto err; 620 } 621 622 if (msg.request != VHOST_USER_GET_STATUS) { 623 PMD_DRV_LOG(ERR, "Unexpected request type (%d)", msg.request); 624 goto err; 625 } 626 627 if (msg.size != sizeof(msg.payload.u64)) { 628 PMD_DRV_LOG(ERR, "Unexpected payload size (%u)", msg.size); 629 goto err; 630 } 631 632 *status = (uint8_t)msg.payload.u64; 633 634 return 0; 635 err: 636 PMD_DRV_LOG(ERR, "Failed to get device status"); 637 return -1; 638 } 639 640 static int 641 vhost_user_set_status(struct virtio_user_dev *dev, uint8_t status) 642 { 643 int ret; 644 struct vhost_user_msg msg = { 645 .request = VHOST_USER_SET_STATUS, 646 .flags = VHOST_USER_VERSION, 647 .size = sizeof(msg.payload.u64), 648 .payload.u64 = status, 649 }; 650 651 /* 652 * If features have not been negotiated, we don't know if the backend 653 * supports protocol features 654 */ 655 if (!(dev->status & VIRTIO_CONFIG_STATUS_FEATURES_OK)) 656 return -ENOTSUP; 657 658 /* Status protocol feature requires protocol features support */ 659 if (!(dev->device_features & (1ULL << VHOST_USER_F_PROTOCOL_FEATURES))) 660 return -ENOTSUP; 661 662 if (!(dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_STATUS))) 663 return -ENOTSUP; 664 665 if (dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK)) 666 msg.flags |= VHOST_USER_NEED_REPLY_MASK; 667 668 ret = vhost_user_write(dev->vhostfd, &msg, NULL, 0); 669 if (ret < 0) { 670 PMD_DRV_LOG(ERR, "Failed to send get status request"); 671 return -1; 672 } 673 674 return vhost_user_check_reply_ack(dev, &msg); 675 } 676 677 #define MAX_VIRTIO_USER_BACKLOG 1 678 static int 679 virtio_user_start_server(struct virtio_user_dev *dev, struct sockaddr_un *un) 680 { 681 int ret; 682 int flag; 683 int fd = dev->listenfd; 684 685 ret = bind(fd, (struct sockaddr *)un, sizeof(*un)); 686 if (ret < 0) { 687 PMD_DRV_LOG(ERR, "failed to bind to %s: %s; remove it and try again\n", 688 dev->path, strerror(errno)); 689 return -1; 690 } 691 ret = listen(fd, MAX_VIRTIO_USER_BACKLOG); 692 if (ret < 0) 693 return -1; 694 695 flag = fcntl(fd, F_GETFL); 696 if (fcntl(fd, F_SETFL, flag | O_NONBLOCK) < 0) { 697 PMD_DRV_LOG(ERR, "fcntl failed, %s", strerror(errno)); 698 return -1; 699 } 700 701 return 0; 702 } 703 704 /** 705 * Set up environment to talk with a vhost user backend. 706 * 707 * @return 708 * - (-1) if fail; 709 * - (0) if succeed. 710 */ 711 static int 712 vhost_user_setup(struct virtio_user_dev *dev) 713 { 714 int fd; 715 int flag; 716 struct sockaddr_un un; 717 718 fd = socket(AF_UNIX, SOCK_STREAM, 0); 719 if (fd < 0) { 720 PMD_DRV_LOG(ERR, "socket() error, %s", strerror(errno)); 721 return -1; 722 } 723 724 flag = fcntl(fd, F_GETFD); 725 if (fcntl(fd, F_SETFD, flag | FD_CLOEXEC) < 0) 726 PMD_DRV_LOG(WARNING, "fcntl failed, %s", strerror(errno)); 727 728 memset(&un, 0, sizeof(un)); 729 un.sun_family = AF_UNIX; 730 strlcpy(un.sun_path, dev->path, sizeof(un.sun_path)); 731 732 if (dev->is_server) { 733 dev->listenfd = fd; 734 if (virtio_user_start_server(dev, &un) < 0) { 735 PMD_DRV_LOG(ERR, "virtio-user startup fails in server mode"); 736 close(fd); 737 return -1; 738 } 739 dev->vhostfd = -1; 740 } else { 741 if (connect(fd, (struct sockaddr *)&un, sizeof(un)) < 0) { 742 PMD_DRV_LOG(ERR, "connect error, %s", strerror(errno)); 743 close(fd); 744 return -1; 745 } 746 dev->vhostfd = fd; 747 } 748 749 return 0; 750 } 751 752 static int 753 vhost_user_enable_queue_pair(struct virtio_user_dev *dev, 754 uint16_t pair_idx, 755 int enable) 756 { 757 int i; 758 759 if (dev->qp_enabled[pair_idx] == enable) 760 return 0; 761 762 for (i = 0; i < 2; ++i) { 763 struct vhost_vring_state state = { 764 .index = pair_idx * 2 + i, 765 .num = enable, 766 }; 767 768 if (vhost_user_set_vring_enable(dev, &state)) 769 return -1; 770 } 771 772 dev->qp_enabled[pair_idx] = enable; 773 return 0; 774 } 775 776 struct virtio_user_backend_ops virtio_ops_user = { 777 .setup = vhost_user_setup, 778 .set_owner = vhost_user_set_owner, 779 .get_features = vhost_user_get_features, 780 .set_features = vhost_user_set_features, 781 .get_protocol_features = vhost_user_get_protocol_features, 782 .set_protocol_features = vhost_user_set_protocol_features, 783 .set_memory_table = vhost_user_set_memory_table, 784 .set_vring_num = vhost_user_set_vring_num, 785 .set_vring_base = vhost_user_set_vring_base, 786 .get_vring_base = vhost_user_get_vring_base, 787 .set_vring_call = vhost_user_set_vring_call, 788 .set_vring_kick = vhost_user_set_vring_kick, 789 .set_vring_addr = vhost_user_set_vring_addr, 790 .get_status = vhost_user_get_status, 791 .set_status = vhost_user_set_status, 792 .enable_qp = vhost_user_enable_queue_pair 793 }; 794