1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #ifndef _VIRTQUEUE_H_ 6 #define _VIRTQUEUE_H_ 7 8 #include <stdint.h> 9 10 #include <rte_atomic.h> 11 #include <rte_memory.h> 12 #include <rte_mempool.h> 13 #include <rte_net.h> 14 15 #include "virtio.h" 16 #include "virtio_ring.h" 17 #include "virtio_logs.h" 18 #include "virtio_rxtx.h" 19 #include "virtio_cvq.h" 20 21 struct rte_mbuf; 22 23 #define DEFAULT_TX_FREE_THRESH 32 24 #define DEFAULT_RX_FREE_THRESH 32 25 26 #define VIRTIO_MBUF_BURST_SZ 64 27 /* 28 * Per virtio_ring.h in Linux. 29 * For virtio_pci on SMP, we don't need to order with respect to MMIO 30 * accesses through relaxed memory I/O windows, so thread_fence is 31 * sufficient. 32 * 33 * For using virtio to talk to real devices (eg. vDPA) we do need real 34 * barriers. 35 */ 36 static inline void 37 virtio_mb(uint8_t weak_barriers) 38 { 39 if (weak_barriers) 40 rte_atomic_thread_fence(rte_memory_order_seq_cst); 41 else 42 rte_mb(); 43 } 44 45 static inline void 46 virtio_rmb(uint8_t weak_barriers) 47 { 48 if (weak_barriers) 49 rte_atomic_thread_fence(rte_memory_order_acquire); 50 else 51 rte_io_rmb(); 52 } 53 54 static inline void 55 virtio_wmb(uint8_t weak_barriers) 56 { 57 if (weak_barriers) 58 rte_atomic_thread_fence(rte_memory_order_release); 59 else 60 rte_io_wmb(); 61 } 62 63 static inline uint16_t 64 virtqueue_fetch_flags_packed(struct vring_packed_desc *dp, 65 uint8_t weak_barriers) 66 { 67 uint16_t flags; 68 69 if (weak_barriers) { 70 /* x86 prefers to using rte_io_rmb over rte_atomic_load_explicit as it reports 71 * a better perf(~1.5%), which comes from the saved branch by the compiler. 72 * The if and else branch are identical on the platforms except Arm. 73 */ 74 #ifdef RTE_ARCH_ARM 75 flags = rte_atomic_load_explicit(&dp->flags, rte_memory_order_acquire); 76 #else 77 flags = dp->flags; 78 rte_io_rmb(); 79 #endif 80 } else { 81 flags = dp->flags; 82 rte_io_rmb(); 83 } 84 85 return flags; 86 } 87 88 static inline void 89 virtqueue_store_flags_packed(struct vring_packed_desc *dp, 90 uint16_t flags, uint8_t weak_barriers) 91 { 92 if (weak_barriers) { 93 /* x86 prefers to using rte_io_wmb over rte_atomic_store_explicit as it reports 94 * a better perf(~1.5%), which comes from the saved branch by the compiler. 95 * The if and else branch are identical on the platforms except Arm. 96 */ 97 #ifdef RTE_ARCH_ARM 98 rte_atomic_store_explicit(&dp->flags, flags, rte_memory_order_release); 99 #else 100 rte_io_wmb(); 101 dp->flags = flags; 102 #endif 103 } else { 104 rte_io_wmb(); 105 dp->flags = flags; 106 } 107 } 108 109 #ifdef RTE_PMD_PACKET_PREFETCH 110 #define rte_packet_prefetch(p) rte_prefetch1(p) 111 #else 112 #define rte_packet_prefetch(p) do {} while(0) 113 #endif 114 115 #define VIRTQUEUE_MAX_NAME_SZ 32 116 117 #ifdef RTE_ARCH_32 118 #define VIRTIO_MBUF_ADDR_MASK(vq) ((vq)->mbuf_addr_mask) 119 #else 120 #define VIRTIO_MBUF_ADDR_MASK(vq) UINT64_MAX 121 #endif 122 123 /** 124 * Return the IOVA (or virtual address in case of virtio-user) of mbuf 125 * data buffer. 126 * 127 * The address is firstly casted to the word size (sizeof(uintptr_t)) 128 * before casting it to uint64_t. It is then masked with the expected 129 * address length (64 bits for virtio-pci, word size for virtio-user). 130 * 131 * This is to make it work with different combination of word size (64 132 * bit and 32 bit) and virtio device (virtio-pci and virtio-user). 133 */ 134 #define VIRTIO_MBUF_ADDR(mb, vq) \ 135 ((*(uint64_t *)((uintptr_t)(mb) + (vq)->mbuf_addr_offset)) & \ 136 VIRTIO_MBUF_ADDR_MASK(vq)) 137 138 /** 139 * Return the physical address (or virtual address in case of 140 * virtio-user) of mbuf data buffer, taking care of mbuf data offset 141 */ 142 #define VIRTIO_MBUF_DATA_DMA_ADDR(mb, vq) \ 143 (VIRTIO_MBUF_ADDR(mb, vq) + (mb)->data_off) 144 145 #define VTNET_SQ_RQ_QUEUE_IDX 0 146 #define VTNET_SQ_TQ_QUEUE_IDX 1 147 #define VTNET_SQ_CQ_QUEUE_IDX 2 148 149 enum { VTNET_RQ = 0, VTNET_TQ = 1, VTNET_CQ = 2 }; 150 /** 151 * The maximum virtqueue size is 2^15. Use that value as the end of 152 * descriptor chain terminator since it will never be a valid index 153 * in the descriptor table. This is used to verify we are correctly 154 * handling vq_free_cnt. 155 */ 156 #define VQ_RING_DESC_CHAIN_END 32768 157 158 #define VIRTIO_NET_OK 0 159 #define VIRTIO_NET_ERR 1 160 161 struct vq_desc_extra { 162 void *cookie; 163 uint16_t ndescs; 164 uint16_t next; 165 }; 166 167 #define virtnet_rxq_to_vq(rxvq) container_of(rxvq, struct virtqueue, rxq) 168 #define virtnet_txq_to_vq(txvq) container_of(txvq, struct virtqueue, txq) 169 #define virtnet_cq_to_vq(cvq) container_of(cvq, struct virtqueue, cq) 170 171 struct virtqueue { 172 struct virtio_hw *hw; /**< virtio_hw structure pointer. */ 173 union { 174 struct { 175 /**< vring keeping desc, used and avail */ 176 struct vring ring; 177 } vq_split; 178 179 struct { 180 /**< vring keeping descs and events */ 181 struct vring_packed ring; 182 bool used_wrap_counter; 183 uint16_t cached_flags; /**< cached flags for descs */ 184 uint16_t event_flags_shadow; 185 } vq_packed; 186 }; 187 188 uint16_t vq_used_cons_idx; /**< last consumed descriptor */ 189 uint16_t vq_nentries; /**< vring desc numbers */ 190 uint16_t vq_free_cnt; /**< num of desc available */ 191 uint16_t vq_avail_idx; /**< sync until needed */ 192 uint16_t vq_free_thresh; /**< free threshold */ 193 194 /** 195 * Head of the free chain in the descriptor table. If 196 * there are no free descriptors, this will be set to 197 * VQ_RING_DESC_CHAIN_END. 198 */ 199 uint16_t vq_desc_head_idx; 200 uint16_t vq_desc_tail_idx; 201 uint16_t vq_queue_index; /**< PCI queue index */ 202 203 void *vq_ring_virt_mem; /**< linear address of vring*/ 204 unsigned int vq_ring_size; 205 uint16_t mbuf_addr_offset; 206 uint64_t mbuf_addr_mask; 207 208 union { 209 struct virtnet_rx rxq; 210 struct virtnet_tx txq; 211 struct virtnet_ctl cq; 212 }; 213 214 const struct rte_memzone *mz; /**< mem zone to populate ring. */ 215 rte_iova_t vq_ring_mem; /**< physical address of vring, 216 * or virtual address for virtio_user. */ 217 218 uint16_t *notify_addr; 219 struct vq_desc_extra vq_descx[]; 220 }; 221 222 /* If multiqueue is provided by host, then we support it. */ 223 #define VIRTIO_NET_CTRL_MQ 4 224 225 #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET 0 226 #define VIRTIO_NET_CTRL_MQ_RSS_CONFIG 1 227 228 #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1 229 #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000 230 231 /** 232 * This is the first element of the scatter-gather list. If you don't 233 * specify GSO or CSUM features, you can simply ignore the header. 234 */ 235 struct virtio_net_hdr { 236 #define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 /**< Use csum_start,csum_offset*/ 237 #define VIRTIO_NET_HDR_F_DATA_VALID 2 /**< Checksum is valid */ 238 uint8_t flags; 239 #define VIRTIO_NET_HDR_GSO_NONE 0 /**< Not a GSO frame */ 240 #define VIRTIO_NET_HDR_GSO_TCPV4 1 /**< GSO frame, IPv4 TCP (TSO) */ 241 #define VIRTIO_NET_HDR_GSO_UDP 3 /**< GSO frame, IPv4 UDP (UFO) */ 242 #define VIRTIO_NET_HDR_GSO_TCPV6 4 /**< GSO frame, IPv6 TCP */ 243 #define VIRTIO_NET_HDR_GSO_ECN 0x80 /**< TCP has ECN set */ 244 uint8_t gso_type; 245 uint16_t hdr_len; /**< Ethernet + IP + tcp/udp hdrs */ 246 uint16_t gso_size; /**< Bytes to append to hdr_len per frame */ 247 uint16_t csum_start; /**< Position to start checksumming from */ 248 uint16_t csum_offset; /**< Offset after that to place checksum */ 249 }; 250 251 /** 252 * This is the version of the header to use when the MRG_RXBUF 253 * feature has been negotiated. 254 */ 255 struct virtio_net_hdr_mrg_rxbuf { 256 struct virtio_net_hdr hdr; 257 uint16_t num_buffers; /**< Number of merged rx buffers */ 258 }; 259 260 /* Region reserved to allow for transmit header and indirect ring */ 261 #define VIRTIO_MAX_TX_INDIRECT 8 262 struct virtio_tx_region { 263 struct virtio_net_hdr_mrg_rxbuf tx_hdr; 264 union __rte_aligned(16) { 265 struct vring_desc tx_indir[VIRTIO_MAX_TX_INDIRECT]; 266 struct vring_packed_desc 267 tx_packed_indir[VIRTIO_MAX_TX_INDIRECT]; 268 }; 269 }; 270 271 static inline int 272 desc_is_used(struct vring_packed_desc *desc, struct virtqueue *vq) 273 { 274 uint16_t used, avail, flags; 275 276 flags = virtqueue_fetch_flags_packed(desc, vq->hw->weak_barriers); 277 used = !!(flags & VRING_PACKED_DESC_F_USED); 278 avail = !!(flags & VRING_PACKED_DESC_F_AVAIL); 279 280 return avail == used && used == vq->vq_packed.used_wrap_counter; 281 } 282 283 static inline void 284 vring_desc_init_packed(struct virtqueue *vq, int n) 285 { 286 int i; 287 for (i = 0; i < n - 1; i++) { 288 vq->vq_packed.ring.desc[i].id = i; 289 vq->vq_descx[i].next = i + 1; 290 } 291 vq->vq_packed.ring.desc[i].id = i; 292 vq->vq_descx[i].next = VQ_RING_DESC_CHAIN_END; 293 } 294 295 /* Chain all the descriptors in the ring with an END */ 296 static inline void 297 vring_desc_init_split(struct vring_desc *dp, uint16_t n) 298 { 299 uint16_t i; 300 301 for (i = 0; i < n - 1; i++) 302 dp[i].next = (uint16_t)(i + 1); 303 dp[i].next = VQ_RING_DESC_CHAIN_END; 304 } 305 306 static inline void 307 vring_desc_init_indirect_packed(struct vring_packed_desc *dp, int n) 308 { 309 int i; 310 for (i = 0; i < n; i++) { 311 dp[i].id = (uint16_t)i; 312 dp[i].flags = VRING_DESC_F_WRITE; 313 } 314 } 315 316 /** 317 * Tell the backend not to interrupt us. Implementation for packed virtqueues. 318 */ 319 static inline void 320 virtqueue_disable_intr_packed(struct virtqueue *vq) 321 { 322 if (vq->vq_packed.event_flags_shadow != RING_EVENT_FLAGS_DISABLE) { 323 vq->vq_packed.event_flags_shadow = RING_EVENT_FLAGS_DISABLE; 324 vq->vq_packed.ring.driver->desc_event_flags = 325 vq->vq_packed.event_flags_shadow; 326 } 327 } 328 329 /** 330 * Tell the backend not to interrupt us. Implementation for split virtqueues. 331 */ 332 static inline void 333 virtqueue_disable_intr_split(struct virtqueue *vq) 334 { 335 vq->vq_split.ring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; 336 } 337 338 /** 339 * Tell the backend not to interrupt us. 340 */ 341 static inline void 342 virtqueue_disable_intr(struct virtqueue *vq) 343 { 344 if (virtio_with_packed_queue(vq->hw)) 345 virtqueue_disable_intr_packed(vq); 346 else 347 virtqueue_disable_intr_split(vq); 348 } 349 350 /** 351 * Tell the backend to interrupt. Implementation for packed virtqueues. 352 */ 353 static inline void 354 virtqueue_enable_intr_packed(struct virtqueue *vq) 355 { 356 if (vq->vq_packed.event_flags_shadow == RING_EVENT_FLAGS_DISABLE) { 357 vq->vq_packed.event_flags_shadow = RING_EVENT_FLAGS_ENABLE; 358 vq->vq_packed.ring.driver->desc_event_flags = 359 vq->vq_packed.event_flags_shadow; 360 } 361 } 362 363 /** 364 * Tell the backend to interrupt. Implementation for split virtqueues. 365 */ 366 static inline void 367 virtqueue_enable_intr_split(struct virtqueue *vq) 368 { 369 vq->vq_split.ring.avail->flags &= (~VRING_AVAIL_F_NO_INTERRUPT); 370 } 371 372 /** 373 * Tell the backend to interrupt us. 374 */ 375 static inline void 376 virtqueue_enable_intr(struct virtqueue *vq) 377 { 378 if (virtio_with_packed_queue(vq->hw)) 379 virtqueue_enable_intr_packed(vq); 380 else 381 virtqueue_enable_intr_split(vq); 382 } 383 384 /** 385 * Get all mbufs to be freed. 386 */ 387 struct rte_mbuf *virtqueue_detach_unused(struct virtqueue *vq); 388 389 /* Flush the elements in the used ring. */ 390 void virtqueue_rxvq_flush(struct virtqueue *vq); 391 392 int virtqueue_rxvq_reset_packed(struct virtqueue *vq); 393 394 int virtqueue_txvq_reset_packed(struct virtqueue *vq); 395 396 void virtqueue_txq_indirect_headers_init(struct virtqueue *vq); 397 398 struct virtqueue *virtqueue_alloc(struct virtio_hw *hw, uint16_t index, 399 uint16_t num, int type, int node, const char *name); 400 401 void virtqueue_free(struct virtqueue *vq); 402 403 static inline int 404 virtqueue_full(const struct virtqueue *vq) 405 { 406 return vq->vq_free_cnt == 0; 407 } 408 409 static inline int 410 virtio_get_queue_type(struct virtio_hw *hw, uint16_t vq_idx) 411 { 412 if (vq_idx == hw->max_queue_pairs * 2) 413 return VTNET_CQ; 414 else if (vq_idx % 2 == 0) 415 return VTNET_RQ; 416 else 417 return VTNET_TQ; 418 } 419 420 /* virtqueue_nused has load-acquire or rte_io_rmb insed */ 421 static inline uint16_t 422 virtqueue_nused(const struct virtqueue *vq) 423 { 424 uint16_t idx; 425 426 if (vq->hw->weak_barriers) { 427 /** 428 * x86 prefers to using rte_smp_rmb over rte_atomic_load_explicit as it 429 * reports a slightly better perf, which comes from the saved 430 * branch by the compiler. 431 * The if and else branches are identical with the smp and io 432 * barriers both defined as compiler barriers on x86. 433 */ 434 #ifdef RTE_ARCH_X86_64 435 idx = vq->vq_split.ring.used->idx; 436 rte_smp_rmb(); 437 #else 438 idx = rte_atomic_load_explicit(&(vq)->vq_split.ring.used->idx, 439 rte_memory_order_acquire); 440 #endif 441 } else { 442 idx = vq->vq_split.ring.used->idx; 443 rte_io_rmb(); 444 } 445 return idx - vq->vq_used_cons_idx; 446 } 447 448 void vq_ring_free_chain(struct virtqueue *vq, uint16_t desc_idx); 449 void vq_ring_free_chain_packed(struct virtqueue *vq, uint16_t used_idx); 450 void vq_ring_free_inorder(struct virtqueue *vq, uint16_t desc_idx, 451 uint16_t num); 452 453 static inline void 454 vq_update_avail_idx(struct virtqueue *vq) 455 { 456 if (vq->hw->weak_barriers) { 457 /* x86 prefers to using rte_smp_wmb over rte_atomic_store_explicit as 458 * it reports a slightly better perf, which comes from the 459 * saved branch by the compiler. 460 * The if and else branches are identical with the smp and 461 * io barriers both defined as compiler barriers on x86. 462 */ 463 #ifdef RTE_ARCH_X86_64 464 rte_smp_wmb(); 465 vq->vq_split.ring.avail->idx = vq->vq_avail_idx; 466 #else 467 rte_atomic_store_explicit(&vq->vq_split.ring.avail->idx, 468 vq->vq_avail_idx, rte_memory_order_release); 469 #endif 470 } else { 471 rte_io_wmb(); 472 vq->vq_split.ring.avail->idx = vq->vq_avail_idx; 473 } 474 } 475 476 static inline void 477 vq_update_avail_ring(struct virtqueue *vq, uint16_t desc_idx) 478 { 479 uint16_t avail_idx; 480 /* 481 * Place the head of the descriptor chain into the next slot and make 482 * it usable to the host. The chain is made available now rather than 483 * deferring to virtqueue_notify() in the hopes that if the host is 484 * currently running on another CPU, we can keep it processing the new 485 * descriptor. 486 */ 487 avail_idx = (uint16_t)(vq->vq_avail_idx & (vq->vq_nentries - 1)); 488 if (unlikely(vq->vq_split.ring.avail->ring[avail_idx] != desc_idx)) 489 vq->vq_split.ring.avail->ring[avail_idx] = desc_idx; 490 vq->vq_avail_idx++; 491 } 492 493 static inline int 494 virtqueue_kick_prepare(struct virtqueue *vq) 495 { 496 /* 497 * Ensure updated avail->idx is visible to vhost before reading 498 * the used->flags. 499 */ 500 virtio_mb(vq->hw->weak_barriers); 501 return !(vq->vq_split.ring.used->flags & VRING_USED_F_NO_NOTIFY); 502 } 503 504 static inline int 505 virtqueue_kick_prepare_packed(struct virtqueue *vq) 506 { 507 uint16_t flags; 508 509 /* 510 * Ensure updated data is visible to vhost before reading the flags. 511 */ 512 virtio_mb(vq->hw->weak_barriers); 513 flags = vq->vq_packed.ring.device->desc_event_flags; 514 515 return flags != RING_EVENT_FLAGS_DISABLE; 516 } 517 518 /* 519 * virtqueue_kick_prepare*() or the virtio_wmb() should be called 520 * before this function to be sure that all the data is visible to vhost. 521 */ 522 static inline void 523 virtqueue_notify(struct virtqueue *vq) 524 { 525 VIRTIO_OPS(vq->hw)->notify_queue(vq->hw, vq); 526 } 527 528 #ifdef RTE_LIBRTE_VIRTIO_DEBUG_DUMP 529 #define VIRTQUEUE_DUMP(vq) do { \ 530 uint16_t used_idx, nused; \ 531 used_idx = rte_atomic_load_explicit(&(vq)->vq_split.ring.used->idx, \ 532 rte_memory_order_relaxed); \ 533 nused = (uint16_t)(used_idx - (vq)->vq_used_cons_idx); \ 534 if (virtio_with_packed_queue((vq)->hw)) { \ 535 PMD_INIT_LOG(DEBUG, \ 536 "VQ: - size=%d; free=%d; used_cons_idx=%d; avail_idx=%d;" \ 537 " cached_flags=0x%x; used_wrap_counter=%d", \ 538 (vq)->vq_nentries, (vq)->vq_free_cnt, (vq)->vq_used_cons_idx, \ 539 (vq)->vq_avail_idx, (vq)->vq_packed.cached_flags, \ 540 (vq)->vq_packed.used_wrap_counter); \ 541 break; \ 542 } \ 543 PMD_INIT_LOG(DEBUG, \ 544 "VQ: - size=%d; free=%d; used=%d; desc_head_idx=%d;" \ 545 " avail.idx=%d; used_cons_idx=%d; used.idx=%d;" \ 546 " avail.flags=0x%x; used.flags=0x%x", \ 547 (vq)->vq_nentries, (vq)->vq_free_cnt, nused, (vq)->vq_desc_head_idx, \ 548 (vq)->vq_split.ring.avail->idx, (vq)->vq_used_cons_idx, \ 549 rte_atomic_load_explicit(&(vq)->vq_split.ring.used->idx, rte_memory_order_relaxed), \ 550 (vq)->vq_split.ring.avail->flags, (vq)->vq_split.ring.used->flags); \ 551 } while (0) 552 #else 553 #define VIRTQUEUE_DUMP(vq) do { } while (0) 554 #endif 555 556 /* avoid write operation when necessary, to lessen cache issues */ 557 #define ASSIGN_UNLESS_EQUAL(var, val) do { \ 558 typeof(var) *const var_ = &(var); \ 559 typeof(val) const val_ = (val); \ 560 if (*var_ != val_) \ 561 *var_ = val_; \ 562 } while (0) 563 564 #define virtqueue_clear_net_hdr(hdr) do { \ 565 typeof(hdr) hdr_ = (hdr); \ 566 ASSIGN_UNLESS_EQUAL((hdr_)->csum_start, 0); \ 567 ASSIGN_UNLESS_EQUAL((hdr_)->csum_offset, 0); \ 568 ASSIGN_UNLESS_EQUAL((hdr_)->flags, 0); \ 569 ASSIGN_UNLESS_EQUAL((hdr_)->gso_type, 0); \ 570 ASSIGN_UNLESS_EQUAL((hdr_)->gso_size, 0); \ 571 ASSIGN_UNLESS_EQUAL((hdr_)->hdr_len, 0); \ 572 } while (0) 573 574 static inline void 575 virtqueue_xmit_offload(struct virtio_net_hdr *hdr, struct rte_mbuf *cookie) 576 { 577 uint64_t csum_l4 = cookie->ol_flags & RTE_MBUF_F_TX_L4_MASK; 578 uint16_t o_l23_len = (cookie->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) ? 579 cookie->outer_l2_len + cookie->outer_l3_len : 0; 580 581 if (cookie->ol_flags & RTE_MBUF_F_TX_TCP_SEG) 582 csum_l4 |= RTE_MBUF_F_TX_TCP_CKSUM; 583 584 switch (csum_l4) { 585 case RTE_MBUF_F_TX_UDP_CKSUM: 586 hdr->csum_start = o_l23_len + cookie->l2_len + cookie->l3_len; 587 hdr->csum_offset = offsetof(struct rte_udp_hdr, dgram_cksum); 588 hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; 589 break; 590 591 case RTE_MBUF_F_TX_TCP_CKSUM: 592 hdr->csum_start = o_l23_len + cookie->l2_len + cookie->l3_len; 593 hdr->csum_offset = offsetof(struct rte_tcp_hdr, cksum); 594 hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; 595 break; 596 597 default: 598 ASSIGN_UNLESS_EQUAL(hdr->csum_start, 0); 599 ASSIGN_UNLESS_EQUAL(hdr->csum_offset, 0); 600 ASSIGN_UNLESS_EQUAL(hdr->flags, 0); 601 break; 602 } 603 604 /* TCP Segmentation Offload */ 605 if (cookie->ol_flags & RTE_MBUF_F_TX_TCP_SEG) { 606 hdr->gso_type = (cookie->ol_flags & RTE_MBUF_F_TX_IPV6) ? 607 VIRTIO_NET_HDR_GSO_TCPV6 : 608 VIRTIO_NET_HDR_GSO_TCPV4; 609 hdr->gso_size = cookie->tso_segsz; 610 hdr->hdr_len = o_l23_len + cookie->l2_len + cookie->l3_len + 611 cookie->l4_len; 612 } else { 613 ASSIGN_UNLESS_EQUAL(hdr->gso_type, 0); 614 ASSIGN_UNLESS_EQUAL(hdr->gso_size, 0); 615 ASSIGN_UNLESS_EQUAL(hdr->hdr_len, 0); 616 } 617 } 618 619 static inline void 620 virtqueue_enqueue_xmit_packed(struct virtnet_tx *txvq, struct rte_mbuf *cookie, 621 uint16_t needed, int use_indirect, int can_push, 622 int in_order) 623 { 624 struct virtio_tx_region *txr = txvq->hdr_mz->addr; 625 struct vq_desc_extra *dxp; 626 struct virtqueue *vq = virtnet_txq_to_vq(txvq); 627 struct vring_packed_desc *start_dp, *head_dp; 628 uint16_t idx, id, head_idx, head_flags; 629 int16_t head_size = vq->hw->vtnet_hdr_size; 630 struct virtio_net_hdr *hdr; 631 uint16_t prev; 632 bool prepend_header = false; 633 uint16_t seg_num = cookie->nb_segs; 634 635 id = in_order ? vq->vq_avail_idx : vq->vq_desc_head_idx; 636 637 dxp = &vq->vq_descx[id]; 638 dxp->ndescs = needed; 639 dxp->cookie = cookie; 640 641 head_idx = vq->vq_avail_idx; 642 idx = head_idx; 643 prev = head_idx; 644 start_dp = vq->vq_packed.ring.desc; 645 646 head_dp = &vq->vq_packed.ring.desc[idx]; 647 head_flags = cookie->next ? VRING_DESC_F_NEXT : 0; 648 head_flags |= vq->vq_packed.cached_flags; 649 650 if (can_push) { 651 /* prepend cannot fail, checked by caller */ 652 hdr = rte_pktmbuf_mtod_offset(cookie, struct virtio_net_hdr *, 653 -head_size); 654 prepend_header = true; 655 656 /* if offload disabled, it is not zeroed below, do it now */ 657 if (!vq->hw->has_tx_offload) 658 virtqueue_clear_net_hdr(hdr); 659 } else if (use_indirect) { 660 /* setup tx ring slot to point to indirect 661 * descriptor list stored in reserved region. 662 * 663 * the first slot in indirect ring is already preset 664 * to point to the header in reserved region 665 */ 666 start_dp[idx].addr = txvq->hdr_mem + RTE_PTR_DIFF(&txr[idx].tx_packed_indir, txr); 667 start_dp[idx].len = (seg_num + 1) * sizeof(struct vring_packed_desc); 668 /* Packed descriptor id needs to be restored when inorder. */ 669 if (in_order) 670 start_dp[idx].id = idx; 671 /* reset flags for indirect desc */ 672 head_flags = VRING_DESC_F_INDIRECT; 673 head_flags |= vq->vq_packed.cached_flags; 674 hdr = (struct virtio_net_hdr *)&txr[idx].tx_hdr; 675 676 /* loop below will fill in rest of the indirect elements */ 677 start_dp = txr[idx].tx_packed_indir; 678 idx = 1; 679 } else { 680 /* setup first tx ring slot to point to header 681 * stored in reserved region. 682 */ 683 start_dp[idx].addr = txvq->hdr_mem + RTE_PTR_DIFF(&txr[idx].tx_hdr, txr); 684 start_dp[idx].len = vq->hw->vtnet_hdr_size; 685 head_flags |= VRING_DESC_F_NEXT; 686 hdr = (struct virtio_net_hdr *)&txr[idx].tx_hdr; 687 idx++; 688 if (idx >= vq->vq_nentries) { 689 idx -= vq->vq_nentries; 690 vq->vq_packed.cached_flags ^= 691 VRING_PACKED_DESC_F_AVAIL_USED; 692 } 693 } 694 695 if (vq->hw->has_tx_offload) 696 virtqueue_xmit_offload(hdr, cookie); 697 698 do { 699 uint16_t flags; 700 701 start_dp[idx].addr = VIRTIO_MBUF_DATA_DMA_ADDR(cookie, vq); 702 start_dp[idx].len = cookie->data_len; 703 if (prepend_header) { 704 start_dp[idx].addr -= head_size; 705 start_dp[idx].len += head_size; 706 prepend_header = false; 707 } 708 709 if (likely(idx != head_idx)) { 710 flags = cookie->next ? VRING_DESC_F_NEXT : 0; 711 flags |= vq->vq_packed.cached_flags; 712 start_dp[idx].flags = flags; 713 } 714 prev = idx; 715 idx++; 716 if (idx >= vq->vq_nentries) { 717 idx -= vq->vq_nentries; 718 vq->vq_packed.cached_flags ^= 719 VRING_PACKED_DESC_F_AVAIL_USED; 720 } 721 } while ((cookie = cookie->next) != NULL); 722 723 start_dp[prev].id = id; 724 725 if (use_indirect) { 726 idx = head_idx; 727 if (++idx >= vq->vq_nentries) { 728 idx -= vq->vq_nentries; 729 vq->vq_packed.cached_flags ^= 730 VRING_PACKED_DESC_F_AVAIL_USED; 731 } 732 } 733 734 vq->vq_free_cnt = (uint16_t)(vq->vq_free_cnt - needed); 735 vq->vq_avail_idx = idx; 736 737 if (!in_order) { 738 vq->vq_desc_head_idx = dxp->next; 739 if (vq->vq_desc_head_idx == VQ_RING_DESC_CHAIN_END) 740 vq->vq_desc_tail_idx = VQ_RING_DESC_CHAIN_END; 741 } 742 743 virtqueue_store_flags_packed(head_dp, head_flags, 744 vq->hw->weak_barriers); 745 } 746 747 static void 748 vq_ring_free_id_packed(struct virtqueue *vq, uint16_t id) 749 { 750 struct vq_desc_extra *dxp; 751 752 dxp = &vq->vq_descx[id]; 753 vq->vq_free_cnt += dxp->ndescs; 754 755 if (vq->vq_desc_tail_idx == VQ_RING_DESC_CHAIN_END) 756 vq->vq_desc_head_idx = id; 757 else 758 vq->vq_descx[vq->vq_desc_tail_idx].next = id; 759 760 vq->vq_desc_tail_idx = id; 761 dxp->next = VQ_RING_DESC_CHAIN_END; 762 } 763 764 static void 765 virtio_xmit_cleanup_inorder_packed(struct virtqueue *vq, uint16_t num) 766 { 767 uint16_t used_idx, id, curr_id, free_cnt = 0; 768 uint16_t size = vq->vq_nentries; 769 struct vring_packed_desc *desc = vq->vq_packed.ring.desc; 770 struct vq_desc_extra *dxp; 771 int nb = num; 772 773 used_idx = vq->vq_used_cons_idx; 774 /* desc_is_used has a load-acquire or rte_io_rmb inside 775 * and wait for used desc in virtqueue. 776 */ 777 while (nb > 0 && desc_is_used(&desc[used_idx], vq)) { 778 id = desc[used_idx].id; 779 do { 780 curr_id = used_idx; 781 dxp = &vq->vq_descx[used_idx]; 782 used_idx += dxp->ndescs; 783 free_cnt += dxp->ndescs; 784 nb -= dxp->ndescs; 785 if (used_idx >= size) { 786 used_idx -= size; 787 vq->vq_packed.used_wrap_counter ^= 1; 788 } 789 if (dxp->cookie != NULL) { 790 rte_pktmbuf_free(dxp->cookie); 791 dxp->cookie = NULL; 792 } 793 } while (curr_id != id); 794 } 795 vq->vq_used_cons_idx = used_idx; 796 vq->vq_free_cnt += free_cnt; 797 } 798 799 static void 800 virtio_xmit_cleanup_normal_packed(struct virtqueue *vq, uint16_t num) 801 { 802 uint16_t used_idx, id; 803 uint16_t size = vq->vq_nentries; 804 struct vring_packed_desc *desc = vq->vq_packed.ring.desc; 805 struct vq_desc_extra *dxp; 806 807 used_idx = vq->vq_used_cons_idx; 808 /* desc_is_used has a load-acquire or rte_io_rmb inside 809 * and wait for used desc in virtqueue. 810 */ 811 while (num-- && desc_is_used(&desc[used_idx], vq)) { 812 id = desc[used_idx].id; 813 dxp = &vq->vq_descx[id]; 814 vq->vq_used_cons_idx += dxp->ndescs; 815 if (vq->vq_used_cons_idx >= size) { 816 vq->vq_used_cons_idx -= size; 817 vq->vq_packed.used_wrap_counter ^= 1; 818 } 819 vq_ring_free_id_packed(vq, id); 820 if (dxp->cookie != NULL) { 821 rte_pktmbuf_free(dxp->cookie); 822 dxp->cookie = NULL; 823 } 824 used_idx = vq->vq_used_cons_idx; 825 } 826 } 827 828 /* Cleanup from completed transmits. */ 829 static inline void 830 virtio_xmit_cleanup_packed(struct virtqueue *vq, uint16_t num, int in_order) 831 { 832 if (in_order) 833 virtio_xmit_cleanup_inorder_packed(vq, num); 834 else 835 virtio_xmit_cleanup_normal_packed(vq, num); 836 } 837 838 static inline void 839 virtio_xmit_cleanup(struct virtqueue *vq, uint16_t num) 840 { 841 uint16_t i, used_idx, desc_idx; 842 for (i = 0; i < num; i++) { 843 struct vring_used_elem *uep; 844 struct vq_desc_extra *dxp; 845 846 used_idx = (uint16_t)(vq->vq_used_cons_idx & 847 (vq->vq_nentries - 1)); 848 uep = &vq->vq_split.ring.used->ring[used_idx]; 849 850 desc_idx = (uint16_t)uep->id; 851 dxp = &vq->vq_descx[desc_idx]; 852 vq->vq_used_cons_idx++; 853 vq_ring_free_chain(vq, desc_idx); 854 855 if (dxp->cookie != NULL) { 856 rte_pktmbuf_free(dxp->cookie); 857 dxp->cookie = NULL; 858 } 859 } 860 } 861 862 /* Cleanup from completed inorder transmits. */ 863 static __rte_always_inline void 864 virtio_xmit_cleanup_inorder(struct virtqueue *vq, uint16_t num) 865 { 866 uint16_t i, idx = vq->vq_used_cons_idx; 867 int16_t free_cnt = 0; 868 struct vq_desc_extra *dxp = NULL; 869 870 if (unlikely(num == 0)) 871 return; 872 873 for (i = 0; i < num; i++) { 874 dxp = &vq->vq_descx[idx++ & (vq->vq_nentries - 1)]; 875 free_cnt += dxp->ndescs; 876 if (dxp->cookie != NULL) { 877 rte_pktmbuf_free(dxp->cookie); 878 dxp->cookie = NULL; 879 } 880 } 881 882 vq->vq_free_cnt += free_cnt; 883 vq->vq_used_cons_idx = idx; 884 } 885 #endif /* _VIRTQUEUE_H_ */ 886