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