Line data Source code
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 559 : 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 1126 : tx_queue_key (u32 hw_if_index, u32 queue_id)
20 : {
21 1126 : return ((u64) hw_if_index << 32) | queue_id;
22 : }
23 :
24 : u32
25 0 : vnet_hw_if_get_tx_queue_index_by_id (vnet_main_t *vnm, u32 hw_if_index,
26 : u32 queue_id)
27 : {
28 0 : vnet_interface_main_t *im = &vnm->interface_main;
29 0 : u64 key = tx_queue_key (hw_if_index, queue_id);
30 0 : uword *p = hash_get_mem (im->txq_index_by_hw_if_index_and_queue_id, &key);
31 0 : return p ? p[0] : ~0;
32 : }
33 :
34 : u32
35 566 : vnet_hw_if_register_tx_queue (vnet_main_t *vnm, u32 hw_if_index, u32 queue_id)
36 : {
37 566 : vnet_interface_main_t *im = &vnm->interface_main;
38 566 : vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
39 : vnet_hw_if_tx_queue_t *txq;
40 566 : u64 key = tx_queue_key (hw_if_index, queue_id);
41 : u32 queue_index;
42 :
43 566 : if (hash_get_mem (im->txq_index_by_hw_if_index_and_queue_id, &key))
44 0 : clib_panic ("Trying to register already registered queue id (%u) in the "
45 : "interface %v\n",
46 : queue_id, hi->name);
47 :
48 566 : pool_get_zero (im->hw_if_tx_queues, txq);
49 566 : queue_index = txq - im->hw_if_tx_queues;
50 566 : vec_add1 (hi->tx_queue_indices, queue_index);
51 566 : hash_set_mem_alloc (&im->txq_index_by_hw_if_index_and_queue_id, &key,
52 : queue_index);
53 566 : txq->hw_if_index = hw_if_index;
54 566 : txq->queue_id = queue_id;
55 :
56 566 : log_debug ("register: interface %v queue-id %u", hi->name, queue_id);
57 :
58 566 : return queue_index;
59 : }
60 :
61 : void
62 0 : vnet_hw_if_unregister_tx_queue (vnet_main_t *vnm, u32 queue_index)
63 : {
64 0 : vnet_interface_main_t *im = &vnm->interface_main;
65 : vnet_hw_if_tx_queue_t *txq;
66 0 : txq = vnet_hw_if_get_tx_queue (vnm, queue_index);
67 0 : vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, txq->hw_if_index);
68 : u64 key;
69 :
70 0 : key = tx_queue_key (txq->hw_if_index, txq->queue_id);
71 0 : hash_unset_mem_free (&im->txq_index_by_hw_if_index_and_queue_id, &key);
72 :
73 0 : for (int i = 0; i < vec_len (hi->tx_queue_indices); i++)
74 0 : if (hi->tx_queue_indices[i] == queue_index)
75 : {
76 0 : vec_del1 (hi->tx_queue_indices, i);
77 0 : break;
78 : }
79 :
80 0 : log_debug ("unregister: interface %v queue-id %u", hi->name, txq->queue_id);
81 0 : clib_bitmap_free (txq->threads);
82 0 : pool_put_index (im->hw_if_tx_queues, queue_index);
83 0 : }
84 :
85 : void
86 4135 : vnet_hw_if_unregister_all_tx_queues (vnet_main_t *vnm, u32 hw_if_index)
87 : {
88 4135 : vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
89 4135 : vnet_interface_main_t *im = &vnm->interface_main;
90 : vnet_hw_if_tx_queue_t *txq;
91 : u64 key;
92 :
93 4135 : log_debug ("unregister_all: interface %v", hi->name);
94 :
95 4695 : for (int i = 0; i < vec_len (hi->tx_queue_indices); i++)
96 : {
97 560 : txq = vnet_hw_if_get_tx_queue (vnm, hi->tx_queue_indices[i]);
98 560 : key = tx_queue_key (txq->hw_if_index, txq->queue_id);
99 560 : hash_unset_mem_free (&im->txq_index_by_hw_if_index_and_queue_id, &key);
100 :
101 560 : clib_bitmap_free (txq->threads);
102 560 : pool_put_index (im->hw_if_tx_queues, hi->tx_queue_indices[i]);
103 : }
104 :
105 4135 : vec_free (hi->tx_queue_indices);
106 4135 : }
107 :
108 : void
109 566 : vnet_hw_if_tx_queue_assign_thread (vnet_main_t *vnm, u32 queue_index,
110 : u32 thread_index)
111 : {
112 566 : vnet_hw_if_tx_queue_t *txq = vnet_hw_if_get_tx_queue (vnm, queue_index);
113 566 : vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, txq->hw_if_index);
114 566 : txq->threads = clib_bitmap_set (txq->threads, thread_index, 1);
115 566 : if (clib_bitmap_count_set_bits (txq->threads) > 1)
116 0 : txq->shared_queue = 1;
117 566 : 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"));
121 566 : }
122 :
123 : void
124 0 : vnet_hw_if_tx_queue_unassign_thread (vnet_main_t *vnm, u32 queue_index,
125 : u32 thread_index)
126 : {
127 0 : vnet_hw_if_tx_queue_t *txq = vnet_hw_if_get_tx_queue (vnm, queue_index);
128 0 : vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, txq->hw_if_index);
129 0 : txq->threads = clib_bitmap_set (txq->threads, thread_index, 0);
130 0 : if (clib_bitmap_count_set_bits (txq->threads) < 2)
131 0 : txq->shared_queue = 0;
132 0 : 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"));
136 0 : }
|