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