FD.io VPP  v18.10-34-gcce845e
Vector Packet Processing
interface_rx_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 
17 #include <vnet/fib/fib_node.h>
18 #include <vnet/l2/l2_input.h>
19 
20 /*
21  * The 'DB' of interface DPOs.
22  * There is only one per-interface per-protocol, so this is a per-interface
23  * vector
24  */
26 
27 static interface_rx_dpo_t *
29 {
30  interface_rx_dpo_t *ido;
31 
33 
34  return (ido);
35 }
36 
37 static inline interface_rx_dpo_t *
39 {
41 
42  return (interface_rx_dpo_get(dpo->dpoi_index));
43 }
44 
45 static inline index_t
47 {
48  return (ido - interface_rx_dpo_pool);
49 }
50 
51 static void
53 {
54  interface_rx_dpo_t *ido;
55 
57  ido->ido_locks++;
58 }
59 
60 static void
62 {
63  interface_rx_dpo_t *ido;
64 
66  ido->ido_locks--;
67 
68  if (0 == ido->ido_locks)
69  {
73  }
74 }
75 
76 /*
77  * interface_rx_dpo_add_or_lock
78  *
79  * Add/create and lock a new or lock an existing for the interface DPO
80  * on the interface and protocol given
81  */
82 void
85  dpo_id_t *dpo)
86 {
87  interface_rx_dpo_t *ido;
88 
90  sw_if_index,
92 
93  if (INDEX_INVALID == interface_rx_dpo_db[proto][sw_if_index])
94  {
95  ido = interface_rx_dpo_alloc();
96 
98  ido->ido_proto = proto;
99 
102  }
103  else
104  {
105  ido = interface_rx_dpo_get(interface_rx_dpo_db[proto][sw_if_index]);
106  }
107 
109 }
110 
111 
112 static clib_error_t *
115  u32 flags)
116 {
117  /*
118  */
119  return (NULL);
120 }
121 
124 
125 /**
126  * @brief Registered callback for HW interface state changes
127  */
128 static clib_error_t *
130  u32 hw_if_index,
131  u32 flags)
132 {
133  return (NULL);
134 }
135 
138 
139 static clib_error_t *
142  u32 is_add)
143 {
144  return (NULL);
145 }
146 
149 
150 u8*
151 format_interface_rx_dpo (u8* s, va_list *ap)
152 {
153  index_t index = va_arg(*ap, index_t);
154  CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
155  vnet_main_t * vnm = vnet_get_main();
157 
158  return (format(s, "%U-rx-dpo: %U",
160  vnm,
162  format_dpo_proto, ido->ido_proto));
163 }
164 
165 static void
167 {
168  fib_show_memory_usage("Interface",
171  sizeof(interface_rx_dpo_t));
172 }
173 
174 
175 const static dpo_vft_t interface_rx_dpo_vft = {
177  .dv_unlock = interface_rx_dpo_unlock,
178  .dv_format = format_interface_rx_dpo,
179  .dv_mem_show = interface_rx_dpo_mem_show,
180 };
181 
182 /**
183  * @brief The per-protocol VLIB graph nodes that are assigned to a glean
184  * object.
185  *
186  * this means that these graph nodes are ones from which a glean is the
187  * parent object in the DPO-graph.
188  */
189 const static char* const interface_rx_dpo_ip4_nodes[] =
190 {
191  "interface-rx-dpo-ip4",
192  NULL,
193 };
194 const static char* const interface_rx_dpo_ip6_nodes[] =
195 {
196  "interface-rx-dpo-ip6",
197  NULL,
198 };
199 const static char* const interface_rx_dpo_l2_nodes[] =
200 {
201  "interface-rx-dpo-l2",
202  NULL,
203 };
204 
205 const static char* const * const interface_rx_dpo_nodes[DPO_PROTO_NUM] =
206 {
210  [DPO_PROTO_MPLS] = NULL,
211 };
212 
213 void
215 {
217  &interface_rx_dpo_vft,
219 }
220 
221 /**
222  * @brief Interface DPO trace data
223  */
225 {
228 
230 {
234 
237  vlib_node_runtime_t * node,
238  vlib_frame_t * from_frame,
239  u8 is_l2)
240 {
241  u32 n_left_from, next_index, * from, * to_next;
242  u32 thread_index = vm->thread_index;
244 
245  im = &vnet_get_main ()->interface_main;
246  from = vlib_frame_vector_args (from_frame);
247  n_left_from = from_frame->n_vectors;
248 
249  next_index = INTERFACE_RX_DPO_INPUT;
250 
251  while (n_left_from > 0)
252  {
253  u32 n_left_to_next;
254 
255  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
256 
257  while (n_left_from >= 4 && n_left_to_next > 2)
258  {
259  const interface_rx_dpo_t *ido0, *ido1;
260  u32 bi0, idoi0, bi1, idoi1;
261  vlib_buffer_t *b0, *b1;
262 
263  bi0 = from[0];
264  to_next[0] = bi0;
265  bi1 = from[1];
266  to_next[1] = bi1;
267  from += 2;
268  to_next += 2;
269  n_left_from -= 2;
270  n_left_to_next -= 2;
271 
272  b0 = vlib_get_buffer (vm, bi0);
273  b1 = vlib_get_buffer (vm, bi1);
274 
275  idoi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
276  idoi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
277  ido0 = interface_rx_dpo_get(idoi0);
278  ido1 = interface_rx_dpo_get(idoi1);
279 
280  vnet_buffer(b0)->sw_if_index[VLIB_RX] = ido0->ido_sw_if_index;
281  vnet_buffer(b1)->sw_if_index[VLIB_RX] = ido1->ido_sw_if_index;
282 
283  if (is_l2)
284  {
285  vnet_update_l2_len (b0);
286  vnet_update_l2_len (b1);
287  }
288 
291  thread_index,
292  ido0->ido_sw_if_index,
293  1,
294  vlib_buffer_length_in_chain (vm, b0));
297  thread_index,
298  ido1->ido_sw_if_index,
299  1,
300  vlib_buffer_length_in_chain (vm, b1));
301 
302  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
303  {
305 
306  tr0 = vlib_add_trace (vm, node, b0, sizeof (*tr0));
307  tr0->sw_if_index = ido0->ido_sw_if_index;
308  }
309  if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
310  {
312 
313  tr1 = vlib_add_trace (vm, node, b1, sizeof (*tr1));
314  tr1->sw_if_index = ido1->ido_sw_if_index;
315  }
316  }
317 
318  while (n_left_from > 0 && n_left_to_next > 0)
319  {
320  const interface_rx_dpo_t * ido0;
321  vlib_buffer_t * b0;
322  u32 bi0, idoi0;
323 
324  bi0 = from[0];
325  to_next[0] = bi0;
326  from += 1;
327  to_next += 1;
328  n_left_from -= 1;
329  n_left_to_next -= 1;
330 
331  b0 = vlib_get_buffer (vm, bi0);
332 
333  idoi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
334  ido0 = interface_rx_dpo_get(idoi0);
335 
336  /* Swap the RX interface of the packet to the one the
337  * interface DPR represents */
338  vnet_buffer(b0)->sw_if_index[VLIB_RX] = ido0->ido_sw_if_index;
339 
340  /* Update l2_len to make l2 tag rewrite work */
341  if (is_l2)
342  vnet_update_l2_len (b0);
343 
344  /* Bump the interface's RX coutners */
347  thread_index,
348  ido0->ido_sw_if_index,
349  1,
350  vlib_buffer_length_in_chain (vm, b0));
351 
352  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
353  {
355 
356  tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
357  tr->sw_if_index = ido0->ido_sw_if_index;
358  }
359  }
360  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
361  }
362  return from_frame->n_vectors;
363 }
364 
365 static u8 *
366 format_interface_rx_dpo_trace (u8 * s, va_list * args)
367 {
368  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
369  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
370  interface_rx_dpo_trace_t * t = va_arg (*args, interface_rx_dpo_trace_t *);
371  u32 indent = format_get_indent (s);
372  s = format (s, "%U sw_if_index:%d",
373  format_white_space, indent,
374  t->sw_if_index);
375  return s;
376 }
377 
378 static uword
380  vlib_node_runtime_t * node,
381  vlib_frame_t * from_frame)
382 {
383  return (interface_rx_dpo_inline(vm, node, from_frame, 0));
384 }
385 
386 static uword
388  vlib_node_runtime_t * node,
389  vlib_frame_t * from_frame)
390 {
391  return (interface_rx_dpo_inline(vm, node, from_frame, 0));
392 }
393 
394 static uword
396  vlib_node_runtime_t * node,
397  vlib_frame_t * from_frame)
398 {
399  return (interface_rx_dpo_inline(vm, node, from_frame, 1));
400 }
401 
403  .function = interface_rx_dpo_ip4,
404  .name = "interface-rx-dpo-ip4",
405  .vector_size = sizeof (u32),
406  .format_trace = format_interface_rx_dpo_trace,
407 
408  .n_next_nodes = 2,
409  .next_nodes = {
410  [INTERFACE_RX_DPO_DROP] = "ip4-drop",
411  [INTERFACE_RX_DPO_INPUT] = "ip4-input",
412  },
413 };
414 
417 
418 VLIB_REGISTER_NODE (interface_rx_dpo_ip6_node) = {
419  .function = interface_rx_dpo_ip6,
420  .name = "interface-rx-dpo-ip6",
421  .vector_size = sizeof (u32),
422  .format_trace = format_interface_rx_dpo_trace,
423 
424  .n_next_nodes = 2,
425  .next_nodes = {
426  [INTERFACE_RX_DPO_DROP] = "ip6-drop",
427  [INTERFACE_RX_DPO_INPUT] = "ip6-input",
428  },
429 };
430 
431 VLIB_NODE_FUNCTION_MULTIARCH (interface_rx_dpo_ip6_node,
433 
434 VLIB_REGISTER_NODE (interface_rx_dpo_l2_node) = {
435  .function = interface_rx_dpo_l2,
436  .name = "interface-rx-dpo-l2",
437  .vector_size = sizeof (u32),
438  .format_trace = format_interface_rx_dpo_trace,
439 
440  .n_next_nodes = 2,
441  .next_nodes = {
442  [INTERFACE_RX_DPO_DROP] = "error-drop",
443  [INTERFACE_RX_DPO_INPUT] = "l2-input",
444  },
445 };
446 
447 VLIB_NODE_FUNCTION_MULTIARCH (interface_rx_dpo_l2_node,
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:404
static void interface_rx_dpo_mem_show(void)
VLIB_NODE_FUNCTION_MULTIARCH(interface_rx_dpo_ip4_node, interface_rx_dpo_ip4)
(constructor) VLIB_REGISTER_NODE (interface_rx_dpo_ip6_node)
#define CLIB_UNUSED(x)
Definition: clib.h:81
A virtual function table regisitered for a DPO type.
Definition: dpo.h:399
Interface DPO trace data.
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:204
static uword interface_rx_dpo_ip6(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
vnet_interface_main_t interface_main
Definition: vnet.h:56
static interface_rx_dpo_t * interface_rx_dpo_get(index_t index)
#define NULL
Definition: clib.h:57
u32 thread_index
Definition: main.h:179
static clib_error_t * interface_rx_dpo_interface_state_change(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
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
static u32 format_get_indent(u8 *s)
Definition: format.h:72
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(interface_rx_dpo_interface_state_change)
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:263
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:228
interface_rx_dpo_next_t_
unsigned char u8
Definition: types.h:56
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:140
static void interface_rx_dpo_unlock(dpo_id_t *dpo)
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:321
u32 sw_if_index
Definition: vxlan_gbp.api:39
#define always_inline
Definition: clib.h:94
vlib_node_registration_t interface_rx_dpo_ip4_node
(constructor) VLIB_REGISTER_NODE (interface_rx_dpo_ip4_node)
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:855
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
static index_t interface_rx_dpo_get_index(interface_rx_dpo_t *ido)
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(interface_rx_dpo_interface_delete)
void fib_show_memory_usage(const char *name, u32 in_use_elts, u32 allocd_elts, size_t size_elt)
Show the memory usage for a type.
Definition: fib_node.c:220
u8 * format_interface_rx_dpo(u8 *s, va_list *ap)
unsigned int u32
Definition: types.h:88
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
struct interface_rx_dpo_trace_t_ interface_rx_dpo_trace_t
Interface DPO trace data.
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:168
format_function_t format_vnet_sw_interface_name
static clib_error_t * interface_rx_dpo_hw_interface_state_change(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Registered callback for HW interface state changes.
u32 ido_sw_if_index
The Software interface index that the packets will be given as the ingress/rx interface.
void interface_rx_dpo_module_init(void)
dpo_type_t dpoi_type
the type
Definition: dpo.h:172
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:274
static const char *const interface_rx_dpo_ip4_nodes[]
The per-protocol VLIB graph nodes that are assigned to a glean object.
static uword interface_rx_dpo_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame, u8 is_l2)
#define PREDICT_FALSE(x)
Definition: clib.h:107
interface_rx_dpo_t * interface_rx_dpo_pool
pool of all interface DPOs
#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
The data-path object representing a change of receive interface.
u32 flags
Definition: vhost_user.h:115
static const char *const *const interface_rx_dpo_nodes[DPO_PROTO_NUM]
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:155
u16 n_vectors
Definition: node.h:401
vlib_main_t * vm
Definition: buffer.c:294
static void interface_rx_dpo_lock(dpo_id_t *dpo)
void interface_rx_dpo_add_or_lock(dpo_proto_t proto, u32 sw_if_index, dpo_id_t *dpo)
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:455
static interface_rx_dpo_t * interface_rx_dpo_alloc(void)
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:185
static u8 * format_interface_rx_dpo_trace(u8 *s, va_list *args)
static uword interface_rx_dpo_ip4(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
#define ASSERT(truth)
u16 ido_locks
number of locks.
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:57
static interface_rx_dpo_t * interface_rx_dpo_get_from_dpo(const dpo_id_t *dpo)
Definition: defs.h:47
#define DPO_PROTO_NUM
Definition: dpo.h:70
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:184
static const char *const interface_rx_dpo_ip6_nodes[]
static void vnet_update_l2_len(vlib_buffer_t *b)
Definition: l2_input.h:221
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:47
dpo_proto_t ido_proto
DPO protocol that the packets will have as they &#39;ingress&#39; on this interface.
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:267
u8 * format_dpo_proto(u8 *s, va_list *args)
format a DPO protocol
Definition: dpo.c:177
enum interface_rx_dpo_next_t_ interface_rx_dpo_next_t
#define vnet_buffer(b)
Definition: buffer.h:344
static uword interface_rx_dpo_l2(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:486
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:116
static index_t * interface_rx_dpo_db[DPO_PROTO_NUM]
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:58
VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION(interface_rx_dpo_hw_interface_state_change)
static const char *const interface_rx_dpo_l2_nodes[]
Definition: defs.h:46
static clib_error_t * interface_rx_dpo_interface_delete(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128