FD.io VPP  v20.01-48-g3e0dafb74
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 
140  from = vlib_frame_vector_args (frame);
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 */
206  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
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 */
246  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
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)
261  vlib_put_frame_to_node (vm, l2output_node.index, f);
262  else
263  vnet_put_frame_to_sw_interface (vnm, sw_if_index, f);
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  */
span_main_t span_main
Definition: span.c:24
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:124
#define CLIB_UNUSED(x)
Definition: clib.h:82
char ** l2output_get_feat_names(void)
Definition: l2_output.c:39
span_mirror_t mirror_rxtx[SPAN_FEAT_N][VLIB_N_RX_TX]
Definition: span.h:38
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
vlib_node_registration_t l2output_node
(constructor) VLIB_REGISTER_NODE (l2output_node)
Definition: l2_output.c:447
vlib_main_t * vlib_main
Definition: span.h:54
#define PREDICT_TRUE(x)
Definition: clib.h:112
static char * span_error_strings[]
Definition: node.c:55
u32 num_mirror_ports
Definition: span.h:33
u32 mirror_sw_if_index
Definition: span.h:63
span_error_t
Definition: node.c:47
int i
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
u32 l2_output_next[32]
Definition: span.h:45
#define VLIB_NODE_FN(node)
Definition: node.h:202
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:451
vlib_node_registration_t span_l2_output_node
(constructor) VLIB_REGISTER_NODE (span_l2_output_node)
Definition: node.c:323
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
static vlib_buffer_t * vlib_buffer_copy(vlib_main_t *vm, vlib_buffer_t *b)
Definition: buffer_funcs.h:989
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
vlib_node_registration_t span_input_node
(constructor) VLIB_REGISTER_NODE (span_input_node)
Definition: node.c:308
vlib_rx_or_tx_t
Definition: defs.h:44
clib_bitmap_t * mirror_ports
Definition: span.h:32
vlib_node_registration_t span_l2_input_node
(constructor) VLIB_REGISTER_NODE (span_l2_input_node)
Definition: node.c:318
#define static_always_inline
Definition: clib.h:99
vl_api_interface_index_t sw_if_index
Definition: gre.api:59
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
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
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
unsigned int u32
Definition: types.h:88
clib_error_t * span_init(vlib_main_t *vm)
Definition: node.c:329
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
Definition: buffer_funcs.h:257
#define clib_bitmap_foreach(i, ai, body)
Macro to iterate across set bits in a bitmap.
Definition: bitmap.h:361
vlib_node_registration_t span_output_node
(constructor) VLIB_REGISTER_NODE (span_output_node)
Definition: node.c:313
span_interface_t * interfaces
Definition: span.h:48
vnet_main_t * vnet_main
Definition: span.h:55
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:194
#define PREDICT_FALSE(x)
Definition: clib.h:111
#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: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:338
vlib_main_t * vm
Definition: in2out_ed.c:1810
The fine-grained event logger allows lightweight, thread-safe event logging at minimum cost...
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:397
static void vnet_put_frame_to_sw_interface(vnet_main_t *vnm, u32 sw_if_index, vlib_frame_t *f)
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:302
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
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:456
char ** l2input_get_feat_names(void)
Return an array of strings containing graph node names of each feature.
Definition: l2_input.c:62
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1810
u32 l2_input_next[32]
Definition: span.h:44
#define span_node_defs
Definition: node.c:296
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:515
u16 flags
Definition: node.h:388
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
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
static u8 * format_span_trace(u8 *s, va_list *args)
Definition: node.c:30
u32 src_sw_if_index
Definition: span.h:62
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
VLIB buffer representation.
Definition: buffer.h:102
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:244
#define VLIB_FRAME_TRACE
Definition: node.h:435
span_feat_t
Definition: span.h:23
#define vnet_buffer(b)
Definition: buffer.h:408
#define foreach_span_error
Definition: node.c:44
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1811
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
u32 max_sw_if_index
Definition: span.h:51
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
Definition: defs.h:46