FD.io VPP  v19.08.1-401-g8e4ed521a
Vector Packet Processing
esp_encrypt.c
Go to the documentation of this file.
1 /*
2  * esp_encrypt.c : IPSec ESP encrypt node
3  *
4  * Copyright (c) 2015 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vnet/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/esp.h>
27 
28 #define foreach_esp_encrypt_next \
29 _(DROP, "error-drop") \
30 _(IP4_LOOKUP, "ip4-lookup") \
31 _(IP6_LOOKUP, "ip6-lookup") \
32 _(INTERFACE_OUTPUT, "interface-output")
33 
34 #define _(v, s) ESP_ENCRYPT_NEXT_##v,
35 typedef enum
36 {
38 #undef _
41 
42 #define foreach_esp_encrypt_error \
43  _(RX_PKTS, "ESP pkts received") \
44  _(SEQ_CYCLED, "sequence number cycled (packet dropped)") \
45  _(CRYPTO_ENGINE_ERROR, "crypto engine error (packet dropped)") \
46  _(CHAINED_BUFFER, "chained buffers (packet dropped)") \
47  _(NO_TRAILER_SPACE, "no trailer space (packet dropped)")
48 
49 typedef enum
50 {
51 #define _(sym,str) ESP_ENCRYPT_ERROR_##sym,
53 #undef _
56 
57 static char *esp_encrypt_error_strings[] = {
58 #define _(sym,string) string,
60 #undef _
61 };
62 
63 typedef struct
64 {
73 
74 /* packet trace format function */
75 static u8 *
76 format_esp_encrypt_trace (u8 * s, va_list * args)
77 {
78  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
79  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
80  esp_encrypt_trace_t *t = va_arg (*args, esp_encrypt_trace_t *);
81 
82  s =
83  format (s,
84  "esp: sa-index %d spi %u (0x%08x) seq %u sa-seq-hi %u crypto %U integrity %U%s",
85  t->sa_index, t->spi, t->spi, t->seq, t->sa_seq_hi,
88  t->udp_encap ? " udp-encap-enabled" : "");
89  return s;
90 }
91 
92 /* pad packet in input buffer */
94 esp_add_footer_and_icv (vlib_buffer_t * b, u8 block_size, u8 icv_sz,
95  u16 * next, vlib_node_runtime_t * node,
96  u16 buffer_data_size)
97 {
98  static const u8 pad_data[ESP_MAX_BLOCK_SIZE] = {
99  0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
100  0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x00, 0x00,
101  };
102 
103  u16 min_length = b->current_length + sizeof (esp_footer_t);
104  u16 new_length = round_pow2 (min_length, block_size);
105  u8 pad_bytes = new_length - min_length;
107  new_length - sizeof (esp_footer_t));
108 
109  if (b->current_data + new_length + icv_sz > buffer_data_size)
110  {
111  b->error = node->errors[ESP_ENCRYPT_ERROR_NO_TRAILER_SPACE];
112  next[0] = ESP_ENCRYPT_NEXT_DROP;
113  return 0;
114  }
115 
116  if (pad_bytes)
117  clib_memcpy_fast ((u8 *) f - pad_bytes, pad_data, pad_bytes);
118 
119  f->pad_length = pad_bytes;
120  b->current_length = new_length + icv_sz;
121  return &f->next_header;
122 }
123 
125 esp_update_ip4_hdr (ip4_header_t * ip4, u16 len, int is_transport, int is_udp)
126 {
127  ip_csum_t sum;
128  u16 old_len;
129 
130  len = clib_net_to_host_u16 (len);
131  old_len = ip4->length;
132 
133  if (is_transport)
134  {
135  u8 prot = is_udp ? IP_PROTOCOL_UDP : IP_PROTOCOL_IPSEC_ESP;
136 
137  sum = ip_csum_update (ip4->checksum, ip4->protocol,
138  prot, ip4_header_t, protocol);
139  ip4->protocol = prot;
140 
141  sum = ip_csum_update (sum, old_len, len, ip4_header_t, length);
142  }
143  else
144  sum = ip_csum_update (ip4->checksum, old_len, len, ip4_header_t, length);
145 
146  ip4->length = len;
147  ip4->checksum = ip_csum_fold (sum);
148 }
149 
152 {
153  clib_memcpy_fast (udp, &sa->udp_hdr, sizeof (udp_header_t));
154  udp->length = clib_net_to_host_u16 (len);
155 }
156 
159 {
160 #ifdef CLIB_HAVE_VEC128
161  static const u8x16 ext_hdr_types = {
162  IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS,
163  IP_PROTOCOL_IPV6_ROUTE,
164  IP_PROTOCOL_IPV6_FRAGMENTATION,
165  };
166 
167  return !u8x16_is_all_zero (ext_hdr_types == u8x16_splat (nexthdr));
168 #else
169  return ((nexthdr ^ IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS) |
170  (nexthdr ^ IP_PROTOCOL_IPV6_ROUTE) |
171  (nexthdr ^ IP_PROTOCOL_IPV6_FRAGMENTATION) != 0);
172 #endif
173 }
174 
177 {
178  /* this code assumes that HbH, route and frag headers will be before
179  others, if that is not the case, they will end up encrypted */
180 
181  u8 len = sizeof (ip6_header_t);
182  ip6_ext_header_t *p;
183 
184  /* if next packet doesn't have ext header */
185  if (ext_hdr_is_pre_esp (ip6->protocol) == 0)
186  return len;
187 
188  p = (void *) (ip6 + 1);
189  len += ip6_ext_header_len (p);
190 
191  while (ext_hdr_is_pre_esp (p->next_hdr))
192  {
193  len += ip6_ext_header_len (p);
194  p = ip6_ext_next_header (p);
195  }
196 
197  return len;
198 }
199 
202  vnet_crypto_op_t * ops, vlib_buffer_t * b[], u16 * nexts)
203 {
204  u32 n_fail, n_ops = vec_len (ops);
205  vnet_crypto_op_t *op = ops;
206 
207  if (n_ops == 0)
208  return;
209 
210  n_fail = n_ops - vnet_crypto_process_ops (vm, op, n_ops);
211 
212  while (n_fail)
213  {
214  ASSERT (op - ops < n_ops);
215 
216  if (op->status != VNET_CRYPTO_OP_STATUS_COMPLETED)
217  {
218  u32 bi = op->user_data;
219  b[bi]->error = node->errors[ESP_ENCRYPT_ERROR_CRYPTO_ENGINE_ERROR];
220  nexts[bi] = ESP_ENCRYPT_NEXT_DROP;
221  n_fail--;
222  }
223  op++;
224  }
225 }
226 
227 typedef struct
228 {
229  u32 salt;
230  u64 iv;
231 } __clib_packed esp_gcm_nonce_t;
232 
233 STATIC_ASSERT_SIZEOF (esp_gcm_nonce_t, 12);
234 
237  vlib_frame_t * frame, int is_ip6, int is_tun)
238 {
239  ipsec_main_t *im = &ipsec_main;
241  u32 *from = vlib_frame_vector_args (frame);
242  u32 n_left = frame->n_vectors;
243  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
244  u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
245  esp_gcm_nonce_t nonces[VLIB_FRAME_SIZE], *nonce = nonces;
246  u32 thread_index = vm->thread_index;
247  u16 buffer_data_size = vlib_buffer_get_default_data_size (vm);
248  u32 current_sa_index = ~0, current_sa_packets = 0;
249  u32 current_sa_bytes = 0, spi = 0;
250  u8 block_sz = 0, iv_sz = 0, icv_sz = 0;
251  ipsec_sa_t *sa0 = 0;
252 
253  vlib_get_buffers (vm, from, b, n_left);
256 
257  while (n_left > 0)
258  {
259  u32 sa_index0;
260  dpo_id_t *dpo;
261  esp_header_t *esp;
262  u8 *payload, *next_hdr_ptr;
263  u16 payload_len;
264  u32 hdr_len;
265 
266  if (n_left > 2)
267  {
268  u8 *p;
269  vlib_prefetch_buffer_header (b[2], LOAD);
270  p = vlib_buffer_get_current (b[1]);
274  }
275 
276  if (is_tun)
277  {
278  /* we are on a ipsec tunnel's feature arc */
279  u32 next0;
280  sa_index0 = *(u32 *) vnet_feature_next_with_data (&next0, b[0],
281  sizeof
282  (sa_index0));
283  next[0] = next0;
284  }
285  else
286  sa_index0 = vnet_buffer (b[0])->ipsec.sad_index;
287 
288  if (sa_index0 != current_sa_index)
289  {
290  if (current_sa_packets)
292  current_sa_index,
293  current_sa_packets,
294  current_sa_bytes);
295  current_sa_packets = current_sa_bytes = 0;
296 
297  sa0 = pool_elt_at_index (im->sad, sa_index0);
298  current_sa_index = sa_index0;
299  spi = clib_net_to_host_u32 (sa0->spi);
300  block_sz = sa0->crypto_block_size;
301  icv_sz = sa0->integ_icv_size;
302  iv_sz = sa0->crypto_iv_size;
303  }
304 
305  if (vlib_buffer_chain_linearize (vm, b[0]) != 1)
306  {
307  b[0]->error = node->errors[ESP_ENCRYPT_ERROR_CHAINED_BUFFER];
308  next[0] = ESP_ENCRYPT_NEXT_DROP;
309  goto trace;
310  }
311 
312  if (PREDICT_FALSE (esp_seq_advance (sa0)))
313  {
314  b[0]->error = node->errors[ESP_ENCRYPT_ERROR_SEQ_CYCLED];
315  next[0] = ESP_ENCRYPT_NEXT_DROP;
316  goto trace;
317  }
318 
319  /* space for IV */
320  hdr_len = iv_sz;
321 
322  if (ipsec_sa_is_set_IS_TUNNEL (sa0))
323  {
324  payload = vlib_buffer_get_current (b[0]);
325  next_hdr_ptr = esp_add_footer_and_icv (b[0], block_sz, icv_sz,
326  next, node,
327  buffer_data_size);
328  if (!next_hdr_ptr)
329  goto trace;
330  payload_len = b[0]->current_length;
331 
332  /* ESP header */
333  hdr_len += sizeof (*esp);
334  esp = (esp_header_t *) (payload - hdr_len);
335 
336  /* optional UDP header */
337  if (ipsec_sa_is_set_UDP_ENCAP (sa0))
338  {
339  hdr_len += sizeof (udp_header_t);
340  esp_fill_udp_hdr (sa0, (udp_header_t *) (payload - hdr_len),
341  payload_len + hdr_len);
342  }
343 
344  /* IP header */
345  if (ipsec_sa_is_set_IS_TUNNEL_V6 (sa0))
346  {
347  ip6_header_t *ip6;
348  u16 len = sizeof (ip6_header_t);
349  hdr_len += len;
350  ip6 = (ip6_header_t *) (payload - hdr_len);
351  clib_memcpy_fast (ip6, &sa0->ip6_hdr, len);
352  *next_hdr_ptr = (is_ip6 ?
353  IP_PROTOCOL_IPV6 : IP_PROTOCOL_IP_IN_IP);
354  len = payload_len + hdr_len - len;
355  ip6->payload_length = clib_net_to_host_u16 (len);
356  }
357  else
358  {
359  ip4_header_t *ip4;
360  u16 len = sizeof (ip4_header_t);
361  hdr_len += len;
362  ip4 = (ip4_header_t *) (payload - hdr_len);
363  clib_memcpy_fast (ip4, &sa0->ip4_hdr, len);
364  *next_hdr_ptr = (is_ip6 ?
365  IP_PROTOCOL_IPV6 : IP_PROTOCOL_IP_IN_IP);
366  len = payload_len + hdr_len;
367  esp_update_ip4_hdr (ip4, len, /* is_transport */ 0, 0);
368  }
369 
370  dpo = &sa0->dpo;
371  if (!is_tun)
372  {
373  next[0] = dpo->dpoi_next_node;
374  vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = dpo->dpoi_index;
375  }
376  }
377  else /* transport mode */
378  {
379  u8 *l2_hdr, l2_len, *ip_hdr, ip_len;
380  udp_header_t *udp = 0;
381  u8 *old_ip_hdr = vlib_buffer_get_current (b[0]);
382 
383  ip_len = is_ip6 ?
384  esp_get_ip6_hdr_len ((ip6_header_t *) old_ip_hdr) :
385  ip4_header_bytes ((ip4_header_t *) old_ip_hdr);
386 
387  vlib_buffer_advance (b[0], ip_len);
388  payload = vlib_buffer_get_current (b[0]);
389  next_hdr_ptr = esp_add_footer_and_icv (b[0], block_sz, icv_sz,
390  next, node,
391  buffer_data_size);
392  if (!next_hdr_ptr)
393  goto trace;
394  payload_len = b[0]->current_length;
395 
396  /* ESP header */
397  hdr_len += sizeof (*esp);
398  esp = (esp_header_t *) (payload - hdr_len);
399 
400  /* optional UDP header */
401  if (ipsec_sa_is_set_UDP_ENCAP (sa0))
402  {
403  hdr_len += sizeof (udp_header_t);
404  udp = (udp_header_t *) (payload - hdr_len);
405  }
406 
407  /* IP header */
408  hdr_len += ip_len;
409  ip_hdr = payload - hdr_len;
410 
411  /* L2 header */
412  if (!is_tun)
413  {
414  l2_len = vnet_buffer (b[0])->ip.save_rewrite_length;
415  hdr_len += l2_len;
416  l2_hdr = payload - hdr_len;
417 
418  /* copy l2 and ip header */
419  clib_memcpy_le32 (l2_hdr, old_ip_hdr - l2_len, l2_len);
420  }
421  else
422  l2_len = 0;
423 
424  clib_memcpy_le64 (ip_hdr, old_ip_hdr, ip_len);
425 
426  if (is_ip6)
427  {
428  ip6_header_t *ip6 = (ip6_header_t *) (ip_hdr);
429  *next_hdr_ptr = ip6->protocol;
430  ip6->protocol = IP_PROTOCOL_IPSEC_ESP;
431  ip6->payload_length =
432  clib_host_to_net_u16 (payload_len + hdr_len - l2_len -
433  ip_len);
434  }
435  else
436  {
437  u16 len;
438  ip4_header_t *ip4 = (ip4_header_t *) (ip_hdr);
439  *next_hdr_ptr = ip4->protocol;
440  len = payload_len + hdr_len - l2_len;
441  if (udp)
442  {
443  esp_update_ip4_hdr (ip4, len, /* is_transport */ 1, 1);
444  esp_fill_udp_hdr (sa0, udp, len - ip_len);
445  }
446  else
447  esp_update_ip4_hdr (ip4, len, /* is_transport */ 1, 0);
448  }
449 
450  if (!is_tun)
451  next[0] = ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT;
452  }
453 
454  esp->spi = spi;
455  esp->seq = clib_net_to_host_u32 (sa0->seq);
456 
457  if (sa0->crypto_enc_op_id)
458  {
459  vnet_crypto_op_t *op;
462  op->src = op->dst = payload;
463  op->key_index = sa0->crypto_key_index;
464  op->len = payload_len - icv_sz;
465  op->user_data = b - bufs;
466 
467  if (ipsec_sa_is_set_IS_AEAD (sa0))
468  {
469  /*
470  * construct the AAD in a scratch space in front
471  * of the IP header.
472  */
473  op->aad = payload - hdr_len - sizeof (esp_aead_t);
474 
475  esp_aad_fill (op, esp, sa0);
476 
477  op->tag = payload + op->len;
478  op->tag_len = 16;
479 
480  u64 *iv = (u64 *) (payload - iv_sz);
481  nonce->salt = sa0->salt;
482  nonce->iv = *iv = clib_host_to_net_u64 (sa0->gcm_iv_counter++);
483  op->iv = (u8 *) nonce;
484  nonce++;
485  }
486  else
487  {
488  op->iv = payload - iv_sz;
490  }
491  }
492 
493  if (sa0->integ_op_id)
494  {
495  vnet_crypto_op_t *op;
497  vnet_crypto_op_init (op, sa0->integ_op_id);
498  op->src = payload - iv_sz - sizeof (esp_header_t);
499  op->digest = payload + payload_len - icv_sz;
500  op->key_index = sa0->integ_key_index;
501  op->digest_len = icv_sz;
502  op->len = payload_len - icv_sz + iv_sz + sizeof (esp_header_t);
503  op->user_data = b - bufs;
504  if (ipsec_sa_is_set_USE_ESN (sa0))
505  {
506  u32 seq_hi = clib_net_to_host_u32 (sa0->seq_hi);
507  clib_memcpy_fast (op->digest, &seq_hi, sizeof (seq_hi));
508  op->len += sizeof (seq_hi);
509  }
510  }
511 
512  vlib_buffer_advance (b[0], 0LL - hdr_len);
513 
514  current_sa_packets += 1;
515  current_sa_bytes += payload_len;
516 
517  trace:
518  if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
519  {
520  esp_encrypt_trace_t *tr = vlib_add_trace (vm, node, b[0],
521  sizeof (*tr));
522  tr->sa_index = sa_index0;
523  tr->spi = sa0->spi;
524  tr->seq = sa0->seq;
525  tr->sa_seq_hi = sa0->seq_hi;
526  tr->udp_encap = ipsec_sa_is_set_UDP_ENCAP (sa0);
527  tr->crypto_alg = sa0->crypto_alg;
528  tr->integ_alg = sa0->integ_alg;
529  }
530  /* next */
531  n_left -= 1;
532  next += 1;
533  b += 1;
534  }
535 
537  current_sa_index, current_sa_packets,
538  current_sa_bytes);
539  esp_process_ops (vm, node, ptd->crypto_ops, bufs, nexts);
540  esp_process_ops (vm, node, ptd->integ_ops, bufs, nexts);
541 
543  ESP_ENCRYPT_ERROR_RX_PKTS, frame->n_vectors);
544 
545  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
546  return frame->n_vectors;
547 }
548 
550  vlib_node_runtime_t * node,
551  vlib_frame_t * from_frame)
552 {
553  return esp_encrypt_inline (vm, node, from_frame, 0 /* is_ip6 */ , 0);
554 }
555 
556 /* *INDENT-OFF* */
558  .name = "esp4-encrypt",
559  .vector_size = sizeof (u32),
560  .format_trace = format_esp_encrypt_trace,
562 
564  .error_strings = esp_encrypt_error_strings,
565 
566  .n_next_nodes = ESP_ENCRYPT_N_NEXT,
567  .next_nodes = {
568 #define _(s,n) [ESP_ENCRYPT_NEXT_##s] = n,
570 #undef _
571  },
572 };
573 /* *INDENT-ON* */
574 
576  vlib_node_runtime_t * node,
577  vlib_frame_t * from_frame)
578 {
579  return esp_encrypt_inline (vm, node, from_frame, 1 /* is_ip6 */ , 0);
580 }
581 
582 /* *INDENT-OFF* */
584  .name = "esp6-encrypt",
585  .vector_size = sizeof (u32),
586  .format_trace = format_esp_encrypt_trace,
588 
590  .error_strings = esp_encrypt_error_strings,
591 
592  .n_next_nodes = ESP_ENCRYPT_N_NEXT,
593  .next_nodes = {
594 #define _(s,n) [ESP_ENCRYPT_NEXT_##s] = n,
596 #undef _
597  },
598 };
599 /* *INDENT-ON* */
600 
602  vlib_node_runtime_t * node,
603  vlib_frame_t * from_frame)
604 {
605  return esp_encrypt_inline (vm, node, from_frame, 0 /* is_ip6 */ , 1);
606 }
607 
608 /* *INDENT-OFF* */
610  .name = "esp4-encrypt-tun",
611  .vector_size = sizeof (u32),
612  .format_trace = format_esp_encrypt_trace,
614 
616  .error_strings = esp_encrypt_error_strings,
617 
618  .n_next_nodes = 1,
619  .next_nodes = {
620  [ESP_ENCRYPT_NEXT_DROP] = "ip4-drop",
621  },
622 };
623 
624 VNET_FEATURE_INIT (esp4_encrypt_tun_feat_node, static) =
625 {
626  .arc_name = "ip4-output",
627  .node_name = "esp4-encrypt-tun",
628  .runs_before = VNET_FEATURES ("adj-midchain-tx"),
629 };
630 
631 VNET_FEATURE_INIT (esp6o4_encrypt_tun_feat_node, static) =
632 {
633  .arc_name = "ip6-output",
634  .node_name = "esp4-encrypt-tun",
635  .runs_before = VNET_FEATURES ("adj-midchain-tx"),
636 };
637 
638 VNET_FEATURE_INIT (esp4_ethernet_encrypt_tun_feat_node, static) =
639 {
640  .arc_name = "ethernet-output",
641  .node_name = "esp4-encrypt-tun",
642  .runs_before = VNET_FEATURES ("adj-midchain-tx", "adj-midchain-tx-no-count"),
643 };
644 /* *INDENT-ON* */
645 
647  vlib_node_runtime_t * node,
648  vlib_frame_t * from_frame)
649 {
650  return esp_encrypt_inline (vm, node, from_frame, 1 /* is_ip6 */ , 1);
651 }
652 
653 /* *INDENT-OFF* */
655  .name = "esp6-encrypt-tun",
656  .vector_size = sizeof (u32),
657  .format_trace = format_esp_encrypt_trace,
659 
661  .error_strings = esp_encrypt_error_strings,
662 
663  .n_next_nodes = 1,
664  .next_nodes = {
665  [ESP_ENCRYPT_NEXT_DROP] = "ip6-drop",
666  },
667 };
668 
669 VNET_FEATURE_INIT (esp6_encrypt_tun_feat_node, static) =
670 {
671  .arc_name = "ip6-output",
672  .node_name = "esp6-encrypt-tun",
673  .runs_before = VNET_FEATURES ("adj-midchain-tx"),
674 };
675 
676 VNET_FEATURE_INIT (esp4o6_encrypt_tun_feat_node, static) =
677 {
678  .arc_name = "ip4-output",
679  .node_name = "esp6-encrypt-tun",
680  .runs_before = VNET_FEATURES ("adj-midchain-tx"),
681 };
682 
683 /* *INDENT-ON* */
684 
685 typedef struct
686 {
689 
690 static u8 *
691 format_esp_no_crypto_trace (u8 * s, va_list * args)
692 {
693  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
694  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
695  esp_no_crypto_trace_t *t = va_arg (*args, esp_no_crypto_trace_t *);
696 
697  s = format (s, "esp-no-crypto: sa-index %u", t->sa_index);
698 
699  return s;
700 }
701 
702 enum
703 {
706 };
707 
708 enum
709 {
711 };
712 
713 static char *esp_no_crypto_error_strings[] = {
714  "Outbound ESP packets received",
715 };
716 
719  vlib_frame_t * frame)
720 {
721  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
722  u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
723  u32 *from = vlib_frame_vector_args (frame);
724  u32 n_left = frame->n_vectors;
725 
726  vlib_get_buffers (vm, from, b, n_left);
727 
728  while (n_left > 0)
729  {
730  u32 next0;
731  u32 sa_index0;
732 
733  /* packets are always going to be dropped, but get the sa_index */
734  sa_index0 = *(u32 *) vnet_feature_next_with_data (&next0, b[0],
735  sizeof (sa_index0));
736 
737  next[0] = ESP_NO_CRYPTO_NEXT_DROP;
738 
739  if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
740  {
741  esp_no_crypto_trace_t *tr = vlib_add_trace (vm, node, b[0],
742  sizeof (*tr));
743  tr->sa_index = sa_index0;
744  }
745 
746  n_left -= 1;
747  next += 1;
748  b += 1;
749  }
750 
753 
754  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
755 
756  return frame->n_vectors;
757 }
758 
760  vlib_node_runtime_t * node,
761  vlib_frame_t * from_frame)
762 {
763  return esp_no_crypto_inline (vm, node, from_frame);
764 }
765 
766 /* *INDENT-OFF* */
768 {
769  .name = "esp4-no-crypto",
770  .vector_size = sizeof (u32),
771  .format_trace = format_esp_no_crypto_trace,
773  .error_strings = esp_no_crypto_error_strings,
774  .n_next_nodes = ESP_NO_CRYPTO_N_NEXT,
775  .next_nodes = {
776  [ESP_NO_CRYPTO_NEXT_DROP] = "ip4-drop",
777  },
778 };
779 
780 VNET_FEATURE_INIT (esp4_no_crypto_tun_feat_node, static) =
781 {
782  .arc_name = "ip4-output",
783  .node_name = "esp4-no-crypto",
784  .runs_before = VNET_FEATURES ("adj-midchain-tx"),
785 };
786 
788  vlib_node_runtime_t * node,
789  vlib_frame_t * from_frame)
790 {
791  return esp_no_crypto_inline (vm, node, from_frame);
792 }
793 
794 /* *INDENT-OFF* */
796 {
797  .name = "esp6-no-crypto",
798  .vector_size = sizeof (u32),
799  .format_trace = format_esp_no_crypto_trace,
801  .error_strings = esp_no_crypto_error_strings,
802  .n_next_nodes = ESP_NO_CRYPTO_N_NEXT,
803  .next_nodes = {
804  [ESP_NO_CRYPTO_NEXT_DROP] = "ip6-drop",
805  },
806 };
807 
808 VNET_FEATURE_INIT (esp6_no_crypto_tun_feat_node, static) =
809 {
810  .arc_name = "ip6-output",
811  .node_name = "esp6-no-crypto",
812  .runs_before = VNET_FEATURES ("adj-midchain-tx"),
813 };
814 /* *INDENT-ON* */
815 
816 /*
817  * fd.io coding-style-patch-verification: ON
818  *
819  * Local Variables:
820  * eval: (c-set-style "gnu")
821  * End:
822  */
u32 vnet_crypto_process_ops(vlib_main_t *vm, vnet_crypto_op_t ops[], u32 n_ops)
Definition: crypto.c:46
u8 * format_ipsec_integ_alg(u8 *s, va_list *args)
Definition: ipsec_format.c:110
static_always_inline u8 esp_get_ip6_hdr_len(ip6_header_t *ip6)
Definition: esp_encrypt.c:176
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
Definition: vlib_api_cli.c:889
u32 flags
Definition: vhost_user.h:141
#define CLIB_UNUSED(x)
Definition: clib.h:82
ipsec_per_thread_data_t * ptd
Definition: ipsec.h:169
vnet_crypto_op_t * integ_ops
Definition: ipsec.h:89
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 thread_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
Definition: counter.h:220
static char * esp_no_crypto_error_strings[]
Definition: esp_encrypt.c:713
static_always_inline void esp_process_ops(vlib_main_t *vm, vlib_node_runtime_t *node, vnet_crypto_op_t *ops, vlib_buffer_t *b[], u16 *nexts)
Definition: esp_encrypt.c:201
ipsec_integ_alg_t
Definition: ipsec_sa.h:58
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
unsigned long u64
Definition: types.h:89
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
#define vec_add2_aligned(V, P, N, A)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:572
ipsec_integ_alg_t integ_alg
Definition: ipsec_sa.h:150
u32 thread_index
Definition: main.h:218
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
struct esp_aead_t_ esp_aead_t
AES GCM Additional Authentication data.
vnet_crypto_op_t * crypto_ops
Definition: ipsec.h:88
static void * ip6_ext_next_header(ip6_ext_header_t *ext_hdr)
Definition: ip6_packet.h:552
static u8 * format_esp_encrypt_trace(u8 *s, va_list *args)
Definition: esp_encrypt.c:76
ipsec_integ_alg_t integ_alg
Definition: esp_encrypt.c:71
uword ip_csum_t
Definition: ip_packet.h:219
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
ipsec_crypto_alg_t crypto_alg
Definition: esp_encrypt.c:70
#define VLIB_NODE_FN(node)
Definition: node.h:202
static_always_inline u8 * esp_add_footer_and_icv(vlib_buffer_t *b, u8 block_size, u8 icv_sz, u16 *next, vlib_node_runtime_t *node, u16 buffer_data_size)
Definition: esp_encrypt.c:94
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:470
vnet_crypto_op_id_t integ_op_id
Definition: ipsec_sa.h:129
unsigned char u8
Definition: types.h:56
vlib_node_registration_t esp4_encrypt_tun_node
(constructor) VLIB_REGISTER_NODE (esp4_encrypt_tun_node)
Definition: esp_encrypt.c:609
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
u32 seq_hi
Definition: ipsec_sa.h:119
static int esp_seq_advance(ipsec_sa_t *sa)
Definition: esp.h:84
vnet_crypto_key_index_t crypto_key_index
Definition: ipsec_sa.h:125
static uword esp_no_crypto_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: esp_encrypt.c:718
#define static_always_inline
Definition: clib.h:99
#define foreach_esp_encrypt_next
Definition: esp_encrypt.c:28
ipsec_main_t ipsec_main
Definition: ipsec.c:28
#define always_inline
Definition: clib.h:98
static_always_inline void esp_fill_udp_hdr(ipsec_sa_t *sa, udp_header_t *udp, u16 len)
Definition: esp_encrypt.c:151
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:203
static_always_inline void vnet_crypto_op_init(vnet_crypto_op_t *op, vnet_crypto_op_id_t type)
Definition: crypto.h:221
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
static_always_inline u8 ext_hdr_is_pre_esp(u8 nexthdr)
Definition: esp_encrypt.c:158
u8 * format_ipsec_crypto_alg(u8 *s, va_list *args)
Definition: ipsec_format.c:78
unsigned int u32
Definition: types.h:88
static const u8 pad_data[]
Definition: ipsec.h:175
#define VLIB_FRAME_SIZE
Definition: node.h:378
STATIC_ASSERT_SIZEOF(esp_gcm_nonce_t, 12)
static u8 * format_esp_no_crypto_trace(u8 *s, va_list *args)
Definition: esp_encrypt.c:691
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
esp_encrypt_error_t
Definition: esp_encrypt.c:49
vlib_node_registration_t esp6_encrypt_node
(constructor) VLIB_REGISTER_NODE (esp6_encrypt_node)
Definition: esp_encrypt.c:583
static u32 vlib_buffer_chain_linearize(vlib_main_t *vm, vlib_buffer_t *b)
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:170
static_always_inline void * vnet_feature_next_with_data(u32 *next0, vlib_buffer_t *b0, u32 n_data_bytes)
Definition: feature.h:289
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:514
vlib_node_registration_t esp6_encrypt_tun_node
(constructor) VLIB_REGISTER_NODE (esp6_encrypt_tun_node)
Definition: esp_encrypt.c:654
static u8 iv[]
Definition: aes_cbc.c:24
static void esp_aad_fill(vnet_crypto_op_t *op, const esp_header_t *esp, const ipsec_sa_t *sa)
Definition: esp.h:138
uword user_data
Definition: crypto.h:143
vl_api_ip_proto_t protocol
Definition: punt.api:39
u32 salt
Definition: ipsec_sa.h:163
unsigned short u16
Definition: types.h:57
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
vlib_node_registration_t esp4_no_crypto_tun_node
(constructor) VLIB_REGISTER_NODE (esp4_no_crypto_tun_node)
Definition: esp_encrypt.c:767
#define PREDICT_FALSE(x)
Definition: clib.h:111
u32 node_index
Node index.
Definition: node.h:496
static char * esp_encrypt_error_strings[]
Definition: esp_encrypt.c:57
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1150
u8 len
Definition: ip_types.api:90
#define ip6_ext_header_len(p)
Definition: ip6_packet.h:548
static_always_inline u32 vlib_buffer_get_default_data_size(vlib_main_t *vm)
Definition: buffer_funcs.h:96
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:397
#define VNET_CRYPTO_OP_FLAG_INIT_IV
Definition: crypto.h:131
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
vlib_main_t * vm
Definition: buffer.c:323
static_always_inline void vlib_buffer_enqueue_to_next(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u16 *nexts, uword count)
Definition: buffer_node.h:332
vlib_node_registration_t esp6_no_crypto_tun_node
(constructor) VLIB_REGISTER_NODE (esp6_no_crypto_tun_node)
Definition: esp_encrypt.c:795
vlib_node_registration_t esp4_encrypt_node
(constructor) VLIB_REGISTER_NODE (esp4_encrypt_node)
Definition: esp_encrypt.c:557
udp_header_t udp_hdr
Definition: ipsec_sa.h:139
#define ARRAY_LEN(x)
Definition: clib.h:62
esp_encrypt_next_t
Definition: esp_encrypt.c:35
static uword round_pow2(uword x, uword pow2)
Definition: clib.h:241
#define ESP_MAX_BLOCK_SIZE
Definition: esp.h:76
vlib_combined_counter_main_t ipsec_sa_counters
SA packet & bytes counters.
Definition: ipsec_sa.c:27
#define ASSERT(truth)
u32 spi
Definition: ipsec.api:274
ip6_header_t ip6_hdr
Definition: ipsec_sa.h:137
ipsec_sa_t * sad
Definition: ipsec.h:97
static_always_inline void esp_update_ip4_hdr(ip4_header_t *ip4, u16 len, int is_transport, int is_udp)
Definition: esp_encrypt.c:125
u32 seq
Definition: esp.h:29
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:248
u32 spi
Definition: esp.h:26
vnet_crypto_key_index_t integ_key_index
Definition: ipsec_sa.h:126
#define VNET_FEATURES(...)
Definition: feature.h:442
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
static_always_inline void clib_memcpy_le64(u8 *dst, u8 *src, u8 len)
Definition: string.h:283
Definition: defs.h:47
u16 payload_length
Definition: ip6_packet.h:374
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:186
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
ipsec_crypto_alg_t
Definition: ipsec_sa.h:36
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:269
static uword esp_encrypt_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_ip6, int is_tun)
Definition: esp_encrypt.c:236
u64 gcm_iv_counter
Definition: ipsec_sa.h:164
vnet_crypto_op_id_t crypto_enc_op_id
Definition: ipsec_sa.h:127
vnet_crypto_op_status_t status
Definition: crypto.h:129
#define vnet_buffer(b)
Definition: buffer.h:365
dpo_id_t dpo
Definition: ipsec_sa.h:123
ipsec_crypto_alg_t crypto_alg
Definition: ipsec_sa.h:146
ip4_header_t ip4_hdr
Definition: ipsec_sa.h:136
u8 crypto_block_size
Definition: ipsec_sa.h:115
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:182
static int ip4_header_bytes(const ip4_header_t *i)
Definition: ip4_packet.h:235
static_always_inline void vlib_get_buffers(vlib_main_t *vm, u32 *bi, vlib_buffer_t **b, int count)
Translate array of buffer indices into buffer pointers.
Definition: buffer_funcs.h:244
VNET_FEATURE_INIT(esp4_encrypt_tun_feat_node, static)
u8 crypto_iv_size
Definition: ipsec_sa.h:114
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
u32 salt
Definition: ipsec.api:289
#define foreach_esp_encrypt_error
Definition: esp_encrypt.c:42
u8 integ_icv_size
Definition: ipsec_sa.h:116
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:275
static_always_inline void clib_memcpy_le32(u8 *dst, u8 *src, u8 len)
Definition: string.h:289