FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
ip_null_dpo.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 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 /**
16  * @brief
17  * The data-path object representing dropping the packet
18  */
19 
20 #include <vnet/dpo/ip_null_dpo.h>
21 #include <vnet/ip/ip.h>
22 
23 /**
24  * @brief A representation of the IP_NULL DPO
25  */
26 typedef struct ip_null_dpo_t_
27 {
28  /**
29  * @brief The action to take on a packet
30  */
32  /**
33  * @brief The next VLIB node
34  */
36  /**
37  * rate limits
38  */
40 
41 /**
42  * @brief the IP_NULL dpos are shared by all routes, hence they are global.
43  * As the neame implies this is only for IP, hence 2.
44  */
46  [0] = {
47  /* proto ip4, no action */
49  },
50  [1] = {
51  /* proto ip4, action send unreach */
53  },
54  [2] = {
55  /* proto ip4, action send unreach */
57  },
58  [3] = {
59  /* proto ip6, no action */
60  .ind_action = IP_NULL_ACTION_NONE,
61  },
62  [4] = {
63  /* proto ip6, action send unreach */
65  },
66  [5] = {
67  /* proto ip6, action send unreach */
69  },
70 };
71 
72 /**
73  * @brief Action strings
74  */
76 
77 void
80  dpo_id_t *dpo)
81 {
82  int i;
83 
84  ASSERT((proto == DPO_PROTO_IP4) ||
85  (proto == DPO_PROTO_IP6));
87 
88  i = (proto == DPO_PROTO_IP4 ? 0 : 1);
89 
91 }
92 
95 {
96  return (&ip_null_dpos[indi]);
97 }
98 
101 {
102  return (ip_null_dpos[indi].ind_action);
103 }
104 
105 static void
107 {
108  /*
109  * not maintaining a lock count on the ip_null, they are const global and
110  * never die.
111  */
112 }
113 static void
115 {
116 }
117 
118 static u8*
119 format_ip_null_dpo (u8 *s, va_list *ap)
120 {
121  index_t index = va_arg(*ap, index_t);
122  CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
123  const ip_null_dpo_t *ind;
125 
126  ind = ip_null_dpo_get(index);
128 
129  return (format(s, "%U-null action:%s",
132 }
133 
134 const static dpo_vft_t ip_null_vft = {
136  .dv_unlock = ip_null_dpo_unlock,
137  .dv_format = format_ip_null_dpo,
138 };
139 
140 /**
141  * @brief The per-protocol VLIB graph nodes that are assigned to a ip_null
142  * object.
143  *
144  * this means that these graph nodes are ones from which a ip_null is the
145  * parent object in the DPO-graph.
146  */
147 const static char* const ip4_null_nodes[] =
148 {
149  "ip4-null",
150  NULL,
151 };
152 const static char* const ip6_null_nodes[] =
153 {
154  "ip6-null",
155  NULL,
156 };
157 
158 const static char* const * const ip_null_nodes[DPO_PROTO_NUM] =
159 {
162 };
163 
164 typedef struct ip_null_dpo_trace_t_
165 {
168 
169 /**
170  * @brief Exit nodes from a IP_NULL
171  */
172 typedef enum ip_null_next_t_
173 {
178 
183  u8 is_ip4)
184 {
185  u32 n_left_from, next_index, *from, *to_next;
186  static f64 time_last_seed_change = -1e100;
187  static u32 hash_seeds[3];
188  static uword hash_bitmap[256 / BITS (uword)];
189  f64 time_now;
190 
192  n_left_from = frame->n_vectors;
193 
194  time_now = vlib_time_now (vm);
195  if (time_now - time_last_seed_change > 1e-1)
196  {
197  uword i;
199  sizeof (hash_seeds));
200  for (i = 0; i < ARRAY_LEN (hash_seeds); i++)
201  hash_seeds[i] = r[i];
202 
203  /* Mark all hash keys as been not-seen before. */
204  for (i = 0; i < ARRAY_LEN (hash_bitmap); i++)
205  hash_bitmap[i] = 0;
206 
207  time_last_seed_change = time_now;
208  }
209 
210  next_index = node->cached_next_index;
211 
212  while (n_left_from > 0)
213  {
214  u32 n_left_to_next;
215 
216  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
217 
218  while (n_left_from > 0 && n_left_to_next > 0)
219  {
220  u32 a0, b0, c0, m0, drop0;
221  vlib_buffer_t *p0;
222  u32 bi0, indi0, next0;
223  const ip_null_dpo_t *ind0;
224  uword bm0;
225 
226  bi0 = from[0];
227  to_next[0] = bi0;
228  from += 1;
229  to_next += 1;
230  n_left_from -= 1;
231  n_left_to_next -= 1;
232 
233  p0 = vlib_get_buffer (vm, bi0);
234 
235  /* lookup dst + src mac */
236  indi0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
237  ind0 = ip_null_dpo_get(indi0);
238  next0 = IP_NULL_NEXT_DROP;
239 
240  /*
241  * rate limit - don't DoS the sender.
242  */
243  a0 = hash_seeds[0];
244  b0 = hash_seeds[1];
245  c0 = hash_seeds[2];
246 
247  if (is_ip4)
248  {
250 
251  a0 ^= ip0->dst_address.data_u32;
252  b0 ^= ip0->src_address.data_u32;
253 
254  hash_v3_finalize32 (a0, b0, c0);
255  }
256  else
257  {
259 
260  a0 ^= ip0->dst_address.as_u32[0];
261  b0 ^= ip0->src_address.as_u32[0];
262  c0 ^= ip0->src_address.as_u32[1];
263 
264  hash_v3_mix32 (a0, b0, c0);
265 
266  a0 ^= ip0->dst_address.as_u32[1];
267  b0 ^= ip0->src_address.as_u32[2];
268  c0 ^= ip0->src_address.as_u32[3];
269 
270  hash_v3_finalize32 (a0, b0, c0);
271  }
272 
273  c0 &= BITS (hash_bitmap) - 1;
274  c0 = c0 / BITS (uword);
275  m0 = (uword) 1 << (c0 % BITS (uword));
276 
277  bm0 = hash_bitmap[c0];
278  drop0 = (bm0 & m0) != 0;
279 
280  /* Mark it as seen. */
281  hash_bitmap[c0] = bm0 | m0;
282 
283  if (PREDICT_FALSE(!drop0))
284  {
285  if (is_ip4)
286  {
287  /*
288  * There's a trade-off here. This conditinal statement
289  * versus a graph node per-condition. Given the number
290  * expect number of packets to reach a null route is 0
291  * we favour the run-time cost over the graph complexity
292  */
294  {
295  next0 = IP_NULL_NEXT_ICMP;
297  p0,
298  ICMP4_destination_unreachable,
299  ICMP4_destination_unreachable_destination_unreachable_host,
300  0);
301  }
303  {
304  next0 = IP_NULL_NEXT_ICMP;
306  p0,
307  ICMP4_destination_unreachable,
308  ICMP4_destination_unreachable_host_administratively_prohibited,
309  0);
310  }
311  }
312  else
313  {
315  {
316  next0 = IP_NULL_NEXT_ICMP;
318  p0,
319  ICMP6_destination_unreachable,
320  ICMP6_destination_unreachable_no_route_to_destination,
321  0);
322  }
324  {
325  next0 = IP_NULL_NEXT_ICMP;
327  p0,
328  ICMP6_destination_unreachable,
329  ICMP6_destination_unreachable_destination_administratively_prohibited,
330  0);
331  }
332  }
333  }
334 
335  if (PREDICT_FALSE (p0->flags & VLIB_BUFFER_IS_TRACED))
336  {
338  sizeof (*tr));
339  tr->ind_index = indi0;
340  }
342  n_left_to_next, bi0, next0);
343  }
344 
345  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
346  }
347 
348  return frame->n_vectors;
349 }
350 
351 static u8 *
352 format_ip_null_dpo_trace (u8 * s, va_list * args)
353 {
354  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
355  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
356  ip_null_dpo_trace_t *t = va_arg (*args, ip_null_dpo_trace_t *);
357 
358  s = format (s, "%U", format_ip_null_dpo, t->ind_index, 0);
359  return s;
360 }
361 
362 static uword
366 {
367  return (ip_null_dpo_switch(vm, node, frame, 1));
368 }
369 
370 /**
371  * @brief
372  */
374  .function = ip4_null_dpo_switch,
375  .name = "ip4-null",
376  .vector_size = sizeof (u32),
377 
378  .format_trace = format_ip_null_dpo_trace,
379  .n_next_nodes = IP_NULL_NEXT_NUM,
380  .next_nodes = {
381  [IP_NULL_NEXT_DROP] = "ip4-drop",
382  [IP_NULL_NEXT_ICMP] = "ip4-icmp-error",
383  },
384 };
385 
386 static uword
390 {
391  return (ip_null_dpo_switch(vm, node, frame, 0));
392 }
393 
394 /**
395  * @brief
396  */
398  .function = ip6_null_dpo_switch,
399  .name = "ip6-null",
400  .vector_size = sizeof (u32),
401 
402  .format_trace = format_ip_null_dpo_trace,
403  .n_next_nodes = IP_NULL_NEXT_NUM,
404  .next_nodes = {
405  [IP_NULL_NEXT_DROP] = "ip6-drop",
406  [IP_NULL_NEXT_ICMP] = "ip6-icmp-error",
407  },
408 };
409 
410 void
412 {
414 }
ip_null_dpo_unlock
static void ip_null_dpo_unlock(dpo_id_t *dpo)
Definition: ip_null_dpo.c:114
vlib_main_t::random_buffer
clib_random_buffer_t random_buffer
Definition: main.h:212
ip6_null_dpo_node
vlib_node_registration_t ip6_null_dpo_node
(constructor) VLIB_REGISTER_NODE (ip6_null_dpo_node)
Definition: ip_null_dpo.c:397
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
ip_null_dpo_trace_t_::ind_index
index_t ind_index
Definition: ip_null_dpo.c:166
IP_NULL_ACTION_SEND_ICMP_PROHIBIT
@ IP_NULL_ACTION_SEND_ICMP_PROHIBIT
Definition: ip_null_dpo.h:39
icmp6_error_set_vnet_buffer
void icmp6_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp6.c:451
next_index
nat44_ei_hairpin_src_next_t next_index
Definition: nat44_ei_hairpinning.c:412
dpo_proto_t
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
IP_NULL_DPO_ACTION_NUM
#define IP_NULL_DPO_ACTION_NUM
Definition: ip_null_dpo.h:48
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
IP_NULL_NEXT_DROP
@ IP_NULL_NEXT_DROP
Definition: ip_null_dpo.c:174
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
ip_null_next_t
enum ip_null_next_t_ ip_null_next_t
Exit nodes from a IP_NULL.
format_ip_null_dpo
static u8 * format_ip_null_dpo(u8 *s, va_list *ap)
Definition: ip_null_dpo.c:119
ip_null_dpo_trace_t
struct ip_null_dpo_trace_t_ ip_null_dpo_trace_t
ip_null_dpo_get_action
ip_null_dpo_action_t ip_null_dpo_get_action(index_t indi)
Definition: ip_null_dpo.c:100
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
ip4_null_dpo_switch
static uword ip4_null_dpo_switch(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip_null_dpo.c:363
r
vnet_hw_if_output_node_runtime_t * r
Definition: interface_output.c:1089
vlib_frame_t
Definition: node.h:372
ip_null_dpo_module_init
void ip_null_dpo_module_init(void)
Definition: ip_null_dpo.c:411
ip4_header_t
Definition: ip4_packet.h:87
IP_NULL_NEXT_NUM
@ IP_NULL_NEXT_NUM
Definition: ip_null_dpo.c:176
IP_NULL_NEXT_ICMP
@ IP_NULL_NEXT_ICMP
Definition: ip_null_dpo.c:175
hash_v3_finalize32
#define hash_v3_finalize32(a, b, c)
Definition: hash.h:563
ip_null_dpo_get
static const ip_null_dpo_t * ip_null_dpo_get(index_t indi)
Definition: ip_null_dpo.c:94
ip_null_dpos
static ip_null_dpo_t ip_null_dpos[2 *IP_NULL_DPO_ACTION_NUM]
the IP_NULL dpos are shared by all routes, hence they are global.
Definition: ip_null_dpo.c:45
CLIB_UNUSED
#define CLIB_UNUSED(x)
Definition: clib.h:90
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:441
ip_null_dpo_t_::ind_next_index
u32 ind_next_index
The next VLIB node.
Definition: ip_null_dpo.c:35
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
ARRAY_LEN
#define ARRAY_LEN(x)
Definition: clib.h:70
BITS
#define BITS(x)
Definition: clib.h:69
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
index_t
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:43
ip_null_dpo_t_::ind_action
ip_null_dpo_action_t ind_action
The action to take on a packet.
Definition: ip_null_dpo.c:31
ip_null_dpo_action_t
enum ip_null_dpo_action_t_ ip_null_dpo_action_t
The IP NULL DPO represents the rubbish bin for IP traffic.
uword
u64 uword
Definition: types.h:112
ip_null_dpo.h
ip_null_nodes
const static char *const *const ip_null_nodes[DPO_PROTO_NUM]
Definition: ip_null_dpo.c:158
ip_null_action_strings
const char * ip_null_action_strings[]
Action strings.
Definition: ip_null_dpo.c:75
f64
double f64
Definition: types.h:142
ip6_header_t::dst_address
ip6_address_t dst_address
Definition: ip6_packet.h:310
format_ip_null_dpo_trace
static u8 * format_ip_null_dpo_trace(u8 *s, va_list *args)
Definition: ip_null_dpo.c:352
dpo_vft_t_::dv_lock
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:428
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
ip4_header_t::dst_address
ip4_address_t dst_address
Definition: ip4_packet.h:125
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
clib_random_buffer_get_data
static void * clib_random_buffer_get_data(clib_random_buffer_t *b, uword n_bytes)
Definition: random_buffer.h:83
IP_NULL_ACTION_SEND_ICMP_UNREACH
@ IP_NULL_ACTION_SEND_ICMP_UNREACH
Definition: ip_null_dpo.h:38
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
index
u32 index
Definition: flow_types.api:221
always_inline
#define always_inline
Definition: rdma_mlx5dv.h:23
ip_null_next_t_
ip_null_next_t_
Exit nodes from a IP_NULL.
Definition: ip_null_dpo.c:172
ip4_header_t::src_address
ip4_address_t src_address
Definition: ip4_packet.h:125
ip_null_dpo_lock
static void ip_null_dpo_lock(dpo_id_t *dpo)
Definition: ip_null_dpo.c:106
format
description fragment has unexpected format
Definition: map.api:433
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
vlib_put_next_frame
vlib_put_next_frame(vm, node, next_index, 0)
DPO_PROTO_IP6
@ DPO_PROTO_IP6
Definition: dpo.h:65
IP_NULL_ACTION_NONE
@ IP_NULL_ACTION_NONE
Definition: ip_null_dpo.h:37
ip.h
u32
unsigned int u32
Definition: types.h:88
ip4_address_t::data_u32
u32 data_u32
Definition: ip4_packet.h:53
ip4_null_dpo_node
vlib_node_registration_t ip4_null_dpo_node
(constructor) VLIB_REGISTER_NODE (ip4_null_dpo_node)
Definition: ip_null_dpo.c:373
IP_NULL_ACTIONS
#define IP_NULL_ACTIONS
Definition: ip_null_dpo.h:42
ip6_header_t
Definition: ip6_packet.h:294
DPO_IP_NULL
@ DPO_IP_NULL
Definition: dpo.h:99
ip_null_dpo_t
struct ip_null_dpo_t_ ip_null_dpo_t
The data-path object representing dropping the packet.
ip6_header_t::src_address
ip6_address_t src_address
Definition: ip6_packet.h:310
vlib_main_t
Definition: main.h:102
ip_null_dpo_t_
The data-path object representing dropping the packet.
Definition: ip_null_dpo.c:26
vlib_node_t
Definition: node.h:247
dpo_vft_t_
A virtual function table regisitered for a DPO type.
Definition: dpo.h:423
format_dpo_proto
u8 * format_dpo_proto(u8 *s, va_list *args)
format a DPO protocol
Definition: dpo.c:180
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
ip6_null_nodes
const static char *const ip6_null_nodes[]
Definition: ip_null_dpo.c:152
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
ip6_null_dpo_switch
static uword ip6_null_dpo_switch(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip_null_dpo.c:387
ip_null_dpo_trace_t_
Definition: ip_null_dpo.c:164
i
int i
Definition: flowhash_template.h:376
DPO_PROTO_IP4
@ DPO_PROTO_IP4
Definition: dpo.h:64
ip_null_dpo_add_and_lock
void ip_null_dpo_add_and_lock(dpo_proto_t proto, ip_null_dpo_action_t action, dpo_id_t *dpo)
Definition: ip_null_dpo.c:78
dpo_id_t_
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:172
ip4_null_nodes
const static char *const ip4_null_nodes[]
The per-protocol VLIB graph nodes that are assigned to a ip_null object.
Definition: ip_null_dpo.c:147
vlib_time_now
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:327
dpo_set
void dpo_set(dpo_id_t *dpo, dpo_type_t type, dpo_proto_t proto, index_t index)
Set/create a DPO ID The DPO will be locked.
Definition: dpo.c:188
vlib_node_runtime_t
Definition: node.h:454
proto
vl_api_ip_proto_t proto
Definition: acl_types.api:51
from
from
Definition: nat44_ei_hairpinning.c:415
ip_null_vft
const static dpo_vft_t ip_null_vft
Definition: ip_null_dpo.c:134
action
vl_api_mac_event_action_t action
Definition: l2.api:211
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
VLIB_TX
@ VLIB_TX
Definition: defs.h:47
n_left_from
n_left_from
Definition: nat44_ei_hairpinning.c:416
ip_null_dpo_switch
static uword ip_null_dpo_switch(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, u8 is_ip4)
Definition: ip_null_dpo.c:180
DPO_PROTO_NUM
#define DPO_PROTO_NUM
Definition: dpo.h:72
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
dpo_register
void dpo_register(dpo_type_t type, const dpo_vft_t *vft, const char *const *const *nodes)
For a given DPO type Register:
Definition: dpo.c:329
hash_v3_mix32
#define hash_v3_mix32(a, b, c)
Definition: hash.h:553
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169