-start of the data buffer (``buf_iova``). Thus the address is adjusted
-by ``addr_offset`` value in order to get the address of ``rearm_data``
-member of ``rte_mbuf``. That way both the packet data and metadata can
-be copied in a single operation. This method can be used because the mbufs
-are direct mbufs allocated by the apps. If another app uses external buffers,
-or indirect mbufs, then multiple copy operations must be used.
-
-.. code-block:: c
-
- static uint32_t
- ioat_enqueue_packets(struct rte_mbuf **pkts,
- uint32_t nb_rx, uint16_t dev_id)
- {
- int ret;
- uint32_t i;
- struct rte_mbuf *pkts_copy[MAX_PKT_BURST];
-
- const uint64_t addr_offset = RTE_PTR_DIFF(pkts[0]->buf_addr,
- &pkts[0]->rearm_data);
-
- ret = rte_mempool_get_bulk(ioat_pktmbuf_pool,
- (void *)pkts_copy, nb_rx);
-
- if (unlikely(ret < 0))
- rte_exit(EXIT_FAILURE, "Unable to allocate memory.\n");
-
- for (i = 0; i < nb_rx; i++) {
- /* Perform data copy */
- ret = rte_ioat_enqueue_copy(dev_id,
- pkts[i]->buf_iova
- - addr_offset,
- pkts_copy[i]->buf_iova
- - addr_offset,
- rte_pktmbuf_data_len(pkts[i])
- + addr_offset,
- (uintptr_t)pkts[i],
- (uintptr_t)pkts_copy[i],
- 0 /* nofence */);
-
- if (ret != 1)
- break;
- }
-
- ret = i;
- /* Free any not enqueued packets. */
- rte_mempool_put_bulk(ioat_pktmbuf_pool, (void *)&pkts[i], nb_rx - i);
- rte_mempool_put_bulk(ioat_pktmbuf_pool, (void *)&pkts_copy[i],
- nb_rx - i);
-
- return ret;
- }
-
-
-All completed copies are processed by ``ioat_tx_port()`` function. When using
-hardware copy mode the function invokes ``rte_ioat_completed_copies()``
-on each assigned IOAT channel to gather copied packets. If software copy
-mode is used the function dequeues copied packets from the rte_ring. Then each
-packet MAC address is changed if it was enabled. After that copies are sent
-in burst mode using `` rte_eth_tx_burst()``.
-
-
-.. code-block:: c
-
- /* Transmit packets from IOAT rawdev/rte_ring for one port. */
- static void
- ioat_tx_port(struct rxtx_port_config *tx_config)
- {
- uint32_t i, j, nb_dq = 0;
- struct rte_mbuf *mbufs_src[MAX_PKT_BURST];
- struct rte_mbuf *mbufs_dst[MAX_PKT_BURST];
-
- for (i = 0; i < tx_config->nb_queues; i++) {
- if (copy_mode == COPY_MODE_IOAT_NUM) {
- /* Deque the mbufs from IOAT device. */
- nb_dq = rte_ioat_completed_copies(
- tx_config->ioat_ids[i], MAX_PKT_BURST,
- (void *)mbufs_src, (void *)mbufs_dst);
- } else {
- /* Deque the mbufs from rx_to_tx_ring. */
- nb_dq = rte_ring_dequeue_burst(
- tx_config->rx_to_tx_ring, (void *)mbufs_dst,
- MAX_PKT_BURST, NULL);
- }
-
- if (nb_dq == 0)
- return;
-
- if (copy_mode == COPY_MODE_IOAT_NUM)
- rte_mempool_put_bulk(ioat_pktmbuf_pool,
- (void *)mbufs_src, nb_dq);
-
- /* Update macs if enabled */
- if (mac_updating) {
- for (j = 0; j < nb_dq; j++)
- update_mac_addrs(mbufs_dst[j],
- tx_config->rxtx_port);
- }
-
- const uint16_t nb_tx = rte_eth_tx_burst(
- tx_config->rxtx_port, 0,
- (void *)mbufs_dst, nb_dq);
-
- port_statistics.tx[tx_config->rxtx_port] += nb_tx;
-
- /* Free any unsent packets. */
- if (unlikely(nb_tx < nb_dq))
- rte_mempool_put_bulk(ioat_pktmbuf_pool,
- (void *)&mbufs_dst[nb_tx],
- nb_dq - nb_tx);
- }
- }
+start of the data buffer (``buf_iova``). Thus the ``rte_pktmbuf_iova()`` API is
+used to get the address of the start of the data within the mbuf.
+
+.. literalinclude:: ../../../examples/ioat/ioatfwd.c
+ :language: c
+ :start-after: Receive packets on one port and enqueue to IOAT rawdev or rte_ring. 8<
+ :end-before: >8 End of receive packets on one port and enqueue to IOAT rawdev or rte_ring.
+ :dedent: 0
+
+
+Once the copies have been completed (this includes gathering the completions in
+HW copy mode), the copied packets are enqueued to the ``rx_to_tx_ring``, which
+is used to pass the packets to the TX function.
+
+All completed copies are processed by ``ioat_tx_port()`` function. This function
+dequeues copied packets from the ``rx_to_tx_ring``. Then each packet MAC address is changed
+if it was enabled. After that copies are sent in burst mode using ``rte_eth_tx_burst()``.
+
+
+.. literalinclude:: ../../../examples/ioat/ioatfwd.c
+ :language: c
+ :start-after: Transmit packets from IOAT rawdev/rte_ring for one port. 8<
+ :end-before: >8 End of transmitting packets from IOAT.
+ :dedent: 0