Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2022 Corigine, Inc.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "nfp_flower_ctrl.h"
7 : :
8 : : #include <rte_service.h>
9 : :
10 : : #include "../nfd3/nfp_nfd3.h"
11 : : #include "../nfdk/nfp_nfdk.h"
12 : : #include "../nfp_logs.h"
13 : : #include "nfp_flower_representor.h"
14 : : #include "nfp_mtr.h"
15 : :
16 : : #define MAX_PKT_BURST 32
17 : :
18 : : static uint16_t
19 : 0 : nfp_flower_ctrl_vnic_recv(void *rx_queue,
20 : : struct rte_mbuf **rx_pkts,
21 : : uint16_t nb_pkts)
22 : : {
23 : : uint64_t dma_addr;
24 : : uint16_t avail = 0;
25 : : struct rte_mbuf *mb;
26 : : uint16_t nb_hold = 0;
27 : : struct nfp_net_hw *hw;
28 : : struct nfp_net_rxq *rxq;
29 : : struct rte_mbuf *new_mb;
30 : : struct nfp_net_dp_buf *rxb;
31 : : struct nfp_net_rx_desc *rxds;
32 : :
33 : : rxq = rx_queue;
34 [ # # ]: 0 : if (unlikely(rxq == NULL)) {
35 : : /*
36 : : * DPDK just checks the queue is lower than max queues
37 : : * enabled. But the queue needs to be configured.
38 : : */
39 : : PMD_RX_LOG(ERR, "RX Bad queue");
40 : : return 0;
41 : : }
42 : :
43 : 0 : hw = rxq->hw;
44 [ # # ]: 0 : while (avail < nb_pkts) {
45 : 0 : rxb = &rxq->rxbufs[rxq->rd_p];
46 [ # # ]: 0 : if (unlikely(rxb == NULL)) {
47 : : PMD_RX_LOG(ERR, "rxb does not exist!");
48 : : break;
49 : : }
50 : :
51 : 0 : rxds = &rxq->rxds[rxq->rd_p];
52 [ # # ]: 0 : if ((rxds->rxd.meta_len_dd & PCIE_DESC_RX_DD) == 0)
53 : : break;
54 : :
55 : : /*
56 : : * Memory barrier to ensure that we won't do other
57 : : * reads before the DD bit.
58 : : */
59 : : rte_rmb();
60 : :
61 : : /*
62 : : * We got a packet. Let's alloc a new mbuf for refilling the
63 : : * free descriptor ring as soon as possible.
64 : : */
65 : 0 : new_mb = rte_pktmbuf_alloc(rxq->mem_pool);
66 [ # # ]: 0 : if (unlikely(new_mb == NULL)) {
67 : : PMD_RX_LOG(ERR, "RX mbuf alloc failed port_id=%u queue_id=%hu",
68 : : rxq->port_id, rxq->qidx);
69 : : nfp_net_mbuf_alloc_failed(rxq);
70 : : break;
71 : : }
72 : :
73 : : /*
74 : : * Grab the mbuf and refill the descriptor with the
75 : : * previously allocated mbuf.
76 : : */
77 : 0 : mb = rxb->mbuf;
78 : 0 : rxb->mbuf = new_mb;
79 : :
80 : : /* Size of this segment */
81 : 0 : mb->data_len = rxds->rxd.data_len - NFP_DESC_META_LEN(rxds);
82 : : /* Size of the whole packet. We just support 1 segment */
83 : 0 : mb->pkt_len = mb->data_len;
84 : :
85 [ # # ]: 0 : if (unlikely((mb->data_len + hw->rx_offset) > rxq->mbuf_size)) {
86 : : /*
87 : : * This should not happen and the user has the
88 : : * responsibility of avoiding it. But we have
89 : : * to give some info about the error.
90 : : */
91 : : PMD_RX_LOG(ERR, "mbuf overflow likely due to the RX offset.");
92 : 0 : rte_pktmbuf_free(mb);
93 : 0 : break;
94 : : }
95 : :
96 : : /* Filling the received mbuf with packet info */
97 [ # # ]: 0 : if (hw->rx_offset != 0)
98 : 0 : mb->data_off = RTE_PKTMBUF_HEADROOM + hw->rx_offset;
99 : : else
100 : 0 : mb->data_off = RTE_PKTMBUF_HEADROOM + NFP_DESC_META_LEN(rxds);
101 : :
102 : : /* No scatter mode supported */
103 : 0 : mb->nb_segs = 1;
104 : 0 : mb->next = NULL;
105 : 0 : mb->port = rxq->port_id;
106 : :
107 : 0 : rx_pkts[avail++] = mb;
108 : :
109 : : /* Now resetting and updating the descriptor */
110 [ # # ]: 0 : rxds->vals[0] = 0;
111 : : rxds->vals[1] = 0;
112 : : dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(new_mb));
113 : : rxds->fld.dd = 0;
114 : 0 : rxds->fld.dma_addr_hi = (dma_addr >> 32) & 0xffff;
115 : 0 : rxds->fld.dma_addr_lo = dma_addr & 0xffffffff;
116 : : nb_hold++;
117 : :
118 : 0 : rxq->rd_p++;
119 [ # # ]: 0 : if (unlikely(rxq->rd_p == rxq->rx_count)) /* Wrapping */
120 : 0 : rxq->rd_p = 0;
121 : : }
122 : :
123 [ # # ]: 0 : if (nb_hold == 0)
124 : : return 0;
125 : :
126 : 0 : nb_hold += rxq->nb_rx_hold;
127 : :
128 : : /*
129 : : * FL descriptors needs to be written before incrementing the
130 : : * FL queue WR pointer
131 : : */
132 : : rte_wmb();
133 [ # # ]: 0 : if (nb_hold >= rxq->rx_free_thresh) {
134 : : PMD_RX_LOG(DEBUG, "port=%hu queue=%hu nb_hold=%hu avail=%hu",
135 : : rxq->port_id, rxq->qidx, nb_hold, avail);
136 : 0 : nfp_qcp_ptr_add(rxq->qcp_fl, NFP_QCP_WRITE_PTR, nb_hold);
137 : : nb_hold = 0;
138 : : }
139 : :
140 : 0 : rxq->nb_rx_hold = nb_hold;
141 : :
142 : 0 : return avail;
143 : : }
144 : :
145 : : static uint16_t
146 : 0 : nfp_flower_ctrl_vnic_nfd3_xmit(struct nfp_app_fw_flower *app_fw_flower,
147 : : struct rte_mbuf *mbuf)
148 : : {
149 : : uint16_t cnt = 0;
150 : : uint64_t dma_addr;
151 : : uint32_t free_descs;
152 : : struct rte_mbuf **lmbuf;
153 : : struct nfp_net_txq *txq;
154 : : struct nfp_net_hw *ctrl_hw;
155 : : struct rte_eth_dev *ctrl_dev;
156 : : struct nfp_net_nfd3_tx_desc *txds;
157 : :
158 : 0 : ctrl_hw = app_fw_flower->ctrl_hw;
159 : 0 : ctrl_dev = ctrl_hw->eth_dev;
160 : :
161 : : /* Flower ctrl vNIC only has a single tx queue */
162 : 0 : txq = ctrl_dev->data->tx_queues[0];
163 [ # # ]: 0 : if (unlikely(txq == NULL)) {
164 : : /*
165 : : * DPDK just checks the queue is lower than max queues
166 : : * enabled. But the queue needs to be configured.
167 : : */
168 : : PMD_TX_LOG(ERR, "ctrl dev TX Bad queue");
169 : 0 : goto xmit_end;
170 : : }
171 : :
172 : 0 : txds = &txq->txds[txq->wr_p];
173 : 0 : txds->vals[0] = 0;
174 : 0 : txds->vals[1] = 0;
175 : 0 : txds->vals[2] = 0;
176 [ # # ]: 0 : txds->vals[3] = 0;
177 : :
178 [ # # ]: 0 : if (nfp_net_nfd3_txq_full(txq))
179 : 0 : nfp_net_tx_free_bufs(txq);
180 : :
181 : : free_descs = nfp_net_nfd3_free_tx_desc(txq);
182 [ # # ]: 0 : if (unlikely(free_descs == 0)) {
183 : : PMD_TX_LOG(ERR, "ctrl dev no free descs");
184 : 0 : goto xmit_end;
185 : : }
186 : :
187 : 0 : lmbuf = &txq->txbufs[txq->wr_p].mbuf;
188 [ # # ]: 0 : RTE_MBUF_PREFETCH_TO_FREE(*lmbuf);
189 [ # # ]: 0 : if (*lmbuf != NULL)
190 : : rte_pktmbuf_free_seg(*lmbuf);
191 : :
192 [ # # ]: 0 : *lmbuf = mbuf;
193 : : dma_addr = rte_mbuf_data_iova(mbuf);
194 : :
195 : 0 : txds->data_len = mbuf->pkt_len;
196 : 0 : txds->dma_len = txds->data_len;
197 : 0 : txds->dma_addr_hi = (dma_addr >> 32) & 0xff;
198 : 0 : txds->dma_addr_lo = (dma_addr & 0xffffffff);
199 : 0 : txds->offset_eop = FLOWER_PKT_DATA_OFFSET | NFD3_DESC_TX_EOP;
200 : :
201 : 0 : txq->wr_p++;
202 [ # # ]: 0 : if (unlikely(txq->wr_p == txq->tx_count)) /* Wrapping */
203 : 0 : txq->wr_p = 0;
204 : :
205 : : cnt++;
206 : 0 : app_fw_flower->ctrl_vnic_tx_count++;
207 : :
208 : 0 : xmit_end:
209 : : rte_wmb();
210 : 0 : nfp_qcp_ptr_add(txq->qcp_q, NFP_QCP_WRITE_PTR, 1);
211 : :
212 : 0 : return cnt;
213 : : }
214 : :
215 : : static uint16_t
216 : 0 : nfp_flower_ctrl_vnic_nfdk_xmit(struct nfp_app_fw_flower *app_fw_flower,
217 : : struct rte_mbuf *mbuf)
218 : : {
219 : : int nop_descs;
220 : : uint32_t type;
221 : : uint32_t dma_len;
222 : : uint32_t tmp_dlen;
223 : : uint64_t dma_addr;
224 : : uint32_t dlen_type;
225 : : uint32_t used_descs;
226 : : uint32_t free_descs;
227 : : struct rte_mbuf **lmbuf;
228 : : struct nfp_net_txq *txq;
229 : : uint32_t issued_descs = 0;
230 : : struct rte_eth_dev *ctrl_dev;
231 : : struct nfp_net_nfdk_tx_desc *ktxds;
232 : :
233 : 0 : ctrl_dev = app_fw_flower->ctrl_hw->eth_dev;
234 : :
235 : : /* Flower ctrl vNIC only has a single tx queue */
236 : 0 : txq = ctrl_dev->data->tx_queues[0];
237 : :
238 [ # # ]: 0 : if (unlikely(mbuf->nb_segs > 1)) {
239 : : PMD_TX_LOG(ERR, "Multisegment packet not supported");
240 : : return 0;
241 : : }
242 : :
243 [ # # # # ]: 0 : if (nfp_net_nfdk_free_tx_desc(txq) < NFDK_TX_DESC_PER_SIMPLE_PKT ||
244 : : nfp_net_nfdk_txq_full(txq))
245 : 0 : nfp_net_tx_free_bufs(txq);
246 : :
247 : : free_descs = nfp_net_nfdk_free_tx_desc(txq);
248 [ # # ]: 0 : if (unlikely(free_descs < NFDK_TX_DESC_PER_SIMPLE_PKT)) {
249 : : PMD_TX_LOG(ERR, "ctrl dev no free descs");
250 : : return 0;
251 : : }
252 : :
253 : 0 : nop_descs = nfp_net_nfdk_tx_maybe_close_block(txq, mbuf);
254 [ # # ]: 0 : if (nop_descs < 0)
255 : : return 0;
256 : :
257 : 0 : issued_descs += nop_descs;
258 : 0 : ktxds = &txq->ktxds[txq->wr_p];
259 : :
260 : : /*
261 : : * Checksum and VLAN flags just in the first descriptor for a
262 : : * multisegment packet, but TSO info needs to be in all of them.
263 : : */
264 : 0 : dma_len = mbuf->data_len;
265 [ # # ]: 0 : if (dma_len <= NFDK_TX_MAX_DATA_PER_HEAD)
266 : : type = NFDK_DESC_TX_TYPE_SIMPLE;
267 : : else
268 : : type = NFDK_DESC_TX_TYPE_GATHER;
269 : :
270 : : /* Implicitly truncates to chunk in below logic */
271 : 0 : dma_len -= 1;
272 : :
273 : : /*
274 : : * We will do our best to pass as much data as we can in descriptor
275 : : * and we need to make sure the first descriptor includes whole
276 : : * head since there is limitation in firmware side. Sometimes the
277 : : * value of 'dma_len & NFDK_DESC_TX_DMA_LEN_HEAD' will be less
278 : : * than packet head len.
279 : : */
280 : : if (dma_len > NFDK_DESC_TX_DMA_LEN_HEAD)
281 : : dma_len = NFDK_DESC_TX_DMA_LEN_HEAD;
282 : 0 : dlen_type = dma_len | (NFDK_DESC_TX_TYPE_HEAD & (type << 12));
283 [ # # ]: 0 : ktxds->dma_len_type = rte_cpu_to_le_16(dlen_type);
284 : : dma_addr = rte_mbuf_data_iova(mbuf);
285 : 0 : ktxds->dma_addr_hi = rte_cpu_to_le_16(dma_addr >> 32);
286 : 0 : ktxds->dma_addr_lo = rte_cpu_to_le_32(dma_addr & 0xffffffff);
287 : 0 : ktxds++;
288 : :
289 : : /*
290 : : * Preserve the original dlen_type, this way below the EOP logic
291 : : * can use dlen_type.
292 : : */
293 : 0 : tmp_dlen = dlen_type & NFDK_DESC_TX_DMA_LEN_HEAD;
294 : 0 : dma_len -= tmp_dlen;
295 : 0 : dma_addr += tmp_dlen + 1;
296 : :
297 : : /*
298 : : * The rest of the data (if any) will be in larger DMA descriptors
299 : : * and is handled with the dma_len loop.
300 : : */
301 : 0 : lmbuf = &txq->txbufs[txq->wr_p].mbuf;
302 [ # # ]: 0 : if (*lmbuf != NULL)
303 : : rte_pktmbuf_free_seg(*lmbuf);
304 : 0 : *lmbuf = mbuf;
305 [ # # ]: 0 : while (dma_len > 0) {
306 : 0 : dma_len -= 1;
307 : 0 : dlen_type = NFDK_DESC_TX_DMA_LEN & dma_len;
308 : :
309 : 0 : ktxds->dma_len_type = rte_cpu_to_le_16(dlen_type);
310 : 0 : ktxds->dma_addr_hi = rte_cpu_to_le_16(dma_addr >> 32);
311 : 0 : ktxds->dma_addr_lo = rte_cpu_to_le_32(dma_addr & 0xffffffff);
312 : 0 : ktxds++;
313 : :
314 : 0 : dma_len -= dlen_type;
315 : 0 : dma_addr += dlen_type + 1;
316 : : }
317 : :
318 : 0 : (ktxds - 1)->dma_len_type = rte_cpu_to_le_16(dlen_type | NFDK_DESC_TX_EOP);
319 : :
320 : 0 : ktxds->raw = rte_cpu_to_le_64(NFDK_DESC_TX_CHAIN_META);
321 : 0 : ktxds++;
322 : :
323 : 0 : used_descs = ktxds - txq->ktxds - txq->wr_p;
324 : 0 : if (RTE_ALIGN_FLOOR(txq->wr_p, NFDK_TX_DESC_BLOCK_CNT) !=
325 [ # # ]: 0 : RTE_ALIGN_FLOOR(txq->wr_p + used_descs - 1, NFDK_TX_DESC_BLOCK_CNT)) {
326 : : PMD_TX_LOG(INFO, "Used descs cross block boundary");
327 : : return 0;
328 : : }
329 : :
330 : 0 : txq->wr_p = D_IDX(txq, txq->wr_p + used_descs);
331 [ # # ]: 0 : if (txq->wr_p % NFDK_TX_DESC_BLOCK_CNT != 0)
332 : 0 : txq->data_pending += mbuf->pkt_len;
333 : : else
334 : 0 : txq->data_pending = 0;
335 : :
336 : 0 : issued_descs += used_descs;
337 : :
338 : : /* Increment write pointers. Force memory write before we let HW know */
339 : : rte_wmb();
340 : 0 : nfp_qcp_ptr_add(txq->qcp_q, NFP_QCP_WRITE_PTR, issued_descs);
341 : :
342 : 0 : return 1;
343 : : }
344 : :
345 : : void
346 : 0 : nfp_flower_ctrl_vnic_xmit_register(struct nfp_app_fw_flower *app_fw_flower)
347 : : {
348 : : struct nfp_net_hw *hw;
349 : : struct nfp_flower_nfd_func *nfd_func;
350 : :
351 : 0 : hw = app_fw_flower->pf_hw;
352 : : nfd_func = &app_fw_flower->nfd_func;
353 : :
354 [ # # ]: 0 : if (hw->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3)
355 : 0 : nfd_func->ctrl_vnic_xmit_t = nfp_flower_ctrl_vnic_nfd3_xmit;
356 : : else
357 : 0 : nfd_func->ctrl_vnic_xmit_t = nfp_flower_ctrl_vnic_nfdk_xmit;
358 : 0 : }
359 : :
360 : : uint16_t
361 : 0 : nfp_flower_ctrl_vnic_xmit(struct nfp_app_fw_flower *app_fw_flower,
362 : : struct rte_mbuf *mbuf)
363 : : {
364 : 0 : return app_fw_flower->nfd_func.ctrl_vnic_xmit_t(app_fw_flower, mbuf);
365 : : }
366 : :
367 : : static void
368 : 0 : nfp_flower_cmsg_rx_stats(struct nfp_flow_priv *flow_priv,
369 : : struct rte_mbuf *mbuf)
370 : : {
371 : : char *msg;
372 : : uint16_t i;
373 : : uint16_t count;
374 : : uint16_t msg_len;
375 : : uint32_t ctx_id;
376 : : struct nfp_flower_stats_frame *stats;
377 : :
378 : 0 : msg = rte_pktmbuf_mtod_offset(mbuf, char *, NFP_FLOWER_CMSG_HLEN);
379 : 0 : msg_len = mbuf->data_len - NFP_FLOWER_CMSG_HLEN;
380 : 0 : count = msg_len / sizeof(struct nfp_flower_stats_frame);
381 : :
382 : 0 : rte_spinlock_lock(&flow_priv->stats_lock);
383 [ # # ]: 0 : for (i = 0; i < count; i++) {
384 : 0 : stats = (struct nfp_flower_stats_frame *)msg + i;
385 [ # # ]: 0 : ctx_id = rte_be_to_cpu_32(stats->stats_con_id);
386 [ # # ]: 0 : flow_priv->stats[ctx_id].pkts += rte_be_to_cpu_32(stats->pkt_count);
387 [ # # ]: 0 : flow_priv->stats[ctx_id].bytes += rte_be_to_cpu_64(stats->byte_count);
388 : : }
389 : : rte_spinlock_unlock(&flow_priv->stats_lock);
390 : 0 : }
391 : :
392 : : static void
393 : 0 : nfp_flower_cmsg_rx_qos_stats(struct nfp_mtr_priv *mtr_priv,
394 : : struct rte_mbuf *mbuf)
395 : : {
396 : : char *msg;
397 : : uint32_t profile_id;
398 : : struct nfp_mtr *mtr;
399 : : struct nfp_mtr_stats_reply *mtr_stats;
400 : :
401 : 0 : msg = rte_pktmbuf_mtod_offset(mbuf, char *, NFP_FLOWER_CMSG_HLEN);
402 : :
403 : : mtr_stats = (struct nfp_mtr_stats_reply *)msg;
404 [ # # ]: 0 : profile_id = rte_be_to_cpu_32(mtr_stats->head.profile_id);
405 : 0 : mtr = nfp_mtr_find_by_profile_id(mtr_priv, profile_id);
406 [ # # ]: 0 : if (mtr == NULL)
407 : : return;
408 : :
409 : 0 : rte_spinlock_lock(&mtr_priv->mtr_stats_lock);
410 [ # # ]: 0 : mtr->mtr_stats.curr.pass_bytes = rte_be_to_cpu_64(mtr_stats->pass_bytes);
411 [ # # ]: 0 : mtr->mtr_stats.curr.pass_pkts = rte_be_to_cpu_64(mtr_stats->pass_pkts);
412 [ # # ]: 0 : mtr->mtr_stats.curr.drop_bytes = rte_be_to_cpu_64(mtr_stats->drop_bytes);
413 [ # # ]: 0 : mtr->mtr_stats.curr.drop_pkts = rte_be_to_cpu_64(mtr_stats->drop_pkts);
414 : : rte_spinlock_unlock(&mtr_priv->mtr_stats_lock);
415 : : }
416 : :
417 : : static int
418 : 0 : nfp_flower_cmsg_port_mod_rx(struct nfp_app_fw_flower *app_fw_flower,
419 : : struct rte_mbuf *pkt_burst)
420 : : {
421 : : uint32_t port;
422 : : struct nfp_flower_representor *repr;
423 : : struct nfp_flower_cmsg_port_mod *msg;
424 : :
425 : 0 : msg = rte_pktmbuf_mtod_offset(pkt_burst, struct nfp_flower_cmsg_port_mod *,
426 : : NFP_FLOWER_CMSG_HLEN);
427 [ # # ]: 0 : port = rte_be_to_cpu_32(msg->portnum);
428 : :
429 [ # # # ]: 0 : switch (NFP_FLOWER_CMSG_PORT_TYPE(port)) {
430 : 0 : case NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT:
431 : 0 : repr = app_fw_flower->phy_reprs[NFP_FLOWER_CMSG_PORT_PHYS_PORT_NUM(port)];
432 : 0 : break;
433 : 0 : case NFP_FLOWER_CMSG_PORT_TYPE_PCIE_PORT:
434 [ # # ]: 0 : if (NFP_FLOWER_CMSG_PORT_VNIC_TYPE(port) == NFP_FLOWER_CMSG_PORT_VNIC_TYPE_VF)
435 : 0 : repr = app_fw_flower->vf_reprs[NFP_FLOWER_CMSG_PORT_VNIC(port)];
436 : : else
437 : 0 : repr = app_fw_flower->pf_repr;
438 : : break;
439 : 0 : default:
440 : 0 : PMD_DRV_LOG(ERR, "ctrl msg for unknown port %#x", port);
441 : 0 : return -EINVAL;
442 : : }
443 : :
444 : 0 : repr->link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
445 [ # # ]: 0 : if ((msg->info & NFP_FLOWER_CMSG_PORT_MOD_INFO_LINK) != 0)
446 : 0 : repr->link.link_status = RTE_ETH_LINK_UP;
447 : : else
448 : 0 : repr->link.link_status = RTE_ETH_LINK_DOWN;
449 : :
450 : : return 0;
451 : : }
452 : :
453 : : static void
454 : 0 : nfp_flower_cmsg_rx(struct nfp_app_fw_flower *app_fw_flower,
455 : : struct rte_mbuf **pkts_burst,
456 : : uint16_t count)
457 : : {
458 : : uint16_t i;
459 : : char *meta;
460 : : uint32_t meta_type;
461 : : uint32_t meta_info;
462 : : struct nfp_mtr_priv *mtr_priv;
463 : : struct nfp_flow_priv *flow_priv;
464 : : struct nfp_flower_cmsg_hdr *cmsg_hdr;
465 : :
466 : 0 : mtr_priv = app_fw_flower->mtr_priv;
467 : 0 : flow_priv = app_fw_flower->flow_priv;
468 : :
469 [ # # ]: 0 : for (i = 0; i < count; i++) {
470 : 0 : meta = rte_pktmbuf_mtod(pkts_burst[i], char *);
471 : :
472 : : /* Free the unsupported ctrl packet */
473 [ # # ]: 0 : meta_type = rte_be_to_cpu_32(*(uint32_t *)(meta - 8));
474 [ # # ]: 0 : meta_info = rte_be_to_cpu_32(*(uint32_t *)(meta - 4));
475 : 0 : if (meta_type != NFP_NET_META_PORTID ||
476 [ # # ]: 0 : meta_info != NFP_META_PORT_ID_CTRL) {
477 : 0 : PMD_DRV_LOG(ERR, "Incorrect metadata for ctrl packet!");
478 : 0 : rte_pktmbuf_free(pkts_burst[i]);
479 : 0 : continue;
480 : : }
481 : :
482 : : cmsg_hdr = (struct nfp_flower_cmsg_hdr *)meta;
483 [ # # ]: 0 : if (unlikely(cmsg_hdr->version != NFP_FLOWER_CMSG_VER1)) {
484 : 0 : PMD_DRV_LOG(ERR, "Incorrect repr control version!");
485 : 0 : rte_pktmbuf_free(pkts_burst[i]);
486 : 0 : continue;
487 : : }
488 : :
489 [ # # ]: 0 : if (cmsg_hdr->type == NFP_FLOWER_CMSG_TYPE_FLOW_STATS) {
490 : : /* We need to deal with stats updates from HW asap */
491 : 0 : nfp_flower_cmsg_rx_stats(flow_priv, pkts_burst[i]);
492 [ # # ]: 0 : } else if (cmsg_hdr->type == NFP_FLOWER_CMSG_TYPE_QOS_STATS) {
493 : : /* Handle meter stats */
494 : 0 : nfp_flower_cmsg_rx_qos_stats(mtr_priv, pkts_burst[i]);
495 [ # # ]: 0 : } else if (cmsg_hdr->type == NFP_FLOWER_CMSG_TYPE_PORT_MOD) {
496 : : /* Handle changes to port configuration/status */
497 : 0 : nfp_flower_cmsg_port_mod_rx(app_fw_flower, pkts_burst[i]);
498 : : }
499 : :
500 : 0 : rte_pktmbuf_free(pkts_burst[i]);
501 : : }
502 : 0 : }
503 : :
504 : : void
505 : 0 : nfp_flower_ctrl_vnic_poll(struct nfp_app_fw_flower *app_fw_flower)
506 : : {
507 : : uint16_t count;
508 : : struct nfp_net_rxq *rxq;
509 : : struct nfp_net_hw *ctrl_hw;
510 : : struct rte_eth_dev *ctrl_eth_dev;
511 : : struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
512 : :
513 : 0 : ctrl_hw = app_fw_flower->ctrl_hw;
514 : 0 : ctrl_eth_dev = ctrl_hw->eth_dev;
515 : :
516 : : /* Ctrl vNIC only has a single Rx queue */
517 : 0 : rxq = ctrl_eth_dev->data->rx_queues[0];
518 : :
519 [ # # ]: 0 : while (rte_service_runstate_get(app_fw_flower->ctrl_vnic_id) != 0) {
520 : 0 : count = nfp_flower_ctrl_vnic_recv(rxq, pkts_burst, MAX_PKT_BURST);
521 [ # # ]: 0 : if (count != 0) {
522 : 0 : app_fw_flower->ctrl_vnic_rx_count += count;
523 : : /* Process cmsgs here */
524 : 0 : nfp_flower_cmsg_rx(app_fw_flower, pkts_burst, count);
525 : : }
526 : : }
527 : 0 : }
|