NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
upf_accel.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2025 NVIDIA CORPORATION AND AFFILIATES. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are permitted
5  * provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright notice, this list of
7  * conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright notice, this list of
9  * conditions and the following disclaimer in the documentation and/or other materials
10  * provided with the distribution.
11  * * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
12  * to endorse or promote products derived from this software without specific prior written
13  * permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21  * STRICT LIABILITY, OR TOR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  */
25 
26 #include <signal.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 
30 #include <rte_ethdev.h>
31 #include <rte_hash_crc.h>
32 
33 #include <dpdk_utils.h>
34 #include <doca_dpdk.h>
35 #include <doca_argp.h>
36 #include <doca_flow.h>
37 #include <doca_bitfield.h>
38 #include <doca_log.h>
39 
40 #include "upf_accel.h"
42 #include "upf_accel_pipeline.h"
43 
44 DOCA_LOG_REGISTER(UPF_ACCEL);
45 
46 volatile bool force_quit;
47 
48 /*
49  * Calculate quota counter index according to a port id and zero based index
50  *
51  * @port_id [in]: port id
52  * @idx [in]: relative (zero based) index
53  * @return: absolute (port wise) quota counter index
54  */
55 static inline uint32_t port_id_and_idx_to_quota_counter(enum upf_accel_port port_id, uint32_t idx)
56 {
57  return port_id * UPF_ACCEL_NUM_QUOTA_COUNTERS_PER_PORT + idx;
58 }
59 
60 /*
61  * Get the offset of a meter.
62  *
63  * Meters are organized as follows:
64  *
65  * -- --
66  * | | Meter[0]
67  * | | Meter[1]
68  * | PDR[0]- ...
69  * | |
70  * | | Meter[UPF_ACCEL_MAX_PDR_NUM_RATE_METERS - 1]
71  * Port[0]- --
72  * | | Meter[UPF_ACCEL_MAX_PDR_NUM_RATE_METERS]
73  * | | Meter[UPF_ACCEL_MAX_PDR_NUM_RATE_METERS +1]
74  * | PDR[1] - ...
75  * | |
76  * | |
77  * -- -
78  *...
79  *
80  * @port_id [in]: port ID .
81  * @pdr_idx [in]: PDR index.
82  * @meter_idx [in]: meter index.
83  * @return: offset in meter table.
84  */
85 static inline uint32_t upf_accel_shared_meters_table_offset_get(enum upf_accel_port port_id,
86  uint32_t pdr_idx,
87  uint32_t meter_idx)
88 {
89  const uint32_t num_meters_per_port = UPF_ACCEL_MAX_PDR_NUM_RATE_METERS * UPF_ACCEL_MAX_NUM_PDR;
90 
91  return (port_id * num_meters_per_port) + UPF_ACCEL_MAX_PDR_NUM_RATE_METERS * pdr_idx + meter_idx;
92 }
93 
94 /*
95  * Clamp rate
96  *
97  * @val [in]: rate.
98  * @return: rate clamped to [1, inf]
99  */
100 static inline uint64_t upf_accel_clamp_rate(uint64_t val)
101 {
102  return val > 0 ? val : 1;
103 }
104 
105 /*
106  * Returns the index of a given pdr pointer located in pdrs.
107  *
108  * @pdrs [in]: PDRs struct
109  * @pdr [in]: PDR pointer from PDRs struct
110  * @return: pdr index in pdrs
111  */
112 static inline uint32_t upf_accel_get_pdr_index_from_pdrs(const struct upf_accel_pdrs *pdrs,
113  const struct upf_accel_pdr *pdr)
114 {
115  if ((pdr < pdrs->arr_pdrs) || (pdr >= pdrs->arr_pdrs + pdrs->num_pdrs)) {
116  DOCA_LOG_ERR("Given PDR is not part of pdrs.");
117  assert(0);
118  }
119 
120  return pdr - pdrs->arr_pdrs;
121 }
122 
123 /*
124  * Returns QER by a given QER ID.
125  *
126  * @qers [in]: QERs struct
127  * @qer_id [in]: QER ID
128  * @return: qer pointer in qers
129  */
130 static inline struct upf_accel_qer *upf_accel_get_qer_by_qer_id(struct upf_accel_qers *qers, uint32_t qer_id)
131 {
132  uint32_t i;
133 
134  for (i = 0; i < qers->num_qers; ++i) {
135  if (qers->arr_qers[i].id == qer_id) {
136  return &qers->arr_qers[i];
137  }
138  }
139 
140  DOCA_LOG_ERR("Failed to find qer ID %u", qer_id);
141  assert(0);
142 
143  return qers->arr_qers;
144 }
145 
146 /*
147  * Shared meters init for a given port
148  *
149  * @upf_accel_ctx [in]: UPF Acceleration context.
150  * @cfg [in]: shared resource configuration.
151  * @qer [in]: UPF PDR
152  * @port_id [in]: port ID.
153  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
154  */
157  const struct upf_accel_pdr *pdr,
158  enum upf_accel_port port_id)
159 {
160  struct doca_flow_port *port = upf_accel_ctx->ports[port_id];
162  uint32_t ids_array[UPF_ACCEL_MAX_NUM_PDR] = {0};
163  struct upf_accel_qer *qer;
164  uint64_t ul_cir_cbs;
165  uint64_t dl_cir_cbs;
167  uint32_t meter_idx;
168  uint32_t i;
169 
170  for (i = 0; i < pdr->qerids_num; ++i) {
171  qer = upf_accel_get_qer_by_qer_id(qers, pdr->qerids[i]);
172 
173  /*
174  * QER MBR units: 1 kilobit per second.
175  * CBS units: 1 byte per second.
176  */
177  ul_cir_cbs = upf_accel_clamp_rate(1000 * (qer->mbr_ul_mbr / CHAR_BIT));
178  dl_cir_cbs = upf_accel_clamp_rate(1000 * (qer->mbr_dl_mbr / CHAR_BIT));
179 
181  port_id,
183  i);
184  cfg->meter_cfg.cir = cfg->meter_cfg.cbs = (pdr->pdi_si == UPF_ACCEL_PDR_PDI_SI_UL) ? ul_cir_cbs :
185  dl_cir_cbs;
187  if (result != DOCA_SUCCESS) {
188  DOCA_LOG_ERR("Failed to cfg shared meter");
190  return result;
191  }
192 
193  ids_array[i] = meter_idx;
194  }
195 
197  if (result != DOCA_SUCCESS) {
198  DOCA_LOG_ERR("Failed to bind shared meters to port");
199  return result;
200  }
201 
202  return DOCA_SUCCESS;
203 }
204 
205 /*
206  * Init shared meters level - one for each port and for each domain
207  *
208  * @upf_accel_ctx [in]: UPF Acceleration context.
209  * @pdr [in]: UPF PDR
210  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
211  */
213  const struct upf_accel_pdr *pdr)
214 {
215  struct doca_flow_shared_resource_cfg cfg = {.meter_cfg = {.limit_type = DOCA_FLOW_METER_LIMIT_TYPE_BYTES,
216  .color_mode = DOCA_FLOW_METER_COLOR_MODE_BLIND,
218  .rfc2697.ebs = 0}};
219  enum upf_accel_port port_id;
221 
222  for (port_id = 0; port_id < upf_accel_ctx->num_ports; port_id++) {
224  if (result != DOCA_SUCCESS) {
225  DOCA_LOG_ERR("Failed to init DOCA shared meters port %u tx: %s",
226  port_id,
228  return result;
229  }
230  }
231 
232  return DOCA_SUCCESS;
233 }
234 
235 /*
236  * Init all shared meters level
237  *
238  * @upf_accel_ctx [in]: UPF Acceleration context.
239  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
240  */
242 {
244  const struct upf_accel_pdr *pdr;
246  uint32_t pdr_idx;
247 
248  for (pdr_idx = 0; pdr_idx < pdrs->num_pdrs; ++pdr_idx) {
249  pdr = &pdrs->arr_pdrs[pdr_idx];
250 
252  if (result != DOCA_SUCCESS) {
253  DOCA_LOG_ERR("Failed to init DOCA shared meters of pdr %u: %s",
254  pdr_idx,
256  return result;
257  }
258  }
259 
260  return DOCA_SUCCESS;
261 }
262 
263 /*
264  * Insert a static PDR entry
265  *
266  * @upf_accel_ctx [in]: UPF Acceleration context.
267  * @cfg [in]: entry configuration.
268  * @entry [out]: Resulting entry.
269  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
270  */
272  struct upf_accel_entry_cfg *cfg,
273  struct doca_flow_pipe_entry **entry)
274 {
276  cfg->port_id,
277  0,
278  cfg->pipe,
279  cfg->match,
280  cfg->action,
281  cfg->mon,
282  cfg->fwd,
283  0,
284  &upf_accel_ctx->static_entry_ctx[cfg->port_id],
285  entry);
286  if (result != DOCA_SUCCESS) {
287  DOCA_LOG_ERR("Failed to add pdr entry: %s", doca_error_get_descr(result));
288  return result;
289  }
290 
291  return result;
292 }
293 
294 /*
295  * Get far struct that has ID matching to far_id
296  *
297  * @fars [in]: A struct containing all the fars pf the app.
298  * @far_id [in]: FAR ID.
299  * @return: A pointer to the far with far_id on success and NULL otherwise.
300  */
301 static inline const struct upf_accel_far *upf_accel_get_far_by_id(const struct upf_accel_fars *fars, uint32_t far_id)
302 {
303  for (uint32_t i = 0; i < fars->num_fars; ++i) {
304  if (fars->arr_fars[i].id == far_id)
305  return &fars->arr_fars[i];
306  }
307 
308  return NULL;
309 }
310 
311 /*
312  * Insert entry to the encap & counter pipe
313  *
314  * @upf_accel_ctx [in]: UPF Acceleration context.
315  * @pdr_idx [in]: Location of PDR in the PDRs array.
316  * @pdr_id [in]: PDR ID.
317  * @far_id [in]: FAR ID.
318  * @qfi [in]: QFI ID or 0 if doesn't exist.
319  * @port_id [in]: port ID.
320  * @entry [out]: Resulting entry.
321  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
322  */
324  uint32_t pdr_idx,
325  uint32_t pdr_id,
326  uint32_t far_id,
327  uint8_t qfi,
328  enum upf_accel_pdr_pdi_si pdi_si,
329  enum upf_accel_port port_id,
330  struct doca_flow_pipe_entry **entry)
331 {
333  struct doca_flow_actions act_enc = {.action_idx = (!!qfi) ? UPF_ACCEL_ENCAP_ACTION_5G :
335  .encap_cfg.encap = {.tun = {
336  .gtp_ext_psc_qfi = qfi & 0x3f,
337  }}};
339  struct doca_flow_monitor mon = {
340  .shared_counter = {.shared_counter_id = port_id_and_idx_to_quota_counter(port_id, pdr_idx)}};
341  struct doca_flow_match match = {.meta.pkt_meta = DOCA_HTOBE32(pdr_id)};
342  struct upf_accel_entry_cfg entry_cfg = {.match = &match,
343  .action = (pdi_si == UPF_ACCEL_PDR_PDI_SI_DL) ? &act_enc : &act_none,
344  .fwd = NULL,
346  .entry_idx = pdr_id,
347  .port_id = port_id,
348  .mon = &mon,
350 
351  if (far == NULL) {
352  DOCA_LOG_ERR("Couldn't find FAR ID");
354  }
355  act_enc.encap_cfg.encap.outer.ip4.dst_ip = RTE_BE32(far->fp_oh_ip.v4);
356  act_enc.encap_cfg.encap.tun.gtp_teid = RTE_BE32(far->fp_oh_teid);
357 
358  if (pipe_pdr_insert(upf_accel_ctx, &entry_cfg, entry)) {
359  DOCA_LOG_ERR("Failed to insert pdr entry: %u", DOCA_BETOH32(entry_cfg.match->meta.pkt_meta));
360  return -1;
361  }
362 
363  return DOCA_SUCCESS;
364 }
365 
366 /*
367  * Insert entry to the both directions counter pipes
368  *
369  * @upf_accel_ctx [in]: UPF Acceleration context.
370  * @pdr_idx [in]: Location of PDR in the PDRs array.
371  * @pdr_id [in]: PDR ID.
372  * @far_id [in]: FAR ID.
373  * @qfi [in]: QFI ID or 0 if doesn't exist.
374  * @entry [out]: pipe entries.
375  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
376  */
378  uint32_t pdr_idx,
379  uint32_t pdr_id,
380  uint32_t far_id,
381  uint8_t qfi,
382  enum upf_accel_pdr_pdi_si pdi_si,
383  struct doca_flow_pipe_entry **entry)
384 {
385  enum upf_accel_port port_id;
386 
387  for (port_id = 0; port_id < upf_accel_ctx->num_ports; port_id++) {
389  pdr_idx,
390  pdr_id,
391  far_id,
392  qfi,
393  pdi_si,
394  port_id,
395  &entry[port_id])) {
396  DOCA_LOG_ERR("Failed to insert encap entry in port %u, pdr_id: %u", port_id, pdr_id);
397  return -1;
398  }
399  }
400 
401  return DOCA_SUCCESS;
402 }
403 
404 /*
405  * Insert entry to the shared meters pipe
406  *
407  * @upf_accel_ctx [in]: UPF Acceleration context.
408  * @pdr_idx [in]: index of PDR in the PDRs array.
409  * @qer_idx [in]: index of QER in the PDR's QERs array.
410  * @port_id [in]: port ID .
411  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
412  */
414  uint32_t pdr_idx,
415  uint32_t qer_idx,
416  enum upf_accel_port port_id)
417 {
418  const struct upf_accel_pdrs *pdrs = upf_accel_ctx->upf_accel_cfg->pdrs;
419  const struct upf_accel_pdr *pdr = &pdrs->arr_pdrs[pdr_idx];
420  struct doca_flow_match match = {.meta.pkt_meta = DOCA_HTOBE32(pdr->id)};
421  struct doca_flow_monitor mon = {
423  };
424  struct doca_flow_fwd fwd = {
426  .next_pipe = qer_idx == (pdr->qerids_num - 1) ?
429  struct upf_accel_entry_cfg entry_cfg = {
432  .match = &match,
433  .fwd = &fwd,
434  .action = NULL,
435  .mon = &mon,
436  .entry_idx = pdr->id,
437  .port_id = port_id};
438 
439  mon.shared_meter.shared_meter_id = upf_accel_shared_meters_table_offset_get(port_id, pdr_idx, qer_idx);
440 
441  if (pipe_pdr_insert(upf_accel_ctx, &entry_cfg, NULL)) {
442  DOCA_LOG_ERR("Failed to insert p%d tx meter %u entry: %u", port_id, qer_idx, pdr->id);
443  return -1;
444  }
445 
446  return DOCA_SUCCESS;
447 }
448 
449 /*
450  * Insert entry to the both directions shared meters pipes
451  *
452  * @upf_accel_ctx [in]: UPF Acceleration context.
453  * @pdr_idx [in]: index of PDR in the PDRs array.
454  * @qer_idx [in]: index of QER in the PDR's QERs array.
455  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
456  */
457 static doca_error_t pipe_shared_meter_insert(struct upf_accel_ctx *upf_accel_ctx, uint32_t pdr_idx, uint32_t qer_idx)
458 {
459  enum upf_accel_port port_id;
461 
462  for (port_id = 0; port_id < upf_accel_ctx->num_ports; port_id++) {
464  if (result != DOCA_SUCCESS) {
465  DOCA_LOG_ERR("Failed to insert PDR rule to port %u meter tables: %s",
466  port_id,
468  return result;
469  }
470  }
471  return DOCA_SUCCESS;
472 }
473 
474 /*
475  * Add all SMF related rules
476  *
477  * @upf_accel_ctx [in]: UPF Acceleration context.
478  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
479  */
481 {
482  const struct upf_accel_pdrs *pdrs = upf_accel_ctx->upf_accel_cfg->pdrs;
483  const size_t num_pdrs = pdrs->num_pdrs;
484  const struct upf_accel_pdr *pdr;
485  struct upf_accel_qer *qer;
487  uint32_t pdr_idx;
488  uint32_t far_id;
489  uint8_t qfi;
490  int pdr_id;
491  uint32_t i;
492 
493  for (pdr_idx = 0; pdr_idx < num_pdrs; pdr_idx++) {
494  pdr = &pdrs->arr_pdrs[pdr_idx];
495  far_id = pdr->farid;
496  pdr_id = pdr->id;
498 
499  if (pdr->qerids_num) {
500  /* QFI is chosen randomly since different QERs might have different QFI values */
502  pdr->qerids[pdr->qerids_num - 1]);
503  qfi = qer->qfi;
504  }
505 
507  pdr_idx,
508  pdr_id,
509  far_id,
510  qfi,
511  pdr->pdi_si,
512  upf_accel_ctx->smf_entries[pdr_idx]);
513  if (result != DOCA_SUCCESS)
514  return result;
515 
516  for (i = 0; i < pdr->qerids_num; ++i) {
518  if (result != DOCA_SUCCESS)
519  return result;
520  }
521  }
522 
523  return DOCA_SUCCESS;
524 }
525 
526 /*
527  * Alloc and populate the counter IDs used for quota enforcement
528  *
529  * The indexes of the counters are organized as followed:
530  * For PDR with ID i:
531  * port 0 counter index is i
532  * port 1 counter index is <num_of_shared_counters_per_port> + i
533  *
534  * @start_idx [in]: first pdr/index to start with
535  * @num_ports [in]: number of ports
536  * @num_cntrs [in]: number of counters
537  * @shared_counter_ids [in/out]: pointer to store the result at
538  * @return: DOCA_SUCCESS on success and DOCA_ERROR_NO_MEMORY otherwise
539  */
541  size_t num_ports,
542  size_t num_cntrs,
543  struct app_shared_counter_ids *shared_counter_ids)
544 {
545  enum upf_accel_port port_id;
546  uint32_t i;
547 
548  shared_counter_ids->cntr_0 = start_idx;
549  shared_counter_ids->cntrs_num = num_cntrs;
550 
551  if (!num_cntrs)
552  return DOCA_SUCCESS;
553 
554  for (port_id = 0; port_id < num_ports; port_id++) {
555  shared_counter_ids->ids[port_id] =
556  rte_calloc("Counter IDS", num_cntrs, sizeof(uint32_t), RTE_CACHE_LINE_SIZE);
557  if (!shared_counter_ids->ids[port_id]) {
558  DOCA_LOG_ERR("Failed to allocate Counter IDS array for port %u", port_id);
559  goto cleanup;
560  }
561 
562  for (i = 0; i < num_cntrs; ++i) {
563  shared_counter_ids->ids[port_id][i] = port_id_and_idx_to_quota_counter(port_id, start_idx + i);
564  }
565  }
566 
567  return DOCA_SUCCESS;
568 
569 cleanup:
570  while (port_id--)
571  rte_free(shared_counter_ids->ids[port_id]);
572  return DOCA_ERROR_NO_MEMORY;
573 }
574 
575 /*
576  * Free the counter IDs arrays
577  *
578  * @shared_counter_ids [in]: Container of IDs to be released
579  * @num_ports [in]: number of ports
580  */
581 static void free_quota_counters_ids(struct app_shared_counter_ids *shared_counter_ids, uint16_t num_ports)
582 {
583  enum upf_accel_port port_id;
584 
585  for (port_id = 0; port_id < num_ports; port_id++)
586  rte_free(shared_counter_ids->ids[port_id]);
587 }
588 
589 /*
590  * Calculate Hash Table size per core
591  *
592  * The total amount of connections supported on each pipe is defined by
593  * UPF_ACCEL_MAX_NUM_CONNECTIONS,
594  * On each port we have 2 pipes (WAN: 5t_udp + 5t_tcp, RAN: 7t + 8t) so the
595  * maximum connections per port is 2 * UPF_ACCEL_MAX_NUM_CONNECTIONS.
596  * Then the result is distributed between the cores.
597  * In addition, to each core some entries are added for failed acceleration connections.
598  *
599  * @num_cores [in]: number of cores
600  * @return: hash table size per core
601  */
602 static uint32_t calculate_hash_table_size(uint16_t num_cores)
603 {
604  uint32_t max_conn_per_port = 2 * UPF_ACCEL_MAX_NUM_CONNECTIONS;
605  uint32_t num_conn_per_core = (max_conn_per_port + num_cores - 1) / num_cores;
606 
607  return num_conn_per_core + UPF_ACCEL_MAX_NUM_FAILED_ACCEL_PER_CORE;
608 };
609 
610 /*
611  * Initiate the counters used for quota enforcement
612  *
613  * Quota enforcement counters defined by QER which we consume from
614  * the PDR description (if exists), hence, the number of counters we'll have
615  * will be at most as the number of PDRs, but per port (i.e. twice).
616  *
617  * @upf_accel_ctx [in]: UPF Acceleration context.
618  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
619  */
621 {
622  struct doca_flow_shared_resource_cfg cfg = {0};
623  struct app_shared_counter_ids shared_counter_ids;
624  enum upf_accel_port port_id;
626  uint32_t i;
627 
631  &shared_counter_ids);
632  if (result != DOCA_SUCCESS) {
633  DOCA_LOG_ERR("Failed to populate quota counters ids");
634  return result;
635  }
636 
637  for (port_id = 0; port_id < upf_accel_ctx->num_ports; port_id++) {
638  for (i = 0; i < upf_accel_ctx->upf_accel_cfg->pdrs->num_pdrs; ++i) {
640  shared_counter_ids.ids[port_id][i],
641  &cfg);
642  if (result != DOCA_SUCCESS) {
643  DOCA_LOG_ERR("Failed to configure shared counter %u to port %d", i, port_id);
644  goto cleanup;
645  }
646  }
648  shared_counter_ids.ids[port_id],
650  upf_accel_ctx->ports[port_id]);
651  if (result != DOCA_SUCCESS) {
652  DOCA_LOG_ERR("Failed to bind shared counter to port %d", port_id);
653  goto cleanup;
654  }
655  }
656 
657 cleanup:
658  free_quota_counters_ids(&shared_counter_ids, upf_accel_ctx->num_ports);
659  return result;
660 }
661 /*
662  * Cleanup and free UPF Acceleration flow processing data
663  *
664  * @fp_data_arr [in]: flow processing data array
665  */
666 static void upf_accel_fp_data_cleanup(struct upf_accel_fp_data *fp_data_arr)
667 {
668  struct upf_accel_fp_data *fp_data;
669  unsigned int lcore;
670 
671  RTE_LCORE_FOREACH_WORKER(lcore)
672  {
673  fp_data = &fp_data_arr[lcore];
674 
675  free_quota_counters_ids(&fp_data->quota_cntrs, fp_data->ctx->num_ports);
676  rte_free(fp_data->dyn_tbl_data);
677  rte_hash_free(fp_data->dyn_tbl);
678  }
679 
680  rte_free(fp_data_arr);
681 }
682 
683 /*
684  * Allocate and initialize UPF Acceleration flow processing data
685  *
686  * @ctx [in]: UPF Acceleration context
687  * @fp_data_arr_out [out]: flow processing data array
688  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
689  */
690 static doca_error_t upf_accel_fp_data_init(struct upf_accel_ctx *ctx, struct upf_accel_fp_data **fp_data_arr_out)
691 {
692  uint16_t num_cores = rte_lcore_count() - 1;
693 
694  assert(num_cores > 0);
695  uint16_t quota_cntrs_per_core_num = ctx->upf_accel_cfg->pdrs->num_pdrs / num_cores;
696  uint16_t quota_cntrs_remainder_num = ctx->upf_accel_cfg->pdrs->num_pdrs % num_cores;
697  uint32_t ht_size = calculate_hash_table_size(num_cores);
698  char mem_name[RTE_MEMZONE_NAMESIZE];
699  struct rte_hash_parameters dyn_tbl_params = {
700  .name = mem_name,
701  .entries = ht_size,
702  .key_len = sizeof(struct upf_accel_match_5t),
703  .hash_func = rte_hash_crc,
704  .hash_func_init_val = 0,
705  .socket_id = rte_socket_id(),
706  .extra_flag = RTE_HASH_EXTRA_FLAGS_EXT_TABLE,
707  };
708  uint16_t curr_quota_base_cntr_idx = 0;
709  struct upf_accel_fp_data *fp_data_arr;
710  struct upf_accel_fp_data *fp_data;
711  uint16_t queue_id = 1;
712  unsigned int lcore;
713  size_t num_cntrs;
714  doca_error_t res;
715 
716  fp_data_arr = rte_calloc("FP data", RTE_MAX_LCORE, sizeof(*fp_data), RTE_CACHE_LINE_SIZE);
717  if (!fp_data_arr) {
718  DOCA_LOG_ERR("Failed to allocate FP data");
719  return DOCA_ERROR_NO_MEMORY;
720  }
721 
722  DOCA_LOG_DBG("Main core is %u", rte_get_main_lcore());
723 
724  RTE_LCORE_FOREACH_WORKER(lcore)
725  {
726  fp_data = &fp_data_arr[lcore];
727 
728  snprintf(mem_name, sizeof(mem_name), "Dyn conn ht %u", lcore);
729  fp_data->dyn_tbl = rte_hash_create(&dyn_tbl_params);
730  if (!fp_data->dyn_tbl) {
731  DOCA_LOG_ERR("Failed to allocate dynamic connection table");
732  res = DOCA_ERROR_NO_MEMORY;
733  goto cleanup;
734  }
735 
736  snprintf(mem_name, sizeof(mem_name), "Dyn conn data %u", lcore);
737  fp_data->dyn_tbl_data = rte_calloc(mem_name,
738  dyn_tbl_params.entries,
739  sizeof(*fp_data->dyn_tbl_data),
740  RTE_CACHE_LINE_SIZE);
741  if (!fp_data->dyn_tbl_data) {
742  DOCA_LOG_ERR("Failed to allocate dynamic connection table data");
743  res = DOCA_ERROR_NO_MEMORY;
744  goto cleanup;
745  }
746 
747  num_cntrs = quota_cntrs_per_core_num;
748  /* The remainder is distributed among the first cores so that it is almost evenly distributed */
749  if (quota_cntrs_remainder_num) {
750  num_cntrs++;
751  quota_cntrs_remainder_num--;
752  }
753 
754  res = alloc_and_populate_quota_counters_ids(curr_quota_base_cntr_idx,
755  ctx->num_ports,
756  num_cntrs,
757  &fp_data->quota_cntrs);
758  if (res != DOCA_SUCCESS) {
759  DOCA_LOG_ERR("Failed to populate quota counters ids for core %u", lcore);
760  goto cleanup;
761  }
762  curr_quota_base_cntr_idx += num_cntrs;
763 
764  fp_data->ctx = ctx;
765  fp_data->queue_id = queue_id++;
766 
769 
770  DOCA_LOG_DBG("FP core %u data initialized", lcore);
771  }
772 
773  *fp_data_arr_out = fp_data_arr;
774  return DOCA_SUCCESS;
775 
776 cleanup:
777  upf_accel_fp_data_cleanup(fp_data_arr);
778  return res;
779 }
780 
781 /*
782  * Print FP SW debug counters of each worker
783  *
784  * @fp_data_arr [in]: flow processing data array
785  */
786 static void upf_accel_fp_sw_counters_print(struct upf_accel_fp_data *fp_data_arr)
787 {
788  struct upf_accel_fp_sw_counters sw_sum = {0};
790  struct upf_accel_fp_data *fp_data;
791  unsigned int lcore;
792 
793  DOCA_LOG_INFO("//////////////////// SW DATAPATH COUNTERS ////////////////////");
794 
795  RTE_LCORE_FOREACH_WORKER(lcore)
796  {
797  fp_data = &fp_data_arr[lcore];
798  sw_counters = &fp_data->sw_counters;
799 
801  "Core %3u sw new_pkts=%-8lu new_bytes=%-8lu ex_pkts=%-8lu ex_bytes=%-8lu err_pkts=%-8lu err_bytes=%-8lu",
802  lcore,
803  sw_counters->new_conn.pkts,
804  sw_counters->new_conn.bytes,
805  sw_counters->ex_conn.pkts,
806  sw_counters->ex_conn.bytes,
807  sw_counters->err.pkts,
808  sw_counters->err.bytes);
809 
810  sw_sum.new_conn.pkts += sw_counters->new_conn.pkts;
811  sw_sum.new_conn.bytes += sw_counters->new_conn.bytes;
812  sw_sum.ex_conn.pkts += sw_counters->ex_conn.pkts;
813  sw_sum.ex_conn.bytes += sw_counters->ex_conn.bytes;
814  sw_sum.err.pkts += sw_counters->err.pkts;
815  sw_sum.err.bytes += sw_counters->err.bytes;
816  }
817 
819  "TOTAL sw new_pkts=%-8lu new_bytes=%-8lu ex_pkts=%-8lu ex_bytes=%-8lu err_pkts=%-8lu err_bytes=%-8lu",
820  sw_sum.new_conn.pkts,
821  sw_sum.new_conn.bytes,
822  sw_sum.ex_conn.pkts,
823  sw_sum.ex_conn.bytes,
824  sw_sum.err.pkts,
825  sw_sum.err.bytes);
826 }
827 
828 /*
829  * Print FP HW acceleration debug counters of each worker
830  *
831  * @fp_data_arr [in]: flow processing data array
832  * @name [in]: name of the acceleration counters
833  * @failed [in]: A flag for printing the successful acceleration counters
834  * (false) or those of the failed (true)
835  */
836 static void upf_accel_fp_accel_counters_print(struct upf_accel_fp_data *fp_data_arr, const char *name)
837 {
838  struct upf_accel_fp_accel_counters *ran_counters;
839  struct upf_accel_fp_accel_counters *wan_counters;
840  struct upf_accel_fp_accel_counters ran_sum = {0};
841  struct upf_accel_fp_accel_counters wan_sum = {0};
842  struct upf_accel_fp_data *fp_data;
843  unsigned int lcore;
844 
845  DOCA_LOG_INFO("//////////////////// %s COUNTERS ////////////////////", name);
846 
847  RTE_LCORE_FOREACH_WORKER(lcore)
848  {
849  fp_data = &fp_data_arr[lcore];
850  if (strcmp(name, "ACCELERATED") == 0) {
851  ran_counters = &fp_data->accel_counters[PARSER_PKT_TYPE_TUNNELED];
852  wan_counters = &fp_data->accel_counters[PARSER_PKT_TYPE_PLAIN];
853  } else if (strcmp(name, "NOT ACCELERATED") == 0) {
854  ran_counters = &fp_data->unaccel_counters[PARSER_PKT_TYPE_TUNNELED];
855  wan_counters = &fp_data->unaccel_counters[PARSER_PKT_TYPE_PLAIN];
856  } else if (strcmp(name, "ACCELERATION FAILED") == 0) {
857  ran_counters = &fp_data->accel_failed_counters[PARSER_PKT_TYPE_TUNNELED];
858  wan_counters = &fp_data->accel_failed_counters[PARSER_PKT_TYPE_PLAIN];
859  } else {
860  DOCA_LOG_ERR("Unknowon counters name");
861  return;
862  }
863 
865  "Core %3u %s ran_current=%-8lu ran_aged=%-8lu ran_total=%-8lu ran_errors=%-8lu ran_aging_errors=%-8lu wan_current=%-8lu wan_aged=%-8lu wan_total=%-8lu wan_errors=%-8lu wan_aging_errors=%-8lu",
866  lcore,
867  name,
868  ran_counters->current,
869  ran_counters->total - ran_counters->current,
870  ran_counters->total,
871  ran_counters->errors,
872  ran_counters->aging_errors,
873  wan_counters->current,
874  wan_counters->total - wan_counters->current,
875  wan_counters->total,
876  wan_counters->errors,
877  wan_counters->aging_errors);
878 
879  ran_sum.current += ran_counters->current;
880  ran_sum.total += ran_counters->total;
881  ran_sum.errors += ran_counters->errors;
882  ran_sum.aging_errors += ran_counters->aging_errors;
883  wan_sum.current += wan_counters->current;
884  wan_sum.total += wan_counters->total;
885  wan_sum.errors += wan_counters->errors;
886  wan_sum.aging_errors += wan_counters->aging_errors;
887  }
888 
890  "TOTAL %s ran_current=%-8lu ran_aged=%-8lu ran_total=%-8lu ran_errors=%-8lu ran_aging_errors=%-8lu wan_current=%-8lu wan_aged=%-8lu wan_total=%-8lu wan_errors=%-8lu wan_aging_errors=%-8lu",
891  name,
892  ran_sum.current,
893  ran_sum.total - ran_sum.current,
894  ran_sum.total,
895  ran_sum.errors,
896  ran_sum.aging_errors,
897  wan_sum.current,
898  wan_sum.total - wan_sum.current,
899  wan_sum.total,
900  wan_sum.errors,
901  wan_sum.aging_errors);
902 }
903 
904 /*
905  * Print PDR counters of each worker
906  *
907  * @upf_accel_ctx [in]: UPF Acceleration context
908  */
910 {
911  const struct upf_accel_pdrs *pdrs = upf_accel_ctx->upf_accel_cfg->pdrs;
912  struct doca_flow_resource_query pdr_sum = {0};
913  struct doca_flow_resource_query pdr_stats;
914  const struct upf_accel_pdr *pdr;
915  enum upf_accel_port port_id;
917  uint32_t pdr_idx;
918  int pdr_id;
919 
920  DOCA_LOG_INFO("//////////////////// HW PDR COUNTERS ////////////////////");
921 
922  for (pdr_idx = 0; pdr_idx < pdrs->num_pdrs; pdr_idx++) {
923  pdr = &pdrs->arr_pdrs[pdr_idx];
924  pdr_id = pdr->id;
925 
926  pdr_sum.counter.total_pkts = 0;
927  pdr_sum.counter.total_bytes = 0;
928 
929  for (port_id = 0; port_id < upf_accel_ctx->num_ports; port_id++) {
931  &pdr_stats);
932  if (result != DOCA_SUCCESS) {
933  DOCA_LOG_ERR("Error querying port %u PDR counter %d: %s",
934  port_id,
935  pdr_id,
937  continue;
938  }
939 
940  DOCA_LOG_INFO("PDR %2d Port %d pkts=%-8lu bytes=%-8lu",
941  pdr_id,
942  port_id,
943  pdr_stats.counter.total_pkts,
944  pdr_stats.counter.total_bytes);
945 
946  pdr_sum.counter.total_pkts += pdr_stats.counter.total_pkts;
947  pdr_sum.counter.total_bytes += pdr_stats.counter.total_bytes;
948  }
949 
950  DOCA_LOG_INFO("PDR %2d TOTAL pkts=%-8lu bytes=%-8lu",
951  pdr_id,
952  pdr_sum.counter.total_pkts,
953  pdr_sum.counter.total_bytes);
954  }
955 }
956 
957 /*
958  * Print Drop Counter
959  *
960  * @upf_accel_ctx [in]: UPF Acceleration context
961  * @drop_type [in]: Drop pipe type
962  */
964 {
965  struct doca_flow_resource_query rx_dropped_stats, rx_dropped_stats_sum = {0};
966  struct doca_flow_resource_query tx_dropped_stats, tx_dropped_stats_sum = {0};
967  struct doca_flow_pipe_entry **entries = upf_accel_ctx->drop_entries[drop_type];
968  enum upf_accel_port port_id;
970  uint8_t entry_idx;
971  char *name;
972 
973  switch (drop_type) {
974  case UPF_ACCEL_DROP_DBG:
975  name = "Debug";
976  break;
977  case UPF_ACCEL_DROP_RATE:
978  name = "Rate";
979  break;
981  name = "Filter";
982  break;
983  default:
984  assert(0);
985  name = "Error!";
986  }
987 
988  for (port_id = 0; port_id < upf_accel_ctx->num_ports; port_id++) {
991  if (result != DOCA_SUCCESS) {
992  DOCA_LOG_ERR("Error querying port %u RX %s Drop counter: %s",
993  port_id,
994  name,
996  return;
997  }
1000  if (result != DOCA_SUCCESS) {
1001  DOCA_LOG_ERR("Error querying port %u TX %s Drop counter: %s",
1002  port_id,
1003  name,
1005  return;
1006  }
1007 
1008  DOCA_LOG_INFO("Port %d DROP %-8s rx_pkts=%-8lu tx_pkts=%-8lu",
1009  port_id,
1010  name,
1011  rx_dropped_stats.counter.total_pkts,
1012  tx_dropped_stats.counter.total_pkts);
1013 
1014  rx_dropped_stats_sum.counter.total_pkts += rx_dropped_stats.counter.total_pkts;
1015  tx_dropped_stats_sum.counter.total_pkts += tx_dropped_stats.counter.total_pkts;
1016  }
1017 
1018  DOCA_LOG_INFO("TOTAL DROP %-8s rx_pkts=%-8lu tx_pkts=%-8lu",
1019  name,
1020  rx_dropped_stats_sum.counter.total_pkts,
1021  tx_dropped_stats_sum.counter.total_pkts);
1022 }
1023 
1024 /*
1025  * Print Counters of The Static HW entries
1026  *
1027  * @upf_accel_ctx [in]: UPF Acceleration context
1028  */
1030 {
1031  int i;
1032 
1033  DOCA_LOG_INFO("//////////////////// STATIC HW COUNTERS ////////////////////");
1034 
1035  for (i = 0; i < UPF_ACCEL_DROP_NUM; i++)
1037 }
1038 
1039 /*
1040  * Print FP debug counters of each worker
1041  *
1042  * @upf_accel_ctx [in]: UPF Acceleration context
1043  * @fp_data_arr [in]: flow processing data array
1044  */
1046 {
1047  DOCA_LOG_INFO("");
1048  upf_accel_fp_sw_counters_print(fp_data_arr);
1049  DOCA_LOG_INFO("");
1050  upf_accel_fp_accel_counters_print(fp_data_arr, "ACCELERATED");
1051  DOCA_LOG_INFO("");
1052  upf_accel_fp_accel_counters_print(fp_data_arr, "NOT ACCELERATED");
1053  DOCA_LOG_INFO("");
1054  upf_accel_fp_accel_counters_print(fp_data_arr, "ACCELERATION FAILED");
1055  DOCA_LOG_INFO("");
1057  DOCA_LOG_INFO("");
1059  DOCA_LOG_INFO("");
1060 }
1061 
1062 /*
1063  * Mask signals that will be handled by the application main loop
1064  *
1065  * @sigset [out]: Set of masked signals
1066  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1067  */
1068 static doca_error_t upf_accel_signals_mask(sigset_t *sigset)
1069 {
1070  int ret;
1071 
1072  sigemptyset(sigset);
1073  sigaddset(sigset, SIGINT);
1074  sigaddset(sigset, SIGTERM);
1075  sigaddset(sigset, SIGUSR1);
1076 
1077  ret = pthread_sigmask(SIG_BLOCK, sigset, NULL);
1078  if (ret) {
1079  DOCA_LOG_ERR("Failed to apply signal mask: %s", strerror(ret));
1080  return DOCA_ERROR_UNEXPECTED;
1081  }
1082 
1083  return DOCA_SUCCESS;
1084 }
1085 
1086 /*
1087  * FP thread main run loop
1088  *
1089  * @param [in]: Array of FP data structures
1090  * @return: 0 on success and system error code otherwise
1091  */
1092 static int upf_accel_fp_loop_wrapper(void *param)
1093 {
1094  struct upf_accel_fp_data *fp_data_arr = param;
1095 
1096  upf_accel_fp_loop(&fp_data_arr[rte_lcore_id()]);
1097  return 0;
1098 }
1099 
1100 /*
1101  * Calculate the maximum number of shared meters needed
1102  *
1103  * @num_ports [in]: number of ports
1104  * @return: number of shared meters
1105  */
1106 static inline int upf_accel_calc_num_shared_meters(uint16_t num_ports)
1107 {
1111 }
1112 
1113 /*
1114  * Calculate the maximum number of shared counters needed
1115  *
1116  * @num_ports [in]: number of ports
1117  * @return: number of shared counters
1118  */
1119 static inline int upf_accel_calc_num_shared_counters(uint16_t num_ports)
1120 {
1121  return UPF_ACCEL_NUM_QUOTA_COUNTERS_PER_PORT * num_ports;
1122 }
1123 
1124 /*
1125  * Get the forwarding port in single port mode.
1126  * In single port mode packets are sent from the same port.
1127  *
1128  * @port_id [in]: port ID
1129  * @return: the forwarding port
1130  */
1132 {
1133  return port_id;
1134 }
1135 
1136 /*
1137  * UPF Acceleration application deinitialization
1138  *
1139  * @upf_accel_ctx [in/out]: UPF Acceleration context
1140  * @fp_data_arr [in]: UPF Acceleration flow processing data
1141  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1142  */
1144 {
1146 
1148  if (result != DOCA_SUCCESS) {
1149  DOCA_LOG_ERR("Failed to stop doca flow ports: %s", doca_error_get_descr(result));
1150  }
1151 
1152  upf_accel_fp_data_cleanup(fp_data_arr);
1154 
1155  return result;
1156 }
1157 
1158 /*
1159  * UPF Acceleration application initialization
1160  *
1161  * @upf_accel_ctx [in/out]: UPF Acceleration context
1162  * @fp_data_arr [out]: UPF Acceleration flow processing data
1163  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1164  */
1166 {
1168  struct entries_status *ctrl_status;
1169  doca_error_t result, tmp_result;
1170  enum upf_accel_port port_id;
1171 
1173  "vnf,hws",
1177  NULL,
1178  NULL);
1179  if (result != DOCA_SUCCESS) {
1180  DOCA_LOG_ERR("Failed to init DOCA Flow: %s", doca_error_get_descr(result));
1181  return result;
1182  }
1183 
1185  if (result != DOCA_SUCCESS) {
1186  DOCA_LOG_ERR("Failed to init FP data");
1187  goto cleanup_doca_flow;
1188  }
1189 
1193  true,
1196  if (result != DOCA_SUCCESS) {
1197  DOCA_LOG_ERR("Failed to init DOCA ports: %s", doca_error_get_descr(result));
1198  goto cleanup_fp_data;
1199  }
1200 
1202  if (result != DOCA_SUCCESS) {
1203  DOCA_LOG_ERR("Failed to init DOCA shared counters: %s", doca_error_get_descr(result));
1204  goto cleanup_ports;
1205  }
1206 
1208  if (result != DOCA_SUCCESS) {
1209  DOCA_LOG_ERR("Failed to init DOCA shared meters: %s", doca_error_get_descr(result));
1210  goto cleanup_ports;
1211  }
1212 
1214  if (result != DOCA_SUCCESS) {
1215  DOCA_LOG_ERR("Failed to create pipeline: %s", doca_error_get_descr(result));
1216  goto cleanup_ports;
1217  }
1218 
1220  DOCA_LOG_ERR("Failed to add smf rules");
1221  goto cleanup_ports;
1222  }
1223 
1224  for (port_id = 0; port_id < upf_accel_ctx->num_ports; port_id++) {
1225  ctrl_status = &upf_accel_ctx->static_entry_ctx[port_id].static_ctx.ctrl_status;
1226 
1228  0,
1230  upf_accel_ctx->num_static_entries[port_id]);
1231  if (result != DOCA_SUCCESS) {
1232  DOCA_LOG_ERR("Failed to process entries on port %u: %s", port_id, doca_error_get_descr(result));
1233  goto cleanup_ports;
1234  }
1235 
1236  if (ctrl_status->nb_processed != (int)upf_accel_ctx->num_static_entries[port_id] ||
1237  ctrl_status->failure) {
1238  DOCA_LOG_ERR("Failed to process port %u entries", port_id);
1239  goto cleanup_ports;
1240  }
1241  }
1242 
1243  return DOCA_SUCCESS;
1244 
1245 cleanup_ports:
1247  if (tmp_result != DOCA_SUCCESS) {
1248  DOCA_LOG_ERR("Failed to stop doca flow ports: %s", doca_error_get_descr(tmp_result));
1249  }
1250 cleanup_fp_data:
1251  upf_accel_fp_data_cleanup(*fp_data_arr);
1252 cleanup_doca_flow:
1254 
1255  return result;
1256 }
1257 
1258 /*
1259  * UPF Acceleration application logic
1260  *
1261  * @upf_accel_ctx [in]: UPF Acceleration context
1262  * @fp_data_arr [in]: UPF Acceleration flow processing data
1263  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1264  */
1266 {
1268  sigset_t sigset;
1269  int sig;
1270  int ret;
1271 
1272  result = upf_accel_signals_mask(&sigset);
1273  if (result != DOCA_SUCCESS) {
1274  DOCA_LOG_ERR("Failed to mask signals");
1275  return result;
1276  }
1277 
1278  if (rte_eal_mp_remote_launch(upf_accel_fp_loop_wrapper, fp_data_arr, SKIP_MAIN)) {
1279  DOCA_LOG_ERR("Failed to launch FP threads");
1280  return result;
1281  }
1282 
1283  DOCA_LOG_INFO("Waiting for traffic, press Ctrl+C for termination");
1284 
1285  while (!force_quit) {
1286  ret = sigwait(&sigset, &sig);
1287  if (ret) {
1288  DOCA_LOG_ERR("Failed to sigwait: %s", strerror(ret));
1289  return result;
1290  }
1291 
1292  switch (sig) {
1293  case SIGINT:
1294  case SIGTERM:
1295  force_quit = true;
1296  break;
1297  case SIGUSR1:
1299  break;
1300  default:
1301  DOCA_LOG_WARN("Polled unexpected signal %d", sig);
1302  break;
1303  }
1304  }
1305 
1306  rte_eal_mp_wait_lcore();
1307 
1309 
1310  return DOCA_SUCCESS;
1311 }
1312 
1313 /*
1314  * Callback to handle file smf json path
1315  *
1316  * @param [in]: file path
1317  * @config [in]: UPF Acceleration configuration
1318  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1319  */
1320 static doca_error_t smf_config_file_path_callback(void *param, void *config)
1321 {
1322  struct upf_accel_config *cfg = (struct upf_accel_config *)config;
1323  const char *n = (const char *)param;
1324 
1325  cfg->smf_config_file_path = n;
1326 
1327  return DOCA_SUCCESS;
1328 }
1329 
1330 /*
1331  * Callback to handle file vxlan json path
1332  *
1333  * @param [in]: file path
1334  * @config [in]: UPF Acceleration configuration
1335  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1336  */
1337 static doca_error_t vxlan_config_file_path_callback(void *param, void *config)
1338 {
1339  struct upf_accel_config *cfg = (struct upf_accel_config *)config;
1340  const char *n = (const char *)param;
1341 
1342  cfg->vxlan_config_file_path = n;
1343 
1344  return DOCA_SUCCESS;
1345 }
1346 
1347 /*
1348  * Callback to handle file path
1349  *
1350  * @param [in]: file path
1351  * @config [in]: UPF Acceleration configuration
1352  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1353  */
1354 static doca_error_t aging_time_sec_callback(void *param, void *config)
1355 {
1356  struct upf_accel_config *cfg = (struct upf_accel_config *)config;
1357  const uint32_t n = *(const uint32_t *)param;
1358 
1359  cfg->hw_aging_time_sec = n;
1360  cfg->sw_aging_time_sec = n;
1361 
1362  return DOCA_SUCCESS;
1363 }
1364 
1365 /*
1366  * Callback to handle number of pkts before acceleration param
1367  *
1368  * @param [in]: input param (num pkts)
1369  * @config [in]: UPF Acceleration configuration
1370  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1371  */
1372 static doca_error_t pkts_before_accel_callback(void *param, void *config)
1373 {
1374  struct upf_accel_config *cfg = (struct upf_accel_config *)config;
1375  const uint32_t n = *(const uint32_t *)param;
1376 
1377  if (n < 1) {
1378  DOCA_LOG_ERR("Bad param: num-pkts-pefore-accel must be greater or equal to 1");
1379  return DOCA_ERROR_INVALID_VALUE;
1380  }
1381 
1382  cfg->dpi_threshold = n;
1383 
1384  return DOCA_SUCCESS;
1385 }
1386 
1387 /*
1388  * Callback to handle UL port number in fixed port mode
1389  *
1390  * Fixed port mode is a configuration where each port receives only one type
1391  * of packet, either uplink (UL - GTP) or downlink (DL - non-GTP).
1392  * Using the '-p' flag we can activate this mode and specify which port will
1393  * receive UL packets, while the other port will receive DL packets.
1394  *
1395  * In this mode, the uldl_pipe on the designated UL port directs all packets
1396  * to the ext_gtp pipe (without matching on UDP dest port), while on the
1397  * DL port, all packets are directed to the 5t pipe.
1398  *
1399  * This mode is necessary for Trex tests, as packets sent by Trex cannot be
1400  * distinguished between GTP and non-GTP solely by examining the UDP dest port.
1401  *
1402  * @param [in]: input param (UL port number).
1403  * @config [in]: UPF Acceleration configuration.
1404  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1405  */
1406 static doca_error_t fixed_port_callback(void *param, void *config)
1407 {
1408  struct upf_accel_config *cfg = (struct upf_accel_config *)config;
1409  const int32_t n = *(const int32_t *)param;
1410 
1411  if (n < 0 || n >= UPF_ACCEL_PORTS_MAX) {
1412  DOCA_LOG_ERR("Bad param: Invalid fixed-port number.");
1413  return DOCA_ERROR_INVALID_VALUE;
1414  }
1415 
1416  cfg->fixed_port = n;
1417 
1418  return DOCA_SUCCESS;
1419 }
1420 
1421 /*
1422  * Handle application parameters registration
1423  *
1424  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1425  */
1427 {
1428  struct doca_argp_param *pdr_file_path_param;
1429  struct doca_argp_param *vxlan_file_path_param;
1430  struct doca_argp_param *aging_time_sec_param;
1431  struct doca_argp_param *pkts_before_accel_param;
1432  struct doca_argp_param *fixed_port_param;
1434 
1435  /* Create and register UPF Acceleration JSON PDR definitions file path */
1436  result = doca_argp_param_create(&pdr_file_path_param);
1437  if (result != DOCA_SUCCESS) {
1438  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
1439  return result;
1440  }
1441  doca_argp_param_set_short_name(pdr_file_path_param, "f");
1442  doca_argp_param_set_long_name(pdr_file_path_param, "smf-config-file-path");
1443  doca_argp_param_set_description(pdr_file_path_param, "SMF JSON definitions file path");
1445  doca_argp_param_set_type(pdr_file_path_param, DOCA_ARGP_TYPE_STRING);
1446  doca_argp_param_set_mandatory(pdr_file_path_param);
1447  result = doca_argp_register_param(pdr_file_path_param);
1448  if (result != DOCA_SUCCESS) {
1449  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
1450  return result;
1451  }
1452 
1453  /* Create and register UPF Acceleration JSON VXLAN definitions file path */
1454  result = doca_argp_param_create(&vxlan_file_path_param);
1455  if (result != DOCA_SUCCESS) {
1456  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
1457  return result;
1458  }
1459  doca_argp_param_set_short_name(vxlan_file_path_param, "x");
1460  doca_argp_param_set_long_name(vxlan_file_path_param, "vxlan-config-file-path");
1461  doca_argp_param_set_description(vxlan_file_path_param, "VXLAN JSON definitions file path");
1463  doca_argp_param_set_type(vxlan_file_path_param, DOCA_ARGP_TYPE_STRING);
1464  result = doca_argp_register_param(vxlan_file_path_param);
1465  if (result != DOCA_SUCCESS) {
1466  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
1467  return result;
1468  }
1469 
1470  /* Create and register UPF Acceleration Aging time in seconds */
1471  result = doca_argp_param_create(&aging_time_sec_param);
1472  if (result != DOCA_SUCCESS) {
1473  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
1474  return result;
1475  }
1476  doca_argp_param_set_short_name(aging_time_sec_param, "a");
1477  doca_argp_param_set_long_name(aging_time_sec_param, "aging-time-sec");
1478  doca_argp_param_set_description(aging_time_sec_param, "Aging period in seconds");
1480  doca_argp_param_set_type(aging_time_sec_param, DOCA_ARGP_TYPE_INT);
1481  result = doca_argp_register_param(aging_time_sec_param);
1482  if (result != DOCA_SUCCESS) {
1483  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
1484  return result;
1485  }
1486 
1487  /* Create and register UPF Acceleration Number of packets before accelerating */
1488  result = doca_argp_param_create(&pkts_before_accel_param);
1489  if (result != DOCA_SUCCESS) {
1490  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
1491  return result;
1492  }
1493  doca_argp_param_set_short_name(pkts_before_accel_param, "o");
1494  doca_argp_param_set_long_name(pkts_before_accel_param, "dpi-packet-threshold");
1496  pkts_before_accel_param,
1497  "Number of packets processed in software before accelerating to hardware, enabling DPI on initial packets");
1498  doca_argp_param_set_callback(pkts_before_accel_param, pkts_before_accel_callback);
1499  doca_argp_param_set_type(pkts_before_accel_param, DOCA_ARGP_TYPE_INT);
1500  result = doca_argp_register_param(pkts_before_accel_param);
1501  if (result != DOCA_SUCCESS) {
1502  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
1503  return result;
1504  }
1505 
1506  /* Create and register UPF Acceleration Number of packets before accelerating */
1507  result = doca_argp_param_create(&fixed_port_param);
1508  if (result != DOCA_SUCCESS) {
1509  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
1510  return result;
1511  }
1512  doca_argp_param_set_short_name(fixed_port_param, "p");
1513  doca_argp_param_set_long_name(fixed_port_param, "fixed-port");
1514  doca_argp_param_set_description(fixed_port_param, "UL port number in fixed-port mode");
1516  doca_argp_param_set_type(fixed_port_param, DOCA_ARGP_TYPE_INT);
1517  result = doca_argp_register_param(fixed_port_param);
1518  if (result != DOCA_SUCCESS) {
1519  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
1520  return result;
1521  }
1522 
1523  return DOCA_SUCCESS;
1524 }
1525 
1527 {
1528  uint16_t nb_ports = rte_eth_dev_count_avail();
1529 
1530  if (nb_ports > UPF_ACCEL_PORTS_MAX) {
1531  DOCA_LOG_ERR("Invalid number (%u) of ports, max %u", nb_ports, UPF_ACCEL_PORTS_MAX);
1532  return DOCA_ERROR_INVALID_VALUE;
1533  }
1534  dpdk_config->port_config.nb_ports = nb_ports;
1535 
1536  return DOCA_SUCCESS;
1537 }
1538 
1539 /*
1540  * UPF Acceleration main function
1541  *
1542  * @argc [in]: command line arguments size
1543  * @argv [in]: array of command line arguments
1544  * @return: EXIT_SUCCESS on success and EXIT_FAILURE otherwise
1545  */
1546 int main(int argc, char **argv)
1547 {
1549  struct doca_log_backend *sdk_log;
1550  int exit_status = EXIT_FAILURE;
1551  struct upf_accel_config upf_accel_cfg = {
1553  .sw_aging_time_sec = UPF_ACCEL_SW_AGING_TIME_DEFAULT_SEC,
1554  .dpi_threshold = UPF_ACCEL_DEFAULT_DPI_THRESHOLD,
1555  .fixed_port = UPF_ACCEL_FIXED_PORT_NONE,
1556  };
1557  struct application_dpdk_config dpdk_config = {
1559  .port_config.isolated_mode = 1,
1560  .port_config.enable_mbuf_metadata = 1,
1561  };
1562  struct upf_accel_fp_data *fp_data_arr = NULL;
1563  struct upf_accel_ctx upf_accel_ctx = {0};
1564  enum upf_accel_port port_id;
1565 
1566  /* Register a logger backend */
1568  if (result != DOCA_SUCCESS)
1569  goto upf_accel_exit;
1570 
1571  /* Register a logger backend for internal SDK errors and warnings */
1572  result = doca_log_backend_create_with_file_sdk(stderr, &sdk_log);
1573  if (result != DOCA_SUCCESS)
1574  goto upf_accel_exit;
1576  if (result != DOCA_SUCCESS)
1577  goto upf_accel_exit;
1578 
1579  DOCA_LOG_INFO("Starting UPF Acceleration app pid %d", getpid());
1580 
1582  if (result != DOCA_SUCCESS) {
1583  DOCA_LOG_ERR("Failed to init ARGP resources: %s", doca_error_get_descr(result));
1584  goto upf_accel_exit;
1585  }
1587 
1589  if (result != DOCA_SUCCESS) {
1590  DOCA_LOG_ERR("Failed to register UPF Acceleration app parameters: %s", doca_error_get_descr(result));
1591  goto argp_cleanup;
1592  }
1593 
1594  result = doca_argp_start(argc, argv);
1595  if (result != DOCA_SUCCESS) {
1596  DOCA_LOG_ERR("Failed to parse app input: %s", doca_error_get_descr(result));
1597  goto argp_cleanup;
1598  }
1599 
1600  result = upf_accel_dpdk_config_num_ports(&dpdk_config);
1601  if (result != DOCA_SUCCESS) {
1602  DOCA_LOG_ERR("Failed to configure num ports");
1603  goto dpdk_cleanup;
1604  }
1605 
1606  /* Update queues and ports */
1607  result = dpdk_queues_and_ports_init(&dpdk_config);
1608  if (result != DOCA_SUCCESS) {
1609  DOCA_LOG_ERR("Failed to update ports and queues");
1610  goto dpdk_cleanup;
1611  }
1612 
1613  if (!rte_flow_dynf_metadata_avail()) {
1614  DOCA_LOG_ERR("Dynamic flow metadata is not available");
1615  goto dpdk_ports_queues_cleanup;
1616  }
1617 
1619  if (result != DOCA_SUCCESS)
1620  goto dpdk_ports_queues_cleanup;
1621 
1624  if (result != DOCA_SUCCESS)
1625  goto dpdk_smf_cleanup;
1626  }
1627 
1638  for (port_id = 0; port_id < upf_accel_ctx.num_ports; port_id++) {
1640  }
1641 
1642  result = init_upf_accel(&upf_accel_ctx, &fp_data_arr);
1643  if (result != DOCA_SUCCESS) {
1644  DOCA_LOG_ERR("init_upf_accel() encountered an error: %s", doca_error_get_descr(result));
1645  goto dpdk_vxlan_cleanup;
1646  }
1647 
1648  result = run_upf_accel(&upf_accel_ctx, fp_data_arr);
1649  if (result != DOCA_SUCCESS) {
1650  DOCA_LOG_ERR("run_upf_accel() encountered an error: %s", doca_error_get_descr(result));
1651  goto upf_accel_deinit;
1652  }
1653 
1654  exit_status = EXIT_SUCCESS;
1655 upf_accel_deinit:
1656  result = deinit_upf_accel(&upf_accel_ctx, fp_data_arr);
1657  if (result != DOCA_SUCCESS) {
1658  DOCA_LOG_ERR("deinit_upf_accel() encountered an error: %s", doca_error_get_descr(result));
1659  }
1660 dpdk_vxlan_cleanup:
1663 dpdk_smf_cleanup:
1665 dpdk_ports_queues_cleanup:
1666  dpdk_queues_and_ports_fini(&dpdk_config);
1667 dpdk_cleanup:
1668  dpdk_fini();
1669 argp_cleanup:
1671 upf_accel_exit:
1672  if (exit_status == EXIT_SUCCESS)
1673  DOCA_LOG_INFO("UPF Acceleration app finished successfully");
1674  else
1675  DOCA_LOG_INFO("UPF Acceleration app finished with errors");
1676  return exit_status;
1677 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
static void cleanup(struct cache_invalidate_sample_state *state)
doca_error_t dpdk_init(int argc, char **argv)
Definition: dpdk_utils.c:907
void dpdk_fini(void)
Definition: dpdk_utils.c:919
doca_error_t dpdk_queues_and_ports_init(struct application_dpdk_config *app_dpdk_config)
Definition: dpdk_utils.c:515
void dpdk_queues_and_ports_fini(struct application_dpdk_config *app_dpdk_config)
Definition: dpdk_utils.c:564
static enum doca_flow_pipe_domain domain
static struct doca_flow_pipe_entry * entries[NB_ENTRIES]
static struct doca_flow_fwd fwd
Definition: flow_parser.c:109
static struct doca_flow_pipe_entry * entry[MAX_ENTRIES]
#define DEFAULT_TIMEOUT_US
Definition: flow_skeleton.c:36
static uint8_t entry_idx
#define DOCA_HTOBE32(_x)
#define DOCA_BETOH32(_x)
DOCA_EXPERIMENTAL void doca_argp_param_set_description(struct doca_argp_param *param, const char *description)
Set the description of the program param, used during program usage.
DOCA_EXPERIMENTAL void doca_argp_param_set_long_name(struct doca_argp_param *param, const char *name)
Set the long name of the program param.
DOCA_EXPERIMENTAL doca_error_t doca_argp_start(int argc, char **argv)
Parse incoming arguments (cmd line/json).
DOCA_EXPERIMENTAL doca_error_t doca_argp_init(const char *program_name, void *program_config)
Initialize the parser interface.
DOCA_EXPERIMENTAL void doca_argp_set_dpdk_program(doca_argp_dpdk_cb_t callback)
Mark the program as based on DPDK API.
DOCA_EXPERIMENTAL void doca_argp_param_set_callback(struct doca_argp_param *param, doca_argp_param_cb_t callback)
Set the callback function of the program param.
DOCA_EXPERIMENTAL void doca_argp_param_set_mandatory(struct doca_argp_param *param)
Mark the program param as mandatory.
DOCA_EXPERIMENTAL doca_error_t doca_argp_param_create(struct doca_argp_param **param)
Create new program param.
DOCA_EXPERIMENTAL void doca_argp_param_set_type(struct doca_argp_param *param, enum doca_argp_type type)
Set the type of the param arguments.
DOCA_EXPERIMENTAL void doca_argp_param_set_short_name(struct doca_argp_param *param, const char *name)
Set the short name of the program param.
DOCA_EXPERIMENTAL doca_error_t doca_argp_destroy(void)
ARG Parser destroy.
DOCA_EXPERIMENTAL doca_error_t doca_argp_register_param(struct doca_argp_param *input_param)
Register a program flag.
@ DOCA_ARGP_TYPE_STRING
Definition: doca_argp.h:56
@ DOCA_ARGP_TYPE_INT
Definition: doca_argp.h:57
enum doca_error doca_error_t
DOCA API return codes.
DOCA_STABLE const char * doca_error_get_descr(doca_error_t error)
Returns the description string of an error code.
@ DOCA_ERROR_INVALID_VALUE
Definition: doca_error.h:44
@ DOCA_ERROR_UNEXPECTED
Definition: doca_error.h:60
@ DOCA_SUCCESS
Definition: doca_error.h:38
@ DOCA_ERROR_NO_MEMORY
Definition: doca_error.h:45
DOCA_STABLE doca_error_t doca_flow_entries_process(struct doca_flow_port *port, uint16_t pipe_queue, uint64_t timeout, uint32_t max_processed_entries)
Process entries in queue.
DOCA_STABLE doca_error_t doca_flow_shared_resources_bind(enum doca_flow_shared_resource_type type, uint32_t *res_array, uint32_t res_array_len, void *bindable_obj)
Binds a bulk of shared resources to a bindable object.
DOCA_EXPERIMENTAL doca_error_t doca_flow_shared_resource_set_cfg(enum doca_flow_shared_resource_type type, uint32_t id, struct doca_flow_shared_resource_cfg *cfg)
Configure a single shared resource.
DOCA_STABLE void doca_flow_destroy(void)
Destroy the doca flow.
DOCA_EXPERIMENTAL doca_error_t doca_flow_resource_query_entry(struct doca_flow_pipe_entry *entry, struct doca_flow_resource_query *query_stats)
Extract information about specific entry.
@ DOCA_FLOW_SHARED_RESOURCE_METER
Definition: doca_flow.h:93
@ DOCA_FLOW_SHARED_RESOURCE_COUNTER
Definition: doca_flow.h:95
@ DOCA_FLOW_METER_COLOR_MODE_BLIND
Definition: doca_flow.h:854
@ DOCA_FLOW_RESOURCE_TYPE_SHARED
Definition: doca_flow.h:614
@ DOCA_FLOW_FWD_PIPE
Definition: doca_flow.h:746
@ DOCA_FLOW_METER_ALGORITHM_TYPE_RFC2697
Definition: doca_flow.h:830
@ DOCA_FLOW_METER_LIMIT_TYPE_BYTES
Definition: doca_flow.h:843
@ DOCA_FLOW_PIPE_DOMAIN_EGRESS
Definition: doca_flow.h:245
@ DOCA_FLOW_PIPE_DOMAIN_DEFAULT
Definition: doca_flow.h:241
DOCA_EXPERIMENTAL doca_error_t doca_log_backend_create_standard(void)
Create default, non configurable backend for application messages.
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.
Definition: doca_log.h:466
#define DOCA_LOG_WARN(format,...)
Generates a WARNING application log message.
Definition: doca_log.h:476
#define DOCA_LOG_INFO(format,...)
Generates an INFO application log message.
Definition: doca_log.h:486
DOCA_EXPERIMENTAL doca_error_t doca_log_backend_create_with_file_sdk(FILE *fptr, struct doca_log_backend **backend)
Create a logging backend with a FILE* stream for SDK messages.
#define DOCA_LOG_DBG(format,...)
Generates a DEBUG application log message.
Definition: doca_log.h:496
DOCA_EXPERIMENTAL doca_error_t doca_log_backend_set_sdk_level(struct doca_log_backend *backend, uint32_t level)
Set the log level limit for SDK logging backends.
@ DOCA_LOG_LEVEL_WARNING
Definition: doca_log.h:47
const struct ip_frag_config * cfg
Definition: ip_frag_dp.c:0
uint16_t queue_id
Definition: ip_frag_dp.c:1
struct ip_frag_sw_counters sw_counters[IP_FRAG_PORT_NUM]
Definition: ip_frag_dp.c:2
#define CHAR_BIT
Definition: limits.h:67
@ PARSER_PKT_TYPE_PLAIN
Definition: packet_parser.h:37
@ PARSER_PKT_TYPE_TUNNELED
Definition: packet_parser.h:36
doca_error_t stop_doca_flow_ports(int nb_ports, struct doca_flow_port *ports[])
Definition: flow_common.c:240
doca_error_t init_doca_flow_ports(int nb_ports, struct doca_flow_port *ports[], bool is_hairpin, struct doca_dev *dev_arr[], uint32_t actions_mem_size[])
Definition: flow_common.c:296
doca_error_t init_doca_flow_cb(int nb_queues, const char *mode, struct flow_resources *resource, uint32_t nr_shared_resources[], doca_flow_entry_process_cb cb, doca_flow_pipe_process_cb pipe_process_cb, struct doca_flow_definitions *defs)
Definition: flow_common.c:79
#define ACTIONS_MEM_SIZE(nr_queues, entries)
Definition: flow_common.h:66
#define ARRAY_INIT(array, val)
Definition: flow_common.h:71
uint32_t * ids[UPF_ACCEL_PORTS_MAX]
Definition: upf_accel.h:171
struct application_port_config port_config
Definition: dpdk_utils.h:70
doca flow actions information
Definition: doca_flow.h:684
struct doca_flow_resource_encap_cfg encap_cfg
Definition: doca_flow.h:710
uint8_t action_idx
Definition: doca_flow.h:685
struct doca_flow_tun tun
Definition: doca_flow.h:569
forwarding configuration
Definition: doca_flow.h:779
uint16_t port_id
Definition: doca_flow.h:795
enum doca_flow_fwd_type type
Definition: doca_flow.h:780
doca flow matcher information
Definition: doca_flow.h:491
struct doca_flow_meta meta
Definition: doca_flow.h:494
doca_be32_t pkt_meta
Definition: doca_flow.h:359
doca monitor action configuration
Definition: doca_flow.h:968
struct doca_flow_monitor::@101::@106 shared_meter
struct doca_flow_monitor::@103::@107 shared_counter
enum doca_flow_resource_type meter_type
Definition: doca_flow.h:969
struct doca_flow_encap_action encap
Definition: doca_flow.h:663
flow resource query
Definition: doca_flow.h:1101
struct doca_flow_resource_query::@115::@117 counter
doca flow shared resource configuration
Definition: doca_flow.h:953
uint8_t gtp_ext_psc_qfi
user context struct that will be used in entries process callback
Definition: flow_common.h:78
uint32_t nr_counters
Definition: flow_common.h:96
struct upf_accel_pdrs * pdrs
Definition: upf_accel.h:260
const char * vxlan_config_file_path
Definition: upf_accel.h:264
struct upf_accel_qers * qers
Definition: upf_accel.h:263
uint32_t hw_aging_time_sec
Definition: upf_accel.h:266
struct upf_accel_fars * fars
Definition: upf_accel.h:261
upf_accel_get_forwarding_port get_fwd_port
Definition: upf_accel.h:351
uint16_t num_queues
Definition: upf_accel.h:339
struct doca_flow_pipe * pipes[UPF_ACCEL_PORTS_MAX][UPF_ACCEL_PIPE_NUM]
Definition: upf_accel.h:343
struct flow_resources resource
Definition: upf_accel.h:340
uint32_t num_static_entries[UPF_ACCEL_PORTS_MAX]
Definition: upf_accel.h:350
struct doca_flow_port * ports[UPF_ACCEL_PORTS_MAX]
Definition: upf_accel.h:344
uint16_t num_ports
Definition: upf_accel.h:338
struct doca_flow_pipe_entry * drop_entries[UPF_ACCEL_DROP_NUM][UPF_ACCEL_NUM_DOMAINS]
Definition: upf_accel.h:347
struct doca_dev * dev_arr[UPF_ACCEL_PORTS_MAX]
Definition: upf_accel.h:345
uint32_t num_shared_resources[SHARED_RESOURCE_NUM_VALUES]
Definition: upf_accel.h:341
struct upf_accel_entry_ctx static_entry_ctx[UPF_ACCEL_PORTS_MAX]
Definition: upf_accel.h:349
struct doca_flow_pipe_entry * smf_entries[UPF_ACCEL_MAX_NUM_PDR][UPF_ACCEL_PORTS_MAX]
Definition: upf_accel.h:346
const struct upf_accel_config * upf_accel_cfg
Definition: upf_accel.h:342
Definition: upf_accel.h:375
struct doca_flow_monitor * mon
Definition: upf_accel.h:379
struct doca_flow_match * match
Definition: upf_accel.h:377
struct doca_flow_pipe * pipe
Definition: upf_accel.h:376
enum doca_flow_pipe_domain domain
Definition: upf_accel.h:382
enum upf_accel_port port_id
Definition: upf_accel.h:381
enum upf_accel_rule_type type
Definition: upf_accel.h:330
struct upf_accel_static_entry_ctx static_ctx
Definition: upf_accel.h:333
uint32_t id
Definition: upf_accel.h:215
struct upf_accel_far arr_fars[]
Definition: upf_accel.h:222
size_t num_fars
Definition: upf_accel.h:221
struct upf_accel_fp_accel_counters accel_failed_counters[PARSER_PKT_TYPE_NUM]
struct upf_accel_entry_ctx * dyn_tbl_data
struct upf_accel_ctx * ctx
struct app_shared_counter_ids quota_cntrs
struct upf_accel_fp_sw_counters sw_counters
struct upf_accel_fp_accel_counters accel_counters[PARSER_PKT_TYPE_NUM]
struct upf_accel_fp_accel_counters unaccel_counters[PARSER_PKT_TYPE_NUM]
struct upf_accel_packet_byte_counter new_conn
struct upf_accel_packet_byte_counter err
struct upf_accel_packet_byte_counter ex_conn
uint32_t qerids[UPF_ACCEL_PDR_QERIDS_LEN]
Definition: upf_accel.h:195
uint32_t qerids_num
Definition: upf_accel.h:194
enum upf_accel_pdr_pdi_si pdi_si
Definition: upf_accel.h:196
uint32_t farid
Definition: upf_accel.h:191
uint32_t id
Definition: upf_accel.h:190
struct upf_accel_pdr arr_pdrs[]
Definition: upf_accel.h:211
size_t num_pdrs
Definition: upf_accel.h:210
uint32_t id
Definition: upf_accel.h:236
uint8_t qfi
Definition: upf_accel.h:237
uint64_t mbr_dl_mbr
Definition: upf_accel.h:238
uint64_t mbr_ul_mbr
Definition: upf_accel.h:239
size_t num_qers
Definition: upf_accel.h:243
struct upf_accel_qer arr_qers[]
Definition: upf_accel.h:244
struct entries_status ctrl_status
Definition: upf_accel.h:326
static int nb_ports
Definition: switch_core.c:44
static uint32_t actions_mem_size[FLOW_SWITCH_PORTS_MAX]
Definition: switch_core.c:43
static int upf_accel_calc_num_shared_meters(uint16_t num_ports)
Definition: upf_accel.c:1106
static doca_error_t upf_accel_signals_mask(sigset_t *sigset)
Definition: upf_accel.c:1068
static doca_error_t deinit_upf_accel(struct upf_accel_ctx *upf_accel_ctx, struct upf_accel_fp_data *fp_data_arr)
Definition: upf_accel.c:1143
static doca_error_t vxlan_config_file_path_callback(void *param, void *config)
Definition: upf_accel.c:1337
static int upf_accel_fp_loop_wrapper(void *param)
Definition: upf_accel.c:1092
static doca_error_t upf_accel_shared_meters_dev_init(struct upf_accel_ctx *upf_accel_ctx, struct doca_flow_shared_resource_cfg *cfg, const struct upf_accel_pdr *pdr, enum upf_accel_port port_id)
Definition: upf_accel.c:155
static enum upf_accel_port upf_accel_single_port_get_fwd_port(enum upf_accel_port port_id)
Definition: upf_accel.c:1131
static doca_error_t upf_accel_shared_meters_init(struct upf_accel_ctx *upf_accel_ctx)
Definition: upf_accel.c:241
static doca_error_t upf_accel_pipe_encap_counter_insert(struct upf_accel_ctx *upf_accel_ctx, uint32_t pdr_idx, uint32_t pdr_id, uint32_t far_id, uint8_t qfi, enum upf_accel_pdr_pdi_si pdi_si, enum upf_accel_port port_id, struct doca_flow_pipe_entry **entry)
Definition: upf_accel.c:323
static doca_error_t pipe_pdr_insert(struct upf_accel_ctx *upf_accel_ctx, struct upf_accel_entry_cfg *cfg, struct doca_flow_pipe_entry **entry)
Definition: upf_accel.c:271
static void upf_accel_fp_data_cleanup(struct upf_accel_fp_data *fp_data_arr)
Definition: upf_accel.c:666
static doca_error_t init_upf_accel(struct upf_accel_ctx *upf_accel_ctx, struct upf_accel_fp_data **fp_data_arr)
Definition: upf_accel.c:1165
static uint32_t port_id_and_idx_to_quota_counter(enum upf_accel_port port_id, uint32_t idx)
Definition: upf_accel.c:55
int main(int argc, char **argv)
Definition: upf_accel.c:1546
static void free_quota_counters_ids(struct app_shared_counter_ids *shared_counter_ids, uint16_t num_ports)
Definition: upf_accel.c:581
static const struct upf_accel_far * upf_accel_get_far_by_id(const struct upf_accel_fars *fars, uint32_t far_id)
Definition: upf_accel.c:301
static doca_error_t upf_accel_init_quota_counters(struct upf_accel_ctx *upf_accel_ctx)
Definition: upf_accel.c:620
static doca_error_t upf_accel_shared_meters_level_init(struct upf_accel_ctx *upf_accel_ctx, const struct upf_accel_pdr *pdr)
Definition: upf_accel.c:212
DOCA_LOG_REGISTER(UPF_ACCEL)
static doca_error_t run_upf_accel(struct upf_accel_ctx *upf_accel_ctx, struct upf_accel_fp_data *fp_data_arr)
Definition: upf_accel.c:1265
static doca_error_t pipe_shared_meter_common_insert(struct upf_accel_ctx *upf_accel_ctx, uint32_t pdr_idx, uint32_t qer_idx, enum upf_accel_port port_id)
Definition: upf_accel.c:413
static doca_error_t upf_accel_register_params(void)
Definition: upf_accel.c:1426
static int upf_accel_calc_num_shared_counters(uint16_t num_ports)
Definition: upf_accel.c:1119
static void upf_accel_fp_sw_counters_print(struct upf_accel_fp_data *fp_data_arr)
Definition: upf_accel.c:786
static doca_error_t aging_time_sec_callback(void *param, void *config)
Definition: upf_accel.c:1354
static doca_error_t smf_config_file_path_callback(void *param, void *config)
Definition: upf_accel.c:1320
static doca_error_t fixed_port_callback(void *param, void *config)
Definition: upf_accel.c:1406
static doca_error_t pkts_before_accel_callback(void *param, void *config)
Definition: upf_accel.c:1372
static doca_error_t upf_accel_smf_rules_add(struct upf_accel_ctx *upf_accel_ctx)
Definition: upf_accel.c:480
static uint32_t calculate_hash_table_size(uint16_t num_cores)
Definition: upf_accel.c:602
static void upf_accel_fp_accel_counters_print(struct upf_accel_fp_data *fp_data_arr, const char *name)
Definition: upf_accel.c:836
static doca_error_t upf_accel_tx_counters_insert(struct upf_accel_ctx *upf_accel_ctx, uint32_t pdr_idx, uint32_t pdr_id, uint32_t far_id, uint8_t qfi, enum upf_accel_pdr_pdi_si pdi_si, struct doca_flow_pipe_entry **entry)
Definition: upf_accel.c:377
static void upf_accel_pdrs_print(struct upf_accel_ctx *upf_accel_ctx)
Definition: upf_accel.c:909
static void upf_accel_static_hw_counters_print(struct upf_accel_ctx *upf_accel_ctx)
Definition: upf_accel.c:1029
static doca_error_t upf_accel_dpdk_config_num_ports(struct application_dpdk_config *dpdk_config)
Definition: upf_accel.c:1526
static doca_error_t alloc_and_populate_quota_counters_ids(uint16_t start_idx, size_t num_ports, size_t num_cntrs, struct app_shared_counter_ids *shared_counter_ids)
Definition: upf_accel.c:540
static void upf_accel_debug_counters_print(struct upf_accel_ctx *upf_accel_ctx, struct upf_accel_fp_data *fp_data_arr)
Definition: upf_accel.c:1045
static doca_error_t upf_accel_fp_data_init(struct upf_accel_ctx *ctx, struct upf_accel_fp_data **fp_data_arr_out)
Definition: upf_accel.c:690
static void upf_accel_drop_counter_print(struct upf_accel_ctx *upf_accel_ctx, enum upf_accel_pipe_drop_type drop_type)
Definition: upf_accel.c:963
static uint32_t upf_accel_shared_meters_table_offset_get(enum upf_accel_port port_id, uint32_t pdr_idx, uint32_t meter_idx)
Definition: upf_accel.c:85
volatile bool force_quit
Definition: upf_accel.c:46
static struct upf_accel_qer * upf_accel_get_qer_by_qer_id(struct upf_accel_qers *qers, uint32_t qer_id)
Definition: upf_accel.c:130
static uint32_t upf_accel_get_pdr_index_from_pdrs(const struct upf_accel_pdrs *pdrs, const struct upf_accel_pdr *pdr)
Definition: upf_accel.c:112
static uint64_t upf_accel_clamp_rate(uint64_t val)
Definition: upf_accel.c:100
static doca_error_t pipe_shared_meter_insert(struct upf_accel_ctx *upf_accel_ctx, uint32_t pdr_idx, uint32_t qer_idx)
Definition: upf_accel.c:457
void upf_accel_sw_aging_ll_init(struct upf_accel_fp_data *fp_data, enum parser_pkt_type pkt_type)
void upf_accel_vxlan_cleanup(struct upf_accel_config *cfg)
#define UPF_ACCEL_DEFAULT_DPI_THRESHOLD
Definition: upf_accel.h:89
upf_accel_port
Definition: upf_accel.h:40
@ UPF_ACCEL_PORTS_MAX
Definition: upf_accel.h:43
doca_error_t upf_accel_vxlan_parse(struct upf_accel_config *cfg)
#define UPF_ACCEL_HW_AGING_TIME_DEFAULT_SEC
Definition: upf_accel.h:79
upf_accel_pipe_drop_type
Definition: upf_accel.h:112
@ UPF_ACCEL_DROP_DBG
Definition: upf_accel.h:113
@ UPF_ACCEL_DROP_RATE
Definition: upf_accel.h:114
@ UPF_ACCEL_DROP_NUM
Definition: upf_accel.h:116
@ UPF_ACCEL_DROP_FILTER
Definition: upf_accel.h:115
#define UPF_ACCEL_MAX_PDR_NUM_RATE_METERS
Definition: upf_accel.h:71
#define UPF_ACCEL_SW_AGING_TIME_DEFAULT_SEC
Definition: upf_accel.h:81
#define UPF_ACCEL_MAX_NUM_PDR
Definition: upf_accel.h:54
static uint8_t upf_accel_domain_idx_get(enum upf_accel_port port_id, uint8_t domain)
Definition: upf_accel.h:406
void upf_accel_smf_cleanup(struct upf_accel_config *cfg)
@ UPF_ACCEL_RULE_STATIC
Definition: upf_accel.h:159
@ UPF_ACCEL_PIPE_TX_COLOR_MATCH_START
Definition: upf_accel.h:136
@ UPF_ACCEL_PIPE_TX_COUNTER
Definition: upf_accel.h:129
@ UPF_ACCEL_PIPE_TX_SHARED_METERS_START
Definition: upf_accel.h:134
@ UPF_ACCEL_PIPE_TX_COLOR_MATCH_NO_MORE_METERS
Definition: upf_accel.h:138
static enum upf_accel_port upf_accel_get_opposite_port(enum upf_accel_port port_id)
Definition: upf_accel.h:417
doca_error_t upf_accel_smf_parse(struct upf_accel_config *cfg)
upf_accel_pdr_pdi_si
Definition: upf_accel.h:101
@ UPF_ACCEL_PDR_PDI_SI_DL
Definition: upf_accel.h:104
@ UPF_ACCEL_PDR_PDI_SI_UL
Definition: upf_accel.h:103
#define UPF_ACCEL_NUM_QUOTA_COUNTERS_PER_PORT
Definition: upf_accel.h:56
#define UPF_ACCEL_FIXED_PORT_NONE
Definition: upf_accel.h:91
@ UPF_ACCEL_ENCAP_ACTION_NONE
Definition: upf_accel.h:153
@ UPF_ACCEL_ENCAP_ACTION_5G
Definition: upf_accel.h:152
@ UPF_ACCEL_ENCAP_ACTION_4G
Definition: upf_accel.h:151
void upf_accel_check_for_valid_entry_aging(struct doca_flow_pipe_entry *entry, uint16_t pipe_queue, enum doca_flow_entry_status status, enum doca_flow_entry_op op, void *user_ctx)
void upf_accel_fp_loop(struct upf_accel_fp_data *fp_data)
struct upf_accel_ctx * ctx
doca_error_t upf_accel_pipeline_create(struct upf_accel_ctx *upf_accel_ctx)
doca_error_t upf_accel_pipe_static_entry_add(struct upf_accel_ctx *upf_accel_ctx, enum upf_accel_port port_id, uint16_t pipe_queue, struct doca_flow_pipe *pipe, const struct doca_flow_match *match, const struct doca_flow_actions *actions, const struct doca_flow_monitor *mon, const struct doca_flow_fwd *fwd, uint32_t flags, void *usr_ctx, struct doca_flow_pipe_entry **entry)
#define UPF_ACCEL_QFI_NONE
#define UPF_ACCEL_MAX_NUM_CONNECTIONS
#define UPF_ACCEL_MAX_NUM_FAILED_ACCEL_PER_CORE