FD.io VPP  v20.01-48-g3e0dafb74
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
68 {
69  u32 n_left_from, *from;
71 
72  from = vlib_frame_vector_args (frame); /* array of buffer indices */
73  n_left_from = frame->n_vectors; /* number of buffer indices */
74 
75  while (n_left_from > 0)
76  {
77  u32 bi0;
78  vlib_buffer_t *b0;
79  u32 next0, error0;
80 
81  bi0 = from[0];
82  b0 = vlib_get_buffer (vm, bi0);
83 
84  next0 = LACP_INPUT_NEXT_NORMAL;
85 
86  /* scan this lacp pkt. error0 is the counter index to bump */
87  error0 = lacp_input (vm, b0, bi0);
88  b0->error = node->errors[error0];
89 
90  /* If this pkt is traced, snapshoot the data */
92  {
93  int len;
94 
95  t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
96  len = (b0->current_length < sizeof (t0->pkt))
97  ? b0->current_length : sizeof (t0->pkt);
98  t0->len = len;
99  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
100  clib_memcpy_fast (&t0->pkt, vlib_buffer_get_current (b0), len);
101  }
102  /* push this pkt to the next graph node, always error-drop */
103  vlib_set_next_frame_buffer (vm, node, next0, bi0);
104 
105  from += 1;
106  n_left_from -= 1;
107  }
108 
109  return frame->n_vectors;
110 }
111 
112 /*
113  * lacp input graph node declaration
114  */
115 /* *INDENT-OFF* */
117  .function = lacp_node_fn,
118  .name = "lacp-input",
119  .vector_size = sizeof (u32),
121 
122  .n_errors = LACP_N_ERROR,
123  .error_strings = lacp_error_strings,
124 
125  .format_trace = lacp_input_format_trace,
126 
127  .n_next_nodes = LACP_INPUT_N_NEXT,
128  .next_nodes = {
129  [LACP_INPUT_NEXT_NORMAL] = "error-drop",
130  },
131 };
132 /* *INDENT-ON* */
133 
134 static void
136 {
137  lacp_main_t *lm = &lacp_main;
138  /* *INDENT-OFF* */
139  ELOG_TYPE_DECLARE (e) =
140  {
141  .format = "Starting LACP process, interface count = %d",
142  .format_args = "i4",
143  };
144  /* *INDENT-ON* */
145  struct
146  {
147  u32 count;
148  } *ed;
149 
151  ed->count = lm->lacp_int;
152 }
153 
154 static void
156 {
157  lacp_main_t *lm = &lacp_main;
158  /* *INDENT-OFF* */
159  ELOG_TYPE_DECLARE (e) =
160  {
161  .format = "Stopping LACP process, interface count = %d",
162  .format_args = "i4",
163  };
164  /* *INDENT-ON* */
165  struct
166  {
167  u32 count;
168  } *ed;
169 
171  ed->count = lm->lacp_int;
172 }
173 
174 /*
175  * lacp periodic function
176  */
177 static uword
179 {
180  lacp_main_t *lm = &lacp_main;
181  f64 poll_time_remaining;
182  uword event_type, *event_data = 0;
183 
184  ethernet_register_input_type (vm, ETHERNET_TYPE_SLOW_PROTOCOLS /* LACP */ ,
185  lacp_input_node.index);
186 
187  poll_time_remaining = 0.2;
188  while (1)
189  {
190  if (lm->lacp_int > 0)
191  poll_time_remaining =
192  vlib_process_wait_for_event_or_clock (vm, poll_time_remaining);
193  else
195 
196  event_type = vlib_process_get_events (vm, &event_data);
197  switch (event_type)
198  {
199  case ~0: /* no events => timeout */
200  break;
202  poll_time_remaining = 0.2;
204  break;
206  if (lm->lacp_int == 0)
207  {
208  poll_time_remaining = SECS_IN_A_DAY;
210  }
211  break;
212  default:
213  clib_warning ("BUG: event type 0x%wx", event_type);
214  break;
215  }
216  vec_reset_length (event_data);
217 
218  if (vlib_process_suspend_time_is_zero (poll_time_remaining))
219  {
220  lacp_periodic (vm);
221  poll_time_remaining = 0.2;
222  }
223  }
224 
225  return 0;
226 }
227 
228 void
230 {
231  lacp_main_t *lm = &lacp_main;
232 
233  /* Already created the process node? */
234  if (lm->lacp_process_node_index > 0)
235  return;
236 
237  /* No, create it now and make a note of the node index */
239  vlib_process_create (lm->vlib_main, "lacp-process", lacp_process,
240  16 /* log2_n_stack_bytes */ );
241 }
242 
243 /*
244  * fd.io coding-style-patch-verification: ON
245  *
246  * Local Variables:
247  * eval: (c-set-style "gnu")
248  * End:
249  */
u8 count
Definition: dhcp.api:208
vlib_main_t * vlib_main
Definition: node.h:121
vlib_main_t vlib_global_main
Definition: main.c:1943
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:470
static vlib_node_registration_t lacp_input_node
(constructor) VLIB_REGISTER_NODE (lacp_input_node)
Definition: node.c:116
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
lacp_next_t
Definition: node.c:55
void lacp_create_periodic_process(void)
Definition: node.c:229
u8 * lacp_input_format_trace(u8 *s, va_list *args)
Definition: input.c:260
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:135
void lacp_periodic(vlib_main_t *vm)
Definition: lacp.c:139
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:769
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:178
vlib_main_t * vm
Definition: in2out_ed.c:1810
u8 len
Definition: ip_types.api:91
#define foreach_lacp_state_flag
Definition: protocol.h:75
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:397
#define clib_warning(format, args...)
Definition: error.h:59
elog_main_t elog_main
Definition: main.h:193
lacp_main_t lacp_main
Definition: lacp.c:26
#define ELOG_TYPE_DECLARE(f)
Definition: elog.h:442
#define foreach_lacp_error
Definition: node.h:61
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1810
static void lacp_elog_stop_event(void)
Definition: node.c:155
lacp_error_t lacp_input(vlib_main_t *vm, vlib_buffer_t *b0, u32 bi0)
Definition: input.c:138
#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:2267
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
union lacp_input_trace_t::@56 pkt
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:408
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1811
u16 flags
Copy of main node flags.
Definition: node.h:509
static char * lacp_error_strings[]
Definition: node.c:44
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:302
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