NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
flow_decrypt.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2023-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 #include <rte_ethdev.h>
26 #include <rte_ether.h>
27 #include <rte_ip.h>
28 
29 #include <doca_flow.h>
30 #include <doca_log.h>
31 #include <doca_bitfield.h>
32 
33 #include "flow_decrypt.h"
34 
35 DOCA_LOG_REGISTER(IPSEC_SECURITY_GW::flow_decrypt);
36 
37 #define DECAP_MAC_TYPE_IDX 12 /* index in decap raw data for inner l3 type */
38 #define DECAP_IDX_SRC_MAC 6 /* index in decap raw data for source mac */
39 #define DECAP_MARKER_HEADER_SIZE 8 /* non-ESP marker header size */
40 #define UDP_DST_PORT_FOR_ESP 4500 /* the udp dest port will be 4500 when next header is ESP */
41 
42 /*
43  * Create ipsec decrypt pipe with ESP header match and changeable shared IPSEC decryption object
44  *
45  * @port [in]: port of the pipe
46  * @expected_entries [in]: expected number of entries in the pipe
47  * @l3_type [in]: DOCA_FLOW_L3_TYPE_IP4 / DOCA_FLOW_L3_TYPE_IP6
48  * @app_cfg [in]: application configuration struct
49  * @pipe_info [out]: pipe info struct
50  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
51  */
52 static doca_error_t create_ipsec_decrypt_pipe(struct doca_flow_port *port,
53  int expected_entries,
54  enum doca_flow_l3_type l3_type,
57 {
58  int nb_actions = 1;
59  struct doca_flow_match match;
61  struct doca_flow_actions actions, *actions_arr[nb_actions];
62  struct doca_flow_fwd fwd;
63  struct doca_flow_fwd fwd_miss;
64  struct doca_flow_pipe_cfg *pipe_cfg;
66 
67  memset(&match, 0, sizeof(match));
68  memset(&monitor, 0, sizeof(monitor));
69  memset(&actions, 0, sizeof(actions));
70  memset(&fwd, 0, sizeof(fwd));
71  memset(&fwd_miss, 0, sizeof(fwd_miss));
72 
73  match.outer.l3_type = l3_type;
74  if (l3_type == DOCA_FLOW_L3_TYPE_IP4)
75  match.outer.ip4.dst_ip = 0xffffffff;
76  else
77  SET_IP6_ADDR(match.outer.ip6.dst_ip, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
78 
79  /* the control pipe coming before will verify the existence of a ESP header */
80  match.tun.type = DOCA_FLOW_TUN_ESP;
81  match.tun.esp_spi = 0xffffffff;
82 
85  if (!app_cfg->sw_antireplay) {
86  actions.crypto.ipsec_sa.sn_en = !app_cfg->sw_antireplay;
87  }
88  actions.crypto.crypto_id = UINT32_MAX;
89  actions.meta.pkt_meta = 0xffffffff;
90  actions_arr[0] = &actions;
91 
92  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
93  if (result != DOCA_SUCCESS) {
94  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
95  return result;
96  }
97 
98  result = doca_flow_pipe_cfg_set_name(pipe_cfg, "DECRYPT_PIPE");
99  if (result != DOCA_SUCCESS) {
100  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
101  goto destroy_pipe_cfg;
102  }
104  if (result != DOCA_SUCCESS) {
105  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg domain: %s", doca_error_get_descr(result));
106  goto destroy_pipe_cfg;
107  }
109  if (result != DOCA_SUCCESS) {
110  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg dir_info: %s", doca_error_get_descr(result));
111  goto destroy_pipe_cfg;
112  }
113  result = doca_flow_pipe_cfg_set_nr_entries(pipe_cfg, expected_entries);
114  if (result != DOCA_SUCCESS) {
115  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg nr_entries: %s", doca_error_get_descr(result));
116  goto destroy_pipe_cfg;
117  }
118  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
119  if (result != DOCA_SUCCESS) {
120  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
121  goto destroy_pipe_cfg;
122  }
123  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, NULL, nb_actions);
124  if (result != DOCA_SUCCESS) {
125  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
126  goto destroy_pipe_cfg;
127  }
128  if (app_cfg->debug_mode) {
131  if (result != DOCA_SUCCESS) {
132  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
133  goto destroy_pipe_cfg;
134  }
135  }
136 
138  fwd.next_pipe = app_cfg->decrypt_pipes.decap_pipe.pipe;
139 
141 
143  if (result != DOCA_SUCCESS) {
144  DOCA_LOG_ERR("Failed to create decrypt pipe: %s", doca_error_get_descr(result));
145  goto destroy_pipe_cfg;
146  }
147 
148  if (app_cfg->debug_mode) {
149  pipe_info->entries_info =
150  (struct security_gateway_entry_info *)calloc(expected_entries,
151  sizeof(struct security_gateway_entry_info));
152  if (pipe_info->entries_info == NULL) {
153  DOCA_LOG_ERR("Failed to allocate entries array");
155  }
156  }
157 
159  doca_flow_pipe_cfg_destroy(pipe_cfg);
160  return result;
161 }
162 
163 /*
164  * Create the DOCA Flow forward struct based on the user configuration
165  *
166  * @app_cfg [in]: application configuration struct
167  * @rss_queues [in]: rss queues array to fill in case of rss forward
168  * @fwd [out]: the created forward struct
169  */
171  uint16_t *rss_queues,
172  struct doca_flow_fwd *fwd)
173 {
174  uint32_t nb_queues = app_cfg->dpdk_config->port_config.nb_queues;
175  uint32_t i;
176 
177  memset(fwd, 0, sizeof(*fwd));
178 
179  if (app_cfg->syndrome_fwd == IPSEC_SECURITY_GW_FWD_SYNDROME_RSS) {
180  /* for software handling the packets will be sent to the application by RSS queues */
181  if (app_cfg->flow_mode == IPSEC_SECURITY_GW_SWITCH) {
183  fwd->next_pipe = app_cfg->switch_pipes.rss_pipe.pipe;
184  } else {
185  for (i = 0; i < nb_queues - 1; i++)
186  rss_queues[i] = i + 1;
187 
192  fwd->rss.nr_queues = nb_queues - 1;
193  }
194  } else {
196  }
197 }
198 
199 /*
200  * Create pipe that match on spi, IP, and bad syndromes, each entry will have a counter
201  *
202  * @app_cfg [in]: application configuration struct
203  * @port [in]: port of the pipe
204  * @expected_entries [in]: expected number of entries in the pipe
205  * @pipe [out]: the created pipe
206  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
207  */
209  struct doca_flow_port *port,
210  int expected_entries,
211  struct doca_flow_pipe **pipe)
212 {
213  int nb_actions = 1;
214  struct doca_flow_fwd fwd;
215  struct doca_flow_monitor monitor;
216  struct doca_flow_match match;
218  struct doca_flow_pipe_cfg *pipe_cfg;
219  union security_gateway_pkt_meta meta = {0};
220  uint16_t rss_queues[app_cfg->dpdk_config->port_config.nb_queues];
221  struct doca_flow_actions actions, *actions_arr[nb_actions];
222  struct doca_flow_actions actions_mask, *actions_mask_arr[nb_actions];
223  union security_gateway_pkt_meta actions_meta = {0};
224 
226 
227  memset(&fwd, 0, sizeof(fwd));
228  memset(&monitor, 0, sizeof(monitor));
229  memset(&match, 0, sizeof(match));
230  memset(&match_mask, 0, sizeof(match_mask));
231  memset(&actions, 0, sizeof(actions));
232  memset(&actions_mask, 0, sizeof(actions_mask));
233 
234  /* ipsec syndrome */
236  match.parser_meta.ipsec_syndrome = 0xff;
237  /* Anti replay syndrome */
239  match.parser_meta.ipsec_ar_syndrome = 0xff;
240  /* rule index */
241  meta.rule_id = -1;
243  match.meta.pkt_meta = 0xffffffff;
244 
246 
247  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
248  if (result != DOCA_SUCCESS) {
249  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
250  return result;
251  }
252 
253  result = doca_flow_pipe_cfg_set_name(pipe_cfg, "bad_syndrome");
254  if (result != DOCA_SUCCESS) {
255  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
256  goto destroy_pipe_cfg;
257  }
259  if (result != DOCA_SUCCESS) {
260  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg domain: %s", doca_error_get_descr(result));
261  goto destroy_pipe_cfg;
262  }
264  if (result != DOCA_SUCCESS) {
265  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg dir_info: %s", doca_error_get_descr(result));
266  goto destroy_pipe_cfg;
267  }
268  result = doca_flow_pipe_cfg_set_nr_entries(pipe_cfg, expected_entries * NUM_OF_SYNDROMES);
269  if (result != DOCA_SUCCESS) {
270  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg nr_entries: %s", doca_error_get_descr(result));
271  goto destroy_pipe_cfg;
272  }
273  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, &match_mask);
274  if (result != DOCA_SUCCESS) {
275  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
276  goto destroy_pipe_cfg;
277  }
279  if (result != DOCA_SUCCESS) {
280  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
281  goto destroy_pipe_cfg;
282  }
283  if (app_cfg->syndrome_fwd == IPSEC_SECURITY_GW_FWD_SYNDROME_RSS) {
284  actions.meta.pkt_meta = 0xffffffff;
285  actions_meta.decrypt_syndrome = -1;
286  actions_meta.antireplay_syndrome = -1;
287  actions_mask.meta.pkt_meta = DOCA_HTOBE32(actions_meta.u32);
288  actions_arr[0] = &actions;
289  actions_mask_arr[0] = &actions_mask;
290  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, actions_mask_arr, NULL, nb_actions);
291  if (result != DOCA_SUCCESS) {
292  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
293  goto destroy_pipe_cfg;
294  }
295  }
296 
298 
299  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, pipe);
300  if (result != DOCA_SUCCESS)
301  DOCA_LOG_ERR("Failed to create decrypt pipe: %s", doca_error_get_descr(result));
302 
304  doca_flow_pipe_cfg_destroy(pipe_cfg);
305  return result;
306 }
307 
308 /*
309  * Add 4 entries for the rule, each entry match the same IP and spi, and different syndrome
310  *
311  * @pipe [in]: pipe to add the entries
312  * @rule [in]: rule of the entries - spi and ip address
313  * @rule_id [in]: rule idx to match on
314  * @decrypt_status [in]: user ctx
315  * @flags [in]: wait for batch / no wait flag for the last entry
316  * @queue_id [in]: queue id
317  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
318  */
319 static doca_error_t add_bad_syndrome_pipe_entry(struct doca_flow_pipe *pipe,
320  struct decrypt_rule *rule,
321  uint32_t rule_id,
322  struct entries_status *decrypt_status,
323  enum doca_flow_flags_type flags,
324  int queue_id)
325 {
326  struct doca_flow_match match;
327  struct doca_flow_actions actions;
329  union security_gateway_pkt_meta meta = {0};
330  union security_gateway_pkt_meta actions_meta = {0};
331 
332  memset(&match, 0, sizeof(match));
333  memset(&actions, 0, sizeof(actions));
334 
335  meta.rule_id = rule_id;
336  match.meta.pkt_meta = DOCA_HTOBE32(meta.u32);
337  match.parser_meta.ipsec_syndrome = 1;
338  match.parser_meta.ipsec_ar_syndrome = 0;
339 
340  actions_meta.decrypt_syndrome = 1;
341  actions_meta.antireplay_syndrome = 0;
342  actions.meta.pkt_meta = DOCA_HTOBE32(actions_meta.u32);
343 
344  /* match on ipsec syndrome 1 */
346  pipe,
347  &match,
348  &actions,
349  NULL,
350  NULL,
352  decrypt_status,
353  &rule->entries[0].entry);
354  if (result != DOCA_SUCCESS) {
355  DOCA_LOG_ERR("Failed to add bad syndrome pipe entry: %s", doca_error_get_descr(result));
356  return result;
357  }
358 
359  match.parser_meta.ipsec_syndrome = 2;
360 
361  actions_meta.decrypt_syndrome = 2;
362  actions.meta.pkt_meta = DOCA_HTOBE32(actions_meta.u32);
363 
364  /* match on ipsec syndrome 2 */
366  pipe,
367  &match,
368  &actions,
369  NULL,
370  NULL,
372  decrypt_status,
373  &rule->entries[1].entry);
374  if (result != DOCA_SUCCESS) {
375  DOCA_LOG_ERR("Failed to add bad syndrome pipe entry: %s", doca_error_get_descr(result));
376  return result;
377  }
378 
379  match.parser_meta.ipsec_syndrome = 0;
380  match.parser_meta.ipsec_ar_syndrome = 1;
381 
382  actions_meta.decrypt_syndrome = 0;
383  actions_meta.antireplay_syndrome = 1;
384  actions.meta.pkt_meta = DOCA_HTOBE32(actions_meta.u32);
385 
386  /* match on ASO syndrome 1 */
388  pipe,
389  &match,
390  &actions,
391  NULL,
392  NULL,
394  decrypt_status,
395  &rule->entries[2].entry);
396  if (result != DOCA_SUCCESS) {
397  DOCA_LOG_ERR("Failed to add bad syndrome pipe entry: %s", doca_error_get_descr(result));
398  return result;
399  }
400 
401  match.parser_meta.ipsec_ar_syndrome = 2;
402  actions_meta.antireplay_syndrome = 2;
403  actions.meta.pkt_meta = DOCA_HTOBE32(actions_meta.u32);
404 
405  /* match on ASO syndrome 2 */
407  pipe,
408  &match,
409  &actions,
410  NULL,
411  NULL,
412  flags,
413  decrypt_status,
414  &rule->entries[3].entry);
415  if (result != DOCA_SUCCESS) {
416  DOCA_LOG_ERR("Failed to add bad syndrome pipe entry: %s", doca_error_get_descr(result));
417  return result;
418  }
419 
420  return DOCA_SUCCESS;
421 }
422 
423 /*
424  * Add vxlan decap pipe entry
425  *
426  * @port [in]: port of the pipe
427  * @pipe [in]: pipe to add entry
428  * @app_cfg [in]: application configuration struct
429  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
430  */
431 static doca_error_t add_vxlan_decap_pipe_entry(struct doca_flow_port *port,
432  struct security_gateway_pipe_info *pipe,
434 {
435  int num_of_entries = 1;
436  struct doca_flow_match match;
437  struct doca_flow_actions actions;
438  struct doca_flow_pipe_entry **entry = NULL;
440 
441  memset(&match, 0, sizeof(match));
442  memset(&actions, 0, sizeof(actions));
443  memset(&app_cfg->secured_status[0], 0, sizeof(app_cfg->secured_status[0]));
444 
445  if (app_cfg->debug_mode) {
446  pipe->entries_info =
447  (struct security_gateway_entry_info *)calloc(1, sizeof(struct security_gateway_entry_info));
448  if (pipe->entries_info == NULL) {
449  DOCA_LOG_ERR("Failed to allocate entries array");
450  return DOCA_ERROR_NO_MEMORY;
451  }
452  snprintf(pipe->entries_info[pipe->nb_entries].name, MAX_NAME_LEN, "vxlan_decap");
453  entry = &pipe->entries_info[pipe->nb_entries++].entry;
454  }
455 
456  actions.action_idx = 0;
457 
459  pipe->pipe,
460  &match,
461  &actions,
462  NULL,
463  NULL,
465  &app_cfg->secured_status[0],
466  entry);
467  if (result != DOCA_SUCCESS) {
468  DOCA_LOG_ERR("Failed to add ipv4 entry: %s", doca_error_get_descr(result));
469  return result;
470  }
471 
472  result = doca_flow_entries_process(port, 0, DEFAULT_TIMEOUT_US, num_of_entries);
473  if (result != DOCA_SUCCESS)
474  return result;
475  if (app_cfg->secured_status[0].nb_processed != num_of_entries || app_cfg->secured_status[0].failure)
476  return DOCA_ERROR_BAD_STATE;
477 
478  return DOCA_SUCCESS;
479 }
480 
481 /*
482  * Create pipe that match vxlan traffic with specific tunnel ID and decap action
483  *
484  * @port [in]: port of the pipe
485  * @app_cfg [in]: application configuration struct
486  * @next_pipe [in]: next pipe to send the packets
487  * @pipe [in]: created pipe pointer
488  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
489  */
490 static doca_error_t create_vxlan_decap_pipe(struct doca_flow_port *port,
492  struct doca_flow_pipe *next_pipe,
493  struct security_gateway_pipe_info *pipe)
494 {
495  int nb_actions = 1;
496  struct doca_flow_match match;
497  struct doca_flow_monitor monitor;
498  struct doca_flow_actions actions, *actions_arr[nb_actions];
499  struct doca_flow_fwd fwd;
500  struct doca_flow_pipe_cfg *pipe_cfg;
502 
503  memset(&match, 0, sizeof(match));
504  memset(&monitor, 0, sizeof(monitor));
505  memset(&actions, 0, sizeof(actions));
506  memset(&fwd, 0, sizeof(fwd));
507 
508  match.tun.type = DOCA_FLOW_TUN_VXLAN;
510  match.tun.vxlan_tun_id = DOCA_HTOBE32(app_cfg->vni);
511 
513  actions.decap_cfg.is_l2 = true;
514  actions_arr[0] = &actions;
515 
516  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
517  if (result != DOCA_SUCCESS) {
518  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
519  return result;
520  }
521 
522  result = doca_flow_pipe_cfg_set_name(pipe_cfg, "VXLAN_DECAP_PIPE");
523  if (result != DOCA_SUCCESS) {
524  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
525  goto destroy_pipe_cfg;
526  }
528  if (result != DOCA_SUCCESS) {
529  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg type: %s", doca_error_get_descr(result));
530  goto destroy_pipe_cfg;
531  }
532  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
533  if (result != DOCA_SUCCESS) {
534  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
535  goto destroy_pipe_cfg;
536  }
537  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, NULL, nb_actions);
538  if (result != DOCA_SUCCESS) {
539  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
540  goto destroy_pipe_cfg;
541  }
542 
543  if (app_cfg->debug_mode) {
546  if (result != DOCA_SUCCESS) {
547  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
548  goto destroy_pipe_cfg;
549  }
550  }
551 
553  fwd.next_pipe = next_pipe;
554 
555  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, &pipe->pipe);
556  if (result != DOCA_SUCCESS) {
557  DOCA_LOG_ERR("Failed to create vxlan decap pipe: %s", doca_error_get_descr(result));
558  goto destroy_pipe_cfg;
559  }
560  doca_flow_pipe_cfg_destroy(pipe_cfg);
561  return add_vxlan_decap_pipe_entry(port, pipe, app_cfg);
562 
564  doca_flow_pipe_cfg_destroy(pipe_cfg);
565  return result;
566 }
567 
568 /*
569  * Create pipe for decap ESP header and match on decrypt syndrome.
570  * If syndrome is not 0 - fwd the packet to bad syndrome pipe.
571  *
572  * @port [in]: port of the pipe
573  * @app_cfg [in]: application configuration struct
574  * @fwd [in]: pointer to forward struct
575  * @pipe_info [out]: pipe info struct
576  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
577  */
578 static doca_error_t create_ipsec_decap_pipe(struct doca_flow_port *port,
580  struct doca_flow_fwd *fwd,
582 {
583  int nb_actions = 1;
584  struct doca_flow_match match;
586  struct doca_flow_monitor monitor;
587  struct doca_flow_actions actions, *actions_arr[nb_actions];
588  struct doca_flow_pipe_cfg *pipe_cfg;
589  struct doca_flow_fwd fwd_miss;
590  struct doca_flow_fwd *fwd_miss_ptr = NULL;
591  uint32_t nb_entries = 1;
593  union security_gateway_pkt_meta meta = {0};
594 
595  memset(&match, 0, sizeof(match));
596  memset(&monitor, 0, sizeof(monitor));
597  memset(&match_mask, 0, sizeof(match_mask));
598  memset(&actions, 0, sizeof(actions));
599 
600  /* ipsec syndrome */
602  match.parser_meta.ipsec_syndrome = 0xff;
603 
604  /* anti-replay syndrome */
606  match.parser_meta.ipsec_ar_syndrome = 0xff;
607 
608  if (app_cfg->mode == IPSEC_SECURITY_GW_TUNNEL)
609  meta.inner_ipv6 = 1;
610 
612  match.meta.pkt_meta = 0xffffffff;
613 
616  actions.has_crypto_encap = true;
617 
620  if (app_cfg->mode == IPSEC_SECURITY_GW_TUNNEL) {
622  uint8_t reformat_decap_data[14] = {
623  0xff,
624  0xff,
625  0xff,
626  0xff,
627  0xff,
628  0xff, /* mac_dst */
629  0xff,
630  0xff,
631  0xff,
632  0xff,
633  0xff,
634  0xff, /* mac_src */
635  0xff,
636  0xff /* mac_type */
637  };
638 
639  memcpy(actions.crypto_encap.encap_data, reformat_decap_data, sizeof(reformat_decap_data));
640  actions.crypto_encap.data_size = sizeof(reformat_decap_data);
641  nb_entries *= 2; /* double for tunnel mode, for inner ip version */
642  } else if (app_cfg->mode == IPSEC_SECURITY_GW_TRANSPORT)
644  else
646 
647  actions_arr[0] = &actions;
648 
649  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
650  if (result != DOCA_SUCCESS) {
651  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
652  return result;
653  }
654 
655  result = doca_flow_pipe_cfg_set_name(pipe_cfg, "DECAP_PIPE");
656  if (result != DOCA_SUCCESS) {
657  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
658  goto destroy_pipe_cfg;
659  }
660  result = doca_flow_pipe_cfg_set_is_root(pipe_cfg, false);
661  if (result != DOCA_SUCCESS) {
662  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg is_root: %s", doca_error_get_descr(result));
663  goto destroy_pipe_cfg;
664  }
666  if (result != DOCA_SUCCESS) {
667  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg dir_info: %s", doca_error_get_descr(result));
668  goto destroy_pipe_cfg;
669  }
671  if (result != DOCA_SUCCESS) {
672  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg nr_entries: %s", doca_error_get_descr(result));
673  goto destroy_pipe_cfg;
674  }
675  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, &match_mask);
676  if (result != DOCA_SUCCESS) {
677  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
678  goto destroy_pipe_cfg;
679  }
680  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, NULL, nb_actions);
681  if (result != DOCA_SUCCESS) {
682  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
683  goto destroy_pipe_cfg;
684  }
685 
686  if (app_cfg->debug_mode) {
688  fwd_miss.next_pipe = app_cfg->decrypt_pipes.bad_syndrome_pipe.pipe;
689  fwd_miss_ptr = &fwd_miss;
690  pipe_info->entries_info =
691  (struct security_gateway_entry_info *)calloc(nb_entries,
692  sizeof(struct security_gateway_entry_info));
693  if (pipe_info->entries_info == NULL) {
694  DOCA_LOG_ERR("Failed to allocate entries array");
696  goto destroy_pipe_cfg;
697  }
700  if (result != DOCA_SUCCESS) {
701  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
702  goto destroy_pipe_cfg;
703  }
704  }
705 
706  result = doca_flow_pipe_create(pipe_cfg, fwd, fwd_miss_ptr, &pipe_info->pipe);
707  if (result != DOCA_SUCCESS)
708  DOCA_LOG_ERR("Failed to create syndrome pipe: %s", doca_error_get_descr(result));
709 
711  doca_flow_pipe_cfg_destroy(pipe_cfg);
712  return result;
713 }
714 
715 /*
716  * Create ingress pipe to remove non-ESP marker and forward to IPv4 or IPv6 pipes
717  *
718  * @port [in]: port of the pipe
719  * @app_cfg [in]: application configuration struct
720  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
721  */
722 static doca_error_t create_marker_decap_pipe(struct doca_flow_port *port, struct ipsec_security_gw_config *app_cfg)
723 {
724  int nb_actions = 1;
725  int num_of_entries = 2;
726  struct doca_flow_match match;
728  struct doca_flow_monitor monitor;
729  struct doca_flow_actions actions, actions_arr[nb_actions];
730  struct doca_flow_actions *actions_list[] = {&actions_arr[0]};
731  struct doca_flow_fwd fwd;
732  struct doca_flow_pipe_cfg *pipe_cfg;
733  struct security_gateway_pipe_info *pipe_info = &app_cfg->decrypt_pipes.marker_remove_pipe;
734  struct doca_flow_pipe_entry *entry = NULL;
736 
739  return DOCA_SUCCESS;
740  }
741 
742  memset(&match, 0, sizeof(match));
743  memset(&match_mask, 0, sizeof(match_mask));
744  memset(&monitor, 0, sizeof(monitor));
745  memset(&actions, 0, sizeof(actions));
746  memset(&fwd, 0, sizeof(fwd));
747  memset(&app_cfg->secured_status[0], 0, sizeof(app_cfg->secured_status[0]));
748 
749  match.parser_meta.outer_l3_type = (enum doca_flow_l3_meta)UINT32_MAX;
751 
752  actions.has_crypto_encap = true;
755 
756  actions_arr[0] = actions;
758 
759  strcpy(pipe_info->name, "MARKER_DECAP_PIPE");
760  pipe_info->nb_entries = 0;
761 
762  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
763  if (result != DOCA_SUCCESS) {
764  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
765  return result;
766  }
767  result = doca_flow_pipe_cfg_set_name(pipe_cfg, pipe_info->name);
768  if (result != DOCA_SUCCESS) {
769  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
770  goto destroy_pipe_cfg;
771  }
773  if (result != DOCA_SUCCESS) {
774  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg type: %s", doca_error_get_descr(result));
775  goto destroy_pipe_cfg;
776  }
778  if (result != DOCA_SUCCESS) {
779  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg domain: %s", doca_error_get_descr(result));
780  goto destroy_pipe_cfg;
781  }
783  if (result != DOCA_SUCCESS) {
784  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg dir_info: %s", doca_error_get_descr(result));
785  goto destroy_pipe_cfg;
786  }
788  if (result != DOCA_SUCCESS) {
789  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg nr_entries: %s", doca_error_get_descr(result));
790  goto destroy_pipe_cfg;
791  }
792  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, &match_mask);
793  if (result != DOCA_SUCCESS) {
794  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
795  goto destroy_pipe_cfg;
796  }
797  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_list, NULL, NULL, 1);
798  if (result != DOCA_SUCCESS) {
799  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
800  goto destroy_pipe_cfg;
801  }
802 
803  if (app_cfg->debug_mode) {
806  if (result != DOCA_SUCCESS) {
807  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
808  goto destroy_pipe_cfg;
809  }
810  }
811 
813  fwd.next_pipe = NULL;
814 
816  if (result != DOCA_SUCCESS) {
817  DOCA_LOG_ERR("Failed to create non-ESP marker decap ingress pipe: %s", doca_error_get_descr(result));
818  goto destroy_pipe_cfg;
819  }
820 
821  if (app_cfg->debug_mode) {
822  pipe_info->entries_info =
823  (struct security_gateway_entry_info *)calloc(2, sizeof(struct security_gateway_entry_info));
824 
825  if (pipe_info->entries_info == NULL) {
826  DOCA_LOG_ERR("Failed to allocate entries array");
828  goto destroy_pipe_cfg;
829  }
830  }
831 
833  fwd.next_pipe = app_cfg->decrypt_pipes.decrypt_ipv4_pipe.pipe;
835  pipe_info->pipe,
836  &match,
837  NULL,
838  NULL,
839  &fwd,
841  &app_cfg->secured_status[0],
842  &entry);
843  if (result != DOCA_SUCCESS) {
844  DOCA_LOG_ERR("Failed to add non-ESP marker decap ingress IPv4 entry: %s", doca_error_get_descr(result));
845  goto destroy_pipe_cfg;
846  }
847  if (result == DOCA_SUCCESS && pipe_info->entries_info != NULL) {
848  snprintf(pipe_info->entries_info[pipe_info->nb_entries].name, MAX_NAME_LEN, "marker_decap_ipv4");
849  pipe_info->entries_info[pipe_info->nb_entries++].entry = entry;
850  }
851 
853  fwd.next_pipe = app_cfg->decrypt_pipes.decrypt_ipv6_pipe.pipe;
855  pipe_info->pipe,
856  &match,
857  NULL,
858  NULL,
859  &fwd,
861  &app_cfg->secured_status[0],
862  &entry);
863  if (result != DOCA_SUCCESS) {
864  DOCA_LOG_ERR("Failed to add non-ESP marker decap ingress IPv6 entry: %s", doca_error_get_descr(result));
865  goto destroy_pipe_cfg;
866  }
867  if (result == DOCA_SUCCESS && pipe_info->entries_info != NULL) {
868  snprintf(pipe_info->entries_info[pipe_info->nb_entries].name, MAX_NAME_LEN, "marker_decap_ipv6");
869  pipe_info->entries_info[pipe_info->nb_entries++].entry = entry;
870  }
871 
872  result = doca_flow_entries_process(port, 0, DEFAULT_TIMEOUT_US, num_of_entries);
873  if (result != DOCA_SUCCESS)
874  goto destroy_pipe_cfg;
875 
876  if (app_cfg->secured_status[0].nb_processed != num_of_entries || app_cfg->secured_status[0].failure)
878 
880  doca_flow_pipe_cfg_destroy(pipe_cfg);
881  return result;
882 }
883 
884 /*
885  * Update the crypto config for decrypt tunnel mode
886  *
887  * @crypto_cfg [in]: shared object config
888  * @eth_header [in]: contains the src mac address
889  * @inner_l3_type [in]: DOCA_FLOW_L3_TYPE_IP4 / DOCA_FLOW_L3_TYPE_IP6
890  */
891 static void create_tunnel_decap_tunnel(struct doca_flow_header_eth *eth_header,
892  enum doca_flow_l3_type inner_l3_type,
893  uint8_t *reformat_data,
894  uint16_t *reformat_data_sz)
895 {
896  uint8_t reformat_decap_data[14] = {
897  0xaa,
898  0xbb,
899  0xcc,
900  0xdd,
901  0xee,
902  0xff, /* mac_dst */
903  0x00,
904  0x00,
905  0x00,
906  0x00,
907  0x00,
908  0x00, /* mac_src */
909  0x00,
910  0x00 /* mac_type */
911  };
912 
913  reformat_decap_data[DECAP_IDX_SRC_MAC] = eth_header->src_mac[0];
914  reformat_decap_data[DECAP_IDX_SRC_MAC + 1] = eth_header->src_mac[1];
915  reformat_decap_data[DECAP_IDX_SRC_MAC + 2] = eth_header->src_mac[2];
916  reformat_decap_data[DECAP_IDX_SRC_MAC + 3] = eth_header->src_mac[3];
917  reformat_decap_data[DECAP_IDX_SRC_MAC + 4] = eth_header->src_mac[4];
918  reformat_decap_data[DECAP_IDX_SRC_MAC + 5] = eth_header->src_mac[5];
919 
920  if (inner_l3_type == DOCA_FLOW_L3_TYPE_IP4) {
921  reformat_decap_data[DECAP_MAC_TYPE_IDX] = 0x08;
922  reformat_decap_data[DECAP_MAC_TYPE_IDX + 1] = 0x00;
923  } else {
924  reformat_decap_data[DECAP_MAC_TYPE_IDX] = 0x86;
925  reformat_decap_data[DECAP_MAC_TYPE_IDX + 1] = 0xdd;
926  }
927 
928  memcpy(reformat_data, reformat_decap_data, sizeof(reformat_decap_data));
929  *reformat_data_sz = sizeof(reformat_decap_data);
930 }
931 
932 /*
933  * Add ipv4 entry to the decap pipe (if tunnel mode add ipv6 entry) with match on inner ip
934  *
935  * @app_cfg [in]: application configuration struct
936  * @port [in]: port of the pipe
937  * @eth_header [in]: contains the src mac address
938  * @pipe [in]: pipe to add entries to
939  *
940  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
941  */
943  struct doca_flow_port *port,
944  struct doca_flow_header_eth *eth_header,
945  struct security_gateway_pipe_info *pipe)
946 {
947  union security_gateway_pkt_meta meta = {0};
948  struct doca_flow_match match;
949  struct doca_flow_actions actions;
950  struct doca_flow_pipe_entry **entry = NULL;
952 
953  memset(&match, 0, sizeof(match));
954  memset(&actions, 0, sizeof(actions));
955  memset(&app_cfg->secured_status[0], 0, sizeof(app_cfg->secured_status[0]));
956 
957  meta.inner_ipv6 = 0;
958  match.meta.pkt_meta = DOCA_HTOBE32(meta.u32);
959  if (app_cfg->mode == IPSEC_SECURITY_GW_TUNNEL)
960  create_tunnel_decap_tunnel(eth_header,
964 
965  if (app_cfg->debug_mode) {
966  snprintf(pipe->entries_info[pipe->nb_entries].name, MAX_NAME_LEN, "decap_inner_ipv4");
967  entry = &pipe->entries_info[pipe->nb_entries++].entry;
968  }
970  pipe->pipe,
971  &match,
972  &actions,
973  NULL,
974  NULL,
976  &app_cfg->secured_status[0],
977  entry);
978  if (result != DOCA_SUCCESS) {
979  DOCA_LOG_ERR("Failed to add pipe entry: %s", doca_error_get_descr(result));
980  return result;
981  }
982  app_cfg->secured_status[0].entries_in_queue += 1;
983 
984  if (app_cfg->mode == IPSEC_SECURITY_GW_TUNNEL) {
985  meta.inner_ipv6 = 1;
986  match.meta.pkt_meta = DOCA_HTOBE32(meta.u32);
987  create_tunnel_decap_tunnel(eth_header,
991  if (app_cfg->debug_mode) {
992  snprintf(pipe->entries_info[pipe->nb_entries].name, MAX_NAME_LEN, "decap_inner_ipv6");
993  entry = &pipe->entries_info[pipe->nb_entries++].entry;
994  }
996  pipe->pipe,
997  &match,
998  &actions,
999  NULL,
1000  NULL,
1002  &app_cfg->secured_status[0],
1003  entry);
1004  if (result != DOCA_SUCCESS) {
1005  DOCA_LOG_ERR("Failed to add pipe entry: %s", doca_error_get_descr(result));
1006  return result;
1007  }
1008  app_cfg->secured_status[0].entries_in_queue += 1;
1009  }
1010 
1011  do {
1012  result = process_entries(port, &app_cfg->secured_status[0], DEFAULT_TIMEOUT_US, 0);
1013  if (result != DOCA_SUCCESS)
1014  return result;
1015  } while (app_cfg->secured_status[0].entries_in_queue > 0);
1016  return DOCA_SUCCESS;
1017 }
1018 
1019 /*
1020  * Create control pipe for secured port
1021  *
1022  * @port [in]: port of the pipe
1023  * @is_root [in]: true in vnf mode
1024  * @debug_mode [in]: true if running in debug mode
1025  * @pipe_info [out]: pipe info struct
1026  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1027  */
1028 static doca_error_t create_control_pipe(struct doca_flow_port *port,
1029  bool is_root,
1030  bool debug_mode,
1032 {
1033  struct doca_flow_pipe_cfg *pipe_cfg;
1035 
1036  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
1037  if (result != DOCA_SUCCESS) {
1038  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
1039  return result;
1040  }
1041 
1042  result = doca_flow_pipe_cfg_set_name(pipe_cfg, "CONTROL_PIPE");
1043  if (result != DOCA_SUCCESS) {
1044  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
1045  goto destroy_pipe_cfg;
1046  }
1047  result = doca_flow_pipe_cfg_set_is_root(pipe_cfg, is_root);
1048  if (result != DOCA_SUCCESS) {
1049  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg is_root: %s", doca_error_get_descr(result));
1050  goto destroy_pipe_cfg;
1051  }
1053  if (result != DOCA_SUCCESS) {
1054  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg type: %s", doca_error_get_descr(result));
1055  goto destroy_pipe_cfg;
1056  }
1058  if (result != DOCA_SUCCESS) {
1059  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg domain: %s", doca_error_get_descr(result));
1060  goto destroy_pipe_cfg;
1061  }
1063  if (result != DOCA_SUCCESS) {
1064  DOCA_LOG_ERR("Failed to create control pipe: %s", doca_error_get_descr(result));
1065  goto destroy_pipe_cfg;
1066  }
1067 
1068  if (debug_mode) {
1069  pipe_info->entries_info =
1070  (struct security_gateway_entry_info *)calloc(2, sizeof(struct security_gateway_entry_info));
1071  if (pipe_info->entries_info == NULL) {
1072  DOCA_LOG_ERR("Failed to allocate entries array");
1074  }
1075  }
1076 
1078  doca_flow_pipe_cfg_destroy(pipe_cfg);
1079  return result;
1080 }
1081 
1082 /*
1083  * Add control pipe entries - one entry that forwards IPv4 traffic to decrypt IPv4 pipe,
1084  * and one entry that forwards IPv6 traffic to decrypt IPv6 pipe
1085  *
1086  * @control_pipe [in]: control pipe pointer
1087  * @app_cfg [in]: application configuration struct
1088  * @is_root [in]: true in vnf mode
1089  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1090  */
1093  bool is_root)
1094 {
1095  struct doca_flow_pipe_entry **entry = NULL;
1096  struct doca_flow_match match;
1097  struct doca_flow_monitor monitor;
1098  struct doca_flow_monitor *monitor_ptr = NULL;
1099  struct doca_flow_fwd fwd;
1101  struct doca_flow_header_format *ip_esp_header = app_cfg->vxlan_encap ? &(match.inner) : &(match.outer);
1102  enum doca_flow_l3_meta *meta_l3_type = app_cfg->vxlan_encap ? &(match.parser_meta.inner_l3_type) :
1103  &(match.parser_meta.outer_l3_type);
1104  enum doca_flow_l4_meta *meta_l4_type = app_cfg->vxlan_encap ? &(match.parser_meta.inner_l4_type) :
1105  &(match.parser_meta.outer_l4_type);
1106 
1107  memset(&match, 0, sizeof(match));
1108  memset(&monitor, 0, sizeof(monitor));
1109  memset(&fwd, 0, sizeof(fwd));
1110 
1111  if (app_cfg->debug_mode && !is_root) {
1113  monitor_ptr = &monitor;
1114  }
1115 
1116  if (app_cfg->marker_encap && app_cfg->vxlan_encap) {
1117  DOCA_LOG_ERR("Non-ESP marker is not supported over VXLAN encapsulation");
1118  return DOCA_ERROR_NOT_SUPPORTED;
1119  }
1120 
1121  if (!app_cfg->vxlan_encap) {
1123  fwd.next_pipe = app_cfg->marker_encap ? app_cfg->decrypt_pipes.marker_remove_pipe.pipe :
1124  app_cfg->decrypt_pipes.decrypt_ipv4_pipe.pipe;
1125  } else {
1127  fwd.next_pipe = app_cfg->decrypt_pipes.vxlan_decap_ipv4_pipe.pipe;
1128  }
1129 
1131  if (is_root) {
1132  ip_esp_header->eth.type = rte_cpu_to_be_16(DOCA_FLOW_ETHER_TYPE_IPV4);
1133  ip_esp_header->l3_type = DOCA_FLOW_L3_TYPE_IP4;
1134  ip_esp_header->ip4.next_proto = IPPROTO_ESP;
1135  } else {
1136  *meta_l3_type = DOCA_FLOW_L3_META_IPV4;
1137  *meta_l4_type = DOCA_FLOW_L4_META_ESP;
1138  }
1139  } else {
1140  if (is_root) {
1141  ip_esp_header->eth.type = rte_cpu_to_be_16(DOCA_FLOW_ETHER_TYPE_IPV4);
1142  ip_esp_header->l3_type = DOCA_FLOW_L3_TYPE_IP4;
1143  ip_esp_header->ip4.next_proto = IPPROTO_UDP;
1144  } else {
1145  *meta_l3_type = DOCA_FLOW_L3_META_IPV4;
1146  *meta_l4_type = DOCA_FLOW_L4_META_UDP;
1147  }
1148  ip_esp_header->l4_type_ext = DOCA_FLOW_L4_TYPE_EXT_UDP;
1149  ip_esp_header->udp.l4_port.dst_port = rte_cpu_to_be_16(UDP_DST_PORT_FOR_ESP);
1150  }
1151 
1152  if (app_cfg->debug_mode) {
1153  snprintf(control_pipe->entries_info[control_pipe->nb_entries].name, MAX_NAME_LEN, "ipv4");
1154  entry = &control_pipe->entries_info[control_pipe->nb_entries++].entry;
1155  }
1157  0,
1158  control_pipe->pipe,
1159  &match,
1160  NULL,
1161  NULL,
1162  NULL,
1163  NULL,
1164  NULL,
1165  monitor_ptr,
1166  &fwd,
1167  NULL,
1168  entry);
1169  if (result != DOCA_SUCCESS) {
1170  DOCA_LOG_ERR("Failed to add IPv4 control entry: %s", doca_error_get_descr(result));
1171  return result;
1172  }
1173 
1174  memset(&match, 0, sizeof(match));
1175 
1176  if (!app_cfg->vxlan_encap) {
1178  fwd.next_pipe = app_cfg->marker_encap ? app_cfg->decrypt_pipes.marker_remove_pipe.pipe :
1179  app_cfg->decrypt_pipes.decrypt_ipv6_pipe.pipe;
1180  } else {
1182  fwd.next_pipe = app_cfg->decrypt_pipes.vxlan_decap_ipv6_pipe.pipe;
1183  }
1184 
1186  if (is_root) {
1187  ip_esp_header->eth.type = rte_cpu_to_be_16(DOCA_FLOW_ETHER_TYPE_IPV6);
1188  ip_esp_header->l3_type = DOCA_FLOW_L3_TYPE_IP6;
1189  ip_esp_header->ip6.next_proto = IPPROTO_ESP;
1190  } else {
1191  *meta_l3_type = DOCA_FLOW_L3_META_IPV6;
1192  *meta_l4_type = DOCA_FLOW_L4_META_ESP;
1193  }
1194  } else {
1195  if (is_root) {
1196  ip_esp_header->eth.type = rte_cpu_to_be_16(DOCA_FLOW_ETHER_TYPE_IPV6);
1197  ip_esp_header->l3_type = DOCA_FLOW_L3_TYPE_IP6;
1198  ip_esp_header->ip6.next_proto = IPPROTO_UDP;
1199  } else {
1200  *meta_l3_type = DOCA_FLOW_L3_META_IPV6;
1201  *meta_l4_type = DOCA_FLOW_L4_META_UDP;
1202  }
1203  ip_esp_header->l4_type_ext = DOCA_FLOW_L4_TYPE_EXT_UDP;
1204  ip_esp_header->udp.l4_port.dst_port = rte_cpu_to_be_16(UDP_DST_PORT_FOR_ESP);
1205  }
1206 
1207  if (app_cfg->debug_mode) {
1208  snprintf(control_pipe->entries_info[control_pipe->nb_entries].name, MAX_NAME_LEN, "ipv6");
1209  entry = &control_pipe->entries_info[control_pipe->nb_entries++].entry;
1210  }
1212  0,
1213  control_pipe->pipe,
1214  &match,
1215  NULL,
1216  NULL,
1217  NULL,
1218  NULL,
1219  NULL,
1220  monitor_ptr,
1221  &fwd,
1222  NULL,
1223  entry);
1224  if (result != DOCA_SUCCESS) {
1225  DOCA_LOG_ERR("Failed to add IPv6 control entry: %s", doca_error_get_descr(result));
1226  return result;
1227  }
1228 
1229  return DOCA_SUCCESS;
1230 }
1231 
1232 /*
1233  * Config and bind shared IPSEC object for decryption
1234  *
1235  * @app_sa_attrs [in]: SA attributes
1236  * @app_cfg [in]: application configuration struct
1237  * @ipsec_id [in]: shared object ID
1238  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1239  */
1242  uint32_t ipsec_id)
1243 {
1246 
1247  memset(&cfg, 0, sizeof(cfg));
1248 
1249  cfg.ipsec_sa_cfg.icv_len = app_cfg->icv_length;
1250  cfg.ipsec_sa_cfg.salt = app_sa_attrs->salt;
1251  cfg.ipsec_sa_cfg.implicit_iv = app_sa_attrs->iv;
1252  cfg.ipsec_sa_cfg.key_cfg.key_type = app_sa_attrs->key_type;
1253  cfg.ipsec_sa_cfg.key_cfg.key = (void *)&app_sa_attrs->enc_key_data;
1254  cfg.ipsec_sa_cfg.sn_initial = app_cfg->sn_initial;
1255  cfg.ipsec_sa_cfg.esn_en = app_sa_attrs->esn_en;
1256  if (!app_cfg->sw_antireplay) {
1257  cfg.ipsec_sa_cfg.sn_offload_type = DOCA_FLOW_CRYPTO_SN_OFFLOAD_AR;
1258  cfg.ipsec_sa_cfg.win_size = DOCA_FLOW_CRYPTO_REPLAY_WIN_SIZE_128;
1259  cfg.ipsec_sa_cfg.lifetime_threshold = app_sa_attrs->lifetime_threshold;
1260  }
1261  /* config ipsec object */
1263  if (result != DOCA_SUCCESS) {
1264  DOCA_LOG_ERR("Failed to cfg shared ipsec object: %s", doca_error_get_descr(result));
1265  return result;
1266  }
1267 
1268  return DOCA_SUCCESS;
1269 }
1270 
1272  int rule_id,
1273  struct doca_flow_port *port,
1275 
1276 {
1277  struct doca_flow_match match;
1278  struct doca_flow_actions actions;
1279  struct doca_flow_pipe_entry **entry = NULL;
1280  struct security_gateway_pipe_info *decrypt_pipe;
1281  uint32_t flags;
1283  union security_gateway_pkt_meta meta = {0};
1284 
1285  memset(&app_cfg->secured_status[0], 0, sizeof(app_cfg->secured_status[0]));
1286  memset(&match, 0, sizeof(match));
1287  memset(&actions, 0, sizeof(actions));
1288 
1289  /* create ipsec shared objects */
1291  if (result != DOCA_SUCCESS)
1292  return result;
1293 
1294  /* build rule match with specific destination IP and ESP SPI */
1295  match.tun.esp_spi = RTE_BE32(rule->esp_spi);
1296 
1297  if (rule->l3_type == DOCA_FLOW_L3_TYPE_IP4) {
1298  decrypt_pipe = &app_cfg->decrypt_pipes.decrypt_ipv4_pipe;
1299  match.outer.ip4.dst_ip = rule->dst_ip4;
1300  } else {
1301  decrypt_pipe = &app_cfg->decrypt_pipes.decrypt_ipv6_pipe;
1302  memcpy(match.outer.ip6.dst_ip, rule->dst_ip6, sizeof(rule->dst_ip6));
1303  }
1304 
1305  actions.action_idx = 0;
1307  /* save rule index in metadata */
1308  meta.decrypt = 1;
1309  meta.rule_id = rule_id;
1310  meta.inner_ipv6 = 0;
1312  meta.inner_ipv6 = 1;
1314 
1315  if (app_cfg->debug_mode) {
1316  flags = DOCA_FLOW_WAIT_FOR_BATCH;
1317  snprintf(decrypt_pipe->entries_info[decrypt_pipe->nb_entries].name, MAX_NAME_LEN, "rule%d", rule_id);
1318  entry = &decrypt_pipe->entries_info[decrypt_pipe->nb_entries++].entry;
1319  } else
1320  flags = DOCA_FLOW_NO_WAIT;
1322  decrypt_pipe->pipe,
1323  &match,
1324  &actions,
1325  NULL,
1326  NULL,
1327  flags,
1328  &app_cfg->secured_status[0],
1329  entry);
1330  if (result != DOCA_SUCCESS) {
1331  DOCA_LOG_ERR("Failed to add pipe entry: %s", doca_error_get_descr(result));
1332  return result;
1333  }
1334  app_cfg->secured_status[0].entries_in_queue++;
1335 
1336  if (app_cfg->debug_mode) {
1337  result = add_bad_syndrome_pipe_entry(app_cfg->decrypt_pipes.bad_syndrome_pipe.pipe,
1338  rule,
1339  rule_id,
1340  &app_cfg->secured_status[0],
1342  0);
1343  if (result != DOCA_SUCCESS) {
1344  DOCA_LOG_ERR("Failed to add pipe entry: %s", doca_error_get_descr(result));
1345  return result;
1346  }
1347  app_cfg->secured_status[0].entries_in_queue += NUM_OF_SYNDROMES;
1348  }
1349 
1350  /* process the entries in the decryption pipe*/
1351  do {
1352  result = process_entries(port, &app_cfg->secured_status[0], DEFAULT_TIMEOUT_US, 0);
1353  if (result != DOCA_SUCCESS)
1354  return result;
1355  } while (app_cfg->secured_status[0].entries_in_queue > 0);
1356  return DOCA_SUCCESS;
1357 }
1358 
1359 doca_error_t bind_decrypt_ids(int nb_rules, int initial_id, struct doca_flow_port *port)
1360 {
1362  int i, array_len = nb_rules;
1363  uint32_t *res_array;
1364 
1365  if (array_len == 0)
1366  return DOCA_SUCCESS;
1367  res_array = (uint32_t *)malloc(array_len * sizeof(uint32_t));
1368  if (res_array == NULL) {
1369  DOCA_LOG_ERR("Failed to allocate ids array");
1370  return DOCA_ERROR_NO_MEMORY;
1371  }
1372 
1373  for (i = 0; i < nb_rules; i++) {
1374  res_array[i] = initial_id + i;
1375  }
1377  if (result != DOCA_SUCCESS) {
1378  DOCA_LOG_ERR("Failed to bind decrypt IDs to the port");
1379  free(res_array);
1380  return result;
1381  }
1382 
1383  free(res_array);
1384  return DOCA_SUCCESS;
1385 }
1386 
1388  struct ipsec_security_gw_ports_map *port,
1389  uint16_t queue_id,
1390  int nb_rules,
1391  int rule_offset)
1392 {
1393  struct doca_flow_match decrypt_match;
1394  struct doca_flow_actions actions;
1395  struct doca_flow_pipe_entry **entry = NULL;
1396  struct security_gateway_pipe_info *decrypt_pipe;
1397  struct doca_flow_port *secured_port;
1398  enum doca_flow_flags_type flags;
1399  enum doca_flow_flags_type decrypt_flags;
1400  int i, rule_id;
1402  union security_gateway_pkt_meta meta = {0};
1403  struct decrypt_rule *rules = app_cfg->app_rules.decrypt_rules;
1404  struct decrypt_pipes *pipes = &app_cfg->decrypt_pipes;
1405  int nb_encrypt_rules = app_cfg->app_rules.nb_encrypt_rules;
1406 
1407  if (app_cfg->flow_mode == IPSEC_SECURITY_GW_VNF) {
1408  secured_port = port->port;
1409  } else {
1410  secured_port = doca_flow_port_switch_get(NULL);
1411  }
1412 
1413  memset(&app_cfg->secured_status[queue_id], 0, sizeof(app_cfg->secured_status[queue_id]));
1414  memset(&decrypt_match, 0, sizeof(decrypt_match));
1415  memset(&actions, 0, sizeof(actions));
1416 
1417  for (i = 0; i < nb_rules; i++) {
1418  rule_id = rule_offset + i;
1419  if (i == nb_rules - 1 || app_cfg->secured_status[queue_id].entries_in_queue == QUEUE_DEPTH - 8)
1420  flags = DOCA_FLOW_NO_WAIT;
1421  else
1422  flags = DOCA_FLOW_WAIT_FOR_BATCH;
1423 
1424  /* create ipsec shared objects */
1426  app_cfg,
1427  nb_encrypt_rules + rule_id);
1428  if (result != DOCA_SUCCESS)
1429  return result;
1430 
1431  /* build rule match with specific destination IP and ESP SPI */
1432  decrypt_match.tun.esp_spi = RTE_BE32(rules[rule_id].esp_spi);
1433  actions.action_idx = 0;
1434  actions.crypto.crypto_id = nb_encrypt_rules + rule_id;
1435 
1436  if (rules[rule_id].l3_type == DOCA_FLOW_L3_TYPE_IP4) {
1437  decrypt_pipe = &pipes->decrypt_ipv4_pipe;
1438  decrypt_match.outer.ip4.dst_ip = rules[rule_id].dst_ip4;
1439  } else {
1440  decrypt_pipe = &pipes->decrypt_ipv6_pipe;
1441  memcpy(decrypt_match.outer.ip6.dst_ip, rules[rule_id].dst_ip6, sizeof(rules[rule_id].dst_ip6));
1442  }
1443 
1444  /* save rule index in metadata */
1445  meta.decrypt = 1;
1446  meta.rule_id = rule_id;
1447  meta.inner_ipv6 = 0;
1449  meta.inner_ipv6 = 1;
1450 
1452 
1453  if (app_cfg->debug_mode) {
1454  decrypt_flags = DOCA_FLOW_WAIT_FOR_BATCH;
1455  snprintf(decrypt_pipe->entries_info[decrypt_pipe->nb_entries].name, MAX_NAME_LEN, "rule%d", i);
1456  entry = &decrypt_pipe->entries_info[decrypt_pipe->nb_entries++].entry;
1457  } else
1458  decrypt_flags = flags;
1460  decrypt_pipe->pipe,
1461  &decrypt_match,
1462  &actions,
1463  NULL,
1464  NULL,
1465  decrypt_flags,
1466  &app_cfg->secured_status[queue_id],
1467  entry);
1468  if (result != DOCA_SUCCESS) {
1469  DOCA_LOG_ERR("Failed to add pipe entry: %s", doca_error_get_descr(result));
1470  return result;
1471  }
1472  app_cfg->secured_status[queue_id].entries_in_queue++;
1473 
1474  if (app_cfg->debug_mode) {
1476  &rules[rule_id],
1477  rule_id,
1478  &app_cfg->secured_status[queue_id],
1479  flags,
1480  queue_id);
1481  if (result != DOCA_SUCCESS) {
1482  DOCA_LOG_ERR("Failed to add pipe entry: %s", doca_error_get_descr(result));
1483  return result;
1484  }
1485  app_cfg->secured_status[queue_id].entries_in_queue += NUM_OF_SYNDROMES;
1486  }
1487  if (app_cfg->secured_status[queue_id].entries_in_queue >= QUEUE_DEPTH - 8) {
1488  result = doca_flow_entries_process(secured_port,
1489  queue_id,
1491  app_cfg->secured_status[queue_id].entries_in_queue);
1492  if (result != DOCA_SUCCESS) {
1493  DOCA_LOG_ERR("Failed to process entries: %s", doca_error_get_descr(result));
1494  return result;
1495  }
1496  if (app_cfg->secured_status[queue_id].failure ||
1497  app_cfg->secured_status[queue_id].entries_in_queue == QUEUE_DEPTH) {
1498  DOCA_LOG_ERR("Failed to process entries");
1499  return DOCA_ERROR_BAD_STATE;
1500  }
1501  }
1502  }
1503 
1504  /* process the entries in the decryption pipe*/
1505  do {
1506  result =
1507  process_entries(secured_port, &app_cfg->secured_status[queue_id], DEFAULT_TIMEOUT_US, queue_id);
1508  if (result != DOCA_SUCCESS)
1509  return result;
1510  } while (app_cfg->secured_status[queue_id].entries_in_queue > 0);
1511  return DOCA_SUCCESS;
1512 }
1513 
1516 {
1517  uint32_t nb_queues = app_cfg->dpdk_config->port_config.nb_queues;
1518  uint16_t rss_queues[nb_queues];
1519  uint32_t rss_flags;
1520  struct doca_flow_port *secured_port;
1521  struct doca_flow_fwd fwd;
1522  bool is_root;
1524  int expected_entries;
1525 
1526  if (app_cfg->socket_ctx.socket_conf)
1527  expected_entries = MAX_NB_RULES;
1528  else if (app_cfg->app_rules.nb_decrypt_rules > 0)
1529  expected_entries = app_cfg->app_rules.nb_decrypt_rules;
1530  else /* default value - no entries expected, putting a default value so that pipe creation won't fail */
1531  expected_entries = DEF_EXPECTED_ENTRIES;
1532 
1533  if (app_cfg->flow_mode == IPSEC_SECURITY_GW_VNF) {
1534  secured_port = ports[SECURED_IDX]->port;
1535  is_root = true;
1536  } else {
1537  secured_port = doca_flow_port_switch_get(NULL);
1538  is_root = false;
1539  }
1540 
1541  if (app_cfg->debug_mode) {
1542  DOCA_LOG_DBG("Creating bad syndrome pipe");
1544  secured_port,
1545  expected_entries,
1546  &app_cfg->decrypt_pipes.bad_syndrome_pipe.pipe);
1547  if (result != DOCA_SUCCESS)
1548  return result;
1549  }
1550 
1551  rss_flags = DOCA_FLOW_RSS_IPV4 | DOCA_FLOW_RSS_IPV6;
1553 
1554  DOCA_LOG_DBG("Creating decap pipe");
1555  snprintf(app_cfg->decrypt_pipes.decap_pipe.name, MAX_NAME_LEN, "decap");
1556  result = create_ipsec_decap_pipe(secured_port, app_cfg, &fwd, &app_cfg->decrypt_pipes.decap_pipe);
1557  if (result != DOCA_SUCCESS)
1558  return result;
1559 
1561  secured_port,
1562  &ports[UNSECURED_IDX]->eth_header,
1563  &app_cfg->decrypt_pipes.decap_pipe);
1564  if (result != DOCA_SUCCESS) {
1565  DOCA_LOG_ERR("Failed to bind IDs: %s", doca_error_get_descr(result));
1566  return result;
1567  }
1568  DOCA_LOG_DBG("Creating IPv4 decrypt pipe");
1569  snprintf(app_cfg->decrypt_pipes.decrypt_ipv4_pipe.name, MAX_NAME_LEN, "IPv4_decrypt");
1570  result = create_ipsec_decrypt_pipe(secured_port,
1571  expected_entries,
1573  app_cfg,
1574  &app_cfg->decrypt_pipes.decrypt_ipv4_pipe);
1575  if (result != DOCA_SUCCESS)
1576  return result;
1577 
1578  DOCA_LOG_DBG("Creating IPv6 decrypt pipe");
1579  snprintf(app_cfg->decrypt_pipes.decrypt_ipv6_pipe.name, MAX_NAME_LEN, "IPv6_decrypt");
1580  result = create_ipsec_decrypt_pipe(secured_port,
1581  expected_entries,
1583  app_cfg,
1584  &app_cfg->decrypt_pipes.decrypt_ipv6_pipe);
1585  if (result != DOCA_SUCCESS)
1586  return result;
1587 
1588  if (app_cfg->vxlan_encap) {
1589  if (app_cfg->marker_encap) {
1590  DOCA_LOG_ERR("Non-ESP marker is not supported over VXLAN encapsulation");
1591  return DOCA_ERROR_NOT_SUPPORTED;
1592  }
1593 
1594  DOCA_LOG_DBG("Creating inner IPv4 vxlan decap pipe");
1595  snprintf(app_cfg->decrypt_pipes.vxlan_decap_ipv4_pipe.name, MAX_NAME_LEN, "vxlan_decap_in_IPv4");
1596  result = create_vxlan_decap_pipe(secured_port,
1597  app_cfg,
1598  app_cfg->decrypt_pipes.decrypt_ipv4_pipe.pipe,
1599  &app_cfg->decrypt_pipes.vxlan_decap_ipv4_pipe);
1600  if (result != DOCA_SUCCESS)
1601  return result;
1602 
1603  DOCA_LOG_DBG("Creating inner IPv6 vxlan decap pipe");
1604  snprintf(app_cfg->decrypt_pipes.vxlan_decap_ipv6_pipe.name, MAX_NAME_LEN, "vxlan_decap_in_IPv6");
1605  result = create_vxlan_decap_pipe(secured_port,
1606  app_cfg,
1607  app_cfg->decrypt_pipes.decrypt_ipv6_pipe.pipe,
1608  &app_cfg->decrypt_pipes.vxlan_decap_ipv6_pipe);
1609  if (result != DOCA_SUCCESS)
1610  return result;
1611  } else if (app_cfg->marker_encap) {
1612  result = create_marker_decap_pipe(secured_port, app_cfg);
1613  if (result != DOCA_SUCCESS) {
1614  DOCA_LOG_ERR("Failed to create non-ESP marker decap ingress pipe: %s",
1616  return result;
1617  }
1618  }
1619 
1620  DOCA_LOG_DBG("Creating control pipe");
1621  snprintf(app_cfg->decrypt_pipes.decrypt_root.name, MAX_NAME_LEN, "decrypt_root");
1622  result = create_control_pipe(secured_port, is_root, app_cfg->debug_mode, &app_cfg->decrypt_pipes.decrypt_root);
1623  if (result != DOCA_SUCCESS)
1624  return result;
1625 
1626  DOCA_LOG_DBG("Adding control pipe entries");
1627  result = add_control_pipe_entries(&app_cfg->decrypt_pipes.decrypt_root, app_cfg, is_root);
1628  if (result != DOCA_SUCCESS)
1629  return result;
1630 
1631  return DOCA_SUCCESS;
1632 }
1633 
1634 /*
1635  * Find packet's segment for the specified offset.
1636  *
1637  * @mb [in]: packet mbuf
1638  * @offset [in]: offset in the packet
1639  * @seg_buf [out]: the segment that contain the offset
1640  * @seg_offset [out]: offset in the segment
1641  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1642  */
1643 static doca_error_t mbuf_get_seg_ofs(struct rte_mbuf *mb,
1644  uint32_t offset,
1645  struct rte_mbuf **seg_buf,
1646  uint32_t *seg_offset)
1647 {
1648  uint32_t packet_len, seg_len;
1649  struct rte_mbuf *tmp_buf;
1650 
1651  packet_len = mb->pkt_len;
1652 
1653  /* if offset is the end of packet */
1654  if (offset >= packet_len) {
1655  DOCA_LOG_ERR("Packet offset is invalid");
1656  return DOCA_ERROR_INVALID_VALUE;
1657  }
1658 
1659  tmp_buf = mb;
1660  for (seg_len = rte_pktmbuf_data_len(tmp_buf); seg_len <= offset; seg_len = rte_pktmbuf_data_len(tmp_buf)) {
1661  tmp_buf = tmp_buf->next;
1662  offset -= seg_len;
1663  }
1664 
1665  *seg_offset = offset;
1666  *seg_buf = tmp_buf;
1667  return DOCA_SUCCESS;
1668 }
1669 
1670 /*
1671  * Remove packet trailer - padding, ESP tail, and ICV
1672  *
1673  * @m [in]: the mbuf to update
1674  * @icv_len [in]: ICV length
1675  * @next_proto [out]: ESP tail next protocol field
1676  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1677  */
1678 static doca_error_t remove_packet_tail(struct rte_mbuf **m, uint32_t icv_len, uint32_t *next_proto)
1679 {
1680  struct rte_mbuf *ml;
1681  const struct rte_esp_tail *esp_tail;
1682  uint32_t esp_tail_offset, esp_tail_seg_offset, trailer_len;
1684 
1685  /* remove trailing zeros */
1687 
1688  /* find tail offset */
1689  trailer_len = icv_len + sizeof(struct rte_esp_tail);
1690 
1691  /* find tail offset */
1692  esp_tail_offset = (*m)->pkt_len - trailer_len;
1693 
1694  /* get the segment with the tail offset */
1695  result = mbuf_get_seg_ofs(*m, esp_tail_offset, &ml, &esp_tail_seg_offset);
1696  if (result != DOCA_SUCCESS)
1697  return result;
1698 
1699  esp_tail = rte_pktmbuf_mtod_offset(ml, const struct rte_esp_tail *, esp_tail_seg_offset);
1700  *next_proto = esp_tail->next_proto;
1701  trailer_len += esp_tail->pad_len;
1702  esp_tail_seg_offset -= esp_tail->pad_len;
1703 
1704  /* remove padding, tail and icv from the end of the packet */
1705  (*m)->pkt_len -= trailer_len;
1706  ml->data_len = esp_tail_seg_offset;
1707  return DOCA_SUCCESS;
1708 }
1709 
1710 /*
1711  * Decap mbuf for tunnel mode
1712  *
1713  * @m [in]: the mbuf to update
1714  * @ctx [in]: the security gateway context
1715  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1716  */
1718 {
1719  uint32_t iv_len = 8;
1720  struct rte_ether_hdr *l2_header;
1721  struct rte_ipv4_hdr *ipv4;
1722  uint32_t proto, l3_len;
1723  char *np;
1724  uint32_t icv_len = get_icv_len_int(ctx->config->icv_length);
1725  uint16_t reformat_decap_data_len;
1726  enum doca_flow_l3_type inner_l3_type;
1728 
1729  result = remove_packet_tail(m, icv_len, &proto);
1730  if (result != DOCA_SUCCESS)
1731  return result;
1732 
1733  /* calculate l3 len */
1734  l2_header = rte_pktmbuf_mtod(*m, struct rte_ether_hdr *);
1735  if (RTE_ETH_IS_IPV4_HDR((*m)->packet_type)) {
1736  ipv4 = (void *)(l2_header + 1);
1737  l3_len = rte_ipv4_hdr_len(ipv4);
1738  } else {
1739  l3_len = sizeof(struct rte_ipv6_hdr);
1740  }
1741 
1742  /* remove l3 and ESP header from the beginning of the packet */
1743  np = rte_pktmbuf_adj(*m, l3_len + sizeof(struct rte_esp_hdr) + iv_len);
1744  if (unlikely(np == NULL))
1745  return DOCA_ERROR_INVALID_VALUE;
1746 
1747  /* change the ether type based on the tail proto */
1748  l2_header = rte_pktmbuf_mtod(*m, struct rte_ether_hdr *);
1749  if (proto == IPPROTO_IPV6) {
1750  inner_l3_type = DOCA_FLOW_L3_TYPE_IP6;
1751  } else {
1752  inner_l3_type = DOCA_FLOW_L3_TYPE_IP4;
1753  }
1755  inner_l3_type,
1756  (uint8_t *)np,
1757  &reformat_decap_data_len);
1758 
1759  return DOCA_SUCCESS;
1760 }
1761 
1762 /*
1763  * Decap mbuf for transport and udp transport mode
1764  *
1765  * @m [in]: the mbuf to update
1766  * @ctx [in]: the security gateway context
1767  * @udp_transport [in]: true for UDP transport mode
1768  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1769  */
1770 static doca_error_t decap_packet_transport(struct rte_mbuf **m,
1772  bool udp_transport)
1773 {
1774  uint32_t iv_len = 8;
1775  struct rte_ether_hdr *l2_header;
1776  char *op, *np;
1777  struct rte_ipv4_hdr *ipv4 = NULL;
1778  struct rte_ipv6_hdr *ipv6 = NULL;
1779  uint32_t l2_l3_len, proto;
1780  int i;
1781  uint32_t icv_len = get_icv_len_int(ctx->config->icv_length);
1783 
1784  result = remove_packet_tail(m, icv_len, &proto);
1785  if (result != DOCA_SUCCESS)
1786  return result;
1787 
1788  /* calculate l2 and l3 len */
1789  l2_header = rte_pktmbuf_mtod(*m, struct rte_ether_hdr *);
1790  if (RTE_ETH_IS_IPV4_HDR((*m)->packet_type)) {
1791  ipv4 = (void *)(l2_header + 1);
1792  l2_l3_len = rte_ipv4_hdr_len(ipv4) + sizeof(struct rte_ether_hdr);
1793  } else {
1794  ipv6 = (void *)(l2_header + 1);
1795  l2_l3_len = sizeof(struct rte_ipv6_hdr) + sizeof(struct rte_ether_hdr);
1796  }
1797 
1798  /* remove ESP header from the beginning of the packet and UDP header in udp_transport mode*/
1799  op = rte_pktmbuf_mtod(*m, char *);
1800  if (!udp_transport)
1801  np = rte_pktmbuf_adj(*m, sizeof(struct rte_esp_hdr) + iv_len);
1802  else
1803  np = rte_pktmbuf_adj(*m, sizeof(struct rte_esp_hdr) + sizeof(struct rte_udp_hdr) + iv_len);
1804  if (unlikely(np == NULL))
1805  return DOCA_ERROR_INVALID_VALUE;
1806 
1807  /* align IP length, next protocol and IPv4 checksum */
1808  if (RTE_ETH_IS_IPV4_HDR((*m)->packet_type)) {
1809  ipv4->next_proto_id = proto;
1810  ipv4->total_length = rte_cpu_to_be_16((*m)->pkt_len - sizeof(struct rte_ether_hdr));
1811  ipv4->hdr_checksum = 0;
1812  ipv4->hdr_checksum = rte_ipv4_cksum(ipv4);
1813  } else {
1814  ipv6->proto = proto;
1815  ipv6->payload_len = rte_cpu_to_be_16((*m)->pkt_len - sizeof(struct rte_ether_hdr) - sizeof(*ipv6));
1816  /* IPv6 does not have checksum */
1817  }
1818 
1819  /* copy old l2 and l3 to the new beginning */
1820  for (i = l2_l3_len - 1; i >= 0; i--)
1821  np[i] = op[i];
1822  return DOCA_SUCCESS;
1823 }
1824 
1825 /*
1826  * extract the sn from the mbuf
1827  *
1828  * @m [in]: the mbuf to extract from
1829  * @mode [in]: application running mode
1830  * @sn [out]: the sn
1831  */
1832 static void get_esp_sn(struct rte_mbuf *m, enum ipsec_security_gw_mode mode, uint32_t *sn)
1833 {
1834  uint32_t l2_l3_len;
1835  struct rte_ether_hdr *oh;
1836  struct rte_ipv4_hdr *ipv4;
1837  struct rte_esp_hdr *esp_hdr;
1838 
1839  oh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
1840  if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
1841  ipv4 = (void *)(oh + 1);
1842  l2_l3_len = rte_ipv4_hdr_len(ipv4) + sizeof(struct rte_ether_hdr);
1843  } else {
1844  l2_l3_len = sizeof(struct rte_ipv6_hdr) + sizeof(struct rte_ether_hdr);
1845  }
1846 
1847  if (mode == IPSEC_SECURITY_GW_UDP_TRANSPORT)
1848  l2_l3_len += sizeof(struct rte_udp_hdr);
1849 
1850  esp_hdr = rte_pktmbuf_mtod_offset(m, struct rte_esp_hdr *, l2_l3_len);
1851  *sn = rte_be_to_cpu_32(esp_hdr->seq);
1852 }
1853 
1854 /*
1855  * Perform anti replay check on a packet and update the state accordingly
1856  * (1) If sn is left (smaller) from window - drop.
1857  * (2) Else, if sn is in the window - check if it was already received (drop) or not (update bitmap).
1858  * (3) Else, if sn is larger than window - slide the window so that sn is the last packet in the window and
1859  * update bitmap.
1860  *
1861  * @sn [in]: the sequence number to check
1862  * @state [in/out]: the anti replay state
1863  * @drop [out]: true if the packet should be dropped
1864  *
1865  * @NOTE: Only supports 64 window size and regular sn (not ESN)
1866  */
1867 static void anti_replay(uint32_t sn, struct antireplay_state *state, bool *drop)
1868 {
1869  uint32_t diff, beg_win_sn;
1870  uint32_t window_size = state->window_size;
1871  uint32_t *end_win_sn = &state->end_win_sn;
1872  uint64_t *bitmap = &state->bitmap;
1873 
1874  beg_win_sn = *end_win_sn + 1 - window_size; /* the first sn in the window */
1875  *drop = true;
1876 
1877  /* (1) Check if sn is smaller than beginning of the window */
1878  if (sn < beg_win_sn)
1879  return; /* drop */
1880  /* (2) Check if sn is in the window */
1881  if (sn <= *end_win_sn) {
1882  diff = sn - beg_win_sn;
1883  /* Check if sn is already received */
1884  if (*bitmap & (((uint64_t)1) << diff))
1885  return; /* drop */
1886  else {
1887  *bitmap |= (((uint64_t)1) << diff);
1888  *drop = false;
1889  }
1890  /* (3) sn is larger than end of window */
1891  } else { /* move window and set last bit */
1892  diff = sn - *end_win_sn;
1893  if (diff >= window_size) {
1894  *bitmap = (((uint64_t)1) << (window_size - 1));
1895  *drop = false;
1896  } else {
1897  *bitmap = (*bitmap >> diff);
1898  *bitmap |= (((uint64_t)1) << (window_size - 1));
1899  *drop = false;
1900  }
1901  *end_win_sn = sn;
1902  }
1903 }
1904 
1906  bool bad_syndrome_check,
1908 {
1909  uint32_t pkt_meta;
1910  uint32_t rule_idx;
1911  uint32_t sn;
1912  union security_gateway_pkt_meta meta;
1914  bool drop;
1915 
1916  pkt_meta = *RTE_FLOW_DYNF_METADATA(*packet);
1917  meta = (union security_gateway_pkt_meta)pkt_meta;
1918  rule_idx = meta.rule_id;
1919  if (bad_syndrome_check) {
1920  if (meta.decrypt_syndrome != 0 || meta.antireplay_syndrome != 0)
1921  return DOCA_ERROR_BAD_STATE;
1922  }
1923  if (ctx->config->sw_antireplay) {
1924  /* Validate anti replay according to the entry's state */
1925  get_esp_sn(*packet, ctx->config->mode, &sn);
1926  result = doca_flow_crypto_ipsec_update_sn(ctx->config->app_rules.nb_encrypt_rules + rule_idx, sn);
1927  if (result != DOCA_SUCCESS)
1928  return result;
1929  /* No synchronization needed, same rule is processed by the same core */
1930  anti_replay(sn, &(ctx->decrypt_rules[rule_idx].antireplay_state), &drop);
1931  if (drop) {
1932  DOCA_LOG_WARN("Anti Replay mechanism dropped packet- sn: %u, rule index: %d", sn, rule_idx);
1933  return DOCA_ERROR_BAD_STATE;
1934  }
1935  }
1936 
1937  if (ctx->config->mode == IPSEC_SECURITY_GW_TRANSPORT)
1938  return decap_packet_transport(packet, ctx, false);
1939  else if (ctx->config->mode == IPSEC_SECURITY_GW_UDP_TRANSPORT)
1940  return decap_packet_transport(packet, ctx, true);
1941  else
1942  return decap_packet_tunnel(packet, ctx);
1943 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
void remove_ethernet_padding(struct rte_mbuf **m)
Definition: flow_common.c:870
doca_error_t process_entries(struct doca_flow_port *port, struct entries_status *status, int timeout, uint16_t pipe_queue)
Definition: flow_common.c:78
void create_hairpin_pipe_fwd(struct ipsec_security_gw_config *app_cfg, int port_id, bool encrypt, uint16_t *rss_queues, uint32_t rss_flags, struct doca_flow_fwd *fwd)
Definition: flow_common.c:512
uint32_t get_icv_len_int(enum doca_flow_crypto_icv_len icv_len)
Definition: flow_common.c:374
#define DEF_EXPECTED_ENTRIES
Definition: flow_common.h:43
#define QUEUE_DEPTH
Definition: flow_common.h:39
#define SECURED_IDX
Definition: flow_common.h:40
#define UNSECURED_IDX
Definition: flow_common.h:41
uint32_t rule_id
Definition: flow_common.h:8
#define SET_IP6_ADDR(addr, a, b, c, d)
Definition: flow_common.h:53
#define unlikely(x)
Definition: utils.h:42
if(bitoffset % 64+bitlength > 64) result|
static int nb_entries
doca_error_t ipsec_security_gw_insert_decrypt_rules(struct ipsec_security_gw_ports_map *ports[], struct ipsec_security_gw_config *app_cfg)
static doca_error_t create_control_pipe(struct doca_flow_port *port, bool is_root, bool debug_mode, struct security_gateway_pipe_info *pipe_info)
#define DECAP_IDX_SRC_MAC
Definition: flow_decrypt.c:38
static void get_bad_syndrome_pipe_fwd(struct ipsec_security_gw_config *app_cfg, uint16_t *rss_queues, struct doca_flow_fwd *fwd)
Definition: flow_decrypt.c:170
doca_error_t bind_decrypt_ids(int nb_rules, int initial_id, struct doca_flow_port *port)
static doca_error_t create_ipsec_decap_pipe(struct doca_flow_port *port, struct ipsec_security_gw_config *app_cfg, struct doca_flow_fwd *fwd, struct security_gateway_pipe_info *pipe_info)
Definition: flow_decrypt.c:578
static doca_error_t remove_packet_tail(struct rte_mbuf **m, uint32_t icv_len, uint32_t *next_proto)
static doca_error_t create_ipsec_decrypt_pipe(struct doca_flow_port *port, int expected_entries, enum doca_flow_l3_type l3_type, struct ipsec_security_gw_config *app_cfg, struct security_gateway_pipe_info *pipe_info)
Definition: flow_decrypt.c:52
DOCA_LOG_REGISTER(IPSEC_SECURITY_GW::flow_decrypt)
static doca_error_t add_vxlan_decap_pipe_entry(struct doca_flow_port *port, struct security_gateway_pipe_info *pipe, struct ipsec_security_gw_config *app_cfg)
Definition: flow_decrypt.c:431
static doca_error_t add_control_pipe_entries(struct security_gateway_pipe_info *control_pipe, struct ipsec_security_gw_config *app_cfg, bool is_root)
#define DECAP_MARKER_HEADER_SIZE
Definition: flow_decrypt.c:39
static void get_esp_sn(struct rte_mbuf *m, enum ipsec_security_gw_mode mode, uint32_t *sn)
static doca_error_t mbuf_get_seg_ofs(struct rte_mbuf *mb, uint32_t offset, struct rte_mbuf **seg_buf, uint32_t *seg_offset)
static doca_error_t add_bad_syndrome_pipe_entry(struct doca_flow_pipe *pipe, struct decrypt_rule *rule, uint32_t rule_id, struct entries_status *decrypt_status, enum doca_flow_flags_type flags, int queue_id)
Definition: flow_decrypt.c:319
static doca_error_t create_ipsec_decrypt_shared_object(struct ipsec_security_gw_sa_attrs *app_sa_attrs, struct ipsec_security_gw_config *app_cfg, uint32_t ipsec_id)
static doca_error_t create_vxlan_decap_pipe(struct doca_flow_port *port, struct ipsec_security_gw_config *app_cfg, struct doca_flow_pipe *next_pipe, struct security_gateway_pipe_info *pipe)
Definition: flow_decrypt.c:490
doca_error_t handle_secured_packets_received(struct rte_mbuf **packet, bool bad_syndrome_check, struct ipsec_security_gw_core_ctx *ctx)
static void anti_replay(uint32_t sn, struct antireplay_state *state, bool *drop)
#define UDP_DST_PORT_FOR_ESP
Definition: flow_decrypt.c:40
static void create_tunnel_decap_tunnel(struct doca_flow_header_eth *eth_header, enum doca_flow_l3_type inner_l3_type, uint8_t *reformat_data, uint16_t *reformat_data_sz)
Definition: flow_decrypt.c:891
#define DECAP_MAC_TYPE_IDX
Definition: flow_decrypt.c:37
static doca_error_t create_marker_decap_pipe(struct doca_flow_port *port, struct ipsec_security_gw_config *app_cfg)
Definition: flow_decrypt.c:722
static doca_error_t decap_packet_transport(struct rte_mbuf **m, struct ipsec_security_gw_core_ctx *ctx, bool udp_transport)
static doca_error_t decap_packet_tunnel(struct rte_mbuf **m, struct ipsec_security_gw_core_ctx *ctx)
static doca_error_t create_bad_syndrome_pipe(struct ipsec_security_gw_config *app_cfg, struct doca_flow_port *port, int expected_entries, struct doca_flow_pipe **pipe)
Definition: flow_decrypt.c:208
static doca_error_t add_decap_pipe_entries(struct ipsec_security_gw_config *app_cfg, struct doca_flow_port *port, struct doca_flow_header_eth *eth_header, struct security_gateway_pipe_info *pipe)
Definition: flow_decrypt.c:942
doca_error_t add_decrypt_entries(struct ipsec_security_gw_config *app_cfg, struct ipsec_security_gw_ports_map *port, uint16_t queue_id, int nb_rules, int rule_offset)
doca_error_t add_decrypt_entry(struct decrypt_rule *rule, int rule_id, struct doca_flow_port *port, struct ipsec_security_gw_config *app_cfg)
static doca_error_t destroy_pipe_cfg(struct doca_flow_pipe_cfg *cfg)
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_monitor monitor
Definition: flow_parser.c:108
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]
#define DEFAULT_TIMEOUT_US
Definition: flow_skeleton.c:36
static struct app_gpu_cfg app_cfg
#define DOCA_HTOBE32(_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_INVALID_VALUE
Definition: doca_error.h:44
@ 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_NO_MEMORY
Definition: doca_error.h:45
DOCA_EXPERIMENTAL doca_error_t doca_flow_crypto_ipsec_update_sn(uint32_t shared_res_id, uint64_t sequence_number)
Update the sequence number state for specific resource.
@ DOCA_FLOW_CRYPTO_SN_OFFLOAD_AR
@ DOCA_FLOW_CRYPTO_REPLAY_WIN_SIZE_128
@ DOCA_FLOW_CRYPTO_HEADER_UDP_ESP_OVER_IPV4
@ DOCA_FLOW_CRYPTO_HEADER_NON_ESP_MARKER
@ DOCA_FLOW_CRYPTO_HEADER_ESP_OVER_IPV4
@ DOCA_FLOW_CRYPTO_HEADER_ESP_TUNNEL
@ DOCA_FLOW_CRYPTO_RESOURCE_IPSEC_SA
@ DOCA_FLOW_CRYPTO_REFORMAT_DECAP
@ DOCA_FLOW_CRYPTO_ACTION_DECRYPT
doca_flow_l3_type
doca flow layer 3 packet type
#define DOCA_FLOW_ETHER_TYPE_IPV6
Definition: doca_flow_net.h:58
#define DOCA_FLOW_ETHER_TYPE_IPV4
Definition: doca_flow_net.h:57
@ DOCA_FLOW_L4_TYPE_EXT_UDP
@ DOCA_FLOW_L3_TYPE_IP6
@ DOCA_FLOW_L3_TYPE_IP4
@ DOCA_FLOW_TUN_EXT_VXLAN_STANDARD
@ DOCA_FLOW_TUN_VXLAN
@ DOCA_FLOW_TUN_ESP
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_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_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_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.
doca_flow_flags_type
doca flow flags type
Definition: doca_flow.h:114
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_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_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_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_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 struct doca_flow_port * doca_flow_port_switch_get(const struct doca_flow_port *port)
Get doca flow switch port.
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_FLOW_RSS_IPV4
Definition: doca_flow.h:764
@ DOCA_FLOW_RSS_IPV6
Definition: doca_flow.h:766
@ DOCA_FLOW_SHARED_RESOURCE_IPSEC_SA
Definition: doca_flow.h:107
@ DOCA_FLOW_DIRECTION_NETWORK_TO_HOST
Definition: doca_flow.h:1094
@ DOCA_FLOW_PIPE_CONTROL
Definition: doca_flow.h:223
@ DOCA_FLOW_PIPE_BASIC
Definition: doca_flow.h:221
@ 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_WAIT_FOR_BATCH
Definition: doca_flow.h:117
@ DOCA_FLOW_RESOURCE_TYPE_NON_SHARED
Definition: doca_flow.h:615
@ DOCA_FLOW_FWD_PIPE
Definition: doca_flow.h:746
@ DOCA_FLOW_FWD_DROP
Definition: doca_flow.h:748
@ DOCA_FLOW_FWD_RSS
Definition: doca_flow.h:742
@ DOCA_FLOW_L4_META_UDP
Definition: doca_flow.h:310
@ DOCA_FLOW_L4_META_ESP
Definition: doca_flow.h:314
@ DOCA_FLOW_PIPE_DOMAIN_SECURE_INGRESS
Definition: doca_flow.h:243
#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_DBG(format,...)
Generates a DEBUG application log message.
Definition: doca_log.h:496
const struct ip_frag_config * cfg
Definition: ip_frag_dp.c:0
uint16_t queue_id
Definition: ip_frag_dp.c:1
@ IPSEC_SECURITY_GW_FWD_SYNDROME_RSS
Definition: ipsec_ctx.h:210
ipsec_security_gw_mode
Definition: ipsec_ctx.h:179
@ IPSEC_SECURITY_GW_UDP_TRANSPORT
Definition: ipsec_ctx.h:182
@ IPSEC_SECURITY_GW_TUNNEL
Definition: ipsec_ctx.h:180
@ IPSEC_SECURITY_GW_TRANSPORT
Definition: ipsec_ctx.h:181
#define MAX_NB_RULES
Definition: ipsec_ctx.h:40
#define NUM_OF_SYNDROMES
Definition: ipsec_ctx.h:43
@ IPSEC_SECURITY_GW_VNF
Definition: ipsec_ctx.h:187
@ IPSEC_SECURITY_GW_SWITCH
Definition: ipsec_ctx.h:188
@ IPSEC_SECURITY_GW_ESP_OFFLOAD_DECAP
Definition: ipsec_ctx.h:195
@ IPSEC_SECURITY_GW_ESP_OFFLOAD_BOTH
Definition: ipsec_ctx.h:193
#define MAX_NAME_LEN
Definition: ipsec_ctx.h:46
uint64_t bitmap
Definition: ipsec_ctx.h:69
uint32_t window_size
Definition: ipsec_ctx.h:67
uint32_t end_win_sn
Definition: ipsec_ctx.h:68
struct doca_flow_pipe_entry * entry
Definition: ipsec_ctx.h:61
struct security_gateway_pipe_info decrypt_ipv4_pipe
Definition: ipsec_ctx.h:153
struct security_gateway_pipe_info decrypt_ipv6_pipe
Definition: ipsec_ctx.h:154
struct security_gateway_pipe_info bad_syndrome_pipe
Definition: ipsec_ctx.h:156
enum doca_flow_l3_type inner_l3_type
Definition: ipsec_ctx.h:87
doca_be32_t dst_ip6[4]
Definition: ipsec_ctx.h:84
doca_be32_t esp_spi
Definition: ipsec_ctx.h:86
doca_be32_t dst_ip4
Definition: ipsec_ctx.h:83
enum doca_flow_l3_type l3_type
Definition: ipsec_ctx.h:81
struct ipsec_security_gw_sa_attrs sa_attrs
Definition: ipsec_ctx.h:88
struct bad_syndrome_entry entries[NUM_OF_SYNDROMES]
Definition: ipsec_ctx.h:89
doca flow actions information
Definition: doca_flow.h:684
struct doca_flow_crypto_encap_action crypto_encap
Definition: doca_flow.h:723
struct doca_flow_meta meta
Definition: doca_flow.h:699
enum doca_flow_resource_type decap_type
Definition: doca_flow.h:689
struct doca_flow_crypto_action crypto
Definition: doca_flow.h:725
struct doca_flow_resource_decap_cfg decap_cfg
Definition: doca_flow.h:692
uint8_t action_idx
Definition: doca_flow.h:685
struct doca_flow_crypto_action::@73::@75 ipsec_sa
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
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 eth header
uint8_t src_mac[DOCA_FLOW_ETHER_ADDR_LEN]
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_ip6 ip6
Definition: doca_flow.h:451
doca_be32_t dst_ip[4]
struct doca_flow_header_l4_port l4_port
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 monitor action configuration
Definition: doca_flow.h:968
enum doca_flow_resource_type counter_type
Definition: doca_flow.h:988
uint8_t ipsec_ar_syndrome
Definition: doca_flow.h:378
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 inner_l4_type
Definition: doca_flow.h:386
enum doca_flow_l4_meta outer_l4_type
Definition: doca_flow.h:383
doca flow shared resource configuration
Definition: doca_flow.h:953
enum doca_flow_tun_type type
doca_be32_t vxlan_tun_id
doca_be32_t esp_spi
enum doca_flow_tun_ext_vxlan_type vxlan_type
user context struct that will be used in entries process callback
Definition: flow_common.h:78
struct doca_flow_port * port
Definition: flow_common.h:72
uint8_t enc_key_data[MAX_KEY_LEN]
Definition: ipsec_ctx.h:52
enum doca_flow_crypto_key_type key_type
Definition: ipsec_ctx.h:51
struct doca_flow_pipe * pipe
Definition: ipsec_ctx.h:73
char name[MAX_NAME_LEN+1]
Definition: ipsec_ctx.h:74
struct doca_flow_pipe_entry * entry
Definition: ipsec_ctx.h:75
struct doca_flow_pipe * pipe
Definition: ipsec_ctx.h:128
struct security_gateway_entry_info * entries_info
Definition: ipsec_ctx.h:130
struct doca_flow_port * ports[UPF_ACCEL_PORTS_MAX]
Definition: upf_accel.h:344
static struct doca_flow_port * ports[FLOW_SWITCH_PORTS_MAX]
Definition: switch_core.c:42
struct upf_accel_ctx * ctx