FD.io VPP  v19.01.3-6-g70449b9b9
Vector Packet Processing
node.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2017 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *------------------------------------------------------------------
16  */
17 
18 #define _GNU_SOURCE
19 #include <stdint.h>
20 #include <vnet/llc/llc.h>
21 #include <vnet/snap/snap.h>
22 #include <vnet/bonding/node.h>
23 
25 
26 #define foreach_bond_input_error \
27  _(NONE, "no error") \
28  _(IF_DOWN, "interface down") \
29  _(PASS_THRU, "pass through (CDP, LLDP, slow protocols)")
30 
31 typedef enum
32 {
33 #define _(f,s) BOND_INPUT_ERROR_##f,
35 #undef _
38 
39 static char *bond_input_error_strings[] = {
40 #define _(n,s) s,
42 #undef _
43 };
44 
45 static u8 *
46 format_bond_input_trace (u8 * s, va_list * args)
47 {
48  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
49  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
50  bond_packet_trace_t *t = va_arg (*args, bond_packet_trace_t *);
51 
52  s = format (s, "src %U, dst %U, %U -> %U",
56  t->sw_if_index,
58  t->bond_sw_if_index);
59 
60  return s;
61 }
62 
63 typedef enum
64 {
68 
71 {
72  llc_header_t *llc;
73  snap_header_t *snap;
74 
75  llc = (llc_header_t *) (eth + 1);
76  snap = (snap_header_t *) (llc + 1);
77 
78  return ((eth->type == htons (ETHERNET_TYPE_CDP)) ||
79  ((llc->src_sap == 0xAA) && (llc->control == 0x03) &&
80  (snap->protocol == htons (0x2000)) &&
81  (snap->oui[0] == 0) && (snap->oui[1] == 0) &&
82  (snap->oui[2] == 0x0C)));
83 }
84 
85 static inline u32
87  vlib_buffer_t * b, u32 bond_sw_if_index)
88 {
89  u16 *ethertype_p, ethertype;
92 
93  ethertype = clib_mem_unaligned (&eth->type, u16);
94  if (!ethernet_frame_is_tagged (ntohs (ethertype)))
95  {
96  // Let some layer2 packets pass through.
97  if (PREDICT_TRUE ((ethertype != htons (ETHERNET_TYPE_SLOW_PROTOCOLS))
98  && !packet_is_cdp (eth)
99  && (ethertype != htons (ETHERNET_TYPE_802_1_LLDP))))
100  {
101  /* Change the physical interface to bond interface */
102  vnet_buffer (b)->sw_if_index[VLIB_RX] = bond_sw_if_index;
103  return 1;
104  }
105  }
106  else
107  {
108  vlan = (void *) (eth + 1);
109  ethertype_p = &vlan->type;
110  ethertype = clib_mem_unaligned (ethertype_p, u16);
111  if (ethertype == ntohs (ETHERNET_TYPE_VLAN))
112  {
113  vlan++;
114  ethertype_p = &vlan->type;
115  }
116  ethertype = clib_mem_unaligned (ethertype_p, u16);
117  if (PREDICT_TRUE ((ethertype != htons (ETHERNET_TYPE_SLOW_PROTOCOLS))
118  && (ethertype != htons (ETHERNET_TYPE_CDP))
119  && (ethertype != htons (ETHERNET_TYPE_802_1_LLDP))))
120  {
121  /* Change the physical interface to bond interface */
122  vnet_buffer (b)->sw_if_index[VLIB_RX] = bond_sw_if_index;
123  return 1;
124  }
125  }
126 
127  vlib_error_count (vm, node->node_index, BOND_INPUT_ERROR_PASS_THRU, 1);
128  return 0;
129 }
130 
131 static inline void
133  u32 * last_slave_sw_if_index, u32 slave_sw_if_index,
134  u32 packet_count,
135  u32 * bond_sw_if_index, vlib_buffer_t * b,
136  u32 * next_index, vlib_error_t * error)
137 {
139  slave_if_t *sif;
140  bond_if_t *bif;
141 
142  if (PREDICT_TRUE (*last_slave_sw_if_index == slave_sw_if_index))
143  return;
144 
145  if (packet_count)
147  VNET_INTERFACE_COUNTER_RX, thread_index,
148  *last_slave_sw_if_index, packet_count);
149 
150  *last_slave_sw_if_index = slave_sw_if_index;
151  *next_index = BOND_INPUT_NEXT_DROP;
152 
153  sif = bond_get_slave_by_sw_if_index (slave_sw_if_index);
154  ASSERT (sif);
155 
157 
158  ASSERT (bif);
159  ASSERT (vec_len (bif->slaves));
160 
161  if (PREDICT_TRUE (bif->admin_up == 0))
162  {
163  *bond_sw_if_index = slave_sw_if_index;
164  *error = node->errors[BOND_INPUT_ERROR_IF_DOWN];
165  }
166 
167  *bond_sw_if_index = bif->sw_if_index;
168  *error = 0;
169  vnet_feature_next (next_index, b);
170 }
171 
173  vlib_node_runtime_t * node,
174  vlib_frame_t * frame)
175 {
177  u32 *from, n_left;
178  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
179  u32 sw_if_indices[VLIB_FRAME_SIZE], *sw_if_index;
180  u16 nexts[VLIB_FRAME_SIZE], *next;
181  u32 last_slave_sw_if_index = ~0;
182  u32 bond_sw_if_index = 0;
183  vlib_error_t error = 0;
184  u32 next_index = 0;
185  u32 cnt = 0;
186 
187  /* Vector of buffer / pkt indices we're supposed to process */
188  from = vlib_frame_vector_args (frame);
189 
190  /* Number of buffers / pkts */
191  n_left = frame->n_vectors;
192 
193  vlib_get_buffers (vm, from, bufs, n_left);
194 
195  b = bufs;
196  next = nexts;
197  sw_if_index = sw_if_indices;
198 
199  while (n_left >= 4)
200  {
201  u32 x = 0;
202  /* Prefetch next iteration */
203  if (PREDICT_TRUE (n_left >= 16))
204  {
205  vlib_prefetch_buffer_data (b[8], LOAD);
206  vlib_prefetch_buffer_data (b[9], LOAD);
207  vlib_prefetch_buffer_data (b[10], LOAD);
208  vlib_prefetch_buffer_data (b[11], LOAD);
209 
210  vlib_prefetch_buffer_header (b[12], LOAD);
211  vlib_prefetch_buffer_header (b[13], LOAD);
212  vlib_prefetch_buffer_header (b[14], LOAD);
213  vlib_prefetch_buffer_header (b[15], LOAD);
214  }
215 
216  sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
217  sw_if_index[1] = vnet_buffer (b[1])->sw_if_index[VLIB_RX];
218  sw_if_index[2] = vnet_buffer (b[2])->sw_if_index[VLIB_RX];
219  sw_if_index[3] = vnet_buffer (b[3])->sw_if_index[VLIB_RX];
220 
221  x |= sw_if_index[0] ^ last_slave_sw_if_index;
222  x |= sw_if_index[1] ^ last_slave_sw_if_index;
223  x |= sw_if_index[2] ^ last_slave_sw_if_index;
224  x |= sw_if_index[3] ^ last_slave_sw_if_index;
225 
226  if (PREDICT_TRUE (x == 0))
227  {
228  next[0] = next[1] = next[2] = next[3] = next_index;
229  if (next_index == BOND_INPUT_NEXT_DROP)
230  {
231  b[0]->error = error;
232  b[1]->error = error;
233  b[2]->error = error;
234  b[3]->error = error;
235  }
236  else
237  {
238  cnt +=
239  bond_sw_if_idx_rewrite (vm, node, b[0], bond_sw_if_index);
240  cnt +=
241  bond_sw_if_idx_rewrite (vm, node, b[1], bond_sw_if_index);
242  cnt +=
243  bond_sw_if_idx_rewrite (vm, node, b[2], bond_sw_if_index);
244  cnt +=
245  bond_sw_if_idx_rewrite (vm, node, b[3], bond_sw_if_index);
246  }
247  }
248  else
249  {
250 
251  bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[0],
252  cnt, &bond_sw_if_index, b[0], &next_index,
253  &error);
254  next[0] = next_index;
255  if (next_index == BOND_INPUT_NEXT_DROP)
256  b[0]->error = error;
257  else
258  cnt += bond_sw_if_idx_rewrite (vm, node, b[0], bond_sw_if_index);
259 
260  bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[1],
261  cnt, &bond_sw_if_index, b[1], &next_index,
262  &error);
263  next[1] = next_index;
264  if (next_index == BOND_INPUT_NEXT_DROP)
265  b[1]->error = error;
266  else
267  cnt += bond_sw_if_idx_rewrite (vm, node, b[1], bond_sw_if_index);
268 
269  bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[2],
270  cnt, &bond_sw_if_index, b[2], &next_index,
271  &error);
272  next[2] = next_index;
273  if (next_index == BOND_INPUT_NEXT_DROP)
274  b[2]->error = error;
275  else
276  cnt += bond_sw_if_idx_rewrite (vm, node, b[2], bond_sw_if_index);
277 
278  bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[3],
279  cnt, &bond_sw_if_index, b[3], &next_index,
280  &error);
281  next[3] = next_index;
282  if (next_index == BOND_INPUT_NEXT_DROP)
283  b[3]->error = error;
284  else
285  cnt += bond_sw_if_idx_rewrite (vm, node, b[3], bond_sw_if_index);
286  }
287 
292 
293  /* next */
294  n_left -= 4;
295  b += 4;
296  sw_if_index += 4;
297  next += 4;
298  }
299 
300  while (n_left)
301  {
302  sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
303  bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[0],
304  cnt, &bond_sw_if_index, b[0], &next_index, &error);
305  next[0] = next_index;
306  if (next_index == BOND_INPUT_NEXT_DROP)
307  b[0]->error = error;
308  else
309  bond_sw_if_idx_rewrite (vm, node, b[0], bond_sw_if_index);
310 
312 
313  /* next */
314  n_left -= 1;
315  b += 1;
316  sw_if_index += 1;
317  next += 1;
318  }
319 
320  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
321  {
322  n_left = frame->n_vectors; /* number of packets to process */
323  b = bufs;
324  sw_if_index = sw_if_indices;
326 
327  while (n_left)
328  {
329  if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
330  {
331  t0 = vlib_add_trace (vm, node, b[0], sizeof (*t0));
332  t0->sw_if_index = sw_if_index[0];
334  sizeof (ethernet_header_t));
335  t0->bond_sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
336  }
337  /* next */
338  n_left--;
339  b++;
340  sw_if_index++;
341  }
342  }
343 
344  /* increase rx counters */
347  VNET_INTERFACE_COUNTER_RX, thread_index, bond_sw_if_index, cnt);
348 
349  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
351  BOND_INPUT_ERROR_NONE, frame->n_vectors);
352 
353  return frame->n_vectors;
354 }
355 
356 static clib_error_t *
358 {
359  return 0;
360 }
361 
362 /* *INDENT-OFF* */
364  .name = "bond-input",
365  .vector_size = sizeof (u32),
366  .format_buffer = format_ethernet_header_with_length,
367  .format_trace = format_bond_input_trace,
368  .type = VLIB_NODE_TYPE_INTERNAL,
369  .n_errors = BOND_INPUT_N_ERROR,
370  .error_strings = bond_input_error_strings,
371  .n_next_nodes = BOND_INPUT_N_NEXT,
372  .next_nodes =
373  {
374  [BOND_INPUT_NEXT_DROP] = "error-drop"
375  }
376 };
377 
379 
380 VNET_FEATURE_INIT (bond_input, static) =
381 {
382  .arc_name = "device-input",
383  .node_name = "bond-input",
384  .runs_before = VNET_FEATURES ("ethernet-input"),
385 };
386 /* *INDENT-ON* */
387 
388 static clib_error_t *
390 {
391  bond_main_t *bm = &bond_main;
392  slave_if_t *sif;
393  vlib_main_t *vm = bm->vlib_main;
394 
395  sif = bond_get_slave_by_sw_if_index (sw_if_index);
396  if (sif)
397  {
399  if (sif->lacp_enabled)
400  return 0;
401 
402  if (sif->port_enabled == 0)
403  {
405  }
406  else
407  {
408  vnet_main_t *vnm = vnet_get_main ();
409  vnet_hw_interface_t *hw =
410  vnet_get_sup_hw_interface (vnm, sw_if_index);
411 
414  }
415  }
416 
417  return 0;
418 }
419 
421 
422 static clib_error_t *
424 {
425  bond_main_t *bm = &bond_main;
426  slave_if_t *sif;
428  vlib_main_t *vm = bm->vlib_main;
429 
430  sw = vnet_get_hw_sw_interface (vnm, hw_if_index);
432  if (sif)
433  {
434  if (sif->lacp_enabled)
435  return 0;
436 
437  if (!(flags & VNET_HW_INTERFACE_FLAG_LINK_UP))
438  {
440  }
441  else if (sif->port_enabled)
442  {
444  }
445  }
446 
447  return 0;
448 }
449 
451 
452 /*
453  * fd.io coding-style-patch-verification: ON
454  *
455  * Local Variables:
456  * eval: (c-set-style "gnu")
457  * End:
458  */
#define foreach_bond_input_error
Definition: node.c:26
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(bond_sw_interface_up_down)
u32 flags
Definition: vhost_user.h:115
#define CLIB_UNUSED(x)
Definition: clib.h:82
static u32 bond_sw_if_idx_rewrite(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b, u32 bond_sw_if_index)
Definition: node.c:86
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
static clib_error_t * bond_input_init(vlib_main_t *vm)
Definition: node.c:357
vnet_interface_main_t interface_main
Definition: vnet.h:56
#define PREDICT_TRUE(x)
Definition: clib.h:112
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:57
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
u8 src_address[6]
Definition: packet.h:56
u32 thread_index
Definition: main.h:179
u8 src_sap
Definition: llc.h:82
u16 vlib_error_t
Definition: error.h:43
bond_main_t bond_main
Definition: node.c:24
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
static void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 thread_index, u32 index, u64 increment)
Increment a simple counter.
Definition: counter.h:78
#define VLIB_NODE_FN(node)
Definition: node.h:201
bond_input_error_t
Definition: node.c:31
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:493
void bond_enable_collecting_distributing(vlib_main_t *vm, slave_if_t *sif)
Definition: cli.c:59
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
static vnet_sw_interface_t * vnet_get_hw_sw_interface(vnet_main_t *vnm, u32 hw_if_index)
VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION(bond_hw_interface_up_down)
vlib_node_registration_t bond_input_node
(constructor) VLIB_REGISTER_NODE (bond_input_node)
Definition: node.c:363
#define static_always_inline
Definition: clib.h:99
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
u32 sw_if_index
Definition: vxlan_gbp.api:37
u8 dst_address[6]
Definition: packet.h:55
u32 sw_if_index
Definition: node.h:170
vnet_hw_interface_flags_t flags
Definition: interface.h:516
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:188
bond_output_next_t
Definition: node.c:63
vlib_main_t * vlib_main
Definition: node.h:317
unsigned int u32
Definition: types.h:88
#define VLIB_FRAME_SIZE
Definition: node.h:401
static clib_error_t * bond_sw_interface_up_down(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: node.c:389
u8 admin_up
Definition: node.h:156
unsigned short u16
Definition: types.h:57
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:214
#define PREDICT_FALSE(x)
Definition: clib.h:111
vnet_main_t vnet_main
Definition: misc.c:43
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:838
u32 node_index
Node index.
Definition: node.h:518
static u8 * format_bond_input_trace(u8 *s, va_list *args)
Definition: node.c:46
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:139
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1150
u8 * format_ethernet_header_with_length(u8 *s, va_list *args)
Definition: format.c:97
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u32 * slaves
Definition: node.h:173
vlib_main_t * vm
Definition: buffer.c:301
static_always_inline void vlib_buffer_enqueue_to_next(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u16 *nexts, uword count)
Definition: buffer_node.h:332
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:295
ethernet_header_t ethernet
Definition: node.h:333
void bond_disable_collecting_distributing(vlib_main_t *vm, slave_if_t *sif)
Definition: cli.c:25
#define vlib_prefetch_buffer_data(b, type)
Definition: buffer.h:189
VNET_FEATURE_INIT(bond_input, static)
#define ASSERT(truth)
static_always_inline u8 packet_is_cdp(ethernet_header_t *eth)
Definition: node.c:70
static bond_if_t * bond_get_master_by_dev_instance(u32 dev_instance)
Definition: node.h:453
u32 bif_dev_instance
Definition: node.h:291
static_always_inline int ethernet_frame_is_tagged(u16 type)
Definition: ethernet.h:111
#define clib_mem_unaligned(pointer, type)
Definition: types.h:155
u8 control
Definition: llc.h:87
static char * bond_input_error_strings[]
Definition: node.c:39
#define VNET_FEATURES(...)
Definition: feature.h:435
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:57
u8 lacp_enabled
Definition: node.h:248
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
Definition: buffer.h:495
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
static clib_error_t * bond_hw_interface_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: node.c:423
#define vnet_buffer(b)
Definition: buffer.h:368
u8 port_enabled
Definition: node.h:242
static slave_if_t * bond_get_slave_by_sw_if_index(u32 sw_if_index)
Definition: node.h:461
static_always_inline void vlib_get_buffers(vlib_main_t *vm, u32 *bi, vlib_buffer_t **b, int count)
Translate array of buffer indices into buffer pointers.
Definition: buffer_funcs.h:145
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:326
u32 bond_sw_if_index
Definition: node.h:335
Definition: defs.h:46
static void bond_update_next(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *last_slave_sw_if_index, u32 slave_sw_if_index, u32 packet_count, u32 *bond_sw_if_index, vlib_buffer_t *b, u32 *next_index, vlib_error_t *error)
Definition: node.c:132