FD.io VPP  v19.08-27-gf4dcae4
Vector Packet Processing
node.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 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 #define _GNU_SOURCE
17 #include <vnet/bonding/node.h>
18 #include <vnet/ethernet/packet.h>
19 #include <lacp/node.h>
20 
21 lacp_state_struct lacp_state_array[] = {
22 #define _(b, s, n) {.bit = b, .str = #s, },
24 #undef _
25  {.str = NULL}
26 };
27 
28 /** \file
29 
30  2 x LACP graph nodes: an "interior" node to process
31  incoming announcements, and a "process" node to periodically
32  send announcements.
33 
34  The interior node is neither pipelined nor dual-looped, because
35  it would be very unusual to see more than one LACP packet in
36  a given input frame. So, it's a very simple / straighforward
37  example.
38 */
39 
40 /*
41  * packet counter strings
42  * Dump these counters via the "show error" CLI command
43  */
44 static char *lacp_error_strings[] = {
45 #define _(sym,string) string,
47 #undef _
48 };
49 
50 /*
51  * We actually send all lacp pkts to the "error" node after scanning
52  * them, so the graph node has only one next-index. The "error-drop"
53  * node automatically bumps our per-node packet counters for us.
54  */
55 typedef enum
56 {
59 } lacp_next_t;
60 
61 /*
62  * Process a frame of lacp packets
63  * Expect 1 packet / frame
64  */
65 static uword
67  vlib_node_runtime_t * node, vlib_frame_t * frame)
68 {
69  u32 n_left_from, *from;
71  uword n_trace = vlib_get_trace_count (vm, node);
72 
73  from = vlib_frame_vector_args (frame); /* array of buffer indices */
74  n_left_from = frame->n_vectors; /* number of buffer indices */
75 
76  while (n_left_from > 0)
77  {
78  u32 bi0;
79  vlib_buffer_t *b0;
80  u32 next0, error0;
81 
82  bi0 = from[0];
83  b0 = vlib_get_buffer (vm, bi0);
84 
85  next0 = LACP_INPUT_NEXT_NORMAL;
86 
87  /* scan this lacp pkt. error0 is the counter index to bump */
88  error0 = lacp_input (vm, b0, bi0);
89  b0->error = node->errors[error0];
90 
91  /* If this pkt is traced, snapshoot the data */
92  if (PREDICT_FALSE (n_trace > 0))
93  {
94  int len;
95  vlib_trace_buffer (vm, node, next0, b0,
96  /* follow_chain */ 0);
97  vlib_set_trace_count (vm, node, --n_trace);
98  t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
99  len = (b0->current_length < sizeof (t0->pkt))
100  ? b0->current_length : sizeof (t0->pkt);
101  t0->len = len;
102  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
103  clib_memcpy_fast (&t0->pkt, vlib_buffer_get_current (b0), len);
104  }
105  /* push this pkt to the next graph node, always error-drop */
106  vlib_set_next_frame_buffer (vm, node, next0, bi0);
107 
108  from += 1;
109  n_left_from -= 1;
110  }
111 
112  return frame->n_vectors;
113 }
114 
115 /*
116  * lacp input graph node declaration
117  */
118 /* *INDENT-OFF* */
120  .function = lacp_node_fn,
121  .name = "lacp-input",
122  .vector_size = sizeof (u32),
124 
125  .n_errors = LACP_N_ERROR,
126  .error_strings = lacp_error_strings,
127 
128  .format_trace = lacp_input_format_trace,
129 
130  .n_next_nodes = LACP_INPUT_N_NEXT,
131  .next_nodes = {
132  [LACP_INPUT_NEXT_NORMAL] = "error-drop",
133  },
134 };
135 /* *INDENT-ON* */
136 
137 static void
139 {
140  lacp_main_t *lm = &lacp_main;
141  /* *INDENT-OFF* */
142  ELOG_TYPE_DECLARE (e) =
143  {
144  .format = "Starting LACP process, interface count = %d",
145  .format_args = "i4",
146  };
147  /* *INDENT-ON* */
148  struct
149  {
150  u32 count;
151  } *ed;
152 
154  ed->count = lm->lacp_int;
155 }
156 
157 static void
159 {
160  lacp_main_t *lm = &lacp_main;
161  /* *INDENT-OFF* */
162  ELOG_TYPE_DECLARE (e) =
163  {
164  .format = "Stopping LACP process, interface count = %d",
165  .format_args = "i4",
166  };
167  /* *INDENT-ON* */
168  struct
169  {
170  u32 count;
171  } *ed;
172 
174  ed->count = lm->lacp_int;
175 }
176 
177 /*
178  * lacp periodic function
179  */
180 static uword
182 {
183  lacp_main_t *lm = &lacp_main;
184  f64 poll_time_remaining;
185  uword event_type, *event_data = 0;
186 
187  ethernet_register_input_type (vm, ETHERNET_TYPE_SLOW_PROTOCOLS /* LACP */ ,
188  lacp_input_node.index);
189 
190  poll_time_remaining = 0.2;
191  while (1)
192  {
193  if (lm->lacp_int > 0)
194  poll_time_remaining =
195  vlib_process_wait_for_event_or_clock (vm, poll_time_remaining);
196  else
198 
199  event_type = vlib_process_get_events (vm, &event_data);
200  switch (event_type)
201  {
202  case ~0: /* no events => timeout */
203  break;
205  poll_time_remaining = 0.2;
207  break;
209  if (lm->lacp_int == 0)
210  {
211  poll_time_remaining = SECS_IN_A_DAY;
213  }
214  break;
215  default:
216  clib_warning ("BUG: event type 0x%wx", event_type);
217  break;
218  }
219  vec_reset_length (event_data);
220 
221  if (vlib_process_suspend_time_is_zero (poll_time_remaining))
222  {
223  lacp_periodic (vm);
224  poll_time_remaining = 0.2;
225  }
226  }
227 
228  return 0;
229 }
230 
231 void
233 {
234  lacp_main_t *lm = &lacp_main;
235 
236  /* Already created the process node? */
237  if (lm->lacp_process_node_index > 0)
238  return;
239 
240  /* No, create it now and make a note of the node index */
242  vlib_process_create (lm->vlib_main, "lacp-process", lacp_process,
243  16 /* log2_n_stack_bytes */ );
244 }
245 
246 /*
247  * fd.io coding-style-patch-verification: ON
248  *
249  * Local Variables:
250  * eval: (c-set-style "gnu")
251  * End:
252  */
vlib_main_t * vlib_main
Definition: node.h:121
vlib_main_t vlib_global_main
Definition: main.c:1937
static u32 vlib_get_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt)
Definition: trace_funcs.h:171
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
Definition: node_funcs.h:673
static uword * vlib_process_wait_for_event(vlib_main_t *vm)
Definition: node_funcs.h:593
static void vlib_set_next_frame_buffer(vlib_main_t *vm, vlib_node_runtime_t *node, u32 next_index, u32 buffer_index)
Definition: node_funcs.h:371
volatile u32 lacp_int
Definition: node.h:134
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
#define NULL
Definition: clib.h:58
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:468
static vlib_node_registration_t lacp_input_node
(constructor) VLIB_REGISTER_NODE (lacp_input_node)
Definition: node.c:119
static uword vlib_process_suspend_time_is_zero(f64 dt)
Returns TRUE if a process suspend time is less than 10us.
Definition: node_funcs.h:410
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
double f64
Definition: types.h:142
static void vlib_trace_buffer(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, vlib_buffer_t *b, int follow_chain)
Definition: trace_funcs.h:124
lacp_next_t
Definition: node.c:55
void lacp_create_periodic_process(void)
Definition: node.c:232
u8 * lacp_input_format_trace(u8 *s, va_list *args)
Definition: input.c:252
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type...
Definition: node_funcs.h:516
unsigned int u32
Definition: types.h:88
static void lacp_elog_start_event(void)
Definition: node.c:138
void lacp_periodic(vlib_main_t *vm)
Definition: lacp.c:138
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
u32 vlib_process_create(vlib_main_t *vm, char *name, vlib_node_function_t *f, u32 log2_n_stack_bytes)
Create a vlib process.
Definition: node.c:761
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
#define ELOG_DATA(em, f)
Definition: elog.h:484
#define PREDICT_FALSE(x)
Definition: clib.h:111
static uword lacp_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: node.c:181
u8 len
Definition: ip_types.api:90
#define foreach_lacp_state_flag
Definition: protocol.h:71
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:395
vlib_main_t * vm
Definition: buffer.c:312
#define clib_warning(format, args...)
Definition: error.h:59
elog_main_t elog_main
Definition: main.h:172
lacp_main_t lacp_main
Definition: lacp.c:25
#define ELOG_TYPE_DECLARE(f)
Definition: elog.h:442
#define foreach_lacp_error
Definition: node.h:61
static void lacp_elog_stop_event(void)
Definition: node.c:158
lacp_error_t lacp_input(vlib_main_t *vm, vlib_buffer_t *b0, u32 bi0)
Definition: input.c:137
#define SECS_IN_A_DAY
Definition: node.h:77
void ethernet_register_input_type(vlib_main_t *vm, ethernet_type_t type, u32 node_index)
Definition: node.c:2053
size_t count
Definition: vapi.c:47
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 lacp_process_node_index
Definition: node.h:125
u32 sw_if_index
Definition: node.h:82
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 vnet_buffer(b)
Definition: buffer.h:361
static char * lacp_error_strings[]
Definition: node.c:44
static void vlib_set_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt, u32 count)
Definition: trace_funcs.h:187
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
static uword lacp_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node.c:66
Definition: defs.h:46
union lacp_input_trace_t::@520 pkt