blob: 9a016a626fb795b50159dcb7e34fc93a3ec82e66 [file] [log] [blame]
Damjan Marion38c61912023-10-17 16:06:26 +00001/* SPDX-License-Identifier: Apache-2.0
2 * Copyright (c) 2023 Cisco Systems, Inc.
3 */
4
5#include <vnet/vnet.h>
6#include <vnet/ethernet/ethernet.h>
7#include <vnet/dev/dev.h>
8#include <vnet/dev/counters.h>
9#include <vnet/dev/log.h>
10
11VLIB_REGISTER_LOG_CLASS (dev_log, static) = {
12 .class_name = "dev",
13 .subclass_name = "error",
14};
15
16void
17vnet_dev_rx_queue_free (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
18{
19 vnet_dev_port_t *port = rxq->port;
20 vnet_dev_t *dev = port->dev;
21 log_debug (dev, "queue %u", rxq->queue_id);
22 if (port->rx_queue_ops.free)
23 port->rx_queue_ops.free (vm, rxq);
24
25 vnet_dev_rx_queue_free_counters (vm, rxq);
26 pool_put_index (port->rx_queues, rxq->index);
27 clib_mem_free (rxq);
28}
29
30vnet_dev_rv_t
31vnet_dev_rx_queue_alloc (vlib_main_t *vm, vnet_dev_port_t *port,
32 u16 queue_size)
33{
34 vnet_dev_main_t *dm = &vnet_dev_main;
35 vnet_dev_rx_queue_t *rxq, **qp;
36 vnet_dev_t *dev = port->dev;
37 vnet_dev_rv_t rv = VNET_DEV_OK;
38 u16 n_threads = vlib_get_n_threads ();
39 u8 buffer_pool_index;
40
41 vnet_dev_port_validate (vm, port);
42
43 log_debug (dev, "port %u queue_size %u", port->port_id, queue_size);
44
45 if (pool_elts (port->rx_queues) == port->attr.max_rx_queues)
46 return VNET_DEV_ERR_NO_AVAIL_QUEUES;
47
48 rxq = vnet_dev_alloc_with_data (sizeof (vnet_dev_port_t),
49 port->rx_queue_config.data_size);
50 pool_get (port->rx_queues, qp);
51 qp[0] = rxq;
52 rxq->enabled = 1;
53 rxq->port = port;
54 rxq->size = queue_size;
55 rxq->index = qp - port->rx_queues;
56
57 /* default queue id - can be changed by driver */
58 rxq->queue_id = qp - port->rx_queues;
59 ASSERT (rxq->queue_id < port->attr.max_rx_queues);
60
61 if (n_threads > 1)
62 {
63 rxq->rx_thread_index = dm->next_rx_queue_thread++;
64 if (dm->next_rx_queue_thread >= n_threads)
65 dm->next_rx_queue_thread = 1;
66 }
67
68 buffer_pool_index =
69 vlib_buffer_pool_get_default_for_numa (vm, dev->numa_node);
70 vlib_buffer_pool_t *bp = vlib_get_buffer_pool (vm, buffer_pool_index);
71
72 rxq->buffer_template = bp->buffer_template;
73 vnet_buffer (&rxq->buffer_template)->sw_if_index[VLIB_TX] = ~0;
74
75 rxq->next_index = vnet_dev_default_next_index_by_port_type[port->attr.type];
76
77 if (port->rx_queue_ops.alloc)
78 rv = port->rx_queue_ops.alloc (vm, rxq);
79
80 if (rv != VNET_DEV_OK)
81 {
82 log_err (dev, "driver rejected rx queue add with rv %d", rv);
83 vnet_dev_rx_queue_free (vm, rxq);
84 }
85 else
86 log_debug (dev, "queue %u added, assigned to thread %u", rxq->queue_id,
87 rxq->rx_thread_index);
88
89 return rv;
90}
91
92vnet_dev_rv_t
93vnet_dev_rx_queue_start (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
94{
95 vnet_dev_rv_t rv = VNET_DEV_OK;
96 if (rxq->port->rx_queue_ops.start)
97 rv = rxq->port->rx_queue_ops.start (vm, rxq);
98
99 if (rv == VNET_DEV_OK)
100 rxq->started = 1;
101
102 return rv;
103}
104
105void
106vnet_dev_rx_queue_stop (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
107{
108 if (rxq->port->rx_queue_ops.stop)
109 rxq->port->rx_queue_ops.stop (vm, rxq);
110 vlib_node_set_state (vm, rxq->port->intf.rx_node_index,
111 VLIB_NODE_STATE_DISABLED);
112 rxq->started = 0;
113}
114
115void
116vnet_dev_tx_queue_free (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
117{
118 vnet_dev_port_t *port = txq->port;
119 vnet_dev_t *dev = port->dev;
120
121 vnet_dev_port_validate (vm, port);
122
123 log_debug (dev, "queue %u", txq->queue_id);
124 if (port->tx_queue_ops.free)
125 port->tx_queue_ops.free (vm, txq);
126
127 clib_bitmap_free (txq->assigned_threads);
128 vnet_dev_tx_queue_free_counters (vm, txq);
129 pool_put_index (port->tx_queues, txq->index);
130 clib_mem_free (txq);
131}
132
133vnet_dev_rv_t
134vnet_dev_tx_queue_alloc (vlib_main_t *vm, vnet_dev_port_t *port,
135 u16 queue_size)
136{
137 vnet_dev_tx_queue_t *txq, **qp;
138 vnet_dev_t *dev = port->dev;
139 vnet_dev_rv_t rv = VNET_DEV_OK;
140
141 log_debug (dev, "port %u size %u", port->port_id, queue_size);
142
143 if (pool_elts (port->tx_queues) == port->attr.max_tx_queues)
144 return VNET_DEV_ERR_NO_AVAIL_QUEUES;
145
146 txq = vnet_dev_alloc_with_data (sizeof (vnet_dev_port_t),
147 port->tx_queue_config.data_size);
148 pool_get (port->tx_queues, qp);
149 qp[0] = txq;
150 txq->enabled = 1;
151 txq->port = port;
152 txq->size = queue_size;
153 txq->index = qp - port->tx_queues;
154
155 /* default queue id - can be changed by driver */
156 txq->queue_id = qp - port->tx_queues;
157 ASSERT (txq->queue_id < port->attr.max_tx_queues);
158
159 if (port->tx_queue_ops.alloc)
160 rv = port->tx_queue_ops.alloc (vm, txq);
161
162 if (rv != VNET_DEV_OK)
163 {
164 log_err (dev, "driver rejected tx queue alloc with rv %d", rv);
165 vnet_dev_tx_queue_free (vm, txq);
166 }
167 else
168 log_debug (dev, "queue %u added", txq->queue_id);
169
170 return rv;
171}
172
173vnet_dev_rv_t
174vnet_dev_tx_queue_start (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
175{
176 vnet_dev_rv_t rv = VNET_DEV_OK;
177 if (txq->port->tx_queue_ops.start)
178 rv = txq->port->tx_queue_ops.start (vm, txq);
179
180 if (rv == VNET_DEV_OK)
181 txq->started = 1;
182
183 return rv;
184}
185
186void
187vnet_dev_tx_queue_stop (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
188{
189 if (txq->port->tx_queue_ops.stop)
190 txq->port->tx_queue_ops.stop (vm, txq);
191 txq->started = 0;
192}
193
194void
195vnet_dev_rx_queue_add_counters (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq,
196 vnet_dev_counter_t *counters, u16 n_counters)
197{
198 rxq->counter_main = vnet_dev_counters_alloc (
199 vm, counters, n_counters, "%s port %u rx-queue %u counters",
200 rxq->port->dev->device_id, rxq->port->port_id, rxq->queue_id);
201}
202
203void
204vnet_dev_rx_queue_free_counters (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
205{
206 if (rxq->counter_main)
207 vnet_dev_counters_free (vm, rxq->counter_main);
208}
209
210void
211vnet_dev_tx_queue_add_counters (vlib_main_t *vm, vnet_dev_tx_queue_t *txq,
212 vnet_dev_counter_t *counters, u16 n_counters)
213{
214 txq->counter_main = vnet_dev_counters_alloc (
215 vm, counters, n_counters, "%s port %u tx-queue %u counters",
216 txq->port->dev->device_id, txq->port->port_id, txq->queue_id);
217}
218
219void
220vnet_dev_tx_queue_free_counters (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
221{
222 if (!txq->counter_main)
223 return;
224
225 log_debug (txq->port->dev, "free");
226 vnet_dev_counters_free (vm, txq->counter_main);
227}