FD.io VPP  v20.01-48-g3e0dafb74
Vector Packet Processing
ip4_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/ip_frag.h>
18 #include <vnet/ip/ip4_to_ip6.h>
19 
20 typedef enum
21 {
28 
29 typedef enum
30 {
36 
37 typedef enum
38 {
44 
45 typedef enum
46 {
52 
53 //This is used to pass information within the buffer data.
54 //Buffer structure being too small to contain big structures like this.
55 /* *INDENT-OFF* */
56 typedef CLIB_PACKED (struct {
57  ip6_address_t daddr;
58  ip6_address_t saddr;
59  //IPv6 header + Fragmentation header will be here
60  //sizeof(ip6) + sizeof(ip_frag) - sizeof(ip4)
61  u8 unused[28];
62 }) ip4_mapt_pseudo_header_t;
63 /* *INDENT-ON* */
64 
65 typedef struct
66 {
67  map_domain_t *d;
68  u16 recv_port;
70 
71 static int
73  ip6_header_t * ip6, void *arg)
74 {
75  icmp_to_icmp6_ctx_t *ctx = arg;
76 
77  ip4_map_t_embedded_address (ctx->d, &ip6->src_address, &ip4->src_address);
78  ip6->dst_address.as_u64[0] =
79  map_get_pfx_net (ctx->d, ip4->dst_address.as_u32, ctx->recv_port);
80  ip6->dst_address.as_u64[1] =
81  map_get_sfx_net (ctx->d, ip4->dst_address.as_u32, ctx->recv_port);
82 
83  return 0;
84 }
85 
86 static int
88  ip6_header_t * ip6, void *arg)
89 {
90  icmp_to_icmp6_ctx_t *ctx = arg;
91 
92  //Note that the source address is within the domain
93  //while the destination address is the one outside the domain
94  ip4_map_t_embedded_address (ctx->d, &ip6->dst_address, &ip4->dst_address);
95  ip6->src_address.as_u64[0] =
96  map_get_pfx_net (ctx->d, ip4->src_address.as_u32, ctx->recv_port);
97  ip6->src_address.as_u64[1] =
98  map_get_sfx_net (ctx->d, ip4->src_address.as_u32, ctx->recv_port);
99 
100  return 0;
101 }
102 
103 static uword
106 {
107  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
108  vlib_node_runtime_t *error_node =
109  vlib_node_get_runtime (vm, ip4_map_t_icmp_node.index);
110  from = vlib_frame_vector_args (frame);
111  n_left_from = frame->n_vectors;
112  next_index = node->cached_next_index;
114  u32 thread_index = vm->thread_index;
115 
116  while (n_left_from > 0)
117  {
118  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
119 
120  while (n_left_from > 0 && n_left_to_next > 0)
121  {
122  u32 pi0;
123  vlib_buffer_t *p0;
124  ip4_mapt_icmp_next_t next0;
125  u8 error0;
126  map_domain_t *d0;
127  u16 len0;
128  icmp_to_icmp6_ctx_t ctx0;
129  ip4_header_t *ip40;
130 
132  pi0 = to_next[0] = from[0];
133  from += 1;
134  n_left_from -= 1;
135  to_next += 1;
136  n_left_to_next -= 1;
137  error0 = MAP_ERROR_NONE;
138 
139  p0 = vlib_get_buffer (vm, pi0);
140  vlib_buffer_advance (p0, sizeof (ip4_mapt_pseudo_header_t)); //The pseudo-header is not used
141  len0 =
142  clib_net_to_host_u16 (((ip4_header_t *)
143  vlib_buffer_get_current (p0))->length);
144  d0 =
146  vnet_buffer (p0)->map_t.map_domain_index);
147 
148  ip40 = vlib_buffer_get_current (p0);
149  ctx0.recv_port = ip4_get_port (ip40, 1);
150  ctx0.d = d0;
151  if (ctx0.recv_port == 0)
152  {
153  // In case of 1:1 mapping, we don't care about the port
154  if (!(d0->ea_bits_len == 0 && d0->rules))
155  {
156  error0 = MAP_ERROR_ICMP;
157  goto err0;
158  }
159  }
160 
161  if (icmp_to_icmp6
162  (p0, ip4_to_ip6_set_icmp_cb, &ctx0,
164  {
165  error0 = MAP_ERROR_ICMP;
166  goto err0;
167  }
168 
169  if (vnet_buffer (p0)->map_t.mtu < p0->current_length)
170  {
171  vnet_buffer (p0)->ip_frag.mtu = vnet_buffer (p0)->map_t.mtu;
172  vnet_buffer (p0)->ip_frag.next_index = IP_FRAG_NEXT_IP6_LOOKUP;
174  }
175  err0:
176  if (PREDICT_TRUE (error0 == MAP_ERROR_NONE))
177  {
179  thread_index,
180  vnet_buffer (p0)->
181  map_t.map_domain_index, 1,
182  len0);
183  }
184  else
185  {
186  next0 = IP4_MAPT_ICMP_NEXT_DROP;
187  }
188  p0->error = error_node->errors[error0];
189  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
190  to_next, n_left_to_next, pi0,
191  next0);
192  }
193  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
194  }
195  return frame->n_vectors;
196 }
197 
198 /*
199  * Translate fragmented IPv4 UDP/TCP packet to IPv6.
200  */
201 always_inline int
203  ip4_mapt_pseudo_header_t * pheader)
204 {
205  ip4_header_t *ip4;
206  ip6_header_t *ip6;
207  ip6_frag_hdr_t *frag;
208 
209  ip4 = vlib_buffer_get_current (p);
210  frag = (ip6_frag_hdr_t *) u8_ptr_add (ip4, sizeof (*ip4) - sizeof (*frag));
211  ip6 =
212  (ip6_header_t *) u8_ptr_add (ip4,
213  sizeof (*ip4) - sizeof (*frag) -
214  sizeof (*ip6));
215  vlib_buffer_advance (p, sizeof (*ip4) - sizeof (*ip6) - sizeof (*frag));
216 
217  //We know that the protocol was one of ICMP, TCP or UDP
218  //because the first fragment was found and cached
219  frag->next_hdr =
220  (ip4->protocol == IP_PROTOCOL_ICMP) ? IP_PROTOCOL_ICMP6 : ip4->protocol;
221  frag->identification = frag_id_4to6 (ip4->fragment_id);
222  frag->rsv = 0;
223  frag->fragment_offset_and_more =
225  clib_net_to_host_u16
228 
230  clib_host_to_net_u32 ((6 << 28) + (ip4->tos << 20));
231  ip6->payload_length =
232  clib_host_to_net_u16 (clib_net_to_host_u16 (ip4->length) -
233  sizeof (*ip4) + sizeof (*frag));
234  ip6->hop_limit = ip4->ttl;
235  ip6->protocol = IP_PROTOCOL_IPV6_FRAGMENTATION;
236 
237  ip6->dst_address.as_u64[0] = pheader->daddr.as_u64[0];
238  ip6->dst_address.as_u64[1] = pheader->daddr.as_u64[1];
239  ip6->src_address.as_u64[0] = pheader->saddr.as_u64[0];
240  ip6->src_address.as_u64[1] = pheader->saddr.as_u64[1];
241 
242  return 0;
243 }
244 
245 static uword
248 {
249  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
250  from = vlib_frame_vector_args (frame);
251  n_left_from = frame->n_vectors;
252  next_index = node->cached_next_index;
253  vlib_node_runtime_t *error_node =
254  vlib_node_get_runtime (vm, ip4_map_t_fragmented_node.index);
255 
256  while (n_left_from > 0)
257  {
258  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
259 
260  while (n_left_from > 0 && n_left_to_next > 0)
261  {
262  u32 pi0;
263  vlib_buffer_t *p0;
264  ip4_mapt_pseudo_header_t *pheader0;
265  ip4_mapt_fragmented_next_t next0;
266 
268  pi0 = to_next[0] = from[0];
269  from += 1;
270  n_left_from -= 1;
271  to_next += 1;
272  n_left_to_next -= 1;
273 
274  p0 = vlib_get_buffer (vm, pi0);
275 
276  //Accessing pseudo header
277  pheader0 = vlib_buffer_get_current (p0);
278  vlib_buffer_advance (p0, sizeof (*pheader0));
279 
280  if (map_ip4_to_ip6_fragmented (p0, pheader0))
281  {
282  p0->error = error_node->errors[MAP_ERROR_FRAGMENT_DROPPED];
284  }
285  else
286  {
287  if (vnet_buffer (p0)->map_t.mtu < p0->current_length)
288  {
289  vnet_buffer (p0)->ip_frag.mtu = vnet_buffer (p0)->map_t.mtu;
290  vnet_buffer (p0)->ip_frag.next_index =
293  }
294  }
295 
296  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
297  to_next, n_left_to_next, pi0,
298  next0);
299  }
300  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
301  }
302  return frame->n_vectors;
303 }
304 
305 /*
306  * Translate IPv4 UDP/TCP packet to IPv6.
307  */
308 always_inline int
309 map_ip4_to_ip6_tcp_udp (vlib_buffer_t * p, ip4_mapt_pseudo_header_t * pheader)
310 {
311  map_main_t *mm = &map_main;
312  ip4_header_t *ip4;
313  ip6_header_t *ip6;
314  ip_csum_t csum;
315  u16 *checksum;
316  ip6_frag_hdr_t *frag;
317  u32 frag_id;
318  ip4_address_t old_src, old_dst;
319 
320  ip4 = vlib_buffer_get_current (p);
321 
322  if (ip4->protocol == IP_PROTOCOL_UDP)
323  {
324  udp_header_t *udp = ip4_next_header (ip4);
325  checksum = &udp->checksum;
326 
327  /*
328  * UDP checksum is optional over IPv4 but mandatory for IPv6 We
329  * do not check udp->length sanity but use our safe computed
330  * value instead
331  */
332  if (PREDICT_FALSE (!*checksum))
333  {
334  u16 udp_len = clib_host_to_net_u16 (ip4->length) - sizeof (*ip4);
335  csum = ip_incremental_checksum (0, udp, udp_len);
336  csum = ip_csum_with_carry (csum, clib_host_to_net_u16 (udp_len));
337  csum =
338  ip_csum_with_carry (csum, clib_host_to_net_u16 (IP_PROTOCOL_UDP));
339  csum = ip_csum_with_carry (csum, *((u64 *) (&ip4->src_address)));
340  *checksum = ~ip_csum_fold (csum);
341  }
342  }
343  else
344  {
345  tcp_header_t *tcp = ip4_next_header (ip4);
346  if (mm->tcp_mss > 0)
347  {
348  csum = tcp->checksum;
349  map_mss_clamping (tcp, &csum, mm->tcp_mss);
350  tcp->checksum = ip_csum_fold (csum);
351  }
352  checksum = &tcp->checksum;
353  }
354 
355  old_src.as_u32 = ip4->src_address.as_u32;
356  old_dst.as_u32 = ip4->dst_address.as_u32;
357 
358  /* Deal with fragmented packets */
360  clib_host_to_net_u16 (IP4_HEADER_FLAG_MORE_FRAGMENTS)))
361  {
362  ip6 =
363  (ip6_header_t *) u8_ptr_add (ip4,
364  sizeof (*ip4) - sizeof (*ip6) -
365  sizeof (*frag));
366  frag =
367  (ip6_frag_hdr_t *) u8_ptr_add (ip4, sizeof (*ip4) - sizeof (*frag));
368  frag_id = frag_id_4to6 (ip4->fragment_id);
369  vlib_buffer_advance (p, sizeof (*ip4) - sizeof (*ip6) - sizeof (*frag));
370  }
371  else
372  {
373  ip6 = (ip6_header_t *) (((u8 *) ip4) + sizeof (*ip4) - sizeof (*ip6));
374  vlib_buffer_advance (p, sizeof (*ip4) - sizeof (*ip6));
375  frag = NULL;
376  }
377 
379  clib_host_to_net_u32 ((6 << 28) + (ip4->tos << 20));
380  ip6->payload_length = u16_net_add (ip4->length, -sizeof (*ip4));
381  ip6->hop_limit = ip4->ttl;
382  ip6->protocol = ip4->protocol;
383  if (PREDICT_FALSE (frag != NULL))
384  {
385  frag->next_hdr = ip6->protocol;
386  frag->identification = frag_id;
387  frag->rsv = 0;
388  frag->fragment_offset_and_more = ip6_frag_hdr_offset_and_more (0, 1);
389  ip6->protocol = IP_PROTOCOL_IPV6_FRAGMENTATION;
390  ip6->payload_length = u16_net_add (ip6->payload_length, sizeof (*frag));
391  }
392 
393  ip6->dst_address.as_u64[0] = pheader->daddr.as_u64[0];
394  ip6->dst_address.as_u64[1] = pheader->daddr.as_u64[1];
395  ip6->src_address.as_u64[0] = pheader->saddr.as_u64[0];
396  ip6->src_address.as_u64[1] = pheader->saddr.as_u64[1];
397 
398  csum = ip_csum_sub_even (*checksum, old_src.as_u32);
399  csum = ip_csum_sub_even (csum, old_dst.as_u32);
400  csum = ip_csum_add_even (csum, ip6->src_address.as_u64[0]);
401  csum = ip_csum_add_even (csum, ip6->src_address.as_u64[1]);
402  csum = ip_csum_add_even (csum, ip6->dst_address.as_u64[0]);
403  csum = ip_csum_add_even (csum, ip6->dst_address.as_u64[1]);
404  *checksum = ip_csum_fold (csum);
405 
406  return 0;
407 }
408 
409 static uword
412 {
413  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
414  from = vlib_frame_vector_args (frame);
415  n_left_from = frame->n_vectors;
416  next_index = node->cached_next_index;
417  vlib_node_runtime_t *error_node =
418  vlib_node_get_runtime (vm, ip4_map_t_tcp_udp_node.index);
419 
420 
421  while (n_left_from > 0)
422  {
423  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
424 
425  while (n_left_from > 0 && n_left_to_next > 0)
426  {
427  u32 pi0;
428  vlib_buffer_t *p0;
429  ip4_mapt_pseudo_header_t *pheader0;
430  ip4_mapt_tcp_udp_next_t next0;
431 
432  pi0 = to_next[0] = from[0];
433  from += 1;
434  n_left_from -= 1;
435  to_next += 1;
436  n_left_to_next -= 1;
437 
439  p0 = vlib_get_buffer (vm, pi0);
440 
441  //Accessing pseudo header
442  pheader0 = vlib_buffer_get_current (p0);
443  vlib_buffer_advance (p0, sizeof (*pheader0));
444 
445  if (map_ip4_to_ip6_tcp_udp (p0, pheader0))
446  {
447  p0->error = error_node->errors[MAP_ERROR_UNKNOWN];
449  }
450  else
451  {
452  if (vnet_buffer (p0)->map_t.mtu < p0->current_length)
453  {
454  //Send to fragmentation node if necessary
455  vnet_buffer (p0)->ip_frag.mtu = vnet_buffer (p0)->map_t.mtu;
456  vnet_buffer (p0)->ip_frag.next_index =
459  }
460  }
461  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
462  to_next, n_left_to_next, pi0,
463  next0);
464  }
465  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
466  }
467 
468  return frame->n_vectors;
469 }
470 
473  ip4_header_t * ip40, u16 ip4_len0, i32 * dst_port0,
474  u8 * error0, ip4_mapt_next_t * next0, u16 l4_dst_port)
475 {
477  {
479  if (d0->ea_bits_len == 0 && d0->rules)
480  {
481  *dst_port0 = 0;
482  }
483  else
484  {
485  *dst_port0 = l4_dst_port;
486  *error0 = (*dst_port0 == -1) ? MAP_ERROR_FRAGMENT_MEMORY : *error0;
487  }
488  }
489  else if (PREDICT_TRUE (ip40->protocol == IP_PROTOCOL_TCP))
490  {
491  vnet_buffer (p0)->map_t.checksum_offset = 36;
493  *error0 = ip4_len0 < 40 ? MAP_ERROR_MALFORMED : *error0;
494  *dst_port0 = l4_dst_port;
495  }
496  else if (PREDICT_TRUE (ip40->protocol == IP_PROTOCOL_UDP))
497  {
498  vnet_buffer (p0)->map_t.checksum_offset = 26;
500  *error0 = ip4_len0 < 28 ? MAP_ERROR_MALFORMED : *error0;
501  *dst_port0 = l4_dst_port;
502  }
503  else if (ip40->protocol == IP_PROTOCOL_ICMP)
504  {
505  *next0 = IP4_MAPT_NEXT_MAPT_ICMP;
506  if (d0->ea_bits_len == 0 && d0->rules)
507  *dst_port0 = 0;
508  else if (((icmp46_header_t *) u8_ptr_add (ip40, sizeof (*ip40)))->code
509  == ICMP4_echo_reply
510  || ((icmp46_header_t *)
511  u8_ptr_add (ip40,
512  sizeof (*ip40)))->code == ICMP4_echo_request)
513  *dst_port0 = l4_dst_port;
514  }
515  else
516  {
517  *error0 = MAP_ERROR_BAD_PROTOCOL;
518  }
519 }
520 
521 static uword
523 {
524  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
525  vlib_node_runtime_t *error_node =
526  vlib_node_get_runtime (vm, ip4_map_t_node.index);
527  from = vlib_frame_vector_args (frame);
528  n_left_from = frame->n_vectors;
529  next_index = node->cached_next_index;
531  u32 thread_index = vm->thread_index;
532 
533  while (n_left_from > 0)
534  {
535  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
536 
537  while (n_left_from > 0 && n_left_to_next > 0)
538  {
539  u32 pi0;
540  vlib_buffer_t *p0;
541  ip4_header_t *ip40;
542  map_domain_t *d0;
543  ip4_mapt_next_t next0 = 0;
544  u16 ip4_len0;
545  u8 error0;
546  i32 dst_port0;
547  ip4_mapt_pseudo_header_t *pheader0;
548 
549  pi0 = to_next[0] = from[0];
550  from += 1;
551  n_left_from -= 1;
552  to_next += 1;
553  n_left_to_next -= 1;
554  error0 = MAP_ERROR_NONE;
555 
556  p0 = vlib_get_buffer (vm, pi0);
557 
558  u16 l4_dst_port = vnet_buffer (p0)->ip.reass.l4_dst_port;
559 
560  ip40 = vlib_buffer_get_current (p0);
561  ip4_len0 = clib_host_to_net_u16 (ip40->length);
562  if (PREDICT_FALSE (p0->current_length < ip4_len0 ||
563  ip40->ip_version_and_header_length != 0x45))
564  {
565  error0 = MAP_ERROR_UNKNOWN;
566  }
567 
568  d0 = ip4_map_get_domain (&ip40->dst_address,
569  &vnet_buffer (p0)->map_t.map_domain_index,
570  &error0);
571 
572  if (!d0)
573  { /* Guess it wasn't for us */
574  vnet_feature_next (&next0, p0);
575  goto exit;
576  }
577 
578  bool df0 =
580  clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT);
581 
582  if (PREDICT_FALSE
583  (df0 && !map_main.frag_ignore_df && (ip4_len0 > d0->mtu)))
584  {
585  p0->error = error_node->errors[MAP_ERROR_FRAGMENT_DROPPED];
586  next0 = IP4_MAPT_NEXT_DROP;
587  goto exit;
588  }
589 
590  vnet_buffer (p0)->map_t.mtu = d0->mtu ? d0->mtu : ~0;
591 
592  dst_port0 = -1;
593  ip4_map_t_classify (p0, d0, ip40, ip4_len0, &dst_port0, &error0,
594  &next0, l4_dst_port);
595 
596  /* Verify that port is not among the well-known ports */
597  if ((d0->psid_length > 0 && d0->psid_offset > 0)
598  && (clib_net_to_host_u16 (dst_port0) <
599  (0x1 << (16 - d0->psid_offset))))
600  {
601  error0 = MAP_ERROR_SEC_CHECK;
602  }
603 
604  //Add MAP-T pseudo header in front of the packet
605  vlib_buffer_advance (p0, -sizeof (*pheader0));
606  pheader0 = vlib_buffer_get_current (p0);
607 
608  //Save addresses within the packet
609  ip4_map_t_embedded_address (d0, &pheader0->saddr,
610  &ip40->src_address);
611  pheader0->daddr.as_u64[0] =
612  map_get_pfx_net (d0, ip40->dst_address.as_u32, (u16) dst_port0);
613  pheader0->daddr.as_u64[1] =
614  map_get_sfx_net (d0, ip40->dst_address.as_u32, (u16) dst_port0);
615 
616  if (PREDICT_TRUE
617  (error0 == MAP_ERROR_NONE && next0 != IP4_MAPT_NEXT_MAPT_ICMP))
618  {
620  thread_index,
621  vnet_buffer (p0)->
622  map_t.map_domain_index, 1,
623  clib_net_to_host_u16
624  (ip40->length));
625  }
626 
627  next0 = (error0 != MAP_ERROR_NONE) ? IP4_MAPT_NEXT_DROP : next0;
628  p0->error = error_node->errors[error0];
629 
630  if (PREDICT_FALSE (p0->flags & VLIB_BUFFER_IS_TRACED))
631  {
632  map_add_trace (vm, node, p0, d0 - map_main.domains, dst_port0);
633  }
634  exit:
635  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
636  to_next, n_left_to_next, pi0,
637  next0);
638  }
639  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
640  }
641  return frame->n_vectors;
642 }
643 
644 static char *map_t_error_strings[] = {
645 #define _(sym,string) string,
647 #undef _
648 };
649 
650 /* *INDENT-OFF* */
651 VNET_FEATURE_INIT (ip4_map_t_feature, static) = {
652  .arc_name = "ip4-unicast",
653  .node_name = "ip4-map-t",
654  .runs_before = VNET_FEATURES ("ip4-flow-classify"),
655  .runs_after = VNET_FEATURES ("ip4-sv-reassembly-feature"),
656 };
657 
658 VLIB_REGISTER_NODE(ip4_map_t_fragmented_node) = {
659  .function = ip4_map_t_fragmented,
660  .name = "ip4-map-t-fragmented",
661  .vector_size = sizeof(u32),
662  .format_trace = format_map_trace,
664 
665  .n_errors = MAP_N_ERROR,
666  .error_strings = map_t_error_strings,
667 
668  .n_next_nodes = IP4_MAPT_FRAGMENTED_N_NEXT,
669  .next_nodes = {
670  [IP4_MAPT_FRAGMENTED_NEXT_IP6_LOOKUP] = "ip6-lookup",
672  [IP4_MAPT_FRAGMENTED_NEXT_DROP] = "error-drop",
673  },
674 };
675 /* *INDENT-ON* */
676 
677 /* *INDENT-OFF* */
678 VLIB_REGISTER_NODE(ip4_map_t_icmp_node) = {
679  .function = ip4_map_t_icmp,
680  .name = "ip4-map-t-icmp",
681  .vector_size = sizeof(u32),
682  .format_trace = format_map_trace,
684 
685  .n_errors = MAP_N_ERROR,
686  .error_strings = map_t_error_strings,
687 
688  .n_next_nodes = IP4_MAPT_ICMP_N_NEXT,
689  .next_nodes = {
690  [IP4_MAPT_ICMP_NEXT_IP6_LOOKUP] = "ip6-lookup",
692  [IP4_MAPT_ICMP_NEXT_DROP] = "error-drop",
693  },
694 };
695 /* *INDENT-ON* */
696 
697 /* *INDENT-OFF* */
698 VLIB_REGISTER_NODE(ip4_map_t_tcp_udp_node) = {
699  .function = ip4_map_t_tcp_udp,
700  .name = "ip4-map-t-tcp-udp",
701  .vector_size = sizeof(u32),
702  .format_trace = format_map_trace,
704 
705  .n_errors = MAP_N_ERROR,
706  .error_strings = map_t_error_strings,
707 
708  .n_next_nodes = IP4_MAPT_TCP_UDP_N_NEXT,
709  .next_nodes = {
710  [IP4_MAPT_TCP_UDP_NEXT_IP6_LOOKUP] = "ip6-lookup",
712  [IP4_MAPT_TCP_UDP_NEXT_DROP] = "error-drop",
713  },
714 };
715 /* *INDENT-ON* */
716 
717 /* *INDENT-OFF* */
718 VLIB_REGISTER_NODE(ip4_map_t_node) = {
719  .function = ip4_map_t,
720  .name = "ip4-map-t",
721  .vector_size = sizeof(u32),
722  .format_trace = format_map_trace,
724 
725  .n_errors = MAP_N_ERROR,
726  .error_strings = map_t_error_strings,
727 
728  .n_next_nodes = IP4_MAPT_N_NEXT,
729  .next_nodes = {
730  [IP4_MAPT_NEXT_MAPT_TCP_UDP] = "ip4-map-t-tcp-udp",
731  [IP4_MAPT_NEXT_MAPT_ICMP] = "ip4-map-t-icmp",
732  [IP4_MAPT_NEXT_MAPT_FRAGMENTED] = "ip4-map-t-fragmented",
733  [IP4_MAPT_NEXT_DROP] = "error-drop",
734  },
735 };
736 /* *INDENT-ON* */
737 
738 /*
739  * fd.io coding-style-patch-verification: ON
740  *
741  * Local Variables:
742  * eval: (c-set-style "gnu")
743  * End:
744  */
ip4_mapt_tcp_udp_next_t
Definition: ip4_map_t.c:37
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
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:247
u8 psid_length
Definition: map.h:88
VNET_FEATURE_INIT(ip4_map_t_feature, static)
map_main_t map_main
Definition: map.c:27
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
ip4_address_t src_address
Definition: ip4_packet.h:170
#define IP6_FRAG_NODE_NAME
Definition: ip_frag.h:44
#define PREDICT_TRUE(x)
Definition: clib.h:112
u64 as_u64[2]
Definition: ip6_packet.h:51
unsigned long u64
Definition: types.h:89
#define NULL
Definition: clib.h:58
u32 thread_index
Definition: main.h:218
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
static_always_inline map_domain_t * ip4_map_get_domain(ip4_address_t *addr, u32 *map_domain_index, u8 *error)
Definition: map.h:339
ip4_mapt_next_t
Definition: ip4_map_t.c:20
uword ip_csum_t
Definition: ip_packet.h:244
static ip_csum_t ip_csum_with_carry(ip_csum_t sum, ip_csum_t x)
Definition: ip_packet.h:247
u16 flags_and_fragment_offset
Definition: ip4_packet.h:151
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:470
struct _tcp_header tcp_header_t
ip6_address_t src_address
Definition: ip6_packet.h:307
unsigned char u8
Definition: types.h:56
IPv4 to IPv6 translation.
static_always_inline void ip4_map_t_classify(vlib_buffer_t *p0, map_domain_t *d0, ip4_header_t *ip40, u16 ip4_len0, i32 *dst_port0, u8 *error0, ip4_mapt_next_t *next0, u16 l4_dst_port)
Definition: ip4_map_t.c:472
static uword ip4_map_t_icmp(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_map_t.c:104
static uword ip4_map_t(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_map_t.c:522
static_always_inline void ip4_map_t_embedded_address(map_domain_t *d, ip6_address_t *ip6, const ip4_address_t *ip4)
Definition: map.h:382
#define u8_ptr_add(ptr, index)
Definition: ip_types.h:34
#define static_always_inline
Definition: clib.h:99
ip4_address_t dst_address
Definition: ip4_packet.h:170
vlib_combined_counter_main_t * domain_counters
Definition: map.h:169
ip4_mapt_fragmented_next_t
Definition: ip4_map_t.c:45
ip6_address_t * rules
Definition: map.h:78
#define frag_id_4to6(id)
Definition: ip4_to_ip6.h:40
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:241
u8 ea_bits_len
Definition: map.h:86
unsigned int u32
Definition: types.h:88
static u16 ip4_get_port(ip4_header_t *ip, u8 sender)
Get TCP/UDP port number or ICMP id from IPv4 packet.
Definition: ip4_to_ip6.h:51
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
vnet_crypto_main_t * cm
Definition: quic_crypto.c:41
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:519
bool frag_ignore_df
Definition: map.h:194
long ctx[MAX_CONNS]
Definition: main.c:144
static_always_inline u64 map_get_pfx_net(map_domain_t *d, u32 addr, u16 port)
Definition: map.h:289
unsigned short u16
Definition: types.h:57
map_domain_t * domains
Definition: map.h:164
static_always_inline u64 map_get_sfx_net(map_domain_t *d, u32 addr, u16 port)
Definition: map.h:321
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
#define PREDICT_FALSE(x)
Definition: clib.h:111
#define always_inline
Definition: ipsec.h:28
#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:218
#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:338
vlib_main_t * vm
Definition: in2out_ed.c:1810
static int ip4_to_ip6_set_icmp_cb(vlib_buffer_t *b, ip4_header_t *ip4, ip6_header_t *ip6, void *arg)
Definition: ip4_map_t.c:72
u8 ip6[16]
Definition: one.api:477
#define IP4_HEADER_FLAG_MORE_FRAGMENTS
Definition: ip4_packet.h:152
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
icmp_to_icmp6_ctx_t
Definition: ip4_map_t.c:69
u16 n_vectors
Definition: node.h:397
ip4_mapt_icmp_next_t
Definition: ip4_map_t.c:29
static int map_ip4_to_ip6_fragmented(vlib_buffer_t *p, ip4_mapt_pseudo_header_t *pheader)
Definition: ip4_map_t.c:202
static u16 ip4_get_fragment_offset(const ip4_header_t *i)
Definition: ip4_packet.h:200
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:302
typedef CLIB_PACKED(struct { ip6_address_t daddr;ip6_address_t saddr;u8 unused[28];})
Definition: ip4_map_t.c:56
u8 psid_offset
Definition: map.h:87
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:89
static int map_ip4_to_ip6_tcp_udp(vlib_buffer_t *p, ip4_mapt_pseudo_header_t *pheader)
Definition: ip4_map_t.c:309
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:456
#define foreach_map_error
Definition: map.h:211
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1810
signed int i32
Definition: types.h:77
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:515
ip_dscp_t tos
Definition: ip4_packet.h:141
static ip_csum_t ip_csum_sub_even(ip_csum_t c, ip_csum_t x)
Definition: ip_packet.h:272
static int icmp_to_icmp6(vlib_buffer_t *p, ip4_to_ip6_set_fn_t fn, void *ctx, ip4_to_ip6_set_fn_t inner_fn, void *inner_ctx)
Translate ICMP4 packet to ICMP6.
Definition: ip4_to_ip6.h:220
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:248
u8 * format_map_trace(u8 *s, va_list *args)
Definition: map.c:1203
#define VNET_FEATURES(...)
Definition: feature.h:442
static_always_inline void map_mss_clamping(tcp_header_t *tcp, ip_csum_t *sum, u16 mss_clamping)
Definition: map.h:448
u32 ip_version_traffic_class_and_flow_label
Definition: ip6_packet.h:294
u16 mtu
Definition: map.h:82
u16 payload_length
Definition: ip6_packet.h:298
static uword ip4_map_t_tcp_udp(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_map_t.c:410
static uword ip4_map_t_fragmented(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_map_t.c:246
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
u16 tcp_mss
Definition: map.h:183
A collection of combined counters.
Definition: counter.h:188
#define vnet_buffer(b)
Definition: buffer.h:408
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1811
#define IP4_HEADER_FLAG_DONT_FRAGMENT
Definition: ip4_packet.h:153
static int ip4_to_ip6_set_inner_icmp_cb(vlib_buffer_t *b, ip4_header_t *ip4, ip6_header_t *ip6, void *arg)
Definition: ip4_map_t.c:87
#define u16_net_add(u, val)
Definition: ip_types.h:35
#define ip6_frag_hdr_offset_and_more(offset, more)
Definition: ip6_packet.h:670
u8 ip_version_and_header_length
Definition: ip4_packet.h:138
u32 ip4
Definition: one.api:440
static ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
Definition: ip_packet.h:318
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:300
static ip_csum_t ip_csum_add_even(ip_csum_t c, ip_csum_t x)
Definition: ip_packet.h:255
ip6_address_t dst_address
Definition: ip6_packet.h:307