fib: midchain adjacency optimisations
[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 #include <vnet/udp/udp.h>
22
23 #include <vnet/crypto/crypto.h>
24
25 #include <vnet/ipsec/ipsec.h>
26 #include <vnet/ipsec/ipsec_tun.h>
27 #include <vnet/ipsec/esp.h>
28
29 #define foreach_esp_encrypt_next                   \
30 _(DROP, "error-drop")                              \
31 _(PENDING, "pending")                              \
32 _(HANDOFF, "handoff")                              \
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 block_size, 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, 0x00, 0x00,
120   };
121
122   u16 min_length = total_len + sizeof (esp_footer_t);
123   u16 new_length = round_pow2 (min_length, block_size);
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 {
240   u32 n_fail, n_ops = vec_len (ops);
241   vnet_crypto_op_t *op = ops;
242
243   if (n_ops == 0)
244     return;
245
246   n_fail = n_ops - vnet_crypto_process_chained_ops (vm, op, chunks, n_ops);
247
248   while (n_fail)
249     {
250       ASSERT (op - ops < n_ops);
251
252       if (op->status != VNET_CRYPTO_OP_STATUS_COMPLETED)
253         {
254           u32 bi = op->user_data;
255           b[bi]->error = node->errors[ESP_ENCRYPT_ERROR_CRYPTO_ENGINE_ERROR];
256           nexts[bi] = ESP_ENCRYPT_NEXT_DROP;
257           n_fail--;
258         }
259       op++;
260     }
261 }
262
263 static_always_inline void
264 esp_process_ops (vlib_main_t * vm, vlib_node_runtime_t * node,
265                  vnet_crypto_op_t * ops, vlib_buffer_t * b[], u16 * nexts)
266 {
267   u32 n_fail, n_ops = vec_len (ops);
268   vnet_crypto_op_t *op = ops;
269
270   if (n_ops == 0)
271     return;
272
273   n_fail = n_ops - vnet_crypto_process_ops (vm, op, n_ops);
274
275   while (n_fail)
276     {
277       ASSERT (op - ops < n_ops);
278
279       if (op->status != VNET_CRYPTO_OP_STATUS_COMPLETED)
280         {
281           u32 bi = op->user_data;
282           b[bi]->error = node->errors[ESP_ENCRYPT_ERROR_CRYPTO_ENGINE_ERROR];
283           nexts[bi] = ESP_ENCRYPT_NEXT_DROP;
284           n_fail--;
285         }
286       op++;
287     }
288 }
289
290 typedef struct
291 {
292   u32 salt;
293   u64 iv;
294 } __clib_packed esp_gcm_nonce_t;
295
296 STATIC_ASSERT_SIZEOF (esp_gcm_nonce_t, 12);
297
298 static_always_inline u32
299 esp_encrypt_chain_crypto (vlib_main_t * vm, ipsec_per_thread_data_t * ptd,
300                           ipsec_sa_t * sa0, vlib_buffer_t * b,
301                           vlib_buffer_t * lb, u8 icv_sz, u8 * start,
302                           u32 start_len, u16 * n_ch)
303 {
304   vnet_crypto_op_chunk_t *ch;
305   vlib_buffer_t *cb = b;
306   u32 n_chunks = 1;
307   u32 total_len;
308   vec_add2 (ptd->chunks, ch, 1);
309   total_len = ch->len = start_len;
310   ch->src = ch->dst = start;
311   cb = vlib_get_buffer (vm, cb->next_buffer);
312
313   while (1)
314     {
315       vec_add2 (ptd->chunks, ch, 1);
316       n_chunks += 1;
317       if (lb == cb)
318         total_len += ch->len = cb->current_length - icv_sz;
319       else
320         total_len += ch->len = cb->current_length;
321       ch->src = ch->dst = vlib_buffer_get_current (cb);
322
323       if (!(cb->flags & VLIB_BUFFER_NEXT_PRESENT))
324         break;
325
326       cb = vlib_get_buffer (vm, cb->next_buffer);
327     }
328
329   if (n_ch)
330     *n_ch = n_chunks;
331
332   return total_len;
333 }
334
335 static_always_inline u32
336 esp_encrypt_chain_integ (vlib_main_t * vm, ipsec_per_thread_data_t * ptd,
337                          ipsec_sa_t * sa0, vlib_buffer_t * b,
338                          vlib_buffer_t * lb, u8 icv_sz, u8 * start,
339                          u32 start_len, u8 * digest, u16 * n_ch)
340 {
341   vnet_crypto_op_chunk_t *ch;
342   vlib_buffer_t *cb = b;
343   u32 n_chunks = 1;
344   u32 total_len;
345   vec_add2 (ptd->chunks, ch, 1);
346   total_len = ch->len = start_len;
347   ch->src = start;
348   cb = vlib_get_buffer (vm, cb->next_buffer);
349
350   while (1)
351     {
352       vec_add2 (ptd->chunks, ch, 1);
353       n_chunks += 1;
354       if (lb == cb)
355         {
356           total_len += ch->len = cb->current_length - icv_sz;
357           if (ipsec_sa_is_set_USE_ESN (sa0))
358             {
359               u32 seq_hi = clib_net_to_host_u32 (sa0->seq_hi);
360               clib_memcpy_fast (digest, &seq_hi, sizeof (seq_hi));
361               ch->len += sizeof (seq_hi);
362               total_len += sizeof (seq_hi);
363             }
364         }
365       else
366         total_len += ch->len = cb->current_length;
367       ch->src = vlib_buffer_get_current (cb);
368
369       if (!(cb->flags & VLIB_BUFFER_NEXT_PRESENT))
370         break;
371
372       cb = vlib_get_buffer (vm, cb->next_buffer);
373     }
374
375   if (n_ch)
376     *n_ch = n_chunks;
377
378   return total_len;
379 }
380
381 always_inline void
382 esp_prepare_sync_op (vlib_main_t * vm, ipsec_per_thread_data_t * ptd,
383                      vnet_crypto_op_t ** crypto_ops,
384                      vnet_crypto_op_t ** integ_ops, ipsec_sa_t * sa0,
385                      u8 * payload, u16 payload_len, u8 iv_sz, u8 icv_sz,
386                      vlib_buffer_t ** bufs, vlib_buffer_t ** b,
387                      vlib_buffer_t * lb, u32 hdr_len, esp_header_t * esp,
388                      esp_gcm_nonce_t * nonce)
389 {
390   if (sa0->crypto_enc_op_id)
391     {
392       vnet_crypto_op_t *op;
393       vec_add2_aligned (crypto_ops[0], op, 1, CLIB_CACHE_LINE_BYTES);
394       vnet_crypto_op_init (op, sa0->crypto_enc_op_id);
395
396       op->src = op->dst = payload;
397       op->key_index = sa0->crypto_key_index;
398       op->len = payload_len - icv_sz;
399       op->user_data = b - bufs;
400
401       if (ipsec_sa_is_set_IS_AEAD (sa0))
402         {
403           /*
404            * construct the AAD in a scratch space in front
405            * of the IP header.
406            */
407           op->aad = payload - hdr_len - sizeof (esp_aead_t);
408           op->aad_len = esp_aad_fill (op->aad, esp, sa0);
409
410           op->tag = payload + op->len;
411           op->tag_len = 16;
412
413           u64 *iv = (u64 *) (payload - iv_sz);
414           nonce->salt = sa0->salt;
415           nonce->iv = *iv = clib_host_to_net_u64 (sa0->gcm_iv_counter++);
416           op->iv = (u8 *) nonce;
417         }
418       else
419         {
420           op->iv = payload - iv_sz;
421           op->flags = VNET_CRYPTO_OP_FLAG_INIT_IV;
422         }
423
424       if (lb != b[0])
425         {
426           /* is chained */
427           op->flags |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
428           op->chunk_index = vec_len (ptd->chunks);
429           op->tag = vlib_buffer_get_tail (lb) - icv_sz;
430           esp_encrypt_chain_crypto (vm, ptd, sa0, b[0], lb, icv_sz, payload,
431                                     payload_len, &op->n_chunks);
432         }
433     }
434
435   if (sa0->integ_op_id)
436     {
437       vnet_crypto_op_t *op;
438       vec_add2_aligned (integ_ops[0], op, 1, CLIB_CACHE_LINE_BYTES);
439       vnet_crypto_op_init (op, sa0->integ_op_id);
440       op->src = payload - iv_sz - sizeof (esp_header_t);
441       op->digest = payload + payload_len - icv_sz;
442       op->key_index = sa0->integ_key_index;
443       op->digest_len = icv_sz;
444       op->len = payload_len - icv_sz + iv_sz + sizeof (esp_header_t);
445       op->user_data = b - bufs;
446
447       if (lb != b[0])
448         {
449           /* is chained */
450           op->flags |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
451           op->chunk_index = vec_len (ptd->chunks);
452           op->digest = vlib_buffer_get_tail (lb) - icv_sz;
453
454           esp_encrypt_chain_integ (vm, ptd, sa0, b[0], lb, icv_sz,
455                                    payload - iv_sz - sizeof (esp_header_t),
456                                    payload_len + iv_sz +
457                                    sizeof (esp_header_t), op->digest,
458                                    &op->n_chunks);
459         }
460       else if (ipsec_sa_is_set_USE_ESN (sa0))
461         {
462           u32 seq_hi = clib_net_to_host_u32 (sa0->seq_hi);
463           clib_memcpy_fast (op->digest, &seq_hi, sizeof (seq_hi));
464           op->len += sizeof (seq_hi);
465         }
466     }
467 }
468
469 static_always_inline int
470 esp_prepare_async_frame (vlib_main_t * vm, ipsec_per_thread_data_t * ptd,
471                          vnet_crypto_async_frame_t ** async_frame,
472                          ipsec_sa_t * sa, vlib_buffer_t * b,
473                          esp_header_t * esp, u8 * payload, u32 payload_len,
474                          u8 iv_sz, u8 icv_sz, u32 bi, u16 * next, u32 hdr_len,
475                          u16 async_next, vlib_buffer_t * lb)
476 {
477   esp_post_data_t *post = esp_post_data (b);
478   u8 *tag, *iv, *aad = 0;
479   u8 flag = 0;
480   u32 key_index;
481   i16 crypto_start_offset, integ_start_offset = 0;
482   u16 crypto_total_len, integ_total_len;
483
484   post->next_index = next[0];
485   next[0] = ESP_ENCRYPT_NEXT_PENDING;
486
487   /* crypto */
488   crypto_start_offset = payload - b->data;
489   crypto_total_len = integ_total_len = payload_len - icv_sz;
490   tag = payload + crypto_total_len;
491
492   /* aead */
493   if (ipsec_sa_is_set_IS_AEAD (sa))
494     {
495       esp_gcm_nonce_t *nonce;
496       u64 *pkt_iv = (u64 *) (payload - iv_sz);
497
498       aad = payload - hdr_len - sizeof (esp_aead_t);
499       esp_aad_fill (aad, esp, sa);
500       nonce = (esp_gcm_nonce_t *) (aad - sizeof (*nonce));
501       nonce->salt = sa->salt;
502       nonce->iv = *pkt_iv = clib_host_to_net_u64 (sa->gcm_iv_counter++);
503       iv = (u8 *) nonce;
504       key_index = sa->crypto_key_index;
505
506       if (lb != b)
507         {
508           /* chain */
509           flag |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
510           tag = vlib_buffer_get_tail (lb) - icv_sz;
511           crypto_total_len = esp_encrypt_chain_crypto (vm, ptd, sa, b, lb,
512                                                        icv_sz, payload,
513                                                        payload_len, 0);
514         }
515       goto out;
516     }
517
518   /* cipher then hash */
519   iv = payload - iv_sz;
520   integ_start_offset = crypto_start_offset - iv_sz - sizeof (esp_header_t);
521   integ_total_len += iv_sz + sizeof (esp_header_t);
522   flag |= VNET_CRYPTO_OP_FLAG_INIT_IV;
523   key_index = sa->linked_key_index;
524
525   if (b != lb)
526     {
527       flag |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
528       crypto_total_len = esp_encrypt_chain_crypto (vm, ptd, sa, b, lb,
529                                                    icv_sz, payload,
530                                                    payload_len, 0);
531       tag = vlib_buffer_get_tail (lb) - icv_sz;
532       integ_total_len = esp_encrypt_chain_integ (vm, ptd, sa, b, lb, icv_sz,
533                                                  payload - iv_sz -
534                                                  sizeof (esp_header_t),
535                                                  payload_len + iv_sz +
536                                                  sizeof (esp_header_t),
537                                                  tag, 0);
538     }
539   else if (ipsec_sa_is_set_USE_ESN (sa) && !ipsec_sa_is_set_IS_AEAD (sa))
540     {
541       u32 seq_hi = clib_net_to_host_u32 (sa->seq_hi);
542       clib_memcpy_fast (tag, &seq_hi, sizeof (seq_hi));
543       integ_total_len += sizeof (seq_hi);
544     }
545
546 out:
547   return vnet_crypto_async_add_to_frame (vm, async_frame, key_index,
548                                          crypto_total_len,
549                                          integ_total_len - crypto_total_len,
550                                          crypto_start_offset,
551                                          integ_start_offset, bi, async_next,
552                                          iv, tag, aad, flag);
553 }
554
555 /* when submitting a frame is failed, drop all buffers in the frame */
556 static_always_inline void
557 esp_async_recycle_failed_submit (vnet_crypto_async_frame_t * f,
558                                  vlib_buffer_t ** b, u16 * next)
559 {
560   u32 n_drop = f->n_elts;
561   while (--n_drop)
562     {
563       (b - n_drop)[0]->error = ESP_ENCRYPT_ERROR_CRYPTO_ENGINE_ERROR;
564       (next - n_drop)[0] = ESP_ENCRYPT_NEXT_DROP;
565     }
566   vnet_crypto_async_reset_frame (f);
567 }
568
569 always_inline uword
570 esp_encrypt_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
571                     vlib_frame_t * frame, int is_ip6, int is_tun,
572                     u16 async_next)
573 {
574   ipsec_main_t *im = &ipsec_main;
575   ipsec_per_thread_data_t *ptd = vec_elt_at_index (im->ptd, vm->thread_index);
576   u32 *from = vlib_frame_vector_args (frame);
577   u32 n_left = frame->n_vectors;
578   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
579   u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
580   esp_gcm_nonce_t nonces[VLIB_FRAME_SIZE], *nonce = nonces;
581   u32 thread_index = vm->thread_index;
582   u16 buffer_data_size = vlib_buffer_get_default_data_size (vm);
583   u32 current_sa_index = ~0, current_sa_packets = 0;
584   u32 current_sa_bytes = 0, spi = 0;
585   u8 block_sz = 0, iv_sz = 0, icv_sz = 0;
586   ipsec_sa_t *sa0 = 0;
587   vlib_buffer_t *lb;
588   vnet_crypto_op_t **crypto_ops = &ptd->crypto_ops;
589   vnet_crypto_op_t **integ_ops = &ptd->integ_ops;
590   vnet_crypto_async_frame_t *async_frame = 0;
591   int is_async = im->async_mode;
592   vnet_crypto_async_op_id_t last_async_op = ~0;
593
594   vlib_get_buffers (vm, from, b, n_left);
595   if (!is_async)
596     {
597       vec_reset_length (ptd->crypto_ops);
598       vec_reset_length (ptd->integ_ops);
599       vec_reset_length (ptd->chained_crypto_ops);
600       vec_reset_length (ptd->chained_integ_ops);
601     }
602   vec_reset_length (ptd->chunks);
603
604   while (n_left > 0)
605     {
606       u32 sa_index0;
607       dpo_id_t *dpo;
608       esp_header_t *esp;
609       u8 *payload, *next_hdr_ptr;
610       u16 payload_len, payload_len_total, n_bufs;
611       u32 hdr_len;
612
613       if (n_left > 2)
614         {
615           u8 *p;
616           vlib_prefetch_buffer_header (b[2], LOAD);
617           p = vlib_buffer_get_current (b[1]);
618           CLIB_PREFETCH (p, CLIB_CACHE_LINE_BYTES, LOAD);
619           p -= CLIB_CACHE_LINE_BYTES;
620           CLIB_PREFETCH (p, CLIB_CACHE_LINE_BYTES, LOAD);
621         }
622
623       if (is_tun)
624         {
625           /* we are on a ipsec tunnel's feature arc */
626           vnet_buffer (b[0])->ipsec.sad_index =
627             sa_index0 = ipsec_tun_protect_get_sa_out
628             (vnet_buffer (b[0])->ip.adj_index[VLIB_TX]);
629         }
630       else
631         sa_index0 = vnet_buffer (b[0])->ipsec.sad_index;
632
633       if (sa_index0 != current_sa_index)
634         {
635           if (current_sa_packets)
636             vlib_increment_combined_counter (&ipsec_sa_counters, thread_index,
637                                              current_sa_index,
638                                              current_sa_packets,
639                                              current_sa_bytes);
640           current_sa_packets = current_sa_bytes = 0;
641
642           sa0 = pool_elt_at_index (im->sad, sa_index0);
643           current_sa_index = sa_index0;
644           spi = clib_net_to_host_u32 (sa0->spi);
645           block_sz = sa0->crypto_block_size;
646           icv_sz = sa0->integ_icv_size;
647           iv_sz = sa0->crypto_iv_size;
648
649           /* submit frame when op_id is different then the old one */
650           if (is_async && sa0->crypto_async_enc_op_id != last_async_op)
651             {
652               if (async_frame && async_frame->n_elts)
653                 {
654                   if (vnet_crypto_async_submit_open_frame (vm, async_frame)
655                       < 0)
656                     esp_async_recycle_failed_submit (async_frame, b, next);
657                 }
658               async_frame =
659                 vnet_crypto_async_get_frame (vm, sa0->crypto_async_enc_op_id);
660               last_async_op = sa0->crypto_async_enc_op_id;
661             }
662         }
663
664       if (PREDICT_FALSE (~0 == sa0->encrypt_thread_index))
665         {
666           /* this is the first packet to use this SA, claim the SA
667            * for this thread. this could happen simultaneously on
668            * another thread */
669           clib_atomic_cmp_and_swap (&sa0->encrypt_thread_index, ~0,
670                                     ipsec_sa_assign_thread (thread_index));
671         }
672
673       if (PREDICT_TRUE (thread_index != sa0->encrypt_thread_index))
674         {
675           next[0] = ESP_ENCRYPT_NEXT_HANDOFF;
676           goto trace;
677         }
678
679       lb = b[0];
680       n_bufs = vlib_buffer_chain_linearize (vm, b[0]);
681       if (n_bufs == 0)
682         {
683           b[0]->error = node->errors[ESP_ENCRYPT_ERROR_NO_BUFFERS];
684           next[0] = ESP_ENCRYPT_NEXT_DROP;
685           goto trace;
686         }
687
688       if (n_bufs > 1)
689         {
690           crypto_ops = &ptd->chained_crypto_ops;
691           integ_ops = &ptd->chained_integ_ops;
692
693           /* find last buffer in the chain */
694           while (lb->flags & VLIB_BUFFER_NEXT_PRESENT)
695             lb = vlib_get_buffer (vm, lb->next_buffer);
696         }
697       else
698         {
699           crypto_ops = &ptd->crypto_ops;
700           integ_ops = &ptd->integ_ops;
701         }
702
703       if (PREDICT_FALSE (esp_seq_advance (sa0)))
704         {
705           b[0]->error = node->errors[ESP_ENCRYPT_ERROR_SEQ_CYCLED];
706           next[0] = ESP_ENCRYPT_NEXT_DROP;
707           goto trace;
708         }
709
710       /* space for IV */
711       hdr_len = iv_sz;
712
713       if (ipsec_sa_is_set_IS_TUNNEL (sa0))
714         {
715           payload = vlib_buffer_get_current (b[0]);
716           next_hdr_ptr = esp_add_footer_and_icv (vm, &lb, block_sz, icv_sz,
717                                                  next, node,
718                                                  buffer_data_size,
719                                                  vlib_buffer_length_in_chain
720                                                  (vm, b[0]));
721           if (!next_hdr_ptr)
722             {
723               b[0]->error = node->errors[ESP_ENCRYPT_ERROR_NO_BUFFERS];
724               next[0] = ESP_ENCRYPT_NEXT_DROP;
725               goto trace;
726             }
727           b[0]->flags &= ~VLIB_BUFFER_TOTAL_LENGTH_VALID;
728           payload_len = b[0]->current_length;
729           payload_len_total = vlib_buffer_length_in_chain (vm, b[0]);
730
731           /* ESP header */
732           hdr_len += sizeof (*esp);
733           esp = (esp_header_t *) (payload - hdr_len);
734
735           /* optional UDP header */
736           if (ipsec_sa_is_set_UDP_ENCAP (sa0))
737             {
738               hdr_len += sizeof (udp_header_t);
739               esp_fill_udp_hdr (sa0, (udp_header_t *) (payload - hdr_len),
740                                 payload_len_total + hdr_len);
741             }
742
743           /* IP header */
744           if (ipsec_sa_is_set_IS_TUNNEL_V6 (sa0))
745             {
746               ip6_header_t *ip6;
747               u16 len = sizeof (ip6_header_t);
748               hdr_len += len;
749               ip6 = (ip6_header_t *) (payload - hdr_len);
750               clib_memcpy_fast (ip6, &sa0->ip6_hdr, len);
751               *next_hdr_ptr = (is_ip6 ?
752                                IP_PROTOCOL_IPV6 : IP_PROTOCOL_IP_IN_IP);
753               len = payload_len_total + hdr_len - len;
754               ip6->payload_length = clib_net_to_host_u16 (len);
755             }
756           else
757             {
758               ip4_header_t *ip4;
759               u16 len = sizeof (ip4_header_t);
760               hdr_len += len;
761               ip4 = (ip4_header_t *) (payload - hdr_len);
762               clib_memcpy_fast (ip4, &sa0->ip4_hdr, len);
763               *next_hdr_ptr = (is_ip6 ?
764                                IP_PROTOCOL_IPV6 : IP_PROTOCOL_IP_IN_IP);
765               len = payload_len_total + hdr_len;
766               esp_update_ip4_hdr (ip4, len, /* is_transport */ 0, 0);
767             }
768
769           dpo = &sa0->dpo;
770           if (!is_tun)
771             {
772               next[0] = dpo->dpoi_next_node;
773               vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = dpo->dpoi_index;
774             }
775           else
776             next[0] = ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT;
777         }
778       else                      /* transport mode */
779         {
780           u8 *l2_hdr, l2_len, *ip_hdr, ip_len;
781           ip6_ext_header_t *ext_hdr;
782           udp_header_t *udp = 0;
783           u16 udp_len = 0;
784           u8 *old_ip_hdr = vlib_buffer_get_current (b[0]);
785
786           ip_len = is_ip6 ?
787             esp_get_ip6_hdr_len ((ip6_header_t *) old_ip_hdr, &ext_hdr) :
788             ip4_header_bytes ((ip4_header_t *) old_ip_hdr);
789
790           vlib_buffer_advance (b[0], ip_len);
791           payload = vlib_buffer_get_current (b[0]);
792           next_hdr_ptr = esp_add_footer_and_icv (vm, &lb, block_sz, icv_sz,
793                                                  next, node,
794                                                  buffer_data_size,
795                                                  vlib_buffer_length_in_chain
796                                                  (vm, b[0]));
797           if (!next_hdr_ptr)
798             goto trace;
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       esp->spi = spi;
875       esp->seq = clib_net_to_host_u32 (sa0->seq);
876
877       if (is_async)
878         {
879           if (PREDICT_FALSE (sa0->crypto_async_enc_op_id == 0))
880             goto trace;
881
882           if (esp_prepare_async_frame (vm, ptd, &async_frame, sa0, b[0], esp,
883                                        payload, payload_len, iv_sz,
884                                        icv_sz, from[b - bufs], next, hdr_len,
885                                        async_next, lb))
886             {
887               esp_async_recycle_failed_submit (async_frame, b, next);
888               goto trace;
889             }
890         }
891       else
892         {
893           esp_prepare_sync_op (vm, ptd, crypto_ops, integ_ops, sa0, payload,
894                                payload_len, iv_sz, icv_sz, bufs, b, lb,
895                                hdr_len, esp, nonce++);
896         }
897
898       vlib_buffer_advance (b[0], 0LL - hdr_len);
899
900       current_sa_packets += 1;
901       current_sa_bytes += payload_len_total;
902
903     trace:
904       if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
905         {
906           esp_encrypt_trace_t *tr = vlib_add_trace (vm, node, b[0],
907                                                     sizeof (*tr));
908           tr->sa_index = sa_index0;
909           tr->spi = sa0->spi;
910           tr->seq = sa0->seq;
911           tr->sa_seq_hi = sa0->seq_hi;
912           tr->udp_encap = ipsec_sa_is_set_UDP_ENCAP (sa0);
913           tr->crypto_alg = sa0->crypto_alg;
914           tr->integ_alg = sa0->integ_alg;
915         }
916       /* next */
917       n_left -= 1;
918       next += 1;
919       b += 1;
920     }
921
922   vlib_increment_combined_counter (&ipsec_sa_counters, thread_index,
923                                    current_sa_index, current_sa_packets,
924                                    current_sa_bytes);
925   if (!is_async)
926     {
927       esp_process_ops (vm, node, ptd->crypto_ops, bufs, nexts);
928       esp_process_chained_ops (vm, node, ptd->chained_crypto_ops, bufs, nexts,
929                                ptd->chunks);
930
931       esp_process_ops (vm, node, ptd->integ_ops, bufs, nexts);
932       esp_process_chained_ops (vm, node, ptd->chained_integ_ops, bufs, nexts,
933                                ptd->chunks);
934     }
935   else if (async_frame && async_frame->n_elts)
936     {
937       if (vnet_crypto_async_submit_open_frame (vm, async_frame) < 0)
938         esp_async_recycle_failed_submit (async_frame, b, next);
939     }
940
941   vlib_node_increment_counter (vm, node->node_index,
942                                ESP_ENCRYPT_ERROR_RX_PKTS, frame->n_vectors);
943
944   vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
945   return frame->n_vectors;
946 }
947
948 always_inline uword
949 esp_encrypt_post_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
950                          vlib_frame_t * frame)
951 {
952   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
953   u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
954   u32 *from = vlib_frame_vector_args (frame);
955   u32 n_left = frame->n_vectors;
956
957   vlib_get_buffers (vm, from, b, n_left);
958
959   if (n_left >= 4)
960     {
961       vlib_prefetch_buffer_header (b[0], LOAD);
962       vlib_prefetch_buffer_header (b[1], LOAD);
963       vlib_prefetch_buffer_header (b[2], LOAD);
964       vlib_prefetch_buffer_header (b[3], LOAD);
965     }
966
967   while (n_left > 8)
968     {
969       vlib_prefetch_buffer_header (b[4], LOAD);
970       vlib_prefetch_buffer_header (b[5], LOAD);
971       vlib_prefetch_buffer_header (b[6], LOAD);
972       vlib_prefetch_buffer_header (b[7], LOAD);
973
974       next[0] = (esp_post_data (b[0]))->next_index;
975       next[1] = (esp_post_data (b[1]))->next_index;
976       next[2] = (esp_post_data (b[2]))->next_index;
977       next[3] = (esp_post_data (b[3]))->next_index;
978
979       if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
980         {
981           if (b[0]->flags & VLIB_BUFFER_IS_TRACED)
982             {
983               esp_encrypt_post_trace_t *tr = vlib_add_trace (vm, node, b[0],
984                                                              sizeof (*tr));
985               tr->next_index = next[0];
986             }
987           if (b[1]->flags & VLIB_BUFFER_IS_TRACED)
988             {
989               esp_encrypt_post_trace_t *tr = vlib_add_trace (vm, node, b[1],
990                                                              sizeof (*tr));
991               tr->next_index = next[1];
992             }
993           if (b[2]->flags & VLIB_BUFFER_IS_TRACED)
994             {
995               esp_encrypt_post_trace_t *tr = vlib_add_trace (vm, node, b[2],
996                                                              sizeof (*tr));
997               tr->next_index = next[2];
998             }
999           if (b[3]->flags & VLIB_BUFFER_IS_TRACED)
1000             {
1001               esp_encrypt_post_trace_t *tr = vlib_add_trace (vm, node, b[3],
1002                                                              sizeof (*tr));
1003               tr->next_index = next[3];
1004             }
1005         }
1006
1007       b += 4;
1008       next += 4;
1009       n_left -= 4;
1010     }
1011
1012   while (n_left > 0)
1013     {
1014       next[0] = (esp_post_data (b[0]))->next_index;
1015       if (PREDICT_FALSE (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
1022       b += 1;
1023       next += 1;
1024       n_left -= 1;
1025     }
1026
1027   vlib_node_increment_counter (vm, node->node_index,
1028                                ESP_ENCRYPT_ERROR_POST_RX_PKTS,
1029                                frame->n_vectors);
1030   vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
1031   return frame->n_vectors;
1032 }
1033
1034 VLIB_NODE_FN (esp4_encrypt_node) (vlib_main_t * vm,
1035                                   vlib_node_runtime_t * node,
1036                                   vlib_frame_t * from_frame)
1037 {
1038   return esp_encrypt_inline (vm, node, from_frame, 0 /* is_ip6 */ , 0,
1039                              esp_encrypt_async_next.esp4_post_next);
1040 }
1041
1042 /* *INDENT-OFF* */
1043 VLIB_REGISTER_NODE (esp4_encrypt_node) = {
1044   .name = "esp4-encrypt",
1045   .vector_size = sizeof (u32),
1046   .format_trace = format_esp_encrypt_trace,
1047   .type = VLIB_NODE_TYPE_INTERNAL,
1048
1049   .n_errors = ARRAY_LEN(esp_encrypt_error_strings),
1050   .error_strings = esp_encrypt_error_strings,
1051
1052   .n_next_nodes = ESP_ENCRYPT_N_NEXT,
1053   .next_nodes = {
1054     [ESP_ENCRYPT_NEXT_DROP] = "ip4-drop",
1055     [ESP_ENCRYPT_NEXT_HANDOFF] = "esp4-encrypt-handoff",
1056     [ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT] = "interface-output",
1057     [ESP_ENCRYPT_NEXT_PENDING] = "esp-encrypt-pending",
1058   },
1059 };
1060 /* *INDENT-ON* */
1061
1062 VLIB_NODE_FN (esp4_encrypt_post_node) (vlib_main_t * vm,
1063                                        vlib_node_runtime_t * node,
1064                                        vlib_frame_t * from_frame)
1065 {
1066   return esp_encrypt_post_inline (vm, node, from_frame);
1067 }
1068
1069 /* *INDENT-OFF* */
1070 VLIB_REGISTER_NODE (esp4_encrypt_post_node) = {
1071   .name = "esp4-encrypt-post",
1072   .vector_size = sizeof (u32),
1073   .format_trace = format_esp_post_encrypt_trace,
1074   .type = VLIB_NODE_TYPE_INTERNAL,
1075   .sibling_of = "esp4-encrypt",
1076
1077   .n_errors = ARRAY_LEN(esp_encrypt_error_strings),
1078   .error_strings = esp_encrypt_error_strings,
1079 };
1080 /* *INDENT-ON* */
1081
1082 VLIB_NODE_FN (esp6_encrypt_node) (vlib_main_t * vm,
1083                                   vlib_node_runtime_t * node,
1084                                   vlib_frame_t * from_frame)
1085 {
1086   return esp_encrypt_inline (vm, node, from_frame, 1 /* is_ip6 */ , 0,
1087                              esp_encrypt_async_next.esp6_post_next);
1088 }
1089
1090 /* *INDENT-OFF* */
1091 VLIB_REGISTER_NODE (esp6_encrypt_node) = {
1092   .name = "esp6-encrypt",
1093   .vector_size = sizeof (u32),
1094   .format_trace = format_esp_encrypt_trace,
1095   .type = VLIB_NODE_TYPE_INTERNAL,
1096
1097   .n_errors = ARRAY_LEN(esp_encrypt_error_strings),
1098   .error_strings = esp_encrypt_error_strings,
1099
1100   .n_next_nodes = ESP_ENCRYPT_N_NEXT,
1101   .next_nodes = {
1102     [ESP_ENCRYPT_NEXT_DROP] = "ip6-drop",
1103     [ESP_ENCRYPT_NEXT_HANDOFF] = "esp6-encrypt-handoff",
1104     [ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT] = "interface-output",
1105     [ESP_ENCRYPT_NEXT_PENDING] = "esp-encrypt-pending",
1106   },
1107 };
1108 /* *INDENT-ON* */
1109
1110 VLIB_NODE_FN (esp6_encrypt_post_node) (vlib_main_t * vm,
1111                                        vlib_node_runtime_t * node,
1112                                        vlib_frame_t * from_frame)
1113 {
1114   return esp_encrypt_post_inline (vm, node, from_frame);
1115 }
1116
1117 /* *INDENT-OFF* */
1118 VLIB_REGISTER_NODE (esp6_encrypt_post_node) = {
1119   .name = "esp6-encrypt-post",
1120   .vector_size = sizeof (u32),
1121   .format_trace = format_esp_post_encrypt_trace,
1122   .type = VLIB_NODE_TYPE_INTERNAL,
1123   .sibling_of = "esp6-encrypt",
1124
1125   .n_errors = ARRAY_LEN(esp_encrypt_error_strings),
1126   .error_strings = esp_encrypt_error_strings,
1127 };
1128 /* *INDENT-ON* */
1129
1130 VLIB_NODE_FN (esp4_encrypt_tun_node) (vlib_main_t * vm,
1131                                       vlib_node_runtime_t * node,
1132                                       vlib_frame_t * from_frame)
1133 {
1134   return esp_encrypt_inline (vm, node, from_frame, 0 /* is_ip6 */ , 1,
1135                              esp_encrypt_async_next.esp4_tun_post_next);
1136 }
1137
1138 /* *INDENT-OFF* */
1139 VLIB_REGISTER_NODE (esp4_encrypt_tun_node) = {
1140   .name = "esp4-encrypt-tun",
1141   .vector_size = sizeof (u32),
1142   .format_trace = format_esp_encrypt_trace,
1143   .type = VLIB_NODE_TYPE_INTERNAL,
1144
1145   .n_errors = ARRAY_LEN(esp_encrypt_error_strings),
1146   .error_strings = esp_encrypt_error_strings,
1147
1148   .n_next_nodes = ESP_ENCRYPT_N_NEXT,
1149   .next_nodes = {
1150     [ESP_ENCRYPT_NEXT_DROP] = "ip4-drop",
1151     [ESP_ENCRYPT_NEXT_HANDOFF] = "esp4-encrypt-tun-handoff",
1152     [ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT] = "adj-midchain-tx",
1153     [ESP_ENCRYPT_NEXT_PENDING] = "esp-encrypt-pending",
1154   },
1155 };
1156
1157 VLIB_NODE_FN (esp4_encrypt_tun_post_node) (vlib_main_t * vm,
1158                                   vlib_node_runtime_t * node,
1159                                   vlib_frame_t * from_frame)
1160 {
1161   return esp_encrypt_post_inline (vm, node, from_frame);
1162 }
1163
1164 /* *INDENT-OFF* */
1165 VLIB_REGISTER_NODE (esp4_encrypt_tun_post_node) = {
1166   .name = "esp4-encrypt-tun-post",
1167   .vector_size = sizeof (u32),
1168   .format_trace = format_esp_post_encrypt_trace,
1169   .type = VLIB_NODE_TYPE_INTERNAL,
1170   .sibling_of = "esp4-encrypt-tun",
1171
1172   .n_errors = ARRAY_LEN(esp_encrypt_error_strings),
1173   .error_strings = esp_encrypt_error_strings,
1174 };
1175 /* *INDENT-ON* */
1176
1177 VLIB_NODE_FN (esp6_encrypt_tun_node) (vlib_main_t * vm,
1178                                       vlib_node_runtime_t * node,
1179                                       vlib_frame_t * from_frame)
1180 {
1181   return esp_encrypt_inline (vm, node, from_frame, 1 /* is_ip6 */ , 1,
1182                              esp_encrypt_async_next.esp6_tun_post_next);
1183 }
1184
1185 /* *INDENT-OFF* */
1186 VLIB_REGISTER_NODE (esp6_encrypt_tun_node) = {
1187   .name = "esp6-encrypt-tun",
1188   .vector_size = sizeof (u32),
1189   .format_trace = format_esp_encrypt_trace,
1190   .type = VLIB_NODE_TYPE_INTERNAL,
1191
1192   .n_errors = ARRAY_LEN(esp_encrypt_error_strings),
1193   .error_strings = esp_encrypt_error_strings,
1194
1195   .n_next_nodes = ESP_ENCRYPT_N_NEXT,
1196   .next_nodes = {
1197     [ESP_ENCRYPT_NEXT_DROP] = "ip6-drop",
1198     [ESP_ENCRYPT_NEXT_HANDOFF] = "esp6-encrypt-tun-handoff",
1199     [ESP_ENCRYPT_NEXT_PENDING] = "esp-encrypt-pending",
1200     [ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT] = "adj-midchain-tx",
1201   },
1202 };
1203
1204 /* *INDENT-ON* */
1205
1206 VLIB_NODE_FN (esp6_encrypt_tun_post_node) (vlib_main_t * vm,
1207                                            vlib_node_runtime_t * node,
1208                                            vlib_frame_t * from_frame)
1209 {
1210   return esp_encrypt_post_inline (vm, node, from_frame);
1211 }
1212
1213 /* *INDENT-OFF* */
1214 VLIB_REGISTER_NODE (esp6_encrypt_tun_post_node) = {
1215   .name = "esp6-encrypt-tun-post",
1216   .vector_size = sizeof (u32),
1217   .format_trace = format_esp_post_encrypt_trace,
1218   .type = VLIB_NODE_TYPE_INTERNAL,
1219   .sibling_of = "esp6-encrypt-tun",
1220
1221   .n_errors = ARRAY_LEN(esp_encrypt_error_strings),
1222   .error_strings = esp_encrypt_error_strings,
1223 };
1224 /* *INDENT-ON* */
1225
1226 typedef struct
1227 {
1228   u32 sa_index;
1229 } esp_no_crypto_trace_t;
1230
1231 static u8 *
1232 format_esp_no_crypto_trace (u8 * s, va_list * args)
1233 {
1234   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1235   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1236   esp_no_crypto_trace_t *t = va_arg (*args, esp_no_crypto_trace_t *);
1237
1238   s = format (s, "esp-no-crypto: sa-index %u", t->sa_index);
1239
1240   return s;
1241 }
1242
1243 enum
1244 {
1245   ESP_NO_CRYPTO_NEXT_DROP,
1246   ESP_NO_CRYPTO_N_NEXT,
1247 };
1248
1249 enum
1250 {
1251   ESP_NO_CRYPTO_ERROR_RX_PKTS,
1252 };
1253
1254 static char *esp_no_crypto_error_strings[] = {
1255   "Outbound ESP packets received",
1256 };
1257
1258 always_inline uword
1259 esp_no_crypto_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
1260                       vlib_frame_t * frame)
1261 {
1262   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
1263   u32 *from = vlib_frame_vector_args (frame);
1264   u32 n_left = frame->n_vectors;
1265
1266   vlib_get_buffers (vm, from, b, n_left);
1267
1268   while (n_left > 0)
1269     {
1270       u32 sa_index0;
1271
1272       /* packets are always going to be dropped, but get the sa_index */
1273       sa_index0 = ipsec_tun_protect_get_sa_out
1274         (vnet_buffer (b[0])->ip.adj_index[VLIB_TX]);
1275
1276       if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
1277         {
1278           esp_no_crypto_trace_t *tr = vlib_add_trace (vm, node, b[0],
1279                                                       sizeof (*tr));
1280           tr->sa_index = sa_index0;
1281         }
1282
1283       n_left -= 1;
1284       b += 1;
1285     }
1286
1287   vlib_node_increment_counter (vm, node->node_index,
1288                                ESP_NO_CRYPTO_ERROR_RX_PKTS, frame->n_vectors);
1289
1290   vlib_buffer_enqueue_to_single_next (vm, node, from,
1291                                       ESP_NO_CRYPTO_NEXT_DROP,
1292                                       frame->n_vectors);
1293
1294   return frame->n_vectors;
1295 }
1296
1297 VLIB_NODE_FN (esp4_no_crypto_tun_node) (vlib_main_t * vm,
1298                                         vlib_node_runtime_t * node,
1299                                         vlib_frame_t * from_frame)
1300 {
1301   return esp_no_crypto_inline (vm, node, from_frame);
1302 }
1303
1304 /* *INDENT-OFF* */
1305 VLIB_REGISTER_NODE (esp4_no_crypto_tun_node) =
1306 {
1307   .name = "esp4-no-crypto",
1308   .vector_size = sizeof (u32),
1309   .format_trace = format_esp_no_crypto_trace,
1310   .n_errors = ARRAY_LEN(esp_no_crypto_error_strings),
1311   .error_strings = esp_no_crypto_error_strings,
1312   .n_next_nodes = ESP_NO_CRYPTO_N_NEXT,
1313   .next_nodes = {
1314     [ESP_NO_CRYPTO_NEXT_DROP] = "ip4-drop",
1315   },
1316 };
1317
1318 VLIB_NODE_FN (esp6_no_crypto_tun_node) (vlib_main_t * vm,
1319                                         vlib_node_runtime_t * node,
1320                                         vlib_frame_t * from_frame)
1321 {
1322   return esp_no_crypto_inline (vm, node, from_frame);
1323 }
1324
1325 /* *INDENT-OFF* */
1326 VLIB_REGISTER_NODE (esp6_no_crypto_tun_node) =
1327 {
1328   .name = "esp6-no-crypto",
1329   .vector_size = sizeof (u32),
1330   .format_trace = format_esp_no_crypto_trace,
1331   .n_errors = ARRAY_LEN(esp_no_crypto_error_strings),
1332   .error_strings = esp_no_crypto_error_strings,
1333   .n_next_nodes = ESP_NO_CRYPTO_N_NEXT,
1334   .next_nodes = {
1335     [ESP_NO_CRYPTO_NEXT_DROP] = "ip6-drop",
1336   },
1337 };
1338 /* *INDENT-ON* */
1339
1340 VLIB_NODE_FN (esp_encrypt_pending_node) (vlib_main_t * vm,
1341                                          vlib_node_runtime_t * node,
1342                                          vlib_frame_t * from_frame)
1343 {
1344   return from_frame->n_vectors;
1345 }
1346
1347 /* *INDENT-OFF* */
1348 VLIB_REGISTER_NODE (esp_encrypt_pending_node) = {
1349   .name = "esp-encrypt-pending",
1350   .vector_size = sizeof (u32),
1351   .type = VLIB_NODE_TYPE_INTERNAL,
1352
1353   .n_next_nodes = 0
1354 };
1355 /* *INDENT-ON* */
1356
1357 /*
1358  * fd.io coding-style-patch-verification: ON
1359  *
1360  * Local Variables:
1361  * eval: (c-set-style "gnu")
1362  * End:
1363  */