FD.io VPP  v21.06-3-gbb25fbf28
Vector Packet Processing
ip_path_mtu_node.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * ip_path_mtu.c
4  *
5  * Copyright (c) 2020 Graphiant.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19 
20 #include <vnet/ip/ip_path_mtu.h>
21 #include <vnet/ip/ip_frag.h>
22 
23 typedef enum
24 {
28 
29 typedef struct ip_pmtu_trace_t_
30 {
34 
35 static u8 *
36 format_ip_pmtu_trace (u8 *s, va_list *args)
37 {
38  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
39  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
40  ip_pmtu_trace_t *t = va_arg (*args, ip_pmtu_trace_t *);
41 
42  s = format (s, "path mtu:%d packet size:%d", t->pmtu, t->packet_size);
43 
44  return s;
45 }
46 
47 static inline uword
50 {
51  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
52  u32 frag_sent = 0, small_packets = 0;
53 
55  n_left_from = frame->n_vectors;
56  next_index = node->cached_next_index;
57 
58  u32 *buffer = 0;
59 
60  while (n_left_from > 0)
61  {
62  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
63 
64  while (n_left_from > 0 && n_left_to_next > 0)
65  {
66  const ip_pmtu_dpo_t *ipm0;
67  u32 pi0, *frag_from, frag_left;
68  vlib_buffer_t *p0;
69  ip_frag_error_t error0;
70  u16 next0;
71 
72  /*
73  * Note: The packet is not enqueued now. It is instead put
74  * in a vector where other fragments will be put as well.
75  */
76  pi0 = from[0];
77  from += 1;
78  n_left_from -= 1;
79 
80  p0 = vlib_get_buffer (vm, pi0);
81  ipm0 = ip_pmtu_dpo_get (vnet_buffer (p0)->ip.adj_index[VLIB_TX]);
82  vnet_buffer (p0)->ip.adj_index[VLIB_TX] = ipm0->ipm_dpo.dpoi_index;
83  next0 = ipm0->ipm_dpo.dpoi_next_node;
84 
85  if (PREDICT_FALSE (p0->flags & VLIB_BUFFER_IS_TRACED))
86  {
87  ip_pmtu_trace_t *t;
88  t = vlib_add_trace (vm, node, p0, sizeof (*t));
89  t->pmtu = ipm0->ipm_pmtu;
91  }
92 
93  if (AF_IP6 == af)
94  error0 =
95  ip6_frag_do_fragment (vm, pi0, ipm0->ipm_pmtu, 0, &buffer);
96  else
97  error0 =
98  ip4_frag_do_fragment (vm, pi0, ipm0->ipm_pmtu, 0, &buffer);
99 
100  if (AF_IP4 == af && error0 == IP_FRAG_ERROR_DONT_FRAGMENT_SET)
101  {
103  p0, ICMP4_destination_unreachable,
104  ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set,
105  ipm0->ipm_pmtu);
106  next0 = IP_FRAG_NEXT_ICMP_ERROR;
107  }
108  else
109  {
110  next0 =
111  (error0 == IP_FRAG_ERROR_NONE ? next0 : IP_FRAG_NEXT_DROP);
112  }
113 
114  if (error0 == IP_FRAG_ERROR_NONE)
115  {
116  /* Free original buffer chain */
117  frag_sent += vec_len (buffer);
118  small_packets += (vec_len (buffer) == 1);
119  vlib_buffer_free_one (vm, pi0); /* Free original packet */
120  }
121  else
122  {
123  vlib_error_count (vm, node->node_index, error0, 1);
124  vec_add1 (buffer, pi0); /* Get rid of the original buffer */
125  }
126 
127  /* Send fragments that were added in the frame */
128  frag_from = buffer;
129  frag_left = vec_len (buffer);
130 
131  while (frag_left > 0)
132  {
133  while (frag_left > 0 && n_left_to_next > 0)
134  {
135  u32 i;
136  i = to_next[0] = frag_from[0];
137  frag_from += 1;
138  frag_left -= 1;
139  to_next += 1;
140  n_left_to_next -= 1;
141 
142  vlib_get_buffer (vm, i)->error = node->errors[error0];
144  vm, node, next_index, to_next, n_left_to_next, i, next0);
145  }
146  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
148  n_left_to_next);
149  }
151  }
152  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
153  }
154  vec_free (buffer);
155 
156  return frame->n_vectors;
157 }
158 
159 // clang-format off
160 
164 {
165  return (ip_pmtu_dpo_inline (vm, node, from_frame, 0));
166 }
167 
171 {
172  return (ip_pmtu_dpo_inline (vm, node, from_frame, 1));
173 }
174 
176  .name = "ip4-pmtu-dpo",
177  .vector_size = sizeof (u32),
178  .format_trace = format_ip_pmtu_trace,
179  .n_errors = 0,
180  .n_next_nodes = IP_PMTU_N_NEXT,
181  .next_nodes =
182  {
183  [IP_PMTU_DROP] = "ip4-drop",
184  }
185 };
187  .name = "ip6-pmtu-dpo",
188  .vector_size = sizeof (u32),
189  .format_trace = format_ip_pmtu_trace,
190  .n_errors = 0,
191  .n_next_nodes = IP_PMTU_N_NEXT,
192  .next_nodes =
193  {
194  [IP_PMTU_DROP] = "ip6-drop",
195  }
196 };
197 
198 // clang-format on
199 
200 /*
201  * fd.io coding-style-patch-verification: ON
202  *
203  * Local Variables:
204  * eval: (c-set-style "gnu")
205  * End:
206  */
vec_reset_length
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
Definition: vec_bootstrap.h:194
dpo_id_t_::dpoi_next_node
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:186
dpo_id_t_::dpoi_index
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:190
ip_frag_error_t
ip_frag_error_t
Definition: ip_frag.h:71
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
buffer
char * buffer
Definition: cJSON.h:163
ip4_ip_pmtu_dpo_node
vlib_node_registration_t ip4_ip_pmtu_dpo_node
(constructor) VLIB_REGISTER_NODE (ip4_ip_pmtu_dpo_node)
Definition: ip_path_mtu_node.c:175
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
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
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
AF_IP4
@ AF_IP4
Definition: ip_types.h:23
from_frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * from_frame
Definition: esp_encrypt.c:1328
vlib_error_count
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:57
vlib_frame_t
Definition: node.h:372
IP_FRAG_NEXT_DROP
@ IP_FRAG_NEXT_DROP
Definition: ip_frag.h:56
vlib_buffer_length_in_chain
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:433
ip_pmtu_trace_t_::packet_size
u16 packet_size
Definition: ip_path_mtu_node.c:32
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
vlib_buffer_t::error
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:145
VLIB_NODE_FN
#define VLIB_NODE_FN(node)
Definition: node.h:202
vec_add1
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:606
CLIB_UNUSED
#define CLIB_UNUSED(x)
Definition: clib.h:90
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:437
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
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
uword
u64 uword
Definition: types.h:112
i
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
ip4_frag_do_fragment
ip_frag_error_t ip4_frag_do_fragment(vlib_main_t *vm, u32 from_bi, u16 mtu, u16 l2unfragmentablesize, u32 **buffer)
Definition: ip_frag.c:93
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
ip_pmtu_dpo_get
static_always_inline ip_pmtu_dpo_t * ip_pmtu_dpo_get(index_t index)
Definition: ip_path_mtu.h:108
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
ip6_ip_pmtu_dpo_node
vlib_node_registration_t ip6_ip_pmtu_dpo_node
(constructor) VLIB_REGISTER_NODE (ip6_ip_pmtu_dpo_node)
Definition: ip_path_mtu_node.c:186
ip_pmtu_trace_t
struct ip_pmtu_trace_t_ ip_pmtu_trace_t
ip_pmtu_dpo_t_::ipm_pmtu
u16 ipm_pmtu
Configured Path Mtu.
Definition: ip_path_mtu.h:38
ip_pmtu_dpo_t_::ipm_dpo
dpo_id_t ipm_dpo
Stacked DPO.
Definition: ip_path_mtu.h:48
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
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
format
description fragment has unexpected format
Definition: map.api:433
vlib_put_next_frame
vlib_put_next_frame(vm, node, next_index, 0)
IP_PMTU_DROP
@ IP_PMTU_DROP
Definition: ip_path_mtu_node.c:25
u32
unsigned int u32
Definition: types.h:88
ip_pmtu_dpo_inline
static uword ip_pmtu_dpo_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, ip_address_family_t af)
Definition: ip_path_mtu_node.c:48
AF_IP6
@ AF_IP6
Definition: ip_types.h:24
ip6_frag_do_fragment
ip_frag_error_t ip6_frag_do_fragment(vlib_main_t *vm, u32 from_bi, u16 mtu, u16 l2unfragmentablesize, u32 **buffer)
Definition: ip_frag.c:381
vlib_main_t
Definition: main.h:102
vlib_node_t
Definition: node.h:247
vlib_add_trace
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:628
u8
unsigned char u8
Definition: types.h:56
ip
vl_api_address_t ip
Definition: l2.api:558
IP_FRAG_NEXT_ICMP_ERROR
@ IP_FRAG_NEXT_ICMP_ERROR
Definition: ip_frag.h:55
ip_pmtu_trace_t_
Definition: ip_path_mtu_node.c:29
ip_pmtu_next_t
ip_pmtu_next_t
Definition: ip_path_mtu_node.c:23
vlib_buffer_free_one
static void vlib_buffer_free_one(vlib_main_t *vm, u32 buffer_index)
Free one buffer Shorthand to free a single buffer chain.
Definition: buffer_funcs.h:1015
vlib_node_runtime_t
Definition: node.h:454
from
from
Definition: nat44_ei_hairpinning.c:415
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_path_mtu.h
VLIB_TX
@ VLIB_TX
Definition: defs.h:47
IP_PMTU_N_NEXT
@ IP_PMTU_N_NEXT
Definition: ip_path_mtu_node.c:26
n_left_from
n_left_from
Definition: nat44_ei_hairpinning.c:416
ip_pmtu_trace_t_::pmtu
u16 pmtu
Definition: ip_path_mtu_node.c:31
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
ip_address_family_t
enum ip_address_family_t_ ip_address_family_t
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
format_ip_pmtu_trace
static u8 * format_ip_pmtu_trace(u8 *s, va_list *args)
Definition: ip_path_mtu_node.c:36
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
ip_pmtu_dpo_t_
The Path MTU DPO.
Definition: ip_path_mtu.h:26