NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
policy.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2023-2024 NVIDIA CORPORATION AND AFFILIATES. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are permitted
5  * provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright notice, this list of
7  * conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright notice, this list of
9  * conditions and the following disclaimer in the documentation and/or other materials
10  * provided with the distribution.
11  * * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
12  * to endorse or promote products derived from this software without specific prior written
13  * permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21  * STRICT LIABILITY, OR TOR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  */
25 
26 #include <netinet/in.h>
27 #include <time.h>
28 
29 #include <doca_argp.h>
30 #include <doca_log.h>
31 #include <doca_flow.h>
32 
33 #include <samples/common.h>
34 #include <flow_parser.h>
35 
36 #include "policy.h"
37 #include "config.h"
38 
39 DOCA_LOG_REGISTER(IPSEC_SECURITY_GW::POLICY);
40 
41 /*
42  * Convert ICV length to doca_flow_crypto_icv_len value
43  *
44  * @icv_length [in]: ICV length {8, 12, 16}
45  * @length [out]: suitable doca_flow_crypto_icv_len value
46  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
47  */
49 {
51 
52  switch (icv_length) {
53  case 8:
55  break;
56  case 12:
58  break;
59  case 16:
61  break;
62  default:
64  }
65  return result;
66 }
67 
68 /*
69  * Convert key type to doca_encryption_key_type value
70  *
71  * @key_type [in]: key type {128, 256}
72  * @return: suitable doca_encryption_key_type value
73  */
74 static enum doca_flow_crypto_key_type convert_to_doca_key_type(uint8_t key_type)
75 {
76  if (key_type == POLICY_KEY_TYPE_128)
78  else
80 }
81 
82 /*
83  * Parse SA attributes
84  *
85  * @policy [in]: application IPSEC policy
86  * @sa_attrs [out]: SA app structure
87  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
88  */
90  enum doca_flow_crypto_icv_len app_icv_len,
91  struct ipsec_security_gw_sa_attrs *sa_attrs)
92 {
93  enum doca_flow_crypto_icv_len icv_length;
95 
96  sa_attrs->key_type = convert_to_doca_key_type(policy->key_type);
97  memcpy(sa_attrs->enc_key_data, policy->enc_key_data, MAX_KEY_LEN);
98  sa_attrs->salt = policy->salt;
99  result = convert_to_doca_icv(policy->icv_length, &icv_length);
100  if (result != DOCA_SUCCESS)
101  return result;
102  if (icv_length != app_icv_len) {
103  DOCA_LOG_ERR("icv length in policy (%d) does not match application's icv length (%d)",
104  policy->icv_length,
105  get_icv_len_int(app_icv_len));
107  }
108 
109  return DOCA_SUCCESS;
110 }
111 
112 /*
113  * Parse new ingress policy and populate the encryption rule structure
114  *
115  * @policy [in]: application IPSEC policy
116  * @app_cfg [in]: application configuration struct
117  * @rule [out]: encryption rule structure
118  * @ip6_table [out]: store hash value for IPV6 addresses
119  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
120  */
123  struct encrypt_rule *rule,
124  struct rte_hash **ip6_table)
125 {
127  int ret;
128 
129  rule->esp_spi = policy->spi;
133  rule->src_port = policy->src_port;
134  rule->dst_port = policy->dst_port;
135 
136  if (rule->l3_type == DOCA_FLOW_L3_TYPE_IP4) {
137  result = parse_ipv4_str(&policy->src_ip_addr[0], &rule->ip4.src_ip);
138  if (result != DOCA_SUCCESS)
139  return result;
140 
141  result = parse_ipv4_str(&policy->dst_ip_addr[0], &rule->ip4.dst_ip);
142  if (result != DOCA_SUCCESS)
143  return result;
144  } else {
145  result = parse_ipv6_str(&policy->src_ip_addr[0], rule->ip6.src_ip);
146  if (result != DOCA_SUCCESS)
147  return result;
148 
149  /* Add IPV6 source IP address to hash table */
150  ret = rte_hash_lookup(*ip6_table, (void *)rule->ip6.src_ip);
151  if (ret < 0) {
152  ret = rte_hash_add_key(*ip6_table, rule->ip6.src_ip);
153  if (ret < 0) {
154  DOCA_LOG_ERR("Failed to add address to hash table");
155  return DOCA_ERROR_DRIVER;
156  }
157  }
158 
159  result = parse_ipv6_str(&policy->dst_ip_addr[0], rule->ip6.dst_ip);
160  if (result != DOCA_SUCCESS)
161  return result;
162  ret = rte_hash_lookup(*ip6_table, (void *)rule->ip6.dst_ip);
163  if (ret < 0) {
164  ret = rte_hash_add_key(*ip6_table, rule->ip6.dst_ip);
165  if (ret < 0) {
166  DOCA_LOG_ERR("Failed to add address to hash table");
167  return DOCA_ERROR_DRIVER;
168  }
169  }
170  }
171 
172  /* If policy mode is tunnel, parse the outer header attributes */
173  if (policy->policy_mode == POLICY_MODE_TUNNEL) {
176  if (rule->encap_l3_type == DOCA_FLOW_L3_TYPE_IP4) {
177  result = parse_ipv4_str(&policy->outer_dst_ip[0], &rule->encap_dst_ip4);
178  if (result != DOCA_SUCCESS)
179  return result;
180  } else {
181  result = parse_ipv6_str(&policy->outer_dst_ip[0], rule->encap_dst_ip6);
182  if (result != DOCA_SUCCESS)
183  return result;
184  }
185  }
186 
187  result = parse_sa_attrs(policy, app_cfg->icv_length, &rule->sa_attrs);
188  if (result != DOCA_SUCCESS)
189  return result;
190 
191  return DOCA_SUCCESS;
192 }
193 
194 /*
195  * Parse new egress policy and populate the decryption rule structure
196  *
197  * @policy [in]: application IPSEC policy
198  * @app_cfg [in]: application configuration struct
199  * @rule [out]: decryption rule structure
200  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
201  */
204  struct decrypt_rule *rule)
205 {
206  enum doca_flow_l3_type outer_l3_type =
208  enum doca_flow_l3_type inner_l3_type = (policy->l3_protocol == POLICY_L3_TYPE_IPV4) ? DOCA_FLOW_L3_TYPE_IP4 :
210  enum ipsec_security_gw_mode mode = app_cfg->mode;
211  char *dst_ip = NULL;
213 
214  rule->inner_l3_type = inner_l3_type;
215 
216  if (mode == IPSEC_SECURITY_GW_TUNNEL) {
217  rule->l3_type = outer_l3_type;
218  dst_ip = &policy->outer_dst_ip[0];
219 
220  } else {
221  rule->l3_type = inner_l3_type;
222  dst_ip = &policy->dst_ip_addr[0];
223  }
224 
225  if (rule->l3_type == DOCA_FLOW_L3_TYPE_IP4) {
226  result = parse_ipv4_str(dst_ip, &rule->dst_ip4);
227  if (result != DOCA_SUCCESS)
228  return result;
229  } else {
230  result = parse_ipv6_str(dst_ip, rule->dst_ip6);
231  if (result != DOCA_SUCCESS)
232  return result;
233  }
234 
235  rule->esp_spi = policy->spi;
236 
237  result = parse_sa_attrs(policy, app_cfg->icv_length, &rule->sa_attrs);
238  if (result != DOCA_SUCCESS)
239  return result;
240 
241  return DOCA_SUCCESS;
242 }
243 
246  struct ipsec_security_gw_ipsec_policy *policy,
247  struct encrypt_rule *rule)
248 {
250 
251  result = ipsec_security_gw_policy_encrypt_parse(policy, app_cfg, rule, &app_cfg->ip6_table);
252  if (result != DOCA_SUCCESS) {
253  DOCA_LOG_ERR("Failed to parse new encryption policy");
254  return result;
255  }
256 
257  result = add_encrypt_entry(rule, app_cfg->app_rules.nb_encrypt_rules, ports, app_cfg);
258  if (result != DOCA_SUCCESS) {
259  DOCA_LOG_ERR("Failed to insert entries for encryption policy");
260  return result;
261  }
262 
263  app_cfg->app_rules.nb_encrypt_rules++;
264  app_cfg->app_rules.nb_rules++;
265 
266  return DOCA_SUCCESS;
267 }
268 
270  struct doca_flow_port *secured_port,
271  struct ipsec_security_gw_ipsec_policy *policy,
272  struct decrypt_rule *rule)
273 {
275 
277  if (result != DOCA_SUCCESS) {
278  DOCA_LOG_ERR("Failed to parse new decryption policy");
279  return result;
280  }
281 
282  result = add_decrypt_entry(rule,
283  DYN_RESERVED_RULES + app_cfg->app_rules.nb_decrypt_rules,
284  secured_port,
285  app_cfg);
286  if (result != DOCA_SUCCESS) {
287  DOCA_LOG_ERR("Failed to insert entries for decryption policy");
288  return result;
289  }
290 
291  app_cfg->app_rules.nb_decrypt_rules++;
292  app_cfg->app_rules.nb_rules++;
293  return DOCA_SUCCESS;
294 }
295 
297 {
298  char *dump;
299  int log_level;
300  uint16_t key_len;
301 
303  return;
304 
305  /* Logs below should be in debug mode, having a check here will save time of calling multiple
306  * DOCA log prints and hex_dump function.
307  */
309  return;
310 
311  /* Set key length in bytes */
312  key_len = (policy->key_type == POLICY_KEY_TYPE_128) ? 16 : 32;
313 
314  DOCA_LOG_DBG("Policy L3 protocol %u == %s",
315  policy->l3_protocol,
316  (policy->l3_protocol == POLICY_L3_TYPE_IPV4) ? "IPV4" : "IPV6");
317  DOCA_LOG_DBG("Policy l4_protocol %u == %s",
318  policy->l4_protocol,
319  (policy->l4_protocol == IPPROTO_UDP) ? "UDP" : "TCP");
320  DOCA_LOG_DBG("Policy src_ip_addr %s", policy->src_ip_addr);
321  DOCA_LOG_DBG("Policy dst_ip_addr %s", policy->dst_ip_addr);
322  DOCA_LOG_DBG("Policy src_port %u", policy->src_port);
323  DOCA_LOG_DBG("Policy dst_port %u", policy->dst_port);
324  DOCA_LOG_DBG("Policy policy_direction %u == %s",
325  policy->policy_direction,
326  (policy->policy_direction == POLICY_DIR_OUT) ? "OUT" : "IN");
327  DOCA_LOG_DBG("Policy policy_mode %u == %s",
328  policy->policy_mode,
329  (policy->policy_mode == POLICY_MODE_TUNNEL) ? "TUNNEL" : "TRANSPORT");
330  DOCA_LOG_DBG("Policy spi 0x%x", policy->spi);
331  dump = hex_dump(policy->enc_key_data, key_len);
332  DOCA_LOG_DBG("Policy enc_key_data =\n%s", dump);
333  free(dump);
334  DOCA_LOG_DBG("Policy salt %u", policy->salt);
335  DOCA_LOG_DBG("Policy key_type %u", (policy->key_type == POLICY_KEY_TYPE_128) ? 128 : 256);
336  DOCA_LOG_DBG("Policy esn %u", policy->esn);
337  DOCA_LOG_DBG("Policy icv_length %u", policy->icv_length);
338  DOCA_LOG_DBG("Policy outer_src_ip %s", policy->outer_src_ip);
339  DOCA_LOG_DBG("Policy outer_dst_ip %s", policy->outer_dst_ip);
340  DOCA_LOG_DBG("Policy outer_l3_protocol %s",
341  (policy->outer_l3_protocol == POLICY_L3_TYPE_IPV4) ? "IPV4" : "IPV6");
342 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
uint32_t get_icv_len_int(enum doca_flow_crypto_icv_len icv_len)
Definition: flow_common.c:374
doca_error_t add_decrypt_entry(struct decrypt_rule *rule, int rule_id, struct doca_flow_port *port, struct ipsec_security_gw_config *app_cfg)
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 parse_ipv6_str(const char *str_ip, doca_be32_t *ipv6_addr)
Definition: flow_parser.c:547
doca_error_t parse_ipv4_str(const char *str_ip, doca_be32_t *ipv4_addr)
Definition: flow_parser.c:268
static struct app_gpu_cfg app_cfg
DOCA_EXPERIMENTAL doca_error_t doca_argp_get_log_level(int *log_level)
Get the log level the user inserted it.
enum doca_error doca_error_t
DOCA API return codes.
@ DOCA_ERROR_NOT_SUPPORTED
Definition: doca_error.h:42
@ DOCA_SUCCESS
Definition: doca_error.h:38
@ DOCA_ERROR_DRIVER
Definition: doca_error.h:59
doca_flow_crypto_icv_len
doca flow crypto ICV length
doca_flow_crypto_key_type
doca flow crypto key type
@ DOCA_FLOW_CRYPTO_ICV_LENGTH_16
@ DOCA_FLOW_CRYPTO_ICV_LENGTH_12
@ DOCA_FLOW_CRYPTO_ICV_LENGTH_8
@ DOCA_FLOW_CRYPTO_KEY_128
@ DOCA_FLOW_CRYPTO_KEY_256
doca_flow_l3_type
doca flow layer 3 packet type
@ DOCA_FLOW_L4_TYPE_EXT_TCP
@ DOCA_FLOW_L4_TYPE_EXT_UDP
@ DOCA_FLOW_L3_TYPE_IP6
@ DOCA_FLOW_L3_TYPE_IP4
#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
@ DOCA_LOG_LEVEL_DEBUG
Definition: doca_log.h:49
ipsec_security_gw_mode
Definition: ipsec_ctx.h:179
@ IPSEC_SECURITY_GW_TUNNEL
Definition: ipsec_ctx.h:180
#define DYN_RESERVED_RULES
Definition: ipsec_ctx.h:41
#define MAX_KEY_LEN
Definition: ipsec_ctx.h:42
char * hex_dump(const void *data, size_t size)
int log_level
Definition: pcc.c:40
static doca_error_t convert_to_doca_icv(uint8_t icv_length, enum doca_flow_crypto_icv_len *length)
Definition: policy.c:48
static doca_error_t ipsec_security_gw_policy_encrypt_parse(struct ipsec_security_gw_ipsec_policy *policy, struct ipsec_security_gw_config *app_cfg, struct encrypt_rule *rule, struct rte_hash **ip6_table)
Definition: policy.c:121
DOCA_LOG_REGISTER(IPSEC_SECURITY_GW::POLICY)
static enum doca_flow_crypto_key_type convert_to_doca_key_type(uint8_t key_type)
Definition: policy.c:74
doca_error_t ipsec_security_gw_handle_decrypt_policy(struct ipsec_security_gw_config *app_cfg, struct doca_flow_port *secured_port, struct ipsec_security_gw_ipsec_policy *policy, struct decrypt_rule *rule)
Definition: policy.c:269
void print_policy_attrs(struct ipsec_security_gw_ipsec_policy *policy)
Definition: policy.c:296
static doca_error_t parse_sa_attrs(struct ipsec_security_gw_ipsec_policy *policy, enum doca_flow_crypto_icv_len app_icv_len, struct ipsec_security_gw_sa_attrs *sa_attrs)
Definition: policy.c:89
doca_error_t ipsec_security_gw_handle_encrypt_policy(struct ipsec_security_gw_config *app_cfg, struct ipsec_security_gw_ports_map *ports[], struct ipsec_security_gw_ipsec_policy *policy, struct encrypt_rule *rule)
Definition: policy.c:244
static doca_error_t ipsec_security_gw_policy_decrypt_parse(struct ipsec_security_gw_ipsec_policy *policy, struct ipsec_security_gw_config *app_cfg, struct decrypt_rule *rule)
Definition: policy.c:202
#define POLICY_MODE_TUNNEL
Definition: policy.h:112
#define POLICY_L4_TYPE_UDP
Definition: policy.h:115
#define POLICY_L3_TYPE_IPV4
Definition: policy.h:113
#define POLICY_DIR_OUT
Definition: policy.h:110
#define POLICY_KEY_TYPE_128
Definition: policy.h:117
enum doca_flow_l3_type inner_l3_type
Definition: ipsec_ctx.h:87
doca_be32_t dst_ip6[4]
Definition: ipsec_ctx.h:84
doca_be32_t esp_spi
Definition: ipsec_ctx.h:86
doca_be32_t dst_ip4
Definition: ipsec_ctx.h:83
enum doca_flow_l3_type l3_type
Definition: ipsec_ctx.h:81
struct ipsec_security_gw_sa_attrs sa_attrs
Definition: ipsec_ctx.h:88
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
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
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
char dst_ip_addr[MAX_IP_ADDR_LEN+1]
Definition: policy.h:145
uint8_t enc_key_data[MAX_KEY_LEN]
Definition: policy.h:141
char outer_dst_ip[MAX_IP_ADDR_LEN+1]
Definition: policy.h:147
char outer_src_ip[MAX_IP_ADDR_LEN+1]
Definition: policy.h:146
char src_ip_addr[MAX_IP_ADDR_LEN+1]
Definition: policy.h:144
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
static struct doca_flow_port * ports[FLOW_SWITCH_PORTS_MAX]
Definition: switch_core.c:42