FD.io VPP  v20.01-48-g3e0dafb74
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 _(HANDOFF, "handoff") \
31 _(INTERFACE_OUTPUT, "interface-output")
32 
33 #define _(v, s) ESP_ENCRYPT_NEXT_##v,
34 typedef enum
35 {
37 #undef _
40 
41 #define foreach_esp_encrypt_error \
42  _(RX_PKTS, "ESP pkts received") \
43  _(SEQ_CYCLED, "sequence number cycled (packet dropped)") \
44  _(CRYPTO_ENGINE_ERROR, "crypto engine error (packet dropped)") \
45  _(CHAINED_BUFFER, "chained buffers (packet dropped)") \
46  _(NO_TRAILER_SPACE, "no trailer space (packet dropped)")
47 
48 typedef enum
49 {
50 #define _(sym,str) ESP_ENCRYPT_ERROR_##sym,
52 #undef _
55 
56 static char *esp_encrypt_error_strings[] = {
57 #define _(sym,string) string,
59 #undef _
60 };
61 
62 typedef struct
63 {
69  ipsec_crypto_alg_t crypto_alg;
70  ipsec_integ_alg_t integ_alg;
72 
73 /* packet trace format function */
74 static u8 *
75 format_esp_encrypt_trace (u8 * s, va_list * args)
76 {
77  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
78  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
79  esp_encrypt_trace_t *t = va_arg (*args, esp_encrypt_trace_t *);
80 
81  s =
82  format (s,
83  "esp: sa-index %d spi %u (0x%08x) seq %u sa-seq-hi %u crypto %U integrity %U%s",
84  t->sa_index, t->spi, t->spi, t->seq, t->sa_seq_hi,
87  t->udp_encap ? " udp-encap-enabled" : "");
88  return s;
89 }
90 
91 /* pad packet in input buffer */
93 esp_add_footer_and_icv (vlib_buffer_t * b, u8 block_size, u8 icv_sz,
94  u16 * next, vlib_node_runtime_t * node,
95  u16 buffer_data_size)
96 {
97  static const u8 pad_data[ESP_MAX_BLOCK_SIZE] = {
98  0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
99  0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x00, 0x00,
100  };
101 
102  u16 min_length = b->current_length + sizeof (esp_footer_t);
103  u16 new_length = round_pow2 (min_length, block_size);
104  u8 pad_bytes = new_length - min_length;
106  new_length - sizeof (esp_footer_t));
107 
108  if (b->current_data + new_length + icv_sz > buffer_data_size)
109  {
110  b->error = node->errors[ESP_ENCRYPT_ERROR_NO_TRAILER_SPACE];
111  next[0] = ESP_ENCRYPT_NEXT_DROP;
112  return 0;
113  }
114 
115  if (pad_bytes)
116  {
117  ASSERT (pad_bytes <= ESP_MAX_BLOCK_SIZE);
118  pad_bytes = clib_min (ESP_MAX_BLOCK_SIZE, pad_bytes);
119  clib_memcpy_fast ((u8 *) f - pad_bytes, pad_data, pad_bytes);
120  }
121 
122  f->pad_length = pad_bytes;
123  b->current_length = new_length + icv_sz;
124  return &f->next_header;
125 }
126 
128 esp_update_ip4_hdr (ip4_header_t * ip4, u16 len, int is_transport, int is_udp)
129 {
130  ip_csum_t sum;
131  u16 old_len;
132 
133  len = clib_net_to_host_u16 (len);
134  old_len = ip4->length;
135 
136  if (is_transport)
137  {
138  u8 prot = is_udp ? IP_PROTOCOL_UDP : IP_PROTOCOL_IPSEC_ESP;
139 
140  sum = ip_csum_update (ip4->checksum, ip4->protocol,
141  prot, ip4_header_t, protocol);
142  ip4->protocol = prot;
143 
144  sum = ip_csum_update (sum, old_len, len, ip4_header_t, length);
145  }
146  else
147  sum = ip_csum_update (ip4->checksum, old_len, len, ip4_header_t, length);
148 
149  ip4->length = len;
150  ip4->checksum = ip_csum_fold (sum);
151 }
152 
155 {
156  clib_memcpy_fast (udp, &sa->udp_hdr, sizeof (udp_header_t));
157  udp->length = clib_net_to_host_u16 (len);
158 }
159 
162 {
163 #ifdef CLIB_HAVE_VEC128
164  static const u8x16 ext_hdr_types = {
165  IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS,
166  IP_PROTOCOL_IPV6_ROUTE,
167  IP_PROTOCOL_IPV6_FRAGMENTATION,
168  };
169 
170  return !u8x16_is_all_zero (ext_hdr_types == u8x16_splat (nexthdr));
171 #else
172  return ((nexthdr ^ IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS) |
173  (nexthdr ^ IP_PROTOCOL_IPV6_ROUTE) |
174  (nexthdr ^ IP_PROTOCOL_IPV6_FRAGMENTATION) != 0);
175 #endif
176 }
177 
179 esp_get_ip6_hdr_len (ip6_header_t * ip6, ip6_ext_header_t ** ext_hdr)
180 {
181  /* this code assumes that HbH, route and frag headers will be before
182  others, if that is not the case, they will end up encrypted */
183  u8 len = sizeof (ip6_header_t);
184  ip6_ext_header_t *p;
185 
186  /* if next packet doesn't have ext header */
187  if (ext_hdr_is_pre_esp (ip6->protocol) == 0)
188  {
189  *ext_hdr = NULL;
190  return len;
191  }
192 
193  p = (void *) (ip6 + 1);
194  len += ip6_ext_header_len (p);
195 
196  while (ext_hdr_is_pre_esp (p->next_hdr))
197  {
198  len += ip6_ext_header_len (p);
199  p = ip6_ext_next_header (p);
200  }
201 
202  *ext_hdr = p;
203  return len;
204 }
205 
208  vnet_crypto_op_t * ops, vlib_buffer_t * b[], u16 * nexts)
209 {
210  u32 n_fail, n_ops = vec_len (ops);
211  vnet_crypto_op_t *op = ops;
212 
213  if (n_ops == 0)
214  return;
215 
216  n_fail = n_ops - vnet_crypto_process_ops (vm, op, n_ops);
217 
218  while (n_fail)
219  {
220  ASSERT (op - ops < n_ops);
221 
222  if (op->status != VNET_CRYPTO_OP_STATUS_COMPLETED)
223  {
224  u32 bi = op->user_data;
225  b[bi]->error = node->errors[ESP_ENCRYPT_ERROR_CRYPTO_ENGINE_ERROR];
226  nexts[bi] = ESP_ENCRYPT_NEXT_DROP;
227  n_fail--;
228  }
229  op++;
230  }
231 }
232 
233 typedef struct
234 {
235  u32 salt;
236  u64 iv;
237 } __clib_packed esp_gcm_nonce_t;
238 
239 STATIC_ASSERT_SIZEOF (esp_gcm_nonce_t, 12);
240 
243  vlib_frame_t * frame, int is_ip6, int is_tun)
244 {
245  ipsec_main_t *im = &ipsec_main;
247  u32 *from = vlib_frame_vector_args (frame);
248  u32 n_left = frame->n_vectors;
249  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
250  u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
251  esp_gcm_nonce_t nonces[VLIB_FRAME_SIZE], *nonce = nonces;
252  u32 thread_index = vm->thread_index;
253  u16 buffer_data_size = vlib_buffer_get_default_data_size (vm);
254  u32 current_sa_index = ~0, current_sa_packets = 0;
255  u32 current_sa_bytes = 0, spi = 0;
256  u8 block_sz = 0, iv_sz = 0, icv_sz = 0;
257  ipsec_sa_t *sa0 = 0;
258 
259  vlib_get_buffers (vm, from, b, n_left);
262 
263  while (n_left > 0)
264  {
265  u32 sa_index0;
266  dpo_id_t *dpo;
267  esp_header_t *esp;
268  u8 *payload, *next_hdr_ptr;
269  u16 payload_len;
270  u32 hdr_len, config_index;
271 
272  if (n_left > 2)
273  {
274  u8 *p;
275  vlib_prefetch_buffer_header (b[2], LOAD);
276  p = vlib_buffer_get_current (b[1]);
280  }
281 
282  if (is_tun)
283  {
284  /* we are on a ipsec tunnel's feature arc */
285  u32 next0;
286  config_index = b[0]->current_config_index;
287  sa_index0 = *(u32 *) vnet_feature_next_with_data (&next0, b[0],
288  sizeof
289  (sa_index0));
290  vnet_buffer (b[0])->ipsec.sad_index = sa_index0;
291  next[0] = next0;
292  }
293  else
294  sa_index0 = vnet_buffer (b[0])->ipsec.sad_index;
295 
296  if (sa_index0 != current_sa_index)
297  {
298  if (current_sa_packets)
300  current_sa_index,
301  current_sa_packets,
302  current_sa_bytes);
303  current_sa_packets = current_sa_bytes = 0;
304 
305  sa0 = pool_elt_at_index (im->sad, sa_index0);
306  current_sa_index = sa_index0;
307  spi = clib_net_to_host_u32 (sa0->spi);
308  block_sz = sa0->crypto_block_size;
309  icv_sz = sa0->integ_icv_size;
310  iv_sz = sa0->crypto_iv_size;
311  }
312 
313  if (PREDICT_FALSE (~0 == sa0->encrypt_thread_index))
314  {
315  /* this is the first packet to use this SA, claim the SA
316  * for this thread. this could happen simultaneously on
317  * another thread */
319  ipsec_sa_assign_thread (thread_index));
320  }
321 
322  if (PREDICT_TRUE (thread_index != sa0->encrypt_thread_index))
323  {
324  next[0] = ESP_ENCRYPT_NEXT_HANDOFF;
325  if (is_tun)
326  {
327  b[0]->current_config_index = config_index;
328  }
329  goto trace;
330  }
331 
332  if (vlib_buffer_chain_linearize (vm, b[0]) != 1)
333  {
334  b[0]->error = node->errors[ESP_ENCRYPT_ERROR_CHAINED_BUFFER];
335  next[0] = ESP_ENCRYPT_NEXT_DROP;
336  goto trace;
337  }
338 
339  if (PREDICT_FALSE (esp_seq_advance (sa0)))
340  {
341  b[0]->error = node->errors[ESP_ENCRYPT_ERROR_SEQ_CYCLED];
342  next[0] = ESP_ENCRYPT_NEXT_DROP;
343  goto trace;
344  }
345 
346  /* space for IV */
347  hdr_len = iv_sz;
348 
349  if (ipsec_sa_is_set_IS_TUNNEL (sa0))
350  {
351  payload = vlib_buffer_get_current (b[0]);
352  next_hdr_ptr = esp_add_footer_and_icv (b[0], block_sz, icv_sz,
353  next, node,
354  buffer_data_size);
355  if (!next_hdr_ptr)
356  goto trace;
357  payload_len = b[0]->current_length;
358 
359  /* ESP header */
360  hdr_len += sizeof (*esp);
361  esp = (esp_header_t *) (payload - hdr_len);
362 
363  /* optional UDP header */
364  if (ipsec_sa_is_set_UDP_ENCAP (sa0))
365  {
366  hdr_len += sizeof (udp_header_t);
367  esp_fill_udp_hdr (sa0, (udp_header_t *) (payload - hdr_len),
368  payload_len + hdr_len);
369  }
370 
371  /* IP header */
372  if (ipsec_sa_is_set_IS_TUNNEL_V6 (sa0))
373  {
374  ip6_header_t *ip6;
375  u16 len = sizeof (ip6_header_t);
376  hdr_len += len;
377  ip6 = (ip6_header_t *) (payload - hdr_len);
378  clib_memcpy_fast (ip6, &sa0->ip6_hdr, len);
379  *next_hdr_ptr = (is_ip6 ?
380  IP_PROTOCOL_IPV6 : IP_PROTOCOL_IP_IN_IP);
381  len = payload_len + hdr_len - len;
382  ip6->payload_length = clib_net_to_host_u16 (len);
383  }
384  else
385  {
386  ip4_header_t *ip4;
387  u16 len = sizeof (ip4_header_t);
388  hdr_len += len;
389  ip4 = (ip4_header_t *) (payload - hdr_len);
390  clib_memcpy_fast (ip4, &sa0->ip4_hdr, len);
391  *next_hdr_ptr = (is_ip6 ?
392  IP_PROTOCOL_IPV6 : IP_PROTOCOL_IP_IN_IP);
393  len = payload_len + hdr_len;
394  esp_update_ip4_hdr (ip4, len, /* is_transport */ 0, 0);
395  }
396 
397  dpo = &sa0->dpo;
398  if (!is_tun)
399  {
400  next[0] = dpo->dpoi_next_node;
401  vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = dpo->dpoi_index;
402  }
403  }
404  else /* transport mode */
405  {
406  u8 *l2_hdr, l2_len, *ip_hdr, ip_len;
407  ip6_ext_header_t *ext_hdr;
408  udp_header_t *udp = 0;
409  u8 *old_ip_hdr = vlib_buffer_get_current (b[0]);
410 
411  ip_len = is_ip6 ?
412  esp_get_ip6_hdr_len ((ip6_header_t *) old_ip_hdr, &ext_hdr) :
413  ip4_header_bytes ((ip4_header_t *) old_ip_hdr);
414 
415  vlib_buffer_advance (b[0], ip_len);
416  payload = vlib_buffer_get_current (b[0]);
417  next_hdr_ptr = esp_add_footer_and_icv (b[0], block_sz, icv_sz,
418  next, node,
419  buffer_data_size);
420  if (!next_hdr_ptr)
421  goto trace;
422  payload_len = b[0]->current_length;
423 
424  /* ESP header */
425  hdr_len += sizeof (*esp);
426  esp = (esp_header_t *) (payload - hdr_len);
427 
428  /* optional UDP header */
429  if (ipsec_sa_is_set_UDP_ENCAP (sa0))
430  {
431  hdr_len += sizeof (udp_header_t);
432  udp = (udp_header_t *) (payload - hdr_len);
433  }
434 
435  /* IP header */
436  hdr_len += ip_len;
437  ip_hdr = payload - hdr_len;
438 
439  /* L2 header */
440  if (!is_tun)
441  {
442  l2_len = vnet_buffer (b[0])->ip.save_rewrite_length;
443  hdr_len += l2_len;
444  l2_hdr = payload - hdr_len;
445 
446  /* copy l2 and ip header */
447  clib_memcpy_le32 (l2_hdr, old_ip_hdr - l2_len, l2_len);
448  }
449  else
450  l2_len = 0;
451 
452  if (is_ip6)
453  {
454  ip6_header_t *ip6 = (ip6_header_t *) (old_ip_hdr);
455  if (PREDICT_TRUE (NULL == ext_hdr))
456  {
457  *next_hdr_ptr = ip6->protocol;
458  ip6->protocol = IP_PROTOCOL_IPSEC_ESP;
459  }
460  else
461  {
462  *next_hdr_ptr = ext_hdr->next_hdr;
463  ext_hdr->next_hdr = IP_PROTOCOL_IPSEC_ESP;
464  }
465  ip6->payload_length =
466  clib_host_to_net_u16 (payload_len + hdr_len - l2_len -
467  sizeof (ip6_header_t));
468  }
469  else
470  {
471  u16 len;
472  ip4_header_t *ip4 = (ip4_header_t *) (old_ip_hdr);
473  *next_hdr_ptr = ip4->protocol;
474  len = payload_len + hdr_len - l2_len;
475  if (udp)
476  {
477  esp_update_ip4_hdr (ip4, len, /* is_transport */ 1, 1);
478  esp_fill_udp_hdr (sa0, udp, len - ip_len);
479  }
480  else
481  esp_update_ip4_hdr (ip4, len, /* is_transport */ 1, 0);
482  }
483 
484  clib_memcpy_le64 (ip_hdr, old_ip_hdr, ip_len);
485 
486  if (!is_tun)
487  next[0] = ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT;
488  }
489 
490  esp->spi = spi;
491  esp->seq = clib_net_to_host_u32 (sa0->seq);
492 
493  if (sa0->crypto_enc_op_id)
494  {
495  vnet_crypto_op_t *op;
498  op->src = op->dst = payload;
499  op->key_index = sa0->crypto_key_index;
500  op->len = payload_len - icv_sz;
501  op->user_data = b - bufs;
502 
503  if (ipsec_sa_is_set_IS_AEAD (sa0))
504  {
505  /*
506  * construct the AAD in a scratch space in front
507  * of the IP header.
508  */
509  op->aad = payload - hdr_len - sizeof (esp_aead_t);
510 
511  esp_aad_fill (op, esp, sa0);
512 
513  op->tag = payload + op->len;
514  op->tag_len = 16;
515 
516  u64 *iv = (u64 *) (payload - iv_sz);
517  nonce->salt = sa0->salt;
518  nonce->iv = *iv = clib_host_to_net_u64 (sa0->gcm_iv_counter++);
519  op->iv = (u8 *) nonce;
520  nonce++;
521  }
522  else
523  {
524  op->iv = payload - iv_sz;
526  }
527  }
528 
529  if (sa0->integ_op_id)
530  {
531  vnet_crypto_op_t *op;
533  vnet_crypto_op_init (op, sa0->integ_op_id);
534  op->src = payload - iv_sz - sizeof (esp_header_t);
535  op->digest = payload + payload_len - icv_sz;
536  op->key_index = sa0->integ_key_index;
537  op->digest_len = icv_sz;
538  op->len = payload_len - icv_sz + iv_sz + sizeof (esp_header_t);
539  op->user_data = b - bufs;
540  if (ipsec_sa_is_set_USE_ESN (sa0))
541  {
542  u32 seq_hi = clib_net_to_host_u32 (sa0->seq_hi);
543  clib_memcpy_fast (op->digest, &seq_hi, sizeof (seq_hi));
544  op->len += sizeof (seq_hi);
545  }
546  }
547 
548  vlib_buffer_advance (b[0], 0LL - hdr_len);
549 
550  current_sa_packets += 1;
551  current_sa_bytes += payload_len;
552 
553  trace:
554  if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
555  {
556  esp_encrypt_trace_t *tr = vlib_add_trace (vm, node, b[0],
557  sizeof (*tr));
558  tr->sa_index = sa_index0;
559  tr->spi = sa0->spi;
560  tr->seq = sa0->seq;
561  tr->sa_seq_hi = sa0->seq_hi;
562  tr->udp_encap = ipsec_sa_is_set_UDP_ENCAP (sa0);
563  tr->crypto_alg = sa0->crypto_alg;
564  tr->integ_alg = sa0->integ_alg;
565  }
566  /* next */
567  n_left -= 1;
568  next += 1;
569  b += 1;
570  }
571 
573  current_sa_index, current_sa_packets,
574  current_sa_bytes);
575  esp_process_ops (vm, node, ptd->crypto_ops, bufs, nexts);
576  esp_process_ops (vm, node, ptd->integ_ops, bufs, nexts);
577 
579  ESP_ENCRYPT_ERROR_RX_PKTS, frame->n_vectors);
580 
581  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
582  return frame->n_vectors;
583 }
584 
587  vlib_frame_t * from_frame)
588 {
589  return esp_encrypt_inline (vm, node, from_frame, 0 /* is_ip6 */ , 0);
590 }
591 
592 /* *INDENT-OFF* */
594  .name = "esp4-encrypt",
595  .vector_size = sizeof (u32),
596  .format_trace = format_esp_encrypt_trace,
598 
600  .error_strings = esp_encrypt_error_strings,
601 
602  .n_next_nodes = ESP_ENCRYPT_N_NEXT,
603  .next_nodes = {
604  [ESP_ENCRYPT_NEXT_DROP] = "ip4-drop",
605  [ESP_ENCRYPT_NEXT_HANDOFF] = "esp4-encrypt-handoff",
606  [ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT] = "interface-output",
607  },
608 };
609 /* *INDENT-ON* */
610 
613  vlib_frame_t * from_frame)
614 {
615  return esp_encrypt_inline (vm, node, from_frame, 1 /* is_ip6 */ , 0);
616 }
617 
618 /* *INDENT-OFF* */
620  .name = "esp6-encrypt",
621  .vector_size = sizeof (u32),
622  .format_trace = format_esp_encrypt_trace,
624 
626  .error_strings = esp_encrypt_error_strings,
627 
628  .n_next_nodes = ESP_ENCRYPT_N_NEXT,
629  .next_nodes = {
630  [ESP_ENCRYPT_NEXT_DROP] = "ip6-drop",
631  [ESP_ENCRYPT_NEXT_HANDOFF] = "esp6-encrypt-handoff",
632  [ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT] = "interface-output",
633  },
634 };
635 /* *INDENT-ON* */
636 
639  vlib_frame_t * from_frame)
640 {
641  return esp_encrypt_inline (vm, node, from_frame, 0 /* is_ip6 */ , 1);
642 }
643 
644 /* *INDENT-OFF* */
646  .name = "esp4-encrypt-tun",
647  .vector_size = sizeof (u32),
648  .format_trace = format_esp_encrypt_trace,
650 
652  .error_strings = esp_encrypt_error_strings,
653 
654  .n_next_nodes = ESP_ENCRYPT_N_NEXT,
655  .next_nodes = {
656  [ESP_ENCRYPT_NEXT_DROP] = "ip4-drop",
657  [ESP_ENCRYPT_NEXT_HANDOFF] = "esp4-encrypt-tun-handoff",
658  [ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT] = "error-drop",
659  },
660 };
661 
662 VNET_FEATURE_INIT (esp4_encrypt_tun_feat_node, static) =
663 {
664  .arc_name = "ip4-output",
665  .node_name = "esp4-encrypt-tun",
666  .runs_before = VNET_FEATURES ("adj-midchain-tx"),
667 };
668 
669 VNET_FEATURE_INIT (esp6o4_encrypt_tun_feat_node, static) =
670 {
671  .arc_name = "ip6-output",
672  .node_name = "esp4-encrypt-tun",
673  .runs_before = VNET_FEATURES ("adj-midchain-tx"),
674 };
675 
676 VNET_FEATURE_INIT (esp4_ethernet_encrypt_tun_feat_node, static) =
677 {
678  .arc_name = "ethernet-output",
679  .node_name = "esp4-encrypt-tun",
680  .runs_before = VNET_FEATURES ("adj-midchain-tx", "adj-midchain-tx-no-count"),
681 };
682 /* *INDENT-ON* */
683 
686  vlib_frame_t * from_frame)
687 {
688  return esp_encrypt_inline (vm, node, from_frame, 1 /* is_ip6 */ , 1);
689 }
690 
691 /* *INDENT-OFF* */
693  .name = "esp6-encrypt-tun",
694  .vector_size = sizeof (u32),
695  .format_trace = format_esp_encrypt_trace,
697 
699  .error_strings = esp_encrypt_error_strings,
700 
701  .n_next_nodes = ESP_ENCRYPT_N_NEXT,
702  .next_nodes = {
703  [ESP_ENCRYPT_NEXT_DROP] = "ip6-drop",
704  [ESP_ENCRYPT_NEXT_HANDOFF] = "esp6-encrypt-tun-handoff",
705  [ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT] = "error-drop",
706  },
707 };
708 
709 VNET_FEATURE_INIT (esp6_encrypt_tun_feat_node, static) =
710 {
711  .arc_name = "ip6-output",
712  .node_name = "esp6-encrypt-tun",
713  .runs_before = VNET_FEATURES ("adj-midchain-tx"),
714 };
715 
716 VNET_FEATURE_INIT (esp4o6_encrypt_tun_feat_node, static) =
717 {
718  .arc_name = "ip4-output",
719  .node_name = "esp6-encrypt-tun",
720  .runs_before = VNET_FEATURES ("adj-midchain-tx"),
721 };
722 
723 /* *INDENT-ON* */
724 
725 typedef struct
726 {
729 
730 static u8 *
731 format_esp_no_crypto_trace (u8 * s, va_list * args)
732 {
733  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
734  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
735  esp_no_crypto_trace_t *t = va_arg (*args, esp_no_crypto_trace_t *);
736 
737  s = format (s, "esp-no-crypto: sa-index %u", t->sa_index);
738 
739  return s;
740 }
741 
742 enum
743 {
746 };
747 
748 enum
749 {
751 };
752 
753 static char *esp_no_crypto_error_strings[] = {
754  "Outbound ESP packets received",
755 };
756 
760 {
761  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
762  u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
763  u32 *from = vlib_frame_vector_args (frame);
764  u32 n_left = frame->n_vectors;
765 
766  vlib_get_buffers (vm, from, b, n_left);
767 
768  while (n_left > 0)
769  {
770  u32 next0;
771  u32 sa_index0;
772 
773  /* packets are always going to be dropped, but get the sa_index */
774  sa_index0 = *(u32 *) vnet_feature_next_with_data (&next0, b[0],
775  sizeof (sa_index0));
776 
777  next[0] = ESP_NO_CRYPTO_NEXT_DROP;
778 
779  if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
780  {
781  esp_no_crypto_trace_t *tr = vlib_add_trace (vm, node, b[0],
782  sizeof (*tr));
783  tr->sa_index = sa_index0;
784  }
785 
786  n_left -= 1;
787  next += 1;
788  b += 1;
789  }
790 
793 
794  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
795 
796  return frame->n_vectors;
797 }
798 
801  vlib_frame_t * from_frame)
802 {
803  return esp_no_crypto_inline (vm, node, from_frame);
804 }
805 
806 /* *INDENT-OFF* */
808 {
809  .name = "esp4-no-crypto",
810  .vector_size = sizeof (u32),
811  .format_trace = format_esp_no_crypto_trace,
813  .error_strings = esp_no_crypto_error_strings,
814  .n_next_nodes = ESP_NO_CRYPTO_N_NEXT,
815  .next_nodes = {
816  [ESP_NO_CRYPTO_NEXT_DROP] = "ip4-drop",
817  },
818 };
819 
820 VNET_FEATURE_INIT (esp4_no_crypto_tun_feat_node, static) =
821 {
822  .arc_name = "ip4-output",
823  .node_name = "esp4-no-crypto",
824  .runs_before = VNET_FEATURES ("adj-midchain-tx"),
825 };
826 
829  vlib_frame_t * from_frame)
830 {
831  return esp_no_crypto_inline (vm, node, from_frame);
832 }
833 
834 /* *INDENT-OFF* */
836 {
837  .name = "esp6-no-crypto",
838  .vector_size = sizeof (u32),
839  .format_trace = format_esp_no_crypto_trace,
841  .error_strings = esp_no_crypto_error_strings,
842  .n_next_nodes = ESP_NO_CRYPTO_N_NEXT,
843  .next_nodes = {
844  [ESP_NO_CRYPTO_NEXT_DROP] = "ip6-drop",
845  },
846 };
847 
848 VNET_FEATURE_INIT (esp6_no_crypto_tun_feat_node, static) =
849 {
850  .arc_name = "ip6-output",
851  .node_name = "esp6-no-crypto",
852  .runs_before = VNET_FEATURES ("adj-midchain-tx"),
853 };
854 /* *INDENT-ON* */
855 
856 /*
857  * fd.io coding-style-patch-verification: ON
858  *
859  * Local Variables:
860  * eval: (c-set-style "gnu")
861  * End:
862  */
u32 vnet_crypto_process_ops(vlib_main_t *vm, vnet_crypto_op_t ops[], u32 n_ops)
Definition: crypto.c:46
VNET_FEATURE_INIT(dpdk_esp4_encrypt_tun_feat_node, static)
u32 spi
u8 * format_ipsec_integ_alg(u8 *s, va_list *args)
Definition: ipsec_format.c:110
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
Definition: vlib_api_cli.c:898
#define clib_min(x, y)
Definition: clib.h:295
#define CLIB_UNUSED(x)
Definition: clib.h:82
ipsec_per_thread_data_t * ptd
Definition: ipsec.h:177
vnet_crypto_op_t * integ_ops
Definition: ipsec.h:94
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_always_inline u8 esp_get_ip6_hdr_len(ip6_header_t *ip6, ip6_ext_header_t **ext_hdr)
Definition: esp_encrypt.c:179
static char * esp_no_crypto_error_strings[]
Definition: esp_encrypt.c:753
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:207
#define PREDICT_TRUE(x)
Definition: clib.h:112
ipsec_integ_alg_t
Definition: ipsec_sa.h:58
esp_encrypt_next_t
Definition: esp_encrypt.c:37
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 NULL
Definition: clib.h:58
static u32 ipsec_sa_assign_thread(u32 thread_id)
Definition: ipsec_sa.h:447
#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:573
ipsec_integ_alg_t integ_alg
Definition: ipsec_sa.h:152
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:93
static void * ip6_ext_next_header(ip6_ext_header_t *ext_hdr)
Definition: ip6_packet.h:510
static u8 * format_esp_encrypt_trace(u8 *s, va_list *args)
Definition: esp_encrypt.c:75
ipsec_integ_alg_t integ_alg
Definition: esp_encrypt.c:75
uword ip_csum_t
Definition: ip_packet.h:244
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
ipsec_crypto_alg_t crypto_alg
Definition: esp_encrypt.c:74
#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:93
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:131
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:645
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
u32 seq_hi
Definition: ipsec_sa.h:121
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:127
vl_api_ip_proto_t protocol
Definition: lb_types.api:71
static uword esp_no_crypto_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: esp_encrypt.c:758
#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
static_always_inline void esp_fill_udp_hdr(ipsec_sa_t *sa, udp_header_t *udp, u16 len)
Definition: esp_encrypt.c:154
#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:161
u8 * format_ipsec_crypto_alg(u8 *s, va_list *args)
Definition: ipsec_format.c:78
u32 salt
unsigned int u32
Definition: types.h:88
static const u8 pad_data[]
Definition: ipsec.h:176
#define VLIB_FRAME_SIZE
Definition: node.h:378
STATIC_ASSERT_SIZEOF(esp_gcm_nonce_t, 12)
bool is_ip6
Definition: ip.api:43
static u8 * format_esp_no_crypto_trace(u8 *s, va_list *args)
Definition: esp_encrypt.c:731
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
vlib_node_registration_t esp6_encrypt_node
(constructor) VLIB_REGISTER_NODE (esp6_encrypt_node)
Definition: esp_encrypt.c:619
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
u32 encrypt_thread_index
Definition: ipsec_sa.h:117
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:519
vlib_node_registration_t esp6_encrypt_tun_node
(constructor) VLIB_REGISTER_NODE (esp6_encrypt_tun_node)
Definition: esp_encrypt.c:692
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
u32 salt
Definition: ipsec_sa.h:165
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:807
#define PREDICT_FALSE(x)
Definition: clib.h:111
#define always_inline
Definition: ipsec.h:28
u32 node_index
Node index.
Definition: node.h:496
static char * esp_encrypt_error_strings[]
Definition: esp_encrypt.c:56
vlib_main_t * vm
Definition: in2out_ed.c:1810
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:91
#define ip6_ext_header_len(p)
Definition: ip6_packet.h:506
static_always_inline u32 vlib_buffer_get_default_data_size(vlib_main_t *vm)
Definition: buffer_funcs.h:96
u8 ip6[16]
Definition: one.api:477
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u32 flags
Definition: vhost_user.h:141
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
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:835
vlib_node_registration_t esp4_encrypt_node
(constructor) VLIB_REGISTER_NODE (esp4_encrypt_node)
Definition: esp_encrypt.c:593
udp_header_t udp_hdr
Definition: ipsec_sa.h:141
u32 current_config_index
Used by feature subgraph arcs to visit enabled feature nodes.
Definition: buffer.h:147
#define ARRAY_LEN(x)
Definition: clib.h:62
static uword round_pow2(uword x, uword pow2)
Definition: clib.h:241
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1810
#define ESP_MAX_BLOCK_SIZE
Definition: esp.h:76
#define clib_atomic_cmp_and_swap(addr, old, new)
Definition: atomics.h:37
vlib_combined_counter_main_t ipsec_sa_counters
SA packet & bytes counters.
Definition: ipsec_sa.c:27
#define ASSERT(truth)
ip6_header_t ip6_hdr
Definition: ipsec_sa.h:139
ipsec_sa_t * sad
Definition: ipsec.h:102
esp_encrypt_error_t
Definition: esp_encrypt.c:53
static_always_inline void esp_update_ip4_hdr(ip4_header_t *ip4, u16 len, int is_transport, int is_udp)
Definition: esp_encrypt.c:128
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:128
#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:298
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:294
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:242
u64 gcm_iv_counter
Definition: ipsec_sa.h:166
vnet_crypto_op_id_t crypto_enc_op_id
Definition: ipsec_sa.h:129
vnet_crypto_op_status_t status
Definition: crypto.h:129
#define vnet_buffer(b)
Definition: buffer.h:408
dpo_id_t dpo
Definition: ipsec_sa.h:125
ipsec_crypto_alg_t crypto_alg
Definition: ipsec_sa.h:148
ip4_header_t ip4_hdr
Definition: ipsec_sa.h:138
u8 crypto_block_size
Definition: ipsec_sa.h:115
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1811
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
u32 ip4
Definition: one.api:440
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
u8 crypto_iv_size
Definition: ipsec_sa.h:114
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
#define foreach_esp_encrypt_error
Definition: esp_encrypt.c:41
u8 integ_icv_size
Definition: ipsec_sa.h:116
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:300
static_always_inline void clib_memcpy_le32(u8 *dst, u8 *src, u8 len)
Definition: string.h:289