http: fix client parse error handling
[vpp.git] / src / vnet / ipsec / ipsec_handoff.c
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,
27   foreach_ipsec_handoff_error
28 #undef _
29     NAT44_HANDOFF_N_ERROR,
30 } ipsec_handoff_error_t;
31
32 static char *ipsec_handoff_error_strings[] = {
33 #define _(sym,string) string,
34   foreach_ipsec_handoff_error
35 #undef _
36 };
37
38 typedef struct ipsec_handoff_trace_t_
39 {
40   u32 next_worker_index;
41 } ipsec_handoff_trace_t;
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 */
56 static_always_inline uword
57 ipsec_handoff (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame,
58                u32 fq_index)
59 {
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;
63
64   from = vlib_frame_vector_args (frame);
65   n_left_from = frame->n_vectors;
66   vlib_get_buffers (vm, from, bufs, n_left_from);
67
68   b = bufs;
69   ti = thread_indices;
70
71   while (n_left_from >= 4)
72     {
73       /* Prefetch next iteration. */
74       if (n_left_from >= 12)
75         {
76           vlib_prefetch_buffer_header (b[8], LOAD);
77           vlib_prefetch_buffer_header (b[9], LOAD);
78           vlib_prefetch_buffer_header (b[10], LOAD);
79           vlib_prefetch_buffer_header (b[11], LOAD);
80         }
81
82       ti[0] = vnet_buffer (b[0])->ipsec.thread_index;
83       ti[1] = vnet_buffer (b[1])->ipsec.thread_index;
84       ti[2] = vnet_buffer (b[2])->ipsec.thread_index;
85       ti[3] = vnet_buffer (b[3])->ipsec.thread_index;
86
87       if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
88         {
89           if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
90             {
91               ipsec_handoff_trace_t *t =
92                 vlib_add_trace (vm, node, b[0], sizeof (*t));
93               t->next_worker_index = ti[0];
94             }
95           if (PREDICT_FALSE (b[1]->flags & VLIB_BUFFER_IS_TRACED))
96             {
97               ipsec_handoff_trace_t *t =
98                 vlib_add_trace (vm, node, b[1], sizeof (*t));
99               t->next_worker_index = ti[1];
100             }
101           if (PREDICT_FALSE (b[2]->flags & VLIB_BUFFER_IS_TRACED))
102             {
103               ipsec_handoff_trace_t *t =
104                 vlib_add_trace (vm, node, b[2], sizeof (*t));
105               t->next_worker_index = ti[2];
106             }
107           if (PREDICT_FALSE (b[3]->flags & VLIB_BUFFER_IS_TRACED))
108             {
109               ipsec_handoff_trace_t *t =
110                 vlib_add_trace (vm, node, b[3], sizeof (*t));
111               t->next_worker_index = ti[3];
112             }
113         }
114
115       n_left_from -= 4;
116       ti += 4;
117       b += 4;
118     }
119   while (n_left_from > 0)
120     {
121       ti[0] = vnet_buffer (b[0])->ipsec.thread_index;
122
123       if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
124         {
125           ipsec_handoff_trace_t *t =
126             vlib_add_trace (vm, node, b[0], sizeof (*t));
127           t->next_worker_index = ti[0];
128         }
129
130       n_left_from -= 1;
131       ti += 1;
132       b += 1;
133     }
134
135   n_enq = vlib_buffer_enqueue_to_thread (vm, node, fq_index, from,
136                                          thread_indices, frame->n_vectors, 1);
137
138   if (n_enq < frame->n_vectors)
139     vlib_node_increment_counter (vm, node->node_index,
140                                  IPSEC_HANDOFF_ERROR_CONGESTION_DROP,
141                                  frame->n_vectors - n_enq);
142
143   return n_enq;
144 }
145
146 VLIB_NODE_FN (esp4_encrypt_handoff) (vlib_main_t * vm,
147                                      vlib_node_runtime_t * node,
148                                      vlib_frame_t * from_frame)
149 {
150   ipsec_main_t *im = &ipsec_main;
151
152   return ipsec_handoff (vm, node, from_frame, im->esp4_enc_fq_index);
153 }
154
155 VLIB_NODE_FN (esp6_encrypt_handoff) (vlib_main_t * vm,
156                                      vlib_node_runtime_t * node,
157                                      vlib_frame_t * from_frame)
158 {
159   ipsec_main_t *im = &ipsec_main;
160
161   return ipsec_handoff (vm, node, from_frame, im->esp6_enc_fq_index);
162 }
163
164 VLIB_NODE_FN (esp4_encrypt_tun_handoff) (vlib_main_t * vm,
165                                          vlib_node_runtime_t * node,
166                                          vlib_frame_t * from_frame)
167 {
168   ipsec_main_t *im = &ipsec_main;
169
170   return ipsec_handoff (vm, node, from_frame, im->esp4_enc_tun_fq_index);
171 }
172
173 VLIB_NODE_FN (esp6_encrypt_tun_handoff) (vlib_main_t * vm,
174                                          vlib_node_runtime_t * node,
175                                          vlib_frame_t * from_frame)
176 {
177   ipsec_main_t *im = &ipsec_main;
178
179   return ipsec_handoff (vm, node, from_frame, im->esp6_enc_tun_fq_index);
180 }
181
182 VLIB_NODE_FN (esp_mpls_encrypt_tun_handoff)
183 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
184 {
185   ipsec_main_t *im = &ipsec_main;
186
187   return ipsec_handoff (vm, node, from_frame, im->esp_mpls_enc_tun_fq_index);
188 }
189
190 VLIB_NODE_FN (esp4_decrypt_handoff) (vlib_main_t * vm,
191                                      vlib_node_runtime_t * node,
192                                      vlib_frame_t * from_frame)
193 {
194   ipsec_main_t *im = &ipsec_main;
195
196   return ipsec_handoff (vm, node, from_frame, im->esp4_dec_fq_index);
197 }
198
199 VLIB_NODE_FN (esp6_decrypt_handoff) (vlib_main_t * vm,
200                                      vlib_node_runtime_t * node,
201                                      vlib_frame_t * from_frame)
202 {
203   ipsec_main_t *im = &ipsec_main;
204
205   return ipsec_handoff (vm, node, from_frame, im->esp6_dec_fq_index);
206 }
207
208 VLIB_NODE_FN (esp4_decrypt_tun_handoff) (vlib_main_t * vm,
209                                          vlib_node_runtime_t * node,
210                                          vlib_frame_t * from_frame)
211 {
212   ipsec_main_t *im = &ipsec_main;
213
214   return ipsec_handoff (vm, node, from_frame, im->esp4_dec_tun_fq_index);
215 }
216
217 VLIB_NODE_FN (esp6_decrypt_tun_handoff) (vlib_main_t * vm,
218                                          vlib_node_runtime_t * node,
219                                          vlib_frame_t * from_frame)
220 {
221   ipsec_main_t *im = &ipsec_main;
222
223   return ipsec_handoff (vm, node, from_frame, im->esp6_dec_tun_fq_index);
224 }
225
226 VLIB_NODE_FN (ah4_encrypt_handoff) (vlib_main_t * vm,
227                                     vlib_node_runtime_t * node,
228                                     vlib_frame_t * from_frame)
229 {
230   ipsec_main_t *im = &ipsec_main;
231
232   return ipsec_handoff (vm, node, from_frame, im->ah4_enc_fq_index);
233 }
234
235 VLIB_NODE_FN (ah6_encrypt_handoff) (vlib_main_t * vm,
236                                     vlib_node_runtime_t * node,
237                                     vlib_frame_t * from_frame)
238 {
239   ipsec_main_t *im = &ipsec_main;
240
241   return ipsec_handoff (vm, node, from_frame, im->ah6_enc_fq_index);
242 }
243
244 VLIB_NODE_FN (ah4_decrypt_handoff) (vlib_main_t * vm,
245                                     vlib_node_runtime_t * node,
246                                     vlib_frame_t * from_frame)
247 {
248   ipsec_main_t *im = &ipsec_main;
249
250   return ipsec_handoff (vm, node, from_frame, im->ah4_dec_fq_index);
251 }
252
253 VLIB_NODE_FN (ah6_decrypt_handoff) (vlib_main_t * vm,
254                                     vlib_node_runtime_t * node,
255                                     vlib_frame_t * from_frame)
256 {
257   ipsec_main_t *im = &ipsec_main;
258
259   return ipsec_handoff (vm, node, from_frame, im->ah6_dec_fq_index);
260 }
261
262 VLIB_REGISTER_NODE (esp4_encrypt_handoff) = {
263   .name = "esp4-encrypt-handoff",
264   .vector_size = sizeof (u32),
265   .format_trace = format_ipsec_handoff_trace,
266   .type = VLIB_NODE_TYPE_INTERNAL,
267   .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
268   .error_strings = ipsec_handoff_error_strings,
269   .n_next_nodes = 1,
270   .next_nodes = {
271     [0] = "error-drop",
272   },
273 };
274 VLIB_REGISTER_NODE (esp6_encrypt_handoff) = {
275   .name = "esp6-encrypt-handoff",
276   .vector_size = sizeof (u32),
277   .format_trace = format_ipsec_handoff_trace,
278   .type = VLIB_NODE_TYPE_INTERNAL,
279   .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
280   .error_strings = ipsec_handoff_error_strings,
281   .n_next_nodes = 1,
282   .next_nodes = {
283     [0] = "error-drop",
284   },
285 };
286 VLIB_REGISTER_NODE (esp4_encrypt_tun_handoff) = {
287   .name = "esp4-encrypt-tun-handoff",
288   .vector_size = sizeof (u32),
289   .format_trace = format_ipsec_handoff_trace,
290   .type = VLIB_NODE_TYPE_INTERNAL,
291   .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
292   .error_strings = ipsec_handoff_error_strings,
293   .n_next_nodes = 1,
294   .next_nodes = {
295     [0] = "error-drop",
296   },
297 };
298 VLIB_REGISTER_NODE (esp6_encrypt_tun_handoff) = {
299   .name = "esp6-encrypt-tun-handoff",
300   .vector_size = sizeof (u32),
301   .format_trace = format_ipsec_handoff_trace,
302   .type = VLIB_NODE_TYPE_INTERNAL,
303   .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
304   .error_strings = ipsec_handoff_error_strings,
305   .n_next_nodes = 1,
306   .next_nodes = {
307     [0] = "error-drop",
308   },
309 };
310 VLIB_REGISTER_NODE (esp_mpls_encrypt_tun_handoff) = {
311   .name = "esp-mpls-encrypt-tun-handoff",
312   .vector_size = sizeof (u32),
313   .format_trace = format_ipsec_handoff_trace,
314   .type = VLIB_NODE_TYPE_INTERNAL,
315   .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
316   .error_strings = ipsec_handoff_error_strings,
317   .n_next_nodes = 1,
318   .next_nodes = {
319     [0] = "error-drop",
320   },
321 };
322 VLIB_REGISTER_NODE (esp4_decrypt_handoff) = {
323   .name = "esp4-decrypt-handoff",
324   .vector_size = sizeof (u32),
325   .format_trace = format_ipsec_handoff_trace,
326   .type = VLIB_NODE_TYPE_INTERNAL,
327   .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
328   .error_strings = ipsec_handoff_error_strings,
329   .n_next_nodes = 1,
330   .next_nodes = {
331     [0] = "error-drop",
332   },
333 };
334 VLIB_REGISTER_NODE (esp6_decrypt_handoff) = {
335   .name = "esp6-decrypt-handoff",
336   .vector_size = sizeof (u32),
337   .format_trace = format_ipsec_handoff_trace,
338   .type = VLIB_NODE_TYPE_INTERNAL,
339   .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
340   .error_strings = ipsec_handoff_error_strings,
341   .n_next_nodes = 1,
342   .next_nodes = {
343     [0] = "error-drop",
344   },
345 };
346 VLIB_REGISTER_NODE (esp4_decrypt_tun_handoff) = {
347   .name = "esp4-decrypt-tun-handoff",
348   .vector_size = sizeof (u32),
349   .format_trace = format_ipsec_handoff_trace,
350   .type = VLIB_NODE_TYPE_INTERNAL,
351   .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
352   .error_strings = ipsec_handoff_error_strings,
353   .n_next_nodes = 1,
354   .next_nodes = {
355     [0] = "error-drop",
356   },
357 };
358 VLIB_REGISTER_NODE (esp6_decrypt_tun_handoff) = {
359   .name = "esp6-decrypt-tun-handoff",
360   .vector_size = sizeof (u32),
361   .format_trace = format_ipsec_handoff_trace,
362   .type = VLIB_NODE_TYPE_INTERNAL,
363   .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
364   .error_strings = ipsec_handoff_error_strings,
365   .n_next_nodes = 1,
366   .next_nodes = {
367     [0] = "error-drop",
368   },
369 };
370 VLIB_REGISTER_NODE (ah4_encrypt_handoff) = {
371   .name = "ah4-encrypt-handoff",
372   .vector_size = sizeof (u32),
373   .format_trace = format_ipsec_handoff_trace,
374   .type = VLIB_NODE_TYPE_INTERNAL,
375   .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
376   .error_strings = ipsec_handoff_error_strings,
377   .n_next_nodes = 1,
378   .next_nodes = {
379     [0] = "error-drop",
380   },
381 };
382 VLIB_REGISTER_NODE (ah6_encrypt_handoff) = {
383   .name = "ah6-encrypt-handoff",
384   .vector_size = sizeof (u32),
385   .format_trace = format_ipsec_handoff_trace,
386   .type = VLIB_NODE_TYPE_INTERNAL,
387   .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
388   .error_strings = ipsec_handoff_error_strings,
389   .n_next_nodes = 1,
390   .next_nodes = {
391     [0] = "error-drop",
392   },
393 };
394 VLIB_REGISTER_NODE (ah4_decrypt_handoff) = {
395   .name = "ah4-decrypt-handoff",
396   .vector_size = sizeof (u32),
397   .format_trace = format_ipsec_handoff_trace,
398   .type = VLIB_NODE_TYPE_INTERNAL,
399   .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
400   .error_strings = ipsec_handoff_error_strings,
401   .n_next_nodes = 1,
402   .next_nodes = {
403     [0] = "error-drop",
404   },
405 };
406 VLIB_REGISTER_NODE (ah6_decrypt_handoff) = {
407   .name = "ah6-decrypt-handoff",
408   .vector_size = sizeof (u32),
409   .format_trace = format_ipsec_handoff_trace,
410   .type = VLIB_NODE_TYPE_INTERNAL,
411   .n_errors = ARRAY_LEN(ipsec_handoff_error_strings),
412   .error_strings = ipsec_handoff_error_strings,
413   .n_next_nodes = 1,
414   .next_nodes = {
415     [0] = "error-drop",
416   },
417 };
418
419 /*
420  * fd.io coding-style-patch-verification: ON
421  *
422  * Local Variables:
423  * eval: (c-set-style "gnu")
424  * End:
425  */