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