2 * esp_encrypt.c : IPSec ESP encrypt node
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <vnet/ipsec/ipsec.h>
19 #include <vnet/ipsec/ipsec_sa.h>
21 #define foreach_ipsec_handoff_error \
22 _(CONGESTION_DROP, "congestion drop")
26 #define _(sym,str) IPSEC_HANDOFF_ERROR_##sym,
27 foreach_ipsec_handoff_error
29 NAT44_HANDOFF_N_ERROR,
30 } ipsec_handoff_error_t;
32 static char *ipsec_handoff_error_strings[] = {
33 #define _(sym,string) string,
34 foreach_ipsec_handoff_error
38 typedef struct ipsec_handoff_trace_t_
40 u32 next_worker_index;
41 } ipsec_handoff_trace_t;
44 format_ipsec_handoff_trace (u8 * s, va_list * args)
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 *);
50 s = format (s, "next-worker %d", t->next_worker_index);
55 /* do worker handoff based on thread_index in NAT HA protcol header */
56 static_always_inline uword
57 ipsec_handoff (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame,
60 vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
61 u16 thread_indices[VLIB_FRAME_SIZE], *ti;
62 u32 n_enq, n_left_from, *from;
66 from = vlib_frame_vector_args (frame);
67 n_left_from = frame->n_vectors;
68 vlib_get_buffers (vm, from, bufs, n_left_from);
73 while (n_left_from >= 4)
75 ipsec_sa_t *sa0, *sa1, *sa2, *sa3;
76 u32 sai0, sai1, sai2, sai3;
78 /* Prefetch next iteration. */
79 if (n_left_from >= 12)
81 vlib_prefetch_buffer_header (b[8], LOAD);
82 vlib_prefetch_buffer_header (b[9], LOAD);
83 vlib_prefetch_buffer_header (b[10], LOAD);
84 vlib_prefetch_buffer_header (b[11], LOAD);
86 vlib_prefetch_buffer_data (b[4], LOAD);
87 vlib_prefetch_buffer_data (b[5], LOAD);
88 vlib_prefetch_buffer_data (b[6], LOAD);
89 vlib_prefetch_buffer_data (b[7], LOAD);
92 sai0 = vnet_buffer (b[0])->ipsec.sad_index;
93 sai1 = vnet_buffer (b[1])->ipsec.sad_index;
94 sai2 = vnet_buffer (b[2])->ipsec.sad_index;
95 sai3 = vnet_buffer (b[3])->ipsec.sad_index;
96 sa0 = pool_elt_at_index (im->sad, sai0);
97 sa1 = pool_elt_at_index (im->sad, sai1);
98 sa2 = pool_elt_at_index (im->sad, sai2);
99 sa3 = pool_elt_at_index (im->sad, sai3);
101 ti[0] = sa0->thread_index;
102 ti[1] = sa1->thread_index;
103 ti[2] = sa2->thread_index;
104 ti[3] = sa3->thread_index;
106 if (node->flags & VLIB_NODE_FLAG_TRACE)
108 if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
110 ipsec_handoff_trace_t *t =
111 vlib_add_trace (vm, node, b[0], sizeof (*t));
112 t->next_worker_index = ti[0];
114 if (PREDICT_FALSE (b[1]->flags & VLIB_BUFFER_IS_TRACED))
116 ipsec_handoff_trace_t *t =
117 vlib_add_trace (vm, node, b[1], sizeof (*t));
118 t->next_worker_index = ti[1];
120 if (PREDICT_FALSE (b[2]->flags & VLIB_BUFFER_IS_TRACED))
122 ipsec_handoff_trace_t *t =
123 vlib_add_trace (vm, node, b[2], sizeof (*t));
124 t->next_worker_index = ti[2];
126 if (PREDICT_FALSE (b[3]->flags & VLIB_BUFFER_IS_TRACED))
128 ipsec_handoff_trace_t *t =
129 vlib_add_trace (vm, node, b[3], sizeof (*t));
130 t->next_worker_index = ti[3];
138 while (n_left_from > 0)
143 sai0 = vnet_buffer (b[0])->ipsec.sad_index;
144 sa0 = pool_elt_at_index (im->sad, sai0);
146 ti[0] = sa0->thread_index;
148 if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
150 ipsec_handoff_trace_t *t =
151 vlib_add_trace (vm, node, b[0], sizeof (*t));
152 t->next_worker_index = ti[0];
160 n_enq = vlib_buffer_enqueue_to_thread (vm, fq_index, from,
161 thread_indices, frame->n_vectors, 1);
163 if (n_enq < frame->n_vectors)
164 vlib_node_increment_counter (vm, node->node_index,
165 IPSEC_HANDOFF_ERROR_CONGESTION_DROP,
166 frame->n_vectors - n_enq);
171 VLIB_NODE_FN (esp4_encrypt_handoff) (vlib_main_t * vm,
172 vlib_node_runtime_t * node,
173 vlib_frame_t * from_frame)
175 ipsec_main_t *im = &ipsec_main;
177 return ipsec_handoff (vm, node, from_frame, im->esp4_enc_fq_index);
180 VLIB_NODE_FN (esp6_encrypt_handoff) (vlib_main_t * vm,
181 vlib_node_runtime_t * node,
182 vlib_frame_t * from_frame)
184 ipsec_main_t *im = &ipsec_main;
186 return ipsec_handoff (vm, node, from_frame, im->esp6_enc_fq_index);
189 VLIB_NODE_FN (esp4_encrypt_tun_handoff) (vlib_main_t * vm,
190 vlib_node_runtime_t * node,
191 vlib_frame_t * from_frame)
193 ipsec_main_t *im = &ipsec_main;
195 return ipsec_handoff (vm, node, from_frame, im->esp4_enc_tun_fq_index);
198 VLIB_NODE_FN (esp6_encrypt_tun_handoff) (vlib_main_t * vm,
199 vlib_node_runtime_t * node,
200 vlib_frame_t * from_frame)
202 ipsec_main_t *im = &ipsec_main;
204 return ipsec_handoff (vm, node, from_frame, im->esp6_enc_tun_fq_index);
207 VLIB_NODE_FN (esp_mpls_encrypt_tun_handoff)
208 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
210 ipsec_main_t *im = &ipsec_main;
212 return ipsec_handoff (vm, node, from_frame, im->esp_mpls_enc_tun_fq_index);
215 VLIB_NODE_FN (esp4_decrypt_handoff) (vlib_main_t * vm,
216 vlib_node_runtime_t * node,
217 vlib_frame_t * from_frame)
219 ipsec_main_t *im = &ipsec_main;
221 return ipsec_handoff (vm, node, from_frame, im->esp4_dec_fq_index);
224 VLIB_NODE_FN (esp6_decrypt_handoff) (vlib_main_t * vm,
225 vlib_node_runtime_t * node,
226 vlib_frame_t * from_frame)
228 ipsec_main_t *im = &ipsec_main;
230 return ipsec_handoff (vm, node, from_frame, im->esp6_dec_fq_index);
233 VLIB_NODE_FN (esp4_decrypt_tun_handoff) (vlib_main_t * vm,
234 vlib_node_runtime_t * node,
235 vlib_frame_t * from_frame)
237 ipsec_main_t *im = &ipsec_main;
239 return ipsec_handoff (vm, node, from_frame, im->esp4_dec_tun_fq_index);
242 VLIB_NODE_FN (esp6_decrypt_tun_handoff) (vlib_main_t * vm,
243 vlib_node_runtime_t * node,
244 vlib_frame_t * from_frame)
246 ipsec_main_t *im = &ipsec_main;
248 return ipsec_handoff (vm, node, from_frame, im->esp6_dec_tun_fq_index);
251 VLIB_NODE_FN (ah4_encrypt_handoff) (vlib_main_t * vm,
252 vlib_node_runtime_t * node,
253 vlib_frame_t * from_frame)
255 ipsec_main_t *im = &ipsec_main;
257 return ipsec_handoff (vm, node, from_frame, im->ah4_enc_fq_index);
260 VLIB_NODE_FN (ah6_encrypt_handoff) (vlib_main_t * vm,
261 vlib_node_runtime_t * node,
262 vlib_frame_t * from_frame)
264 ipsec_main_t *im = &ipsec_main;
266 return ipsec_handoff (vm, node, from_frame, im->ah6_enc_fq_index);
269 VLIB_NODE_FN (ah4_decrypt_handoff) (vlib_main_t * vm,
270 vlib_node_runtime_t * node,
271 vlib_frame_t * from_frame)
273 ipsec_main_t *im = &ipsec_main;
275 return ipsec_handoff (vm, node, from_frame, im->ah4_dec_fq_index);
278 VLIB_NODE_FN (ah6_decrypt_handoff) (vlib_main_t * vm,
279 vlib_node_runtime_t * node,
280 vlib_frame_t * from_frame)
282 ipsec_main_t *im = &ipsec_main;
284 return ipsec_handoff (vm, node, from_frame, im->ah6_dec_fq_index);
288 VLIB_REGISTER_NODE (esp4_encrypt_handoff) = {
289 .name = "esp4-encrypt-handoff",
290 .vector_size = sizeof (u32),
291 .format_trace = format_ipsec_handoff_trace,
292 .type = VLIB_NODE_TYPE_INTERNAL,
293 .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
294 .error_strings = ipsec_handoff_error_strings,
300 VLIB_REGISTER_NODE (esp6_encrypt_handoff) = {
301 .name = "esp6-encrypt-handoff",
302 .vector_size = sizeof (u32),
303 .format_trace = format_ipsec_handoff_trace,
304 .type = VLIB_NODE_TYPE_INTERNAL,
305 .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
306 .error_strings = ipsec_handoff_error_strings,
312 VLIB_REGISTER_NODE (esp4_encrypt_tun_handoff) = {
313 .name = "esp4-encrypt-tun-handoff",
314 .vector_size = sizeof (u32),
315 .format_trace = format_ipsec_handoff_trace,
316 .type = VLIB_NODE_TYPE_INTERNAL,
317 .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
318 .error_strings = ipsec_handoff_error_strings,
324 VLIB_REGISTER_NODE (esp6_encrypt_tun_handoff) = {
325 .name = "esp6-encrypt-tun-handoff",
326 .vector_size = sizeof (u32),
327 .format_trace = format_ipsec_handoff_trace,
328 .type = VLIB_NODE_TYPE_INTERNAL,
329 .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
330 .error_strings = ipsec_handoff_error_strings,
336 VLIB_REGISTER_NODE (esp_mpls_encrypt_tun_handoff) = {
337 .name = "esp-mpls-encrypt-tun-handoff",
338 .vector_size = sizeof (u32),
339 .format_trace = format_ipsec_handoff_trace,
340 .type = VLIB_NODE_TYPE_INTERNAL,
341 .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
342 .error_strings = ipsec_handoff_error_strings,
348 VLIB_REGISTER_NODE (esp4_decrypt_handoff) = {
349 .name = "esp4-decrypt-handoff",
350 .vector_size = sizeof (u32),
351 .format_trace = format_ipsec_handoff_trace,
352 .type = VLIB_NODE_TYPE_INTERNAL,
353 .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
354 .error_strings = ipsec_handoff_error_strings,
360 VLIB_REGISTER_NODE (esp6_decrypt_handoff) = {
361 .name = "esp6-decrypt-handoff",
362 .vector_size = sizeof (u32),
363 .format_trace = format_ipsec_handoff_trace,
364 .type = VLIB_NODE_TYPE_INTERNAL,
365 .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
366 .error_strings = ipsec_handoff_error_strings,
372 VLIB_REGISTER_NODE (esp4_decrypt_tun_handoff) = {
373 .name = "esp4-decrypt-tun-handoff",
374 .vector_size = sizeof (u32),
375 .format_trace = format_ipsec_handoff_trace,
376 .type = VLIB_NODE_TYPE_INTERNAL,
377 .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
378 .error_strings = ipsec_handoff_error_strings,
384 VLIB_REGISTER_NODE (esp6_decrypt_tun_handoff) = {
385 .name = "esp6-decrypt-tun-handoff",
386 .vector_size = sizeof (u32),
387 .format_trace = format_ipsec_handoff_trace,
388 .type = VLIB_NODE_TYPE_INTERNAL,
389 .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
390 .error_strings = ipsec_handoff_error_strings,
396 VLIB_REGISTER_NODE (ah4_encrypt_handoff) = {
397 .name = "ah4-encrypt-handoff",
398 .vector_size = sizeof (u32),
399 .format_trace = format_ipsec_handoff_trace,
400 .type = VLIB_NODE_TYPE_INTERNAL,
401 .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
402 .error_strings = ipsec_handoff_error_strings,
408 VLIB_REGISTER_NODE (ah6_encrypt_handoff) = {
409 .name = "ah6-encrypt-handoff",
410 .vector_size = sizeof (u32),
411 .format_trace = format_ipsec_handoff_trace,
412 .type = VLIB_NODE_TYPE_INTERNAL,
413 .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
414 .error_strings = ipsec_handoff_error_strings,
420 VLIB_REGISTER_NODE (ah4_decrypt_handoff) = {
421 .name = "ah4-decrypt-handoff",
422 .vector_size = sizeof (u32),
423 .format_trace = format_ipsec_handoff_trace,
424 .type = VLIB_NODE_TYPE_INTERNAL,
425 .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
426 .error_strings = ipsec_handoff_error_strings,
432 VLIB_REGISTER_NODE (ah6_decrypt_handoff) = {
433 .name = "ah6-decrypt-handoff",
434 .vector_size = sizeof (u32),
435 .format_trace = format_ipsec_handoff_trace,
436 .type = VLIB_NODE_TYPE_INTERNAL,
437 .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
438 .error_strings = ipsec_handoff_error_strings,
447 * fd.io coding-style-patch-verification: ON
450 * eval: (c-set-style "gnu")