FD.io VPP  v17.10-9-gd594711
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 
29 
30 /* packet trace format function */
31 u8 *
32 format_span_trace (u8 * s, va_list * args)
33 {
34  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
35  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
36  span_trace_t *t = va_arg (*args, span_trace_t *);
37 
38  vnet_main_t *vnm = &vnet_main;
39  s = format (s, "SPAN: mirrored %U -> %U",
42 
43  return s;
44 }
45 
46 #define foreach_span_error \
47 _(HITS, "SPAN incomming packets processed")
48 
49 typedef enum
50 {
51 #define _(sym,str) SPAN_ERROR_##sym,
53 #undef _
55 } span_error_t;
56 
57 static char *span_error_strings[] = {
58 #define _(sym,string) string,
60 #undef _
61 };
62 
65  vlib_buffer_t * b0, vlib_frame_t ** mirror_frames,
67 {
68  vlib_buffer_t *c0;
69  span_main_t *sm = &span_main;
70  vnet_main_t *vnm = &vnet_main;
71  u32 *to_mirror_next = 0;
72  u32 i;
73 
74  span_interface_t *si0 = vec_elt_at_index (sm->interfaces, sw_if_index0);
75  span_mirror_t *sm0 = &si0->mirror_rxtx[sf][rxtx];
76 
77  if (sm0->num_mirror_ports == 0)
78  return;
79 
80  /* Don't do it again */
81  if (PREDICT_FALSE (b0->flags & VNET_BUFFER_F_SPAN_CLONE))
82  return;
83 
84  /* *INDENT-OFF* */
86  {
87  if (mirror_frames[i] == 0)
88  {
89  if (sf == SPAN_FEAT_L2)
90  mirror_frames[i] = vlib_get_frame_to_node (vnm->vlib_main, l2output_node.index);
91  else
92  mirror_frames[i] = vnet_get_frame_to_sw_interface (vnm, i);
93  }
94  to_mirror_next = vlib_frame_vector_args (mirror_frames[i]);
95  to_mirror_next += mirror_frames[i]->n_vectors;
96  /* This can fail */
97  c0 = vlib_buffer_copy (vm, b0);
98  if (PREDICT_TRUE(c0 != 0))
99  {
100  vnet_buffer (c0)->sw_if_index[VLIB_TX] = i;
101  c0->flags |= VNET_BUFFER_F_SPAN_CLONE;
102  if (sf == SPAN_FEAT_L2)
103  vnet_buffer (c0)->l2.feature_bitmap = L2OUTPUT_FEAT_OUTPUT;
104  to_mirror_next[0] = vlib_get_buffer_index (vm, c0);
105  mirror_frames[i]->n_vectors++;
107  {
108  span_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
109  t->src_sw_if_index = sw_if_index0;
110  t->mirror_sw_if_index = i;
111  }
112  }
113  }));
114  /* *INDENT-ON* */
115 }
116 
119  vlib_frame_t * frame, vlib_rx_or_tx_t rxtx,
120  span_feat_t sf)
121 {
122  span_main_t *sm = &span_main;
123  vnet_main_t *vnm = &vnet_main;
124  u32 n_left_from, *from, *to_next;
125  u32 n_span_packets = 0;
126  u32 next_index;
127  u32 sw_if_index;
128  static __thread vlib_frame_t **mirror_frames = 0;
129 
130  from = vlib_frame_vector_args (frame);
131  n_left_from = frame->n_vectors;
132  next_index = node->cached_next_index;
133 
134  vec_validate_aligned (mirror_frames, sm->max_sw_if_index,
136 
137  while (n_left_from > 0)
138  {
139  u32 n_left_to_next;
140 
141  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
142 
143  while (n_left_from >= 4 && n_left_to_next >= 2)
144  {
145  u32 bi0;
146  u32 bi1;
147  vlib_buffer_t *b0;
148  vlib_buffer_t *b1;
149  u32 sw_if_index0;
150  u32 next0 = 0;
151  u32 sw_if_index1;
152  u32 next1 = 0;
153 
154  /* speculatively enqueue b0, b1 to the current next frame */
155  to_next[0] = bi0 = from[0];
156  to_next[1] = bi1 = from[1];
157  to_next += 2;
158  n_left_to_next -= 2;
159  from += 2;
160  n_left_from -= 2;
161 
162  b0 = vlib_get_buffer (vm, bi0);
163  b1 = vlib_get_buffer (vm, bi1);
164  sw_if_index0 = vnet_buffer (b0)->sw_if_index[rxtx];
165  sw_if_index1 = vnet_buffer (b1)->sw_if_index[rxtx];
166 
167  span_mirror (vm, node, sw_if_index0, b0, mirror_frames, rxtx, sf);
168  span_mirror (vm, node, sw_if_index1, b1, mirror_frames, rxtx, sf);
169 
170  switch (sf)
171  {
172  case SPAN_FEAT_L2:
173  if (rxtx == VLIB_RX)
174  {
175  next0 = vnet_l2_feature_next (b0, sm->l2_input_next,
176  L2INPUT_FEAT_SPAN);
177  next1 = vnet_l2_feature_next (b1, sm->l2_input_next,
178  L2INPUT_FEAT_SPAN);
179  }
180  else
181  {
182  next0 = vnet_l2_feature_next (b0, sm->l2_output_next,
183  L2OUTPUT_FEAT_SPAN);
184  next1 = vnet_l2_feature_next (b1, sm->l2_output_next,
185  L2OUTPUT_FEAT_SPAN);
186  }
187  break;
188  case SPAN_FEAT_DEVICE:
189  default:
190  vnet_feature_next (sw_if_index0, &next0, b0);
191  vnet_feature_next (sw_if_index1, &next1, b1);
192  break;
193  }
194 
195  /* verify speculative enqueue, maybe switch current next frame */
196  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
197  to_next, n_left_to_next,
198  bi0, bi1, next0, next1);
199  }
200  while (n_left_from > 0 && n_left_to_next > 0)
201  {
202  u32 bi0;
203  vlib_buffer_t *b0;
204  u32 sw_if_index0;
205  u32 next0 = 0;
206 
207  /* speculatively enqueue b0 to the current next frame */
208  to_next[0] = bi0 = from[0];
209  to_next += 1;
210  n_left_to_next -= 1;
211  from += 1;
212  n_left_from -= 1;
213 
214  b0 = vlib_get_buffer (vm, bi0);
215  sw_if_index0 = vnet_buffer (b0)->sw_if_index[rxtx];
216 
217  span_mirror (vm, node, sw_if_index0, b0, mirror_frames, rxtx, sf);
218 
219  switch (sf)
220  {
221  case SPAN_FEAT_L2:
222  if (rxtx == VLIB_RX)
223  next0 = vnet_l2_feature_next (b0, sm->l2_input_next,
224  L2INPUT_FEAT_SPAN);
225  else
226  next0 = vnet_l2_feature_next (b0, sm->l2_output_next,
227  L2OUTPUT_FEAT_SPAN);
228  break;
229  case SPAN_FEAT_DEVICE:
230  default:
231  vnet_feature_next (sw_if_index0, &next0, b0);
232  break;
233  }
234 
235  /* verify speculative enqueue, maybe switch current next frame */
236  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
237  n_left_to_next, bi0, next0);
238  }
239 
240  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
241  }
242 
243 
244  for (sw_if_index = 0; sw_if_index < vec_len (mirror_frames); sw_if_index++)
245  {
246  vlib_frame_t *f = mirror_frames[sw_if_index];
247  if (f == 0)
248  continue;
249 
250  if (sf == SPAN_FEAT_L2)
252  else
253  vnet_put_frame_to_sw_interface (vnm, sw_if_index, f);
254  mirror_frames[sw_if_index] = 0;
255  }
256  vlib_node_increment_counter (vm, span_node.index, SPAN_ERROR_HITS,
257  n_span_packets);
258 
259  return frame->n_vectors;
260 }
261 
262 static uword
264  vlib_frame_t * frame)
265 {
266  return span_node_inline_fn (vm, node, frame, VLIB_RX, SPAN_FEAT_DEVICE);
267 }
268 
269 static uword
271  vlib_frame_t * frame)
272 {
273  return span_node_inline_fn (vm, node, frame, VLIB_TX, SPAN_FEAT_DEVICE);
274 }
275 
276 static uword
278  vlib_frame_t * frame)
279 {
280  return span_node_inline_fn (vm, node, frame, VLIB_RX, SPAN_FEAT_L2);
281 }
282 
283 static uword
285  vlib_frame_t * frame)
286 {
287  return span_node_inline_fn (vm, node, frame, VLIB_TX, SPAN_FEAT_L2);
288 }
289 
290 #define span_node_defs \
291  .vector_size = sizeof (u32), \
292  .format_trace = format_span_trace, \
293  .type = VLIB_NODE_TYPE_INTERNAL, \
294  .n_errors = ARRAY_LEN(span_error_strings), \
295  .error_strings = span_error_strings, \
296  .n_next_nodes = 0, \
297  .next_nodes = { \
298  [0] = "error-drop" \
299  }
300 
301 /* *INDENT-OFF* */
304  .function = span_device_input_node_fn,
305  .name = "span-input",
306 };
307 
309 
312  .function = span_device_output_node_fn,
313  .name = "span-output",
314 };
315 
317 
320  .function = span_l2_input_node_fn,
321  .name = "span-l2-input",
322 };
323 
325 
328  .function = span_l2_output_node_fn,
329  .name = "span-l2-output",
330 };
331 
333 
335 {
336  span_main_t *sm = &span_main;
337 
338  sm->vlib_main = vm;
339  sm->vnet_main = vnet_get_main ();
340 
341  /* Initialize the feature next-node indexes */
343  span_l2_input_node.index,
346  sm->l2_input_next);
347 
349  span_l2_output_node.index,
352  sm->l2_output_next);
353  return 0;
354 }
355 
357 /* *INDENT-ON* */
358 
359 #undef span_node_defs
360 /*
361  * fd.io coding-style-patch-verification: ON
362  *
363  * Local Variables:
364  * eval: (c-set-style "gnu")
365  * End:
366  */
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
#define CLIB_UNUSED(x)
Definition: clib.h:79
char ** l2output_get_feat_names(void)
Definition: l2_output.c:38
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:501
vlib_main_t * vlib_main
Definition: span.h:54
#define PREDICT_TRUE(x)
Definition: clib.h:98
static char * span_error_strings[]
Definition: node.c:57
u32 num_mirror_ports
Definition: span.h:33
u32 mirror_sw_if_index
Definition: span.h:63
span_error_t
Definition: node.c:49
struct _vlib_node_registration vlib_node_registration_t
static uword span_l2_output_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node.c:284
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
u32 l2_output_next[32]
Definition: span.h:45
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:443
vlib_node_registration_t span_l2_output_node
(constructor) VLIB_REGISTER_NODE (span_l2_output_node)
Definition: node.c:326
format_function_t format_vnet_sw_if_index_name
static vlib_buffer_t * vlib_buffer_copy(vlib_main_t *vm, vlib_buffer_t *b)
Definition: buffer_funcs.h:465
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:302
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:85
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
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:118
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
clib_error_t * span_init(vlib_main_t *vm)
Definition: node.c:334
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
Definition: buffer_funcs.h:74
static uword span_device_input_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node.c:263
static uword span_device_output_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node.c:270
u8 * format_span_trace(u8 *s, va_list *args)
Definition: node.c:32
#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:310
vlib_main_t * vlib_main
Definition: vnet.h:78
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:191
#define PREDICT_FALSE(x)
Definition: clib.h:97
vnet_main_t vnet_main
Definition: misc.c:43
vlib_node_registration_t span_node
Definition: node.c:28
#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
span_main_t span_main
Definition: span.h:58
static_always_inline void vnet_feature_next(u32 sw_if_index, u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:221
#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:364
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1158
The fine-grained event logger allows lightweight, thread-safe event logging at minimum cost...
u16 n_vectors
Definition: node.h:344
static void vnet_put_frame_to_sw_interface(vnet_main_t *vnm, u32 sw_if_index, vlib_frame_t *f)
vlib_main_t * vm
Definition: buffer.c:283
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
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:93
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
char ** l2input_get_feat_names(void)
Return an array of strings containing graph node names of each feature.
Definition: l2_input.c:60
u32 l2_input_next[32]
Definition: span.h:44
#define span_node_defs
Definition: node.c:290
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:456
unsigned int u32
Definition: types.h:88
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:64
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
u32 src_sw_if_index
Definition: span.h:62
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:267
static uword span_l2_input_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node.c:277
span_feat_t
Definition: span.h:23
#define vnet_buffer(b)
Definition: buffer.h:306
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
#define foreach_span_error
Definition: node.c:46
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
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
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:57
VLIB_NODE_FUNCTION_MULTIARCH(ethernet_input_not_l2_node, ethernet_input_not_l2)
Definition: node.c:1207
Definition: defs.h:46