FD.io VPP  v21.06-3-gbb25fbf28
Vector Packet Processing
node.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 <vlib/vlib.h>
17 #include <vnet/vnet.h>
18 #include <vppinfra/error.h>
19 
20 #include <vnet/span/span.h>
21 #include <vnet/l2/l2_input.h>
22 #include <vnet/l2/l2_output.h>
23 #include <vnet/l2/feat_bitmap.h>
24 
25 #include <vppinfra/error.h>
26 #include <vppinfra/elog.h>
27 
28 /* packet trace format function */
29 static u8 *
30 format_span_trace (u8 * s, va_list * args)
31 {
32  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
33  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
34  span_trace_t *t = va_arg (*args, span_trace_t *);
35 
36  vnet_main_t *vnm = vnet_get_main ();
37  s = format (s, "SPAN: mirrored %U -> %U",
40 
41  return s;
42 }
43 
44 #define foreach_span_error \
45 _(HITS, "SPAN incoming packets processed")
46 
47 typedef enum
48 {
49 #define _(sym,str) SPAN_ERROR_##sym,
51 #undef _
53 } span_error_t;
54 
55 static char *span_error_strings[] = {
56 #define _(sym,string) string,
58 #undef _
59 };
60 
63  vlib_buffer_t * b0, vlib_frame_t ** mirror_frames,
65 {
66  vlib_buffer_t *c0;
67  span_main_t *sm = &span_main;
68  vnet_main_t *vnm = vnet_get_main ();
69  u32 *to_mirror_next = 0;
70  u32 i;
71  span_interface_t *si0;
72  span_mirror_t *sm0;
73 
74  if (sw_if_index0 >= vec_len (sm->interfaces))
75  return;
76 
77  si0 = vec_elt_at_index (sm->interfaces, sw_if_index0);
78  sm0 = &si0->mirror_rxtx[sf][rxtx];
79 
80  if (sm0->num_mirror_ports == 0)
81  return;
82 
83  /* Don't do it again */
84  if (PREDICT_FALSE (b0->flags & VNET_BUFFER_F_SPAN_CLONE))
85  return;
86 
87  /* *INDENT-OFF* */
89  {
90  if (mirror_frames[i] == 0)
91  {
92  if (sf == SPAN_FEAT_L2)
93  mirror_frames[i] = vlib_get_frame_to_node (vm, l2output_node.index);
94  else
95  mirror_frames[i] = vnet_get_frame_to_sw_interface (vnm, i);
96  }
97  to_mirror_next = vlib_frame_vector_args (mirror_frames[i]);
98  to_mirror_next += mirror_frames[i]->n_vectors;
99  /* This can fail */
100  c0 = vlib_buffer_copy (vm, b0);
101  if (PREDICT_TRUE(c0 != 0))
102  {
103  vnet_buffer (c0)->sw_if_index[VLIB_TX] = i;
104  c0->flags |= VNET_BUFFER_F_SPAN_CLONE;
105  if (sf == SPAN_FEAT_L2)
106  vnet_buffer (c0)->l2.feature_bitmap = L2OUTPUT_FEAT_OUTPUT;
107  to_mirror_next[0] = vlib_get_buffer_index (vm, c0);
108  mirror_frames[i]->n_vectors++;
109  if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
110  {
111  span_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
112  t->src_sw_if_index = sw_if_index0;
113  t->mirror_sw_if_index = i;
114 #if 0
115  /* Enable this path to allow packet trace of SPAN packets.
116  Note that all SPAN packets will show up on the trace output
117  with the first SPAN packet (since they are in the same frame)
118  thus making trace output of the original packet confusing */
119  mirror_frames[i]->flags |= VLIB_FRAME_TRACE;
120  c0->flags |= VLIB_BUFFER_IS_TRACED;
121 #endif
122  }
123  }
124  }
125  /* *INDENT-ON* */
126 }
127 
131  span_feat_t sf)
132 {
133  span_main_t *sm = &span_main;
134  vnet_main_t *vnm = vnet_get_main ();
135  u32 n_left_from, *from, *to_next;
136  u32 next_index;
138  static __thread vlib_frame_t **mirror_frames = 0;
139 
141  n_left_from = frame->n_vectors;
142  next_index = node->cached_next_index;
143 
144  vec_validate_aligned (mirror_frames, sm->max_sw_if_index,
146 
147  while (n_left_from > 0)
148  {
149  u32 n_left_to_next;
150 
151  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
152 
153  while (n_left_from >= 4 && n_left_to_next >= 2)
154  {
155  u32 bi0;
156  u32 bi1;
157  vlib_buffer_t *b0;
158  vlib_buffer_t *b1;
159  u32 sw_if_index0;
160  u32 next0 = 0;
161  u32 sw_if_index1;
162  u32 next1 = 0;
163 
164  /* speculatively enqueue b0, b1 to the current next frame */
165  to_next[0] = bi0 = from[0];
166  to_next[1] = bi1 = from[1];
167  to_next += 2;
168  n_left_to_next -= 2;
169  from += 2;
170  n_left_from -= 2;
171 
172  b0 = vlib_get_buffer (vm, bi0);
173  b1 = vlib_get_buffer (vm, bi1);
174  sw_if_index0 = vnet_buffer (b0)->sw_if_index[rxtx];
175  sw_if_index1 = vnet_buffer (b1)->sw_if_index[rxtx];
176 
177  span_mirror (vm, node, sw_if_index0, b0, mirror_frames, rxtx, sf);
178  span_mirror (vm, node, sw_if_index1, b1, mirror_frames, rxtx, sf);
179 
180  switch (sf)
181  {
182  case SPAN_FEAT_L2:
183  if (rxtx == VLIB_RX)
184  {
185  next0 = vnet_l2_feature_next (b0, sm->l2_input_next,
186  L2INPUT_FEAT_SPAN);
187  next1 = vnet_l2_feature_next (b1, sm->l2_input_next,
188  L2INPUT_FEAT_SPAN);
189  }
190  else
191  {
192  next0 = vnet_l2_feature_next (b0, sm->l2_output_next,
193  L2OUTPUT_FEAT_SPAN);
194  next1 = vnet_l2_feature_next (b1, sm->l2_output_next,
195  L2OUTPUT_FEAT_SPAN);
196  }
197  break;
198  case SPAN_FEAT_DEVICE:
199  default:
200  vnet_feature_next (&next0, b0);
201  vnet_feature_next (&next1, b1);
202  break;
203  }
204 
205  /* verify speculative enqueue, maybe switch current next frame */
207  to_next, n_left_to_next,
208  bi0, bi1, next0, next1);
209  }
210  while (n_left_from > 0 && n_left_to_next > 0)
211  {
212  u32 bi0;
213  vlib_buffer_t *b0;
214  u32 sw_if_index0;
215  u32 next0 = 0;
216 
217  /* speculatively enqueue b0 to the current next frame */
218  to_next[0] = bi0 = from[0];
219  to_next += 1;
220  n_left_to_next -= 1;
221  from += 1;
222  n_left_from -= 1;
223 
224  b0 = vlib_get_buffer (vm, bi0);
225  sw_if_index0 = vnet_buffer (b0)->sw_if_index[rxtx];
226 
227  span_mirror (vm, node, sw_if_index0, b0, mirror_frames, rxtx, sf);
228 
229  switch (sf)
230  {
231  case SPAN_FEAT_L2:
232  if (rxtx == VLIB_RX)
233  next0 = vnet_l2_feature_next (b0, sm->l2_input_next,
234  L2INPUT_FEAT_SPAN);
235  else
236  next0 = vnet_l2_feature_next (b0, sm->l2_output_next,
237  L2OUTPUT_FEAT_SPAN);
238  break;
239  case SPAN_FEAT_DEVICE:
240  default:
241  vnet_feature_next (&next0, b0);
242  break;
243  }
244 
245  /* verify speculative enqueue, maybe switch current next frame */
247  n_left_to_next, bi0, next0);
248  }
249 
250  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
251  }
252 
253 
254  for (sw_if_index = 0; sw_if_index < vec_len (mirror_frames); sw_if_index++)
255  {
256  vlib_frame_t *f = mirror_frames[sw_if_index];
257  if (f == 0)
258  continue;
259 
260  if (sf == SPAN_FEAT_L2)
262  else
264  mirror_frames[sw_if_index] = 0;
265  }
266 
267  return frame->n_vectors;
268 }
269 
272 {
274 }
275 
278 {
280 }
281 
285 {
287 }
288 
292 {
294 }
295 
296 #define span_node_defs \
297  .vector_size = sizeof (u32), \
298  .format_trace = format_span_trace, \
299  .type = VLIB_NODE_TYPE_INTERNAL, \
300  .n_errors = ARRAY_LEN(span_error_strings), \
301  .error_strings = span_error_strings, \
302  .n_next_nodes = 0, \
303  .next_nodes = { \
304  [0] = "error-drop" \
305  }
306 
307 /* *INDENT-OFF* */
310  .name = "span-input",
311 };
312 
315  .name = "span-output",
316 };
317 
320  .name = "span-l2-input",
321 };
322 
325  .name = "span-l2-output",
326 };
327 
328 #ifndef CLIB_MARCH_VARIANT
330 {
331  span_main_t *sm = &span_main;
332 
333  sm->vlib_main = vm;
334  sm->vnet_main = vnet_get_main ();
335 
336  /* Initialize the feature next-node indexes */
338  span_l2_input_node.index,
341  sm->l2_input_next);
342 
344  span_l2_output_node.index,
347  sm->l2_output_next);
348  return 0;
349 }
350 
352 /* *INDENT-ON* */
353 #endif /* CLIB_MARCH_VARIANT */
354 
355 #undef span_node_defs
356 /*
357  * fd.io coding-style-patch-verification: ON
358  *
359  * Local Variables:
360  * eval: (c-set-style "gnu")
361  * End:
362  */
vlib.h
vlib_frame_t::n_vectors
u16 n_vectors
Definition: node.h:387
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
vlib_buffer_copy
static vlib_buffer_t * vlib_buffer_copy(vlib_main_t *vm, vlib_buffer_t *b)
Definition: buffer_funcs.h:1081
next_index
nat44_ei_hairpin_src_next_t next_index
Definition: nat44_ei_hairpinning.c:412
elog.h
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
f
vlib_frame_t * f
Definition: interface_output.c:1080
span_main_t::vlib_main
vlib_main_t * vlib_main
Definition: span.h:54
span_init
clib_error_t * span_init(vlib_main_t *vm)
Definition: node.c:329
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
span_main_t
Definition: span.h:41
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
span_mirror_t::num_mirror_ports
u32 num_mirror_ports
Definition: span.h:33
VLIB_RX
@ VLIB_RX
Definition: defs.h:46
SPAN_FEAT_DEVICE
@ SPAN_FEAT_DEVICE
Definition: span.h:25
span_main
span_main_t span_main
Definition: span.c:24
vlib_frame_t
Definition: node.h:372
vlib_get_frame_to_node
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:184
span_input_node
vlib_node_registration_t span_input_node
(constructor) VLIB_REGISTER_NODE (span_input_node)
Definition: node.c:308
foreach_span_error
#define foreach_span_error
Definition: node.c:44
span_error_strings
static char * span_error_strings[]
Definition: node.c:55
span_error_t
span_error_t
Definition: node.c:47
span_interface_t::mirror_rxtx
span_mirror_t mirror_rxtx[SPAN_FEAT_N][VLIB_N_RX_TX]
Definition: span.h:38
format_span_trace
static u8 * format_span_trace(u8 *s, va_list *args)
Definition: node.c:30
vlib_put_frame_to_node
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:218
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
error.h
VLIB_NODE_FN
#define VLIB_NODE_FN(node)
Definition: node.h:202
l2_output.h
CLIB_UNUSED
#define CLIB_UNUSED(x)
Definition: clib.h:90
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:437
l2output_get_feat_names
char ** l2output_get_feat_names(void)
Definition: l2_output.c:38
vec_elt_at_index
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Definition: vec_bootstrap.h:203
vnet_get_main
vnet_main_t * vnet_get_main(void)
Definition: pnat_test_stubs.h:56
L2OUTPUT_N_FEAT
@ L2OUTPUT_N_FEAT
Definition: l2_output.h:105
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
span_trace_t::mirror_sw_if_index
u32 mirror_sw_if_index
Definition: span.h:63
vnet_feature_next
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:322
vlib_get_buffer_index
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
Definition: buffer_funcs.h:324
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
vec_validate_aligned
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:534
vnet_get_frame_to_sw_interface
static vlib_frame_t * vnet_get_frame_to_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
Definition: interface_funcs.h:354
span_mirror
static_always_inline void span_mirror(vlib_main_t *vm, vlib_node_runtime_t *node, u32 sw_if_index0, vlib_buffer_t *b0, vlib_frame_t **mirror_frames, vlib_rx_or_tx_t rxtx, span_feat_t sf)
Definition: node.c:62
span_mirror_t::mirror_ports
clib_bitmap_t * mirror_ports
Definition: span.h:32
static_always_inline
#define static_always_inline
Definition: clib.h:112
uword
u64 uword
Definition: types.h:112
span.h
vlib_rx_or_tx_t
vlib_rx_or_tx_t
Definition: defs.h:44
l2input_get_feat_names
char ** l2input_get_feat_names(void)
Return an array of strings containing graph node names of each feature.
Definition: l2_input.c:59
i
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
L2INPUT_N_FEAT
@ L2INPUT_N_FEAT
Definition: l2_input.h:163
CLIB_CACHE_LINE_BYTES
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
SPAN_N_ERROR
@ SPAN_N_ERROR
Definition: node.c:52
span_l2_output_node
vlib_node_registration_t span_l2_output_node
(constructor) VLIB_REGISTER_NODE (span_l2_output_node)
Definition: node.c:323
l2_input.h
span_node_defs
#define span_node_defs
Definition: node.c:296
span_node_inline_fn
static_always_inline uword span_node_inline_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, vlib_rx_or_tx_t rxtx, span_feat_t sf)
Definition: node.c:129
vnet_l2_feature_next
static u32 vnet_l2_feature_next(vlib_buffer_t *b, u32 *next_nodes, u32 feat_bit)
Return the graph node index for the feature corresponding to the next set bit after clearing the curr...
Definition: feat_bitmap.h:94
vnet_main_t
Definition: vnet.h:76
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
format_vnet_sw_if_index_name
format_function_t format_vnet_sw_if_index_name
Definition: interface_funcs.h:455
format
description fragment has unexpected format
Definition: map.api:433
vlib_put_next_frame
vlib_put_next_frame(vm, node, next_index, 0)
vlib_frame_t::flags
u16 flags
Definition: node.h:378
SPAN_FEAT_L2
@ SPAN_FEAT_L2
Definition: span.h:26
u32
unsigned int u32
Definition: types.h:88
VLIB_INIT_FUNCTION
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
span_output_node
vlib_node_registration_t span_output_node
(constructor) VLIB_REGISTER_NODE (span_output_node)
Definition: node.c:313
vnet_put_frame_to_sw_interface
static void vnet_put_frame_to_sw_interface(vnet_main_t *vnm, u32 sw_if_index, vlib_frame_t *f)
Definition: interface_funcs.h:361
span_mirror_t
Definition: span.h:30
span_main_t::vnet_main
vnet_main_t * vnet_main
Definition: span.h:55
span_l2_input_node
vlib_node_registration_t span_l2_input_node
(constructor) VLIB_REGISTER_NODE (span_l2_input_node)
Definition: node.c:318
vlib_main_t
Definition: main.h:102
vlib_node_t
Definition: node.h:247
l2output_node
vlib_node_registration_t l2output_node
(constructor) VLIB_REGISTER_NODE (l2output_node)
Definition: l2_output.c:446
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
clib_error_t
Definition: clib_error.h:21
span_main_t::l2_input_next
u32 l2_input_next[32]
Definition: span.h:44
feat_bitmap.h
span_main_t::l2_output_next
u32 l2_output_next[32]
Definition: span.h:45
vlib_init_function_t
clib_error_t *() vlib_init_function_t(struct vlib_main_t *vm)
Definition: init.h:51
vlib_validate_buffer_enqueue_x2
#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
vnet.h
span_interface_t
Definition: span.h:36
span_main_t::max_sw_if_index
u32 max_sw_if_index
Definition: span.h:51
clib_bitmap_foreach
#define clib_bitmap_foreach(i, ai)
Macro to iterate across set bits in a bitmap.
Definition: bitmap.h:361
vlib_node_runtime_t
Definition: node.h:454
span_trace_t::src_sw_if_index
u32 src_sw_if_index
Definition: span.h:62
VLIB_FRAME_TRACE
#define VLIB_FRAME_TRACE
Definition: node.h:425
from
from
Definition: nat44_ei_hairpinning.c:415
PREDICT_TRUE
#define PREDICT_TRUE(x)
Definition: clib.h:125
span_main_t::interfaces
span_interface_t * interfaces
Definition: span.h:48
sw_if_index
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
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
feat_bitmap_init_next_nodes
static void feat_bitmap_init_next_nodes(vlib_main_t *vm, u32 node_index, u32 num_features, char **feat_names, u32 *next_nodes)
Initialize the feature next-node indexes of a graph node.
Definition: feat_bitmap.h:43
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
span_trace_t
Definition: span.h:60
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
span_feat_t
span_feat_t
Definition: span.h:23