Damjan Marion | 1bd6cbb | 2021-04-15 13:12:51 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: Apache-2.0 |
| 2 | * Copyright(c) 2021 Cisco Systems, Inc. |
| 3 | */ |
| 4 | |
| 5 | #include <vnet/vnet.h> |
| 6 | #include <vnet/devices/devices.h> |
| 7 | #include <vnet/interface/tx_queue_funcs.h> |
| 8 | #include <vlib/unix/unix.h> |
| 9 | |
| 10 | VLIB_REGISTER_LOG_CLASS (if_txq_log, static) = { |
| 11 | .class_name = "interface", |
| 12 | .subclass_name = "tx-queue", |
| 13 | }; |
| 14 | |
| 15 | #define log_debug(fmt, ...) vlib_log_debug (if_txq_log.class, fmt, __VA_ARGS__) |
| 16 | #define log_err(fmt, ...) vlib_log_err (if_txq_log.class, fmt, __VA_ARGS__) |
| 17 | |
| 18 | static u64 |
| 19 | tx_queue_key (u32 hw_if_index, u32 queue_id) |
| 20 | { |
| 21 | return ((u64) hw_if_index << 32) | queue_id; |
| 22 | } |
| 23 | |
| 24 | u32 |
| 25 | vnet_hw_if_get_tx_queue_index_by_id (vnet_main_t *vnm, u32 hw_if_index, |
| 26 | u32 queue_id) |
| 27 | { |
| 28 | vnet_interface_main_t *im = &vnm->interface_main; |
| 29 | u64 key = tx_queue_key (hw_if_index, queue_id); |
| 30 | uword *p = hash_get_mem (im->txq_index_by_hw_if_index_and_queue_id, &key); |
| 31 | return p ? p[0] : ~0; |
| 32 | } |
| 33 | |
| 34 | u32 |
| 35 | vnet_hw_if_register_tx_queue (vnet_main_t *vnm, u32 hw_if_index, u32 queue_id) |
| 36 | { |
| 37 | vnet_interface_main_t *im = &vnm->interface_main; |
| 38 | vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index); |
| 39 | vnet_hw_if_tx_queue_t *txq; |
| 40 | u64 key = tx_queue_key (hw_if_index, queue_id); |
| 41 | u32 queue_index; |
| 42 | |
| 43 | if (hash_get_mem (im->txq_index_by_hw_if_index_and_queue_id, &key)) |
| 44 | clib_panic ("Trying to register already registered queue id (%u) in the " |
| 45 | "interface %v\n", |
| 46 | queue_id, hi->name); |
| 47 | |
| 48 | pool_get_zero (im->hw_if_tx_queues, txq); |
| 49 | queue_index = txq - im->hw_if_tx_queues; |
| 50 | vec_add1 (hi->tx_queue_indices, queue_index); |
| 51 | hash_set_mem_alloc (&im->txq_index_by_hw_if_index_and_queue_id, &key, |
| 52 | queue_index); |
| 53 | txq->hw_if_index = hw_if_index; |
| 54 | txq->queue_id = queue_id; |
| 55 | |
| 56 | log_debug ("register: interface %v queue-id %u", hi->name, queue_id); |
| 57 | |
| 58 | return queue_index; |
| 59 | } |
| 60 | |
| 61 | void |
| 62 | vnet_hw_if_unregister_tx_queue (vnet_main_t *vnm, u32 queue_index) |
| 63 | { |
| 64 | vnet_interface_main_t *im = &vnm->interface_main; |
| 65 | vnet_hw_if_tx_queue_t *txq; |
| 66 | txq = vnet_hw_if_get_tx_queue (vnm, queue_index); |
| 67 | vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, txq->hw_if_index); |
| 68 | u64 key; |
| 69 | |
| 70 | key = tx_queue_key (txq->hw_if_index, txq->queue_id); |
| 71 | hash_unset_mem_free (&im->txq_index_by_hw_if_index_and_queue_id, &key); |
| 72 | |
| 73 | for (int i = 0; i < vec_len (hi->tx_queue_indices); i++) |
| 74 | if (hi->tx_queue_indices[i] == queue_index) |
| 75 | { |
| 76 | vec_del1 (hi->tx_queue_indices, i); |
| 77 | break; |
| 78 | } |
| 79 | |
| 80 | log_debug ("unregister: interface %v queue-id %u", hi->name, txq->queue_id); |
| 81 | clib_bitmap_free (txq->threads); |
| 82 | pool_put_index (im->hw_if_tx_queues, queue_index); |
| 83 | } |
| 84 | |
| 85 | void |
| 86 | vnet_hw_if_unregister_all_tx_queues (vnet_main_t *vnm, u32 hw_if_index) |
| 87 | { |
| 88 | vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index); |
| 89 | vnet_interface_main_t *im = &vnm->interface_main; |
| 90 | vnet_hw_if_tx_queue_t *txq; |
| 91 | u64 key; |
| 92 | |
| 93 | log_debug ("unregister_all: interface %v", hi->name); |
| 94 | |
| 95 | for (int i = 0; i < vec_len (hi->tx_queue_indices); i++) |
| 96 | { |
| 97 | txq = vnet_hw_if_get_tx_queue (vnm, hi->tx_queue_indices[i]); |
| 98 | key = tx_queue_key (txq->hw_if_index, txq->queue_id); |
| 99 | hash_unset_mem_free (&im->txq_index_by_hw_if_index_and_queue_id, &key); |
| 100 | |
| 101 | clib_bitmap_free (txq->threads); |
| 102 | pool_put_index (im->hw_if_tx_queues, hi->tx_queue_indices[i]); |
| 103 | } |
| 104 | |
| 105 | vec_free (hi->tx_queue_indices); |
| 106 | } |
| 107 | |
| 108 | void |
| 109 | vnet_hw_if_tx_queue_assign_thread (vnet_main_t *vnm, u32 queue_index, |
| 110 | u32 thread_index) |
| 111 | { |
| 112 | vnet_hw_if_tx_queue_t *txq = vnet_hw_if_get_tx_queue (vnm, queue_index); |
| 113 | vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, txq->hw_if_index); |
| 114 | txq->threads = clib_bitmap_set (txq->threads, thread_index, 1); |
Mohsin Kazmi | 005605f | 2021-05-24 18:33:50 +0200 | [diff] [blame] | 115 | if (clib_bitmap_count_set_bits (txq->threads) > 1) |
| 116 | txq->shared_queue = 1; |
| 117 | log_debug ( |
| 118 | "assign_thread: interface %v queue-id %u thread %u queue-shared %s", |
| 119 | hi->name, txq->queue_id, thread_index, |
| 120 | (txq->shared_queue == 1 ? "yes" : "no")); |
Damjan Marion | 1bd6cbb | 2021-04-15 13:12:51 +0200 | [diff] [blame] | 121 | } |
| 122 | |
| 123 | void |
| 124 | vnet_hw_if_tx_queue_unassign_thread (vnet_main_t *vnm, u32 queue_index, |
| 125 | u32 thread_index) |
| 126 | { |
| 127 | vnet_hw_if_tx_queue_t *txq = vnet_hw_if_get_tx_queue (vnm, queue_index); |
| 128 | vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, txq->hw_if_index); |
| 129 | txq->threads = clib_bitmap_set (txq->threads, thread_index, 0); |
Mohsin Kazmi | 005605f | 2021-05-24 18:33:50 +0200 | [diff] [blame] | 130 | if (clib_bitmap_count_set_bits (txq->threads) < 2) |
| 131 | txq->shared_queue = 0; |
| 132 | log_debug ( |
| 133 | "unassign_thread: interface %v queue-id %u thread %u queue-shared %s", |
| 134 | hi->name, txq->queue_id, thread_index, |
| 135 | (txq->shared_queue == 1 ? "yes" : "no")); |
Damjan Marion | 1bd6cbb | 2021-04-15 13:12:51 +0200 | [diff] [blame] | 136 | } |