FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
ipsec_handoff.c
Go to the documentation of this file.
1 /*
2  * esp_encrypt.c : IPSec ESP encrypt node
3  *
4  * Copyright (c) 2015 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vnet/ipsec/ipsec.h>
19 #include <vnet/ipsec/ipsec_sa.h>
20 
21 #define foreach_ipsec_handoff_error \
22 _(CONGESTION_DROP, "congestion drop")
23 
24 typedef enum
25 {
26 #define _(sym,str) IPSEC_HANDOFF_ERROR_##sym,
28 #undef _
31 
32 static char *ipsec_handoff_error_strings[] = {
33 #define _(sym,string) string,
35 #undef _
36 };
37 
38 typedef struct ipsec_handoff_trace_t_
39 {
42 
43 static u8 *
44 format_ipsec_handoff_trace (u8 * s, va_list * args)
45 {
46  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
47  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
48  ipsec_handoff_trace_t *t = va_arg (*args, ipsec_handoff_trace_t *);
49 
50  s = format (s, "next-worker %d", t->next_worker_index);
51 
52  return s;
53 }
54 
55 /* do worker handoff based on thread_index in NAT HA protcol header */
59  vlib_frame_t * frame, u32 fq_index, bool is_enc)
60 {
61  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
62  u16 thread_indices[VLIB_FRAME_SIZE], *ti;
63  u32 n_enq, n_left_from, *from;
64  ipsec_main_t *im;
65 
66  im = &ipsec_main;
67  from = vlib_frame_vector_args (frame);
68  n_left_from = frame->n_vectors;
69  vlib_get_buffers (vm, from, bufs, n_left_from);
70 
71  b = bufs;
72  ti = thread_indices;
73 
74  while (n_left_from >= 4)
75  {
76  ipsec_sa_t *sa0, *sa1, *sa2, *sa3;
77  u32 sai0, sai1, sai2, sai3;
78 
79  /* Prefetch next iteration. */
80  if (n_left_from >= 12)
81  {
82  vlib_prefetch_buffer_header (b[8], LOAD);
83  vlib_prefetch_buffer_header (b[9], LOAD);
84  vlib_prefetch_buffer_header (b[10], LOAD);
85  vlib_prefetch_buffer_header (b[11], LOAD);
86 
87  vlib_prefetch_buffer_data (b[4], LOAD);
88  vlib_prefetch_buffer_data (b[5], LOAD);
89  vlib_prefetch_buffer_data (b[6], LOAD);
90  vlib_prefetch_buffer_data (b[7], LOAD);
91  }
92 
93  sai0 = vnet_buffer (b[0])->ipsec.sad_index;
94  sai1 = vnet_buffer (b[1])->ipsec.sad_index;
95  sai2 = vnet_buffer (b[2])->ipsec.sad_index;
96  sai3 = vnet_buffer (b[3])->ipsec.sad_index;
97  sa0 = pool_elt_at_index (im->sad, sai0);
98  sa1 = pool_elt_at_index (im->sad, sai1);
99  sa2 = pool_elt_at_index (im->sad, sai2);
100  sa3 = pool_elt_at_index (im->sad, sai3);
101 
102  if (is_enc)
103  {
104  ti[0] = sa0->encrypt_thread_index;
105  ti[1] = sa1->encrypt_thread_index;
106  ti[2] = sa2->encrypt_thread_index;
107  ti[3] = sa3->encrypt_thread_index;
108  }
109  else
110  {
111  ti[0] = sa0->decrypt_thread_index;
112  ti[1] = sa1->decrypt_thread_index;
113  ti[2] = sa2->decrypt_thread_index;
114  ti[3] = sa3->decrypt_thread_index;
115  }
116 
117  if (node->flags & VLIB_NODE_FLAG_TRACE)
118  {
119  if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
120  {
122  vlib_add_trace (vm, node, b[0], sizeof (*t));
123  t->next_worker_index = ti[0];
124  }
125  if (PREDICT_FALSE (b[1]->flags & VLIB_BUFFER_IS_TRACED))
126  {
128  vlib_add_trace (vm, node, b[1], sizeof (*t));
129  t->next_worker_index = ti[1];
130  }
131  if (PREDICT_FALSE (b[2]->flags & VLIB_BUFFER_IS_TRACED))
132  {
134  vlib_add_trace (vm, node, b[2], sizeof (*t));
135  t->next_worker_index = ti[2];
136  }
137  if (PREDICT_FALSE (b[3]->flags & VLIB_BUFFER_IS_TRACED))
138  {
140  vlib_add_trace (vm, node, b[3], sizeof (*t));
141  t->next_worker_index = ti[3];
142  }
143  }
144 
145  n_left_from -= 4;
146  ti += 4;
147  b += 4;
148  }
149  while (n_left_from > 0)
150  {
151  ipsec_sa_t *sa0;
152  u32 sai0;
153 
154  sai0 = vnet_buffer (b[0])->ipsec.sad_index;
155  sa0 = pool_elt_at_index (im->sad, sai0);
156 
157  if (is_enc)
158  ti[0] = sa0->encrypt_thread_index;
159  else
160  ti[0] = sa0->decrypt_thread_index;
161 
162  if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
163  {
165  vlib_add_trace (vm, node, b[0], sizeof (*t));
166  t->next_worker_index = ti[0];
167  }
168 
169  n_left_from -= 1;
170  ti += 1;
171  b += 1;
172  }
173 
174  n_enq = vlib_buffer_enqueue_to_thread (vm, fq_index, from,
175  thread_indices, frame->n_vectors, 1);
176 
177  if (n_enq < frame->n_vectors)
179  IPSEC_HANDOFF_ERROR_CONGESTION_DROP,
180  frame->n_vectors - n_enq);
181 
182  return n_enq;
183 }
184 
187  vlib_frame_t * from_frame)
188 {
189  ipsec_main_t *im = &ipsec_main;
190 
191  return ipsec_handoff (vm, node, from_frame, im->esp4_enc_fq_index, true);
192 }
193 
196  vlib_frame_t * from_frame)
197 {
198  ipsec_main_t *im = &ipsec_main;
199 
200  return ipsec_handoff (vm, node, from_frame, im->esp6_enc_fq_index, true);
201 }
202 
205  vlib_frame_t * from_frame)
206 {
207  ipsec_main_t *im = &ipsec_main;
208 
209  return ipsec_handoff (vm, node, from_frame, im->esp4_enc_tun_fq_index,
210  true);
211 }
212 
215  vlib_frame_t * from_frame)
216 {
217  ipsec_main_t *im = &ipsec_main;
218 
219  return ipsec_handoff (vm, node, from_frame, im->esp6_enc_tun_fq_index,
220  true);
221 }
222 
225  vlib_frame_t * from_frame)
226 {
227  ipsec_main_t *im = &ipsec_main;
228 
229  return ipsec_handoff (vm, node, from_frame, im->esp4_dec_fq_index, false);
230 }
231 
234  vlib_frame_t * from_frame)
235 {
236  ipsec_main_t *im = &ipsec_main;
237 
238  return ipsec_handoff (vm, node, from_frame, im->esp6_dec_fq_index, false);
239 }
240 
243  vlib_frame_t * from_frame)
244 {
245  ipsec_main_t *im = &ipsec_main;
246 
247  return ipsec_handoff (vm, node, from_frame, im->esp4_dec_tun_fq_index,
248  false);
249 }
250 
253  vlib_frame_t * from_frame)
254 {
255  ipsec_main_t *im = &ipsec_main;
256 
257  return ipsec_handoff (vm, node, from_frame, im->esp6_dec_tun_fq_index,
258  false);
259 }
260 
263  vlib_frame_t * from_frame)
264 {
265  ipsec_main_t *im = &ipsec_main;
266 
267  return ipsec_handoff (vm, node, from_frame, im->ah4_enc_fq_index, true);
268 }
269 
272  vlib_frame_t * from_frame)
273 {
274  ipsec_main_t *im = &ipsec_main;
275 
276  return ipsec_handoff (vm, node, from_frame, im->ah6_enc_fq_index, true);
277 }
278 
281  vlib_frame_t * from_frame)
282 {
283  ipsec_main_t *im = &ipsec_main;
284 
285  return ipsec_handoff (vm, node, from_frame, im->ah4_dec_fq_index, false);
286 }
287 
290  vlib_frame_t * from_frame)
291 {
292  ipsec_main_t *im = &ipsec_main;
293 
294  return ipsec_handoff (vm, node, from_frame, im->ah6_dec_fq_index, false);
295 }
296 
297 /* *INDENT-OFF* */
299  .name = "esp4-encrypt-handoff",
300  .vector_size = sizeof (u32),
301  .format_trace = format_ipsec_handoff_trace,
304  .error_strings = ipsec_handoff_error_strings,
305  .n_next_nodes = 1,
306  .next_nodes = {
307  [0] = "error-drop",
308  },
309 };
311  .name = "esp6-encrypt-handoff",
312  .vector_size = sizeof (u32),
313  .format_trace = format_ipsec_handoff_trace,
316  .error_strings = ipsec_handoff_error_strings,
317  .n_next_nodes = 1,
318  .next_nodes = {
319  [0] = "error-drop",
320  },
321 };
323  .name = "esp4-encrypt-tun-handoff",
324  .vector_size = sizeof (u32),
325  .format_trace = format_ipsec_handoff_trace,
328  .error_strings = ipsec_handoff_error_strings,
329  .n_next_nodes = 1,
330  .next_nodes = {
331  [0] = "error-drop",
332  },
333 };
335  .name = "esp6-encrypt-tun-handoff",
336  .vector_size = sizeof (u32),
337  .format_trace = format_ipsec_handoff_trace,
340  .error_strings = ipsec_handoff_error_strings,
341  .n_next_nodes = 1,
342  .next_nodes = {
343  [0] = "error-drop",
344  },
345 };
347  .name = "esp4-decrypt-handoff",
348  .vector_size = sizeof (u32),
349  .format_trace = format_ipsec_handoff_trace,
352  .error_strings = ipsec_handoff_error_strings,
353  .n_next_nodes = 1,
354  .next_nodes = {
355  [0] = "error-drop",
356  },
357 };
359  .name = "esp6-decrypt-handoff",
360  .vector_size = sizeof (u32),
361  .format_trace = format_ipsec_handoff_trace,
364  .error_strings = ipsec_handoff_error_strings,
365  .n_next_nodes = 1,
366  .next_nodes = {
367  [0] = "error-drop",
368  },
369 };
371  .name = "esp4-decrypt-tun-handoff",
372  .vector_size = sizeof (u32),
373  .format_trace = format_ipsec_handoff_trace,
376  .error_strings = ipsec_handoff_error_strings,
377  .n_next_nodes = 1,
378  .next_nodes = {
379  [0] = "error-drop",
380  },
381 };
383  .name = "esp6-decrypt-tun-handoff",
384  .vector_size = sizeof (u32),
385  .format_trace = format_ipsec_handoff_trace,
388  .error_strings = ipsec_handoff_error_strings,
389  .n_next_nodes = 1,
390  .next_nodes = {
391  [0] = "error-drop",
392  },
393 };
395  .name = "ah4-encrypt-handoff",
396  .vector_size = sizeof (u32),
397  .format_trace = format_ipsec_handoff_trace,
400  .error_strings = ipsec_handoff_error_strings,
401  .n_next_nodes = 1,
402  .next_nodes = {
403  [0] = "error-drop",
404  },
405 };
407  .name = "ah6-encrypt-handoff",
408  .vector_size = sizeof (u32),
409  .format_trace = format_ipsec_handoff_trace,
412  .error_strings = ipsec_handoff_error_strings,
413  .n_next_nodes = 1,
414  .next_nodes = {
415  [0] = "error-drop",
416  },
417 };
419  .name = "ah4-decrypt-handoff",
420  .vector_size = sizeof (u32),
421  .format_trace = format_ipsec_handoff_trace,
424  .error_strings = ipsec_handoff_error_strings,
425  .n_next_nodes = 1,
426  .next_nodes = {
427  [0] = "error-drop",
428  },
429 };
431  .name = "ah6-decrypt-handoff",
432  .vector_size = sizeof (u32),
433  .format_trace = format_ipsec_handoff_trace,
436  .error_strings = ipsec_handoff_error_strings,
437  .n_next_nodes = 1,
438  .next_nodes = {
439  [0] = "error-drop",
440  },
441 };
442 /* *INDENT-ON* */
443 
444 /*
445  * fd.io coding-style-patch-verification: ON
446  *
447  * Local Variables:
448  * eval: (c-set-style "gnu")
449  * End:
450  */
vlib_node_registration_t esp6_decrypt_handoff
(constructor) VLIB_REGISTER_NODE (esp6_decrypt_handoff)
struct ipsec_handoff_trace_t_ ipsec_handoff_trace_t
vlib_node_registration_t ah6_encrypt_handoff
(constructor) VLIB_REGISTER_NODE (ah6_encrypt_handoff)
#define CLIB_UNUSED(x)
Definition: clib.h:87
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:103
vlib_node_registration_t esp6_encrypt_tun_handoff
(constructor) VLIB_REGISTER_NODE (esp6_encrypt_tun_handoff)
static u8 * format_ipsec_handoff_trace(u8 *s, va_list *args)
Definition: ipsec_handoff.c:44
vlib_main_t * vm
Definition: in2out_ed.c:1582
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
static_always_inline uword ipsec_handoff(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, u32 fq_index, bool is_enc)
Definition: ipsec_handoff.c:57
#define VLIB_NODE_FN(node)
Definition: node.h:202
unsigned char u8
Definition: types.h:56
vlib_node_registration_t esp4_decrypt_tun_handoff
(constructor) VLIB_REGISTER_NODE (esp4_decrypt_tun_handoff)
u32 esp4_enc_tun_fq_index
Definition: ipsec.h:197
#define static_always_inline
Definition: clib.h:108
ipsec_main_t ipsec_main
Definition: ipsec.c:28
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:203
u32 esp4_dec_tun_fq_index
Definition: ipsec.h:199
u32 ah6_dec_fq_index
Definition: ipsec.h:191
static char * ipsec_handoff_error_strings[]
Definition: ipsec_handoff.c:32
u32 esp4_dec_fq_index
Definition: ipsec.h:194
unsigned int u32
Definition: types.h:88
#define VLIB_FRAME_SIZE
Definition: node.h:377
vl_api_fib_path_type_t type
Definition: fib_types.api:123
u32 encrypt_thread_index
Definition: ipsec_sa.h:118
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
unsigned short u16
Definition: types.h:57
vlib_node_registration_t esp4_encrypt_tun_handoff
(constructor) VLIB_REGISTER_NODE (esp4_encrypt_tun_handoff)
u32 esp6_dec_tun_fq_index
Definition: ipsec.h:200
vlib_node_registration_t esp6_decrypt_tun_handoff
(constructor) VLIB_REGISTER_NODE (esp6_decrypt_tun_handoff)
#define PREDICT_FALSE(x)
Definition: clib.h:120
u32 ah4_enc_fq_index
Worker handoff.
Definition: ipsec.h:188
u32 node_index
Node index.
Definition: node.h:487
u32 ah4_dec_fq_index
Definition: ipsec.h:189
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1231
u32 ah6_enc_fq_index
Definition: ipsec.h:190
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:396
u32 esp6_enc_tun_fq_index
Definition: ipsec.h:198
#define vlib_prefetch_buffer_data(b, type)
Definition: buffer.h:204
#define ARRAY_LEN(x)
Definition: clib.h:67
vlib_node_registration_t ah4_encrypt_handoff
(constructor) VLIB_REGISTER_NODE (ah4_encrypt_handoff)
vlib_node_registration_t esp4_encrypt_handoff
(constructor) VLIB_REGISTER_NODE (esp4_encrypt_handoff)
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1582
u32 esp6_dec_fq_index
Definition: ipsec.h:196
vlib_node_registration_t ah4_decrypt_handoff
(constructor) VLIB_REGISTER_NODE (ah4_decrypt_handoff)
u32 esp6_enc_fq_index
Definition: ipsec.h:195
vlib_node_registration_t ah6_decrypt_handoff
(constructor) VLIB_REGISTER_NODE (ah6_decrypt_handoff)
ipsec_sa_t * sad
Definition: ipsec.h:107
vlib_node_registration_t esp6_encrypt_handoff
(constructor) VLIB_REGISTER_NODE (esp6_encrypt_handoff)
#define foreach_ipsec_handoff_error
Definition: ipsec_handoff.c:21
u32 esp4_enc_fq_index
Definition: ipsec.h:193
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1583
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
ipsec_handoff_error_t
Definition: ipsec_handoff.c:24
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:297
vlib_node_registration_t esp4_decrypt_handoff
(constructor) VLIB_REGISTER_NODE (esp4_decrypt_handoff)
static_always_inline u32 vlib_buffer_enqueue_to_thread(vlib_main_t *vm, u32 frame_queue_index, u32 *buffer_indices, u16 *thread_indices, u32 n_packets, int drop_on_congestion)
Definition: buffer_node.h:494
#define vnet_buffer(b)
Definition: buffer.h:417
u16 flags
Copy of main node flags.
Definition: node.h:500
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:577
static_always_inline void vlib_get_buffers(vlib_main_t *vm, u32 *bi, vlib_buffer_t **b, int count)
Translate array of buffer indices into buffer pointers.
Definition: buffer_funcs.h:280
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:301
u32 decrypt_thread_index
Definition: ipsec_sa.h:119