FD.io VPP  v18.01.1-37-g7ea3975
Vector Packet Processing
l2_bridge_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/l2_bridge_dpo.h>
17 #include <vnet/fib/fib_node.h>
18 #include <vnet/ethernet/ethernet.h>
19 
20 /*
21  * The 'DB' of L2 bridge DPOs.
22  * There is only one per-interface, so this is a per-interface vector
23  */
25 
26 static l2_bridge_dpo_t *
28 {
29  l2_bridge_dpo_t *l2b;
30 
32 
33  return (l2b);
34 }
35 
36 static inline l2_bridge_dpo_t *
38 {
40 
41  return (l2_bridge_dpo_get(dpo->dpoi_index));
42 }
43 
44 static inline index_t
46 {
47  return (l2b - l2_bridge_dpo_pool);
48 }
49 
50 static void
52 {
53  l2_bridge_dpo_t *l2b;
54 
55  l2b = l2_bridge_dpo_get_from_dpo(dpo);
56  l2b->l2b_locks++;
57 }
58 
59 static void
61 {
62  l2_bridge_dpo_t *l2b;
63 
64  l2b = l2_bridge_dpo_get_from_dpo(dpo);
65  l2b->l2b_locks--;
66 
67  if (0 == l2b->l2b_locks)
68  {
71  }
72 }
73 
74 /*
75  * l2_bridge_dpo_add_or_lock
76  *
77  * Add/create and lock a new or lock an existing for the L2 Bridge
78  * on the interface given
79  */
80 void
82  dpo_id_t *dpo)
83 {
84  l2_bridge_dpo_t *l2b;
85 
87  sw_if_index,
89 
90  if (INDEX_INVALID == l2_bridge_dpo_db[sw_if_index])
91  {
92  l2b = l2_bridge_dpo_alloc();
93 
94  l2b->l2b_sw_if_index = sw_if_index;
95 
96  l2_bridge_dpo_db[sw_if_index] =
98  }
99  else
100  {
101  l2b = l2_bridge_dpo_get(l2_bridge_dpo_db[sw_if_index]);
102  }
103 
105 }
106 
107 
108 static clib_error_t *
110  u32 sw_if_index,
111  u32 flags)
112 {
113  /*
114  */
115  return (NULL);
116 }
117 
120 
121 /**
122  * @brief Registered callback for HW interface state changes
123  */
124 static clib_error_t *
126  u32 hw_if_index,
127  u32 flags)
128 {
129  return (NULL);
130 }
131 
134 
135 static clib_error_t *
137  u32 sw_if_index,
138  u32 is_add)
139 {
140  return (NULL);
141 }
142 
145 
146 u8*
147 format_l2_bridge_dpo (u8* s, va_list *ap)
148 {
149  index_t index = va_arg(*ap, index_t);
150  CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
151  vnet_main_t * vnm = vnet_get_main();
152  l2_bridge_dpo_t *l2b = l2_bridge_dpo_get(index);
153 
154  return (format(s, "l2-bridge-%U-dpo",
156  vnm,
158 }
159 
160 static void
162 {
163  fib_show_memory_usage("L2-bridge",
166  sizeof(l2_bridge_dpo_t));
167 }
168 
169 
170 const static dpo_vft_t l2_bridge_dpo_vft = {
172  .dv_unlock = l2_bridge_dpo_unlock,
173  .dv_format = format_l2_bridge_dpo,
174  .dv_mem_show = l2_bridge_dpo_mem_show,
175 };
176 
177 /**
178  * @brief The per-protocol VLIB graph nodes that are assigned to a glean
179  * object.
180  *
181  * this means that these graph nodes are ones from which a glean is the
182  * parent object in the DPO-graph.
183  */
184 const static char* const l2_bridge_dpo_l2_nodes[] =
185 {
186  "l2-bridge-dpo",
187  NULL,
188 };
189 
190 const static char* const * const l2_bridge_dpo_nodes[DPO_PROTO_NUM] =
191 {
193 };
194 
195 void
197 {
199  &l2_bridge_dpo_vft,
201 }
202 
203 /**
204  * @brief Interface DPO trace data
205  */
207 {
210 
212 {
216 
219  vlib_node_runtime_t * node,
220  vlib_frame_t * from_frame)
221 {
222  u32 n_left_from, next_index, * from, * to_next;
223 
224  from = vlib_frame_vector_args (from_frame);
225  n_left_from = from_frame->n_vectors;
226 
227  next_index = node->cached_next_index;
228 
229  while (n_left_from > 0)
230  {
231  u32 n_left_to_next;
232 
233  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
234 
235  while (n_left_from >= 4 && n_left_to_next > 2)
236  {
237  const l2_bridge_dpo_t *l2b0, *l2b1;
238  u32 bi0, l2bi0, bi1, l2bi1;
239  vlib_buffer_t *b0, *b1;
240  u8 len0, len1;
241 
242  bi0 = from[0];
243  to_next[0] = bi0;
244  bi1 = from[1];
245  to_next[1] = bi1;
246  from += 2;
247  to_next += 2;
248  n_left_from -= 2;
249  n_left_to_next -= 2;
250 
251  b0 = vlib_get_buffer (vm, bi0);
252  b1 = vlib_get_buffer (vm, bi1);
253 
254  l2bi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
255  l2bi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
256  l2b0 = l2_bridge_dpo_get(l2bi0);
257  l2b1 = l2_bridge_dpo_get(l2bi1);
258 
259  vnet_buffer(b0)->sw_if_index[VLIB_TX] = l2b0->l2b_sw_if_index;
260  vnet_buffer(b1)->sw_if_index[VLIB_TX] = l2b1->l2b_sw_if_index;
261 
262  len0 = ((u8*)vlib_buffer_get_current(b0) -
264  len1 = ((u8*)vlib_buffer_get_current(b1) -
266  vnet_buffer(b0)->l2.l2_len = len0;
267  vnet_buffer(b1)->l2.l2_len = len1;
268 
269  vlib_buffer_advance(b0, -len0);
270  vlib_buffer_advance(b1, -len1);
271 
273  {
275 
276  tr0 = vlib_add_trace (vm, node, b0, sizeof (*tr0));
277  tr0->sw_if_index = l2b0->l2b_sw_if_index;
278  }
280  {
282 
283  tr1 = vlib_add_trace (vm, node, b1, sizeof (*tr1));
284  tr1->sw_if_index = l2b1->l2b_sw_if_index;
285  }
286 
287  vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
288  n_left_to_next, bi0, bi1,
291  }
292 
293  while (n_left_from > 0 && n_left_to_next > 0)
294  {
295  const l2_bridge_dpo_t * l2b0;
296  vlib_buffer_t * b0;
297  u32 bi0, l2bi0;
298  u8 len0;
299 
300  bi0 = from[0];
301  to_next[0] = bi0;
302  from += 1;
303  to_next += 1;
304  n_left_from -= 1;
305  n_left_to_next -= 1;
306 
307  b0 = vlib_get_buffer (vm, bi0);
308 
309  l2bi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
310  l2b0 = l2_bridge_dpo_get(l2bi0);
311 
312  vnet_buffer(b0)->sw_if_index[VLIB_TX] = l2b0->l2b_sw_if_index;
313 
314  /*
315  * take that, rewind it back...
316  */
317  len0 = ((u8*)vlib_buffer_get_current(b0) -
319  vnet_buffer(b0)->l2.l2_len = len0;
320  vlib_buffer_advance(b0, -len0);
321 
323  {
325 
326  tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
327  tr->sw_if_index = l2b0->l2b_sw_if_index;
328  }
329 
330  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
331  n_left_to_next, bi0,
333  }
334  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
335  }
336  return from_frame->n_vectors;
337 }
338 
339 static u8 *
340 format_l2_bridge_dpo_trace (u8 * s, va_list * args)
341 {
342  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
343  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
344  l2_bridge_dpo_trace_t * t = va_arg (*args, l2_bridge_dpo_trace_t *);
345  u32 indent = format_get_indent (s);
346  s = format (s, "%U sw_if_index:%d",
347  format_white_space, indent,
348  t->sw_if_index);
349  return s;
350 }
351 
352 static uword
354  vlib_node_runtime_t * node,
355  vlib_frame_t * from_frame)
356 {
357  return (l2_bridge_dpo_inline(vm, node, from_frame));
358 }
359 
360 
362  .function = l2_bridge_dpo_l2,
363  .name = "l2-bridge-dpo",
364  .vector_size = sizeof (u32),
365  .format_trace = format_l2_bridge_dpo_trace,
366 
367  .n_next_nodes = 2,
368  .next_nodes = {
369  [L2_BRIDGE_DPO_DROP] = "error-drop",
370  [L2_BRIDGE_DPO_OUTPUT] = "l2-output",
371  },
372 };
373 
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:382
#define CLIB_UNUSED(x)
Definition: clib.h:79
A virtual function table regisitered for a DPO type.
Definition: dpo.h:377
static l2_bridge_dpo_t * l2_bridge_dpo_get_from_dpo(const dpo_id_t *dpo)
Definition: l2_bridge_dpo.c:37
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
struct l2_bridge_dpo_trace_t_ l2_bridge_dpo_trace_t
Interface DPO trace data.
static index_t * l2_bridge_dpo_db
Definition: l2_bridge_dpo.c:24
#define NULL
Definition: clib.h:55
u8 * format_l2_bridge_dpo(u8 *s, va_list *ap)
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 l2_bridge_dpo_t * l2_bridge_dpo_alloc(void)
Definition: l2_bridge_dpo.c:27
u16 l2b_locks
number of locks.
Definition: l2_bridge_dpo.h:37
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
static const char *const *const l2_bridge_dpo_nodes[DPO_PROTO_NUM]
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:225
static const char *const l2_bridge_dpo_l2_nodes[]
The per-protocol VLIB graph nodes that are assigned to a glean object.
Interface DPO trace data.
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:140
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
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
enum l2_bridge_dpo_next_t_ l2_bridge_dpo_next_t
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
The data-path object representing an L2 bridge.
Definition: l2_bridge_dpo.h:27
static void l2_bridge_dpo_mem_show(void)
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(l2_bridge_dpo_interface_delete)
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
format_function_t format_vnet_sw_interface_name
static ethernet_header_t * ethernet_buffer_get_header(vlib_buffer_t *b)
Definition: ethernet.h:352
static u8 * format_l2_bridge_dpo_trace(u8 *s, va_list *args)
l2_bridge_dpo_next_t_
dpo_type_t dpoi_type
the type
Definition: dpo.h:170
void l2_bridge_dpo_add_or_lock(u32 sw_if_index, dpo_id_t *dpo)
Definition: l2_bridge_dpo.c:81
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:195
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:271
VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION(l2_bridge_dpo_hw_interface_state_change)
#define PREDICT_FALSE(x)
Definition: clib.h:105
#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
vlib_node_registration_t l2_bridge_dpo_l2_node
(constructor) VLIB_REGISTER_NODE (l2_bridge_dpo_l2_node)
#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
void l2_bridge_dpo_module_init(void)
static uword l2_bridge_dpo_l2(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
u16 n_vectors
Definition: node.h:344
vlib_main_t * vm
Definition: buffer.c:283
l2_bridge_dpo_t * l2_bridge_dpo_pool
pool of all interface DPOs
Definition: l2_bridge_dpo.h:48
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:93
static void l2_bridge_dpo_unlock(dpo_id_t *dpo)
Definition: l2_bridge_dpo.c:60
static clib_error_t * l2_bridge_dpo_interface_state_change(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
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
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:456
static l2_bridge_dpo_t * l2_bridge_dpo_get(index_t index)
Definition: l2_bridge_dpo.h:51
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:208
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
u32 l2b_sw_if_index
The Software interface index that the packets will output on.
Definition: l2_bridge_dpo.h:32
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(l2_bridge_dpo_interface_state_change)
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:182
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:267
static index_t l2_bridge_dpo_get_index(l2_bridge_dpo_t *l2b)
Definition: l2_bridge_dpo.c:45
#define vnet_buffer(b)
Definition: buffer.h:326
#define VLIB_NODE_FUNCTION_MULTIARCH(node, fn)
Definition: node.h:158
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
static clib_error_t * l2_bridge_dpo_interface_delete(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
static void l2_bridge_dpo_lock(dpo_id_t *dpo)
Definition: l2_bridge_dpo.c:51
u32 flags
Definition: vhost-user.h:77
#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:481
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
static uword l2_bridge_dpo_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
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
static clib_error_t * l2_bridge_dpo_hw_interface_state_change(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Registered callback for HW interface state changes.
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128