NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
psp_gw_flows.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024-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 <string>
27 #include <vector>
28 
29 #include <rte_ether.h>
30 #include <rte_ethdev.h>
31 #include <rte_ip.h>
32 #include <netinet/icmp6.h>
33 
34 #include <doca_bitfield.h>
35 #include <doca_flow.h>
36 #include <doca_flow_crypto.h>
37 #include <doca_flow_tune_server.h>
38 #include <doca_log.h>
39 
40 #include "psp_gw_config.h"
41 #include "psp_gw_flows.h"
42 #include "psp_gw_utils.h"
43 
44 #define IF_SUCCESS(result, expr) \
45  if (result == DOCA_SUCCESS) { \
46  result = expr; \
47  if (likely(result == DOCA_SUCCESS)) { \
48  DOCA_LOG_DBG("Success: %s", #expr); \
49  } else { \
50  DOCA_LOG_ERR("Error: %s: %s", #expr, doca_error_get_descr(result)); \
51  } \
52  } else { /* skip this expr */ \
53  }
54 
55 #define NEXT_HEADER_IPV4 0x4
56 #define NEXT_HEADER_IPV6 0x29
57 
58 DOCA_LOG_REGISTER(PSP_GATEWAY);
59 
60 static const uint32_t DEFAULT_TIMEOUT_US = 10000; /* default timeout for processing entries */
61 static const uint32_t PSP_ICV_SIZE = 16;
62 static const uint32_t MAX_ACTIONS_MEM_SIZE = 8388608 * 64;
63 
68  // encapped Ethernet header contents.
69  rte_ether_hdr eth;
70 
71  // encapped IP header contents (extension header not supported)
72  rte_ipv6_hdr ip;
73 
74  rte_udp_hdr udp;
75 
76  // encapped PSP header contents.
77  rte_psp_base_hdr psp;
78  rte_be64_t psp_virt_cookie;
79 
80 } __rte_packed __rte_aligned(2);
81 
86  // encapped Ethernet header contents.
87  rte_ether_hdr eth;
88 
89  // encapped IP header contents (extension header not supported)
90  rte_ipv4_hdr ip;
91 
92  rte_udp_hdr udp;
93 
94  // encapped PSP header contents.
95  rte_psp_base_hdr psp;
96  rte_be64_t psp_virt_cookie;
97 
98 } __rte_packed __rte_aligned(2);
99 
104  // encaped udp header
105  rte_udp_hdr udp;
106 
107  // encapped PSP header contents.
108  rte_psp_base_hdr psp;
109  rte_be64_t psp_virt_cookie;
110 
111 } __rte_packed __rte_aligned(2);
112 
113 const uint8_t PSP_SAMPLE_ENABLE = 1 << 7;
114 
117  pf_dev(pf),
118  vf_port_id(vf_port_id),
119  sampling_enabled(app_config->log2_sample_rate > 0)
120 {
121  monitor_count.counter_type = DOCA_FLOW_RESOURCE_TYPE_NON_SHARED;
122 
123  for (uint16_t i = 0; i < app_config->dpdk_config.port_config.nb_queues; i++) {
124  rss_queues.push_back(i);
125  }
126  fwd_rss.type = DOCA_FLOW_FWD_RSS;
129  fwd_rss.rss.queues_array = rss_queues.data();
130  fwd_rss.rss.nr_queues = (int)rss_queues.size();
131 }
132 
134 {
135  if (vf_port)
136  doca_flow_port_stop(vf_port);
137 
138  if (pf_dev->port_obj)
139  doca_flow_port_stop(pf_dev->port_obj);
140 
143 }
144 
146 {
148 
149  IF_SUCCESS(result, init_doca_flow(app_config));
150  IF_SUCCESS(result, start_port(pf_dev->port_id, pf_dev->dev, &pf_dev->port_obj));
151  IF_SUCCESS(result, start_port(vf_port_id, nullptr, &vf_port));
152  IF_SUCCESS(result, bind_shared_resources());
153  init_status(app_config);
154  IF_SUCCESS(result, rss_pipe_create());
155  if (sampling_enabled) {
156  IF_SUCCESS(result, fwd_to_wire_pipe_create());
157  IF_SUCCESS(result, fwd_to_rss_pipe_create());
158  }
159  IF_SUCCESS(result, syndrome_stats_pipe_create());
160  IF_SUCCESS(result, ingress_acl_pipe_create(true));
161  IF_SUCCESS(result, ingress_acl_pipe_create(false));
162  if (!app_config->disable_ingress_acl) {
163  IF_SUCCESS(result, create_ingress_src_ip6_pipe());
164  }
165  IF_SUCCESS(result, ingress_inner_classifier_pipe_create());
166  if (sampling_enabled) {
167  IF_SUCCESS(result, configure_mirrors());
168  }
169  IF_SUCCESS(result, create_pipes());
170 
171  return result;
172 }
173 
174 doca_error_t PSP_GatewayFlows::configure_mirrors(void)
175 {
176  assert(rss_pipe);
178 
179  doca_flow_mirror_target mirr_tgt = {};
180  mirr_tgt.fwd.type = DOCA_FLOW_FWD_PIPE;
181  mirr_tgt.fwd.next_pipe = ingress_inner_ip_classifier_pipe;
182 
183  struct doca_flow_shared_resource_cfg res_cfg = {};
184  res_cfg.mirror_cfg.nr_targets = 1;
185  res_cfg.mirror_cfg.target = &mirr_tgt;
186 
187  IF_SUCCESS(
188  result,
189  doca_flow_shared_resource_set_cfg(DOCA_FLOW_SHARED_RESOURCE_MIRROR, mirror_res_id_ingress, &res_cfg));
190 
193  &mirror_res_id_ingress,
194  1,
195  pf_dev->port_obj));
196 
197  doca_flow_mirror_target mirr_tgt_rss_pipe = {};
198  mirr_tgt_rss_pipe.fwd.type = DOCA_FLOW_FWD_PIPE;
199  mirr_tgt_rss_pipe.fwd.next_pipe = fwd_to_rss_pipe;
200 
201  res_cfg.mirror_cfg.target = &mirr_tgt_rss_pipe;
202 
207  &mirror_res_id_rss,
208  1,
209  pf_dev->port_obj));
210 
211  if (app_config->maintain_order) {
212  doca_flow_mirror_target mirr_tgt_drop = {};
213  mirr_tgt_drop.fwd.type = DOCA_FLOW_FWD_DROP;
214 
215  res_cfg.mirror_cfg.target = &mirr_tgt_drop;
216 
219  mirror_res_id_drop,
220  &res_cfg));
223  &mirror_res_id_drop,
224  1,
225  pf_dev->port_obj));
226  }
227 
228  return result;
229 }
230 
231 doca_error_t PSP_GatewayFlows::start_port(uint16_t port_id, doca_dev *port_dev, doca_flow_port **port)
232 {
233  doca_flow_port_cfg *port_cfg;
235 
237 
238  IF_SUCCESS(result, doca_flow_port_cfg_set_port_id(port_cfg, port_id));
239  IF_SUCCESS(result, doca_flow_port_cfg_set_dev(port_cfg, port_dev));
241  IF_SUCCESS(result, doca_flow_port_start(port_cfg, port));
242 
243  if (result == DOCA_SUCCESS) {
244  rte_ether_addr port_mac_addr;
245  rte_eth_macaddr_get(port_id, &port_mac_addr);
246  DOCA_LOG_INFO("Started port_id %d, mac-addr: %s", port_id, mac_to_string(port_mac_addr).c_str());
247  }
248 
249  if (port_cfg) {
250  doca_flow_port_cfg_destroy(port_cfg);
251  }
252  return result;
253 }
254 
255 doca_error_t PSP_GatewayFlows::init_doca_flow(const psp_gw_app_config *app_cfg)
256 {
257  struct doca_flow_tune_server_cfg *server_cfg;
259 
260  uint16_t nb_queues = app_cfg->dpdk_config.port_config.nb_queues;
261 
262  uint16_t rss_queues[nb_queues];
263  for (int i = 0; i < nb_queues; i++)
264  rss_queues[i] = i;
265  doca_flow_resource_rss_cfg rss_config = {};
266  rss_config.nr_queues = nb_queues;
267  rss_config.queues_array = rss_queues;
268 
269  /* Init DOCA Flow with crypto shared resources */
270  doca_flow_cfg *flow_cfg;
272  IF_SUCCESS(result, doca_flow_cfg_set_pipe_queues(flow_cfg, nb_queues));
274  IF_SUCCESS(result, doca_flow_cfg_set_mode_args(flow_cfg, "switch,hws,isolated,expert"));
275  IF_SUCCESS(result, doca_flow_cfg_set_cb_entry_process(flow_cfg, PSP_GatewayFlows::check_for_valid_entry));
276  IF_SUCCESS(result, doca_flow_cfg_set_default_rss(flow_cfg, &rss_config));
279  app_cfg->max_tunnels + 1,
281  IF_SUCCESS(
282  result,
284  IF_SUCCESS(result, doca_flow_init(flow_cfg));
285  if (result != DOCA_SUCCESS) {
286  doca_flow_cfg_destroy(flow_cfg);
287  return result;
288  }
289  DOCA_LOG_INFO("Initialized DOCA Flow for a max of %d tunnels", app_cfg->max_tunnels);
290  doca_flow_cfg_destroy(flow_cfg);
291 
292  /* Init DOCA Flow Tune Server */
294  if (result != DOCA_SUCCESS) {
295  DOCA_LOG_ERR("Failed to create flow tune server configuration");
296  return result;
297  }
298  result = doca_flow_tune_server_init(server_cfg);
299  if (result != DOCA_SUCCESS) {
301  DOCA_LOG_DBG("DOCA Flow Tune Server isn't supported in this runtime version");
303  } else {
304  DOCA_LOG_ERR("Failed to initialize the DOCA Flow Tune Server");
305  }
306  }
307 
309  return result;
310 }
311 
312 void PSP_GatewayFlows::init_status(psp_gw_app_config *app_config)
313 {
314  app_config->status =
315  std::vector<entries_status>(app_config->dpdk_config.port_config.nb_queues, entries_status());
316 }
317 
318 doca_error_t PSP_GatewayFlows::bind_shared_resources(void)
319 {
321 
322  std::vector<uint32_t> psp_ids(app_config->max_tunnels);
323  for (uint32_t i = 0; i < app_config->max_tunnels; i++) {
324  psp_ids[i] = i + 1;
325  }
326 
329  psp_ids.data(),
330  app_config->max_tunnels,
331  pf_dev->port_obj));
332 
333  return result;
334 }
335 
336 doca_error_t PSP_GatewayFlows::create_pipes(void)
337 {
339 
340  if (sampling_enabled) {
341  IF_SUCCESS(result, ingress_sampling_pipe_create());
342  }
343  IF_SUCCESS(result, ingress_decrypt_pipe_create());
344 
345  if (sampling_enabled) {
346  IF_SUCCESS(result, empty_pipe_create_not_sampled());
347  IF_SUCCESS(result, egress_sampling_pipe_create());
348  IF_SUCCESS(result, set_sample_bit_pipe_create());
349  }
350  IF_SUCCESS(result, egress_acl_pipe_create(true));
351  IF_SUCCESS(result, egress_acl_pipe_create(false));
352  IF_SUCCESS(result, create_egress_dst_ip6_pipe());
353  IF_SUCCESS(result, empty_pipe_create());
354 
355  IF_SUCCESS(result, ingress_root_pipe_create());
356 
357  return result;
358 }
359 
360 doca_error_t PSP_GatewayFlows::rss_pipe_create(void)
361 {
362  DOCA_LOG_DBG("\n>> %s", __FUNCTION__);
364 
365  doca_flow_match empty_match = {};
366 
367  // Note packets sent to RSS will be processed by lcore_pkt_proc_func().
368 
369  doca_flow_pipe_cfg *pipe_cfg;
370  IF_SUCCESS(result, doca_flow_pipe_cfg_create(&pipe_cfg, pf_dev->port_obj));
371  IF_SUCCESS(result, doca_flow_pipe_cfg_set_name(pipe_cfg, "RSS_PIPE"));
374  IF_SUCCESS(result, doca_flow_pipe_cfg_set_monitor(pipe_cfg, &monitor_count));
375  IF_SUCCESS(result, doca_flow_pipe_cfg_set_match(pipe_cfg, &empty_match, nullptr));
376  IF_SUCCESS(result, doca_flow_pipe_create(pipe_cfg, &fwd_rss, nullptr, &rss_pipe));
377  IF_SUCCESS(
378  result,
379  add_single_entry(0, rss_pipe, pf_dev->port_obj, nullptr, nullptr, nullptr, nullptr, &default_rss_entry));
380 
381  if (pipe_cfg) {
382  doca_flow_pipe_cfg_destroy(pipe_cfg);
383  }
384 
385  return result;
386 }
387 
388 doca_error_t PSP_GatewayFlows::ingress_decrypt_pipe_create(void)
389 {
390  DOCA_LOG_DBG("\n>> %s", __FUNCTION__);
391  assert(sampling_enabled ? ingress_sampling_pipe : ingress_inner_ip_classifier_pipe);
392  assert(rss_pipe);
394 
395  doca_flow_match match = {};
396  match.parser_meta.port_id = UINT16_MAX;
400 
405 
406  doca_flow_actions *actions_arr[] = {&actions};
407 
408  doca_flow_fwd fwd = {};
410  fwd.next_pipe = sampling_enabled ? ingress_sampling_pipe : ingress_inner_ip_classifier_pipe;
411 
412  doca_flow_fwd fwd_miss = {};
414 
415  doca_flow_pipe_cfg *pipe_cfg;
416  IF_SUCCESS(result, doca_flow_pipe_cfg_create(&pipe_cfg, pf_dev->port_obj));
417  IF_SUCCESS(result, doca_flow_pipe_cfg_set_name(pipe_cfg, "PSP_DECRYPT"));
422  IF_SUCCESS(result, doca_flow_pipe_cfg_set_match(pipe_cfg, &match, nullptr));
423  IF_SUCCESS(result, doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, nullptr, nullptr, 1));
424  IF_SUCCESS(result, doca_flow_pipe_cfg_set_monitor(pipe_cfg, &monitor_count));
425  IF_SUCCESS(result, doca_flow_pipe_create(pipe_cfg, &fwd, &fwd_miss, &ingress_decrypt_pipe));
426 
427  if (pipe_cfg) {
428  doca_flow_pipe_cfg_destroy(pipe_cfg);
429  }
430 
431  doca_flow_match match_uplink = {};
432  match_uplink.parser_meta.port_id = 0;
433 
435  add_single_entry(0,
436  ingress_decrypt_pipe,
437  pf_dev->port_obj,
438  &match_uplink,
439  &actions,
440  nullptr,
441  nullptr,
442  &default_decrypt_entry));
443 
444  return result;
445 }
446 
447 doca_error_t PSP_GatewayFlows::ingress_inner_classifier_pipe_create(void)
448 {
449  DOCA_LOG_DBG("\n>> %s", __FUNCTION__);
451 
452  doca_flow_match match = {};
453  if (app_config->mode == PSP_GW_MODE_TUNNEL) {
454  match.tun.type = DOCA_FLOW_TUN_PSP;
455  match.tun.psp.nexthdr = -1;
456  } else {
457  match.parser_meta.outer_l3_type = (enum doca_flow_l3_meta) - 1; // changeable
458  }
459 
460  doca_flow_fwd fwd = {};
462  fwd.next_pipe = nullptr;
463 
464  doca_flow_fwd fwd_miss = {};
466 
467  doca_flow_pipe_cfg *pipe_cfg;
468  IF_SUCCESS(result, doca_flow_pipe_cfg_create(&pipe_cfg, pf_dev->port_obj));
469  IF_SUCCESS(result, doca_flow_pipe_cfg_set_name(pipe_cfg, "PSP_INNER_IP_CLASSIFIER"));
474  IF_SUCCESS(result, doca_flow_pipe_cfg_set_match(pipe_cfg, &match, &match));
475  IF_SUCCESS(result, doca_flow_pipe_cfg_set_monitor(pipe_cfg, &monitor_count));
476  IF_SUCCESS(result, doca_flow_pipe_create(pipe_cfg, &fwd, &fwd_miss, &ingress_inner_ip_classifier_pipe));
477 
478  if (pipe_cfg) {
479  doca_flow_pipe_cfg_destroy(pipe_cfg);
480  }
481 
482  if (app_config->mode == PSP_GW_MODE_TUNNEL) {
484  } else {
486  }
487 
488  fwd.next_pipe = !app_config->disable_ingress_acl ? ingress_src_ip6_pipe : ingress_acl_ipv6_pipe;
490  add_single_entry(0,
491  ingress_inner_ip_classifier_pipe,
492  pf_dev->port_obj,
493  &match,
494  nullptr,
495  nullptr,
496  &fwd,
497  &ingress_ipv6_clasify_entry));
498 
499  if (app_config->mode == PSP_GW_MODE_TUNNEL) {
501  } else {
503  }
504  fwd.next_pipe = ingress_acl_ipv4_pipe;
506  add_single_entry(0,
507  ingress_inner_ip_classifier_pipe,
508  pf_dev->port_obj,
509  &match,
510  nullptr,
511  nullptr,
512  &fwd,
513  &ingress_ipv4_clasify_entry));
514 
515  return result;
516 }
517 
518 doca_error_t PSP_GatewayFlows::ingress_sampling_pipe_create(void)
519 {
520  DOCA_LOG_DBG("\n>> %s", __FUNCTION__);
521  assert(mirror_res_id_ingress);
522  assert(rss_pipe);
523  assert(sampling_enabled);
525 
526  doca_flow_match match_psp_sampling_bit = {};
527  match_psp_sampling_bit.tun.type = DOCA_FLOW_TUN_PSP;
528  match_psp_sampling_bit.tun.psp.s_d_ver_v = PSP_SAMPLE_ENABLE;
529 
530  doca_flow_monitor mirror_action = {};
532  mirror_action.shared_mirror_id = mirror_res_id_ingress;
533 
534  doca_flow_actions set_meta = {};
535  set_meta.meta.pkt_meta = DOCA_HTOBE32(app_config->ingress_sample_meta_indicator);
536 
537  doca_flow_actions *actions_arr[] = {&set_meta};
538 
539  doca_flow_actions set_meta_mask = {};
540  set_meta_mask.meta.pkt_meta = UINT32_MAX;
541 
542  doca_flow_actions *actions_masks_arr[] = {&set_meta_mask};
543 
544  doca_flow_fwd fwd = {};
546  fwd.next_pipe = rss_pipe;
547 
548  doca_flow_fwd fwd_miss = {};
550  fwd_miss.next_pipe = ingress_inner_ip_classifier_pipe;
551 
552  doca_flow_pipe_cfg *pipe_cfg;
553  IF_SUCCESS(result, doca_flow_pipe_cfg_create(&pipe_cfg, pf_dev->port_obj));
554  IF_SUCCESS(result, doca_flow_pipe_cfg_set_name(pipe_cfg, "INGR_SAMPL"));
557  IF_SUCCESS(result, doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, actions_masks_arr, nullptr, 1));
558  IF_SUCCESS(result, doca_flow_pipe_cfg_set_monitor(pipe_cfg, &monitor_count));
559  IF_SUCCESS(result, doca_flow_pipe_cfg_set_match(pipe_cfg, &match_psp_sampling_bit, &match_psp_sampling_bit));
560  IF_SUCCESS(result, doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, actions_masks_arr, nullptr, 1));
561  IF_SUCCESS(result, doca_flow_pipe_cfg_set_monitor(pipe_cfg, &mirror_action));
562  IF_SUCCESS(result, doca_flow_pipe_create(pipe_cfg, &fwd, &fwd_miss, &ingress_sampling_pipe));
563 
564  if (pipe_cfg) {
565  doca_flow_pipe_cfg_destroy(pipe_cfg);
566  }
567 
569  add_single_entry(0,
570  ingress_sampling_pipe,
571  pf_dev->port_obj,
572  nullptr,
573  nullptr,
574  nullptr,
575  nullptr,
576  &default_ingr_sampling_entry));
577 
578  return result;
579 }
580 
581 doca_error_t PSP_GatewayFlows::create_ingress_src_ip6_pipe(void)
582 {
583  DOCA_LOG_DBG("\n>> %s", __FUNCTION__);
585  doca_flow_match match = {};
587  doca_flow_header_format *match_hdr = app_config->mode == PSP_GW_MODE_TUNNEL ? &match.inner : &match.outer;
589  &match.parser_meta.outer_l3_type;
590  match.tun.type = DOCA_FLOW_TUN_PSP;
591  match.tun.psp.spi = UINT32_MAX;
592  *l3_meta = DOCA_FLOW_L3_META_IPV6;
593  match_hdr->l3_type = DOCA_FLOW_L3_TYPE_IP6;
594  SET_IP6_ADDR(match_hdr->ip6.src_ip, UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX);
595 
596  actions.meta.u32[2] = UINT32_MAX;
597  doca_flow_actions *actions_arr[] = {&actions};
598 
599  doca_flow_fwd fwd = {};
601  fwd.next_pipe = ingress_acl_ipv6_pipe;
602 
603  doca_flow_fwd fwd_miss = {};
605  fwd_miss.next_pipe = syndrome_stats_pipe;
606 
607  doca_flow_pipe_cfg *pipe_cfg;
608  IF_SUCCESS(result, doca_flow_pipe_cfg_create(&pipe_cfg, pf_dev->port_obj));
609  IF_SUCCESS(result, doca_flow_pipe_cfg_set_name(pipe_cfg, "ING_SRC_IP6"));
613  IF_SUCCESS(result, doca_flow_pipe_cfg_set_match(pipe_cfg, &match, nullptr));
614  IF_SUCCESS(result, doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, nullptr, nullptr, 1));
615  IF_SUCCESS(result, doca_flow_pipe_cfg_set_monitor(pipe_cfg, &monitor_count));
616  IF_SUCCESS(result, doca_flow_pipe_create(pipe_cfg, &fwd, &fwd_miss, &ingress_src_ip6_pipe));
617  if (pipe_cfg) {
618  doca_flow_pipe_cfg_destroy(pipe_cfg);
619  }
620 
621  return result;
622 }
623 
624 doca_error_t PSP_GatewayFlows::ingress_acl_pipe_create(bool ipv4)
625 {
626  DOCA_LOG_DBG("\n>> %s", __FUNCTION__);
628  doca_flow_match match = {};
629  struct doca_flow_pipe **pipe = ipv4 ? &ingress_acl_ipv4_pipe : &ingress_acl_ipv6_pipe;
630  struct doca_flow_pipe_entry **entry = ipv4 ? &default_ingr_acl_ipv4_entry : &default_ingr_acl_ipv6_entry;
631  match.parser_meta.psp_syndrome = UINT8_MAX;
632  doca_flow_header_format *match_hdr = app_config->mode == PSP_GW_MODE_TUNNEL ? &match.inner : &match.outer;
633  if (!app_config->disable_ingress_acl) {
635  if (ipv4) {
636  match.tun.type = DOCA_FLOW_TUN_PSP;
637  match.tun.psp.spi = UINT32_MAX;
638  match_hdr->ip4.src_ip = UINT32_MAX;
639  match_hdr->ip4.dst_ip = UINT32_MAX;
640  } else {
641  match.meta.u32[2] = UINT32_MAX;
642  SET_IP6_ADDR(match_hdr->ip6.dst_ip, UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX);
643  }
644  }
645 
647  actions.has_crypto_encap = true;
652 
653  // In tunnel mode, we need to decap the eth/ip/udp/psp headers and add ethernet header
654  // In transport mode, we only remove the udp/psp headers
655  if (app_config->mode == PSP_GW_MODE_TUNNEL) {
657  actions.crypto_encap.data_size = sizeof(rte_ether_hdr);
658 
659  rte_ether_hdr *eth_hdr = (rte_ether_hdr *)actions.crypto_encap.encap_data;
660  eth_hdr->ether_type = ipv4 ? RTE_BE16(RTE_ETHER_TYPE_IPV4) : RTE_BE16(RTE_ETHER_TYPE_IPV6);
661  eth_hdr->src_addr = pf_dev->src_mac;
662  eth_hdr->dst_addr = app_config->dcap_dmac;
663  }
664 
665  doca_flow_actions *actions_arr[] = {&actions};
666 
667  doca_flow_fwd fwd = {};
669  fwd.port_id = vf_port_id;
670 
671  doca_flow_fwd fwd_miss = {};
673  fwd_miss.next_pipe = syndrome_stats_pipe;
674 
675  int nr_entries = app_config->disable_ingress_acl ? 1 : app_config->max_tunnels;
676 
677  doca_flow_pipe_cfg *pipe_cfg;
678  IF_SUCCESS(result, doca_flow_pipe_cfg_create(&pipe_cfg, pf_dev->port_obj));
679  IF_SUCCESS(result, doca_flow_pipe_cfg_set_name(pipe_cfg, ipv4 ? "INGR_ACL_IPV4" : "INGR_ACL_IPV6"));
681  IF_SUCCESS(result, doca_flow_pipe_cfg_set_nr_entries(pipe_cfg, nr_entries));
683  IF_SUCCESS(result, doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, nullptr, nullptr, 1));
684  IF_SUCCESS(result, doca_flow_pipe_cfg_set_monitor(pipe_cfg, &monitor_count));
685  IF_SUCCESS(result, doca_flow_pipe_cfg_set_match(pipe_cfg, &match, &match));
686  IF_SUCCESS(result, doca_flow_pipe_create(pipe_cfg, &fwd, &fwd_miss, pipe));
687 
688  if (pipe_cfg) {
689  doca_flow_pipe_cfg_destroy(pipe_cfg);
690  }
691 
692  if (app_config->disable_ingress_acl) {
693  doca_flow_match match_no_syndrome = {};
695  add_single_entry(0,
696  *pipe,
697  pf_dev->port_obj,
698  &match_no_syndrome,
699  &actions,
700  nullptr,
701  nullptr,
702  entry));
703  }
704 
705  return result;
706 }
707 
708 doca_error_t PSP_GatewayFlows::add_ingress_src_ip6_entry(psp_session_t *session, int dst_vip_id)
709 {
710  doca_flow_match match = {};
711  match.tun.type = DOCA_FLOW_TUN_PSP;
712  match.tun.psp.spi = RTE_BE32(session->spi_ingress);
713  doca_flow_header_format *match_hdr = app_config->mode == PSP_GW_MODE_TUNNEL ? &match.inner : &match.outer;
714  SET_IP6_ADDR(match_hdr->ip6.src_ip,
715  session->dst_vip.ipv6_addr[0],
716  session->dst_vip.ipv6_addr[1],
717  session->dst_vip.ipv6_addr[2],
718  session->dst_vip.ipv6_addr[3]);
719 
721  actions.meta.u32[2] = dst_vip_id;
722 
723  return add_single_entry(0, ingress_src_ip6_pipe, pf_dev->port_obj, &match, &actions, nullptr, nullptr, nullptr);
724 }
725 
727 {
728  struct doca_flow_pipe *pipe;
729  if (app_config->disable_ingress_acl) {
730  DOCA_LOG_ERR("Cannot insert ingress ACL flow; disabled");
731  return DOCA_ERROR_BAD_STATE;
732  }
733 
734  doca_flow_match match = {};
735  match.parser_meta.psp_syndrome = 0;
736  doca_flow_header_format *match_hdr = app_config->mode == PSP_GW_MODE_TUNNEL ? &match.inner : &match.outer;
737  if (session->src_vip.type == DOCA_FLOW_L3_TYPE_IP4) {
738  pipe = ingress_acl_ipv4_pipe;
739  match.tun.type = DOCA_FLOW_TUN_PSP;
740  match.tun.psp.spi = RTE_BE32(session->spi_ingress);
741  match_hdr->l3_type = DOCA_FLOW_L3_TYPE_IP4;
742  match_hdr->ip4.src_ip = session->dst_vip.ipv4_addr; // use dst_vip of session as src for ingress
743  match_hdr->ip4.dst_ip = session->src_vip.ipv4_addr; // use src_vip of session as dst for ingress
744  } else {
745  pipe = ingress_acl_ipv6_pipe;
746  match_hdr->l3_type = DOCA_FLOW_L3_TYPE_IP6;
747  SET_IP6_ADDR(match_hdr->ip6.dst_ip,
748  session->src_vip.ipv6_addr[0],
749  session->src_vip.ipv6_addr[1],
750  session->src_vip.ipv6_addr[2],
751  session->src_vip.ipv6_addr[3]);
752  int dst_vip_id = rte_hash_lookup(app_config->ip6_table, session->dst_vip.ipv6_addr);
753  if (dst_vip_id < 0) {
754  DOCA_LOG_WARN("Failed to find source IP in table");
755  int ret = rte_hash_add_key(app_config->ip6_table, session->dst_vip.ipv6_addr);
756  if (ret < 0) {
757  DOCA_LOG_ERR("Failed to add address to hash table");
758  return DOCA_ERROR_DRIVER;
759  }
760  dst_vip_id = rte_hash_lookup(app_config->ip6_table, session->dst_vip.ipv6_addr);
761  }
762  match.meta.u32[2] = dst_vip_id;
763  doca_error_t result = add_ingress_src_ip6_entry(session, dst_vip_id);
764  if (result != DOCA_SUCCESS)
765  return result;
766  }
767 
770  add_single_entry(0, pipe, pf_dev->port_obj, &match, nullptr, nullptr, nullptr, &session->acl_entry));
771 
772  return result;
773 }
774 
775 doca_error_t PSP_GatewayFlows::syndrome_stats_pipe_create(void)
776 {
778 
779  doca_flow_match syndrome_match = {};
780  syndrome_match.parser_meta.psp_syndrome = 0xff;
781 
782  // If we got here, the packet failed either the PSP decryption syndrome check
783  // or the ACL check. Whether the syndrome bits match here or not, the
784  // fate of the packet is to be dropped.
785  doca_flow_fwd fwd_drop = {};
786  fwd_drop.type = DOCA_FLOW_FWD_DROP;
787 
788  doca_flow_pipe_cfg *pipe_cfg;
789  IF_SUCCESS(result, doca_flow_pipe_cfg_create(&pipe_cfg, pf_dev->port_obj));
790  IF_SUCCESS(result, doca_flow_pipe_cfg_set_name(pipe_cfg, "SYNDROME_STATS"));
795  IF_SUCCESS(result, doca_flow_pipe_cfg_set_match(pipe_cfg, &syndrome_match, nullptr));
796  IF_SUCCESS(result, doca_flow_pipe_cfg_set_monitor(pipe_cfg, &monitor_count));
797  IF_SUCCESS(result, doca_flow_pipe_create(pipe_cfg, &fwd_drop, &fwd_drop, &syndrome_stats_pipe));
798 
799  if (pipe_cfg) {
800  doca_flow_pipe_cfg_destroy(pipe_cfg);
801  }
802 
803  for (int i = 0; i < NUM_OF_PSP_SYNDROMES; i++) {
804  // We don't hold counter for the SYNDROME_OK enum value (0) so we can skip it
805  syndrome_match.parser_meta.psp_syndrome = i + 1;
807  add_single_entry(0,
808  syndrome_stats_pipe,
809  pf_dev->port_obj,
810  &syndrome_match,
811  nullptr,
812  &monitor_count,
813  nullptr,
814  &syndrome_stats_entries[i]));
815  }
816 
817  return result;
818 }
819 
820 doca_error_t PSP_GatewayFlows::create_egress_dst_ip6_pipe(void)
821 {
822  DOCA_LOG_DBG("\n>> %s", __FUNCTION__);
824  doca_flow_match match = {};
826 
829  SET_IP6_ADDR(match.outer.ip6.dst_ip, UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX);
830 
831  actions.meta.u32[2] = UINT32_MAX;
832  doca_flow_actions *actions_arr[] = {&actions};
833 
834  doca_flow_fwd fwd = {};
836  fwd.next_pipe = egress_acl_ipv6_pipe;
837 
838  doca_flow_fwd fwd_miss = {};
840  fwd_miss.next_pipe = rss_pipe;
841 
842  doca_flow_pipe_cfg *pipe_cfg;
843  IF_SUCCESS(result, doca_flow_pipe_cfg_create(&pipe_cfg, pf_dev->port_obj));
844  IF_SUCCESS(result, doca_flow_pipe_cfg_set_name(pipe_cfg, "EGR_ACL"));
849  IF_SUCCESS(result, doca_flow_pipe_cfg_set_match(pipe_cfg, &match, nullptr));
850  IF_SUCCESS(result, doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, nullptr, nullptr, 1));
851  IF_SUCCESS(result, doca_flow_pipe_cfg_set_monitor(pipe_cfg, &monitor_count));
852  IF_SUCCESS(result, doca_flow_pipe_create(pipe_cfg, &fwd, &fwd_miss, &egress_dst_ip6_pipe));
853  if (pipe_cfg) {
854  doca_flow_pipe_cfg_destroy(pipe_cfg);
855  }
856 
857  return result;
858 }
859 
860 doca_error_t PSP_GatewayFlows::egress_acl_pipe_create(bool ipv4)
861 {
862  DOCA_LOG_DBG("\n>> %s", __FUNCTION__);
863  assert(rss_pipe);
864  assert(!sampling_enabled || egress_sampling_pipe);
866  struct doca_flow_pipe **pipe = ipv4 ? &egress_acl_ipv4_pipe : &egress_acl_ipv6_pipe;
867  doca_flow_match match = {};
868 
871  if (ipv4) {
872  match.outer.ip4.dst_ip = UINT32_MAX;
873  match.outer.ip4.src_ip = UINT32_MAX;
874  } else {
875  match.meta.u32[2] = UINT32_MAX;
876  SET_IP6_ADDR(match.outer.ip6.src_ip, UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX);
877  }
878 
880  doca_flow_actions encap_ipv4 = {};
881  doca_flow_actions encap_ipv6 = {};
882 
883  actions.has_crypto_encap = true;
888  actions.crypto.crypto_id = UINT32_MAX; // per entry
889 
890  encap_ipv6 = actions;
891  encap_ipv4 = actions;
892 
893  if (app_config->mode == PSP_GW_MODE_TUNNEL) {
894  encap_ipv6.crypto_encap.net_type = encap_ipv4.crypto_encap.net_type =
896  encap_ipv6.crypto_encap.data_size = sizeof(eth_ipv6_psp_tunnel_hdr);
897  encap_ipv4.crypto_encap.data_size = sizeof(eth_ipv4_psp_tunnel_hdr);
898  } else {
901  encap_ipv6.crypto_encap.data_size = encap_ipv4.crypto_encap.data_size = sizeof(udp_psp_transport_hdr);
902  }
903 
904  if (!app_config->net_config.vc_enabled) {
905  encap_ipv6.crypto_encap.data_size -= sizeof(uint64_t);
906  encap_ipv4.crypto_encap.data_size -= sizeof(uint64_t);
907  }
908  memset(encap_ipv6.crypto_encap.encap_data, 0xff, encap_ipv6.crypto_encap.data_size);
909  memset(encap_ipv4.crypto_encap.encap_data, 0xff, encap_ipv4.crypto_encap.data_size);
910 
911  doca_flow_actions *actions_arr[] = {&encap_ipv6, &encap_ipv4};
912 
913  doca_flow_fwd fwd_to_sampling = {};
914  fwd_to_sampling.type = DOCA_FLOW_FWD_PIPE;
915  fwd_to_sampling.next_pipe = set_sample_bit_pipe;
916 
917  doca_flow_fwd fwd_to_wire = {};
918  fwd_to_wire.type = DOCA_FLOW_FWD_PORT;
919  fwd_to_wire.port_id = pf_dev->port_id;
920 
921  auto p_fwd = sampling_enabled ? &fwd_to_sampling : &fwd_to_wire;
922 
923  doca_flow_fwd fwd_miss = {};
925  fwd_miss.next_pipe = rss_pipe;
926 
927  doca_flow_pipe_cfg *pipe_cfg;
928  IF_SUCCESS(result, doca_flow_pipe_cfg_create(&pipe_cfg, pf_dev->port_obj));
929  IF_SUCCESS(result, doca_flow_pipe_cfg_set_name(pipe_cfg, ipv4 ? "EGR_ACL_IPV4" : "EGR_ACL_IPV6"));
934  IF_SUCCESS(result, doca_flow_pipe_cfg_set_match(pipe_cfg, &match, nullptr));
935  IF_SUCCESS(result, doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, nullptr, nullptr, 2));
936  IF_SUCCESS(result, doca_flow_pipe_cfg_set_monitor(pipe_cfg, &monitor_count));
937  IF_SUCCESS(result, doca_flow_pipe_create(pipe_cfg, p_fwd, &fwd_miss, pipe));
938 
939  if (pipe_cfg) {
940  doca_flow_pipe_cfg_destroy(pipe_cfg);
941  }
942 
943  return result;
944 }
945 
946 doca_error_t PSP_GatewayFlows::add_egress_dst_ip6_entry(psp_session_t *session, int dst_vip_id)
947 {
948  doca_flow_match match = {};
950  session->dst_vip.ipv6_addr[0],
951  session->dst_vip.ipv6_addr[1],
952  session->dst_vip.ipv6_addr[2],
953  session->dst_vip.ipv6_addr[3]);
954 
956  actions.meta.u32[2] = dst_vip_id;
957 
958  return add_single_entry(0, egress_dst_ip6_pipe, pf_dev->port_obj, &match, &actions, nullptr, nullptr, nullptr);
959 }
960 
962 {
963  DOCA_LOG_DBG("\n>> %s", __FUNCTION__);
965  std::string dst_pip = ip_to_string(session->dst_pip);
966  std::string src_vip = ip_to_string(session->src_vip);
967  std::string dst_vip = ip_to_string(session->dst_vip);
968  struct doca_flow_pipe *pipe;
969 
970  DOCA_LOG_DBG("Creating encrypt flow entry: dst_pip %s, src_vip %s, dst_vip %s, SPI %d, crypto_id %d",
971  dst_pip.c_str(),
972  src_vip.c_str(),
973  dst_vip.c_str(),
974  session->spi_egress,
975  session->crypto_id);
976 
977  struct doca_flow_shared_resource_cfg res_cfg = {};
980  res_cfg.psp_cfg.key_cfg.key = (uint32_t *)encrypt_key;
981 
983  if (result != DOCA_SUCCESS) {
984  DOCA_LOG_ERR("Failed to configure crypto_id %d: %s", session->crypto_id, doca_error_get_descr(result));
985  return result;
986  }
987 
988  doca_flow_match encap_encrypt_match = {};
989  if (session->dst_vip.type == DOCA_FLOW_L3_TYPE_IP4) {
990  pipe = egress_acl_ipv4_pipe;
991  encap_encrypt_match.parser_meta.outer_l3_type = DOCA_FLOW_L3_META_IPV4;
992  encap_encrypt_match.outer.l3_type = DOCA_FLOW_L3_TYPE_IP4;
993  encap_encrypt_match.outer.ip4.src_ip = session->src_vip.ipv4_addr;
994  encap_encrypt_match.outer.ip4.dst_ip = session->dst_vip.ipv4_addr;
995  } else {
996  pipe = egress_acl_ipv6_pipe;
997  encap_encrypt_match.parser_meta.outer_l3_type = DOCA_FLOW_L3_META_IPV6;
998  encap_encrypt_match.outer.l3_type = DOCA_FLOW_L3_TYPE_IP6;
999  SET_IP6_ADDR(encap_encrypt_match.outer.ip6.src_ip,
1000  session->src_vip.ipv6_addr[0],
1001  session->src_vip.ipv6_addr[1],
1002  session->src_vip.ipv6_addr[2],
1003  session->src_vip.ipv6_addr[3]);
1004 
1005  int dst_vip_id = rte_hash_lookup(app_config->ip6_table, session->dst_vip.ipv6_addr);
1006  if (dst_vip_id < 0) {
1007  DOCA_LOG_WARN("Failed to find source IP in table");
1008  int ret = rte_hash_add_key(app_config->ip6_table, session->dst_vip.ipv6_addr);
1009  if (ret < 0) {
1010  DOCA_LOG_ERR("Failed to add address to hash table");
1011  return DOCA_ERROR_DRIVER;
1012  }
1013  dst_vip_id = rte_hash_lookup(app_config->ip6_table, session->dst_vip.ipv6_addr);
1014  }
1015  encap_encrypt_match.meta.u32[2] = dst_vip_id;
1016  result = add_egress_dst_ip6_entry(session, dst_vip_id);
1017  if (result != DOCA_SUCCESS)
1018  return result;
1019  }
1020 
1021  doca_flow_actions encap_actions = {};
1022  encap_actions.has_crypto_encap = true;
1023  /* Add to ipv4/ipv6 according to dst pip in tunnel mode and dst vip in transport mode */
1024  if ((app_config->mode == PSP_GW_MODE_TUNNEL && session->dst_pip.type == DOCA_FLOW_L3_TYPE_IP6) ||
1026  encap_actions.action_idx = 0;
1027  } else {
1028  encap_actions.action_idx = 1;
1029  }
1030  if (app_config->mode == PSP_GW_MODE_TRANSPORT)
1031  format_encap_transport_data(session, encap_actions.crypto_encap.encap_data);
1032  else if (session->dst_pip.type == DOCA_FLOW_L3_TYPE_IP6)
1033  format_encap_tunnel_data_ipv6(session, encap_actions.crypto_encap.encap_data);
1034  else
1035  format_encap_tunnel_data_ipv4(session, encap_actions.crypto_encap.encap_data);
1036 
1037  encap_actions.crypto.crypto_id = session->crypto_id;
1038 
1039  result = add_single_entry(0,
1040  pipe,
1041  pf_dev->port_obj,
1042  &encap_encrypt_match,
1043  &encap_actions,
1044  nullptr,
1045  nullptr,
1046  &session->encap_encrypt_entry);
1047 
1048  if (result != DOCA_SUCCESS) {
1049  DOCA_LOG_ERR("Failed to add encrypt_encap pipe entry: %s", doca_error_get_descr(result));
1050  return result;
1051  }
1052 
1053  DOCA_LOG_DBG("Created session entry: %p", session->encap_encrypt_entry);
1054 
1055  session->pkt_count_egress = UINT64_MAX; // force next query to detect a change
1056 
1057  return result;
1058 }
1059 
1060 void PSP_GatewayFlows::format_encap_tunnel_data_ipv6(const psp_session_t *session, uint8_t *encap_data)
1061 {
1062  static const doca_be32_t DEFAULT_VTC_FLOW = 0x6 << 28;
1063 
1064  auto *encap_hdr = (eth_ipv6_psp_tunnel_hdr *)encap_data;
1065  encap_hdr->eth.ether_type = RTE_BE16(RTE_ETHER_TYPE_IPV6);
1066  encap_hdr->ip.vtc_flow = RTE_BE32(DEFAULT_VTC_FLOW);
1067  encap_hdr->ip.proto = IPPROTO_UDP;
1068  encap_hdr->ip.hop_limits = 50;
1069  encap_hdr->udp.src_port = 0x0; // computed
1070  encap_hdr->udp.dst_port = RTE_BE16(DOCA_FLOW_PSP_DEFAULT_PORT);
1071  encap_hdr->psp.nexthdr = session->dst_vip.type == DOCA_FLOW_L3_TYPE_IP6 ? NEXT_HEADER_IPV6 : NEXT_HEADER_IPV4;
1072  encap_hdr->psp.hdrextlen = (uint8_t)(app_config->net_config.vc_enabled ? 2 : 1);
1073  encap_hdr->psp.res_cryptofst = (uint8_t)app_config->net_config.crypt_offset;
1074  encap_hdr->psp.spi = RTE_BE32(session->spi_egress);
1075  encap_hdr->psp_virt_cookie = RTE_BE64(session->vc);
1076 
1077  const auto &dmac = app_config->nexthop_enable ? app_config->nexthop_dmac : session->dst_mac;
1078  memcpy(encap_hdr->eth.src_addr.addr_bytes, pf_dev->src_mac.addr_bytes, RTE_ETHER_ADDR_LEN);
1079  memcpy(encap_hdr->eth.dst_addr.addr_bytes, dmac.addr_bytes, RTE_ETHER_ADDR_LEN);
1080  memcpy(encap_hdr->ip.src_addr, pf_dev->src_pip.ipv6_addr, IPV6_ADDR_LEN);
1081  memcpy(encap_hdr->ip.dst_addr, session->dst_pip.ipv6_addr, IPV6_ADDR_LEN);
1082 
1083  encap_hdr->psp.rsrv1 = 1; // always 1
1084  encap_hdr->psp.ver = session->psp_proto_ver;
1085  encap_hdr->psp.v = !!app_config->net_config.vc_enabled;
1086  // encap_hdr->psp.s will be set by the egress_sampling pipe
1087 }
1088 
1089 void PSP_GatewayFlows::format_encap_tunnel_data_ipv4(const psp_session_t *session, uint8_t *encap_data)
1090 {
1091  auto *encap_hdr = (eth_ipv4_psp_tunnel_hdr *)encap_data;
1092  encap_hdr->eth.ether_type = RTE_BE16(RTE_ETHER_TYPE_IPV4);
1093  encap_hdr->udp.src_port = 0x0; // computed
1094  encap_hdr->udp.dst_port = RTE_BE16(DOCA_FLOW_PSP_DEFAULT_PORT);
1095  encap_hdr->psp.nexthdr = session->dst_vip.type == DOCA_FLOW_L3_TYPE_IP6 ? NEXT_HEADER_IPV6 : NEXT_HEADER_IPV4;
1096  encap_hdr->psp.hdrextlen = (uint8_t)(app_config->net_config.vc_enabled ? 2 : 1);
1097  encap_hdr->psp.res_cryptofst = (uint8_t)app_config->net_config.crypt_offset;
1098  encap_hdr->psp.spi = RTE_BE32(session->spi_egress);
1099  encap_hdr->psp_virt_cookie = RTE_BE64(session->vc);
1100 
1101  const auto &dmac = app_config->nexthop_enable ? app_config->nexthop_dmac : session->dst_mac;
1102  memcpy(encap_hdr->eth.src_addr.addr_bytes, pf_dev->src_mac.addr_bytes, RTE_ETHER_ADDR_LEN);
1103  memcpy(encap_hdr->eth.dst_addr.addr_bytes, dmac.addr_bytes, RTE_ETHER_ADDR_LEN);
1104  encap_hdr->ip.src_addr = pf_dev->src_pip.ipv4_addr;
1105  encap_hdr->ip.dst_addr = session->dst_pip.ipv4_addr;
1106  encap_hdr->ip.version_ihl = 0x45;
1107  encap_hdr->ip.next_proto_id = IPPROTO_UDP;
1108  encap_hdr->ip.time_to_live = 64;
1109 
1110  encap_hdr->psp.rsrv1 = 1; // always 1
1111  encap_hdr->psp.ver = session->psp_proto_ver;
1112  encap_hdr->psp.v = !!app_config->net_config.vc_enabled;
1113  // encap_hdr->psp.s will be set by the egress_sampling pipe
1114 }
1115 
1116 void PSP_GatewayFlows::format_encap_transport_data(const psp_session_t *session, uint8_t *encap_data)
1117 {
1118  auto *encap_hdr = (udp_psp_transport_hdr *)encap_data;
1119  encap_hdr->udp.src_port = 0x0; // computed
1120  encap_hdr->udp.dst_port = RTE_BE16(DOCA_FLOW_PSP_DEFAULT_PORT);
1121  encap_hdr->psp.nexthdr = 0; // computed
1122  encap_hdr->psp.hdrextlen = (uint8_t)(app_config->net_config.vc_enabled ? 2 : 1);
1123  encap_hdr->psp.res_cryptofst = (uint8_t)app_config->net_config.crypt_offset;
1124  encap_hdr->psp.spi = RTE_BE32(session->spi_egress);
1125  encap_hdr->psp_virt_cookie = RTE_BE64(session->vc);
1126 
1127  encap_hdr->psp.rsrv1 = 1; // always 1
1128  encap_hdr->psp.ver = session->psp_proto_ver;
1129  encap_hdr->psp.v = !!app_config->net_config.vc_enabled;
1130  // encap_hdr->psp.s will be set by the egress_sampling pipe
1131 }
1132 
1134 {
1135  DOCA_LOG_DBG("\n>> %s", __FUNCTION__);
1137  uint16_t pipe_queue = 0;
1138  uint32_t flags = DOCA_FLOW_NO_WAIT;
1139  uint32_t num_of_entries = 1;
1140 
1141  result = doca_flow_pipe_remove_entry(pipe_queue, flags, session->encap_encrypt_entry);
1142  if (result != DOCA_SUCCESS) {
1143  DOCA_LOG_INFO("Error removing PSP encap entry: %s", doca_error_get_descr(result));
1144  }
1145 
1146  result = doca_flow_entries_process(pf_dev->port_obj, 0, DEFAULT_TIMEOUT_US, num_of_entries);
1147  if (result != DOCA_SUCCESS) {
1148  DOCA_LOG_ERR("Failed to process entry: %s", doca_error_get_descr(result));
1149  return result;
1150  }
1151 
1152  return result;
1153 }
1154 
1155 doca_error_t PSP_GatewayFlows::egress_sampling_pipe_create(void)
1156 {
1157  DOCA_LOG_DBG("\n>> %s", __FUNCTION__);
1158  assert(sampling_enabled);
1159 
1161 
1165 
1166  doca_flow_match match = {};
1167  match.tun.type = DOCA_FLOW_TUN_PSP;
1168  match.tun.psp.s_d_ver_v = -1;
1169 
1170  doca_flow_monitor mirror_action = {};
1172  mirror_action.shared_mirror_id = -1;
1173 
1174  doca_flow_fwd fwd = {};
1176  fwd.next_pipe = fwd_to_wire_pipe;
1177 
1178  doca_flow_fwd fwd_miss = {};
1179  if (app_config->maintain_order) {
1181  } else {
1182  fwd_miss = fwd;
1183  }
1184 
1185  doca_flow_pipe_cfg *pipe_cfg;
1186  IF_SUCCESS(result, doca_flow_pipe_cfg_create(&pipe_cfg, pf_dev->port_obj));
1187  IF_SUCCESS(result, doca_flow_pipe_cfg_set_name(pipe_cfg, "EGR_SAMPL"));
1192  IF_SUCCESS(result, doca_flow_pipe_cfg_set_monitor(pipe_cfg, &mirror_action));
1193  IF_SUCCESS(result, doca_flow_pipe_create(pipe_cfg, &fwd, &fwd_miss, &egress_sampling_pipe));
1194 
1195  if (pipe_cfg) {
1196  doca_flow_pipe_cfg_destroy(pipe_cfg);
1197  }
1198 
1200  mirror_action.shared_mirror_id = mirror_res_id_rss;
1202  add_single_entry(0,
1203  egress_sampling_pipe,
1204  pf_dev->port_obj,
1205  &match,
1206  nullptr,
1207  &mirror_action,
1208  nullptr,
1209  &egr_sampling_rss));
1210 
1211  if (app_config->maintain_order) {
1212  match.tun.psp.s_d_ver_v = 0;
1213  mirror_action.shared_mirror_id = mirror_res_id_drop;
1215  add_single_entry(0,
1216  egress_sampling_pipe,
1217  pf_dev->port_obj,
1218  &match,
1219  nullptr,
1220  &mirror_action,
1221  nullptr,
1222  &egr_sampling_drop));
1223  }
1224  return result;
1225 }
1226 
1227 doca_error_t PSP_GatewayFlows::empty_pipe_create(void)
1228 {
1230 
1231  doca_flow_match match = {};
1232  match.outer.eth.type = UINT16_MAX;
1233  match.meta.pkt_meta = UINT32_MAX;
1234 
1235  doca_flow_fwd fwd = {};
1237 
1238  doca_flow_fwd fwd_miss = {};
1240 
1241  doca_flow_pipe_cfg *pipe_cfg;
1242  IF_SUCCESS(result, doca_flow_pipe_cfg_create(&pipe_cfg, pf_dev->port_obj));
1243  IF_SUCCESS(result, doca_flow_pipe_cfg_set_name(pipe_cfg, "EMPTY"));
1247  IF_SUCCESS(result, doca_flow_pipe_cfg_set_match(pipe_cfg, &match, &match));
1248  IF_SUCCESS(result, doca_flow_pipe_cfg_set_monitor(pipe_cfg, &monitor_count));
1250  IF_SUCCESS(result, doca_flow_pipe_create(pipe_cfg, &fwd, &fwd_miss, &empty_pipe));
1251 
1252  if (pipe_cfg) {
1253  doca_flow_pipe_cfg_destroy(pipe_cfg);
1254  }
1255 
1256  match.outer.eth.type = RTE_BE16(DOCA_FLOW_ETHER_TYPE_ARP);
1257  match.meta.pkt_meta = RTE_BE32(app_config->return_to_vf_indicator); // ARP indicator
1259  fwd.port_id = vf_port_id;
1260  IF_SUCCESS(
1261  result,
1262  add_single_entry(0, empty_pipe, pf_dev->port_obj, &match, nullptr, nullptr, &fwd, &arp_empty_pipe_entry));
1263 
1264  match.outer.eth.type = RTE_BE16(DOCA_FLOW_ETHER_TYPE_IPV6);
1265  // pkt_meta is already set as return_to_vf_indicator in previous entry
1266  // fwd.type is already set as DOCA_FLOW_FWD_PORT in previous entry
1267  // fwd.port_id is already set to vf_port_id in previous entry
1268 
1269  IF_SUCCESS(
1270  result,
1271  add_single_entry(0, empty_pipe, pf_dev->port_obj, &match, nullptr, nullptr, &fwd, &ns_empty_pipe_entry));
1272 
1273  match.outer.eth.type = RTE_BE16(DOCA_FLOW_ETHER_TYPE_IPV4);
1274  match.meta.pkt_meta = 0;
1276  fwd.next_pipe = egress_acl_ipv4_pipe;
1278  add_single_entry(0,
1279  empty_pipe,
1280  pf_dev->port_obj,
1281  &match,
1282  nullptr,
1283  nullptr,
1284  &fwd,
1285  &ipv4_empty_pipe_entry));
1286 
1287  match.outer.eth.type = RTE_BE16(DOCA_FLOW_ETHER_TYPE_IPV6);
1288  fwd.next_pipe = egress_dst_ip6_pipe;
1289  // pkt_meta is already set as 0 in previous entry
1290 
1292  add_single_entry(0,
1293  empty_pipe,
1294  pf_dev->port_obj,
1295  &match,
1296  nullptr,
1297  nullptr,
1298  &fwd,
1299  &ipv6_empty_pipe_entry));
1300  return result;
1301 }
1302 
1303 doca_error_t PSP_GatewayFlows::fwd_to_wire_pipe_create(void)
1304 {
1306 
1307  doca_flow_match match = {};
1308 
1309  doca_flow_fwd fwd = {};
1311  fwd.port_id = pf_dev->port_id;
1312 
1313  doca_flow_fwd fwd_miss = {};
1315 
1316  doca_flow_pipe_cfg *pipe_cfg;
1317  IF_SUCCESS(result, doca_flow_pipe_cfg_create(&pipe_cfg, pf_dev->port_obj));
1318  IF_SUCCESS(result, doca_flow_pipe_cfg_set_name(pipe_cfg, "fwd_to_wire"));
1321  IF_SUCCESS(result, doca_flow_pipe_cfg_set_match(pipe_cfg, &match, nullptr));
1322  IF_SUCCESS(result, doca_flow_pipe_cfg_set_monitor(pipe_cfg, &monitor_count));
1324  IF_SUCCESS(result, doca_flow_pipe_create(pipe_cfg, &fwd, &fwd_miss, &fwd_to_wire_pipe));
1325 
1327  add_single_entry(0,
1328  fwd_to_wire_pipe,
1329  pf_dev->port_obj,
1330  nullptr,
1331  nullptr,
1332  nullptr,
1333  nullptr,
1334  &fwd_to_wire_entry));
1335 
1336  if (pipe_cfg) {
1337  doca_flow_pipe_cfg_destroy(pipe_cfg);
1338  }
1339 
1340  return result;
1341 }
1342 
1343 doca_error_t PSP_GatewayFlows::fwd_to_rss_pipe_create(void)
1344 {
1346 
1347  doca_flow_match match = {};
1348 
1350  actions.meta.pkt_meta = DOCA_HTOBE32(app_config->egress_sample_meta_indicator);
1351  doca_flow_actions *actions_arr[] = {&actions};
1352 
1353  doca_flow_actions actions_mask = {};
1354  actions_mask.meta.pkt_meta = UINT32_MAX;
1355  doca_flow_actions *actions_masks_arr[] = {&actions_mask};
1356 
1357  doca_flow_pipe_cfg *pipe_cfg;
1358  IF_SUCCESS(result, doca_flow_pipe_cfg_create(&pipe_cfg, pf_dev->port_obj));
1359  IF_SUCCESS(result, doca_flow_pipe_cfg_set_name(pipe_cfg, "fwd_to_rss"));
1361  IF_SUCCESS(result, doca_flow_pipe_cfg_set_match(pipe_cfg, &match, &match));
1362  IF_SUCCESS(result, doca_flow_pipe_cfg_set_monitor(pipe_cfg, &monitor_count));
1364  IF_SUCCESS(result, doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, actions_masks_arr, nullptr, 1));
1365  IF_SUCCESS(result, doca_flow_pipe_create(pipe_cfg, &fwd_rss, NULL, &fwd_to_rss_pipe));
1366 
1368  add_single_entry(0,
1369  fwd_to_rss_pipe,
1370  pf_dev->port_obj,
1371  nullptr,
1372  nullptr,
1373  nullptr,
1374  nullptr,
1375  &fwd_to_rss_entry));
1376 
1377  if (pipe_cfg) {
1378  doca_flow_pipe_cfg_destroy(pipe_cfg);
1379  }
1380 
1381  return result;
1382 }
1383 
1384 doca_error_t PSP_GatewayFlows::set_sample_bit_pipe_create(void)
1385 {
1387 
1388  uint16_t mask = (uint16_t)((1 << app_config->log2_sample_rate) - 1);
1389  DOCA_LOG_DBG("Sampling: matching (rand & 0x%x) == 1", mask);
1390 
1391  doca_flow_match match_sampling_match_mask = {};
1392  match_sampling_match_mask.parser_meta.random = DOCA_HTOBE16(mask);
1393 
1394  doca_flow_match match_sampling_match = {};
1395  match_sampling_match.parser_meta.random = DOCA_HTOBE16(0x1);
1396 
1397  doca_flow_fwd fwd = {};
1399  fwd.next_pipe = egress_sampling_pipe;
1400 
1401  doca_flow_fwd fwd_miss = {};
1403  fwd_miss.next_pipe = egress_sampling_pipe;
1404 
1405  doca_flow_actions set_sample_bit = {};
1406  set_sample_bit.tun.type = DOCA_FLOW_TUN_PSP;
1407  set_sample_bit.tun.psp.s_d_ver_v = PSP_SAMPLE_ENABLE;
1408 
1409  doca_flow_actions *actions_arr[] = {&set_sample_bit};
1410  doca_flow_actions *actions_masks_arr[] = {&set_sample_bit};
1411 
1412  doca_flow_pipe_cfg *pipe_cfg;
1413  IF_SUCCESS(result, doca_flow_pipe_cfg_create(&pipe_cfg, pf_dev->port_obj));
1414  IF_SUCCESS(result, doca_flow_pipe_cfg_set_name(pipe_cfg, "FWD_TO_RSS"));
1417  IF_SUCCESS(result, doca_flow_pipe_cfg_set_match(pipe_cfg, &match_sampling_match, &match_sampling_match_mask));
1418  IF_SUCCESS(result, doca_flow_pipe_cfg_set_monitor(pipe_cfg, &monitor_count));
1420  IF_SUCCESS(result, doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, actions_masks_arr, nullptr, 1));
1421  IF_SUCCESS(result, doca_flow_pipe_create(pipe_cfg, &fwd, &fwd_miss, &set_sample_bit_pipe));
1422 
1424  add_single_entry(0,
1425  set_sample_bit_pipe,
1426  pf_dev->port_obj,
1427  nullptr,
1428  nullptr,
1429  nullptr,
1430  nullptr,
1431  &set_sample_bit_entry));
1432 
1433  if (pipe_cfg) {
1434  doca_flow_pipe_cfg_destroy(pipe_cfg);
1435  }
1436 
1437  return result;
1438 }
1439 
1440 doca_error_t PSP_GatewayFlows::empty_pipe_create_not_sampled(void)
1441 {
1443  doca_flow_match match = {};
1444 
1445  doca_flow_fwd fwd = {};
1447  fwd.port_id = pf_dev->port_id;
1448 
1449  doca_flow_pipe_cfg *pipe_cfg;
1450  IF_SUCCESS(result, doca_flow_pipe_cfg_create(&pipe_cfg, pf_dev->port_obj));
1451  IF_SUCCESS(result, doca_flow_pipe_cfg_set_name(pipe_cfg, "EMPTY_NOT_SAMPLED"));
1454  IF_SUCCESS(result, doca_flow_pipe_cfg_set_match(pipe_cfg, &match, nullptr));
1455  IF_SUCCESS(result, doca_flow_pipe_cfg_set_monitor(pipe_cfg, &monitor_count));
1456  IF_SUCCESS(result, doca_flow_pipe_create(pipe_cfg, &fwd, nullptr, &empty_pipe_not_sampled));
1458  add_single_entry(0,
1459  empty_pipe_not_sampled,
1460  pf_dev->port_obj,
1461  nullptr,
1462  nullptr,
1463  nullptr,
1464  nullptr,
1465  &empty_pipe_entry));
1466 
1467  if (pipe_cfg) {
1468  doca_flow_pipe_cfg_destroy(pipe_cfg);
1469  }
1470 
1471  return result;
1472 }
1473 
1474 doca_error_t PSP_GatewayFlows::ingress_root_pipe_create(void)
1475 {
1476  DOCA_LOG_DBG("\n>> %s", __FUNCTION__);
1477  assert(ingress_decrypt_pipe);
1479 
1480  doca_flow_pipe_cfg *pipe_cfg;
1481  IF_SUCCESS(result, doca_flow_pipe_cfg_create(&pipe_cfg, pf_dev->port_obj));
1482  IF_SUCCESS(result, doca_flow_pipe_cfg_set_name(pipe_cfg, "ROOT"));
1485  uint32_t nb_entries = app_config->mode == PSP_GW_MODE_TUNNEL ? 7 : 9;
1487  IF_SUCCESS(result, doca_flow_pipe_create(pipe_cfg, nullptr, nullptr, &ingress_root_pipe));
1488 
1489  if (pipe_cfg) {
1490  doca_flow_pipe_cfg_destroy(pipe_cfg);
1491  }
1492 
1493  // Note outer_l4_ok can be matched with spec=true, mask=UINT8_MAX to
1494  // restrict traffic to TCP/UDP (ICMP would miss to RSS).
1495  doca_flow_match mask = {};
1496  mask.parser_meta.port_id = UINT16_MAX;
1497  mask.parser_meta.outer_l3_ok = UINT8_MAX;
1498  mask.parser_meta.outer_ip4_checksum_ok = UINT8_MAX;
1499  mask.outer.eth.type = UINT16_MAX;
1500 
1501  doca_flow_match ipv6_from_uplink = {};
1502  ipv6_from_uplink.parser_meta.port_id = pf_dev->port_id;
1503  ipv6_from_uplink.parser_meta.outer_l3_ok = true;
1504  ipv6_from_uplink.parser_meta.outer_ip4_checksum_ok = false;
1505  ipv6_from_uplink.outer.eth.type = RTE_BE16(RTE_ETHER_TYPE_IPV6);
1506 
1507  doca_flow_match ipv4_from_uplink = {};
1508  ipv4_from_uplink.parser_meta.port_id = pf_dev->port_id;
1509  ipv4_from_uplink.parser_meta.outer_l3_ok = true;
1510  ipv4_from_uplink.parser_meta.outer_ip4_checksum_ok = true;
1511  ipv4_from_uplink.outer.eth.type = RTE_BE16(RTE_ETHER_TYPE_IPV4);
1512 
1513  doca_flow_match ipv4_from_vf = {};
1514  ipv4_from_vf.parser_meta.port_id = vf_port_id;
1515  ipv4_from_vf.parser_meta.outer_l3_ok = true;
1516  ipv4_from_vf.parser_meta.outer_ip4_checksum_ok = true;
1517  ipv4_from_vf.outer.eth.type = RTE_BE16(RTE_ETHER_TYPE_IPV4);
1518 
1519  doca_flow_match ipv6_from_vf = {};
1520  ipv6_from_vf.parser_meta.port_id = vf_port_id;
1521  ipv6_from_vf.parser_meta.outer_l3_ok = true;
1522  ipv6_from_vf.parser_meta.outer_ip4_checksum_ok = false;
1523  ipv6_from_vf.outer.eth.type = RTE_BE16(RTE_ETHER_TYPE_IPV6);
1524 
1525  doca_flow_match arp_mask = {};
1526  arp_mask.parser_meta.port_id = UINT16_MAX;
1527  arp_mask.outer.eth.type = UINT16_MAX;
1528 
1529  doca_flow_match ns_mask = {};
1530  ns_mask.parser_meta.port_id = UINT16_MAX;
1531  ns_mask.outer.eth.type = UINT16_MAX;
1532  ns_mask.parser_meta.outer_l3_type = (enum doca_flow_l3_meta)UINT32_MAX;
1533  ns_mask.parser_meta.outer_l4_type = (enum doca_flow_l4_meta)UINT32_MAX;
1534  ns_mask.outer.l4_type_ext = (enum doca_flow_l4_type_ext)UINT32_MAX;
1535  ns_mask.outer.ip6.next_proto = UINT8_MAX;
1536  ns_mask.outer.icmp.type = UINT8_MAX;
1537 
1538  doca_flow_match arp_from_vf = {};
1539  arp_from_vf.parser_meta.port_id = vf_port_id;
1540  arp_from_vf.outer.eth.type = RTE_BE16(DOCA_FLOW_ETHER_TYPE_ARP);
1541 
1542  doca_flow_match arp_from_uplink = {};
1543  arp_from_uplink.parser_meta.port_id = pf_dev->port_id;
1544  arp_from_uplink.outer.eth.type = RTE_BE16(DOCA_FLOW_ETHER_TYPE_ARP);
1545 
1546  doca_flow_match ns_from_vf = {};
1547  ns_from_vf.parser_meta.port_id = vf_port_id;
1548  ns_from_vf.outer.eth.type = RTE_BE16(RTE_ETHER_TYPE_IPV6);
1552  ns_from_vf.outer.ip6.next_proto = IPPROTO_ICMPV6;
1553  ns_from_vf.outer.icmp.type = ND_NEIGHBOR_SOLICIT;
1554 
1555  doca_flow_match ns_from_uplink = {};
1556  ns_from_uplink.parser_meta.port_id = pf_dev->port_id;
1557  ns_from_uplink.outer.eth.type = RTE_BE16(RTE_ETHER_TYPE_IPV6);
1561  ns_from_uplink.outer.ip6.next_proto = IPPROTO_ICMPV6;
1562  ns_from_uplink.outer.icmp.type = ND_NEIGHBOR_SOLICIT;
1563 
1564  doca_flow_match empty_match = {};
1565 
1566  doca_flow_fwd fwd_ingress = {};
1567  fwd_ingress.type = DOCA_FLOW_FWD_PIPE;
1568  fwd_ingress.next_pipe = ingress_decrypt_pipe;
1569 
1570  doca_flow_fwd fwd_egress = {};
1571  fwd_egress.type = DOCA_FLOW_FWD_PIPE;
1572  fwd_egress.next_pipe = empty_pipe; // and then to egress acl pipes
1573 
1574  doca_flow_fwd fwd_to_vf = {};
1575  fwd_to_vf.type = DOCA_FLOW_FWD_PORT;
1576  fwd_to_vf.port_id = vf_port_id;
1577 
1578  doca_flow_fwd fwd_to_wire = {};
1579  fwd_to_wire.type = DOCA_FLOW_FWD_PORT;
1580  fwd_to_wire.port_id = pf_dev->port_id;
1581 
1582  doca_flow_fwd fwd_miss = {};
1584 
1585  uint16_t pipe_queue = 0;
1586 
1589  2,
1590  ingress_root_pipe,
1591  &ipv6_from_uplink,
1592  &mask,
1593  nullptr,
1594  nullptr,
1595  nullptr,
1596  nullptr,
1597  &monitor_count,
1598  &fwd_ingress,
1599  nullptr,
1600  &root_jump_to_ingress_ipv6_entry));
1601 
1604  1,
1605  ingress_root_pipe,
1606  &ipv4_from_uplink,
1607  &mask,
1608  nullptr,
1609  nullptr,
1610  nullptr,
1611  nullptr,
1612  &monitor_count,
1613  &fwd_ingress,
1614  nullptr,
1615  &root_jump_to_ingress_ipv4_entry));
1616 
1619  2,
1620  ingress_root_pipe,
1621  &ipv6_from_vf,
1622  &mask,
1623  nullptr,
1624  nullptr,
1625  nullptr,
1626  nullptr,
1627  &monitor_count,
1628  &fwd_egress,
1629  nullptr,
1630  &root_jump_to_egress_ipv6_entry));
1631 
1634  2,
1635  ingress_root_pipe,
1636  &ipv4_from_vf,
1637  &mask,
1638  nullptr,
1639  nullptr,
1640  nullptr,
1641  nullptr,
1642  &monitor_count,
1643  &fwd_egress,
1644  nullptr,
1645  &root_jump_to_egress_ipv4_entry));
1646 
1647  if (app_config->mode == PSP_GW_MODE_TUNNEL) {
1648  // In tunnel mode, ARP packets are handled by the application
1651  3,
1652  ingress_root_pipe,
1653  &arp_from_vf,
1654  &arp_mask,
1655  nullptr,
1656  nullptr,
1657  nullptr,
1658  nullptr,
1659  &monitor_count,
1660  &fwd_rss,
1661  nullptr,
1662  &vf_arp_to_rss));
1663 
1666  1,
1667  ingress_root_pipe,
1668  &ns_from_vf,
1669  &ns_mask,
1670  nullptr,
1671  nullptr,
1672  nullptr,
1673  nullptr,
1674  &monitor_count,
1675  &fwd_rss,
1676  nullptr,
1677  &vf_ns_to_rss));
1678  } else {
1679  // In transport mode, ARP packets are forwarded to the opposite port (PF or VF)
1682  3,
1683  ingress_root_pipe,
1684  &arp_from_vf,
1685  &arp_mask,
1686  nullptr,
1687  nullptr,
1688  nullptr,
1689  nullptr,
1690  &monitor_count,
1691  &fwd_to_wire,
1692  nullptr,
1693  &vf_arp_to_wire));
1696  3,
1697  ingress_root_pipe,
1698  &arp_from_uplink,
1699  &arp_mask,
1700  nullptr,
1701  nullptr,
1702  nullptr,
1703  nullptr,
1704  &monitor_count,
1705  &fwd_to_vf,
1706  nullptr,
1707  &uplink_arp_to_vf));
1708 
1711  1,
1712  ingress_root_pipe,
1713  &ns_from_vf,
1714  &ns_mask,
1715  nullptr,
1716  nullptr,
1717  nullptr,
1718  nullptr,
1719  &monitor_count,
1720  &fwd_to_wire,
1721  nullptr,
1722  &vf_ns_to_wire));
1725  1,
1726  ingress_root_pipe,
1727  &ns_from_uplink,
1728  &ns_mask,
1729  nullptr,
1730  nullptr,
1731  nullptr,
1732  nullptr,
1733  &monitor_count,
1734  &fwd_to_vf,
1735  nullptr,
1736  &uplink_ns_to_vf));
1737  }
1738  // default miss in switch mode goes to NIC domain. this entry ensures to drop a non-matched packet
1741  4,
1742  ingress_root_pipe,
1743  &empty_match,
1744  &empty_match,
1745  nullptr,
1746  nullptr,
1747  nullptr,
1748  nullptr,
1749  &monitor_count,
1750  &fwd_miss,
1751  nullptr,
1752  &root_default_drop));
1753 
1754  return result;
1755 }
1756 
1757 /*
1758  * Entry processing callback
1759  *
1760  * @entry [in]: entry pointer
1761  * @pipe_queue [in]: queue identifier
1762  * @status [in]: DOCA Flow entry status
1763  * @op [in]: DOCA Flow entry operation
1764  * @user_ctx [out]: user context
1765  */
1766 void PSP_GatewayFlows::check_for_valid_entry(doca_flow_pipe_entry *entry,
1767  uint16_t pipe_queue,
1768  enum doca_flow_entry_status status,
1769  enum doca_flow_entry_op op,
1770  void *user_ctx)
1771 {
1772  (void)entry;
1773  (void)op;
1774  (void)pipe_queue;
1775 
1776  auto *entry_status = (entries_status *)user_ctx;
1777 
1778  if (entry_status == NULL || op != DOCA_FLOW_ENTRY_OP_ADD)
1779  return;
1780 
1781  if (status != DOCA_FLOW_ENTRY_STATUS_SUCCESS)
1782  entry_status->failure = true; /* set failure to true if processing failed */
1783 
1784  entry_status->nb_processed++;
1785  entry_status->entries_in_queue--;
1786 }
1787 
1788 doca_error_t PSP_GatewayFlows::add_single_entry(uint16_t pipe_queue,
1789  doca_flow_pipe *pipe,
1790  doca_flow_port *port,
1791  const doca_flow_match *match,
1792  const doca_flow_actions *actions,
1793  const doca_flow_monitor *mon,
1794  const doca_flow_fwd *fwd,
1795  doca_flow_pipe_entry **entry)
1796 {
1797  int num_of_entries = 1;
1798  uint32_t flags = DOCA_FLOW_NO_WAIT;
1799 
1800  app_config->status[pipe_queue] = entries_status();
1801  app_config->status[pipe_queue].entries_in_queue = num_of_entries;
1802 
1804  pipe,
1805  match,
1806  actions,
1807  mon,
1808  fwd,
1809  flags,
1810  &app_config->status[pipe_queue],
1811  entry);
1812 
1813  if (result != DOCA_SUCCESS) {
1814  DOCA_LOG_ERR("Failed to add entry: %s", doca_error_get_descr(result));
1815  return result;
1816  }
1817 
1818  result = doca_flow_entries_process(port, 0, DEFAULT_TIMEOUT_US, num_of_entries);
1819  if (result != DOCA_SUCCESS) {
1820  DOCA_LOG_ERR("Failed to process entry: %s", doca_error_get_descr(result));
1821  return result;
1822  }
1823 
1824  if (app_config->status[pipe_queue].nb_processed != num_of_entries || app_config->status[pipe_queue].failure) {
1825  DOCA_LOG_ERR("Failed to process entry; nb_processed = %d, failure = %d",
1826  app_config->status[pipe_queue].nb_processed,
1827  app_config->status[pipe_queue].failure);
1828  return DOCA_ERROR_BAD_STATE;
1829  }
1830 
1831  return result;
1832 }
1833 
1835  doca_flow_pipe *pipe; // used to query misses
1836  doca_flow_pipe_entry *entry; // used to query static entries
1837  std::string name; // displays the pipe name
1838 };
1839 
1840 std::pair<uint64_t, uint64_t> PSP_GatewayFlows::perform_pipe_query(pipe_query *query, bool suppress_output)
1841 {
1842  uint64_t new_hits = 0;
1843  uint64_t new_misses = 0;
1844 
1845  if (query->entry) {
1848  if (result == DOCA_SUCCESS) {
1849  new_hits = stats.counter.total_pkts;
1850  }
1851  }
1852  if (query->pipe) {
1855  if (result == DOCA_SUCCESS) {
1856  new_misses = stats.counter.total_pkts;
1857  }
1858  }
1859  if (!suppress_output) {
1860  if (query->entry && query->pipe) {
1861  DOCA_LOG_INFO("%s: %ld hits %ld misses", query->name.c_str(), new_hits, new_misses);
1862  } else if (query->entry) {
1863  DOCA_LOG_INFO("%s: %ld hits", query->name.c_str(), new_hits);
1864  } else if (query->pipe) {
1865  DOCA_LOG_INFO("%s: %ld misses", query->name.c_str(), new_hits);
1866  }
1867  }
1868 
1869  return std::make_pair(new_hits, new_misses);
1870 }
1871 
1873 {
1874  std::vector<pipe_query> queries;
1875  queries.emplace_back(pipe_query{nullptr, default_rss_entry, "rss_pipe"});
1876  queries.emplace_back(pipe_query{nullptr, root_jump_to_ingress_ipv6_entry, "root_jump_to_ingress_ipv6_entry"});
1877  queries.emplace_back(pipe_query{nullptr, root_jump_to_ingress_ipv4_entry, "root_jump_to_ingress_ipv4_entry"});
1878  queries.emplace_back(pipe_query{nullptr, root_jump_to_egress_ipv6_entry, "root_jump_to_egress_ipv6_entry"});
1879  queries.emplace_back(pipe_query{nullptr, root_jump_to_egress_ipv4_entry, "root_jump_to_egress_ipv4_entry"});
1880  queries.emplace_back(pipe_query{nullptr, vf_arp_to_rss, "vf_arp_to_rss"});
1881  queries.emplace_back(pipe_query{nullptr, vf_ns_to_rss, "vf_ns_to_rss"});
1882  queries.emplace_back(pipe_query{nullptr, vf_arp_to_wire, "vf_arp_to_wire"});
1883  queries.emplace_back(pipe_query{nullptr, uplink_arp_to_vf, "uplink_arp_to_vf"});
1884  queries.emplace_back(pipe_query{nullptr, vf_ns_to_wire, "vf_ns_to_wire"});
1885  queries.emplace_back(pipe_query{nullptr, uplink_ns_to_vf, "uplink_ns_to_vf"});
1886  queries.emplace_back(pipe_query{nullptr, root_default_drop, "root_miss_drop"});
1887  queries.emplace_back(pipe_query{ingress_decrypt_pipe, default_decrypt_entry, "default_decrypt_entry"});
1888  queries.emplace_back(
1889  pipe_query{ingress_inner_ip_classifier_pipe, ingress_ipv4_clasify_entry, "ingress_ipv4_clasify"});
1890  queries.emplace_back(
1891  pipe_query{ingress_inner_ip_classifier_pipe, ingress_ipv6_clasify_entry, "ingress_ipv6_clasify"});
1892  queries.emplace_back(pipe_query{ingress_sampling_pipe, default_ingr_sampling_entry, "ingress_sampling_pipe"});
1893  queries.emplace_back(pipe_query{ingress_acl_ipv4_pipe, default_ingr_acl_ipv4_entry, "ingress_acl_ipv4_pipe"});
1894  queries.emplace_back(pipe_query{ingress_acl_ipv6_pipe, default_ingr_acl_ipv6_entry, "ingress_acl_ipv6_pipe"});
1895  for (int i = 0; i < NUM_OF_PSP_SYNDROMES; i++) {
1896  switch (i + 1) {
1898  queries.emplace_back(pipe_query{nullptr, syndrome_stats_entries[i], "syndrome - ICV Fail"});
1899  break;
1901  queries.emplace_back(pipe_query{nullptr, syndrome_stats_entries[i], "syndrome - Bad Trailer"});
1902  break;
1903  }
1904  }
1905  queries.emplace_back(pipe_query{empty_pipe, nullptr, "egress_root"});
1906  queries.emplace_back(pipe_query{egress_acl_ipv4_pipe, nullptr, "egress_acl_ipv4_pipe"});
1907  queries.emplace_back(pipe_query{egress_acl_ipv6_pipe, nullptr, "egress_acl_ipv6_pipe"});
1908  queries.emplace_back(pipe_query{egress_sampling_pipe, egr_sampling_rss, "egress_sampling_rss"});
1909  queries.emplace_back(pipe_query{egress_sampling_pipe, egr_sampling_drop, "egress_sampling_drop"});
1910  queries.emplace_back(pipe_query{nullptr, empty_pipe_entry, "arp_packets_intercepted"});
1911  queries.emplace_back(pipe_query{fwd_to_wire_pipe, fwd_to_wire_entry, "fwd_to_wire_entry"});
1912  queries.emplace_back(pipe_query{nullptr, fwd_to_rss_entry, "fwd_to_rss_entry"});
1913  queries.emplace_back(pipe_query{nullptr, ipv4_empty_pipe_entry, "fwd_egress_acl_ipv4"});
1914  queries.emplace_back(pipe_query{nullptr, ipv6_empty_pipe_entry, "fwd_egress_acl_ipv6"});
1915  queries.emplace_back(pipe_query{nullptr, ns_empty_pipe_entry, "ns_empty_pipe_entry"});
1916 
1917  uint64_t total_pkts = 0;
1918  for (auto &query : queries) {
1919  auto hits_misses = perform_pipe_query(&query, true);
1920  total_pkts += hits_misses.first + hits_misses.second;
1921  }
1922 
1923  if (total_pkts != prev_static_flow_count) {
1924  total_pkts = 0;
1925  DOCA_LOG_INFO("-------------------------");
1926  for (auto &query : queries) {
1927  auto hits_misses = perform_pipe_query(&query, false);
1928  total_pkts += hits_misses.first + hits_misses.second;
1929  }
1930  prev_static_flow_count = total_pkts;
1931  }
1932 }
1933 
1935 {
1936  if (session.encap_encrypt_entry) {
1937  doca_flow_resource_query encap_encrypt_stats = {};
1938  doca_error_t encap_result =
1939  doca_flow_resource_query_entry(session.encap_encrypt_entry, &encap_encrypt_stats);
1940 
1941  if (encap_result == DOCA_SUCCESS) {
1942  if (session.pkt_count_egress != encap_encrypt_stats.counter.total_pkts) {
1943  DOCA_LOG_DBG("Session Egress (%s -> %s) entry: %p",
1944  session_vips_pair.first.c_str(),
1945  session_vips_pair.second.c_str(),
1946  session.encap_encrypt_entry);
1947  DOCA_LOG_INFO("Session Egress (%s -> %s): %ld hits",
1948  session_vips_pair.first.c_str(),
1949  session_vips_pair.second.c_str(),
1950  encap_encrypt_stats.counter.total_pkts);
1951  session.pkt_count_egress = encap_encrypt_stats.counter.total_pkts;
1952  }
1953  } else {
1954  DOCA_LOG_INFO("Session Egress (%s -> %s): query failed: %s",
1955  session_vips_pair.first.c_str(),
1956  session_vips_pair.second.c_str(),
1957  doca_error_get_descr(encap_result));
1958  }
1959  }
1960 
1961  if (!app_config->disable_ingress_acl && session.acl_entry) {
1962  doca_flow_resource_query acl_stats = {};
1964 
1965  if (result == DOCA_SUCCESS) {
1966  if (session.pkt_count_ingress != acl_stats.counter.total_pkts) {
1967  DOCA_LOG_DBG("Session ACL entry: %p", session.acl_entry);
1968  DOCA_LOG_INFO("Session Ingress (%s <- %s): %ld hits",
1969  session_vips_pair.first.c_str(),
1970  session_vips_pair.second.c_str(),
1971  acl_stats.counter.total_pkts);
1972  session.pkt_count_ingress = acl_stats.counter.total_pkts;
1973  }
1974  } else {
1975  DOCA_LOG_INFO("Session Ingress (%s <- %s): query failed: %s",
1976  session_vips_pair.first.c_str(),
1977  session_vips_pair.second.c_str(),
1979  }
1980  }
1981 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
#define SET_IP6_ADDR(addr, a, b, c, d)
Definition: flow_common.h:53
void show_session_flow_count(const session_key session_vips_pair, psp_session_t &session)
Shows flow counters for the given tunnel, if they have changed since the last invocation.
void show_static_flow_counts(void)
Shows flow counters for pipes which have a fixed number of entries, if any counter values have change...
doca_error_t add_ingress_acl_entry(psp_session_t *session)
Adds an ingress ACL entry for the given session to accept the combination of src_vip and SPI.
doca_error_t remove_encrypt_entry(psp_session_t *session)
Removes the indicated flow entry.
PSP_GatewayFlows(psp_pf_dev *pf, uint16_t vf_port_id, psp_gw_app_config *app_config)
Constructs the object. This operation cannot fail.
doca_error_t init(void)
Initialized the DOCA resources.
virtual ~PSP_GatewayFlows(void)
doca_error_t add_encrypt_entry(psp_session_t *session, const void *encrypt_key)
Adds a flow pipe entry to perform encryption on a new flow to the indicated peer. The caller is respo...
static struct eth_l2_fwd_stats stats
static int nb_entries
static struct doca_flow_fwd fwd_miss
Definition: flow_parser.c:110
static uint16_t * rss_queues
Definition: flow_parser.c:114
static struct doca_flow_actions actions
Definition: flow_parser.c:107
static struct doca_flow_fwd fwd
Definition: flow_parser.c:109
static struct doca_flow_match match_mask
Definition: flow_parser.c:106
static struct doca_flow_pipe_entry * entry[MAX_ENTRIES]
static struct app_gpu_cfg app_cfg
#define DOCA_HTOBE32(_x)
#define DOCA_HTOBE16(_x)
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_BAD_STATE
Definition: doca_error.h:56
@ DOCA_ERROR_NOT_SUPPORTED
Definition: doca_error.h:42
@ DOCA_SUCCESS
Definition: doca_error.h:38
@ DOCA_ERROR_DRIVER
Definition: doca_error.h:59
@ DOCA_FLOW_CRYPTO_HEADER_PSP_OVER_IPV4
@ DOCA_FLOW_CRYPTO_HEADER_PSP_OVER_IPV6
@ DOCA_FLOW_CRYPTO_HEADER_PSP_TUNNEL
@ DOCA_FLOW_CRYPTO_RESOURCE_PSP
@ DOCA_FLOW_CRYPTO_KEY_128
@ DOCA_FLOW_CRYPTO_KEY_256
@ DOCA_FLOW_CRYPTO_REFORMAT_ENCAP
@ DOCA_FLOW_CRYPTO_REFORMAT_DECAP
@ DOCA_FLOW_CRYPTO_ACTION_DECRYPT
@ DOCA_FLOW_CRYPTO_ACTION_ENCRYPT
doca_flow_l4_type_ext
doca flow layer 4 packet extend type
#define DOCA_FLOW_ETHER_TYPE_ARP
Definition: doca_flow_net.h:60
#define DOCA_FLOW_ETHER_TYPE_IPV6
Definition: doca_flow_net.h:58
#define DOCA_FLOW_PSP_DEFAULT_PORT
Definition: doca_flow_net.h:53
#define DOCA_FLOW_ETHER_TYPE_IPV4
Definition: doca_flow_net.h:57
@ DOCA_FLOW_L4_TYPE_EXT_ICMP6
@ DOCA_FLOW_L4_TYPE_EXT_UDP
@ DOCA_FLOW_L3_TYPE_IP6
@ DOCA_FLOW_L3_TYPE_IP4
@ DOCA_FLOW_TUN_PSP
DOCA_EXPERIMENTAL doca_error_t doca_flow_tune_server_init(struct doca_flow_tune_server_cfg *cfg)
Initialize a DOCA Flow Tune Server.
DOCA_EXPERIMENTAL doca_error_t doca_flow_tune_server_cfg_destroy(struct doca_flow_tune_server_cfg *cfg)
Destroy DOCA Flow Tune Server configuration struct.
DOCA_EXPERIMENTAL doca_error_t doca_flow_tune_server_cfg_create(struct doca_flow_tune_server_cfg **cfg)
Create DOCA Flow Tune Server configuration struct.
DOCA_EXPERIMENTAL void doca_flow_tune_server_destroy(void)
Destroy the DOCA Flow Tune Server.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_destroy(struct doca_flow_pipe_cfg *cfg)
Destroy DOCA Flow pipe configuration struct.
DOCA_STABLE doca_error_t doca_flow_cfg_set_mode_args(struct doca_flow_cfg *cfg, const char *mode_args)
Set DOCA mode args.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_create(struct doca_flow_pipe_cfg **cfg, struct doca_flow_port *port)
Create DOCA Flow pipe configuration struct.
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_pipe_cfg_set_name(struct doca_flow_pipe_cfg *cfg, const char *name)
Set pipe's name.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_cfg_set_match(struct doca_flow_pipe_cfg *cfg, const struct doca_flow_match *match, const struct doca_flow_match *match_mask)
Set pipe's match and match mask.
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_pipe_control_add_entry(uint16_t pipe_queue, uint32_t priority, struct doca_flow_pipe *pipe, const struct doca_flow_match *match, const struct doca_flow_match *match_mask, const struct doca_flow_match_condition *condition, const struct doca_flow_actions *actions, const struct doca_flow_actions *actions_mask, const struct doca_flow_action_descs *action_descs, const struct doca_flow_monitor *monitor, const struct doca_flow_fwd *fwd, void *usr_ctx, struct doca_flow_pipe_entry **entry)
Add one new entry to a control pipe.
DOCA_EXPERIMENTAL doca_error_t doca_flow_port_start(const struct doca_flow_port_cfg *cfg, struct doca_flow_port **port)
Start a doca port.
doca_flow_entry_op
doca flow entry operation
Definition: doca_flow.h:146
DOCA_STABLE doca_error_t doca_flow_cfg_set_cb_entry_process(struct doca_flow_cfg *cfg, doca_flow_entry_process_cb cb)
Set callback for entry create/destroy.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_set_is_root(struct doca_flow_pipe_cfg *cfg, bool is_root)
Set if pipe is root or not.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_create(const struct doca_flow_pipe_cfg *cfg, const struct doca_flow_fwd *fwd, const struct doca_flow_fwd *fwd_miss, struct doca_flow_pipe **pipe)
Create one new pipe.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_cfg_set_miss_counter(struct doca_flow_pipe_cfg *cfg, bool miss_counter)
Set to enable pipe's miss counter.
DOCA_STABLE doca_error_t doca_flow_cfg_create(struct doca_flow_cfg **cfg)
Create DOCA Flow configuration struct.
doca_flow_l3_meta
doca flow l3 valid type for parser meta
Definition: doca_flow.h:293
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_set_type(struct doca_flow_pipe_cfg *cfg, enum doca_flow_pipe_type type)
Set pipe's type.
#define DOCA_FLOW_PSP_DECRYPTION_ID
Definition: doca_flow.h:621
DOCA_EXPERIMENTAL doca_error_t doca_flow_init(struct doca_flow_cfg *cfg)
Initialize the doca flow.
DOCA_EXPERIMENTAL doca_error_t doca_flow_port_cfg_set_dev(struct doca_flow_port_cfg *cfg, struct doca_dev *dev)
Set port's device.
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 doca_error_t doca_flow_cfg_set_nr_counters(struct doca_flow_cfg *cfg, uint32_t nr_counters)
Set number of counters to configure.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_cfg_set_actions(struct doca_flow_pipe_cfg *cfg, struct doca_flow_actions *const *actions, struct doca_flow_actions *const *actions_masks, struct doca_flow_action_descs *const *action_descs, size_t nr_actions)
Set pipe's actions, actions mask and actions descriptor.
DOCA_EXPERIMENTAL doca_error_t doca_flow_port_cfg_set_actions_mem_size(struct doca_flow_port_cfg *cfg, uint32_t size)
Set max memory size used by actions.
DOCA_STABLE doca_error_t doca_flow_cfg_set_nr_shared_resource(struct doca_flow_cfg *cfg, uint32_t nr_shared_resource, enum doca_flow_shared_resource_type type)
Set number of shared resource.
DOCA_STABLE doca_error_t doca_flow_port_stop(struct doca_flow_port *port)
Stop a doca port.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_cfg_set_monitor(struct doca_flow_pipe_cfg *cfg, const struct doca_flow_monitor *monitor)
Set pipe's monitor.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_add_entry(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 *monitor, const struct doca_flow_fwd *fwd, uint32_t flags, void *usr_ctx, struct doca_flow_pipe_entry **entry)
Add one new entry to a pipe.
DOCA_STABLE doca_error_t doca_flow_pipe_remove_entry(uint16_t pipe_queue, uint32_t flags, struct doca_flow_pipe_entry *entry)
Free one pipe entry.
doca_flow_entry_status
doca flow entry status
Definition: doca_flow.h:160
DOCA_STABLE void doca_flow_destroy(void)
Destroy the doca flow.
DOCA_EXPERIMENTAL doca_error_t doca_flow_port_cfg_set_port_id(struct doca_flow_port_cfg *cfg, uint16_t port_id)
Set the logical port ID.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_set_nr_entries(struct doca_flow_pipe_cfg *cfg, uint32_t nr_entries)
Set pipe's maximum number of flow rules.
DOCA_EXPERIMENTAL doca_error_t doca_flow_cfg_set_default_rss(struct doca_flow_cfg *cfg, const struct doca_flow_resource_rss_cfg *rss)
Set RSS global configuration.
DOCA_EXPERIMENTAL doca_error_t doca_flow_resource_query_pipe_miss(struct doca_flow_pipe *pipe, struct doca_flow_resource_query *query_stats)
Extract information about pipe miss entry.
DOCA_STABLE doca_error_t doca_flow_port_cfg_create(struct doca_flow_port_cfg **cfg)
Create DOCA Flow port configuration struct.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_cfg_set_dir_info(struct doca_flow_pipe_cfg *cfg, enum doca_flow_direction_info dir_info)
Set pipe's Direction info.
doca_flow_l4_meta
doca flow l4 valid type for parser meta
Definition: doca_flow.h:305
DOCA_STABLE doca_error_t doca_flow_port_cfg_destroy(struct doca_flow_port_cfg *cfg)
Destroy DOCA Flow port configuration struct.
DOCA_STABLE doca_error_t doca_flow_cfg_set_pipe_queues(struct doca_flow_cfg *cfg, uint16_t pipe_queues)
Set pipe queues.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_set_domain(struct doca_flow_pipe_cfg *cfg, enum doca_flow_pipe_domain domain)
Set pipe's domain.
DOCA_STABLE doca_error_t doca_flow_cfg_destroy(struct doca_flow_cfg *cfg)
Destroy DOCA Flow configuration struct.
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_RSS_IPV4
Definition: doca_flow.h:764
@ DOCA_FLOW_RSS_IPV6
Definition: doca_flow.h:766
@ DOCA_FLOW_SHARED_RESOURCE_PSP
Definition: doca_flow.h:101
@ DOCA_FLOW_SHARED_RESOURCE_MIRROR
Definition: doca_flow.h:99
@ DOCA_FLOW_ENTRY_OP_ADD
Definition: doca_flow.h:147
@ DOCA_FLOW_DIRECTION_HOST_TO_NETWORK
Definition: doca_flow.h:1095
@ DOCA_FLOW_DIRECTION_NETWORK_TO_HOST
Definition: doca_flow.h:1094
@ DOCA_FLOW_PIPE_CONTROL
Definition: doca_flow.h:223
@ DOCA_FLOW_L3_META_IPV4
Definition: doca_flow.h:296
@ DOCA_FLOW_L3_META_IPV6
Definition: doca_flow.h:298
@ DOCA_FLOW_NO_WAIT
Definition: doca_flow.h:115
@ DOCA_FLOW_CRYPTO_SYNDROME_ICV_FAIL
Definition: doca_flow.h:324
@ DOCA_FLOW_CRYPTO_SYNDROME_BAD_TRAILER
Definition: doca_flow.h:326
@ DOCA_FLOW_RESOURCE_TYPE_NON_SHARED
Definition: doca_flow.h:615
@ DOCA_FLOW_FWD_PORT
Definition: doca_flow.h:744
@ DOCA_FLOW_FWD_PIPE
Definition: doca_flow.h:746
@ DOCA_FLOW_FWD_CHANGEABLE
Definition: doca_flow.h:756
@ DOCA_FLOW_FWD_DROP
Definition: doca_flow.h:748
@ DOCA_FLOW_FWD_RSS
Definition: doca_flow.h:742
@ DOCA_FLOW_ENTRY_STATUS_SUCCESS
Definition: doca_flow.h:163
@ DOCA_FLOW_L4_META_UDP
Definition: doca_flow.h:310
@ DOCA_FLOW_L4_META_ICMP
Definition: doca_flow.h:312
@ DOCA_FLOW_PIPE_DOMAIN_EGRESS
Definition: doca_flow.h:245
@ DOCA_FLOW_PIPE_DOMAIN_SECURE_INGRESS
Definition: doca_flow.h:243
@ DOCA_FLOW_PIPE_DOMAIN_SECURE_EGRESS
Definition: doca_flow.h:247
#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
#define DOCA_LOG_DBG(format,...)
Generates a DEBUG application log message.
Definition: doca_log.h:496
uint32_t doca_be32_t
Definition: doca_types.h:121
std::pair< std::string, std::string > session_key
Definition: psp_gw_config.h:79
static constexpr uint32_t IPV6_ADDR_LEN
Definition: psp_gw_config.h:77
@ PSP_GW_MODE_TUNNEL
Definition: psp_gw_config.h:87
@ PSP_GW_MODE_TRANSPORT
Definition: psp_gw_config.h:88
DOCA_LOG_REGISTER(PSP_GATEWAY)
#define NEXT_HEADER_IPV4
#define IF_SUCCESS(result, expr)
const uint8_t PSP_SAMPLE_ENABLE
static const uint32_t DEFAULT_TIMEOUT_US
static const uint32_t PSP_ICV_SIZE
struct PSP_GatewayFlows::pipe_query __rte_aligned
#define NEXT_HEADER_IPV6
static const uint32_t MAX_ACTIONS_MEM_SIZE
static const int NUM_OF_PSP_SYNDROMES
Definition: psp_gw_flows.h:40
std::string mac_to_string(const rte_ether_addr &mac_addr)
Converts a MAC/ethernet address to a C++ string.
std::string ip_to_string(const struct doca_flow_ip_addr &ip_addr)
Converts a DOCA Flow IP address struct to a C++ string.
doca_flow_pipe_entry * entry
doca flow actions information
Definition: doca_flow.h:684
struct doca_flow_tun tun
Definition: doca_flow.h:705
struct doca_flow_crypto_encap_action crypto_encap
Definition: doca_flow.h:723
struct doca_flow_meta meta
Definition: doca_flow.h:699
struct doca_flow_crypto_action crypto
Definition: doca_flow.h:725
uint8_t action_idx
Definition: doca_flow.h:685
enum doca_flow_crypto_action_type action_type
Definition: doca_flow.h:627
enum doca_flow_crypto_resource_type resource_type
Definition: doca_flow.h:629
enum doca_flow_crypto_encap_action_type action_type
Definition: doca_flow.h:645
enum doca_flow_crypto_encap_net_type net_type
Definition: doca_flow.h:647
uint8_t encap_data[DOCA_FLOW_CRYPTO_HEADER_LEN_MAX]
Definition: doca_flow.h:653
enum doca_flow_crypto_key_type key_type
forwarding configuration
Definition: doca_flow.h:779
struct doca_flow_pipe * next_pipe
Definition: doca_flow.h:800
uint16_t port_id
Definition: doca_flow.h:795
enum doca_flow_fwd_type type
Definition: doca_flow.h:780
enum doca_flow_resource_type rss_type
Definition: doca_flow.h:784
struct doca_flow_resource_rss_cfg rss
Definition: doca_flow.h:787
doca flow packet format
Definition: doca_flow.h:439
struct doca_flow_header_ip4 ip4
Definition: doca_flow.h:449
enum doca_flow_l4_type_ext l4_type_ext
Definition: doca_flow.h:454
struct doca_flow_header_eth eth
Definition: doca_flow.h:440
struct doca_flow_header_udp udp
Definition: doca_flow.h:459
enum doca_flow_l3_type l3_type
Definition: doca_flow.h:446
struct doca_flow_header_icmp icmp
Definition: doca_flow.h:457
struct doca_flow_header_ip6 ip6
Definition: doca_flow.h:451
doca_be32_t dst_ip[4]
doca_be32_t src_ip[4]
struct doca_flow_header_l4_port l4_port
doca_be32_t ipv4_addr
doca_be32_t ipv6_addr[4]
enum doca_flow_l3_type type
doca flow matcher information
Definition: doca_flow.h:491
struct doca_flow_header_format inner
Definition: doca_flow.h:502
struct doca_flow_parser_meta parser_meta
Definition: doca_flow.h:496
struct doca_flow_header_format outer
Definition: doca_flow.h:498
struct doca_flow_tun tun
Definition: doca_flow.h:500
struct doca_flow_meta meta
Definition: doca_flow.h:494
doca_be32_t pkt_meta
Definition: doca_flow.h:359
doca_be32_t u32[DOCA_FLOW_META_SCRATCH_PAD_MAX]
Definition: doca_flow.h:360
doca flow mirror target
Definition: doca_flow.h:929
struct doca_flow_fwd fwd
Definition: doca_flow.h:934
doca monitor action configuration
Definition: doca_flow.h:968
uint32_t shared_mirror_id
Definition: doca_flow.h:997
enum doca_flow_resource_type counter_type
Definition: doca_flow.h:988
uint8_t outer_ip4_checksum_ok
Definition: doca_flow.h:390
enum doca_flow_l3_meta outer_l3_type
Definition: doca_flow.h:382
enum doca_flow_l3_meta inner_l3_type
Definition: doca_flow.h:385
enum doca_flow_l4_meta outer_l4_type
Definition: doca_flow.h:383
doca_be16_t random
Definition: doca_flow.h:376
struct doca_flow_mirror_target * target
Definition: doca_flow.h:944
struct doca_flow_crypto_key_cfg key_cfg
Definition: doca_flow.h:898
flow resource query
Definition: doca_flow.h:1101
struct doca_flow_resource_query::@115::@117 counter
doca flow rss resource configuration
Definition: doca_flow.h:180
doca flow shared resource configuration
Definition: doca_flow.h:953
struct doca_flow_resource_psp_cfg psp_cfg
Definition: doca_flow.h:957
struct doca_flow_resource_mirror_cfg mirror_cfg
Definition: doca_flow.h:958
enum doca_flow_tun_type type
struct doca_flow_header_psp psp
user context struct that will be used in entries process callback
Definition: flow_common.h:78
packet header structure to simplify populating the encap_data array for tunnel encap ipv4 data
rte_psp_base_hdr psp
packet header structure to simplify populating the encap_data array for tunnel encap ipv6 data
rte_psp_base_hdr psp
describes the configuration of the PSP networking service on the local host.
Maintains the state of the host PF.
Definition: psp_gw_flows.h:47
struct doca_flow_ip_addr src_pip
Definition: psp_gw_flows.h:55
rte_ether_addr src_mac
Definition: psp_gw_flows.h:52
doca_dev * dev
Definition: psp_gw_flows.h:48
doca_flow_port * port_obj
Definition: psp_gw_flows.h:50
uint16_t port_id
Definition: psp_gw_flows.h:49
describes a PSP tunnel connection to a single address on a peer.
Definition: psp_gw_flows.h:63
uint64_t pkt_count_egress
Definition: psp_gw_flows.h:79
doca_flow_pipe_entry * encap_encrypt_entry
Definition: psp_gw_flows.h:77
uint32_t crypto_id
Definition: psp_gw_flows.h:72
rte_ether_addr dst_mac
Definition: psp_gw_flows.h:64
doca_flow_pipe_entry * acl_entry
Definition: psp_gw_flows.h:78
uint64_t pkt_count_ingress
Definition: psp_gw_flows.h:80
struct doca_flow_ip_addr src_vip
Definition: psp_gw_flows.h:68
uint32_t spi_ingress
Definition: psp_gw_flows.h:71
uint32_t psp_proto_ver
Definition: psp_gw_flows.h:74
uint32_t spi_egress
Definition: psp_gw_flows.h:70
struct doca_flow_ip_addr dst_pip
Definition: psp_gw_flows.h:66
struct doca_flow_ip_addr dst_vip
Definition: psp_gw_flows.h:67
uint64_t vc
Definition: psp_gw_flows.h:75
packet header structure to simplify populating the encap_data array for transport encap data
rte_psp_base_hdr psp