FD.io VPP  v18.01.2-1-g9b554f3
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  */
45 static ip_null_dpo_t ip_null_dpos[2 * IP_NULL_DPO_ACTION_NUM] = {
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
79  ip_null_dpo_action_t action,
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 
90  dpo_set(dpo, DPO_IP_NULL, proto, (i*IP_NULL_DPO_ACTION_NUM) + action);
91 }
92 
95 {
96  return (&ip_null_dpos[indi]);
97 }
98 
99 static void
101 {
102  /*
103  * not maintaining a lock count on the ip_null, they are const global and
104  * never die.
105  */
106 }
107 static void
109 {
110 }
111 
112 static u8*
113 format_ip_null_dpo (u8 *s, va_list *ap)
114 {
115  index_t index = va_arg(*ap, index_t);
116  CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
117  const ip_null_dpo_t *ind;
118  dpo_proto_t proto;
119 
120  ind = ip_null_dpo_get(index);
121  proto = (index < IP_NULL_DPO_ACTION_NUM ? DPO_PROTO_IP4 : DPO_PROTO_IP6);
122 
123  return (format(s, "%U-null action:%s",
124  format_dpo_proto, proto,
126 }
127 
128 const static dpo_vft_t ip_null_vft = {
130  .dv_unlock = ip_null_dpo_unlock,
131  .dv_format = format_ip_null_dpo,
132 };
133 
134 /**
135  * @brief The per-protocol VLIB graph nodes that are assigned to a ip_null
136  * object.
137  *
138  * this means that these graph nodes are ones from which a ip_null is the
139  * parent object in the DPO-graph.
140  */
141 const static char* const ip4_null_nodes[] =
142 {
143  "ip4-null",
144  NULL,
145 };
146 const static char* const ip6_null_nodes[] =
147 {
148  "ip6-null",
149  NULL,
150 };
151 
152 const static char* const * const ip_null_nodes[DPO_PROTO_NUM] =
153 {
156 };
157 
158 typedef struct ip_null_dpo_trace_t_
159 {
162 
163 /**
164  * @brief Exit nodes from a IP_NULL
165  */
166 typedef enum ip_null_next_t_
167 {
172 
175  vlib_node_runtime_t * node,
176  vlib_frame_t * frame,
177  u8 is_ip4)
178 {
179  u32 n_left_from, next_index, *from, *to_next;
180  static f64 time_last_seed_change = -1e100;
181  static u32 hash_seeds[3];
182  static uword hash_bitmap[256 / BITS (uword)];
183  f64 time_now;
184 
185  from = vlib_frame_vector_args (frame);
186  n_left_from = frame->n_vectors;
187 
188  time_now = vlib_time_now (vm);
189  if (time_now - time_last_seed_change > 1e-1)
190  {
191  uword i;
193  sizeof (hash_seeds));
194  for (i = 0; i < ARRAY_LEN (hash_seeds); i++)
195  hash_seeds[i] = r[i];
196 
197  /* Mark all hash keys as been not-seen before. */
198  for (i = 0; i < ARRAY_LEN (hash_bitmap); i++)
199  hash_bitmap[i] = 0;
200 
201  time_last_seed_change = time_now;
202  }
203 
204  next_index = node->cached_next_index;
205 
206  while (n_left_from > 0)
207  {
208  u32 n_left_to_next;
209 
210  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
211 
212  while (n_left_from > 0 && n_left_to_next > 0)
213  {
214  u32 a0, b0, c0, m0, drop0;
215  vlib_buffer_t *p0;
216  u32 bi0, indi0, next0;
217  const ip_null_dpo_t *ind0;
218  uword bm0;
219 
220  bi0 = from[0];
221  to_next[0] = bi0;
222  from += 1;
223  to_next += 1;
224  n_left_from -= 1;
225  n_left_to_next -= 1;
226 
227  p0 = vlib_get_buffer (vm, bi0);
228 
229  /* lookup dst + src mac */
230  indi0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
231  ind0 = ip_null_dpo_get(indi0);
232  next0 = IP_NULL_NEXT_DROP;
233 
234  /*
235  * rate limit - don't DoS the sender.
236  */
237  a0 = hash_seeds[0];
238  b0 = hash_seeds[1];
239  c0 = hash_seeds[2];
240 
241  if (is_ip4)
242  {
244 
245  a0 ^= ip0->dst_address.data_u32;
246  b0 ^= ip0->src_address.data_u32;
247 
248  hash_v3_finalize32 (a0, b0, c0);
249  }
250  else
251  {
253 
254  a0 ^= ip0->dst_address.as_u32[0];
255  b0 ^= ip0->src_address.as_u32[0];
256  c0 ^= ip0->src_address.as_u32[1];
257 
258  hash_v3_mix32 (a0, b0, c0);
259 
260  a0 ^= ip0->dst_address.as_u32[1];
261  b0 ^= ip0->src_address.as_u32[2];
262  c0 ^= ip0->src_address.as_u32[3];
263 
264  hash_v3_finalize32 (a0, b0, c0);
265  }
266 
267  c0 &= BITS (hash_bitmap) - 1;
268  c0 = c0 / BITS (uword);
269  m0 = (uword) 1 << (c0 % BITS (uword));
270 
271  bm0 = hash_bitmap[c0];
272  drop0 = (bm0 & m0) != 0;
273 
274  /* Mark it as seen. */
275  hash_bitmap[c0] = bm0 | m0;
276 
277  if (PREDICT_FALSE(!drop0))
278  {
279  if (is_ip4)
280  {
281  /*
282  * There's a trade-off here. This conditinal statement
283  * versus a graph node per-condition. Given the number
284  * expect number of packets to reach a null route is 0
285  * we favour the run-time cost over the graph complexity
286  */
288  {
289  next0 = IP_NULL_NEXT_ICMP;
291  p0,
292  ICMP4_destination_unreachable,
293  ICMP4_destination_unreachable_destination_unreachable_host,
294  0);
295  }
297  {
298  next0 = IP_NULL_NEXT_ICMP;
300  p0,
301  ICMP4_destination_unreachable,
302  ICMP4_destination_unreachable_host_administratively_prohibited,
303  0);
304  }
305  }
306  else
307  {
309  {
310  next0 = IP_NULL_NEXT_ICMP;
312  p0,
313  ICMP6_destination_unreachable,
314  ICMP6_destination_unreachable_no_route_to_destination,
315  0);
316  }
318  {
319  next0 = IP_NULL_NEXT_ICMP;
321  p0,
322  ICMP6_destination_unreachable,
323  ICMP6_destination_unreachable_destination_administratively_prohibited,
324  0);
325  }
326  }
327  }
328 
330  {
331  ip_null_dpo_trace_t *tr = vlib_add_trace (vm, node, p0,
332  sizeof (*tr));
333  tr->ind_index = indi0;
334  }
335  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
336  n_left_to_next, bi0, next0);
337  }
338 
339  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
340  }
341 
342  return frame->n_vectors;
343 }
344 
345 static u8 *
346 format_ip_null_dpo_trace (u8 * s, va_list * args)
347 {
348  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
349  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
350  ip_null_dpo_trace_t *t = va_arg (*args, ip_null_dpo_trace_t *);
351 
352  s = format (s, "%U", format_ip_null_dpo, t->ind_index, 0);
353  return s;
354 }
355 
356 static uword
358  vlib_node_runtime_t * node,
359  vlib_frame_t * frame)
360 {
361  return (ip_null_dpo_switch(vm, node, frame, 1));
362 }
363 
364 /**
365  * @brief
366  */
368  .function = ip4_null_dpo_switch,
369  .name = "ip4-null",
370  .vector_size = sizeof (u32),
371 
372  .format_trace = format_ip_null_dpo_trace,
373  .n_next_nodes = IP_NULL_NEXT_NUM,
374  .next_nodes = {
375  [IP_NULL_NEXT_DROP] = "ip4-drop",
376  [IP_NULL_NEXT_ICMP] = "ip4-icmp-error",
377  },
378 };
379 
380 static uword
382  vlib_node_runtime_t * node,
383  vlib_frame_t * frame)
384 {
385  return (ip_null_dpo_switch(vm, node, frame, 0));
386 }
387 
388 /**
389  * @brief
390  */
392  .function = ip6_null_dpo_switch,
393  .name = "ip6-null",
394  .vector_size = sizeof (u32),
395 
396  .format_trace = format_ip_null_dpo_trace,
397  .n_next_nodes = IP_NULL_NEXT_NUM,
398  .next_nodes = {
399  [IP_NULL_NEXT_DROP] = "ip6-drop",
400  [IP_NULL_NEXT_ICMP] = "ip6-icmp-error",
401  },
402 };
403 
404 void
406 {
407  dpo_register(DPO_IP_NULL, &ip_null_vft, ip_null_nodes);
408 }
enum ip_null_dpo_action_t_ ip_null_dpo_action_t
The IP NULL DPO represents the rubbish bin for IP traffic.
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:382
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
vlib_node_registration_t ip6_null_dpo_node
(constructor) VLIB_REGISTER_NODE (ip6_null_dpo_node)
Definition: ip_null_dpo.c:391
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
#define CLIB_UNUSED(x)
Definition: clib.h:79
A virtual function table regisitered for a DPO type.
Definition: dpo.h:377
ip4_address_t src_address
Definition: ip4_packet.h:164
static uword ip4_null_dpo_switch(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip_null_dpo.c:357
#define NULL
Definition: clib.h:55
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:224
static void ip_null_dpo_unlock(dpo_id_t *dpo)
Definition: ip_null_dpo.c:108
static void * clib_random_buffer_get_data(clib_random_buffer_t *b, uword n_bytes)
Definition: random_buffer.h:78
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:41
#define IP_NULL_DPO_ACTION_NUM
Definition: ip_null_dpo.h:48
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
ip6_address_t src_address
Definition: ip6_packet.h:341
#define hash_v3_mix32(a, b, c)
Definition: hash.h:553
static const ip_null_dpo_t * ip_null_dpo_get(index_t indi)
Definition: ip_null_dpo.c:94
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:306
#define always_inline
Definition: clib.h:92
static u8 * format_ip_null_dpo(u8 *s, va_list *ap)
Definition: ip_null_dpo.c:113
ip4_address_t dst_address
Definition: ip4_packet.h:164
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
static u8 * format_ip_null_dpo_trace(u8 *s, va_list *args)
Definition: ip_null_dpo.c:346
void icmp6_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp6.c:509
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:166
void ip_null_dpo_module_init(void)
Definition: ip_null_dpo.c:405
static const char *const ip6_null_nodes[]
Definition: ip_null_dpo.c:146
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:195
#define PREDICT_FALSE(x)
Definition: clib.h:105
static void ip_null_dpo_lock(dpo_id_t *dpo)
Definition: ip_null_dpo.c:100
#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:364
u32 as_u32[4]
Definition: ip6_packet.h:50
struct ip_null_dpo_trace_t_ ip_null_dpo_trace_t
u16 n_vectors
Definition: node.h:344
vlib_main_t * vm
Definition: buffer.c:283
static const char *const *const ip_null_nodes[DPO_PROTO_NUM]
Definition: ip_null_dpo.c:152
void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp4.c:431
ip_null_next_t_
Exit nodes from a IP_NULL.
Definition: ip_null_dpo.c:166
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:93
#define ARRAY_LEN(x)
Definition: clib.h:59
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:454
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:182
ip_null_dpo_action_t ind_action
The action to take on a packet.
Definition: ip_null_dpo.c:31
const char * ip_null_action_strings[]
Action strings.
Definition: ip_null_dpo.c:75
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:456
#define ASSERT(truth)
u32 ind_next_index
The next VLIB node.
Definition: ip_null_dpo.c:35
unsigned int u32
Definition: types.h:88
#define hash_v3_finalize32(a, b, c)
Definition: hash.h:563
The data-path object representing dropping the packet.
Definition: ip_null_dpo.c:26
u64 uword
Definition: types.h:112
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
enum ip_null_next_t_ ip_null_next_t
Exit nodes from a IP_NULL.
Definition: defs.h:47
#define DPO_PROTO_NUM
Definition: dpo.h:70
double f64
Definition: types.h:142
unsigned char u8
Definition: types.h:56
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:267
u8 * format_dpo_proto(u8 *s, va_list *args)
format a DPO protocol
Definition: dpo.c:174
static const char *const ip4_null_nodes[]
The per-protocol VLIB graph nodes that are assigned to a ip_null object.
Definition: ip_null_dpo.c:141
#define vnet_buffer(b)
Definition: buffer.h:326
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
vlib_node_registration_t ip4_null_dpo_node
(constructor) VLIB_REGISTER_NODE (ip4_null_dpo_node)
Definition: ip_null_dpo.c:367
struct ip_null_dpo_t_ ip_null_dpo_t
The data-path object representing dropping the packet.
#define IP_NULL_ACTIONS
Definition: ip_null_dpo.h:42
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:75
#define BITS(x)
Definition: clib.h:58
static uword ip6_null_dpo_switch(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip_null_dpo.c:381
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
clib_random_buffer_t random_buffer
Definition: main.h:167
ip6_address_t dst_address
Definition: ip6_packet.h:341
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:174