ipsec: remove pending node
[vpp.git] / src / vnet / ipsec / esp_encrypt.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/vnet.h>
19 #include <vnet/api_errno.h>
20 #include <vnet/ip/ip.h>
21
22 #include <vnet/crypto/crypto.h>
23
24 #include <vnet/ipsec/ipsec.h>
25 #include <vnet/ipsec/ipsec_tun.h>
26 #include <vnet/ipsec/esp.h>
27
28 #define foreach_esp_encrypt_next                   \
29 _(DROP4, "ip4-drop")                               \
30 _(DROP6, "ip6-drop")                               \
31 _(HANDOFF4, "handoff4")                            \
32 _(HANDOFF6, "handoff6")                            \
33 _(INTERFACE_OUTPUT, "interface-output")
34
35 #define _(v, s) ESP_ENCRYPT_NEXT_##v,
36 typedef enum
37 {
38   foreach_esp_encrypt_next
39 #undef _
40     ESP_ENCRYPT_N_NEXT,
41 } esp_encrypt_next_t;
42
43 #define foreach_esp_encrypt_error                               \
44  _(RX_PKTS, "ESP pkts received")                                \
45  _(POST_RX_PKTS, "ESP-post pkts received")                      \
46  _(SEQ_CYCLED, "sequence number cycled (packet dropped)")       \
47  _(CRYPTO_ENGINE_ERROR, "crypto engine error (packet dropped)") \
48  _(CRYPTO_QUEUE_FULL, "crypto queue full (packet dropped)")     \
49  _(NO_BUFFERS, "no buffers (packet dropped)")                   \
50
51 typedef enum
52 {
53 #define _(sym,str) ESP_ENCRYPT_ERROR_##sym,
54   foreach_esp_encrypt_error
55 #undef _
56     ESP_ENCRYPT_N_ERROR,
57 } esp_encrypt_error_t;
58
59 static char *esp_encrypt_error_strings[] = {
60 #define _(sym,string) string,
61   foreach_esp_encrypt_error
62 #undef _
63 };
64
65 typedef struct
66 {
67   u32 sa_index;
68   u32 spi;
69   u32 seq;
70   u32 sa_seq_hi;
71   u8 udp_encap;
72   ipsec_crypto_alg_t crypto_alg;
73   ipsec_integ_alg_t integ_alg;
74 } esp_encrypt_trace_t;
75
76 typedef struct
77 {
78   u32 next_index;
79 } esp_encrypt_post_trace_t;
80
81 /* packet trace format function */
82 static u8 *
83 format_esp_encrypt_trace (u8 * s, va_list * args)
84 {
85   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
86   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
87   esp_encrypt_trace_t *t = va_arg (*args, esp_encrypt_trace_t *);
88
89   s =
90     format (s,
91             "esp: sa-index %d spi %u (0x%08x) seq %u sa-seq-hi %u crypto %U integrity %U%s",
92             t->sa_index, t->spi, t->spi, t->seq, t->sa_seq_hi,
93             format_ipsec_crypto_alg,
94             t->crypto_alg, format_ipsec_integ_alg, t->integ_alg,
95             t->udp_encap ? " udp-encap-enabled" : "");
96   return s;
97 }
98
99 static u8 *
100 format_esp_post_encrypt_trace (u8 * s, va_list * args)
101 {
102   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
103   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
104   esp_encrypt_post_trace_t *t = va_arg (*args, esp_encrypt_post_trace_t *);
105
106   s = format (s, "esp-post: next node index %u", t->next_index);
107   return s;
108 }
109
110 /* pad packet in input buffer */
111 static_always_inline u8 *
112 esp_add_footer_and_icv (vlib_main_t * vm, vlib_buffer_t ** last,
113                         u8 esp_align, u8 icv_sz,
114                         u16 * next, vlib_node_runtime_t * node,
115                         u16 buffer_data_size, uword total_len)
116 {
117   static const u8 pad_data[ESP_MAX_BLOCK_SIZE] = {
118     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
119     0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00,
120   };
121
122   u16 min_length = total_len + sizeof (esp_footer_t);
123   u16 new_length = round_pow2 (min_length, esp_align);
124   u8 pad_bytes = new_length - min_length;
125   esp_footer_t *f = (esp_footer_t *) (vlib_buffer_get_current (last[0]) +
126                                       last[0]->current_length + pad_bytes);
127   u16 tail_sz = sizeof (esp_footer_t) + pad_bytes + icv_sz;
128
129   if (last[0]->current_length + tail_sz > buffer_data_size)
130     {
131       u32 tmp_bi = 0;
132       if (vlib_buffer_alloc (vm, &tmp_bi, 1) != 1)
133         return 0;
134
135       vlib_buffer_t *tmp = vlib_get_buffer (vm, tmp_bi);
136       last[0]->next_buffer = tmp_bi;
137       last[0]->flags |= VLIB_BUFFER_NEXT_PRESENT;
138       f = (esp_footer_t *) (vlib_buffer_get_current (tmp) + pad_bytes);
139       tmp->current_length += tail_sz;
140       last[0] = tmp;
141     }
142   else
143     last[0]->current_length += tail_sz;
144
145   f->pad_length = pad_bytes;
146   if (pad_bytes)
147     {
148       ASSERT (pad_bytes <= ESP_MAX_BLOCK_SIZE);
149       pad_bytes = clib_min (ESP_MAX_BLOCK_SIZE, pad_bytes);
150       clib_memcpy_fast ((u8 *) f - pad_bytes, pad_data, pad_bytes);
151     }
152
153   return &f->next_header;
154 }
155
156 static_always_inline void
157 esp_update_ip4_hdr (ip4_header_t * ip4, u16 len, int is_transport, int is_udp)
158 {
159   ip_csum_t sum;
160   u16 old_len;
161
162   len = clib_net_to_host_u16 (len);
163   old_len = ip4->length;
164
165   if (is_transport)
166     {
167       u8 prot = is_udp ? IP_PROTOCOL_UDP : IP_PROTOCOL_IPSEC_ESP;
168
169       sum = ip_csum_update (ip4->checksum, ip4->protocol,
170                             prot, ip4_header_t, protocol);
171       ip4->protocol = prot;
172
173       sum = ip_csum_update (sum, old_len, len, ip4_header_t, length);
174     }
175   else
176     sum = ip_csum_update (ip4->checksum, old_len, len, ip4_header_t, length);
177
178   ip4->length = len;
179   ip4->checksum = ip_csum_fold (sum);
180 }
181
182 static_always_inline void
183 esp_fill_udp_hdr (ipsec_sa_t * sa, udp_header_t * udp, u16 len)
184 {
185   clib_memcpy_fast (udp, &sa->udp_hdr, sizeof (udp_header_t));
186   udp->length = clib_net_to_host_u16 (len);
187 }
188
189 static_always_inline u8
190 ext_hdr_is_pre_esp (u8 nexthdr)
191 {
192 #ifdef CLIB_HAVE_VEC128
193   static const u8x16 ext_hdr_types = {
194     IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS,
195     IP_PROTOCOL_IPV6_ROUTE,
196     IP_PROTOCOL_IPV6_FRAGMENTATION,
197   };
198
199   return !u8x16_is_all_zero (ext_hdr_types == u8x16_splat (nexthdr));
200 #else
201   return ((nexthdr ^ IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS) |
202           (nexthdr ^ IP_PROTOCOL_IPV6_ROUTE) |
203           (nexthdr ^ IP_PROTOCOL_IPV6_FRAGMENTATION) != 0);
204 #endif
205 }
206
207 static_always_inline u8
208 esp_get_ip6_hdr_len (ip6_header_t * ip6, ip6_ext_header_t ** ext_hdr)
209 {
210   /* this code assumes that HbH, route and frag headers will be before
211      others, if that is not the case, they will end up encrypted */
212   u8 len = sizeof (ip6_header_t);
213   ip6_ext_header_t *p;
214
215   /* if next packet doesn't have ext header */
216   if (ext_hdr_is_pre_esp (ip6->protocol) == 0)
217     {
218       *ext_hdr = NULL;
219       return len;
220     }
221
222   p = (void *) (ip6 + 1);
223   len += ip6_ext_header_len (p);
224
225   while (ext_hdr_is_pre_esp (p->next_hdr))
226     {
227       len += ip6_ext_header_len (p);
228       p = ip6_ext_next_header (p);
229     }
230
231   *ext_hdr = p;
232   return len;
233 }
234
235 static_always_inline void
236 esp_process_chained_ops (vlib_main_t * vm, vlib_node_runtime_t * node,
237                          vnet_crypto_op_t * ops, vlib_buffer_t * b[],
238                          u16 * nexts, vnet_crypto_op_chunk_t * chunks,
239                          u16 drop_next)
240 {
241   u32 n_fail, n_ops = vec_len (ops);
242   vnet_crypto_op_t *op = ops;
243
244   if (n_ops == 0)
245     return;
246
247   n_fail = n_ops - vnet_crypto_process_chained_ops (vm, op, chunks, n_ops);
248
249   while (n_fail)
250     {
251       ASSERT (op - ops < n_ops);
252
253       if (op->status != VNET_CRYPTO_OP_STATUS_COMPLETED)
254         {
255           u32 bi = op->user_data;
256           b[bi]->error = node->errors[ESP_ENCRYPT_ERROR_CRYPTO_ENGINE_ERROR];
257           nexts[bi] = drop_next;
258           n_fail--;
259         }
260       op++;
261     }
262 }
263
264 static_always_inline void
265 esp_process_ops (vlib_main_t * vm, vlib_node_runtime_t * node,
266                  vnet_crypto_op_t * ops, vlib_buffer_t * b[], u16 * nexts,
267                  u16 drop_next)
268 {
269   u32 n_fail, n_ops = vec_len (ops);
270   vnet_crypto_op_t *op = ops;
271
272   if (n_ops == 0)
273     return;
274
275   n_fail = n_ops - vnet_crypto_process_ops (vm, op, n_ops);
276
277   while (n_fail)
278     {
279       ASSERT (op - ops < n_ops);
280
281       if (op->status != VNET_CRYPTO_OP_STATUS_COMPLETED)
282         {
283           u32 bi = op->user_data;
284           b[bi]->error = node->errors[ESP_ENCRYPT_ERROR_CRYPTO_ENGINE_ERROR];
285           nexts[bi] = drop_next;
286           n_fail--;
287         }
288       op++;
289     }
290 }
291
292 typedef struct
293 {
294   u32 salt;
295   u64 iv;
296 } __clib_packed esp_gcm_nonce_t;
297
298 STATIC_ASSERT_SIZEOF (esp_gcm_nonce_t, 12);
299
300 static_always_inline u32
301 esp_encrypt_chain_crypto (vlib_main_t * vm, ipsec_per_thread_data_t * ptd,
302                           ipsec_sa_t * sa0, vlib_buffer_t * b,
303                           vlib_buffer_t * lb, u8 icv_sz, u8 * start,
304                           u32 start_len, u16 * n_ch)
305 {
306   vnet_crypto_op_chunk_t *ch;
307   vlib_buffer_t *cb = b;
308   u32 n_chunks = 1;
309   u32 total_len;
310   vec_add2 (ptd->chunks, ch, 1);
311   total_len = ch->len = start_len;
312   ch->src = ch->dst = start;
313   cb = vlib_get_buffer (vm, cb->next_buffer);
314
315   while (1)
316     {
317       vec_add2 (ptd->chunks, ch, 1);
318       n_chunks += 1;
319       if (lb == cb)
320         total_len += ch->len = cb->current_length - icv_sz;
321       else
322         total_len += ch->len = cb->current_length;
323       ch->src = ch->dst = vlib_buffer_get_current (cb);
324
325       if (!(cb->flags & VLIB_BUFFER_NEXT_PRESENT))
326         break;
327
328       cb = vlib_get_buffer (vm, cb->next_buffer);
329     }
330
331   if (n_ch)
332     *n_ch = n_chunks;
333
334   return total_len;
335 }
336
337 static_always_inline u32
338 esp_encrypt_chain_integ (vlib_main_t * vm, ipsec_per_thread_data_t * ptd,
339                          ipsec_sa_t * sa0, vlib_buffer_t * b,
340                          vlib_buffer_t * lb, u8 icv_sz, u8 * start,
341                          u32 start_len, u8 * digest, u16 * n_ch)
342 {
343   vnet_crypto_op_chunk_t *ch;
344   vlib_buffer_t *cb = b;
345   u32 n_chunks = 1;
346   u32 total_len;
347   vec_add2 (ptd->chunks, ch, 1);
348   total_len = ch->len = start_len;
349   ch->src = start;
350   cb = vlib_get_buffer (vm, cb->next_buffer);
351
352   while (1)
353     {
354       vec_add2 (ptd->chunks, ch, 1);
355       n_chunks += 1;
356       if (lb == cb)
357         {
358           total_len += ch->len = cb->current_length - icv_sz;
359           if (ipsec_sa_is_set_USE_ESN (sa0))
360             {
361               u32 seq_hi = clib_net_to_host_u32 (sa0->seq_hi);
362               clib_memcpy_fast (digest, &seq_hi, sizeof (seq_hi));
363               ch->len += sizeof (seq_hi);
364               total_len += sizeof (seq_hi);
365             }
366         }
367       else
368         total_len += ch->len = cb->current_length;
369       ch->src = vlib_buffer_get_current (cb);
370
371       if (!(cb->flags & VLIB_BUFFER_NEXT_PRESENT))
372         break;
373
374       cb = vlib_get_buffer (vm, cb->next_buffer);
375     }
376
377   if (n_ch)
378     *n_ch = n_chunks;
379
380   return total_len;
381 }
382
383 always_inline void
384 esp_prepare_sync_op (vlib_main_t * vm, ipsec_per_thread_data_t * ptd,
385                      vnet_crypto_op_t ** crypto_ops,
386                      vnet_crypto_op_t ** integ_ops, ipsec_sa_t * sa0,
387                      u8 * payload, u16 payload_len, u8 iv_sz, u8 icv_sz,
388                      vlib_buffer_t ** bufs, vlib_buffer_t ** b,
389                      vlib_buffer_t * lb, u32 hdr_len, esp_header_t * esp,
390                      esp_gcm_nonce_t * nonce)
391 {
392   if (sa0->crypto_enc_op_id)
393     {
394       vnet_crypto_op_t *op;
395       vec_add2_aligned (crypto_ops[0], op, 1, CLIB_CACHE_LINE_BYTES);
396       vnet_crypto_op_init (op, sa0->crypto_enc_op_id);
397
398       op->src = op->dst = payload;
399       op->key_index = sa0->crypto_key_index;
400       op->len = payload_len - icv_sz;
401       op->user_data = b - bufs;
402
403       if (ipsec_sa_is_set_IS_AEAD (sa0))
404         {
405           /*
406            * construct the AAD in a scratch space in front
407            * of the IP header.
408            */
409           op->aad = payload - hdr_len - sizeof (esp_aead_t);
410           op->aad_len = esp_aad_fill (op->aad, esp, sa0);
411
412           op->tag = payload + op->len;
413           op->tag_len = 16;
414
415           u64 *iv = (u64 *) (payload - iv_sz);
416           nonce->salt = sa0->salt;
417           nonce->iv = *iv = clib_host_to_net_u64 (sa0->gcm_iv_counter++);
418           op->iv = (u8 *) nonce;
419         }
420       else
421         {
422           op->iv = payload - iv_sz;
423           op->flags = VNET_CRYPTO_OP_FLAG_INIT_IV;
424         }
425
426       if (lb != b[0])
427         {
428           /* is chained */
429           op->flags |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
430           op->chunk_index = vec_len (ptd->chunks);
431           op->tag = vlib_buffer_get_tail (lb) - icv_sz;
432           esp_encrypt_chain_crypto (vm, ptd, sa0, b[0], lb, icv_sz, payload,
433                                     payload_len, &op->n_chunks);
434         }
435     }
436
437   if (sa0->integ_op_id)
438     {
439       vnet_crypto_op_t *op;
440       vec_add2_aligned (integ_ops[0], op, 1, CLIB_CACHE_LINE_BYTES);
441       vnet_crypto_op_init (op, sa0->integ_op_id);
442       op->src = payload - iv_sz - sizeof (esp_header_t);
443       op->digest = payload + payload_len - icv_sz;
444       op->key_index = sa0->integ_key_index;
445       op->digest_len = icv_sz;
446       op->len = payload_len - icv_sz + iv_sz + sizeof (esp_header_t);
447       op->user_data = b - bufs;
448
449       if (lb != b[0])
450         {
451           /* is chained */
452           op->flags |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
453           op->chunk_index = vec_len (ptd->chunks);
454           op->digest = vlib_buffer_get_tail (lb) - icv_sz;
455
456           esp_encrypt_chain_integ (vm, ptd, sa0, b[0], lb, icv_sz,
457                                    payload - iv_sz - sizeof (esp_header_t),
458                                    payload_len + iv_sz +
459                                    sizeof (esp_header_t), op->digest,
460                                    &op->n_chunks);
461         }
462       else if (ipsec_sa_is_set_USE_ESN (sa0))
463         {
464           u32 seq_hi = clib_net_to_host_u32 (sa0->seq_hi);
465           clib_memcpy_fast (op->digest, &seq_hi, sizeof (seq_hi));
466           op->len += sizeof (seq_hi);
467         }
468     }
469 }
470
471 static_always_inline int
472 esp_prepare_async_frame (vlib_main_t * vm, ipsec_per_thread_data_t * ptd,
473                          vnet_crypto_async_frame_t ** async_frame,
474                          ipsec_sa_t * sa, vlib_buffer_t * b,
475                          esp_header_t * esp, u8 * payload, u32 payload_len,
476                          u8 iv_sz, u8 icv_sz, u32 bi, u16 next, u32 hdr_len,
477                          u16 async_next, vlib_buffer_t * lb)
478 {
479   esp_post_data_t *post = esp_post_data (b);
480   u8 *tag, *iv, *aad = 0;
481   u8 flag = 0;
482   u32 key_index;
483   i16 crypto_start_offset, integ_start_offset = 0;
484   u16 crypto_total_len, integ_total_len;
485
486   post->next_index = next;
487
488   /* crypto */
489   crypto_start_offset = payload - b->data;
490   crypto_total_len = integ_total_len = payload_len - icv_sz;
491   tag = payload + crypto_total_len;
492
493   /* aead */
494   if (ipsec_sa_is_set_IS_AEAD (sa))
495     {
496       esp_gcm_nonce_t *nonce;
497       u64 *pkt_iv = (u64 *) (payload - iv_sz);
498
499       aad = payload - hdr_len - sizeof (esp_aead_t);
500       esp_aad_fill (aad, esp, sa);
501       nonce = (esp_gcm_nonce_t *) (aad - sizeof (*nonce));
502       nonce->salt = sa->salt;
503       nonce->iv = *pkt_iv = clib_host_to_net_u64 (sa->gcm_iv_counter++);
504       iv = (u8 *) nonce;
505       key_index = sa->crypto_key_index;
506
507       if (lb != b)
508         {
509           /* chain */
510           flag |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
511           tag = vlib_buffer_get_tail (lb) - icv_sz;
512           crypto_total_len = esp_encrypt_chain_crypto (vm, ptd, sa, b, lb,
513                                                        icv_sz, payload,
514                                                        payload_len, 0);
515         }
516       goto out;
517     }
518
519   /* cipher then hash */
520   iv = payload - iv_sz;
521   integ_start_offset = crypto_start_offset - iv_sz - sizeof (esp_header_t);
522   integ_total_len += iv_sz + sizeof (esp_header_t);
523   flag |= VNET_CRYPTO_OP_FLAG_INIT_IV;
524   key_index = sa->linked_key_index;
525
526   if (b != lb)
527     {
528       flag |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
529       crypto_total_len = esp_encrypt_chain_crypto (vm, ptd, sa, b, lb,
530                                                    icv_sz, payload,
531                                                    payload_len, 0);
532       tag = vlib_buffer_get_tail (lb) - icv_sz;
533       integ_total_len = esp_encrypt_chain_integ (vm, ptd, sa, b, lb, icv_sz,
534                                                  payload - iv_sz -
535                                                  sizeof (esp_header_t),
536                                                  payload_len + iv_sz +
537                                                  sizeof (esp_header_t),
538                                                  tag, 0);
539     }
540   else if (ipsec_sa_is_set_USE_ESN (sa) && !ipsec_sa_is_set_IS_AEAD (sa))
541     {
542       u32 seq_hi = clib_net_to_host_u32 (sa->seq_hi);
543       clib_memcpy_fast (tag, &seq_hi, sizeof (seq_hi));
544       integ_total_len += sizeof (seq_hi);
545     }
546
547 out:
548   return vnet_crypto_async_add_to_frame (vm, async_frame, key_index,
549                                          crypto_total_len,
550                                          integ_total_len - crypto_total_len,
551                                          crypto_start_offset,
552                                          integ_start_offset, bi, async_next,
553                                          iv, tag, aad, flag);
554 }
555
556 always_inline uword
557 esp_encrypt_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
558                     vlib_frame_t * frame, int is_ip6, int is_tun,
559                     u16 async_next)
560 {
561   ipsec_main_t *im = &ipsec_main;
562   ipsec_per_thread_data_t *ptd = vec_elt_at_index (im->ptd, vm->thread_index);
563   u32 *from = vlib_frame_vector_args (frame);
564   u32 n_left = frame->n_vectors;
565   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
566   u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
567   esp_gcm_nonce_t nonces[VLIB_FRAME_SIZE], *nonce = nonces;
568   u32 thread_index = vm->thread_index;
569   u16 buffer_data_size = vlib_buffer_get_default_data_size (vm);
570   u32 current_sa_index = ~0, current_sa_packets = 0;
571   u32 current_sa_bytes = 0, spi = 0;
572   u8 esp_align = 4, iv_sz = 0, icv_sz = 0;
573   ipsec_sa_t *sa0 = 0;
574   vlib_buffer_t *lb;
575   vnet_crypto_op_t **crypto_ops = &ptd->crypto_ops;
576   vnet_crypto_op_t **integ_ops = &ptd->integ_ops;
577   vnet_crypto_async_frame_t *async_frame = 0;
578   int is_async = im->async_mode;
579   vnet_crypto_async_op_id_t last_async_op = ~0;
580   u16 drop_next = (is_ip6 ? ESP_ENCRYPT_NEXT_DROP6 : ESP_ENCRYPT_NEXT_DROP4);
581   u16 n_async_drop = 0;
582
583   vlib_get_buffers (vm, from, b, n_left);
584   if (!is_async)
585     {
586       vec_reset_length (ptd->crypto_ops);
587       vec_reset_length (ptd->integ_ops);
588       vec_reset_length (ptd->chained_crypto_ops);
589       vec_reset_length (ptd->chained_integ_ops);
590     }
591   vec_reset_length (ptd->chunks);
592
593   while (n_left > 0)
594     {
595       u32 sa_index0;
596       dpo_id_t *dpo;
597       esp_header_t *esp;
598       u8 *payload, *next_hdr_ptr;
599       u16 payload_len, payload_len_total, n_bufs;
600       u32 hdr_len;
601
602       if (n_left > 2)
603         {
604           u8 *p;
605           vlib_prefetch_buffer_header (b[2], LOAD);
606           p = vlib_buffer_get_current (b[1]);
607           CLIB_PREFETCH (p, CLIB_CACHE_LINE_BYTES, LOAD);
608           p -= CLIB_CACHE_LINE_BYTES;
609           CLIB_PREFETCH (p, CLIB_CACHE_LINE_BYTES, LOAD);
610           /* speculate that the trailer goes in the first buffer */
611           CLIB_PREFETCH (vlib_buffer_get_tail (b[1]),
612                          CLIB_CACHE_LINE_BYTES, LOAD);
613         }
614
615       if (is_tun)
616         {
617           /* we are on a ipsec tunnel's feature arc */
618           vnet_buffer (b[0])->ipsec.sad_index =
619             sa_index0 = ipsec_tun_protect_get_sa_out
620             (vnet_buffer (b[0])->ip.adj_index[VLIB_TX]);
621         }
622       else
623         sa_index0 = vnet_buffer (b[0])->ipsec.sad_index;
624
625       if (sa_index0 != current_sa_index)
626         {
627           if (current_sa_packets)
628             vlib_increment_combined_counter (&ipsec_sa_counters, thread_index,
629                                              current_sa_index,
630                                              current_sa_packets,
631                                              current_sa_bytes);
632           current_sa_packets = current_sa_bytes = 0;
633
634           sa0 = pool_elt_at_index (im->sad, sa_index0);
635
636           /* fetch the second cacheline ASAP */
637           CLIB_PREFETCH (sa0->cacheline1, CLIB_CACHE_LINE_BYTES, LOAD);
638
639           current_sa_index = sa_index0;
640           spi = clib_net_to_host_u32 (sa0->spi);
641           esp_align = sa0->esp_block_align;
642           icv_sz = sa0->integ_icv_size;
643           iv_sz = sa0->crypto_iv_size;
644
645           /* submit frame when op_id is different then the old one */
646           if (is_async && sa0->crypto_async_enc_op_id != last_async_op)
647             {
648               if (async_frame && async_frame->n_elts)
649                 {
650                   if (vnet_crypto_async_submit_open_frame (vm, async_frame))
651                     esp_async_recycle_failed_submit (async_frame, b, from,
652                                                      nexts, &n_async_drop,
653                                                      drop_next,
654                                                      ESP_ENCRYPT_ERROR_CRYPTO_ENGINE_ERROR);
655                 }
656               async_frame =
657                 vnet_crypto_async_get_frame (vm, sa0->crypto_async_enc_op_id);
658               last_async_op = sa0->crypto_async_enc_op_id;
659             }
660         }
661
662       if (PREDICT_FALSE (~0 == sa0->encrypt_thread_index))
663         {
664           /* this is the first packet to use this SA, claim the SA
665            * for this thread. this could happen simultaneously on
666            * another thread */
667           clib_atomic_cmp_and_swap (&sa0->encrypt_thread_index, ~0,
668                                     ipsec_sa_assign_thread (thread_index));
669         }
670
671       if (PREDICT_TRUE (thread_index != sa0->encrypt_thread_index))
672         {
673           esp_set_next_index (is_async, from, nexts, from[b - bufs],
674                               &n_async_drop,
675                               (is_ip6 ? ESP_ENCRYPT_NEXT_HANDOFF6 :
676                                ESP_ENCRYPT_NEXT_HANDOFF4), next);
677           goto trace;
678         }
679
680       lb = b[0];
681       n_bufs = vlib_buffer_chain_linearize (vm, b[0]);
682       if (n_bufs == 0)
683         {
684           b[0]->error = node->errors[ESP_ENCRYPT_ERROR_NO_BUFFERS];
685           esp_set_next_index (is_async, from, nexts, from[b - bufs],
686                               &n_async_drop, drop_next, next);
687           goto trace;
688         }
689
690       if (n_bufs > 1)
691         {
692           /* find last buffer in the chain */
693           while (lb->flags & VLIB_BUFFER_NEXT_PRESENT)
694             lb = vlib_get_buffer (vm, lb->next_buffer);
695         }
696
697       if (PREDICT_FALSE (esp_seq_advance (sa0)))
698         {
699           b[0]->error = node->errors[ESP_ENCRYPT_ERROR_SEQ_CYCLED];
700           esp_set_next_index (is_async, from, nexts, from[b - bufs],
701                               &n_async_drop, drop_next, next);
702           goto trace;
703         }
704
705       /* space for IV */
706       hdr_len = iv_sz;
707
708       if (ipsec_sa_is_set_IS_TUNNEL (sa0))
709         {
710           payload = vlib_buffer_get_current (b[0]);
711           next_hdr_ptr = esp_add_footer_and_icv (vm, &lb, esp_align, icv_sz,
712                                                  next, node,
713                                                  buffer_data_size,
714                                                  vlib_buffer_length_in_chain
715                                                  (vm, b[0]));
716           if (!next_hdr_ptr)
717             {
718               b[0]->error = node->errors[ESP_ENCRYPT_ERROR_NO_BUFFERS];
719               esp_set_next_index (is_async, from, nexts, from[b - bufs],
720                                   &n_async_drop, drop_next, next);
721               goto trace;
722             }
723           b[0]->flags &= ~VLIB_BUFFER_TOTAL_LENGTH_VALID;
724           payload_len = b[0]->current_length;
725           payload_len_total = vlib_buffer_length_in_chain (vm, b[0]);
726
727           /* ESP header */
728           hdr_len += sizeof (*esp);
729           esp = (esp_header_t *) (payload - hdr_len);
730
731           /* optional UDP header */
732           if (ipsec_sa_is_set_UDP_ENCAP (sa0))
733             {
734               hdr_len += sizeof (udp_header_t);
735               esp_fill_udp_hdr (sa0, (udp_header_t *) (payload - hdr_len),
736                                 payload_len_total + hdr_len);
737             }
738
739           /* IP header */
740           if (ipsec_sa_is_set_IS_TUNNEL_V6 (sa0))
741             {
742               ip6_header_t *ip6;
743               u16 len = sizeof (ip6_header_t);
744               hdr_len += len;
745               ip6 = (ip6_header_t *) (payload - hdr_len);
746               clib_memcpy_fast (ip6, &sa0->ip6_hdr, len);
747               *next_hdr_ptr = (is_ip6 ?
748                                IP_PROTOCOL_IPV6 : IP_PROTOCOL_IP_IN_IP);
749               len = payload_len_total + hdr_len - len;
750               ip6->payload_length = clib_net_to_host_u16 (len);
751             }
752           else
753             {
754               ip4_header_t *ip4;
755               u16 len = sizeof (ip4_header_t);
756               hdr_len += len;
757               ip4 = (ip4_header_t *) (payload - hdr_len);
758               clib_memcpy_fast (ip4, &sa0->ip4_hdr, len);
759               *next_hdr_ptr = (is_ip6 ?
760                                IP_PROTOCOL_IPV6 : IP_PROTOCOL_IP_IN_IP);
761               len = payload_len_total + hdr_len;
762               esp_update_ip4_hdr (ip4, len, /* is_transport */ 0, 0);
763             }
764
765           dpo = &sa0->dpo;
766           if (!is_tun)
767             {
768               next[0] = dpo->dpoi_next_node;
769               vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = dpo->dpoi_index;
770             }
771           else
772             next[0] = ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT;
773         }
774       else                      /* transport mode */
775         {
776           u8 *l2_hdr, l2_len, *ip_hdr, ip_len;
777           ip6_ext_header_t *ext_hdr;
778           udp_header_t *udp = 0;
779           u16 udp_len = 0;
780           u8 *old_ip_hdr = vlib_buffer_get_current (b[0]);
781
782           ip_len = is_ip6 ?
783             esp_get_ip6_hdr_len ((ip6_header_t *) old_ip_hdr, &ext_hdr) :
784             ip4_header_bytes ((ip4_header_t *) old_ip_hdr);
785
786           vlib_buffer_advance (b[0], ip_len);
787           payload = vlib_buffer_get_current (b[0]);
788           next_hdr_ptr = esp_add_footer_and_icv (vm, &lb, esp_align, icv_sz,
789                                                  next, node,
790                                                  buffer_data_size,
791                                                  vlib_buffer_length_in_chain
792                                                  (vm, b[0]));
793           if (!next_hdr_ptr)
794             {
795               esp_set_next_index (is_async, from, nexts, from[b - bufs],
796                                   &n_async_drop, drop_next, next);
797               goto trace;
798             }
799
800           b[0]->flags &= ~VLIB_BUFFER_TOTAL_LENGTH_VALID;
801           payload_len = b[0]->current_length;
802           payload_len_total = vlib_buffer_length_in_chain (vm, b[0]);
803
804           /* ESP header */
805           hdr_len += sizeof (*esp);
806           esp = (esp_header_t *) (payload - hdr_len);
807
808           /* optional UDP header */
809           if (ipsec_sa_is_set_UDP_ENCAP (sa0))
810             {
811               hdr_len += sizeof (udp_header_t);
812               udp = (udp_header_t *) (payload - hdr_len);
813             }
814
815           /* IP header */
816           hdr_len += ip_len;
817           ip_hdr = payload - hdr_len;
818
819           /* L2 header */
820           if (!is_tun)
821             {
822               l2_len = vnet_buffer (b[0])->ip.save_rewrite_length;
823               hdr_len += l2_len;
824               l2_hdr = payload - hdr_len;
825
826               /* copy l2 and ip header */
827               clib_memcpy_le32 (l2_hdr, old_ip_hdr - l2_len, l2_len);
828             }
829           else
830             l2_len = 0;
831
832           if (is_ip6)
833             {
834               ip6_header_t *ip6 = (ip6_header_t *) (old_ip_hdr);
835               if (PREDICT_TRUE (NULL == ext_hdr))
836                 {
837                   *next_hdr_ptr = ip6->protocol;
838                   ip6->protocol = IP_PROTOCOL_IPSEC_ESP;
839                 }
840               else
841                 {
842                   *next_hdr_ptr = ext_hdr->next_hdr;
843                   ext_hdr->next_hdr = IP_PROTOCOL_IPSEC_ESP;
844                 }
845               ip6->payload_length =
846                 clib_host_to_net_u16 (payload_len_total + hdr_len - l2_len -
847                                       sizeof (ip6_header_t));
848             }
849           else
850             {
851               u16 len;
852               ip4_header_t *ip4 = (ip4_header_t *) (old_ip_hdr);
853               *next_hdr_ptr = ip4->protocol;
854               len = payload_len_total + hdr_len - l2_len;
855               if (udp)
856                 {
857                   esp_update_ip4_hdr (ip4, len, /* is_transport */ 1, 1);
858                   udp_len = len - ip_len;
859                 }
860               else
861                 esp_update_ip4_hdr (ip4, len, /* is_transport */ 1, 0);
862             }
863
864           clib_memcpy_le64 (ip_hdr, old_ip_hdr, ip_len);
865
866           if (udp)
867             {
868               esp_fill_udp_hdr (sa0, udp, udp_len);
869             }
870
871           next[0] = ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT;
872         }
873
874       if (lb != b[0])
875         {
876           crypto_ops = &ptd->chained_crypto_ops;
877           integ_ops = &ptd->chained_integ_ops;
878         }
879       else
880         {
881           crypto_ops = &ptd->crypto_ops;
882           integ_ops = &ptd->integ_ops;
883         }
884
885       esp->spi = spi;
886       esp->seq = clib_net_to_host_u32 (sa0->seq);
887
888       if (is_async)
889         {
890           if (PREDICT_FALSE (sa0->crypto_async_enc_op_id == 0))
891             {
892               esp_set_next_index (is_async, from, nexts, from[b - bufs],
893                                   &n_async_drop, drop_next, next);
894               goto trace;
895             }
896
897           if (esp_prepare_async_frame (vm, ptd, &async_frame, sa0, b[0], esp,
898                                        payload, payload_len, iv_sz,
899                                        icv_sz, from[b - bufs], next[0],
900                                        hdr_len, async_next, lb))
901             {
902               /* The fail only caused by submission, free the whole frame. */
903               if (async_frame->n_elts)
904                 esp_async_recycle_failed_submit (async_frame, b, from, nexts,
905                                                  &n_async_drop, drop_next,
906                                                  ESP_ENCRYPT_ERROR_CRYPTO_ENGINE_ERROR);
907               b[0]->error = ESP_ENCRYPT_ERROR_CRYPTO_ENGINE_ERROR;
908               esp_set_next_index (1, from, nexts, from[b - bufs],
909                                   &n_async_drop, drop_next, next);
910               goto trace;
911             }
912         }
913       else
914         {
915           esp_prepare_sync_op (vm, ptd, crypto_ops, integ_ops, sa0, payload,
916                                payload_len, iv_sz, icv_sz, bufs, b, lb,
917                                hdr_len, esp, nonce++);
918         }
919
920       vlib_buffer_advance (b[0], 0LL - hdr_len);
921
922       current_sa_packets += 1;
923       current_sa_bytes += payload_len_total;
924
925     trace:
926       if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
927         {
928           esp_encrypt_trace_t *tr = vlib_add_trace (vm, node, b[0],
929                                                     sizeof (*tr));
930           tr->sa_index = sa_index0;
931           tr->spi = sa0->spi;
932           tr->seq = sa0->seq;
933           tr->sa_seq_hi = sa0->seq_hi;
934           tr->udp_encap = ipsec_sa_is_set_UDP_ENCAP (sa0);
935           tr->crypto_alg = sa0->crypto_alg;
936           tr->integ_alg = sa0->integ_alg;
937         }
938       /* next */
939       n_left -= 1;
940       next += 1;
941       b += 1;
942     }
943
944   vlib_increment_combined_counter (&ipsec_sa_counters, thread_index,
945                                    current_sa_index, current_sa_packets,
946                                    current_sa_bytes);
947   if (!is_async)
948     {
949       esp_process_ops (vm, node, ptd->crypto_ops, bufs, nexts, drop_next);
950       esp_process_chained_ops (vm, node, ptd->chained_crypto_ops, bufs, nexts,
951                                ptd->chunks, drop_next);
952
953       esp_process_ops (vm, node, ptd->integ_ops, bufs, nexts, drop_next);
954       esp_process_chained_ops (vm, node, ptd->chained_integ_ops, bufs, nexts,
955                                ptd->chunks, drop_next);
956     }
957   else
958     {
959       if (async_frame && async_frame->n_elts)
960         {
961           if (vnet_crypto_async_submit_open_frame (vm, async_frame) < 0)
962             esp_async_recycle_failed_submit (async_frame, b, from, nexts,
963                                              &n_async_drop, drop_next,
964                                              ESP_ENCRYPT_ERROR_CRYPTO_ENGINE_ERROR);
965         }
966       vlib_node_increment_counter (vm, node->node_index,
967                                    ESP_ENCRYPT_ERROR_RX_PKTS,
968                                    frame->n_vectors);
969       if (n_async_drop)
970         vlib_buffer_enqueue_to_next (vm, node, from, nexts, n_async_drop);
971
972       return frame->n_vectors;
973     }
974
975   vlib_node_increment_counter (vm, node->node_index,
976                                ESP_ENCRYPT_ERROR_RX_PKTS, frame->n_vectors);
977
978   vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
979   return frame->n_vectors;
980 }
981
982 always_inline uword
983 esp_encrypt_post_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
984                          vlib_frame_t * frame)
985 {
986   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
987   u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
988   u32 *from = vlib_frame_vector_args (frame);
989   u32 n_left = frame->n_vectors;
990
991   vlib_get_buffers (vm, from, b, n_left);
992
993   if (n_left >= 4)
994     {
995       vlib_prefetch_buffer_header (b[0], LOAD);
996       vlib_prefetch_buffer_header (b[1], LOAD);
997       vlib_prefetch_buffer_header (b[2], LOAD);
998       vlib_prefetch_buffer_header (b[3], LOAD);
999     }
1000
1001   while (n_left > 8)
1002     {
1003       vlib_prefetch_buffer_header (b[4], LOAD);
1004       vlib_prefetch_buffer_header (b[5], LOAD);
1005       vlib_prefetch_buffer_header (b[6], LOAD);
1006       vlib_prefetch_buffer_header (b[7], LOAD);
1007
1008       next[0] = (esp_post_data (b[0]))->next_index;
1009       next[1] = (esp_post_data (b[1]))->next_index;
1010       next[2] = (esp_post_data (b[2]))->next_index;
1011       next[3] = (esp_post_data (b[3]))->next_index;
1012
1013       if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
1014         {
1015           if (b[0]->flags & VLIB_BUFFER_IS_TRACED)
1016             {
1017               esp_encrypt_post_trace_t *tr = vlib_add_trace (vm, node, b[0],
1018                                                              sizeof (*tr));
1019               tr->next_index = next[0];
1020             }
1021           if (b[1]->flags & VLIB_BUFFER_IS_TRACED)
1022             {
1023               esp_encrypt_post_trace_t *tr = vlib_add_trace (vm, node, b[1],
1024                                                              sizeof (*tr));
1025               tr->next_index = next[1];
1026             }
1027           if (b[2]->flags & VLIB_BUFFER_IS_TRACED)
1028             {
1029               esp_encrypt_post_trace_t *tr = vlib_add_trace (vm, node, b[2],
1030                                                              sizeof (*tr));
1031               tr->next_index = next[2];
1032             }
1033           if (b[3]->flags & VLIB_BUFFER_IS_TRACED)
1034             {
1035               esp_encrypt_post_trace_t *tr = vlib_add_trace (vm, node, b[3],
1036                                                              sizeof (*tr));
1037               tr->next_index = next[3];
1038             }
1039         }
1040
1041       b += 4;
1042       next += 4;
1043       n_left -= 4;
1044     }
1045
1046   while (n_left > 0)
1047     {
1048       next[0] = (esp_post_data (b[0]))->next_index;
1049       if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
1050         {
1051           esp_encrypt_post_trace_t *tr = vlib_add_trace (vm, node, b[0],
1052                                                          sizeof (*tr));
1053           tr->next_index = next[0];
1054         }
1055
1056       b += 1;
1057       next += 1;
1058       n_left -= 1;
1059     }
1060
1061   vlib_node_increment_counter (vm, node->node_index,
1062                                ESP_ENCRYPT_ERROR_POST_RX_PKTS,
1063                                frame->n_vectors);
1064   vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
1065   return frame->n_vectors;
1066 }
1067
1068 VLIB_NODE_FN (esp4_encrypt_node) (vlib_main_t * vm,
1069                                   vlib_node_runtime_t * node,
1070                                   vlib_frame_t * from_frame)
1071 {
1072   return esp_encrypt_inline (vm, node, from_frame, 0 /* is_ip6 */ , 0,
1073                              esp_encrypt_async_next.esp4_post_next);
1074 }
1075
1076 /* *INDENT-OFF* */
1077 VLIB_REGISTER_NODE (esp4_encrypt_node) = {
1078   .name = "esp4-encrypt",
1079   .vector_size = sizeof (u32),
1080   .format_trace = format_esp_encrypt_trace,
1081   .type = VLIB_NODE_TYPE_INTERNAL,
1082
1083   .n_errors = ARRAY_LEN(esp_encrypt_error_strings),
1084   .error_strings = esp_encrypt_error_strings,
1085
1086   .n_next_nodes = ESP_ENCRYPT_N_NEXT,
1087   .next_nodes = {
1088     [ESP_ENCRYPT_NEXT_DROP4] = "ip4-drop",
1089     [ESP_ENCRYPT_NEXT_DROP6] = "ip6-drop",
1090     [ESP_ENCRYPT_NEXT_HANDOFF4] = "esp4-encrypt-handoff",
1091     [ESP_ENCRYPT_NEXT_HANDOFF6] = "esp6-encrypt-handoff",
1092     [ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT] = "interface-output"
1093   },
1094 };
1095 /* *INDENT-ON* */
1096
1097 VLIB_NODE_FN (esp4_encrypt_post_node) (vlib_main_t * vm,
1098                                        vlib_node_runtime_t * node,
1099                                        vlib_frame_t * from_frame)
1100 {
1101   return esp_encrypt_post_inline (vm, node, from_frame);
1102 }
1103
1104 /* *INDENT-OFF* */
1105 VLIB_REGISTER_NODE (esp4_encrypt_post_node) = {
1106   .name = "esp4-encrypt-post",
1107   .vector_size = sizeof (u32),
1108   .format_trace = format_esp_post_encrypt_trace,
1109   .type = VLIB_NODE_TYPE_INTERNAL,
1110   .sibling_of = "esp4-encrypt",
1111
1112   .n_errors = ARRAY_LEN(esp_encrypt_error_strings),
1113   .error_strings = esp_encrypt_error_strings,
1114 };
1115 /* *INDENT-ON* */
1116
1117 VLIB_NODE_FN (esp6_encrypt_node) (vlib_main_t * vm,
1118                                   vlib_node_runtime_t * node,
1119                                   vlib_frame_t * from_frame)
1120 {
1121   return esp_encrypt_inline (vm, node, from_frame, 1 /* is_ip6 */ , 0,
1122                              esp_encrypt_async_next.esp6_post_next);
1123 }
1124
1125 /* *INDENT-OFF* */
1126 VLIB_REGISTER_NODE (esp6_encrypt_node) = {
1127   .name = "esp6-encrypt",
1128   .vector_size = sizeof (u32),
1129   .format_trace = format_esp_encrypt_trace,
1130   .type = VLIB_NODE_TYPE_INTERNAL,
1131   .sibling_of = "esp4-encrypt",
1132
1133   .n_errors = ARRAY_LEN(esp_encrypt_error_strings),
1134   .error_strings = esp_encrypt_error_strings,
1135 };
1136 /* *INDENT-ON* */
1137
1138 VLIB_NODE_FN (esp6_encrypt_post_node) (vlib_main_t * vm,
1139                                        vlib_node_runtime_t * node,
1140                                        vlib_frame_t * from_frame)
1141 {
1142   return esp_encrypt_post_inline (vm, node, from_frame);
1143 }
1144
1145 /* *INDENT-OFF* */
1146 VLIB_REGISTER_NODE (esp6_encrypt_post_node) = {
1147   .name = "esp6-encrypt-post",
1148   .vector_size = sizeof (u32),
1149   .format_trace = format_esp_post_encrypt_trace,
1150   .type = VLIB_NODE_TYPE_INTERNAL,
1151   .sibling_of = "esp4-encrypt",
1152
1153   .n_errors = ARRAY_LEN(esp_encrypt_error_strings),
1154   .error_strings = esp_encrypt_error_strings,
1155 };
1156 /* *INDENT-ON* */
1157
1158 VLIB_NODE_FN (esp4_encrypt_tun_node) (vlib_main_t * vm,
1159                                       vlib_node_runtime_t * node,
1160                                       vlib_frame_t * from_frame)
1161 {
1162   return esp_encrypt_inline (vm, node, from_frame, 0 /* is_ip6 */ , 1,
1163                              esp_encrypt_async_next.esp4_tun_post_next);
1164 }
1165
1166 /* *INDENT-OFF* */
1167 VLIB_REGISTER_NODE (esp4_encrypt_tun_node) = {
1168   .name = "esp4-encrypt-tun",
1169   .vector_size = sizeof (u32),
1170   .format_trace = format_esp_encrypt_trace,
1171   .type = VLIB_NODE_TYPE_INTERNAL,
1172
1173   .n_errors = ARRAY_LEN(esp_encrypt_error_strings),
1174   .error_strings = esp_encrypt_error_strings,
1175
1176   .n_next_nodes = ESP_ENCRYPT_N_NEXT,
1177   .next_nodes = {
1178     [ESP_ENCRYPT_NEXT_DROP4] = "ip4-drop",
1179     [ESP_ENCRYPT_NEXT_DROP6] = "ip6-drop",
1180     [ESP_ENCRYPT_NEXT_HANDOFF4] = "esp4-encrypt-tun-handoff",
1181     [ESP_ENCRYPT_NEXT_HANDOFF6] = "error-drop",
1182     [ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT] = "adj-midchain-tx",
1183   },
1184 };
1185
1186 VLIB_NODE_FN (esp4_encrypt_tun_post_node) (vlib_main_t * vm,
1187                                   vlib_node_runtime_t * node,
1188                                   vlib_frame_t * from_frame)
1189 {
1190   return esp_encrypt_post_inline (vm, node, from_frame);
1191 }
1192
1193 /* *INDENT-OFF* */
1194 VLIB_REGISTER_NODE (esp4_encrypt_tun_post_node) = {
1195   .name = "esp4-encrypt-tun-post",
1196   .vector_size = sizeof (u32),
1197   .format_trace = format_esp_post_encrypt_trace,
1198   .type = VLIB_NODE_TYPE_INTERNAL,
1199   .sibling_of = "esp4-encrypt-tun",
1200
1201   .n_errors = ARRAY_LEN(esp_encrypt_error_strings),
1202   .error_strings = esp_encrypt_error_strings,
1203 };
1204 /* *INDENT-ON* */
1205
1206 VLIB_NODE_FN (esp6_encrypt_tun_node) (vlib_main_t * vm,
1207                                       vlib_node_runtime_t * node,
1208                                       vlib_frame_t * from_frame)
1209 {
1210   return esp_encrypt_inline (vm, node, from_frame, 1 /* is_ip6 */ , 1,
1211                              esp_encrypt_async_next.esp6_tun_post_next);
1212 }
1213
1214 /* *INDENT-OFF* */
1215 VLIB_REGISTER_NODE (esp6_encrypt_tun_node) = {
1216   .name = "esp6-encrypt-tun",
1217   .vector_size = sizeof (u32),
1218   .format_trace = format_esp_encrypt_trace,
1219   .type = VLIB_NODE_TYPE_INTERNAL,
1220
1221   .n_errors = ARRAY_LEN(esp_encrypt_error_strings),
1222   .error_strings = esp_encrypt_error_strings,
1223
1224   .n_next_nodes = ESP_ENCRYPT_N_NEXT,
1225   .next_nodes = {
1226     [ESP_ENCRYPT_NEXT_DROP4] = "ip4-drop",
1227     [ESP_ENCRYPT_NEXT_DROP6] = "ip6-drop",
1228     [ESP_ENCRYPT_NEXT_HANDOFF4] = "error-drop",
1229     [ESP_ENCRYPT_NEXT_HANDOFF6] = "esp6-encrypt-tun-handoff",
1230     [ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT] = "adj-midchain-tx",
1231   },
1232 };
1233
1234 /* *INDENT-ON* */
1235
1236 VLIB_NODE_FN (esp6_encrypt_tun_post_node) (vlib_main_t * vm,
1237                                            vlib_node_runtime_t * node,
1238                                            vlib_frame_t * from_frame)
1239 {
1240   return esp_encrypt_post_inline (vm, node, from_frame);
1241 }
1242
1243 /* *INDENT-OFF* */
1244 VLIB_REGISTER_NODE (esp6_encrypt_tun_post_node) = {
1245   .name = "esp6-encrypt-tun-post",
1246   .vector_size = sizeof (u32),
1247   .format_trace = format_esp_post_encrypt_trace,
1248   .type = VLIB_NODE_TYPE_INTERNAL,
1249   .sibling_of = "esp6-encrypt-tun",
1250
1251   .n_errors = ARRAY_LEN(esp_encrypt_error_strings),
1252   .error_strings = esp_encrypt_error_strings,
1253 };
1254 /* *INDENT-ON* */
1255
1256 typedef struct
1257 {
1258   u32 sa_index;
1259 } esp_no_crypto_trace_t;
1260
1261 static u8 *
1262 format_esp_no_crypto_trace (u8 * s, va_list * args)
1263 {
1264   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1265   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1266   esp_no_crypto_trace_t *t = va_arg (*args, esp_no_crypto_trace_t *);
1267
1268   s = format (s, "esp-no-crypto: sa-index %u", t->sa_index);
1269
1270   return s;
1271 }
1272
1273 enum
1274 {
1275   ESP_NO_CRYPTO_NEXT_DROP,
1276   ESP_NO_CRYPTO_N_NEXT,
1277 };
1278
1279 enum
1280 {
1281   ESP_NO_CRYPTO_ERROR_RX_PKTS,
1282 };
1283
1284 static char *esp_no_crypto_error_strings[] = {
1285   "Outbound ESP packets received",
1286 };
1287
1288 always_inline uword
1289 esp_no_crypto_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
1290                       vlib_frame_t * frame)
1291 {
1292   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
1293   u32 *from = vlib_frame_vector_args (frame);
1294   u32 n_left = frame->n_vectors;
1295
1296   vlib_get_buffers (vm, from, b, n_left);
1297
1298   while (n_left > 0)
1299     {
1300       u32 sa_index0;
1301
1302       /* packets are always going to be dropped, but get the sa_index */
1303       sa_index0 = ipsec_tun_protect_get_sa_out
1304         (vnet_buffer (b[0])->ip.adj_index[VLIB_TX]);
1305
1306       if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
1307         {
1308           esp_no_crypto_trace_t *tr = vlib_add_trace (vm, node, b[0],
1309                                                       sizeof (*tr));
1310           tr->sa_index = sa_index0;
1311         }
1312
1313       n_left -= 1;
1314       b += 1;
1315     }
1316
1317   vlib_node_increment_counter (vm, node->node_index,
1318                                ESP_NO_CRYPTO_ERROR_RX_PKTS, frame->n_vectors);
1319
1320   vlib_buffer_enqueue_to_single_next (vm, node, from,
1321                                       ESP_NO_CRYPTO_NEXT_DROP,
1322                                       frame->n_vectors);
1323
1324   return frame->n_vectors;
1325 }
1326
1327 VLIB_NODE_FN (esp4_no_crypto_tun_node) (vlib_main_t * vm,
1328                                         vlib_node_runtime_t * node,
1329                                         vlib_frame_t * from_frame)
1330 {
1331   return esp_no_crypto_inline (vm, node, from_frame);
1332 }
1333
1334 /* *INDENT-OFF* */
1335 VLIB_REGISTER_NODE (esp4_no_crypto_tun_node) =
1336 {
1337   .name = "esp4-no-crypto",
1338   .vector_size = sizeof (u32),
1339   .format_trace = format_esp_no_crypto_trace,
1340   .n_errors = ARRAY_LEN(esp_no_crypto_error_strings),
1341   .error_strings = esp_no_crypto_error_strings,
1342   .n_next_nodes = ESP_NO_CRYPTO_N_NEXT,
1343   .next_nodes = {
1344     [ESP_NO_CRYPTO_NEXT_DROP] = "ip4-drop",
1345   },
1346 };
1347
1348 VLIB_NODE_FN (esp6_no_crypto_tun_node) (vlib_main_t * vm,
1349                                         vlib_node_runtime_t * node,
1350                                         vlib_frame_t * from_frame)
1351 {
1352   return esp_no_crypto_inline (vm, node, from_frame);
1353 }
1354
1355 /* *INDENT-OFF* */
1356 VLIB_REGISTER_NODE (esp6_no_crypto_tun_node) =
1357 {
1358   .name = "esp6-no-crypto",
1359   .vector_size = sizeof (u32),
1360   .format_trace = format_esp_no_crypto_trace,
1361   .n_errors = ARRAY_LEN(esp_no_crypto_error_strings),
1362   .error_strings = esp_no_crypto_error_strings,
1363   .n_next_nodes = ESP_NO_CRYPTO_N_NEXT,
1364   .next_nodes = {
1365     [ESP_NO_CRYPTO_NEXT_DROP] = "ip6-drop",
1366   },
1367 };
1368 /* *INDENT-ON* */
1369
1370 /*
1371  * fd.io coding-style-patch-verification: ON
1372  *
1373  * Local Variables:
1374  * eval: (c-set-style "gnu")
1375  * End:
1376  */