FD.io VPP  v17.07.01-10-g3be13f0
Vector Packet Processing
interface_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 #include <vnet/dpo/interface_dpo.h>
17 #include <vnet/fib/fib_node.h>
18 
19 /*
20  * The 'DB' of interface DPOs.
21  * There is only one per-interface per-protocol, so this is a per-interface
22  * vector
23  */
25 
26 static interface_dpo_t *
28 {
29  interface_dpo_t *ido;
30 
32 
33  return (ido);
34 }
35 
36 static inline interface_dpo_t *
38 {
40 
41  return (interface_dpo_get(dpo->dpoi_index));
42 }
43 
44 static inline index_t
46 {
47  return (ido - interface_dpo_pool);
48 }
49 
50 static void
52 {
53  interface_dpo_t *ido;
54 
55  ido = interface_dpo_get_from_dpo(dpo);
56  ido->ido_locks++;
57 }
58 
59 static void
61 {
62  interface_dpo_t *ido;
63 
64  ido = interface_dpo_get_from_dpo(dpo);
65  ido->ido_locks--;
66 
67  if (0 == ido->ido_locks)
68  {
72  }
73 }
74 
75 /*
76  * interface_dpo_add_or_lock
77  *
78  * Add/create and lock a new or lock an existing for the interface DPO
79  * on the interface and protocol given
80  */
81 void
83  u32 sw_if_index,
84  dpo_id_t *dpo)
85 {
86  interface_dpo_t *ido;
87 
89  sw_if_index,
91 
92  if (INDEX_INVALID == interface_dpo_db[proto][sw_if_index])
93  {
94  ido = interface_dpo_alloc();
95 
96  ido->ido_sw_if_index = sw_if_index;
97  ido->ido_proto = proto;
98 
99  interface_dpo_db[proto][sw_if_index] =
101  }
102  else
103  {
104  ido = interface_dpo_get(interface_dpo_db[proto][sw_if_index]);
105  }
106 
107  dpo_set(dpo, DPO_INTERFACE, proto, interface_dpo_get_index(ido));
108 }
109 
110 
111 static clib_error_t *
113  u32 sw_if_index,
114  u32 flags)
115 {
116  /*
117  */
118  return (NULL);
119 }
120 
123 
124 /**
125  * @brief Registered callback for HW interface state changes
126  */
127 static clib_error_t *
129  u32 hw_if_index,
130  u32 flags)
131 {
132  return (NULL);
133 }
134 
137 
138 static clib_error_t *
140  u32 sw_if_index,
141  u32 is_add)
142 {
143  return (NULL);
144 }
145 
148 
149 u8*
150 format_interface_dpo (u8* s, va_list *ap)
151 {
152  index_t index = va_arg(*ap, index_t);
153  CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
154  vnet_main_t * vnm = vnet_get_main();
155  interface_dpo_t *ido = interface_dpo_get(index);
156 
157  return (format(s, "%U-dpo: %U",
159  vnm,
161  format_dpo_proto, ido->ido_proto));
162 }
163 
164 static void
166 {
167  fib_show_memory_usage("Interface",
170  sizeof(interface_dpo_t));
171 }
172 
173 
174 const static dpo_vft_t interface_dpo_vft = {
176  .dv_unlock = interface_dpo_unlock,
177  .dv_format = format_interface_dpo,
178  .dv_mem_show = interface_dpo_mem_show,
179 };
180 
181 /**
182  * @brief The per-protocol VLIB graph nodes that are assigned to a glean
183  * object.
184  *
185  * this means that these graph nodes are ones from which a glean is the
186  * parent object in the DPO-graph.
187  */
188 const static char* const interface_dpo_ip4_nodes[] =
189 {
190  "interface-dpo-ip4",
191  NULL,
192 };
193 const static char* const interface_dpo_ip6_nodes[] =
194 {
195  "interface-dpo-ip4",
196  NULL,
197 };
198 
199 const static char* const * const interface_dpo_nodes[DPO_PROTO_NUM] =
200 {
203  [DPO_PROTO_MPLS] = NULL,
204 };
205 
206 void
208 {
210  &interface_dpo_vft,
212 }
213 
214 /**
215  * @brief Interface DPO trace data
216  */
218 {
221 
223 {
227 
230  vlib_node_runtime_t * node,
231  vlib_frame_t * from_frame)
232 {
233  u32 n_left_from, next_index, * from, * to_next;
234  u32 thread_index = vlib_get_thread_index ();
236 
237  im = &vnet_get_main ()->interface_main;
238  from = vlib_frame_vector_args (from_frame);
239  n_left_from = from_frame->n_vectors;
240 
241  next_index = node->cached_next_index;
242 
243  while (n_left_from > 0)
244  {
245  u32 n_left_to_next;
246 
247  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
248 
249  while (n_left_from >= 4 && n_left_to_next > 2)
250  {
251  const interface_dpo_t *ido0, *ido1;
252  u32 bi0, idoi0, bi1, idoi1;
253  vlib_buffer_t *b0, *b1;
254 
255  bi0 = from[0];
256  to_next[0] = bi0;
257  bi1 = from[1];
258  to_next[1] = bi1;
259  from += 2;
260  to_next += 2;
261  n_left_from -= 2;
262  n_left_to_next -= 2;
263 
264  b0 = vlib_get_buffer (vm, bi0);
265  b1 = vlib_get_buffer (vm, bi1);
266 
267  idoi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
268  idoi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
269  ido0 = interface_dpo_get(idoi0);
270  ido1 = interface_dpo_get(idoi1);
271 
272  vnet_buffer(b0)->sw_if_index[VLIB_RX] = ido0->ido_sw_if_index;
273  vnet_buffer(b1)->sw_if_index[VLIB_RX] = ido1->ido_sw_if_index;
274 
277  thread_index,
278  ido0->ido_sw_if_index,
279  1,
280  vlib_buffer_length_in_chain (vm, b0));
283  thread_index,
284  ido1->ido_sw_if_index,
285  1,
286  vlib_buffer_length_in_chain (vm, b1));
287 
289  {
291 
292  tr0 = vlib_add_trace (vm, node, b0, sizeof (*tr0));
293  tr0->sw_if_index = ido0->ido_sw_if_index;
294  }
296  {
298 
299  tr1 = vlib_add_trace (vm, node, b1, sizeof (*tr1));
300  tr1->sw_if_index = ido1->ido_sw_if_index;
301  }
302 
303  vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
304  n_left_to_next, bi0, bi1,
307  }
308 
309  while (n_left_from > 0 && n_left_to_next > 0)
310  {
311  const interface_dpo_t * ido0;
312  vlib_buffer_t * b0;
313  u32 bi0, idoi0;
314 
315  bi0 = from[0];
316  to_next[0] = bi0;
317  from += 1;
318  to_next += 1;
319  n_left_from -= 1;
320  n_left_to_next -= 1;
321 
322  b0 = vlib_get_buffer (vm, bi0);
323 
324  idoi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
325  ido0 = interface_dpo_get(idoi0);
326 
327  /* Swap the RX interface of the packet to the one the
328  * interface DPR represents */
329  vnet_buffer(b0)->sw_if_index[VLIB_RX] = ido0->ido_sw_if_index;
330 
331  /* Bump the interface's RX coutners */
334  thread_index,
335  ido0->ido_sw_if_index,
336  1,
337  vlib_buffer_length_in_chain (vm, b0));
338 
340  {
342 
343  tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
344  tr->sw_if_index = ido0->ido_sw_if_index;
345  }
346 
347  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
348  n_left_to_next, bi0,
350  }
351  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
352  }
353  return from_frame->n_vectors;
354 }
355 
356 static u8 *
357 format_interface_dpo_trace (u8 * s, va_list * args)
358 {
359  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
360  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
361  interface_dpo_trace_t * t = va_arg (*args, interface_dpo_trace_t *);
362  uword indent = format_get_indent (s);
363  s = format (s, "%U sw_if_index:%d",
364  format_white_space, indent,
365  t->sw_if_index);
366  return s;
367 }
368 
369 static uword
371  vlib_node_runtime_t * node,
372  vlib_frame_t * from_frame)
373 {
374  return (interface_dpo_inline(vm, node, from_frame));
375 }
376 
377 static uword
379  vlib_node_runtime_t * node,
380  vlib_frame_t * from_frame)
381 {
382  return (interface_dpo_inline(vm, node, from_frame));
383 }
384 
386  .function = interface_dpo_ip4,
387  .name = "interface-dpo-ip4",
388  .vector_size = sizeof (u32),
389  .format_trace = format_interface_dpo_trace,
390 
391  .n_next_nodes = 2,
392  .next_nodes = {
393  [INTERFACE_DPO_DROP] = "ip4-drop",
394  [INTERFACE_DPO_INPUT] = "ip4-input",
395  },
396 };
397 
400 
401 VLIB_REGISTER_NODE (interface_dpo_ip6_node) = {
402  .function = interface_dpo_ip6,
403  .name = "interface-dpo-ip6",
404  .vector_size = sizeof (u32),
405  .format_trace = format_interface_dpo_trace,
406 
407  .n_next_nodes = 2,
408  .next_nodes = {
409  [INTERFACE_DPO_DROP] = "ip6-drop",
410  [INTERFACE_DPO_INPUT] = "ip6-input",
411  },
412 };
413 
414 VLIB_NODE_FUNCTION_MULTIARCH (interface_dpo_ip6_node,
416 
VLIB_NODE_FUNCTION_MULTIARCH(interface_dpo_ip4_node, interface_dpo_ip4)
(constructor) VLIB_REGISTER_NODE (interface_dpo_ip6_node)
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:341
#define CLIB_UNUSED(x)
Definition: clib.h:79
A virtual function table regisitered for a DPO type.
Definition: dpo.h:336
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:211
u16 ido_locks
number of locks.
Definition: interface_dpo.h:47
static interface_dpo_t * interface_dpo_get(index_t index)
Definition: interface_dpo.h:62
static clib_error_t * interface_dpo_interface_delete(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static uword interface_dpo_ip4(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
vlib_node_registration_t interface_dpo_ip4_node
(constructor) VLIB_REGISTER_NODE (interface_dpo_ip4_node)
vnet_interface_main_t interface_main
Definition: vnet.h:56
interface_dpo_next_t_
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(interface_dpo_interface_state_change)
#define NULL
Definition: clib.h:55
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:459
void interface_dpo_add_or_lock(dpo_proto_t proto, u32 sw_if_index, dpo_id_t *dpo)
Definition: interface_dpo.c:82
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 index_t * interface_dpo_db[DPO_PROTO_NUM]
Definition: interface_dpo.c:24
static interface_dpo_t * interface_dpo_get_from_dpo(const dpo_id_t *dpo)
Definition: interface_dpo.c:37
static void interface_dpo_lock(dpo_id_t *dpo)
Definition: interface_dpo.c:51
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
The data-path object representing interfaceing the packet, i.e.
Definition: interface_dpo.h:25
static const char *const *const interface_dpo_nodes[DPO_PROTO_NUM]
static const char *const interface_dpo_ip6_nodes[]
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:100
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:121
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:260
#define always_inline
Definition: clib.h:84
static uword format_get_indent(u8 *s)
Definition: format.h:72
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:653
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
void interface_dpo_module_init(void)
VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION(interface_dpo_hw_interface_state_change)
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:221
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
static uword interface_dpo_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(interface_dpo_interface_delete)
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:152
format_function_t format_vnet_sw_interface_name
dpo_type_t dpoi_type
the type
Definition: dpo.h:156
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:241
#define PREDICT_FALSE(x)
Definition: clib.h:97
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
#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:216
#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:366
dpo_proto_t ido_proto
DPO protocol that the packets will have as they &#39;ingress&#39; on this interface.
Definition: interface_dpo.h:42
static clib_error_t * interface_dpo_interface_state_change(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
u16 n_vectors
Definition: node.h:345
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:185
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:85
struct interface_dpo_trace_t_ interface_dpo_trace_t
Interface DPO trace data.
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:159
static const char *const interface_dpo_ip4_nodes[]
The per-protocol VLIB graph nodes that are assigned to a glean object.
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:460
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
enum interface_dpo_next_t_ interface_dpo_next_t
static uword interface_dpo_ip6(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
static u8 * format_interface_dpo_trace(u8 *s, va_list *args)
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
Definition: defs.h:47
#define DPO_PROTO_NUM
Definition: dpo.h:73
u32 ido_sw_if_index
The Software interface index that the packets will be given as the ingress/rx interface.
Definition: interface_dpo.h:31
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:168
unsigned char u8
Definition: types.h:56
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:47
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:269
static interface_dpo_t * interface_dpo_alloc(void)
Definition: interface_dpo.c:27
u8 * format_dpo_proto(u8 *s, va_list *args)
format a DPO protocol
Definition: dpo.c:151
u8 * format_interface_dpo(u8 *s, va_list *ap)
static clib_error_t * interface_dpo_hw_interface_state_change(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Registered callback for HW interface state changes.
#define vnet_buffer(b)
Definition: buffer.h:304
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:144
static index_t interface_dpo_get_index(interface_dpo_t *ido)
Definition: interface_dpo.c:45
static void interface_dpo_unlock(dpo_id_t *dpo)
Definition: interface_dpo.c:60
interface_dpo_t * interface_dpo_pool
pool of all interface DPOs
Definition: interface_dpo.h:59
u32 flags
Definition: vhost-user.h:76
#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:485
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:74
static void interface_dpo_mem_show(void)
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
Definition: defs.h:46
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109