NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
flow_encrypt.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 
27 #include <doca_log.h>
28 #include <doca_bitfield.h>
29 
30 #include <pack.h>
31 #include <utils.h>
32 
33 #include "doca_flow.h"
34 #include "flow_encrypt.h"
35 
36 DOCA_LOG_REGISTER(IPSEC_SECURITY_GW::flow_encrypt);
37 
38 #define ENCAP_DST_IP_IDX_IP4 30 /* index in encap raw data for destination IPv4 */
39 #define ENCAP_DST_IP_IDX_IP6 38 /* index in encap raw data for destination IPv4 */
40 #define ENCAP_IP_ID_IDX_IP4 18 /* index in encap raw data for IPv4 ID */
41 #define ENCAP_IDX_SRC_MAC 6 /* index in encap raw data for source mac */
42 #define ENCAP_DST_UDP_PORT_IDX 2 /* index in encap raw data for UDP destination port */
43 #define ENCAP_ESP_SPI_IDX_TUNNEL_IP4 34 /* index in encap raw data for esp SPI in IPv4 tunnel */
44 #define ENCAP_ESP_SPI_IDX_TUNNEL_IP6 54 /* index in encap raw data for esp SPI in IPv6 tunnel */
45 #define ENCAP_ESP_SPI_IDX_TRANSPORT 0 /* index in encap raw data for esp SPI in transport mode*/
46 #define ENCAP_ESP_SPI_IDX_UDP_TRANSPORT 8 /* index in encap raw data for esp SPI in transport over UDP mode*/
47 #define ENCAP_ESP_SN_IDX_TUNNEL_IP4 38 /* index in encap raw data for esp SN in IPv4 tunnel */
48 #define ENCAP_ESP_SN_IDX_TUNNEL_IP6 58 /* index in encap raw data for esp SN in IPv6 tunnel */
49 #define ENCAP_ESP_SN_IDX_TRANSPORT 4 /* index in encap raw data for esp SN in transport mode*/
50 #define ENCAP_ESP_SN_IDX_UDP_TRANSPORT 12 /* index in encap raw data for esp SN in transport over UDP mode*/
51 
52 #define ENCAP_MARKER_HEADER_SIZE 8 /* non-ESP marker header size */
53 #define PADDING_ALIGN 4 /* padding alignment */
54 
55 static const uint8_t esp_pad_bytes[15] = {
56  1,
57  2,
58  3,
59  4,
60  5,
61  6,
62  7,
63  8,
64  9,
65  10,
66  11,
67  12,
68  13,
69  14,
70  15,
71 };
72 
73 static uint16_t current_ip_id; /* Incremented for each new packet */
74 
75 /*
76  * Create reformat data for encapsulation in transport mode, and copy it to reformat_data pointer
77  *
78  * @rule [in]: current rule for encapsulation
79  * @sw_sn_inc [in]: if true, sequence number will be incremented in software
80  * @reformat_data [out]: pointer to created data
81  * @reformat_data_sz [out]: data size
82  */
83 static void create_transport_encap(struct encrypt_rule *rule,
84  bool sw_sn_inc,
85  uint8_t *reformat_data,
86  uint16_t *reformat_data_sz)
87 {
88  uint8_t reformat_encap_data[16] = {
89  0x00,
90  0x00,
91  0x00,
92  0x00, /* SPI */
93  0x00,
94  0x00,
95  0x00,
96  0x00, /* SN */
97  0x00,
98  0x00,
99  0x00,
100  0x00, /* IV */
101  0x00,
102  0x00,
103  0x00,
104  0x00,
105  };
106 
107  reformat_encap_data[ENCAP_ESP_SPI_IDX_TRANSPORT] = GET_BYTE(rule->esp_spi, 3);
108  reformat_encap_data[ENCAP_ESP_SPI_IDX_TRANSPORT + 1] = GET_BYTE(rule->esp_spi, 2);
109  reformat_encap_data[ENCAP_ESP_SPI_IDX_TRANSPORT + 2] = GET_BYTE(rule->esp_spi, 1);
110  reformat_encap_data[ENCAP_ESP_SPI_IDX_TRANSPORT + 3] = GET_BYTE(rule->esp_spi, 0);
111 
112  if (sw_sn_inc == true) {
113  reformat_encap_data[ENCAP_ESP_SN_IDX_TRANSPORT] = GET_BYTE(rule->current_sn, 3);
114  reformat_encap_data[ENCAP_ESP_SN_IDX_TRANSPORT + 1] = GET_BYTE(rule->current_sn, 2);
115  reformat_encap_data[ENCAP_ESP_SN_IDX_TRANSPORT + 2] = GET_BYTE(rule->current_sn, 1);
116  reformat_encap_data[ENCAP_ESP_SN_IDX_TRANSPORT + 3] = GET_BYTE(rule->current_sn, 0);
117  }
118 
119  memcpy(reformat_data, reformat_encap_data, sizeof(reformat_encap_data));
120  *reformat_data_sz = sizeof(reformat_encap_data);
121 }
122 
123 /*
124  * Create reformat data for encapsulation in UDP transport mode, and copy it to reformat_data pointer
125  *
126  * @rule [in]: current rule for encapsulation
127  * @sw_sn_inc [in]: if true, sequence number will be incremented in software
128  * @reformat_data [out]: pointer to created data
129  * @reformat_data_sz [out]: data size
130  */
131 static void create_udp_transport_encap(struct encrypt_rule *rule,
132  bool sw_sn_inc,
133  uint8_t *reformat_data,
134  uint16_t *reformat_data_sz)
135 {
136  uint16_t udp_dst_port = 4500;
137  uint8_t reformat_encap_data[24] = {
138  0x30, 0x39, 0x00, 0x00, /* UDP src/dst */
139  0x00, 0xa4, 0x00, 0x00, /* USD sum/len */
140  0x00, 0x00, 0x00, 0x00, /* SPI */
141  0x00, 0x00, 0x00, 0x00, /* SN */
142  0x00, 0x00, 0x00, 0x00, /* IV */
143  0x00, 0x00, 0x00, 0x00,
144  };
145 
146  reformat_encap_data[ENCAP_ESP_SPI_IDX_UDP_TRANSPORT] = GET_BYTE(rule->esp_spi, 3);
147  reformat_encap_data[ENCAP_ESP_SPI_IDX_UDP_TRANSPORT + 1] = GET_BYTE(rule->esp_spi, 2);
148  reformat_encap_data[ENCAP_ESP_SPI_IDX_UDP_TRANSPORT + 2] = GET_BYTE(rule->esp_spi, 1);
149  reformat_encap_data[ENCAP_ESP_SPI_IDX_UDP_TRANSPORT + 3] = GET_BYTE(rule->esp_spi, 0);
150 
151  reformat_encap_data[ENCAP_DST_UDP_PORT_IDX] = GET_BYTE(udp_dst_port, 1);
152  reformat_encap_data[ENCAP_DST_UDP_PORT_IDX + 1] = GET_BYTE(udp_dst_port, 0);
153 
154  if (sw_sn_inc == true) {
155  reformat_encap_data[ENCAP_ESP_SN_IDX_UDP_TRANSPORT] = GET_BYTE(rule->current_sn, 3);
156  reformat_encap_data[ENCAP_ESP_SN_IDX_UDP_TRANSPORT + 1] = GET_BYTE(rule->current_sn, 2);
157  reformat_encap_data[ENCAP_ESP_SN_IDX_UDP_TRANSPORT + 2] = GET_BYTE(rule->current_sn, 1);
158  reformat_encap_data[ENCAP_ESP_SN_IDX_UDP_TRANSPORT + 3] = GET_BYTE(rule->current_sn, 0);
159  }
160 
161  memcpy(reformat_data, reformat_encap_data, sizeof(reformat_encap_data));
162  *reformat_data_sz = sizeof(reformat_encap_data);
163 }
164 
165 /*
166  * Create reformat data for encapsulation IPV4 tunnel, and copy it to reformat_data pointer
167  *
168  * @rule [in]: current rule for encapsulation
169  * @sw_sn_inc [in]: if true, sequence number will be incremented in software
170  * @eth_header [in]: contains the src mac address
171  * @reformat_data [out]: pointer to created data
172  * @reformat_data_sz [out]: data size
173  */
174 static void create_ipv4_tunnel_encap(struct encrypt_rule *rule,
175  bool sw_sn_inc,
176  struct doca_flow_header_eth *eth_header,
177  uint8_t *reformat_data,
178  uint16_t *reformat_data_sz)
179 {
180  uint8_t reformat_encap_data[50] = {
181  0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, /* mac_dst */
182  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* mac_src */
183  0x08, 0x00, /* mac_type */
184  0x45, 0x00, 0x00, 0x00, 0x00, 0x00, /* IPv4 - Part 1 */
185  0x00, 0x00, 0x00, 0x32, 0x00, 0x00, /* IPv4 - Part 2 */
186  0x02, 0x02, 0x02, 0x02, /* IP src */
187  0x00, 0x00, 0x00, 0x00, /* IP dst */
188  0x00, 0x00, 0x00, 0x00, /* SPI */
189  0x00, 0x00, 0x00, 0x00, /* SN */
190  0x00, 0x00, 0x00, 0x00, /* IV */
191  0x00, 0x00, 0x00, 0x00,
192  };
193 
194  reformat_encap_data[ENCAP_IDX_SRC_MAC] = eth_header->src_mac[0];
195  reformat_encap_data[ENCAP_IDX_SRC_MAC + 1] = eth_header->src_mac[1];
196  reformat_encap_data[ENCAP_IDX_SRC_MAC + 2] = eth_header->src_mac[2];
197  reformat_encap_data[ENCAP_IDX_SRC_MAC + 3] = eth_header->src_mac[3];
198  reformat_encap_data[ENCAP_IDX_SRC_MAC + 4] = eth_header->src_mac[4];
199  reformat_encap_data[ENCAP_IDX_SRC_MAC + 5] = eth_header->src_mac[5];
200 
201  /* dst IP was already converted to big endian */
202  reformat_encap_data[ENCAP_DST_IP_IDX_IP4] = GET_BYTE(rule->encap_dst_ip4, 0);
203  reformat_encap_data[ENCAP_DST_IP_IDX_IP4 + 1] = GET_BYTE(rule->encap_dst_ip4, 1);
204  reformat_encap_data[ENCAP_DST_IP_IDX_IP4 + 2] = GET_BYTE(rule->encap_dst_ip4, 2);
205  reformat_encap_data[ENCAP_DST_IP_IDX_IP4 + 3] = GET_BYTE(rule->encap_dst_ip4, 3);
206 
207  reformat_encap_data[ENCAP_ESP_SPI_IDX_TUNNEL_IP4] = GET_BYTE(rule->esp_spi, 3);
208  reformat_encap_data[ENCAP_ESP_SPI_IDX_TUNNEL_IP4 + 1] = GET_BYTE(rule->esp_spi, 2);
209  reformat_encap_data[ENCAP_ESP_SPI_IDX_TUNNEL_IP4 + 2] = GET_BYTE(rule->esp_spi, 1);
210  reformat_encap_data[ENCAP_ESP_SPI_IDX_TUNNEL_IP4 + 3] = GET_BYTE(rule->esp_spi, 0);
211 
212  reformat_encap_data[ENCAP_IP_ID_IDX_IP4] = GET_BYTE(current_ip_id, 1);
213  reformat_encap_data[ENCAP_IP_ID_IDX_IP4 + 1] = GET_BYTE(current_ip_id, 0);
214  ++current_ip_id;
215 
216  if (sw_sn_inc == true) {
217  reformat_encap_data[ENCAP_ESP_SN_IDX_TUNNEL_IP4] = GET_BYTE(rule->current_sn, 3);
218  reformat_encap_data[ENCAP_ESP_SN_IDX_TUNNEL_IP4 + 1] = GET_BYTE(rule->current_sn, 2);
219  reformat_encap_data[ENCAP_ESP_SN_IDX_TUNNEL_IP4 + 2] = GET_BYTE(rule->current_sn, 1);
220  reformat_encap_data[ENCAP_ESP_SN_IDX_TUNNEL_IP4 + 3] = GET_BYTE(rule->current_sn, 0);
221  }
222 
223  memcpy(reformat_data, reformat_encap_data, sizeof(reformat_encap_data));
224  *reformat_data_sz = sizeof(reformat_encap_data);
225 }
226 
227 /*
228  * Create reformat data for encapsulation IPV6 tunnel, and copy it to reformat_data pointer
229  *
230  * @rule [in]: current rule for encapsulation
231  * @sw_sn_inc [in]: if true, sequence number will be incremented in software
232  * @eth_header [in]: contains the src mac address
233  * @reformat_data [out]: pointer to created data
234  * @reformat_data_sz [out]: data size
235  */
236 static void create_ipv6_tunnel_encap(struct encrypt_rule *rule,
237  bool sw_sn_inc,
238  struct doca_flow_header_eth *eth_header,
239  uint8_t *reformat_data,
240  uint16_t *reformat_data_sz)
241 {
242  uint8_t reformat_encap_data[70] = {
243  0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, /* mac_dst */
244  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* mac_src */
245  0x86, 0xdd, /* mac_type */
246  0x60, 0x00, 0x00, 0x00, /* IPv6 - Part 1 */
247  0x00, 0x00, 0x32, 0x40, /* IPv6 - Part 2 */
248  0x02, 0x02, 0x02, 0x02, /* IP src */
249  0x02, 0x02, 0x02, 0x02, /* IP src */
250  0x02, 0x02, 0x02, 0x02, /* IP src */
251  0x02, 0x02, 0x02, 0x02, /* IP src */
252  0x01, 0x01, 0x01, 0x01, /* IP dst */
253  0x01, 0x01, 0x01, 0x01, /* IP dst */
254  0x01, 0x01, 0x01, 0x01, /* IP dst */
255  0x01, 0x01, 0x01, 0x01, /* IP dst */
256  0x00, 0x00, 0x00, 0x00, /* SPI */
257  0x00, 0x00, 0x00, 0x00, /* SN */
258  0x00, 0x00, 0x00, 0x00, /* IV */
259  0x00, 0x00, 0x00, 0x00,
260  };
261 
262  reformat_encap_data[ENCAP_IDX_SRC_MAC] = eth_header->src_mac[0];
263  reformat_encap_data[ENCAP_IDX_SRC_MAC + 1] = eth_header->src_mac[1];
264  reformat_encap_data[ENCAP_IDX_SRC_MAC + 2] = eth_header->src_mac[2];
265  reformat_encap_data[ENCAP_IDX_SRC_MAC + 3] = eth_header->src_mac[3];
266  reformat_encap_data[ENCAP_IDX_SRC_MAC + 4] = eth_header->src_mac[4];
267  reformat_encap_data[ENCAP_IDX_SRC_MAC + 5] = eth_header->src_mac[5];
268 
269  /* dst IP was already converted to big endian */
270  reformat_encap_data[ENCAP_DST_IP_IDX_IP6] = GET_BYTE(rule->encap_dst_ip6[0], 0);
271  reformat_encap_data[ENCAP_DST_IP_IDX_IP6 + 1] = GET_BYTE(rule->encap_dst_ip6[0], 1);
272  reformat_encap_data[ENCAP_DST_IP_IDX_IP6 + 2] = GET_BYTE(rule->encap_dst_ip6[0], 2);
273  reformat_encap_data[ENCAP_DST_IP_IDX_IP6 + 3] = GET_BYTE(rule->encap_dst_ip6[0], 3);
274  reformat_encap_data[ENCAP_DST_IP_IDX_IP6 + 4] = GET_BYTE(rule->encap_dst_ip6[1], 0);
275  reformat_encap_data[ENCAP_DST_IP_IDX_IP6 + 5] = GET_BYTE(rule->encap_dst_ip6[1], 1);
276  reformat_encap_data[ENCAP_DST_IP_IDX_IP6 + 6] = GET_BYTE(rule->encap_dst_ip6[1], 2);
277  reformat_encap_data[ENCAP_DST_IP_IDX_IP6 + 7] = GET_BYTE(rule->encap_dst_ip6[1], 3);
278  reformat_encap_data[ENCAP_DST_IP_IDX_IP6 + 8] = GET_BYTE(rule->encap_dst_ip6[2], 0);
279  reformat_encap_data[ENCAP_DST_IP_IDX_IP6 + 9] = GET_BYTE(rule->encap_dst_ip6[2], 1);
280  reformat_encap_data[ENCAP_DST_IP_IDX_IP6 + 10] = GET_BYTE(rule->encap_dst_ip6[2], 2);
281  reformat_encap_data[ENCAP_DST_IP_IDX_IP6 + 11] = GET_BYTE(rule->encap_dst_ip6[2], 3);
282  reformat_encap_data[ENCAP_DST_IP_IDX_IP6 + 12] = GET_BYTE(rule->encap_dst_ip6[3], 0);
283  reformat_encap_data[ENCAP_DST_IP_IDX_IP6 + 13] = GET_BYTE(rule->encap_dst_ip6[3], 1);
284  reformat_encap_data[ENCAP_DST_IP_IDX_IP6 + 14] = GET_BYTE(rule->encap_dst_ip6[3], 2);
285  reformat_encap_data[ENCAP_DST_IP_IDX_IP6 + 15] = GET_BYTE(rule->encap_dst_ip6[3], 3);
286 
287  reformat_encap_data[ENCAP_ESP_SPI_IDX_TUNNEL_IP6] = GET_BYTE(rule->esp_spi, 3);
288  reformat_encap_data[ENCAP_ESP_SPI_IDX_TUNNEL_IP6 + 1] = GET_BYTE(rule->esp_spi, 2);
289  reformat_encap_data[ENCAP_ESP_SPI_IDX_TUNNEL_IP6 + 2] = GET_BYTE(rule->esp_spi, 1);
290  reformat_encap_data[ENCAP_ESP_SPI_IDX_TUNNEL_IP6 + 3] = GET_BYTE(rule->esp_spi, 0);
291 
292  if (sw_sn_inc == true) {
293  reformat_encap_data[ENCAP_ESP_SN_IDX_TUNNEL_IP6] = GET_BYTE(rule->current_sn, 3);
294  reformat_encap_data[ENCAP_ESP_SN_IDX_TUNNEL_IP6 + 1] = GET_BYTE(rule->current_sn, 2);
295  reformat_encap_data[ENCAP_ESP_SN_IDX_TUNNEL_IP6 + 2] = GET_BYTE(rule->current_sn, 1);
296  reformat_encap_data[ENCAP_ESP_SN_IDX_TUNNEL_IP6 + 3] = GET_BYTE(rule->current_sn, 0);
297  }
298 
299  memcpy(reformat_data, reformat_encap_data, sizeof(reformat_encap_data));
300  *reformat_data_sz = sizeof(reformat_encap_data);
301 }
302 
303 /*
304  * Create egress IP classifier to choose to which encrypt pipe to forward the packet
305  *
306  * @port [in]: port of the pipe
307  * @is_root [in]: true for vnf mode
308  * @debug_mode [in]: true for vnf mode
309  * @encrypt_pipes [in]: all the encrypt pipes
310  * @app_cfg [in]: application configuration struct
311  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
312  */
313 static doca_error_t create_egress_ip_classifier(struct doca_flow_port *port,
314  bool is_root,
315  bool debug_mode,
318 {
319  struct doca_flow_match match;
320  struct doca_flow_monitor monitor;
321  struct doca_flow_fwd fwd;
322  struct doca_flow_pipe_cfg *pipe_cfg;
324  struct doca_flow_pipe_entry **entry = NULL;
326  int num_of_entries = 2;
327 
328  memset(&match, 0, sizeof(match));
329  memset(&monitor, 0, sizeof(monitor));
330  memset(&fwd, 0, sizeof(fwd));
331  memset(&app_cfg->secured_status[0], 0, sizeof(app_cfg->secured_status[0]));
332 
333  match.parser_meta.outer_l3_type = UINT32_MAX;
334  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
335  if (result != DOCA_SUCCESS) {
336  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
337  return result;
338  }
339 
340  result = doca_flow_pipe_cfg_set_name(pipe_cfg, "IP_CLASSIFIER_PIPE");
341  if (result != DOCA_SUCCESS) {
342  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
343  goto destroy_pipe_cfg;
344  }
346  if (result != DOCA_SUCCESS) {
347  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg type: %s", doca_error_get_descr(result));
348  goto destroy_pipe_cfg;
349  }
350  result = doca_flow_pipe_cfg_set_is_root(pipe_cfg, is_root);
351  if (result != DOCA_SUCCESS) {
352  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg is_root: %s", doca_error_get_descr(result));
353  goto destroy_pipe_cfg;
354  }
356  if (result != DOCA_SUCCESS) {
357  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg domain: %s", doca_error_get_descr(result));
358  goto destroy_pipe_cfg;
359  }
361  if (result != DOCA_SUCCESS) {
362  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg dir_info: %s", doca_error_get_descr(result));
363  goto destroy_pipe_cfg;
364  }
365  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
366  if (result != DOCA_SUCCESS) {
367  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
368  goto destroy_pipe_cfg;
369  }
370  if (debug_mode) {
373  if (result != DOCA_SUCCESS) {
374  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
375  goto destroy_pipe_cfg;
376  }
377  }
378 
380 
381  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, &pipe->pipe);
382  if (result != DOCA_SUCCESS) {
383  DOCA_LOG_ERR("Failed to create IP classifier pipe: %s", doca_error_get_descr(result));
384  goto destroy_pipe_cfg;
385  }
386 
387  doca_flow_pipe_cfg_destroy(pipe_cfg);
388 
389  if (debug_mode) {
390  pipe->entries_info =
391  (struct security_gateway_entry_info *)calloc(2, sizeof(struct security_gateway_entry_info));
392  if (pipe->entries_info == NULL) {
393  DOCA_LOG_ERR("Failed to allocate entries array");
394  return DOCA_ERROR_NO_MEMORY;
395  }
396  }
397 
400 
401  if (debug_mode) {
402  snprintf(pipe->entries_info[pipe->nb_entries].name, MAX_NAME_LEN, "IPv4");
403  entry = &pipe->entries_info[pipe->nb_entries++].entry;
404  }
406  pipe->pipe,
407  &match,
408  NULL,
409  NULL,
410  &fwd,
412  &app_cfg->secured_status[0],
413  entry);
414  if (result != DOCA_SUCCESS) {
415  DOCA_LOG_ERR("Failed to add ipv4 entry: %s", doca_error_get_descr(result));
416  return result;
417  }
418 
421 
422  if (debug_mode) {
423  snprintf(pipe->entries_info[pipe->nb_entries].name, MAX_NAME_LEN, "IPv6");
424  entry = &pipe->entries_info[pipe->nb_entries++].entry;
425  }
427  pipe->pipe,
428  &match,
429  NULL,
430  NULL,
431  &fwd,
433  &app_cfg->secured_status[0],
434  entry);
435  if (result != DOCA_SUCCESS) {
436  DOCA_LOG_ERR("Failed to add ipv6 entry: %s", doca_error_get_descr(result));
437  return result;
438  }
439 
440  result = doca_flow_entries_process(port, 0, DEFAULT_TIMEOUT_US, num_of_entries);
441  if (result != DOCA_SUCCESS)
442  return result;
443  if (app_cfg->secured_status[0].nb_processed != num_of_entries || app_cfg->secured_status[0].failure)
444  return DOCA_ERROR_BAD_STATE;
445 
446  return DOCA_SUCCESS;
447 
449  doca_flow_pipe_cfg_destroy(pipe_cfg);
450  return result;
451 }
452 
453 /*
454  * Add vxlan encap pipe entry
455  *
456  * @port [in]: port of the pipe
457  * @pipe [in]: pipe to add entry
458  * @app_cfg [in]: application configuration struct
459  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
460  */
461 static doca_error_t add_vxlan_encap_pipe_entry(struct doca_flow_port *port,
462  struct security_gateway_pipe_info *pipe,
464 {
465  int num_of_entries = 1;
466  struct doca_flow_match match;
467  struct doca_flow_actions actions;
468  struct doca_flow_pipe_entry **entry = NULL;
470 
471  memset(&match, 0, sizeof(match));
472  memset(&actions, 0, sizeof(actions));
473  memset(&app_cfg->secured_status[0], 0, sizeof(app_cfg->secured_status[0]));
474 
475  if (app_cfg->debug_mode) {
476  pipe->entries_info =
477  (struct security_gateway_entry_info *)calloc(1, sizeof(struct security_gateway_entry_info));
478  if (pipe->entries_info == NULL) {
479  DOCA_LOG_ERR("Failed to allocate entries array");
480  return DOCA_ERROR_NO_MEMORY;
481  }
482  snprintf(pipe->entries_info[pipe->nb_entries].name, MAX_NAME_LEN, "vxlan_encap");
483  entry = &pipe->entries_info[pipe->nb_entries++].entry;
484  }
485 
486  SET_MAC_ADDR(actions.encap_cfg.encap.outer.eth.src_mac, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66);
487  SET_MAC_ADDR(actions.encap_cfg.encap.outer.eth.dst_mac, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff);
495 
497  pipe->pipe,
498  &match,
499  &actions,
500  NULL,
501  NULL,
503  &app_cfg->secured_status[0],
504  entry);
505  if (result != DOCA_SUCCESS) {
506  DOCA_LOG_ERR("Failed to add ipv4 entry: %s", doca_error_get_descr(result));
507  return result;
508  }
509 
510  result = doca_flow_entries_process(port, 0, DEFAULT_TIMEOUT_US, num_of_entries);
511  if (result != DOCA_SUCCESS)
512  return result;
513  if (app_cfg->secured_status[0].nb_processed != num_of_entries || app_cfg->secured_status[0].failure)
514  return DOCA_ERROR_BAD_STATE;
515 
516  return DOCA_SUCCESS;
517 }
518 
519 /*
520  * Create vxlan encap pipe
521  *
522  * @port [in]: port of the pipe
523  * @port_id [in]: port ID to forward the packet to
524  * @app_cfg [in]: application configuration struct
525  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
526  */
527 static doca_error_t create_vxlan_encap_pipe(struct doca_flow_port *port,
528  int port_id,
530 {
531  int nb_actions = 1;
532  struct security_gateway_pipe_info *pipe = &app_cfg->encrypt_pipes.vxlan_encap_pipe;
533  struct doca_flow_actions actions, *actions_arr[nb_actions];
534  struct doca_flow_match match;
535  struct doca_flow_monitor monitor;
536  struct doca_flow_fwd fwd;
537  struct doca_flow_pipe_cfg *pipe_cfg;
539 
540  memset(&match, 0, sizeof(match));
541  memset(&monitor, 0, sizeof(monitor));
542  memset(&actions, 0, sizeof(actions));
543  memset(&fwd, 0, sizeof(fwd));
544 
546  actions.encap_cfg.is_l2 = true;
547  SET_MAC_ADDR(actions.encap_cfg.encap.outer.eth.src_mac, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
548  SET_MAC_ADDR(actions.encap_cfg.encap.outer.eth.dst_mac, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
550  actions.encap_cfg.encap.outer.ip4.src_ip = 0xffffffff;
551  actions.encap_cfg.encap.outer.ip4.dst_ip = 0xffffffff;
557  actions.encap_cfg.encap.tun.vxlan_tun_id = 0xffffffff;
558  actions_arr[0] = &actions;
559 
560  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
561  if (result != DOCA_SUCCESS) {
562  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
563  return result;
564  }
565 
566  result = doca_flow_pipe_cfg_set_name(pipe_cfg, "VXLAN_ENCAP_PIPE");
567  if (result != DOCA_SUCCESS) {
568  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
569  goto destroy_pipe_cfg;
570  }
572  if (result != DOCA_SUCCESS) {
573  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg type: %s", doca_error_get_descr(result));
574  goto destroy_pipe_cfg;
575  }
577  if (result != DOCA_SUCCESS) {
578  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg domain: %s", doca_error_get_descr(result));
579  goto destroy_pipe_cfg;
580  }
581  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
582  if (result != DOCA_SUCCESS) {
583  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
584  goto destroy_pipe_cfg;
585  }
586  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, NULL, nb_actions);
587  if (result != DOCA_SUCCESS) {
588  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
589  goto destroy_pipe_cfg;
590  }
591 
592  if (app_cfg->debug_mode) {
595  if (result != DOCA_SUCCESS) {
596  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
597  goto destroy_pipe_cfg;
598  }
599  }
601  fwd.port_id = port_id;
602 
603  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, &pipe->pipe);
604  if (result != DOCA_SUCCESS) {
605  DOCA_LOG_ERR("Failed to create vxlan encap pipe: %s", doca_error_get_descr(result));
606  goto destroy_pipe_cfg;
607  }
608 
609  doca_flow_pipe_cfg_destroy(pipe_cfg);
610  return add_vxlan_encap_pipe_entry(port, pipe, app_cfg);
611 
613  doca_flow_pipe_cfg_destroy(pipe_cfg);
614  return result;
615 }
616 
617 /*
618  * Create egress pipe to insert non-ESP marker header and forward to specified port
619  *
620  * @port [in]: port of the pipe
621  * @port_id [in]: port ID to forward the packet to
622  * @app_cfg [in]: application configuration struct
623  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
624  */
625 static doca_error_t create_marker_encap_pipe(struct doca_flow_port *port,
626  uint16_t port_id,
628 {
629  int nb_actions = 1;
630  struct doca_flow_match match;
632  struct doca_flow_monitor monitor;
633  struct doca_flow_actions actions, actions_arr[nb_actions];
634  struct doca_flow_actions *actions_list[] = {&actions_arr[0]};
635  struct doca_flow_fwd fwd;
636  struct doca_flow_pipe_cfg *pipe_cfg;
637  struct security_gateway_pipe_info *pipe_info = &app_cfg->encrypt_pipes.marker_insert_pipe;
638  struct doca_flow_pipe_entry *entry = NULL;
640 
643  return DOCA_SUCCESS;
644  }
645 
646  memset(&match, 0, sizeof(match));
647  memset(&match_mask, 0, sizeof(match_mask));
648  memset(&monitor, 0, sizeof(monitor));
649  memset(&actions, 0, sizeof(actions));
650  memset(&fwd, 0, sizeof(fwd));
651  memset(&app_cfg->secured_status[0], 0, sizeof(app_cfg->secured_status[0]));
652 
653  actions.has_crypto_encap = true;
656 
657  actions_arr[0] = actions;
658  memset(actions_arr[0].crypto_encap.encap_data, 0, ENCAP_MARKER_HEADER_SIZE);
660 
661  strcpy(pipe_info->name, "MARKER_ENCAP_PIPE");
662  pipe_info->nb_entries = 0;
663 
664  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
665  if (result != DOCA_SUCCESS) {
666  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
667  return result;
668  }
669  result = doca_flow_pipe_cfg_set_name(pipe_cfg, pipe_info->name);
670  if (result != DOCA_SUCCESS) {
671  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
672  goto destroy_pipe_cfg;
673  }
675  if (result != DOCA_SUCCESS) {
676  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg type: %s", doca_error_get_descr(result));
677  goto destroy_pipe_cfg;
678  }
680  if (result != DOCA_SUCCESS) {
681  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg domain: %s", doca_error_get_descr(result));
682  goto destroy_pipe_cfg;
683  }
685  if (result != DOCA_SUCCESS) {
686  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg dir_info: %s", doca_error_get_descr(result));
687  goto destroy_pipe_cfg;
688  }
690  if (result != DOCA_SUCCESS) {
691  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg nr_entries: %s", doca_error_get_descr(result));
692  goto destroy_pipe_cfg;
693  }
694  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, &match_mask);
695  if (result != DOCA_SUCCESS) {
696  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
697  goto destroy_pipe_cfg;
698  }
699  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_list, NULL, NULL, 1);
700  if (result != DOCA_SUCCESS) {
701  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
702  goto destroy_pipe_cfg;
703  }
704 
705  if (app_cfg->debug_mode) {
708  if (result != DOCA_SUCCESS) {
709  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
710  goto destroy_pipe_cfg;
711  }
712  }
713 
715  fwd.port_id = port_id;
716 
718  if (result != DOCA_SUCCESS) {
719  DOCA_LOG_ERR("Failed to create non-ESP marker encap pipe: %s", doca_error_get_descr(result));
720  goto destroy_pipe_cfg;
721  }
722 
723  if (app_cfg->debug_mode) {
724  pipe_info->entries_info =
725  (struct security_gateway_entry_info *)calloc(1, sizeof(struct security_gateway_entry_info));
726 
727  if (pipe_info->entries_info == NULL) {
728  DOCA_LOG_ERR("Failed to allocate entries array");
730  goto destroy_pipe_cfg;
731  }
732  }
733 
735  pipe_info->pipe,
736  &match,
737  NULL,
738  NULL,
739  &fwd,
741  &app_cfg->secured_status[0],
742  &entry);
743  if (result != DOCA_SUCCESS) {
744  DOCA_LOG_ERR("Failed to add non-ESP marker encap entry: %s", doca_error_get_descr(result));
745  goto destroy_pipe_cfg;
746  }
747 
749  if (result != DOCA_SUCCESS)
750  goto destroy_pipe_cfg;
751 
752  if (app_cfg->secured_status[0].nb_processed != 1 || app_cfg->secured_status[0].failure)
754 
755  if (result == DOCA_SUCCESS && pipe_info->entries_info != NULL) {
756  snprintf(pipe_info->entries_info[pipe_info->nb_entries].name, MAX_NAME_LEN, "marker_encap");
757  pipe_info->entries_info[pipe_info->nb_entries++].entry = entry;
758  }
759 
761  doca_flow_pipe_cfg_destroy(pipe_cfg);
762  return result;
763 }
764 
765 /*
766  * Create ipsec encrypt pipe changeable meta data match and changeable shared IPSEC encryption object
767  *
768  * @port [in]: port of the pipe
769  * @port_id [in]: port ID to forward the packet to
770  * @expected_entries [in]: expected number of entries
771  * @app_cfg [in]: application configuration struct
772  * @l3_type [in]: DOCA_FLOW_L3_META_IPV4 / DOCA_FLOW_L3_META_IPV6
773  * @pipe_info [out]: pipe info struct
774  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
775  */
776 static doca_error_t create_ipsec_encrypt_pipe(struct doca_flow_port *port,
777  uint16_t port_id,
778  int expected_entries,
780  enum doca_flow_l3_meta l3_type,
782 {
783  int nb_actions = 2;
784  struct doca_flow_match match;
786  struct doca_flow_monitor monitor;
787  struct doca_flow_actions actions, actions_arr[nb_actions];
788  struct doca_flow_fwd fwd;
789  struct doca_flow_pipe_cfg *pipe_cfg;
791  union security_gateway_pkt_meta meta = {0};
792 
793  memset(&match, 0, sizeof(match));
794  memset(&match_mask, 0, sizeof(match_mask));
795  memset(&monitor, 0, sizeof(monitor));
796  memset(&actions, 0, sizeof(actions));
797  memset(&fwd, 0, sizeof(fwd));
798 
799  meta.rule_id = -1;
801  match.meta.pkt_meta = 0xffffffff;
803  match.parser_meta.outer_l3_type = l3_type;
804 
807  actions.has_crypto_encap = true;
808 
812  if (!app_cfg->sw_sn_inc_enable) {
813  actions.crypto.ipsec_sa.sn_en = !app_cfg->sw_sn_inc_enable;
814  }
816  actions.crypto.crypto_id = UINT32_MAX;
817 
818  if (app_cfg->mode == IPSEC_SECURITY_GW_TUNNEL) {
820  actions_arr[0] = actions;
821  actions_arr[1] = actions;
822  /* action idx 0 will add encap ipv4 */
823  memset(actions_arr[0].crypto_encap.encap_data, 0xff, 50);
824  actions_arr[0].crypto_encap.data_size = 50;
825  /* action idx 1 will add encap ipv6 */
826  memset(actions_arr[1].crypto_encap.encap_data, 0xff, 70);
827  actions_arr[1].crypto_encap.data_size = 70;
828  } else if (app_cfg->mode == IPSEC_SECURITY_GW_TRANSPORT) {
832  memset(actions.crypto_encap.encap_data, 0xff, 16);
834  actions_arr[0] = actions;
835  } else {
839  memset(actions.crypto_encap.encap_data, 0xff, 24);
841  actions_arr[0] = actions;
842  }
843 
844  struct doca_flow_actions *actions_list[] = {&actions_arr[0], &actions_arr[1]};
845 
846  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
847  if (result != DOCA_SUCCESS) {
848  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
849  return result;
850  }
851 
852  result = doca_flow_pipe_cfg_set_name(pipe_cfg, "ENCRYPT_PIPE");
853  if (result != DOCA_SUCCESS) {
854  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
855  goto destroy_pipe_cfg;
856  }
858  if (result != DOCA_SUCCESS) {
859  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg type: %s", doca_error_get_descr(result));
860  goto destroy_pipe_cfg;
861  }
863  if (result != DOCA_SUCCESS) {
864  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg domain: %s", doca_error_get_descr(result));
865  goto destroy_pipe_cfg;
866  }
868  if (result != DOCA_SUCCESS) {
869  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg dir_info: %s", doca_error_get_descr(result));
870  goto destroy_pipe_cfg;
871  }
872  result = doca_flow_pipe_cfg_set_nr_entries(pipe_cfg, expected_entries);
873  if (result != DOCA_SUCCESS) {
874  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg nr_entries: %s", doca_error_get_descr(result));
875  goto destroy_pipe_cfg;
876  }
877  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, &match_mask);
878  if (result != DOCA_SUCCESS) {
879  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
880  goto destroy_pipe_cfg;
881  }
882  /* 2 actions only in tunnel mode */
883  result =
885  actions_list,
886  NULL,
887  NULL,
888  app_cfg->mode == IPSEC_SECURITY_GW_TUNNEL ? nb_actions : nb_actions - 1);
889  if (result != DOCA_SUCCESS) {
890  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
891  goto destroy_pipe_cfg;
892  }
893  if (app_cfg->debug_mode) {
896  if (result != DOCA_SUCCESS) {
897  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
898  goto destroy_pipe_cfg;
899  }
900  }
901 
902  if (!app_cfg->vxlan_encap) {
903  if (app_cfg->marker_encap && app_cfg->encrypt_pipes.marker_insert_pipe.pipe != NULL) {
905  fwd.next_pipe = app_cfg->encrypt_pipes.marker_insert_pipe.pipe;
906  } else {
908  fwd.port_id = port_id;
909  }
910  } else {
912  fwd.next_pipe = app_cfg->encrypt_pipes.vxlan_encap_pipe.pipe;
913  }
914 
916  if (result != DOCA_SUCCESS) {
917  DOCA_LOG_ERR("Failed to create encrypt pipe: %s", doca_error_get_descr(result));
918  goto destroy_pipe_cfg;
919  }
920 
921  if (app_cfg->debug_mode) {
922  pipe_info->entries_info =
923  (struct security_gateway_entry_info *)calloc(expected_entries,
924  sizeof(struct security_gateway_entry_info));
925  if (pipe_info->entries_info == NULL) {
926  DOCA_LOG_ERR("Failed to allocate entries array");
928  }
929  }
930 
932  doca_flow_pipe_cfg_destroy(pipe_cfg);
933  return result;
934 }
935 
936 /*
937  * Create pipe with source ipv6 match, and fwd to the hairpin pipe
938  *
939  * @port [in]: port of the pipe
940  * @debug_mode [in]: true if running in debug mode
941  * @expected_entries [in]: expected number of entries
942  * @protocol_type [in]: DOCA_FLOW_L4_TYPE_EXT_TCP / DOCA_FLOW_L4_TYPE_EXT_UDP
943  * @hairpin_pipe [in]: pipe to forward the packets
944  * @pipe_info [out]: pipe info struct
945  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
946  */
947 static doca_error_t create_ipsec_src_ip6_pipe(struct doca_flow_port *port,
948  bool debug_mode,
949  int expected_entries,
950  enum doca_flow_l4_type_ext protocol_type,
951  struct doca_flow_pipe *hairpin_pipe,
953 {
954  int nb_actions = 1;
955  struct doca_flow_match match;
956  struct doca_flow_monitor monitor;
957  struct doca_flow_fwd fwd;
958  struct doca_flow_actions actions, *actions_arr[nb_actions];
959  struct doca_flow_pipe_cfg *pipe_cfg;
961 
962  memset(&match, 0, sizeof(match));
963  memset(&monitor, 0, sizeof(monitor));
964  memset(&fwd, 0, sizeof(fwd));
965  memset(&actions, 0, sizeof(actions));
966 
971  SET_IP6_ADDR(match.outer.ip6.src_ip, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
972 
973  actions.meta.u32[0] = UINT32_MAX;
974  actions_arr[0] = &actions;
975 
976  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
977  if (result != DOCA_SUCCESS) {
978  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
979  return result;
980  }
981 
982  result = doca_flow_pipe_cfg_set_name(pipe_cfg, "SRC_IP6_PIPE");
983  if (result != DOCA_SUCCESS) {
984  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
985  goto destroy_pipe_cfg;
986  }
988  if (result != DOCA_SUCCESS) {
989  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg type: %s", doca_error_get_descr(result));
990  goto destroy_pipe_cfg;
991  }
992  result = doca_flow_pipe_cfg_set_is_root(pipe_cfg, false);
993  if (result != DOCA_SUCCESS) {
994  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg is_root: %s", doca_error_get_descr(result));
995  goto destroy_pipe_cfg;
996  }
997  result = doca_flow_pipe_cfg_set_nr_entries(pipe_cfg, expected_entries);
998  if (result != DOCA_SUCCESS) {
999  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg nr_entries: %s", doca_error_get_descr(result));
1000  goto destroy_pipe_cfg;
1001  }
1002  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
1003  if (result != DOCA_SUCCESS) {
1004  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
1005  goto destroy_pipe_cfg;
1006  }
1007  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, NULL, nb_actions);
1008  if (result != DOCA_SUCCESS) {
1009  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
1010  goto destroy_pipe_cfg;
1011  }
1012  if (debug_mode) {
1015  if (result != DOCA_SUCCESS) {
1016  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
1017  goto destroy_pipe_cfg;
1018  }
1019  }
1020 
1022  fwd.next_pipe = hairpin_pipe;
1023 
1024  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, &pipe_info->pipe);
1025  if (result != DOCA_SUCCESS) {
1026  DOCA_LOG_ERR("Failed to create hairpin pipe: %s", doca_error_get_descr(result));
1027  goto destroy_pipe_cfg;
1028  }
1029 
1030  if (debug_mode) {
1031  pipe_info->entries_info =
1032  (struct security_gateway_entry_info *)calloc(expected_entries,
1033  sizeof(struct security_gateway_entry_info));
1034  if (pipe_info->entries_info == NULL) {
1035  DOCA_LOG_ERR("Failed to allocate entries array");
1037  }
1038  }
1039 
1041  doca_flow_pipe_cfg_destroy(pipe_cfg);
1042  return result;
1043 }
1044 
1045 /*
1046  * Create pipe with 5 tuple match, changeable set meta, and fwd to the second port
1047  *
1048  * @port [in]: port of the pipe
1049  * @debug_mode [in]: true if running in debug mode
1050  * @expected_entries [in]: expected number of entries
1051  * @protocol_type [in]: DOCA_FLOW_L4_TYPE_EXT_TCP / DOCA_FLOW_L4_TYPE_EXT_UDP
1052  * @l3_type [in]: DOCA_FLOW_L3_TYPE_IP4 / DOCA_FLOW_L3_TYPE_IP6
1053  * @fwd [in]: pointer to forward struct
1054  * @pipe_info [out]: pipe info struct
1055  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1056  */
1057 static doca_error_t create_ipsec_hairpin_pipe(struct doca_flow_port *port,
1058  bool debug_mode,
1059  int expected_entries,
1060  enum doca_flow_l4_type_ext protocol_type,
1061  enum doca_flow_l3_type l3_type,
1062  struct doca_flow_fwd *fwd,
1064 {
1065  int nb_actions = 1;
1066  struct doca_flow_match match;
1067  struct doca_flow_monitor monitor;
1068  struct doca_flow_actions actions, *actions_arr[nb_actions];
1069  struct doca_flow_pipe_cfg *pipe_cfg;
1071 
1072  memset(&match, 0, sizeof(match));
1073  memset(&monitor, 0, sizeof(monitor));
1074  memset(&actions, 0, sizeof(actions));
1075 
1076  match.outer.l4_type_ext = protocol_type;
1077  match.outer.l3_type = l3_type;
1078  if (l3_type == DOCA_FLOW_L3_TYPE_IP4) {
1079  match.outer.ip4.dst_ip = 0xffffffff;
1080  match.outer.ip4.src_ip = 0xffffffff;
1081  } else {
1082  match.meta.u32[0] = UINT32_MAX;
1083  SET_IP6_ADDR(match.outer.ip6.dst_ip, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
1084  }
1085 
1086  SET_L4_PORT(outer, src_port, 0xffff);
1087  SET_L4_PORT(outer, dst_port, 0xffff);
1088 
1089  actions.meta.pkt_meta = 0xffffffff;
1090  actions_arr[0] = &actions;
1091 
1092  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
1093  if (result != DOCA_SUCCESS) {
1094  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
1095  return result;
1096  }
1097 
1098  result = doca_flow_pipe_cfg_set_name(pipe_cfg, "HAIRPIN_PIPE");
1099  if (result != DOCA_SUCCESS) {
1100  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
1101  goto destroy_pipe_cfg;
1102  }
1104  if (result != DOCA_SUCCESS) {
1105  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg type: %s", doca_error_get_descr(result));
1106  goto destroy_pipe_cfg;
1107  }
1108  result = doca_flow_pipe_cfg_set_is_root(pipe_cfg, false);
1109  if (result != DOCA_SUCCESS) {
1110  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg is_root: %s", doca_error_get_descr(result));
1111  goto destroy_pipe_cfg;
1112  }
1113  result = doca_flow_pipe_cfg_set_nr_entries(pipe_cfg, expected_entries);
1114  if (result != DOCA_SUCCESS) {
1115  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg nr_entries: %s", doca_error_get_descr(result));
1116  goto destroy_pipe_cfg;
1117  }
1118  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, &match);
1119  if (result != DOCA_SUCCESS) {
1120  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
1121  goto destroy_pipe_cfg;
1122  }
1123  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, NULL, nb_actions);
1124  if (result != DOCA_SUCCESS) {
1125  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
1126  goto destroy_pipe_cfg;
1127  }
1128  if (debug_mode) {
1131  if (result != DOCA_SUCCESS) {
1132  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
1133  goto destroy_pipe_cfg;
1134  }
1135  }
1136 
1138  if (result != DOCA_SUCCESS) {
1139  DOCA_LOG_ERR("Failed to create hairpin pipe: %s", doca_error_get_descr(result));
1140  goto destroy_pipe_cfg;
1141  }
1142 
1143  if (debug_mode) {
1144  pipe_info->entries_info =
1145  (struct security_gateway_entry_info *)calloc(expected_entries,
1146  sizeof(struct security_gateway_entry_info));
1147  if (pipe_info->entries_info == NULL) {
1148  DOCA_LOG_ERR("Failed to allocate entries array");
1150  }
1151  }
1152 
1154  doca_flow_pipe_cfg_destroy(pipe_cfg);
1155  return result;
1156 }
1157 
1158 /*
1159  * Create control pipe for unsecured port
1160  *
1161  * @port [in]: port of the pipe
1162  * @is_root [in]: true in vnf mode
1163  * @debug_mode [in]: true if running in debug mode
1164  * @pipe_info [out]: pipe info struct
1165  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1166  */
1167 static doca_error_t create_control_pipe(struct doca_flow_port *port,
1168  bool is_root,
1169  bool debug_mode,
1171 {
1172  struct doca_flow_pipe_cfg *pipe_cfg;
1174 
1175  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
1176  if (result != DOCA_SUCCESS) {
1177  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
1178  return result;
1179  }
1180 
1181  result = doca_flow_pipe_cfg_set_name(pipe_cfg, "CONTROL_PIPE");
1182  if (result != DOCA_SUCCESS) {
1183  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
1184  goto destroy_pipe_cfg;
1185  }
1187  if (result != DOCA_SUCCESS) {
1188  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg type: %s", doca_error_get_descr(result));
1189  goto destroy_pipe_cfg;
1190  }
1191  result = doca_flow_pipe_cfg_set_is_root(pipe_cfg, is_root);
1192  if (result != DOCA_SUCCESS) {
1193  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg is_root: %s", doca_error_get_descr(result));
1194  goto destroy_pipe_cfg;
1195  }
1196 
1198  if (result != DOCA_SUCCESS) {
1199  DOCA_LOG_ERR("Failed to create control pipe: %s", doca_error_get_descr(result));
1200  goto destroy_pipe_cfg;
1201  }
1202 
1203  if (debug_mode) {
1204  pipe_info->entries_info =
1205  (struct security_gateway_entry_info *)calloc(4, sizeof(struct security_gateway_entry_info));
1206  if (pipe_info->entries_info == NULL) {
1207  DOCA_LOG_ERR("Failed to allocate entries array");
1209  }
1210  }
1211 
1213  doca_flow_pipe_cfg_destroy(pipe_cfg);
1214  return result;
1215 }
1216 
1217 /*
1218  * Check if BW perf is enabled
1219  *
1220  * @app_cfg [in]: application configuration struct
1221  * @return: true if BW perf is enabled.
1222  */
1223 static inline bool is_perf_bw(struct ipsec_security_gw_config *app_cfg)
1224 {
1225  return (app_cfg->perf_measurement == IPSEC_SECURITY_GW_PERF_BW ||
1226  app_cfg->perf_measurement == IPSEC_SECURITY_GW_PERF_BOTH);
1227 }
1228 
1229 /*
1230  * Add control pipe entries
1231  * - entry that forwards IPv4 TCP traffic to IPv4 TCP pipe,
1232  * - entry that forwards IPv4 UDP traffic to IPv4 UDP pipe,
1233  * - entry that forwards IPv6 TCP traffic to source IPv6 TCP pipe,
1234  * - entry that forwards IPv6 UDP traffic to source IPv6 UDP pipe,
1235  * - entry with lower priority that drop the packets
1236  *
1237  * @control_pipe [in]: control pipe pointer
1238  * @pipes [in]: all the pipes to forward the packets to
1239  * @perf_bw [in]: true if perf mode includes bandwidth
1240  * @debug_mode [in]: true if running in debug mode
1241  * @is_root [in]: true in vnf mode
1242  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1243  */
1245  struct encrypt_pipes *pipes,
1246  bool perf_bw,
1247  bool debug_mode,
1248  bool is_root)
1249 {
1250  struct doca_flow_pipe_entry **entry = NULL;
1251  struct doca_flow_monitor monitor;
1252  struct doca_flow_monitor *monitor_ptr = NULL;
1253  struct doca_flow_match match;
1254  struct doca_flow_fwd fwd;
1255 
1257 
1258  memset(&match, 0, sizeof(match));
1259  memset(&monitor, 0, sizeof(monitor));
1260  memset(&fwd, 0, sizeof(fwd));
1261 
1262  if (debug_mode && !is_root) {
1264  monitor_ptr = &monitor;
1265  }
1266 
1267  if (is_root) {
1268  match.outer.eth.type = rte_cpu_to_be_16(DOCA_FLOW_ETHER_TYPE_IPV4);
1271  } else {
1274  }
1275 
1277  fwd.next_pipe = pipes->ipv4_tcp_pipe.pipe;
1278  if (debug_mode) {
1279  snprintf(control_pipe->entries_info[control_pipe->nb_entries].name, MAX_NAME_LEN, "ipv4_tcp");
1280  entry = &control_pipe->entries_info[control_pipe->nb_entries++].entry;
1281  }
1283  0,
1284  control_pipe->pipe,
1285  &match,
1286  NULL,
1287  NULL,
1288  NULL,
1289  NULL,
1290  NULL,
1291  monitor_ptr,
1292  &fwd,
1293  NULL,
1294  entry);
1295  if (result != DOCA_SUCCESS) {
1296  DOCA_LOG_ERR("Failed to add TCP IPv4 control entry: %s", doca_error_get_descr(result));
1297  return result;
1298  }
1299 
1300  memset(&match, 0, sizeof(match));
1301  if (is_root) {
1302  match.outer.eth.type = rte_cpu_to_be_16(DOCA_FLOW_ETHER_TYPE_IPV4);
1305  } else {
1308  }
1309 
1311  fwd.next_pipe = pipes->ipv4_udp_pipe.pipe;
1312  if (debug_mode) {
1313  snprintf(control_pipe->entries_info[control_pipe->nb_entries].name, MAX_NAME_LEN, "ipv4_udp");
1314  entry = &control_pipe->entries_info[control_pipe->nb_entries++].entry;
1315  }
1317  0,
1318  control_pipe->pipe,
1319  &match,
1320  NULL,
1321  NULL,
1322  NULL,
1323  NULL,
1324  NULL,
1325  monitor_ptr,
1326  &fwd,
1327  NULL,
1328  entry);
1329  if (result != DOCA_SUCCESS) {
1330  DOCA_LOG_ERR("Failed to add UDP IPv4 control entry: %s", doca_error_get_descr(result));
1331  return result;
1332  }
1333  memset(&match, 0, sizeof(match));
1334  if (is_root) {
1335  match.outer.eth.type = rte_cpu_to_be_16(DOCA_FLOW_ETHER_TYPE_IPV6);
1338  } else {
1341  }
1342 
1344  if (!perf_bw)
1346  else
1347  fwd.next_pipe = pipes->ipv6_tcp_pipe.pipe;
1348  if (debug_mode) {
1349  snprintf(control_pipe->entries_info[control_pipe->nb_entries].name, MAX_NAME_LEN, "ipv6_tcp");
1350  entry = &control_pipe->entries_info[control_pipe->nb_entries++].entry;
1351  }
1353  0,
1354  control_pipe->pipe,
1355  &match,
1356  NULL,
1357  NULL,
1358  NULL,
1359  NULL,
1360  NULL,
1361  monitor_ptr,
1362  &fwd,
1363  NULL,
1364  entry);
1365  if (result != DOCA_SUCCESS) {
1366  DOCA_LOG_ERR("Failed to add TCP IPv6 control entry: %s", doca_error_get_descr(result));
1367  return result;
1368  }
1369 
1370  memset(&match, 0, sizeof(match));
1371  if (is_root) {
1372  match.outer.eth.type = rte_cpu_to_be_16(DOCA_FLOW_ETHER_TYPE_IPV6);
1375  } else {
1378  }
1379 
1381  if (!perf_bw)
1383  else
1384  fwd.next_pipe = pipes->ipv6_udp_pipe.pipe;
1385  if (debug_mode) {
1386  snprintf(control_pipe->entries_info[control_pipe->nb_entries].name, MAX_NAME_LEN, "ipv6_udp");
1387  entry = &control_pipe->entries_info[control_pipe->nb_entries++].entry;
1388  }
1390  0,
1391  control_pipe->pipe,
1392  &match,
1393  NULL,
1394  NULL,
1395  NULL,
1396  NULL,
1397  NULL,
1398  monitor_ptr,
1399  &fwd,
1400  NULL,
1401  entry);
1402  if (result != DOCA_SUCCESS) {
1403  DOCA_LOG_ERR("Failed to add UDP IPv6 control entry: %s", doca_error_get_descr(result));
1404  return result;
1405  }
1406 
1407  return DOCA_SUCCESS;
1408 }
1409 
1410 /*
1411  * Update the crypto config for encrypt transport mode according to the rule
1412  *
1413  * @crypto_cfg [in]: shared object config
1414  * @rule [in]: encrypt rule
1415  */
1417  struct encrypt_rule *rule)
1418 {
1419  create_transport_encap(rule, false, crypto_cfg->encap_data, &crypto_cfg->data_size);
1420 }
1421 
1422 /*
1423  * Update the crypto config for encrypt transport over UDP mode according to the rule
1424  *
1425  * @crypto_cfg [in]: shared object config
1426  * @rule [in]: encrypt rule
1427  */
1429  struct encrypt_rule *rule)
1430 {
1431  create_udp_transport_encap(rule, false, crypto_cfg->encap_data, &crypto_cfg->data_size);
1432 }
1433 
1434 /*
1435  * Update the crypto config for encrypt tunnel mode according to the rule
1436  *
1437  * @crypto_cfg [in]: shared object config
1438  * @rule [in]: encrypt rule
1439  * @eth_header [in]: contains the src mac address
1440  */
1442  struct encrypt_rule *rule,
1443  struct doca_flow_header_eth *eth_header)
1444 {
1445  if (rule->encap_l3_type == DOCA_FLOW_L3_TYPE_IP4)
1446  create_ipv4_tunnel_encap(rule, false, eth_header, crypto_cfg->encap_data, &crypto_cfg->data_size);
1447  else
1448  create_ipv6_tunnel_encap(rule, false, eth_header, crypto_cfg->encap_data, &crypto_cfg->data_size);
1449 }
1450 
1451 /*
1452  * Config and bind shared IPSEC object for encryption
1453  *
1454  * @app_sa_attrs [in]: SA attributes
1455  * @app_cfg [in]: application configuration struct
1456  * @ipsec_id [in]: shared object ID
1457  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1458  */
1461  uint32_t ipsec_id)
1462 {
1465 
1466  memset(&cfg, 0, sizeof(cfg));
1467 
1468  cfg.ipsec_sa_cfg.icv_len = app_cfg->icv_length;
1469  cfg.ipsec_sa_cfg.salt = app_sa_attrs->salt;
1470  cfg.ipsec_sa_cfg.implicit_iv = app_sa_attrs->iv;
1471  cfg.ipsec_sa_cfg.key_cfg.key_type = app_sa_attrs->key_type;
1472  cfg.ipsec_sa_cfg.key_cfg.key = (void *)&app_sa_attrs->enc_key_data;
1473  cfg.ipsec_sa_cfg.sn_initial = app_cfg->sn_initial;
1474  cfg.ipsec_sa_cfg.esn_en = app_sa_attrs->esn_en;
1475  if (!app_cfg->sw_sn_inc_enable) {
1476  cfg.ipsec_sa_cfg.sn_offload_type = DOCA_FLOW_CRYPTO_SN_OFFLOAD_INC;
1477  cfg.ipsec_sa_cfg.lifetime_threshold = app_sa_attrs->lifetime_threshold;
1478  }
1479  /* config ipsec object */
1481  if (result != DOCA_SUCCESS) {
1482  DOCA_LOG_ERR("Failed to cfg shared ipsec object: %s", doca_error_get_descr(result));
1483  return result;
1484  }
1485 
1486  return DOCA_SUCCESS;
1487 }
1488 
1489 /*
1490  * Get the relevant pipe for adding the rule
1491  *
1492  * @rule [in]: the rule that need to add
1493  * @pipes [in]: encrypt pipes struct
1494  * @src_ip6 [in]: true if we want to get the source ipv6 pipe
1495  * @pipe [out]: output pipe
1496  */
1497 static void get_pipe_for_rule(struct encrypt_rule *rule,
1498  struct encrypt_pipes *pipes,
1499  bool src_ip6,
1500  struct security_gateway_pipe_info **pipe)
1501 {
1502  if (!src_ip6) {
1503  if (rule->l3_type == DOCA_FLOW_L3_TYPE_IP4) {
1504  if (rule->protocol == DOCA_FLOW_L4_TYPE_EXT_TCP)
1505  *pipe = &pipes->ipv4_tcp_pipe;
1506  else
1507  *pipe = &pipes->ipv4_udp_pipe;
1508  } else {
1509  if (rule->protocol == DOCA_FLOW_L4_TYPE_EXT_TCP)
1510  *pipe = &pipes->ipv6_tcp_pipe;
1511  else
1512  *pipe = &pipes->ipv6_udp_pipe;
1513  }
1514  } else {
1515  if (rule->protocol == DOCA_FLOW_L4_TYPE_EXT_TCP)
1516  *pipe = &pipes->ipv6_src_tcp_pipe;
1517  else
1518  *pipe = &pipes->ipv6_src_udp_pipe;
1519  }
1520 }
1521 
1522 /*
1523  * Add entry to source IPv6 pipe
1524  *
1525  * @port [in]: port of the pipe
1526  * @rule [in]: encrypt rule
1527  * @pipes [in]: encrypt pipes struct
1528  * @hairpin_status [in]: the entries status
1529  * @src_ip_id [in]: source IP unique ID
1530  * @queue_id [in]: queue ID to forward the packets to
1531  * @debug_mode [in]: true when running in debug mode
1532  * @i [in]: rule id
1533  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1534  */
1535 static doca_error_t add_src_ip6_entry(struct doca_flow_port *port,
1536  struct encrypt_rule *rule,
1537  struct encrypt_pipes *pipes,
1538  struct entries_status *hairpin_status,
1539  uint32_t src_ip_id,
1540  uint16_t queue_id,
1541  bool debug_mode,
1542  int i)
1543 {
1544  struct doca_flow_match match;
1545  struct doca_flow_actions actions;
1548  struct doca_flow_pipe_entry **entry = NULL;
1550 
1551  memset(&match, 0, sizeof(match));
1552  memset(&actions, 0, sizeof(actions));
1553 
1554  get_pipe_for_rule(rule, pipes, true, &pipe);
1555 
1556  memcpy(match.outer.ip6.src_ip, rule->ip6.src_ip, sizeof(rule->ip6.src_ip));
1557  actions.meta.u32[0] = DOCA_HTOBE32(src_ip_id);
1558 
1559  if (hairpin_status->entries_in_queue == QUEUE_DEPTH - 1)
1560  flags = DOCA_FLOW_NO_WAIT;
1561  else
1562  flags = DOCA_FLOW_WAIT_FOR_BATCH;
1563 
1564  /* add entry to hairpin pipe*/
1565  if (debug_mode) {
1566  snprintf(pipe->entries_info[pipe->nb_entries].name, MAX_NAME_LEN, "rule%d", i);
1567  entry = &pipe->entries_info[pipe->nb_entries++].entry;
1568  }
1570  pipe->pipe,
1571  &match,
1572  &actions,
1573  NULL,
1574  NULL,
1575  flags,
1576  hairpin_status,
1577  entry);
1578  if (result != DOCA_SUCCESS) {
1579  DOCA_LOG_ERR("Failed to add hairpin pipe entry: %s", doca_error_get_descr(result));
1580  return result;
1581  }
1582  hairpin_status->entries_in_queue++;
1583  if (hairpin_status->entries_in_queue == QUEUE_DEPTH) {
1584  result = process_entries(port, hairpin_status, DEFAULT_TIMEOUT_US, queue_id);
1585  if (result != DOCA_SUCCESS)
1586  return result;
1587  }
1588  return DOCA_SUCCESS;
1589 }
1590 
1591 /*
1592  * Add 5-tuple entries based on a rule
1593  * If ipv6 - add the source IP to different pipe
1594  *
1595  * @port [in]: port of the pipe
1596  * @rule [in]: encrypt rule
1597  * @app_cfg [in]: application configuration structure
1598  * @nb_rules [in]: number of encryption rules
1599  * @i [in]: rule index
1600  * @queue_id [in]: queue ID to forward the packets to
1601  * @hairpin_status [in]: the entries status
1602  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1603  */
1604 static doca_error_t add_five_tuple_match_entry(struct doca_flow_port *port,
1605  struct encrypt_rule *rule,
1607  int nb_rules,
1608  int i,
1609  uint16_t queue_id,
1610  struct entries_status *hairpin_status)
1611 {
1612  struct doca_flow_match match;
1613  struct doca_flow_actions actions;
1615  enum doca_flow_flags_type flags;
1616  int src_ip_id = 0;
1618  union security_gateway_pkt_meta meta = {0};
1619  struct doca_flow_pipe_entry **entry = NULL;
1620 
1621  memset(&match, 0, sizeof(match));
1622  memset(&actions, 0, sizeof(actions));
1623 
1624  if (rule->l3_type == DOCA_FLOW_L3_TYPE_IP6 && !is_perf_bw(app_cfg)) {
1625  src_ip_id = rte_hash_lookup(app_cfg->ip6_table, (void *)&rule->ip6.dst_ip);
1626  if (src_ip_id < 0) {
1627  DOCA_LOG_ERR("Failed to find source IP in table");
1628  return DOCA_ERROR_NOT_FOUND;
1629  }
1630  result = add_src_ip6_entry(port,
1631  rule,
1632  &app_cfg->encrypt_pipes,
1633  hairpin_status,
1634  src_ip_id,
1635  queue_id,
1636  app_cfg->debug_mode,
1637  i);
1638  if (result != DOCA_SUCCESS)
1639  return result;
1640  }
1641 
1642  get_pipe_for_rule(rule, &app_cfg->encrypt_pipes, false, &pipe);
1643 
1644  match.outer.l4_type_ext = rule->protocol;
1645  SET_L4_PORT(outer, src_port, rte_cpu_to_be_16(rule->src_port));
1646  SET_L4_PORT(outer, dst_port, rte_cpu_to_be_16(rule->dst_port));
1647 
1648  if (rule->l3_type == DOCA_FLOW_L3_TYPE_IP4) {
1649  match.outer.ip4.dst_ip = rule->ip4.dst_ip;
1650  match.outer.ip4.src_ip = rule->ip4.src_ip;
1651  } else {
1652  match.meta.u32[0] = DOCA_HTOBE32(src_ip_id);
1653  memcpy(match.outer.ip6.dst_ip, rule->ip6.dst_ip, sizeof(rule->ip6.dst_ip));
1654  }
1655 
1656  meta.encrypt = 1;
1657  meta.rule_id = i;
1659  actions.action_idx = 0;
1660 
1661  if (i == nb_rules - 1 || hairpin_status->entries_in_queue == QUEUE_DEPTH - 1)
1662  flags = DOCA_FLOW_NO_WAIT;
1663  else
1664  flags = DOCA_FLOW_WAIT_FOR_BATCH;
1665 
1666  /* add entry to hairpin pipe*/
1667  if (app_cfg->debug_mode) {
1668  snprintf(pipe->entries_info[pipe->nb_entries].name, MAX_NAME_LEN, "rule%d", i);
1669  entry = &pipe->entries_info[pipe->nb_entries++].entry;
1670  }
1672  pipe->pipe,
1673  &match,
1674  &actions,
1675  NULL,
1676  NULL,
1677  flags,
1678  hairpin_status,
1679  entry);
1680  if (result != DOCA_SUCCESS) {
1681  DOCA_LOG_ERR("Failed to add hairpin pipe entry: %s", doca_error_get_descr(result));
1682  return result;
1683  }
1684  hairpin_status->entries_in_queue++;
1685  if (hairpin_status->entries_in_queue == QUEUE_DEPTH) {
1686  result = process_entries(port, hairpin_status, DEFAULT_TIMEOUT_US, queue_id);
1687  if (result != DOCA_SUCCESS)
1688  return result;
1689  }
1690 
1691  return DOCA_SUCCESS;
1692 }
1693 
1695  int rule_id,
1698 {
1699  struct doca_flow_match match;
1700  struct doca_flow_actions actions;
1701  struct doca_flow_pipe_entry **entry = NULL;
1702  struct security_gateway_pipe_info *encrypt_pipe;
1703  struct doca_flow_port *secured_port = NULL;
1704  struct doca_flow_port *unsecured_port = NULL;
1705  union security_gateway_pkt_meta meta = {0};
1707 
1708  if (app_cfg->flow_mode == IPSEC_SECURITY_GW_SWITCH) {
1709  secured_port = doca_flow_port_switch_get(NULL);
1710  unsecured_port = doca_flow_port_switch_get(NULL);
1711  } else {
1712  secured_port = ports[SECURED_IDX]->port;
1713  unsecured_port = ports[UNSECURED_IDX]->port;
1714  }
1715 
1716  memset(&app_cfg->unsecured_status[0], 0, sizeof(app_cfg->unsecured_status[0]));
1717  memset(&app_cfg->secured_status[0], 0, sizeof(app_cfg->secured_status[0]));
1718  memset(&match, 0, sizeof(match));
1719  memset(&actions, 0, sizeof(actions));
1720 
1723  /* SW encap in tunnel mode */
1724  if (rule->encap_l3_type == DOCA_FLOW_L3_TYPE_IP4)
1725  encrypt_pipe = &app_cfg->encrypt_pipes.ipv4_encrypt_pipe;
1726  else
1727  encrypt_pipe = &app_cfg->encrypt_pipes.ipv6_encrypt_pipe;
1728  } else {
1729  if (rule->l3_type == DOCA_FLOW_L3_TYPE_IP4)
1730  encrypt_pipe = &app_cfg->encrypt_pipes.ipv4_encrypt_pipe;
1731  else
1732  encrypt_pipe = &app_cfg->encrypt_pipes.ipv6_encrypt_pipe;
1733  }
1734  /* add entry to hairpin pipe*/
1735  result = add_five_tuple_match_entry(unsecured_port,
1736  rule,
1737  app_cfg,
1738  rule_id + 1,
1739  rule_id,
1740  0,
1741  &app_cfg->unsecured_status[0]);
1742  if (result != DOCA_SUCCESS) {
1743  DOCA_LOG_ERR("Failed to add pipe entry: %s", doca_error_get_descr(result));
1744  return result;
1745  }
1746 
1747  /* create ipsec shared object */
1749  if (result != DOCA_SUCCESS)
1750  return result;
1751 
1752  memset(&match, 0, sizeof(match));
1753 
1754  meta.rule_id = rule_id;
1755  match.meta.pkt_meta = DOCA_HTOBE32(meta.u32);
1756 
1757  actions.action_idx = 0;
1759 
1760  if (app_cfg->mode == IPSEC_SECURITY_GW_TUNNEL) {
1762  if (rule->encap_l3_type == DOCA_FLOW_L3_TYPE_IP4)
1763  actions.action_idx = 0;
1764  else
1765  actions.action_idx = 1;
1766  } else if (app_cfg->mode == IPSEC_SECURITY_GW_TRANSPORT)
1768  else
1770  /* add entry to encrypt pipe*/
1771  if (app_cfg->debug_mode) {
1772  snprintf(encrypt_pipe->entries_info[encrypt_pipe->nb_entries].name, MAX_NAME_LEN, "rule%d", rule_id);
1773  entry = &encrypt_pipe->entries_info[encrypt_pipe->nb_entries++].entry;
1774  }
1776  encrypt_pipe->pipe,
1777  &match,
1778  &actions,
1779  NULL,
1780  NULL,
1782  &app_cfg->secured_status[0],
1783  entry);
1784  if (result != DOCA_SUCCESS) {
1785  DOCA_LOG_ERR("Failed to add pipe entry: %s", doca_error_get_descr(result));
1786  return result;
1787  }
1788  app_cfg->secured_status[0].entries_in_queue++;
1789 
1790  /* process the entries in the encryption pipe*/
1791  do {
1792  result = process_entries(secured_port, &app_cfg->secured_status[0], DEFAULT_TIMEOUT_US, 0);
1793  if (result != DOCA_SUCCESS)
1794  return result;
1795  } while (app_cfg->secured_status[0].entries_in_queue > 0);
1796 
1797  /* process the entries in the 5 tuple match pipes */
1798  do {
1799  result = process_entries(unsecured_port, &app_cfg->unsecured_status[0], DEFAULT_TIMEOUT_US, 0);
1800  if (result != DOCA_SUCCESS)
1801  return result;
1802  } while (app_cfg->unsecured_status[0].entries_in_queue > 0);
1803  return DOCA_SUCCESS;
1804 }
1805 
1806 doca_error_t bind_encrypt_ids(int nb_rules, struct doca_flow_port *port)
1807 {
1809  int i, array_len = nb_rules;
1810  uint32_t *res_array;
1811 
1812  if (array_len == 0)
1813  return DOCA_SUCCESS;
1814  res_array = (uint32_t *)malloc(array_len * sizeof(uint32_t));
1815  if (res_array == NULL) {
1816  DOCA_LOG_ERR("Failed to allocate ids array");
1817  return DOCA_ERROR_NO_MEMORY;
1818  }
1819 
1820  for (i = 0; i < nb_rules; i++) {
1821  res_array[i] = i;
1822  }
1823 
1825  if (result != DOCA_SUCCESS) {
1826  DOCA_LOG_ERR("Failed to bind encrypt IDs to the port");
1827  free(res_array);
1828  return result;
1829  }
1830 
1831  free(res_array);
1832  return DOCA_SUCCESS;
1833 }
1834 
1837  uint16_t queue_id,
1838  int nb_rules,
1839  int rule_offset)
1840 {
1841  struct doca_flow_match match;
1842  struct doca_flow_actions actions;
1843  struct doca_flow_pipe_entry **entry = NULL;
1844  struct security_gateway_pipe_info *encrypt_pipe;
1845  enum doca_flow_flags_type flags;
1846  struct doca_flow_port *secured_port = NULL;
1847  struct doca_flow_port *unsecured_port = NULL;
1848  int i, rule_id;
1850  union security_gateway_pkt_meta meta = {0};
1851  struct encrypt_rule *rules = app_cfg->app_rules.encrypt_rules;
1852  struct encrypt_pipes *pipes = &app_cfg->encrypt_pipes;
1853 
1854  if (app_cfg->flow_mode == IPSEC_SECURITY_GW_SWITCH) {
1855  secured_port = doca_flow_port_switch_get(NULL);
1856  unsecured_port = doca_flow_port_switch_get(NULL);
1857  } else {
1858  secured_port = ports[SECURED_IDX]->port;
1859  unsecured_port = ports[UNSECURED_IDX]->port;
1860  }
1861 
1862  memset(&app_cfg->secured_status[queue_id], 0, sizeof(app_cfg->secured_status[queue_id]));
1863  memset(&app_cfg->unsecured_status[queue_id], 0, sizeof(app_cfg->unsecured_status[queue_id]));
1864  memset(&match, 0, sizeof(match));
1865  memset(&actions, 0, sizeof(actions));
1866 
1867  for (i = 0; i < nb_rules; i++) {
1868  rule_id = rule_offset + i;
1869  if (app_cfg->mode == IPSEC_SECURITY_GW_TUNNEL &&
1872  /* SW encap in tunnel mode */
1873  if (rules[rule_id].encap_l3_type == DOCA_FLOW_L3_TYPE_IP4)
1874  encrypt_pipe = &pipes->ipv4_encrypt_pipe;
1875  else
1876  encrypt_pipe = &pipes->ipv6_encrypt_pipe;
1877  } else {
1878  if (rules[rule_id].l3_type == DOCA_FLOW_L3_TYPE_IP4)
1879  encrypt_pipe = &pipes->ipv4_encrypt_pipe;
1880  else
1881  encrypt_pipe = &pipes->ipv6_encrypt_pipe;
1882  }
1883  /* add entry to hairpin pipe*/
1884  result = add_five_tuple_match_entry(unsecured_port,
1885  &rules[rule_id],
1886  app_cfg,
1887  nb_rules,
1888  rule_id,
1889  queue_id,
1890  &app_cfg->unsecured_status[queue_id]);
1891  if (result != DOCA_SUCCESS) {
1892  DOCA_LOG_ERR("Failed to add pipe entry: %s", doca_error_get_descr(result));
1893  return result;
1894  }
1895 
1896  /* create ipsec shared object */
1898  if (result != DOCA_SUCCESS)
1899  return result;
1900 
1901  memset(&match, 0, sizeof(match));
1902 
1903  meta.rule_id = rule_id;
1904  match.meta.pkt_meta = DOCA_HTOBE32(meta.u32);
1905 
1906  actions.action_idx = 0;
1908  if (app_cfg->mode == IPSEC_SECURITY_GW_TUNNEL) {
1910  &rules[rule_id],
1911  &ports[SECURED_IDX]->eth_header);
1912  if (rules[rule_id].encap_l3_type == DOCA_FLOW_L3_TYPE_IP4)
1913  actions.action_idx = 0;
1914  else
1915  actions.action_idx = 1;
1916  } else if (app_cfg->mode == IPSEC_SECURITY_GW_TRANSPORT)
1918  else
1920 
1921  if (rule_id == nb_rules - 1 || app_cfg->secured_status[queue_id].entries_in_queue == QUEUE_DEPTH - 1)
1922  flags = DOCA_FLOW_NO_WAIT;
1923  else
1924  flags = DOCA_FLOW_WAIT_FOR_BATCH;
1925  /* add entry to encrypt pipe*/
1926  if (app_cfg->debug_mode) {
1927  snprintf(encrypt_pipe->entries_info[encrypt_pipe->nb_entries].name, MAX_NAME_LEN, "rule%d", i);
1928  entry = &encrypt_pipe->entries_info[encrypt_pipe->nb_entries++].entry;
1929  }
1931  encrypt_pipe->pipe,
1932  &match,
1933  &actions,
1934  NULL,
1935  NULL,
1936  flags,
1937  &app_cfg->secured_status[queue_id],
1938  entry);
1939  if (result != DOCA_SUCCESS) {
1940  DOCA_LOG_ERR("Failed to add pipe entry: %s", doca_error_get_descr(result));
1941  return result;
1942  }
1943  app_cfg->secured_status[queue_id].entries_in_queue++;
1944  if (app_cfg->secured_status[queue_id].entries_in_queue == QUEUE_DEPTH) {
1945  result = process_entries(secured_port,
1946  &app_cfg->secured_status[queue_id],
1948  queue_id);
1949  if (result != DOCA_SUCCESS)
1950  return result;
1951  }
1952  }
1953  /* process the entries in the encryption pipe*/
1954  do {
1955  result =
1956  process_entries(secured_port, &app_cfg->secured_status[queue_id], DEFAULT_TIMEOUT_US, queue_id);
1957  if (result != DOCA_SUCCESS)
1958  return result;
1959  } while (app_cfg->secured_status[queue_id].entries_in_queue > 0);
1960 
1961  /* process the entries in the 5 tuple match pipes */
1962  do {
1963  result = process_entries(unsecured_port,
1964  &app_cfg->unsecured_status[queue_id],
1966  queue_id);
1967  if (result != DOCA_SUCCESS)
1968  return result;
1969  } while (app_cfg->unsecured_status[queue_id].entries_in_queue > 0);
1970  return DOCA_SUCCESS;
1971 }
1972 
1975 {
1976  struct doca_flow_port *secured_port = NULL;
1977  bool is_root;
1979  int expected_entries;
1980 
1981  if (app_cfg->socket_ctx.socket_conf)
1982  expected_entries = MAX_NB_RULES;
1983  else if (app_cfg->app_rules.nb_encrypt_rules > 0)
1984  expected_entries = app_cfg->app_rules.nb_encrypt_rules;
1985  else /* default value - no entries expected so putting a default value so that pipe creation won't fail */
1986  expected_entries = DEF_EXPECTED_ENTRIES;
1987 
1988  if (app_cfg->flow_mode == IPSEC_SECURITY_GW_VNF) {
1989  secured_port = ports[SECURED_IDX]->port;
1990  is_root = true;
1991  } else {
1992  secured_port = doca_flow_port_switch_get(NULL);
1993  is_root = false;
1994  }
1995 
1996  if (app_cfg->vxlan_encap) {
1997  if (app_cfg->marker_encap) {
1998  DOCA_LOG_ERR("Non-ESP marker is not supported over VXLAN encapsulation");
1999  return DOCA_ERROR_NOT_SUPPORTED;
2000  }
2001 
2002  snprintf(app_cfg->encrypt_pipes.vxlan_encap_pipe.name, MAX_NAME_LEN, "vxlan_encap");
2003  result = create_vxlan_encap_pipe(secured_port, ports[SECURED_IDX]->port_id, app_cfg);
2004  if (result != DOCA_SUCCESS)
2005  return result;
2006  } else if (app_cfg->marker_encap) {
2007  result = create_marker_encap_pipe(secured_port, ports[SECURED_IDX]->port_id, app_cfg);
2008  if (result != DOCA_SUCCESS) {
2009  DOCA_LOG_ERR("Failed to create non-ESP marker egress pipe: %s", doca_error_get_descr(result));
2010  return result;
2011  }
2012  }
2013 
2014  snprintf(app_cfg->encrypt_pipes.ipv4_encrypt_pipe.name, MAX_NAME_LEN, "IPv4_encrypt");
2015  result = create_ipsec_encrypt_pipe(secured_port,
2016  ports[SECURED_IDX]->port_id,
2017  expected_entries,
2018  app_cfg,
2020  &app_cfg->encrypt_pipes.ipv4_encrypt_pipe);
2021  if (result != DOCA_SUCCESS)
2022  return result;
2023 
2024  snprintf(app_cfg->encrypt_pipes.ipv6_encrypt_pipe.name, MAX_NAME_LEN, "IPv6_encrypt");
2025  result = create_ipsec_encrypt_pipe(secured_port,
2026  ports[SECURED_IDX]->port_id,
2027  expected_entries,
2028  app_cfg,
2030  &app_cfg->encrypt_pipes.ipv6_encrypt_pipe);
2031  if (result != DOCA_SUCCESS)
2032  return result;
2033 
2034  snprintf(app_cfg->encrypt_pipes.egress_ip_classifier.name, MAX_NAME_LEN, "ip_classifier");
2035  result = create_egress_ip_classifier(secured_port,
2036  is_root,
2037  app_cfg->debug_mode,
2038  &app_cfg->encrypt_pipes,
2039  app_cfg);
2040  if (result != DOCA_SUCCESS)
2041  return result;
2042 
2043  return DOCA_SUCCESS;
2044 }
2045 
2048 {
2049  uint32_t nb_queues = app_cfg->dpdk_config->port_config.nb_queues;
2050  uint16_t rss_queues[nb_queues];
2051  uint32_t rss_flags;
2052  struct doca_flow_port *unsecured_port = NULL;
2053  struct doca_flow_fwd fwd;
2054  bool is_root;
2055  bool perf_bw;
2057  int expected_entries;
2058 
2059  if (app_cfg->socket_ctx.socket_conf)
2060  expected_entries = MAX_NB_RULES;
2061  else if (app_cfg->app_rules.nb_encrypt_rules > 0)
2062  expected_entries = app_cfg->app_rules.nb_encrypt_rules;
2063  else /* default value - no entries expected so putting a default value so that pipe creation won't fail */
2064  expected_entries = DEF_EXPECTED_ENTRIES;
2065 
2066  if (app_cfg->flow_mode == IPSEC_SECURITY_GW_VNF) {
2067  unsecured_port = ports[UNSECURED_IDX]->port;
2068  is_root = true;
2069  } else {
2070  unsecured_port = doca_flow_port_switch_get(NULL);
2071  is_root = false;
2072  }
2073 
2074  rss_flags = DOCA_FLOW_RSS_IPV4 | DOCA_FLOW_RSS_TCP;
2076 
2077  DOCA_LOG_DBG("Creating IPv4 TCP hairpin pipe");
2078  snprintf(app_cfg->encrypt_pipes.ipv4_tcp_pipe.name, MAX_NAME_LEN, "IPv4_tcp_hairpin");
2079  result = create_ipsec_hairpin_pipe(unsecured_port,
2080  app_cfg->debug_mode,
2081  expected_entries,
2084  &fwd,
2085  &app_cfg->encrypt_pipes.ipv4_tcp_pipe);
2086  if (result != DOCA_SUCCESS) {
2087  DOCA_LOG_ERR("Failed create IPv4 TCP hairpin pipe");
2088  return result;
2089  }
2090 
2091  DOCA_LOG_DBG("Creating IPv4 UDP hairpin pipe");
2092  snprintf(app_cfg->encrypt_pipes.ipv4_udp_pipe.name, MAX_NAME_LEN, "IPv4_udp_hairpin");
2093  rss_flags = DOCA_FLOW_RSS_IPV4 | DOCA_FLOW_RSS_UDP;
2095 
2096  result = create_ipsec_hairpin_pipe(unsecured_port,
2097  app_cfg->debug_mode,
2098  expected_entries,
2101  &fwd,
2102  &app_cfg->encrypt_pipes.ipv4_udp_pipe);
2103  if (result != DOCA_SUCCESS) {
2104  DOCA_LOG_ERR("Failed create IPv4 UDP hairpin pipe");
2105  return result;
2106  }
2107 
2108  DOCA_LOG_DBG("Creating IPv6 TCP hairpin pipe");
2109  snprintf(app_cfg->encrypt_pipes.ipv6_tcp_pipe.name, MAX_NAME_LEN, "IPv6_tcp_hairpin");
2110  rss_flags = DOCA_FLOW_RSS_IPV6 | DOCA_FLOW_RSS_TCP;
2112 
2113  result = create_ipsec_hairpin_pipe(unsecured_port,
2114  app_cfg->debug_mode,
2115  expected_entries,
2118  &fwd,
2119  &app_cfg->encrypt_pipes.ipv6_tcp_pipe);
2120  if (result != DOCA_SUCCESS) {
2121  DOCA_LOG_ERR("Failed create IPv6 TCP hairpin pipe");
2122  return result;
2123  }
2124 
2125  DOCA_LOG_DBG("Creating IPv6 UDP hairpin pipe");
2126  snprintf(app_cfg->encrypt_pipes.ipv6_udp_pipe.name, MAX_NAME_LEN, "IPv6_udp_hairpin");
2127  rss_flags = DOCA_FLOW_RSS_IPV6 | DOCA_FLOW_RSS_UDP;
2129 
2130  result = create_ipsec_hairpin_pipe(unsecured_port,
2131  app_cfg->debug_mode,
2132  expected_entries,
2135  &fwd,
2136  &app_cfg->encrypt_pipes.ipv6_udp_pipe);
2137  if (result != DOCA_SUCCESS) {
2138  DOCA_LOG_ERR("Failed create IPv6 UDP hairpin pipe");
2139  return result;
2140  }
2141 
2142  perf_bw = is_perf_bw(app_cfg);
2143  if (!perf_bw) {
2144  DOCA_LOG_DBG("Creating source IPv6 TCP hairpin pipe");
2145  snprintf(app_cfg->encrypt_pipes.ipv6_src_tcp_pipe.name, MAX_NAME_LEN, "IPv6_src_tcp");
2146  result = create_ipsec_src_ip6_pipe(unsecured_port,
2147  app_cfg->debug_mode,
2148  expected_entries,
2150  app_cfg->encrypt_pipes.ipv6_tcp_pipe.pipe,
2151  &app_cfg->encrypt_pipes.ipv6_src_tcp_pipe);
2152  if (result != DOCA_SUCCESS) {
2153  DOCA_LOG_ERR("Failed create source ip6 TCP hairpin pipe");
2154  return result;
2155  }
2156 
2157  DOCA_LOG_DBG("Creating source IPv6 UDP hairpin pipe");
2158  snprintf(app_cfg->encrypt_pipes.ipv6_src_udp_pipe.name, MAX_NAME_LEN, "IPv6_src_udp");
2159  result = create_ipsec_src_ip6_pipe(unsecured_port,
2160  app_cfg->debug_mode,
2161  expected_entries,
2163  app_cfg->encrypt_pipes.ipv6_udp_pipe.pipe,
2164  &app_cfg->encrypt_pipes.ipv6_src_udp_pipe);
2165  if (result != DOCA_SUCCESS) {
2166  DOCA_LOG_ERR("Failed create source ip6 UDP hairpin pipe");
2167  return result;
2168  }
2169  }
2170  DOCA_LOG_DBG("Creating control pipe");
2171  snprintf(app_cfg->encrypt_pipes.encrypt_root.name, MAX_NAME_LEN, "encrypt_root");
2172  result =
2173  create_control_pipe(unsecured_port, is_root, app_cfg->debug_mode, &app_cfg->encrypt_pipes.encrypt_root);
2174  if (result != DOCA_SUCCESS)
2175  return result;
2176 
2177  DOCA_LOG_DBG("Adding control entries");
2178  result = add_control_pipe_entries(&app_cfg->encrypt_pipes.encrypt_root,
2179  &app_cfg->encrypt_pipes,
2180  perf_bw,
2181  app_cfg->debug_mode,
2182  is_root);
2183  if (result != DOCA_SUCCESS)
2184  return result;
2185 
2186  return DOCA_SUCCESS;
2187 }
2188 
2189 /*
2190  * Update mbuf with the new headers and trailer data for tunnel mode
2191  *
2192  * @m [in]: the mbuf to update
2193  * @ctx [in]: the security gateway context
2194  * @rule_idx [in]: the index of the rule to use
2195  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
2196  */
2197 static doca_error_t prepare_packet_tunnel(struct rte_mbuf **m,
2199  uint32_t rule_idx)
2200 {
2201  struct rte_ether_hdr *nh;
2202  struct rte_esp_tail *esp_tail;
2203  struct rte_ipv4_hdr *ipv4;
2204  struct rte_ipv6_hdr *ipv6;
2205  struct rte_mbuf *last_seg;
2206  struct encrypt_rule *rule = &ctx->encrypt_rules[rule_idx];
2207  uint32_t icv_len = get_icv_len_int(ctx->config->icv_length);
2208  bool sw_sn_inc = ctx->config->sw_sn_inc_enable;
2209  void *trailer_pointer;
2210  uint32_t payload_len, esp_len, encrypted_len, padding_len, trailer_len, padding_offset;
2211  uint16_t reformat_encap_data_len;
2212 
2213  if (rule->encap_l3_type == DOCA_FLOW_L3_TYPE_IP4)
2214  reformat_encap_data_len = 50;
2215  else
2216  reformat_encap_data_len = 70;
2217 
2218  /* remove trailing zeros */
2220 
2221  /* in tunnel mode need to encrypt everything beside the eth header */
2222  payload_len = (*m)->pkt_len - sizeof(struct rte_ether_hdr);
2223  /* extra header space required */
2224  esp_len = reformat_encap_data_len - sizeof(struct rte_ether_hdr);
2225 
2226  encrypted_len = payload_len + (sizeof(struct rte_esp_tail));
2227  /* align payload to 4 bytes */
2228  encrypted_len = RTE_ALIGN_CEIL(encrypted_len, PADDING_ALIGN);
2229 
2230  padding_len = encrypted_len - payload_len;
2231  /* extra trailer space is required */
2232  trailer_len = padding_len + icv_len;
2233 
2234  /* append the needed space at the beginning of the packet */
2235  nh = (struct rte_ether_hdr *)(void *)rte_pktmbuf_prepend(*m, esp_len);
2236  if (nh == NULL)
2237  return DOCA_ERROR_NO_MEMORY;
2238 
2239  last_seg = rte_pktmbuf_lastseg(*m);
2240 
2241  /* append tail */
2242  padding_offset = last_seg->data_len;
2243  last_seg->data_len += trailer_len;
2244  (*m)->pkt_len += trailer_len;
2245  trailer_pointer = rte_pktmbuf_mtod_offset(last_seg, typeof(trailer_pointer), padding_offset);
2246 
2247  /* add the new IP and ESP headers */
2248  if (rule->encap_l3_type == DOCA_FLOW_L3_TYPE_IP4) {
2250  sw_sn_inc,
2251  &ctx->ports[SECURED_IDX]->eth_header,
2252  (void *)nh,
2253  &reformat_encap_data_len);
2254  ipv4 = (void *)(nh + 1);
2255  ipv4->total_length = rte_cpu_to_be_16((*m)->pkt_len - sizeof(struct rte_ether_hdr));
2256  ipv4->hdr_checksum = 0;
2257  ipv4->hdr_checksum = rte_ipv4_cksum(ipv4);
2258  } else {
2260  sw_sn_inc,
2261  &ctx->ports[SECURED_IDX]->eth_header,
2262  (void *)nh,
2263  &reformat_encap_data_len);
2264  ipv6 = (void *)(nh + 1);
2265  ipv6->payload_len = rte_cpu_to_be_16((*m)->pkt_len - sizeof(struct rte_ether_hdr) - sizeof(*ipv6));
2266  }
2267 
2268  padding_len -= sizeof(struct rte_esp_tail);
2269 
2270  /* add padding (if needed) */
2271  if (padding_len > 0)
2272  memcpy(trailer_pointer, esp_pad_bytes, RTE_MIN(padding_len, sizeof(esp_pad_bytes)));
2273 
2274  esp_tail = (struct rte_esp_tail *)(trailer_pointer + padding_len);
2275  esp_tail->pad_len = padding_len;
2276  /* set the next proto according to the original packet */
2277  if (rule->l3_type == DOCA_FLOW_L3_TYPE_IP4)
2278  esp_tail->next_proto = 4; /* ipv4 */
2279  else
2280  esp_tail->next_proto = 41; /* ipv6 */
2281 
2282  ctx->encrypt_rules[rule_idx].current_sn++;
2283  return DOCA_SUCCESS;
2284 }
2285 
2286 /*
2287  * Update mbuf with the new headers and trailer data for transport and udp transport mode
2288  *
2289  * @m [in]: the mbuf to update
2290  * @ctx [in]: the security gateway context
2291  * @rule_idx [in]: the index of the rule to use
2292  * @udp_transport [in]: true for UDP transport mode
2293  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
2294  */
2295 static doca_error_t prepare_packet_transport(struct rte_mbuf **m,
2297  uint32_t rule_idx,
2298  bool udp_transport)
2299 {
2300  struct rte_ether_hdr *oh, *nh;
2301  struct rte_esp_tail *esp_tail;
2302  struct rte_ipv4_hdr *ipv4;
2303  struct rte_ipv6_hdr *ipv6;
2304  struct rte_mbuf *last_seg;
2305  struct encrypt_rule *rule = &ctx->encrypt_rules[rule_idx];
2306  uint32_t icv_len = get_icv_len_int(ctx->config->icv_length);
2307  void *trailer_pointer;
2308  uint32_t payload_len, esp_len, encrypted_len, padding_len, trailer_len, padding_offset, l2_l3_len;
2309  uint16_t reformat_encap_data_len;
2310  int protocol, next_protocol = 0;
2311  bool sw_sn_inc = ctx->config->sw_sn_inc_enable;
2312 
2313  if (udp_transport) {
2314  reformat_encap_data_len = 24;
2315  protocol = IPPROTO_UDP;
2316  } else {
2317  reformat_encap_data_len = 16;
2318  protocol = IPPROTO_ESP;
2319  }
2320 
2321  /* remove trailing zeros */
2323 
2324  /* get l2 and l3 headers length */
2325  oh = rte_pktmbuf_mtod(*m, struct rte_ether_hdr *);
2326 
2327  if (RTE_ETH_IS_IPV4_HDR((*m)->packet_type)) {
2328  ipv4 = (void *)(oh + 1);
2329  l2_l3_len = rte_ipv4_hdr_len(ipv4) + sizeof(struct rte_ether_hdr);
2330  } else
2331  l2_l3_len = sizeof(struct rte_ipv6_hdr) + sizeof(struct rte_ether_hdr);
2332 
2333  /* in transport mode need to encrypt everything beside l2 and l3 headers*/
2334  payload_len = (*m)->pkt_len - l2_l3_len;
2335  /* extra header space required */
2336  esp_len = reformat_encap_data_len;
2337 
2338  encrypted_len = payload_len + (sizeof(struct rte_esp_tail));
2339  /* align payload to 4 bytes */
2340  encrypted_len = RTE_ALIGN_CEIL(encrypted_len, PADDING_ALIGN);
2341 
2342  padding_len = encrypted_len - payload_len;
2343  /* extra trailer space is required */
2344  trailer_len = padding_len + icv_len;
2345 
2346  nh = (struct rte_ether_hdr *)(void *)rte_pktmbuf_prepend(*m, esp_len);
2347  if (nh == NULL)
2348  return DOCA_ERROR_NO_MEMORY;
2349 
2350  last_seg = rte_pktmbuf_lastseg(*m);
2351 
2352  /* append tail */
2353  padding_offset = last_seg->data_len;
2354  last_seg->data_len += trailer_len;
2355  (*m)->pkt_len += trailer_len;
2356  trailer_pointer = rte_pktmbuf_mtod_offset(last_seg, typeof(trailer_pointer), padding_offset);
2357 
2358  /* move l2 and l3 to beginning of packet, and copy ESP header after */
2359  memmove(nh, oh, l2_l3_len);
2360  if (udp_transport)
2361  create_udp_transport_encap(rule, sw_sn_inc, ((void *)nh) + l2_l3_len, &reformat_encap_data_len);
2362  else
2363  create_transport_encap(rule, sw_sn_inc, ((void *)nh) + l2_l3_len, &reformat_encap_data_len);
2364 
2365  /* update next protocol to ESP/UDP, total length and checksum */
2366  if (RTE_ETH_IS_IPV4_HDR((*m)->packet_type)) {
2367  ipv4 = (void *)(nh + 1);
2368  next_protocol = ipv4->next_proto_id;
2369  ipv4->next_proto_id = protocol;
2370  ipv4->total_length = rte_cpu_to_be_16((*m)->pkt_len - sizeof(struct rte_ether_hdr));
2371  ipv4->hdr_checksum = 0;
2372  ipv4->hdr_checksum = rte_ipv4_cksum(ipv4);
2373  if (udp_transport) {
2374  struct rte_udp_hdr *udp = (void *)(ipv4 + 1);
2375  uint16_t udp_len = (*m)->pkt_len - sizeof(struct rte_ether_hdr) - sizeof(struct rte_ipv4_hdr);
2376 
2377  udp->dgram_len = rte_cpu_to_be_16(udp_len);
2378  udp->dgram_cksum = RTE_BE16(0);
2379  }
2380  } else if (RTE_ETH_IS_IPV6_HDR((*m)->packet_type)) {
2381  ipv6 = (void *)(nh + 1);
2382  next_protocol = ipv6->proto;
2383  ipv6->proto = protocol;
2384  ipv6->payload_len = rte_cpu_to_be_16((*m)->pkt_len - sizeof(struct rte_ether_hdr) - sizeof(*ipv6));
2385  if (udp_transport) {
2386  struct rte_udp_hdr *udp = (void *)(ipv6 + 1);
2387  uint16_t udp_len = (*m)->pkt_len - sizeof(struct rte_ether_hdr) - sizeof(struct rte_ipv6_hdr);
2388 
2389  udp->dgram_len = rte_cpu_to_be_16(udp_len);
2390  udp->dgram_cksum = RTE_BE16(0);
2391  }
2392  }
2393 
2394  padding_len -= sizeof(struct rte_esp_tail);
2395 
2396  /* add padding (if needed) */
2397  if (padding_len > 0)
2398  memcpy(trailer_pointer, esp_pad_bytes, RTE_MIN(padding_len, sizeof(esp_pad_bytes)));
2399 
2400  /* set the next proto according to the original packet */
2401  esp_tail = (struct rte_esp_tail *)(trailer_pointer + padding_len);
2402  esp_tail->pad_len = padding_len;
2403  esp_tail->next_proto = next_protocol;
2404 
2405  ctx->encrypt_rules[rule_idx].current_sn++;
2406  return DOCA_SUCCESS;
2407 }
2408 
2410 {
2411  uint32_t pkt_meta;
2412  uint32_t rule_idx;
2414 
2415  pkt_meta = *RTE_FLOW_DYNF_METADATA(*packet);
2416  rule_idx = ((union security_gateway_pkt_meta)pkt_meta).rule_id;
2417 
2418  if (ctx->config->mode == IPSEC_SECURITY_GW_TRANSPORT)
2419  result = prepare_packet_transport(packet, ctx, rule_idx, false);
2420  else if (ctx->config->mode == IPSEC_SECURITY_GW_UDP_TRANSPORT)
2421  result = prepare_packet_transport(packet, ctx, rule_idx, true);
2422  else
2423  result = prepare_packet_tunnel(packet, ctx, rule_idx);
2424  if (result != DOCA_SUCCESS)
2425  return result;
2426  return doca_flow_crypto_ipsec_update_sn(rule_idx, ctx->encrypt_rules[rule_idx].current_sn);
2427 }
#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
#define SET_MAC_ADDR(addr, a, b, c, d, e, f)
Definition: flow_common.h:60
uint32_t rule_id
Definition: flow_common.h:8
#define SET_IP6_ADDR(addr, a, b, c, d)
Definition: flow_common.h:53
if(bitoffset % 64+bitlength > 64) result|
static doca_error_t create_ipsec_src_ip6_pipe(struct doca_flow_port *port, bool debug_mode, int expected_entries, enum doca_flow_l4_type_ext protocol_type, struct doca_flow_pipe *hairpin_pipe, struct security_gateway_pipe_info *pipe_info)
Definition: flow_encrypt.c:947
static doca_error_t add_five_tuple_match_entry(struct doca_flow_port *port, struct encrypt_rule *rule, struct ipsec_security_gw_config *app_cfg, int nb_rules, int i, uint16_t queue_id, struct entries_status *hairpin_status)
doca_error_t ipsec_security_gw_create_encrypt_egress(struct ipsec_security_gw_ports_map *ports[], struct ipsec_security_gw_config *app_cfg)
static void get_pipe_for_rule(struct encrypt_rule *rule, struct encrypt_pipes *pipes, bool src_ip6, struct security_gateway_pipe_info **pipe)
#define ENCAP_ESP_SPI_IDX_TUNNEL_IP6
Definition: flow_encrypt.c:44
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)
static bool is_perf_bw(struct ipsec_security_gw_config *app_cfg)
#define ENCAP_DST_UDP_PORT_IDX
Definition: flow_encrypt.c:42
doca_error_t bind_encrypt_ids(int nb_rules, struct doca_flow_port *port)
static doca_error_t add_control_pipe_entries(struct security_gateway_pipe_info *control_pipe, struct encrypt_pipes *pipes, bool perf_bw, bool debug_mode, bool is_root)
static doca_error_t prepare_packet_tunnel(struct rte_mbuf **m, struct ipsec_security_gw_core_ctx *ctx, uint32_t rule_idx)
doca_error_t ipsec_security_gw_insert_encrypt_rules(struct ipsec_security_gw_ports_map *ports[], struct ipsec_security_gw_config *app_cfg)
static void create_ipsec_encrypt_shared_object_tunnel(struct doca_flow_crypto_encap_action *crypto_cfg, struct encrypt_rule *rule, struct doca_flow_header_eth *eth_header)
static uint16_t current_ip_id
Definition: flow_encrypt.c:73
static const uint8_t esp_pad_bytes[15]
Definition: flow_encrypt.c:55
static void create_ipv6_tunnel_encap(struct encrypt_rule *rule, bool sw_sn_inc, struct doca_flow_header_eth *eth_header, uint8_t *reformat_data, uint16_t *reformat_data_sz)
Definition: flow_encrypt.c:236
static void create_transport_encap(struct encrypt_rule *rule, bool sw_sn_inc, uint8_t *reformat_data, uint16_t *reformat_data_sz)
Definition: flow_encrypt.c:83
#define ENCAP_IDX_SRC_MAC
Definition: flow_encrypt.c:41
static void create_ipv4_tunnel_encap(struct encrypt_rule *rule, bool sw_sn_inc, struct doca_flow_header_eth *eth_header, uint8_t *reformat_data, uint16_t *reformat_data_sz)
Definition: flow_encrypt.c:174
#define ENCAP_ESP_SN_IDX_TUNNEL_IP6
Definition: flow_encrypt.c:48
static doca_error_t prepare_packet_transport(struct rte_mbuf **m, struct ipsec_security_gw_core_ctx *ctx, uint32_t rule_idx, bool udp_transport)
static doca_error_t create_marker_encap_pipe(struct doca_flow_port *port, uint16_t port_id, struct ipsec_security_gw_config *app_cfg)
Definition: flow_encrypt.c:625
doca_error_t add_encrypt_entry(struct encrypt_rule *rule, int rule_id, struct ipsec_security_gw_ports_map **ports, struct ipsec_security_gw_config *app_cfg)
static doca_error_t create_ipsec_hairpin_pipe(struct doca_flow_port *port, bool debug_mode, int expected_entries, enum doca_flow_l4_type_ext protocol_type, enum doca_flow_l3_type l3_type, struct doca_flow_fwd *fwd, struct security_gateway_pipe_info *pipe_info)
#define ENCAP_DST_IP_IDX_IP6
Definition: flow_encrypt.c:39
static doca_error_t create_ipsec_encrypt_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_egress_ip_classifier(struct doca_flow_port *port, bool is_root, bool debug_mode, struct encrypt_pipes *encrypt_pipes, struct ipsec_security_gw_config *app_cfg)
Definition: flow_encrypt.c:313
#define ENCAP_MARKER_HEADER_SIZE
Definition: flow_encrypt.c:52
static doca_error_t add_src_ip6_entry(struct doca_flow_port *port, struct encrypt_rule *rule, struct encrypt_pipes *pipes, struct entries_status *hairpin_status, uint32_t src_ip_id, uint16_t queue_id, bool debug_mode, int i)
DOCA_LOG_REGISTER(IPSEC_SECURITY_GW::flow_encrypt)
doca_error_t add_encrypt_entries(struct ipsec_security_gw_config *app_cfg, struct ipsec_security_gw_ports_map *ports[], uint16_t queue_id, int nb_rules, int rule_offset)
#define ENCAP_IP_ID_IDX_IP4
Definition: flow_encrypt.c:40
static void create_udp_transport_encap(struct encrypt_rule *rule, bool sw_sn_inc, uint8_t *reformat_data, uint16_t *reformat_data_sz)
Definition: flow_encrypt.c:131
#define PADDING_ALIGN
Definition: flow_encrypt.c:53
static doca_error_t create_ipsec_encrypt_pipe(struct doca_flow_port *port, uint16_t port_id, int expected_entries, struct ipsec_security_gw_config *app_cfg, enum doca_flow_l3_meta l3_type, struct security_gateway_pipe_info *pipe_info)
Definition: flow_encrypt.c:776
static doca_error_t create_vxlan_encap_pipe(struct doca_flow_port *port, int port_id, struct ipsec_security_gw_config *app_cfg)
Definition: flow_encrypt.c:527
doca_error_t handle_unsecured_packets_received(struct rte_mbuf **packet, struct ipsec_security_gw_core_ctx *ctx)
#define ENCAP_ESP_SN_IDX_TRANSPORT
Definition: flow_encrypt.c:49
static void create_ipsec_encrypt_shared_object_transport(struct doca_flow_crypto_encap_action *crypto_cfg, struct encrypt_rule *rule)
#define ENCAP_DST_IP_IDX_IP4
Definition: flow_encrypt.c:38
static void create_ipsec_encrypt_shared_object_transport_over_udp(struct doca_flow_crypto_encap_action *crypto_cfg, struct encrypt_rule *rule)
#define ENCAP_ESP_SPI_IDX_TRANSPORT
Definition: flow_encrypt.c:45
#define ENCAP_ESP_SN_IDX_UDP_TRANSPORT
Definition: flow_encrypt.c:50
#define ENCAP_ESP_SN_IDX_TUNNEL_IP4
Definition: flow_encrypt.c:47
static doca_error_t add_vxlan_encap_pipe_entry(struct doca_flow_port *port, struct security_gateway_pipe_info *pipe, struct ipsec_security_gw_config *app_cfg)
Definition: flow_encrypt.c:461
#define ENCAP_ESP_SPI_IDX_UDP_TRANSPORT
Definition: flow_encrypt.c:46
#define ENCAP_ESP_SPI_IDX_TUNNEL_IP4
Definition: flow_encrypt.c:43
static doca_error_t destroy_pipe_cfg(struct doca_flow_pipe_cfg *cfg)
static uint16_t * rss_queues
Definition: flow_parser.c:114
#define SET_L4_PORT(layer, port, value)
Definition: flow_parser.c:67
static struct doca_flow_actions actions
Definition: flow_parser.c:107
#define BE_IPV4_ADDR(a, b, c, d)
Definition: flow_parser.c:64
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_NOT_FOUND
Definition: doca_error.h:54
@ 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_INC
@ DOCA_FLOW_CRYPTO_HEADER_ESP_OVER_IPV6
@ 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_HEADER_UDP_ESP_OVER_IPV6
@ DOCA_FLOW_CRYPTO_RESOURCE_IPSEC_SA
@ DOCA_FLOW_CRYPTO_REFORMAT_ENCAP
@ DOCA_FLOW_CRYPTO_ACTION_ENCRYPT
doca_flow_l4_type_ext
doca flow layer 4 packet extend type
#define DOCA_FLOW_VXLAN_DEFAULT_PORT
Definition: doca_flow_net.h:49
doca_flow_l3_type
doca flow layer 3 packet type
#define DOCA_FLOW_PROTO_UDP
Definition: doca_flow_net.h:42
#define DOCA_FLOW_ETHER_TYPE_IPV6
Definition: doca_flow_net.h:58
#define DOCA_FLOW_PROTO_TCP
Definition: doca_flow_net.h:41
#define DOCA_FLOW_ETHER_TYPE_IPV4
Definition: doca_flow_net.h:57
@ DOCA_FLOW_L4_TYPE_EXT_TCP
@ DOCA_FLOW_L4_TYPE_EXT_UDP
@ DOCA_FLOW_L3_TYPE_IP6
@ DOCA_FLOW_L3_TYPE_IP4
@ DOCA_FLOW_IP4_FLAG_DONT_FRAGMENT
@ DOCA_FLOW_TUN_VXLAN
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_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_TCP
Definition: doca_flow.h:770
@ DOCA_FLOW_RSS_IPV4
Definition: doca_flow.h:764
@ DOCA_FLOW_RSS_IPV6
Definition: doca_flow.h:766
@ DOCA_FLOW_RSS_UDP
Definition: doca_flow.h:768
@ DOCA_FLOW_SHARED_RESOURCE_IPSEC_SA
Definition: doca_flow.h:107
@ DOCA_FLOW_DIRECTION_HOST_TO_NETWORK
Definition: doca_flow.h:1095
@ 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_PORT
Definition: doca_flow.h:744
@ DOCA_FLOW_FWD_PIPE
Definition: doca_flow.h:746
@ DOCA_FLOW_L4_META_UDP
Definition: doca_flow.h:310
@ DOCA_FLOW_L4_META_TCP
Definition: doca_flow.h:308
@ DOCA_FLOW_PIPE_DOMAIN_EGRESS
Definition: doca_flow.h:245
@ 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_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_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
@ IPSEC_SECURITY_GW_VNF
Definition: ipsec_ctx.h:187
@ IPSEC_SECURITY_GW_SWITCH
Definition: ipsec_ctx.h:188
@ IPSEC_SECURITY_GW_ESP_OFFLOAD_ENCAP
Definition: ipsec_ctx.h:194
@ IPSEC_SECURITY_GW_ESP_OFFLOAD_DECAP
Definition: ipsec_ctx.h:195
@ IPSEC_SECURITY_GW_ESP_OFFLOAD_BOTH
Definition: ipsec_ctx.h:193
@ IPSEC_SECURITY_GW_ESP_OFFLOAD_NONE
Definition: ipsec_ctx.h:196
@ IPSEC_SECURITY_GW_PERF_BW
Definition: ipsec_ctx.h:203
@ IPSEC_SECURITY_GW_PERF_BOTH
Definition: ipsec_ctx.h:204
#define MAX_NAME_LEN
Definition: ipsec_ctx.h:46
#define GET_BYTE(V, N)
Definition: pack.h:37
uint16_t src_port
Definition: packets.h:0
uint16_t dst_port
Definition: packets.h:1
rte_udp_hdr udp
Definition: psp_gw_flows.cpp:6
doca flow actions information
Definition: doca_flow.h:684
uint32_t flags
Definition: doca_flow.h:687
struct doca_flow_crypto_encap_action crypto_encap
Definition: doca_flow.h:723
struct doca_flow_resource_encap_cfg encap_cfg
Definition: doca_flow.h:710
enum doca_flow_resource_type encap_type
Definition: doca_flow.h:707
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
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
doca flow crypto encap action information
Definition: doca_flow.h:644
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
struct doca_flow_tun tun
Definition: doca_flow.h:569
struct doca_flow_header_format outer
Definition: doca_flow.h:567
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
doca flow eth header
uint8_t dst_mac[DOCA_FLOW_ETHER_ADDR_LEN]
uint8_t src_mac[DOCA_FLOW_ETHER_ADDR_LEN]
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_be16_t flags_fragment_offset
doca_be32_t dst_ip[4]
doca_be32_t src_ip[4]
struct doca_flow_header_l4_port l4_port
doca flow matcher information
Definition: doca_flow.h:491
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_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 monitor action configuration
Definition: doca_flow.h:968
enum doca_flow_resource_type counter_type
Definition: doca_flow.h:988
enum doca_flow_l3_meta outer_l3_type
Definition: doca_flow.h:382
enum doca_flow_l4_meta outer_l4_type
Definition: doca_flow.h:383
struct doca_flow_encap_action encap
Definition: doca_flow.h:663
doca flow shared resource configuration
Definition: doca_flow.h:953
enum doca_flow_tun_type type
doca_be32_t vxlan_tun_id
struct security_gateway_pipe_info ipv4_encrypt_pipe
Definition: ipsec_ctx.h:137
struct security_gateway_pipe_info ipv6_tcp_pipe
Definition: ipsec_ctx.h:141
struct security_gateway_pipe_info ipv6_src_udp_pipe
Definition: ipsec_ctx.h:144
struct security_gateway_pipe_info ipv4_udp_pipe
Definition: ipsec_ctx.h:140
struct security_gateway_pipe_info egress_ip_classifier
Definition: ipsec_ctx.h:136
struct security_gateway_pipe_info ipv6_udp_pipe
Definition: ipsec_ctx.h:142
struct security_gateway_pipe_info ipv6_src_tcp_pipe
Definition: ipsec_ctx.h:143
struct security_gateway_pipe_info ipv6_encrypt_pipe
Definition: ipsec_ctx.h:138
struct security_gateway_pipe_info ipv4_tcp_pipe
Definition: ipsec_ctx.h:139
enum doca_flow_l4_type_ext protocol
Definition: ipsec_ctx.h:108
struct ipsec_security_gw_sa_attrs sa_attrs
Definition: ipsec_ctx.h:122
uint32_t current_sn
Definition: ipsec_ctx.h:121
doca_be32_t encap_dst_ip4
Definition: ipsec_ctx.h:117
struct ipsec_security_gw_ip6 ip6
Definition: ipsec_ctx.h:111
doca_be32_t esp_spi
Definition: ipsec_ctx.h:120
enum doca_flow_l3_type encap_l3_type
Definition: ipsec_ctx.h:115
doca_be32_t encap_dst_ip6[4]
Definition: ipsec_ctx.h:118
struct ipsec_security_gw_ip4 ip4
Definition: ipsec_ctx.h:110
enum doca_flow_l3_type l3_type
Definition: ipsec_ctx.h:107
user context struct that will be used in entries process callback
Definition: flow_common.h:78
int entries_in_queue
Definition: flow_common.h:81
doca_be32_t dst_ip
Definition: ipsec_ctx.h:96
doca_be32_t src_ip
Definition: ipsec_ctx.h:95
doca_be32_t src_ip[4]
Definition: ipsec_ctx.h:101
doca_be32_t dst_ip[4]
Definition: ipsec_ctx.h:102
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