FD.io VPP  v21.06-3-gbb25fbf28
Vector Packet Processing
ip6_map_t.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "map.h"
16 
17 #include <vnet/ip/ip4_to_ip6.h>
18 #include <vnet/ip/ip6_to_ip4.h>
19 #include <vnet/ip/ip_frag.h>
20 
21 typedef enum
22 {
30 
31 typedef enum
32 {
39 
40 typedef enum
41 {
48 
49 typedef enum
50 {
57 
58 typedef struct
59 {
63 
64 static int
66 {
67  icmp6_to_icmp_ctx_t *ctx = arg;
68  u32 ip4_sadr;
69 
70  // Security check
71  // Note that this prevents an intermediate IPv6 router from answering
72  // the request.
73  ip4_sadr = map_get_ip4 (&ip6->src_address, ctx->d->ip6_src_len);
74  if (ip6->src_address.as_u64[0] !=
75  map_get_pfx_net (ctx->d, ip4_sadr, ctx->sender_port)
76  || ip6->src_address.as_u64[1] != map_get_sfx_net (ctx->d, ip4_sadr,
77  ctx->sender_port))
78  return -1;
79 
80  ip4->dst_address.as_u32 =
81  ip6_map_t_embedded_address (ctx->d, &ip6->dst_address);
82  ip4->src_address.as_u32 = ip4_sadr;
83 
84  return 0;
85 }
86 
87 static int
89  void *arg)
90 {
91  icmp6_to_icmp_ctx_t *ctx = arg;
92  u32 inner_ip4_dadr;
93 
94  //Security check of inner packet
95  inner_ip4_dadr = map_get_ip4 (&ip6->dst_address, ctx->d->ip6_src_len);
96  if (ip6->dst_address.as_u64[0] !=
97  map_get_pfx_net (ctx->d, inner_ip4_dadr, ctx->sender_port)
98  || ip6->dst_address.as_u64[1] != map_get_sfx_net (ctx->d,
99  inner_ip4_dadr,
100  ctx->sender_port))
101  return -1;
102 
103  ip4->dst_address.as_u32 = inner_ip4_dadr;
104  ip4->src_address.as_u32 =
105  ip6_map_t_embedded_address (ctx->d, &ip6->src_address);
106 
107  return 0;
108 }
109 
110 static uword
113 {
114  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
115  vlib_node_runtime_t *error_node =
118  n_left_from = frame->n_vectors;
119  next_index = node->cached_next_index;
122 
123  while (n_left_from > 0)
124  {
125  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
126 
127  while (n_left_from > 0 && n_left_to_next > 0)
128  {
129  u32 pi0;
130  vlib_buffer_t *p0;
131  u8 error0;
132  ip6_mapt_icmp_next_t next0;
133  map_domain_t *d0;
134  u16 len0;
135  icmp6_to_icmp_ctx_t ctx0;
136  ip6_header_t *ip60;
137 
138  pi0 = to_next[0] = from[0];
139  from += 1;
140  n_left_from -= 1;
141  to_next += 1;
142  n_left_to_next -= 1;
143  error0 = MAP_ERROR_NONE;
145 
146  p0 = vlib_get_buffer (vm, pi0);
147  ip60 = vlib_buffer_get_current (p0);
148  len0 = clib_net_to_host_u16 (ip60->payload_length);
149  d0 =
151  vnet_buffer (p0)->map_t.map_domain_index);
152  ctx0.d = d0;
153  ctx0.sender_port = 0;
154  if (!ip6_get_port
155  (vm, p0, ip60, p0->current_length, NULL, &ctx0.sender_port,
156  NULL, NULL, NULL, NULL))
157  {
158  // In case of 1:1 mapping, we don't care about the port
159  if (!(d0->ea_bits_len == 0 && d0->rules))
160  {
161  error0 = MAP_ERROR_ICMP;
162  goto err0;
163  }
164  }
165 
166  if (icmp6_to_icmp (vm, p0, ip6_to_ip4_set_icmp_cb, &ctx0,
168  {
169  error0 = MAP_ERROR_ICMP;
170  goto err0;
171  }
172 
173  if (vnet_buffer (p0)->map_t.mtu < p0->current_length)
174  {
175  // Send to fragmentation node if necessary
176  vnet_buffer (p0)->ip_frag.mtu = vnet_buffer (p0)->map_t.mtu;
177  vnet_buffer (p0)->ip_frag.next_index = IP_FRAG_NEXT_IP4_LOOKUP;
179  }
180  else
181  {
182  next0 = ip6_map_ip4_lookup_bypass (p0, NULL) ?
184  }
185  err0:
186  if (PREDICT_TRUE (error0 == MAP_ERROR_NONE))
187  {
189  thread_index,
190  vnet_buffer (p0)->
191  map_t.map_domain_index, 1,
192  len0);
193  }
194  else
195  {
196  next0 = IP6_MAPT_ICMP_NEXT_DROP;
197  }
198 
199  p0->error = error_node->errors[error0];
201  to_next, n_left_to_next, pi0,
202  next0);
203  }
204  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
205  }
206  return frame->n_vectors;
207 }
208 
209 /*
210  * Translate IPv6 fragmented packet to IPv4.
211  */
212 always_inline int
214 {
215  ip6_header_t *ip6;
216  ip6_frag_hdr_t *frag;
217  ip4_header_t *ip4;
218  u16 frag_id;
219  u8 frag_more;
220  u16 frag_offset;
221  u8 l4_protocol;
222  u16 l4_offset;
223 
225 
226  if (ip6_parse
227  (vm, p, ip6, p->current_length, &l4_protocol, &l4_offset, &frag_offset))
228  return -1;
229 
230  frag = (ip6_frag_hdr_t *) u8_ptr_add (ip6, frag_offset);
231  ip4 = (ip4_header_t *) u8_ptr_add (ip6, l4_offset - sizeof (*ip4));
232  vlib_buffer_advance (p, l4_offset - sizeof (*ip4));
233 
234  frag_id = frag_id_6to4 (frag->identification);
235  frag_more = ip6_frag_hdr_more (frag);
236  frag_offset = ip6_frag_hdr_offset (frag);
237 
238  ip4->dst_address.as_u32 = vnet_buffer (p)->map_t.v6.daddr;
239  ip4->src_address.as_u32 = vnet_buffer (p)->map_t.v6.saddr;
240 
241  ip4->ip_version_and_header_length =
243  ip4->tos = ip6_translate_tos (ip6->ip_version_traffic_class_and_flow_label);
244  ip4->length =
245  u16_net_add (ip6->payload_length,
246  sizeof (*ip4) - l4_offset + sizeof (*ip6));
247  ip4->fragment_id = frag_id;
248  ip4->flags_and_fragment_offset =
249  clib_host_to_net_u16 (frag_offset |
250  (frag_more ? IP4_HEADER_FLAG_MORE_FRAGMENTS : 0));
251  ip4->ttl = ip6->hop_limit;
252  ip4->protocol =
253  (l4_protocol == IP_PROTOCOL_ICMP6) ? IP_PROTOCOL_ICMP : l4_protocol;
254  ip4->checksum = ip4_header_checksum (ip4);
255 
256  return 0;
257 }
258 
259 static uword
262 {
263  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
265  n_left_from = frame->n_vectors;
266  next_index = node->cached_next_index;
267  vlib_node_runtime_t *error_node =
269 
270  while (n_left_from > 0)
271  {
272  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
273 
274  while (n_left_from > 0 && n_left_to_next > 0)
275  {
276  u32 pi0;
277  vlib_buffer_t *p0;
278  u32 next0;
279 
280  pi0 = to_next[0] = from[0];
281  from += 1;
282  n_left_from -= 1;
283  to_next += 1;
284  n_left_to_next -= 1;
286  p0 = vlib_get_buffer (vm, pi0);
287 
288  if (map_ip6_to_ip4_fragmented (vm, p0))
289  {
290  p0->error = error_node->errors[MAP_ERROR_FRAGMENT_DROPPED];
292  }
293  else
294  {
295  if (vnet_buffer (p0)->map_t.mtu < p0->current_length)
296  {
297  // Send to fragmentation node if necessary
298  vnet_buffer (p0)->ip_frag.mtu = vnet_buffer (p0)->map_t.mtu;
299  vnet_buffer (p0)->ip_frag.next_index =
302  }
303  else
304  {
305  next0 = ip6_map_ip4_lookup_bypass (p0, NULL) ?
307  }
308  }
309 
311  to_next, n_left_to_next, pi0,
312  next0);
313  }
314  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
315  }
316  return frame->n_vectors;
317 }
318 
319 /*
320  * Translate IPv6 UDP/TCP packet to IPv4.
321  * Returns 0 on success.
322  * Returns a non-zero error code on error.
323  */
324 always_inline int
326  bool udp_checksum)
327 {
328  map_main_t *mm = &map_main;
329  ip6_header_t *ip6;
330  u16 *checksum;
331  ip_csum_t csum = 0;
332  ip4_header_t *ip4;
333  u16 fragment_id;
334  u16 flags;
335  u16 frag_offset;
336  u8 l4_protocol;
337  u16 l4_offset;
338  ip6_address_t old_src, old_dst;
339 
341 
342  if (ip6_parse
343  (vm, p, ip6, p->current_length, &l4_protocol, &l4_offset, &frag_offset))
344  return -1;
345 
346  if (l4_protocol == IP_PROTOCOL_TCP)
347  {
348  tcp_header_t *tcp = (tcp_header_t *) u8_ptr_add (ip6, l4_offset);
349  if (mm->tcp_mss > 0)
350  {
351  csum = tcp->checksum;
352  map_mss_clamping (tcp, &csum, mm->tcp_mss);
353  tcp->checksum = ip_csum_fold (csum);
354  }
355  checksum = &tcp->checksum;
356  }
357  else
358  {
359  udp_header_t *udp = (udp_header_t *) u8_ptr_add (ip6, l4_offset);
360  checksum = &udp->checksum;
361  }
362 
363  old_src.as_u64[0] = ip6->src_address.as_u64[0];
364  old_src.as_u64[1] = ip6->src_address.as_u64[1];
365  old_dst.as_u64[0] = ip6->dst_address.as_u64[0];
366  old_dst.as_u64[1] = ip6->dst_address.as_u64[1];
367 
368  ip4 = (ip4_header_t *) u8_ptr_add (ip6, l4_offset - sizeof (*ip4));
369 
370  vlib_buffer_advance (p, l4_offset - sizeof (*ip4));
371 
372  if (PREDICT_FALSE (frag_offset))
373  {
374  // Only the first fragment
375  ip6_frag_hdr_t *hdr = (ip6_frag_hdr_t *) u8_ptr_add (ip6, frag_offset);
376  fragment_id = frag_id_6to4 (hdr->identification);
377  flags = clib_host_to_net_u16 (IP4_HEADER_FLAG_MORE_FRAGMENTS);
378  }
379  else
380  {
381  fragment_id = 0;
382  flags = 0;
383  }
384 
385  ip4->dst_address.as_u32 = vnet_buffer (p)->map_t.v6.daddr;
386  ip4->src_address.as_u32 = vnet_buffer (p)->map_t.v6.saddr;
387 
388  /*
389  * Drop spoofed packets that from a known domain source.
390  */
391  u32 map_domain_index = -1;
392  u8 error = 0;
393 
394  ip4_map_get_domain (&ip4->src_address, &map_domain_index, &error);
395  if (error)
396  return error;
397 
398  ip4->ip_version_and_header_length =
400  ip4->tos = ip6_translate_tos (ip6->ip_version_traffic_class_and_flow_label);
401  ip4->length =
402  u16_net_add (ip6->payload_length,
403  sizeof (*ip4) + sizeof (*ip6) - l4_offset);
404  ip4->fragment_id = fragment_id;
405  ip4->flags_and_fragment_offset = flags;
406  ip4->ttl = ip6->hop_limit;
407  ip4->protocol = l4_protocol;
408  ip4->checksum = ip4_header_checksum (ip4);
409 
410  // UDP checksum is optional over IPv4
411  if (!udp_checksum && l4_protocol == IP_PROTOCOL_UDP)
412  {
413  *checksum = 0;
414  }
415  else
416  {
417  csum = ip_csum_sub_even (*checksum, old_src.as_u64[0]);
418  csum = ip_csum_sub_even (csum, old_src.as_u64[1]);
419  csum = ip_csum_sub_even (csum, old_dst.as_u64[0]);
420  csum = ip_csum_sub_even (csum, old_dst.as_u64[1]);
421  csum = ip_csum_add_even (csum, ip4->dst_address.as_u32);
422  csum = ip_csum_add_even (csum, ip4->src_address.as_u32);
423  *checksum = ip_csum_fold (csum);
424  }
425 
426  return 0;
427 }
428 
429 static uword
432 {
433  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
434  vlib_node_runtime_t *error_node =
436 
438  n_left_from = frame->n_vectors;
439  next_index = node->cached_next_index;
440  while (n_left_from > 0)
441  {
442  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
443 
444  while (n_left_from > 0 && n_left_to_next > 0)
445  {
446  u32 pi0;
447  vlib_buffer_t *p0;
449 
450  pi0 = to_next[0] = from[0];
451  from += 1;
452  n_left_from -= 1;
453  to_next += 1;
454  n_left_to_next -= 1;
456 
457  p0 = vlib_get_buffer (vm, pi0);
458 
459  if (map_ip6_to_ip4_tcp_udp (vm, p0, true))
460  {
461  p0->error = error_node->errors[MAP_ERROR_UNKNOWN];
463  }
464  else
465  {
466  if (vnet_buffer (p0)->map_t.mtu < p0->current_length)
467  {
468  // Send to fragmentation node if necessary
469  vnet_buffer (p0)->ip_frag.mtu = vnet_buffer (p0)->map_t.mtu;
470  vnet_buffer (p0)->ip_frag.next_index =
473  }
474  else
475  {
476  next0 = ip6_map_ip4_lookup_bypass (p0, NULL) ?
478  }
479  }
480 
482  to_next, n_left_to_next, pi0,
483  next0);
484  }
485  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
486  }
487  return frame->n_vectors;
488 }
489 
490 static uword
492 {
493  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
494  vlib_node_runtime_t *error_node =
496  map_main_t *mm = &map_main;
499 
501  n_left_from = frame->n_vectors;
502  next_index = node->cached_next_index;
503  while (n_left_from > 0)
504  {
505  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
506 
507  while (n_left_from > 0 && n_left_to_next > 0)
508  {
509  u32 pi0;
510  vlib_buffer_t *p0;
511  ip6_header_t *ip60;
512  u8 error0;
513  u32 l4_len0;
514  i32 map_port0;
515  map_domain_t *d0;
516  ip6_frag_hdr_t *frag0;
517  ip6_mapt_next_t next0 = 0;
518  u32 saddr;
519 
520  pi0 = to_next[0] = from[0];
521  from += 1;
522  n_left_from -= 1;
523  to_next += 1;
524  n_left_to_next -= 1;
525  error0 = MAP_ERROR_NONE;
526  p0 = vlib_get_buffer (vm, pi0);
527  u16 l4_src_port = vnet_buffer (p0)->ip.reass.l4_src_port;
528 
529  ip60 = vlib_buffer_get_current (p0);
530 
531  d0 =
533  &vnet_buffer (p0)->map_t.map_domain_index,
534  &error0);
535  if (!d0)
536  { /* Guess it wasn't for us */
537  vnet_feature_next (&next0, p0);
538  goto exit;
539  }
540 
541  saddr = map_get_ip4 (&ip60->src_address, d0->ip6_src_len);
542  vnet_buffer (p0)->map_t.v6.saddr = saddr;
543  vnet_buffer (p0)->map_t.v6.daddr =
545  vnet_buffer (p0)->map_t.mtu = d0->mtu ? d0->mtu : ~0;
546 
547  map_port0 = -1;
548 
549  if (PREDICT_FALSE (ip60->hop_limit == 1))
550  {
551  icmp6_error_set_vnet_buffer (p0, ICMP6_time_exceeded,
552  ICMP6_time_exceeded_ttl_exceeded_in_transit,
553  0);
554  p0->error = error_node->errors[MAP_ERROR_TIME_EXCEEDED];
555  next0 = IP6_MAPT_NEXT_ICMP;
556  goto trace;
557  }
558 
559  if (PREDICT_FALSE
560  (ip6_parse (vm, p0, ip60, p0->current_length,
561  &(vnet_buffer (p0)->map_t.v6.l4_protocol),
562  &(vnet_buffer (p0)->map_t.v6.l4_offset),
563  &(vnet_buffer (p0)->map_t.v6.frag_offset))))
564  {
565  error0 =
566  error0 == MAP_ERROR_NONE ? MAP_ERROR_MALFORMED : error0;
567  }
568 
569  l4_len0 =
570  (u32) clib_net_to_host_u16 (ip60->payload_length) +
571  sizeof (*ip60) - vnet_buffer (p0)->map_t.v6.l4_offset;
572  frag0 =
573  (ip6_frag_hdr_t *) u8_ptr_add (ip60,
574  vnet_buffer (p0)->map_t.v6.
575  frag_offset);
576 
577  if (PREDICT_FALSE
578  (vnet_buffer (p0)->map_t.v6.frag_offset
579  && ip6_frag_hdr_offset (frag0)))
580  {
581  map_port0 = l4_src_port;
583  }
584  else
585  if (PREDICT_TRUE
586  (vnet_buffer (p0)->map_t.v6.l4_protocol == IP_PROTOCOL_TCP))
587  {
588  error0 =
589  l4_len0 <
590  sizeof (tcp_header_t) ? MAP_ERROR_MALFORMED : error0;
591  vnet_buffer (p0)->map_t.checksum_offset =
592  vnet_buffer (p0)->map_t.v6.l4_offset + 16;
594  map_port0 = l4_src_port;
595  }
596  else
597  if (PREDICT_TRUE
598  (vnet_buffer (p0)->map_t.v6.l4_protocol == IP_PROTOCOL_UDP))
599  {
600  error0 =
601  l4_len0 <
602  sizeof (udp_header_t) ? MAP_ERROR_MALFORMED : error0;
603  vnet_buffer (p0)->map_t.checksum_offset =
604  vnet_buffer (p0)->map_t.v6.l4_offset + 6;
606  map_port0 = l4_src_port;
607  }
608  else if (vnet_buffer (p0)->map_t.v6.l4_protocol ==
609  IP_PROTOCOL_ICMP6)
610  {
611  error0 =
612  l4_len0 <
613  sizeof (icmp46_header_t) ? MAP_ERROR_MALFORMED : error0;
614  next0 = IP6_MAPT_NEXT_MAPT_ICMP;
615  if (((icmp46_header_t *)
616  u8_ptr_add (ip60,
617  vnet_buffer (p0)->map_t.v6.l4_offset))->type ==
618  ICMP6_echo_reply
619  || ((icmp46_header_t *)
620  u8_ptr_add (ip60,
621  vnet_buffer (p0)->map_t.v6.l4_offset))->
622  type == ICMP6_echo_request)
623  map_port0 = l4_src_port;
624  }
625  else
626  {
627  // TODO: In case of 1:1 mapping, it might be possible to
628  // do something with those packets.
629  error0 = MAP_ERROR_BAD_PROTOCOL;
630  }
631 
632  if (PREDICT_FALSE (map_port0 != -1) &&
633  (ip60->src_address.as_u64[0] !=
634  map_get_pfx_net (d0, vnet_buffer (p0)->map_t.v6.saddr,
635  map_port0)
636  || ip60->src_address.as_u64[1] != map_get_sfx_net (d0,
638  (p0)->map_t.
639  v6.saddr,
640  map_port0)))
641  {
642  // Security check when map_port0 is not zero (non-first
643  // fragment, UDP or TCP)
644  error0 =
645  error0 == MAP_ERROR_NONE ? MAP_ERROR_SEC_CHECK : error0;
646  }
647 
648  if (PREDICT_TRUE
649  (error0 == MAP_ERROR_NONE && next0 != IP6_MAPT_NEXT_MAPT_ICMP))
650  {
652  thread_index,
653  vnet_buffer (p0)->map_t.
654  map_domain_index, 1,
655  clib_net_to_host_u16 (ip60->
656  payload_length));
657  }
658 
659  if (PREDICT_FALSE
660  (error0 == MAP_ERROR_SEC_CHECK && mm->icmp6_enabled))
661  {
662  icmp6_error_set_vnet_buffer (p0, ICMP6_destination_unreachable,
663  ICMP6_destination_unreachable_source_address_failed_policy,
664  0);
665  next0 = IP6_MAPT_NEXT_ICMP;
666  }
667  else
668  {
669  next0 = (error0 != MAP_ERROR_NONE) ? IP6_MAPT_NEXT_DROP : next0;
670  }
671 
672  p0->error = error_node->errors[error0];
673  trace:
674  if (PREDICT_FALSE (p0->flags & VLIB_BUFFER_IS_TRACED))
675  {
676  map_add_trace (vm, node, p0,
677  vnet_buffer (p0)->map_t.map_domain_index,
678  map_port0);
679  }
680  exit:
682  to_next, n_left_to_next, pi0,
683  next0);
684  }
685  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
686  }
687  return frame->n_vectors;
688 }
689 
690 /* *INDENT-OFF* */
692  .function = ip6_map_t_fragmented,
693  .name = "ip6-map-t-fragmented",
694  .vector_size = sizeof (u32),
695  .format_trace = format_map_trace,
697 
698  .n_errors = MAP_N_ERROR,
699  .error_counters = map_error_counters,
700 
701  .n_next_nodes = IP6_MAPT_FRAGMENTED_N_NEXT,
702  .next_nodes =
703  {
704  [IP6_MAPT_FRAGMENTED_NEXT_IP4_LOOKUP] = "ip4-lookup",
705  [IP6_MAPT_FRAGMENTED_NEXT_IP4_REWRITE] = "ip4-load-balance",
707  [IP6_MAPT_FRAGMENTED_NEXT_DROP] = "error-drop",
708  },
709 };
710 /* *INDENT-ON* */
711 
712 /* *INDENT-OFF* */
714  .function = ip6_map_t_icmp,
715  .name = "ip6-map-t-icmp",
716  .vector_size = sizeof (u32),
717  .format_trace = format_map_trace,
719 
720  .n_errors = MAP_N_ERROR,
721  .error_counters = map_error_counters,
722 
723  .n_next_nodes = IP6_MAPT_ICMP_N_NEXT,
724  .next_nodes =
725  {
726  [IP6_MAPT_ICMP_NEXT_IP4_LOOKUP] = "ip4-lookup",
727  [IP6_MAPT_ICMP_NEXT_IP4_REWRITE] = "ip4-load-balance",
729  [IP6_MAPT_ICMP_NEXT_DROP] = "error-drop",
730  },
731 };
732 /* *INDENT-ON* */
733 
734 /* *INDENT-OFF* */
736  .function = ip6_map_t_tcp_udp,
737  .name = "ip6-map-t-tcp-udp",
738  .vector_size = sizeof (u32),
739  .format_trace = format_map_trace,
741 
742  .n_errors = MAP_N_ERROR,
743  .error_counters = map_error_counters,
744 
745  .n_next_nodes = IP6_MAPT_TCP_UDP_N_NEXT,
746  .next_nodes =
747  {
748  [IP6_MAPT_TCP_UDP_NEXT_IP4_LOOKUP] = "ip4-lookup",
749  [IP6_MAPT_TCP_UDP_NEXT_IP4_REWRITE] = "ip4-load-balance",
751  [IP6_MAPT_TCP_UDP_NEXT_DROP] = "error-drop",
752  },
753 };
754 /* *INDENT-ON* */
755 
756 /* *INDENT-OFF* */
757 VNET_FEATURE_INIT (ip6_map_t_feature, static) = {
758  .arc_name = "ip6-unicast",
759  .node_name = "ip6-map-t",
760  .runs_before = VNET_FEATURES ("ip6-flow-classify"),
761  .runs_after = VNET_FEATURES ("ip6-sv-reassembly-feature"),
762 };
763 
765  .function = ip6_map_t,
766  .name = "ip6-map-t",
767  .vector_size = sizeof(u32),
768  .format_trace = format_map_trace,
770 
771  .n_errors = MAP_N_ERROR,
772  .error_counters = map_error_counters,
773 
774  .n_next_nodes = IP6_MAPT_N_NEXT,
775  .next_nodes =
776  {
777  [IP6_MAPT_NEXT_MAPT_TCP_UDP] = "ip6-map-t-tcp-udp",
778  [IP6_MAPT_NEXT_MAPT_ICMP] = "ip6-map-t-icmp",
779  [IP6_MAPT_NEXT_MAPT_FRAGMENTED] = "ip6-map-t-fragmented",
780  [IP6_MAPT_NEXT_DROP] = "error-drop",
781  [IP6_MAPT_NEXT_ICMP] = "ip6-icmp-error",
782  },
783 };
784 /* *INDENT-ON* */
785 
786 /*
787  * fd.io coding-style-patch-verification: ON
788  *
789  * Local Variables:
790  * eval: (c-set-style "gnu")
791  * End:
792  */
IP6_MAPT_ICMP_NEXT_IP4_REWRITE
@ IP6_MAPT_ICMP_NEXT_IP4_REWRITE
Definition: ip6_map_t.c:34
IP6_MAPT_NEXT_DROP
@ IP6_MAPT_NEXT_DROP
Definition: ip6_map_t.c:26
map_domain_t::rules
ip6_address_t * rules
Definition: map.h:82
IP6_MAPT_FRAGMENTED_NEXT_IP4_REWRITE
@ IP6_MAPT_FRAGMENTED_NEXT_IP4_REWRITE
Definition: ip6_map_t.c:52
ip6_frag_hdr_more
#define ip6_frag_hdr_more(hdr)
Definition: ip6_packet.h:706
trace
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
Definition: vlib_api_cli.c:899
thread_index
u32 thread_index
Definition: nat44_ei_hairpinning.c:492
u8_ptr_add
#define u8_ptr_add(ptr, index)
Definition: ip_types.h:56
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
map_ip6_to_ip4_tcp_udp
static int map_ip6_to_ip4_tcp_udp(vlib_main_t *vm, vlib_buffer_t *p, bool udp_checksum)
Definition: ip6_map_t.c:325
icmp6_error_set_vnet_buffer
void icmp6_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp6.c:446
ip4
vl_api_ip4_address_t ip4
Definition: one.api:376
ip6_map_t
static uword ip6_map_t(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip6_map_t.c:491
next_index
nat44_ei_hairpin_src_next_t next_index
Definition: nat44_ei_hairpinning.c:412
vlib_get_buffer
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
pool_elt_at_index
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:553
IP6_MAPT_NEXT_MAPT_FRAGMENTED
@ IP6_MAPT_NEXT_MAPT_FRAGMENTED
Definition: ip6_map_t.c:25
map_domain_t::mtu
u16 mtu
Definition: map.h:86
ip6_map_t_tcp_udp
static uword ip6_map_t_tcp_udp(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip6_map_t.c:430
tcp_header_t
struct _tcp_header tcp_header_t
map_main_t::icmp6_enabled
bool icmp6_enabled
Definition: map.h:185
MAP_DOMAIN_COUNTER_RX
@ MAP_DOMAIN_COUNTER_RX
Definition: map.h:126
VLIB_NODE_TYPE_INTERNAL
@ VLIB_NODE_TYPE_INTERNAL
Definition: node.h:72
IP6_MAPT_TCP_UDP_NEXT_IP4_FRAG
@ IP6_MAPT_TCP_UDP_NEXT_IP4_FRAG
Definition: ip6_map_t.c:44
IP6_MAPT_FRAGMENTED_NEXT_IP4_LOOKUP
@ IP6_MAPT_FRAGMENTED_NEXT_IP4_LOOKUP
Definition: ip6_map_t.c:51
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
ip6_header_t::hop_limit
u8 hop_limit
Definition: ip6_packet.h:307
ip6_map_t_icmp
static uword ip6_map_t_icmp(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip6_map_t.c:111
IP6_MAPT_ICMP_NEXT_DROP
@ IP6_MAPT_ICMP_NEXT_DROP
Definition: ip6_map_t.c:36
IP6_MAPT_FRAGMENTED_NEXT_IP4_FRAG
@ IP6_MAPT_FRAGMENTED_NEXT_IP4_FRAG
Definition: ip6_map_t.c:53
ip6_map_ip4_lookup_bypass
static_always_inline bool ip6_map_ip4_lookup_bypass(vlib_buffer_t *p0, ip4_header_t *ip)
Definition: map.h:486
ip6_map_get_domain
static_always_inline map_domain_t * ip6_map_get_domain(ip6_address_t *addr, u32 *map_domain_index, u8 *error)
Definition: map.h:334
u16
unsigned short u16
Definition: types.h:57
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
icmp6_to_icmp
static int icmp6_to_icmp(vlib_main_t *vm, vlib_buffer_t *p, ip6_to_ip4_icmp_set_fn_t fn, void *ctx, ip6_to_ip4_icmp_set_fn_t inner_fn, void *inner_ctx)
Translate ICMP6 packet to ICMP4.
Definition: ip6_to_ip4.h:350
IP6_MAPT_TCP_UDP_NEXT_IP4_LOOKUP
@ IP6_MAPT_TCP_UDP_NEXT_IP4_LOOKUP
Definition: ip6_map_t.c:42
ip6_map_t_embedded_address
static_always_inline u32 ip6_map_t_embedded_address(map_domain_t *d, ip6_address_t *addr)
Definition: map.h:368
map_ip6_to_ip4_fragmented
static int map_ip6_to_ip4_fragmented(vlib_main_t *vm, vlib_buffer_t *p)
Definition: ip6_map_t.c:213
vlib_frame_t
Definition: node.h:372
IP4_VERSION_AND_HEADER_LENGTH_NO_OPTIONS
#define IP4_VERSION_AND_HEADER_LENGTH_NO_OPTIONS
Definition: ip4_packet.h:149
map_add_trace
static void map_add_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b, u32 map_domain_index, u16 port)
Definition: map.h:222
udp_header_t
Definition: udp_packet.h:45
ip4_header_t
Definition: ip4_packet.h:87
error
Definition: cJSON.c:88
map_main
map_main_t map_main
Definition: map.c:27
IP6_MAPT_ICMP_NEXT_IP4_FRAG
@ IP6_MAPT_ICMP_NEXT_IP4_FRAG
Definition: ip6_map_t.c:35
i32
signed int i32
Definition: types.h:77
map_domain_t
Definition: map.h:76
map_mss_clamping
static_always_inline void map_mss_clamping(tcp_header_t *tcp, ip_csum_t *sum, u16 mss_clamping)
Definition: map.h:423
ip6_map_t_tcp_udp_node
vlib_node_registration_t ip6_map_t_tcp_udp_node
(constructor) VLIB_REGISTER_NODE (ip6_map_t_tcp_udp_node)
Definition: ip6_map_t.c:735
ip6_map_t_icmp_node
vlib_node_registration_t ip6_map_t_icmp_node
(constructor) VLIB_REGISTER_NODE (ip6_map_t_icmp_node)
Definition: ip6_map_t.c:713
vlib_node_runtime_t::errors
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:460
ip6_mapt_next_t
ip6_mapt_next_t
Definition: ip6_map_t.c:21
vlib_buffer_advance
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:276
ip6_parse
static_always_inline int ip6_parse(vlib_main_t *vm, vlib_buffer_t *b, const ip6_header_t *ip6, u32 buff_len, u8 *l4_protocol, u16 *l4_offset, u16 *frag_hdr_offset)
Parse some useful information from IPv6 header.
Definition: ip6_to_ip4.h:65
vlib_buffer_t::error
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:145
map_main_t::tcp_mss
u16 tcp_mss
Definition: map.h:187
icmp6_to_icmp_ctx_t
Definition: ip6_map_t.c:58
IP6_MAPT_NEXT_ICMP
@ IP6_MAPT_NEXT_ICMP
Definition: ip6_map_t.c:27
IP6_MAPT_FRAGMENTED_NEXT_DROP
@ IP6_MAPT_FRAGMENTED_NEXT_DROP
Definition: ip6_map_t.c:54
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:437
map_main_t
Definition: map.h:165
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
vnet_feature_next
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:322
vlib_frame_vector_args
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
IP6_MAPT_TCP_UDP_N_NEXT
@ IP6_MAPT_TCP_UDP_N_NEXT
Definition: ip6_map_t.c:46
uword
u64 uword
Definition: types.h:112
icmp6_to_icmp_ctx_t::d
map_domain_t * d
Definition: ip6_map_t.c:60
ip4_map_get_domain
static_always_inline map_domain_t * ip4_map_get_domain(ip4_address_t *addr, u32 *map_domain_index, u8 *error)
Definition: map.h:314
vlib_main_t::thread_index
u32 thread_index
Definition: main.h:213
map_main_t::domain_counters
vlib_combined_counter_main_t * domain_counters
Definition: map.h:173
IP6_MAPT_FRAGMENTED_N_NEXT
@ IP6_MAPT_FRAGMENTED_N_NEXT
Definition: ip6_map_t.c:55
ip6_header_t::dst_address
ip6_address_t dst_address
Definition: ip6_packet.h:310
ip6_frag_hdr_offset
#define ip6_frag_hdr_offset(hdr)
Definition: ip6_packet.h:700
cm
vnet_feature_config_main_t * cm
Definition: nat44_ei_hairpinning.c:591
ip6_to_ip4.h
IPv6 to IPv4 translation.
ip6_map_t_node
vlib_node_registration_t ip6_map_t_node
(constructor) VLIB_REGISTER_NODE (ip6_map_t_node)
Definition: ip6_map_t.c:764
IP4_FRAG_NODE_NAME
#define IP4_FRAG_NODE_NAME
Definition: ip_frag.h:43
VNET_FEATURE_INIT
VNET_FEATURE_INIT(ip6_map_t_feature, static)
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
ip6_to_ip4_set_icmp_cb
static int ip6_to_ip4_set_icmp_cb(ip6_header_t *ip6, ip4_header_t *ip4, void *arg)
Definition: ip6_map_t.c:65
vlib_buffer_t::current_length
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:122
map.h
ip_frag.h
udp_header_t::checksum
u16 checksum
Definition: udp_packet.h:55
ip_csum_sub_even
static ip_csum_t ip_csum_sub_even(ip_csum_t c, ip_csum_t x)
Definition: ip_packet.h:273
IP6_MAPT_ICMP_N_NEXT
@ IP6_MAPT_ICMP_N_NEXT
Definition: ip6_map_t.c:37
vlib_validate_buffer_enqueue_x1
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:224
always_inline
#define always_inline
Definition: rdma_mlx5dv.h:23
map_get_ip4
static_always_inline u32 map_get_ip4(ip6_address_t *addr, u16 prefix_len)
Definition: map.h:303
ip6_mapt_tcp_udp_next_t
ip6_mapt_tcp_udp_next_t
Definition: ip6_map_t.c:40
IP6_MAPT_NEXT_MAPT_ICMP
@ IP6_MAPT_NEXT_MAPT_ICMP
Definition: ip6_map_t.c:24
ip6_map_t_fragmented
static uword ip6_map_t_fragmented(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip6_map_t.c:260
vlib_combined_counter_main_t
A collection of combined counters.
Definition: counter.h:203
IP6_MAPT_NEXT_MAPT_TCP_UDP
@ IP6_MAPT_NEXT_MAPT_TCP_UDP
Definition: ip6_map_t.c:23
vlib_put_next_frame
vlib_put_next_frame(vm, node, next_index, 0)
map_get_sfx_net
static_always_inline u64 map_get_sfx_net(map_domain_t *d, u32 addr, u16 port)
Definition: map.h:296
u32
unsigned int u32
Definition: types.h:88
ip6
vl_api_ip6_address_t ip6
Definition: one.api:424
ip6_map_t_fragmented_node
vlib_node_registration_t ip6_map_t_fragmented_node
(constructor) VLIB_REGISTER_NODE (ip6_map_t_fragmented_node)
Definition: ip6_map_t.c:691
ctx
long ctx[MAX_CONNS]
Definition: main.c:144
IP6_MAPT_ICMP_NEXT_IP4_LOOKUP
@ IP6_MAPT_ICMP_NEXT_IP4_LOOKUP
Definition: ip6_map_t.c:33
vlib_node_get_runtime
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
Definition: node_funcs.h:116
ip6_header_t
Definition: ip6_packet.h:294
ip6_get_port
static u16 ip6_get_port(vlib_main_t *vm, vlib_buffer_t *b, ip6_header_t *ip6, u16 buffer_len, u8 *ip_protocol, u16 *src_port, u16 *dst_port, u8 *icmp_type_or_tcp_flags, u32 *tcp_ack_number, u32 *tcp_seq_number)
Get L4 information like port number or ICMP id from IPv6 packet.
Definition: ip6_to_ip4.h:117
ip6_mapt_icmp_next_t
ip6_mapt_icmp_next_t
Definition: ip6_map_t.c:31
ip6_header_t::src_address
ip6_address_t src_address
Definition: ip6_packet.h:310
vlib_main_t
Definition: main.h:102
VNET_FEATURES
#define VNET_FEATURES(...)
Definition: feature.h:470
u8
unsigned char u8
Definition: types.h:56
vlib_buffer_get_current
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
ip4_header_checksum
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:314
ip_csum_t
uword ip_csum_t
Definition: ip_packet.h:245
icmp6_to_icmp_ctx_t::sender_port
u16 sender_port
Definition: ip6_map_t.c:61
frag_id_6to4
#define frag_id_6to4(id)
Definition: ip6_to_ip4.h:49
ip4_to_ip6.h
IPv4 to IPv6 translation.
map_main_t::domains
map_domain_t * domains
Definition: map.h:168
map_get_pfx_net
static_always_inline u64 map_get_pfx_net(map_domain_t *d, u32 addr, u16 port)
Definition: map.h:264
ip6_mapt_fragmented_next_t
ip6_mapt_fragmented_next_t
Definition: ip6_map_t.c:49
u16_net_add
#define u16_net_add(u, val)
Definition: ip_types.h:57
map_domain_t::ea_bits_len
u8 ea_bits_len
Definition: map.h:90
IP6_MAPT_TCP_UDP_NEXT_DROP
@ IP6_MAPT_TCP_UDP_NEXT_DROP
Definition: ip6_map_t.c:45
ip6_header_t::payload_length
u16 payload_length
Definition: ip6_packet.h:301
vlib_node_runtime_t
Definition: node.h:454
IP_FRAG_NEXT_IP4_LOOKUP
@ IP_FRAG_NEXT_IP4_LOOKUP
Definition: ip_frag.h:53
udp_checksum
u16 udp_checksum(udp_header_t *uh, u32 udp_len, void *ih, u8 version)
Definition: packets.c:116
ip6_translate_tos
static_always_inline u8 ip6_translate_tos(u32 ip_version_traffic_class_and_flow_label)
Translate TOS value from IPv6 to IPv4.
Definition: ip6_to_ip4.h:332
from
from
Definition: nat44_ei_hairpinning.c:415
PREDICT_TRUE
#define PREDICT_TRUE(x)
Definition: clib.h:125
ip_csum_add_even
static ip_csum_t ip_csum_add_even(ip_csum_t c, ip_csum_t x)
Definition: ip_packet.h:256
vlib_get_next_frame
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:395
ip_csum_fold
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:301
IP4_HEADER_FLAG_MORE_FRAGMENTS
#define IP4_HEADER_FLAG_MORE_FRAGMENTS
Definition: ip4_packet.h:107
n_left_from
n_left_from
Definition: nat44_ei_hairpinning.c:416
ip6_to_ip4_set_inner_icmp_cb
static int ip6_to_ip4_set_inner_icmp_cb(ip6_header_t *ip6, ip4_header_t *ip4, void *arg)
Definition: ip6_map_t.c:88
type
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vlib_increment_combined_counter
vlib_increment_combined_counter(ccm, ti, sw_if_index, n_buffers, n_bytes)
format_map_trace
u8 * format_map_trace(u8 *s, va_list *args)
Definition: map.c:1204
map_domain_t::ip6_src_len
u8 ip6_src_len
Definition: map.h:89
vlib_buffer_t::flags
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index,...
Definition: buffer.h:133
IP6_MAPT_N_NEXT
@ IP6_MAPT_N_NEXT
Definition: ip6_map_t.c:28
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
IP6_MAPT_TCP_UDP_NEXT_IP4_REWRITE
@ IP6_MAPT_TCP_UDP_NEXT_IP4_REWRITE
Definition: ip6_map_t.c:43
flags
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105