FD.io VPP  v21.06-3-gbb25fbf28
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 {
29 
30 typedef enum
31 {
38 
39 typedef enum
40 {
47 
48 typedef enum
49 {
56 
57 //This is used to pass information within the buffer data.
58 //Buffer structure being too small to contain big structures like this.
59 /* *INDENT-OFF* */
60 typedef CLIB_PACKED (struct {
61  ip6_address_t daddr;
62  ip6_address_t saddr;
63  //IPv6 header + Fragmentation header will be here
64  //sizeof(ip6) + sizeof(ip_frag) - sizeof(ip4)
65  u8 unused[28];
66 }) ip4_mapt_pseudo_header_t;
67 /* *INDENT-ON* */
68 
69 typedef struct
70 {
71  map_domain_t *d;
72  u16 recv_port;
74 
75 static int
77  ip6_header_t * ip6, void *arg)
78 {
79  icmp_to_icmp6_ctx_t *ctx = arg;
80 
81  ip4_map_t_embedded_address (ctx->d, &ip6->src_address, &ip4->src_address);
82  ip6->dst_address.as_u64[0] =
83  map_get_pfx_net (ctx->d, ip4->dst_address.as_u32, ctx->recv_port);
84  ip6->dst_address.as_u64[1] =
85  map_get_sfx_net (ctx->d, ip4->dst_address.as_u32, ctx->recv_port);
86 
87  return 0;
88 }
89 
90 static int
92  ip6_header_t * ip6, void *arg)
93 {
94  icmp_to_icmp6_ctx_t *ctx = arg;
95  ip4_address_t old_src, old_dst;
96 
97  old_src.as_u32 = ip4->src_address.as_u32;
98  old_dst.as_u32 = ip4->dst_address.as_u32;
99 
100  //Note that the source address is within the domain
101  //while the destination address is the one outside the domain
102  ip4_map_t_embedded_address (ctx->d, &ip6->dst_address, &old_dst);
103  ip6->src_address.as_u64[0] =
104  map_get_pfx_net (ctx->d, old_src.as_u32, ctx->recv_port);
105  ip6->src_address.as_u64[1] =
106  map_get_sfx_net (ctx->d, old_src.as_u32, ctx->recv_port);
107 
108  return 0;
109 }
110 
111 static uword
114 {
115  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
116  vlib_node_runtime_t *error_node =
119  n_left_from = frame->n_vectors;
120  next_index = node->cached_next_index;
123 
124  while (n_left_from > 0)
125  {
126  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
127 
128  while (n_left_from > 0 && n_left_to_next > 0)
129  {
130  u32 pi0;
131  vlib_buffer_t *p0;
132  ip4_mapt_icmp_next_t next0;
133  u8 error0;
134  map_domain_t *d0;
135  u16 len0;
136  icmp_to_icmp6_ctx_t ctx0;
137  ip4_header_t *ip40;
138 
140  pi0 = to_next[0] = from[0];
141  from += 1;
142  n_left_from -= 1;
143  to_next += 1;
144  n_left_to_next -= 1;
145  error0 = MAP_ERROR_NONE;
146 
147  p0 = vlib_get_buffer (vm, pi0);
148  vlib_buffer_advance (p0, sizeof (ip4_mapt_pseudo_header_t)); //The pseudo-header is not used
149  len0 =
150  clib_net_to_host_u16 (((ip4_header_t *)
152  d0 =
154  vnet_buffer (p0)->map_t.map_domain_index);
155 
156  ip40 = vlib_buffer_get_current (p0);
157  ctx0.recv_port = ip4_get_port (ip40, 0);
158  ctx0.d = d0;
159  if (ctx0.recv_port == 0)
160  {
161  // In case of 1:1 mapping, we don't care about the port
162  if (!(d0->ea_bits_len == 0 && d0->rules))
163  {
164  error0 = MAP_ERROR_ICMP;
165  goto err0;
166  }
167  }
168 
169  if (icmp_to_icmp6
170  (p0, ip4_to_ip6_set_icmp_cb, &ctx0,
172  {
173  error0 = MAP_ERROR_ICMP;
174  goto err0;
175  }
176 
177  if (vnet_buffer (p0)->map_t.mtu < p0->current_length)
178  {
179  vnet_buffer (p0)->ip_frag.mtu = vnet_buffer (p0)->map_t.mtu;
180  vnet_buffer (p0)->ip_frag.next_index = IP_FRAG_NEXT_IP6_LOOKUP;
182  }
183  else
184  {
185  next0 = ip4_map_ip6_lookup_bypass (p0, NULL) ?
187  }
188  err0:
189  if (PREDICT_TRUE (error0 == MAP_ERROR_NONE))
190  {
192  thread_index,
193  vnet_buffer (p0)->
194  map_t.map_domain_index, 1,
195  len0);
196  }
197  else
198  {
199  next0 = IP4_MAPT_ICMP_NEXT_DROP;
200  }
201  p0->error = error_node->errors[error0];
203  to_next, n_left_to_next, pi0,
204  next0);
205  }
206  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
207  }
208  return frame->n_vectors;
209 }
210 
211 /*
212  * Translate fragmented IPv4 UDP/TCP packet to IPv6.
213  */
214 always_inline int
216  ip4_mapt_pseudo_header_t * pheader)
217 {
218  ip4_header_t *ip4;
219  ip6_header_t *ip6;
220  ip6_frag_hdr_t *frag;
221 
223  frag = (ip6_frag_hdr_t *) u8_ptr_add (ip4, sizeof (*ip4) - sizeof (*frag));
224  ip6 =
226  sizeof (*ip4) - sizeof (*frag) -
227  sizeof (*ip6));
228  vlib_buffer_advance (p, sizeof (*ip4) - sizeof (*ip6) - sizeof (*frag));
229 
230  //We know that the protocol was one of ICMP, TCP or UDP
231  //because the first fragment was found and cached
232  frag->next_hdr =
233  (ip4->protocol == IP_PROTOCOL_ICMP) ? IP_PROTOCOL_ICMP6 : ip4->protocol;
234  frag->identification = frag_id_4to6 (ip4->fragment_id);
235  frag->rsv = 0;
236  frag->fragment_offset_and_more =
238  clib_net_to_host_u16
239  (ip4->flags_and_fragment_offset) &
241 
242  ip6->ip_version_traffic_class_and_flow_label =
243  clib_host_to_net_u32 ((6 << 28) + (ip4->tos << 20));
244  ip6->payload_length =
245  clib_host_to_net_u16 (clib_net_to_host_u16 (ip4->length) -
246  sizeof (*ip4) + sizeof (*frag));
247  ip6->hop_limit = ip4->ttl;
248  ip6->protocol = IP_PROTOCOL_IPV6_FRAGMENTATION;
249 
250  ip6->dst_address.as_u64[0] = pheader->daddr.as_u64[0];
251  ip6->dst_address.as_u64[1] = pheader->daddr.as_u64[1];
252  ip6->src_address.as_u64[0] = pheader->saddr.as_u64[0];
253  ip6->src_address.as_u64[1] = pheader->saddr.as_u64[1];
254 
255  return 0;
256 }
257 
258 static uword
261 {
262  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
264  n_left_from = frame->n_vectors;
265  next_index = node->cached_next_index;
266  vlib_node_runtime_t *error_node =
268 
269  while (n_left_from > 0)
270  {
271  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
272 
273  while (n_left_from > 0 && n_left_to_next > 0)
274  {
275  u32 pi0;
276  vlib_buffer_t *p0;
277  ip4_mapt_pseudo_header_t *pheader0;
279 
281  pi0 = to_next[0] = from[0];
282  from += 1;
283  n_left_from -= 1;
284  to_next += 1;
285  n_left_to_next -= 1;
286 
287  p0 = vlib_get_buffer (vm, pi0);
288 
289  //Accessing pseudo header
290  pheader0 = vlib_buffer_get_current (p0);
291  vlib_buffer_advance (p0, sizeof (*pheader0));
292 
293  if (map_ip4_to_ip6_fragmented (p0, pheader0))
294  {
295  p0->error = error_node->errors[MAP_ERROR_FRAGMENT_DROPPED];
297  }
298  else
299  {
300  if (vnet_buffer (p0)->map_t.mtu < p0->current_length)
301  {
302  vnet_buffer (p0)->ip_frag.mtu = vnet_buffer (p0)->map_t.mtu;
303  vnet_buffer (p0)->ip_frag.next_index =
306  }
307  else
308  {
309  next0 = ip4_map_ip6_lookup_bypass (p0, NULL) ?
311  }
312  }
313 
315  to_next, n_left_to_next, pi0,
316  next0);
317  }
318  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
319  }
320  return frame->n_vectors;
321 }
322 
323 /*
324  * Translate IPv4 UDP/TCP packet to IPv6.
325  */
326 always_inline int
327 map_ip4_to_ip6_tcp_udp (vlib_buffer_t * p, ip4_mapt_pseudo_header_t * pheader)
328 {
329  map_main_t *mm = &map_main;
330  ip4_header_t *ip4;
331  ip6_header_t *ip6;
332  ip_csum_t csum;
333  u16 *checksum;
334  ip6_frag_hdr_t *frag;
335  u32 frag_id;
336  ip4_address_t old_src, old_dst;
337 
339 
340  if (ip4->protocol == IP_PROTOCOL_UDP)
341  {
343  checksum = &udp->checksum;
344 
345  /*
346  * UDP checksum is optional over IPv4 but mandatory for IPv6 We
347  * do not check udp->length sanity but use our safe computed
348  * value instead
349  */
350  if (PREDICT_FALSE (!*checksum))
351  {
352  u16 udp_len = clib_host_to_net_u16 (ip4->length) - sizeof (*ip4);
353  csum = ip_incremental_checksum (0, udp, udp_len);
354  csum = ip_csum_with_carry (csum, clib_host_to_net_u16 (udp_len));
355  csum =
356  ip_csum_with_carry (csum, clib_host_to_net_u16 (IP_PROTOCOL_UDP));
357  csum = ip_csum_with_carry (csum, *((u64 *) (&ip4->src_address)));
358  *checksum = ~ip_csum_fold (csum);
359  }
360  }
361  else
362  {
364  if (mm->tcp_mss > 0)
365  {
366  csum = tcp->checksum;
367  map_mss_clamping (tcp, &csum, mm->tcp_mss);
368  tcp->checksum = ip_csum_fold (csum);
369  }
370  checksum = &tcp->checksum;
371  }
372 
373  old_src.as_u32 = ip4->src_address.as_u32;
374  old_dst.as_u32 = ip4->dst_address.as_u32;
375 
376  /* Deal with fragmented packets */
377  if (PREDICT_FALSE (ip4->flags_and_fragment_offset &
378  clib_host_to_net_u16 (IP4_HEADER_FLAG_MORE_FRAGMENTS)))
379  {
380  ip6 =
382  sizeof (*ip4) - sizeof (*ip6) -
383  sizeof (*frag));
384  frag =
385  (ip6_frag_hdr_t *) u8_ptr_add (ip4, sizeof (*ip4) - sizeof (*frag));
386  frag_id = frag_id_4to6 (ip4->fragment_id);
387  vlib_buffer_advance (p, sizeof (*ip4) - sizeof (*ip6) - sizeof (*frag));
388  }
389  else
390  {
391  ip6 = (ip6_header_t *) (((u8 *) ip4) + sizeof (*ip4) - sizeof (*ip6));
392  vlib_buffer_advance (p, sizeof (*ip4) - sizeof (*ip6));
393  frag = NULL;
394  }
395 
396  ip6->ip_version_traffic_class_and_flow_label =
397  clib_host_to_net_u32 ((6 << 28) + (ip4->tos << 20));
398  ip6->payload_length = u16_net_add (ip4->length, -sizeof (*ip4));
399  ip6->hop_limit = ip4->ttl;
400  ip6->protocol = ip4->protocol;
401  if (PREDICT_FALSE (frag != NULL))
402  {
403  frag->next_hdr = ip6->protocol;
404  frag->identification = frag_id;
405  frag->rsv = 0;
406  frag->fragment_offset_and_more = ip6_frag_hdr_offset_and_more (0, 1);
407  ip6->protocol = IP_PROTOCOL_IPV6_FRAGMENTATION;
408  ip6->payload_length = u16_net_add (ip6->payload_length, sizeof (*frag));
409  }
410 
411  ip6->dst_address.as_u64[0] = pheader->daddr.as_u64[0];
412  ip6->dst_address.as_u64[1] = pheader->daddr.as_u64[1];
413  ip6->src_address.as_u64[0] = pheader->saddr.as_u64[0];
414  ip6->src_address.as_u64[1] = pheader->saddr.as_u64[1];
415 
416  csum = ip_csum_sub_even (*checksum, old_src.as_u32);
417  csum = ip_csum_sub_even (csum, old_dst.as_u32);
418  csum = ip_csum_add_even (csum, ip6->src_address.as_u64[0]);
419  csum = ip_csum_add_even (csum, ip6->src_address.as_u64[1]);
420  csum = ip_csum_add_even (csum, ip6->dst_address.as_u64[0]);
421  csum = ip_csum_add_even (csum, ip6->dst_address.as_u64[1]);
422  *checksum = ip_csum_fold (csum);
423 
424  return 0;
425 }
426 
427 static uword
430 {
431  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
433  n_left_from = frame->n_vectors;
434  next_index = node->cached_next_index;
435  vlib_node_runtime_t *error_node =
437 
438 
439  while (n_left_from > 0)
440  {
441  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
442 
443  while (n_left_from > 0 && n_left_to_next > 0)
444  {
445  u32 pi0;
446  vlib_buffer_t *p0;
447  ip4_mapt_pseudo_header_t *pheader0;
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;
455 
457  p0 = vlib_get_buffer (vm, pi0);
458 
459  //Accessing pseudo header
460  pheader0 = vlib_buffer_get_current (p0);
461  vlib_buffer_advance (p0, sizeof (*pheader0));
462 
463  if (map_ip4_to_ip6_tcp_udp (p0, pheader0))
464  {
465  p0->error = error_node->errors[MAP_ERROR_UNKNOWN];
467  }
468  else
469  {
470  if (vnet_buffer (p0)->map_t.mtu < p0->current_length)
471  {
472  //Send to fragmentation node if necessary
473  vnet_buffer (p0)->ip_frag.mtu = vnet_buffer (p0)->map_t.mtu;
474  vnet_buffer (p0)->ip_frag.next_index =
477  }
478  else
479  {
480  next0 = ip4_map_ip6_lookup_bypass (p0, NULL) ?
482  }
483  }
485  to_next, n_left_to_next, pi0,
486  next0);
487  }
488  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
489  }
490 
491  return frame->n_vectors;
492 }
493 
496  ip4_header_t * ip40, u16 ip4_len0, i32 * dst_port0,
497  u8 * error0, ip4_mapt_next_t * next0, u16 l4_dst_port)
498 {
500  {
502  if (d0->ea_bits_len == 0 && d0->rules)
503  {
504  *dst_port0 = 0;
505  }
506  else
507  {
508  *dst_port0 = l4_dst_port;
509  *error0 = (*dst_port0 == -1) ? MAP_ERROR_FRAGMENT_MEMORY : *error0;
510  }
511  }
512  else if (PREDICT_TRUE (ip40->protocol == IP_PROTOCOL_TCP))
513  {
514  vnet_buffer (p0)->map_t.checksum_offset = 36;
516  *error0 = ip4_len0 < 40 ? MAP_ERROR_MALFORMED : *error0;
517  *dst_port0 = l4_dst_port;
518  }
519  else if (PREDICT_TRUE (ip40->protocol == IP_PROTOCOL_UDP))
520  {
521  vnet_buffer (p0)->map_t.checksum_offset = 26;
523  *error0 = ip4_len0 < 28 ? MAP_ERROR_MALFORMED : *error0;
524  *dst_port0 = l4_dst_port;
525  }
526  else if (ip40->protocol == IP_PROTOCOL_ICMP)
527  {
528  *next0 = IP4_MAPT_NEXT_MAPT_ICMP;
529  if (d0->ea_bits_len == 0 && d0->rules)
530  *dst_port0 = 0;
531  else if (((icmp46_header_t *) u8_ptr_add (ip40, sizeof (*ip40)))->type
532  == ICMP4_echo_reply
533  || ((icmp46_header_t *)
534  u8_ptr_add (ip40,
535  sizeof (*ip40)))->type == ICMP4_echo_request)
536  *dst_port0 = l4_dst_port;
537  }
538  else
539  {
540  *error0 = MAP_ERROR_BAD_PROTOCOL;
541  }
542 }
543 
544 static uword
546 {
547  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
548  vlib_node_runtime_t *error_node =
551  n_left_from = frame->n_vectors;
552  next_index = node->cached_next_index;
555 
556  while (n_left_from > 0)
557  {
558  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
559 
560  while (n_left_from > 0 && n_left_to_next > 0)
561  {
562  u32 pi0;
563  vlib_buffer_t *p0;
564  ip4_header_t *ip40;
565  map_domain_t *d0;
566  ip4_mapt_next_t next0 = 0;
567  u16 ip4_len0;
568  u8 error0;
569  i32 dst_port0;
570  ip4_mapt_pseudo_header_t *pheader0;
571 
572  pi0 = to_next[0] = from[0];
573  from += 1;
574  n_left_from -= 1;
575  to_next += 1;
576  n_left_to_next -= 1;
577  error0 = MAP_ERROR_NONE;
578 
579  p0 = vlib_get_buffer (vm, pi0);
580 
581  u16 l4_dst_port = vnet_buffer (p0)->ip.reass.l4_dst_port;
582 
583  ip40 = vlib_buffer_get_current (p0);
584  ip4_len0 = clib_host_to_net_u16 (ip40->length);
585  if (PREDICT_FALSE (p0->current_length < ip4_len0 ||
586  ip40->ip_version_and_header_length != 0x45))
587  {
588  error0 = MAP_ERROR_UNKNOWN;
589  }
590 
591  d0 = ip4_map_get_domain (&ip40->dst_address,
592  &vnet_buffer (p0)->map_t.map_domain_index,
593  &error0);
594 
595  if (!d0)
596  { /* Guess it wasn't for us */
597  vnet_feature_next (&next0, p0);
598  goto exit;
599  }
600 
601  dst_port0 = -1;
602 
603  if (PREDICT_FALSE (ip40->ttl == 1))
604  {
605  icmp4_error_set_vnet_buffer (p0, ICMP4_time_exceeded,
606  ICMP4_time_exceeded_ttl_exceeded_in_transit,
607  0);
608  p0->error = error_node->errors[MAP_ERROR_TIME_EXCEEDED];
609  next0 = IP4_MAPT_NEXT_ICMP_ERROR;
610  goto trace;
611  }
612 
613  bool df0 =
615  clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT);
616 
617  vnet_buffer (p0)->map_t.mtu = d0->mtu ? d0->mtu : ~0;
618 
619  if (PREDICT_FALSE
620  (df0 && !map_main.frag_ignore_df
621  &&
622  ((ip4_len0 +
623  (sizeof (ip6_header_t) - sizeof (ip4_header_t))) >
624  vnet_buffer (p0)->map_t.mtu)))
625  {
626  icmp4_error_set_vnet_buffer (p0, ICMP4_destination_unreachable,
627  ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set,
628  vnet_buffer (p0)->map_t.mtu -
629  (sizeof (ip6_header_t) -
630  sizeof (ip4_header_t)));
631  p0->error = error_node->errors[MAP_ERROR_DF_SET];
632  next0 = IP4_MAPT_NEXT_ICMP_ERROR;
633  goto trace;
634  }
635 
636  ip4_map_t_classify (p0, d0, ip40, ip4_len0, &dst_port0, &error0,
637  &next0, l4_dst_port);
638 
639  /* Verify that port is not among the well-known ports */
640  if ((d0->psid_length > 0 && d0->psid_offset > 0)
641  && (clib_net_to_host_u16 (dst_port0) <
642  (0x1 << (16 - d0->psid_offset))))
643  {
644  error0 = MAP_ERROR_SEC_CHECK;
645  }
646 
647  //Add MAP-T pseudo header in front of the packet
648  vlib_buffer_advance (p0, -sizeof (*pheader0));
649  pheader0 = vlib_buffer_get_current (p0);
650 
651  //Save addresses within the packet
652  ip4_map_t_embedded_address (d0, &pheader0->saddr,
653  &ip40->src_address);
654  pheader0->daddr.as_u64[0] =
655  map_get_pfx_net (d0, ip40->dst_address.as_u32, (u16) dst_port0);
656  pheader0->daddr.as_u64[1] =
657  map_get_sfx_net (d0, ip40->dst_address.as_u32, (u16) dst_port0);
658 
659  if (PREDICT_TRUE
660  (error0 == MAP_ERROR_NONE && next0 != IP4_MAPT_NEXT_MAPT_ICMP))
661  {
663  thread_index,
664  vnet_buffer (p0)->
665  map_t.map_domain_index, 1,
666  clib_net_to_host_u16
667  (ip40->length));
668  }
669 
670  next0 = (error0 != MAP_ERROR_NONE) ? IP4_MAPT_NEXT_DROP : next0;
671  p0->error = error_node->errors[error0];
672  trace:
673  if (PREDICT_FALSE (p0->flags & VLIB_BUFFER_IS_TRACED))
674  {
675  map_add_trace (vm, node, p0, d0 - map_main.domains, dst_port0);
676  }
677  exit:
679  to_next, n_left_to_next, pi0,
680  next0);
681  }
682  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
683  }
684  return frame->n_vectors;
685 }
686 
687 /* *INDENT-OFF* */
688 VNET_FEATURE_INIT (ip4_map_t_feature, static) = {
689  .arc_name = "ip4-unicast",
690  .node_name = "ip4-map-t",
691  .runs_before = VNET_FEATURES ("ip4-flow-classify"),
692  .runs_after = VNET_FEATURES ("ip4-sv-reassembly-feature"),
693 };
694 
696  .function = ip4_map_t_fragmented,
697  .name = "ip4-map-t-fragmented",
698  .vector_size = sizeof(u32),
699  .format_trace = format_map_trace,
701 
702  .n_errors = MAP_N_ERROR,
703  .error_counters = map_error_counters,
704 
705  .n_next_nodes = IP4_MAPT_FRAGMENTED_N_NEXT,
706  .next_nodes = {
707  [IP4_MAPT_FRAGMENTED_NEXT_IP6_LOOKUP] = "ip6-lookup",
708  [IP4_MAPT_FRAGMENTED_NEXT_IP6_REWRITE] = "ip6-load-balance",
710  [IP4_MAPT_FRAGMENTED_NEXT_DROP] = "error-drop",
711  },
712 };
713 /* *INDENT-ON* */
714 
715 /* *INDENT-OFF* */
717  .function = ip4_map_t_icmp,
718  .name = "ip4-map-t-icmp",
719  .vector_size = sizeof(u32),
720  .format_trace = format_map_trace,
722 
723  .n_errors = MAP_N_ERROR,
724  .error_counters = map_error_counters,
725 
726  .n_next_nodes = IP4_MAPT_ICMP_N_NEXT,
727  .next_nodes = {
728  [IP4_MAPT_ICMP_NEXT_IP6_LOOKUP] = "ip6-lookup",
729  [IP4_MAPT_ICMP_NEXT_IP6_REWRITE] = "ip6-load-balance",
731  [IP4_MAPT_ICMP_NEXT_DROP] = "error-drop",
732  },
733 };
734 /* *INDENT-ON* */
735 
736 /* *INDENT-OFF* */
738  .function = ip4_map_t_tcp_udp,
739  .name = "ip4-map-t-tcp-udp",
740  .vector_size = sizeof(u32),
741  .format_trace = format_map_trace,
743 
744  .n_errors = MAP_N_ERROR,
745  .error_counters = map_error_counters,
746 
747  .n_next_nodes = IP4_MAPT_TCP_UDP_N_NEXT,
748  .next_nodes = {
749  [IP4_MAPT_TCP_UDP_NEXT_IP6_LOOKUP] = "ip6-lookup",
750  [IP4_MAPT_TCP_UDP_NEXT_IP6_REWRITE] = "ip6-load-balance",
752  [IP4_MAPT_TCP_UDP_NEXT_DROP] = "error-drop",
753  },
754 };
755 /* *INDENT-ON* */
756 
757 /* *INDENT-OFF* */
759  .function = ip4_map_t,
760  .name = "ip4-map-t",
761  .vector_size = sizeof(u32),
762  .format_trace = format_map_trace,
764 
765  .n_errors = MAP_N_ERROR,
766  .error_counters = map_error_counters,
767 
768  .n_next_nodes = IP4_MAPT_N_NEXT,
769  .next_nodes = {
770  [IP4_MAPT_NEXT_MAPT_TCP_UDP] = "ip4-map-t-tcp-udp",
771  [IP4_MAPT_NEXT_MAPT_ICMP] = "ip4-map-t-icmp",
772  [IP4_MAPT_NEXT_MAPT_FRAGMENTED] = "ip4-map-t-fragmented",
773  [IP4_MAPT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
774  [IP4_MAPT_NEXT_DROP] = "error-drop",
775  },
776 };
777 /* *INDENT-ON* */
778 
779 /*
780  * fd.io coding-style-patch-verification: ON
781  *
782  * Local Variables:
783  * eval: (c-set-style "gnu")
784  * End:
785  */
map_domain_t::rules
ip6_address_t * rules
Definition: map.h:82
trace
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
Definition: vlib_api_cli.c:899
ip4_map_t
static uword ip4_map_t(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_map_t.c:545
thread_index
u32 thread_index
Definition: nat44_ei_hairpinning.c:492
IP4_HEADER_FLAG_DONT_FRAGMENT
#define IP4_HEADER_FLAG_DONT_FRAGMENT
Definition: ip4_packet.h:108
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
ip4_map_t_tcp_udp_node
vlib_node_registration_t ip4_map_t_tcp_udp_node
(constructor) VLIB_REGISTER_NODE (ip4_map_t_tcp_udp_node)
Definition: ip4_map_t.c:737
ip4
vl_api_ip4_address_t ip4
Definition: one.api:376
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
map_domain_t::mtu
u16 mtu
Definition: map.h:86
IP4_MAPT_ICMP_NEXT_IP6_REWRITE
@ IP4_MAPT_ICMP_NEXT_IP6_REWRITE
Definition: ip4_map_t.c:33
ip4_mapt_tcp_udp_next_t
ip4_mapt_tcp_udp_next_t
Definition: ip4_map_t.c:39
IP4_MAPT_FRAGMENTED_N_NEXT
@ IP4_MAPT_FRAGMENTED_N_NEXT
Definition: ip4_map_t.c:54
tcp_header_t
struct _tcp_header tcp_header_t
VLIB_NODE_TYPE_INTERNAL
@ VLIB_NODE_TYPE_INTERNAL
Definition: node.h:72
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
IP4_MAPT_TCP_UDP_N_NEXT
@ IP4_MAPT_TCP_UDP_N_NEXT
Definition: ip4_map_t.c:45
ip4_address_t::as_u32
u32 as_u32
Definition: ip4_packet.h:57
ip6_frag_hdr_offset_and_more
#define ip6_frag_hdr_offset_and_more(offset, more)
Definition: ip6_packet.h:709
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
IP4_MAPT_NEXT_DROP
@ IP4_MAPT_NEXT_DROP
Definition: ip4_map_t.c:26
vlib_frame_t
Definition: node.h:372
ip4_map_t_classify
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:495
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
IP4_MAPT_NEXT_MAPT_FRAGMENTED
@ IP4_MAPT_NEXT_MAPT_FRAGMENTED
Definition: ip4_map_t.c:24
frag_id_4to6
#define frag_id_4to6(id)
Definition: ip4_to_ip6.h:40
ip4_map_t_node
vlib_node_registration_t ip4_map_t_node
(constructor) VLIB_REGISTER_NODE (ip4_map_t_node)
Definition: ip4_map_t.c:758
map_main
map_main_t map_main
Definition: map.c:27
CLIB_PACKED
typedef CLIB_PACKED(struct { ip6_address_t daddr;ip6_address_t saddr;u8 unused[28];})
Definition: ip4_map_t.c:60
ip4_header_t::length
u16 length
Definition: ip4_packet.h:99
i32
signed int i32
Definition: types.h:77
map_domain_t
Definition: map.h:76
IP4_MAPT_ICMP_NEXT_IP6_LOOKUP
@ IP4_MAPT_ICMP_NEXT_IP6_LOOKUP
Definition: ip4_map_t.c:32
ip4_get_port
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
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
ip4_mapt_next_t
ip4_mapt_next_t
Definition: ip4_map_t.c:20
vlib_node_runtime_t::errors
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:460
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
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
IP4_MAPT_TCP_UDP_NEXT_IP6_REWRITE
@ IP4_MAPT_TCP_UDP_NEXT_IP6_REWRITE
Definition: ip4_map_t.c:42
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:437
map_main_t
Definition: map.h:165
ip_incremental_checksum
static ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
Definition: ip_packet.h:319
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
IP4_MAPT_NEXT_MAPT_ICMP
@ IP4_MAPT_NEXT_MAPT_ICMP
Definition: ip4_map_t.c:23
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
ip4_get_fragment_offset
static u16 ip4_get_fragment_offset(const ip4_header_t *i)
Definition: ip4_packet.h:155
IP4_MAPT_NEXT_MAPT_TCP_UDP
@ IP4_MAPT_NEXT_MAPT_TCP_UDP
Definition: ip4_map_t.c:22
map_domain_t::psid_offset
u8 psid_offset
Definition: map.h:91
IP4_MAPT_ICMP_NEXT_IP6_FRAG
@ IP4_MAPT_ICMP_NEXT_IP6_FRAG
Definition: ip4_map_t.c:34
static_always_inline
#define static_always_inline
Definition: clib.h:112
ip4_map_t_tcp_udp
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:428
uword
u64 uword
Definition: types.h:112
IP4_MAPT_TCP_UDP_NEXT_IP6_LOOKUP
@ IP4_MAPT_TCP_UDP_NEXT_IP6_LOOKUP
Definition: ip4_map_t.c:41
IP4_MAPT_TCP_UDP_NEXT_IP6_FRAG
@ IP4_MAPT_TCP_UDP_NEXT_IP6_FRAG
Definition: ip4_map_t.c:43
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
ip4_map_t_icmp
static uword ip4_map_t_icmp(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_map_t.c:112
ip4_map_t_fragmented
static uword ip4_map_t_fragmented(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_map_t.c:259
map_ip4_to_ip6_fragmented
static int map_ip4_to_ip6_fragmented(vlib_buffer_t *p, ip4_mapt_pseudo_header_t *pheader)
Definition: ip4_map_t.c:215
cm
vnet_feature_config_main_t * cm
Definition: nat44_ei_hairpinning.c:591
ip4_address_t
Definition: ip4_packet.h:50
IP4_MAPT_FRAGMENTED_NEXT_IP6_LOOKUP
@ IP4_MAPT_FRAGMENTED_NEXT_IP6_LOOKUP
Definition: ip4_map_t.c:50
IP4_MAPT_N_NEXT
@ IP4_MAPT_N_NEXT
Definition: ip4_map_t.c:27
icmp_to_icmp6
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
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
ip4_to_ip6_set_inner_icmp_cb
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:91
IP6_FRAG_NODE_NAME
#define IP6_FRAG_NODE_NAME
Definition: ip_frag.h:44
ip4_header_t::dst_address
ip4_address_t dst_address
Definition: ip4_packet.h:125
vlib_buffer_t::current_length
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:122
map.h
icmp4_error_set_vnet_buffer
static_always_inline void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp4.h:51
ip_frag.h
ip4_to_ip6_set_icmp_cb
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:76
udp_header_t::checksum
u16 checksum
Definition: udp_packet.h:55
ip4_mapt_fragmented_next_t
ip4_mapt_fragmented_next_t
Definition: ip4_map_t.c:48
IP4_MAPT_NEXT_ICMP_ERROR
@ IP4_MAPT_NEXT_ICMP_ERROR
Definition: ip4_map_t.c:25
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
IP4_MAPT_FRAGMENTED_NEXT_IP6_REWRITE
@ IP4_MAPT_FRAGMENTED_NEXT_IP6_REWRITE
Definition: ip4_map_t.c:51
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
IP4_MAPT_FRAGMENTED_NEXT_IP6_FRAG
@ IP4_MAPT_FRAGMENTED_NEXT_IP6_FRAG
Definition: ip4_map_t.c:52
always_inline
#define always_inline
Definition: rdma_mlx5dv.h:23
ip4_header_t::src_address
ip4_address_t src_address
Definition: ip4_packet.h:125
IP_FRAG_NEXT_IP6_LOOKUP
@ IP_FRAG_NEXT_IP6_LOOKUP
Definition: ip_frag.h:54
IP4_MAPT_ICMP_NEXT_DROP
@ IP4_MAPT_ICMP_NEXT_DROP
Definition: ip4_map_t.c:35
u64
unsigned long u64
Definition: types.h:89
vlib_combined_counter_main_t
A collection of combined counters.
Definition: counter.h:203
map_ip4_to_ip6_tcp_udp
static int map_ip4_to_ip6_tcp_udp(vlib_buffer_t *p, ip4_mapt_pseudo_header_t *pheader)
Definition: ip4_map_t.c:327
vlib_put_next_frame
vlib_put_next_frame(vm, node, next_index, 0)
ip_csum_with_carry
static ip_csum_t ip_csum_with_carry(ip_csum_t sum, ip_csum_t x)
Definition: ip_packet.h:248
map_main_t::frag_ignore_df
bool frag_ignore_df
Definition: map.h:198
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
MAP_DOMAIN_COUNTER_TX
@ MAP_DOMAIN_COUNTER_TX
Definition: map.h:127
ip4_header_t::ttl
u8 ttl
Definition: ip4_packet.h:112
ip6
vl_api_ip6_address_t ip6
Definition: one.api:424
ctx
long ctx[MAX_CONNS]
Definition: main.c:144
ip4_map_ip6_lookup_bypass
static_always_inline bool ip4_map_ip6_lookup_bypass(vlib_buffer_t *p0, ip4_header_t *ip)
Definition: map.h:472
IP4_MAPT_FRAGMENTED_NEXT_DROP
@ IP4_MAPT_FRAGMENTED_NEXT_DROP
Definition: ip4_map_t.c:53
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
ip4_header_t::flags_and_fragment_offset
u16 flags_and_fragment_offset
Definition: ip4_packet.h:106
ip4_map_t_icmp_node
vlib_node_registration_t ip4_map_t_icmp_node
(constructor) VLIB_REGISTER_NODE (ip4_map_t_icmp_node)
Definition: ip4_map_t.c:716
map_domain_t::psid_length
u8 psid_length
Definition: map.h:92
length
char const int length
Definition: cJSON.h:163
vlib_main_t
Definition: main.h:102
ip4_header_t::ip_version_and_header_length
u8 ip_version_and_header_length
Definition: ip4_packet.h:93
b
vlib_buffer_t ** b
Definition: nat44_ei_out2in.c:717
VNET_FEATURES
#define VNET_FEATURES(...)
Definition: feature.h:470
u8
unsigned char u8
Definition: types.h:56
icmp_to_icmp6_ctx_t
icmp_to_icmp6_ctx_t
Definition: ip4_map_t.c:73
ip4_map_t_fragmented_node
vlib_node_registration_t ip4_map_t_fragmented_node
(constructor) VLIB_REGISTER_NODE (ip4_map_t_fragmented_node)
Definition: ip4_map_t.c:695
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
ip_csum_t
uword ip_csum_t
Definition: ip_packet.h:245
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
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
ip4_map_t_embedded_address
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:357
vlib_node_runtime_t
Definition: node.h:454
ip4_mapt_icmp_next_t
ip4_mapt_icmp_next_t
Definition: ip4_map_t.c:30
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_MAPT_TCP_UDP_NEXT_DROP
@ IP4_MAPT_TCP_UDP_NEXT_DROP
Definition: ip4_map_t.c:44
IP4_MAPT_ICMP_N_NEXT
@ IP4_MAPT_ICMP_N_NEXT
Definition: ip4_map_t.c:36
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
VNET_FEATURE_INIT
VNET_FEATURE_INIT(ip4_map_t_feature, static)
type
vl_api_fib_path_type_t type
Definition: fib_types.api:123
ip4_header_t::protocol
u8 protocol
Definition: ip4_packet.h:115
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
ip4_next_header
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:196
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
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169