Mohsin Kazmi | 7869985 | 2023-05-05 12:32:59 +0000 | [diff] [blame] | 1 | .. _TX_Queue_doc: |
| 2 | |
| 3 | Transmit Queues |
| 4 | =============== |
| 5 | |
| 6 | Overview |
| 7 | ________ |
| 8 | |
| 9 | VPP implements Transmit queues infra to access and manage them. It provides |
| 10 | common registration functions to register or unregister interfaces’ transmit |
| 11 | queues. It also provides functions for queues placement on given thread(s). |
| 12 | |
| 13 | The TXQ Infrastructure |
| 14 | _______________________ |
| 15 | |
| 16 | Infra registers each queue using a unique key which is formed by concatenating |
| 17 | the hardware interface index ``hw_if_index`` and unique queue identifier for |
| 18 | given interface ``queue_id``. As a result of registration of queue, infra |
| 19 | returns back a unique global ``queue_index`` which can be used by driver to |
| 20 | access that queue later. |
| 21 | |
| 22 | Interface output node uses pre-computed ``output_node_thread_runtime`` data |
| 23 | which provides essential information related to queue placements on given |
| 24 | thread of given interface. Transmit queue infra implements an algorithm to |
| 25 | pre-compute this information. It also pre-computes scalar arguments of frame |
| 26 | ``vnet_hw_if_tx_frame_t``. It also pre-calculates a ``lookup_table`` for |
| 27 | thread if there are multiple transmit queues are placed on that thread. |
| 28 | Interface drivers call ``vnet_hw_if_update_runtime_data()`` to execute that |
| 29 | algorithm after registering the transmit queues to TXQ infra. |
| 30 | |
| 31 | The algorithm makes the copy of existing runtime data and iterate through them |
| 32 | for each vpp main and worker thread. In each iteration, algorithm loop through |
| 33 | all the tx queues of given interface to fill the information in the frame data |
| 34 | structure ``vnet_hw_if_tx_frame_t``. Algorithm also updates the information |
| 35 | related to number of transmit queues of given interface on given vpp thread in |
| 36 | data structure ``output_node_thread_runtime``. As a consequence of any update |
| 37 | to the copy, triggers the function to update the actual working copy by taking |
| 38 | the worker barrier and free the old copy of ``output_node_thread_runtime``. |
| 39 | |
| 40 | Multi-TXQ infra |
| 41 | ^^^^^^^^^^^^^^^ |
| 42 | |
| 43 | Interface output node uses packet flow hash using hash infra in case of multi-txq |
| 44 | on given thread. Each hardware interface class contains type of the hash required |
| 45 | for interfaces from that hardware interface class i.e. ethernet interface hardware |
| 46 | class contains type ``VNET_HASH_FN_TYPE_ETHERNET``. Though, the hash function |
| 47 | itself is contained by hardware interface data structure of given interface. Default |
| 48 | hashing function is selected upon interface creation based on priority. User can |
| 49 | configure a different hash to an interface for multi-txq use case. |
| 50 | |
| 51 | Interface output node uses packet flow hash as an index to the pre-calculated lookup |
| 52 | table to get the queue identifier for given transmit queue. Interface output node |
| 53 | enqueues the packets to respective frame and also copies the ``vnet_hw_if_tx_frame_t`` |
| 54 | to frame scalar arguments. Drivers use scalar arguments ``vnet_hw_if_tx_frame_t`` |
| 55 | of the given frame to extract the information about the transmit queue to be used to |
| 56 | transmit the packets. Drivers may need to acquire a lock on given queue before |
| 57 | transmitting the packets based on the ``shared_queue`` bit status. |
| 58 | |
| 59 | Data structures |
| 60 | ^^^^^^^^^^^^^^^ |
| 61 | |
| 62 | Queue information is stored in data structure ``vnet_hw_if_tx_queue_t``: |
| 63 | |
| 64 | .. code:: c |
| 65 | |
| 66 | typedef struct |
| 67 | { |
| 68 | /* either this queue is shared among multiple threads */ |
| 69 | u8 shared_queue : 1; |
| 70 | /* hw interface index */ |
| 71 | u32 hw_if_index; |
| 72 | |
| 73 | /* hardware queue identifier */ |
| 74 | u32 queue_id; |
| 75 | |
| 76 | /* bitmap of threads which use this queue */ |
| 77 | clib_bitmap_t *threads; |
| 78 | } vnet_hw_if_tx_queue_t; |
| 79 | |
| 80 | |
| 81 | Frame information is stored in data structure: ``vnet_hw_if_tx_frame_t``: |
| 82 | |
| 83 | .. code:: c |
| 84 | |
| 85 | typedef enum |
| 86 | { |
| 87 | VNET_HW_IF_TX_FRAME_HINT_NOT_CHAINED = (1 << 0), |
| 88 | VNET_HW_IF_TX_FRAME_HINT_NO_GSO = (1 << 1), |
| 89 | VNET_HW_IF_TX_FRAME_HINT_NO_CKSUM_OFFLOAD = (1 << 2), |
| 90 | } vnet_hw_if_tx_frame_hint_t; |
| 91 | |
| 92 | typedef struct |
| 93 | { |
| 94 | u8 shared_queue : 1; |
| 95 | vnet_hw_if_tx_frame_hint_t hints : 16; |
| 96 | u32 queue_id; |
| 97 | } vnet_hw_if_tx_frame_t; |
| 98 | |
| 99 | Output node runtime information is stored in data structure: ``output_node_thread_runtime``: |
| 100 | |
| 101 | .. code:: c |
| 102 | |
| 103 | typedef struct |
| 104 | { |
| 105 | CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); |
| 106 | vnet_hw_if_tx_frame_t *frame; |
| 107 | u32 *lookup_table; |
| 108 | u32 n_queues; |
| 109 | } vnet_hw_if_output_node_runtime_t; |
| 110 | |
| 111 | |
| 112 | MultiTXQ API |
| 113 | ^^^^^^^^^^^^ |
| 114 | |
| 115 | This API message is used to place tx queue of an interface to vpp main or worker(s) thread(s). |
| 116 | |
| 117 | .. code:: c |
| 118 | |
| 119 | autoendian autoreply define sw_interface_set_tx_placement |
| 120 | { |
| 121 | u32 client_index; |
| 122 | u32 context; |
| 123 | vl_api_interface_index_t sw_if_index; |
| 124 | u32 queue_id; |
| 125 | u32 array_size; |
| 126 | u32 threads[array_size]; |
| 127 | option vat_help = "<interface | sw_if_index <index>> queue <n> [threads <list> | mask <hex>]"; |
| 128 | }; |
| 129 | |
| 130 | Multi-TXQ CLI |
| 131 | ^^^^^^^^^^^^^ |
| 132 | |
| 133 | :: |
| 134 | |
| 135 | set interface tx-queue set interface tx-queue <interface> queue <n> [threads <list>] |
| 136 | set interface tx-hash set interface tx-hash <interface> hash-name <hash-name> |
| 137 | |
| 138 | :: |
| 139 | |
| 140 | show hardware-interfaces |
| 141 | |
| 142 | Name Idx Link Hardware |
| 143 | tap0 1 up tap0 |
| 144 | Link speed: unknown |
| 145 | RX Queues: |
| 146 | queue thread mode |
| 147 | 0 main (0) polling |
| 148 | TX Queues: |
| 149 | TX Hash: [name: crc32c-5tuple priority: 50 description: IPv4/IPv6 header and TCP/UDP ports] |
| 150 | queue shared thread(s) |
| 151 | 0 no 0 |
| 152 | Ethernet address 02:fe:27:69:5a:b5 |
| 153 | VIRTIO interface |
| 154 | instance 0 |
| 155 | RX QUEUE : Total Packets |
| 156 | 0 : 0 |
| 157 | TX QUEUE : Total Packets |
| 158 | 0 : 0 |
| 159 | |