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