FD.io VPP  v19.01.3-6-g70449b9b9
Vector Packet Processing
node.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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  * osi_node.c: osi packet processing
17  *
18  * Copyright (c) 2010 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39 
40 #include <vlib/vlib.h>
41 #include <vnet/pg/pg.h>
42 #include <vnet/osi/osi.h>
43 #include <vnet/ppp/ppp.h>
44 #include <vnet/hdlc/hdlc.h>
45 #include <vnet/llc/llc.h>
46 
47 #define foreach_osi_input_next \
48  _ (PUNT, "error-punt") \
49  _ (DROP, "error-drop")
50 
51 typedef enum
52 {
53 #define _(s,n) OSI_INPUT_NEXT_##s,
55 #undef _
58 
59 typedef struct
60 {
61  u8 packet_data[32];
63 
64 static u8 *
65 format_osi_input_trace (u8 * s, va_list * va)
66 {
67  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
68  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
69  osi_input_trace_t *t = va_arg (*va, osi_input_trace_t *);
70 
71  s = format (s, "%U", format_osi_header, t->packet_data);
72 
73  return s;
74 }
75 
76 static uword
78  vlib_node_runtime_t * node, vlib_frame_t * from_frame)
79 {
80  osi_main_t *lm = &osi_main;
81  u32 n_left_from, next_index, *from, *to_next;
82 
83  from = vlib_frame_vector_args (from_frame);
84  n_left_from = from_frame->n_vectors;
85 
86  if (node->flags & VLIB_NODE_FLAG_TRACE)
88  from,
89  n_left_from,
90  sizeof (from[0]),
91  sizeof (osi_input_trace_t));
92 
93  next_index = node->cached_next_index;
94 
95  while (n_left_from > 0)
96  {
97  u32 n_left_to_next;
98 
99  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
100 
101  while (n_left_from >= 4 && n_left_to_next >= 2)
102  {
103  u32 bi0, bi1;
104  vlib_buffer_t *b0, *b1;
105  osi_header_t *h0, *h1;
106  u8 next0, next1, enqueue_code;
107 
108  /* Prefetch next iteration. */
109  {
110  vlib_buffer_t *b2, *b3;
111 
112  b2 = vlib_get_buffer (vm, from[2]);
113  b3 = vlib_get_buffer (vm, from[3]);
114 
115  vlib_prefetch_buffer_header (b2, LOAD);
116  vlib_prefetch_buffer_header (b3, LOAD);
117 
118  CLIB_PREFETCH (b2->data, sizeof (h0[0]), LOAD);
119  CLIB_PREFETCH (b3->data, sizeof (h1[0]), LOAD);
120  }
121 
122  bi0 = from[0];
123  bi1 = from[1];
124  to_next[0] = bi0;
125  to_next[1] = bi1;
126  from += 2;
127  to_next += 2;
128  n_left_to_next -= 2;
129  n_left_from -= 2;
130 
131  b0 = vlib_get_buffer (vm, bi0);
132  b1 = vlib_get_buffer (vm, bi1);
133 
134  h0 = (void *) (b0->data + b0->current_data);
135  h1 = (void *) (b1->data + b1->current_data);
136 
137  next0 = lm->input_next_by_protocol[h0->protocol];
138  next1 = lm->input_next_by_protocol[h1->protocol];
139 
140  b0->error =
141  node->errors[next0 ==
142  OSI_INPUT_NEXT_DROP ? OSI_ERROR_UNKNOWN_PROTOCOL :
143  OSI_ERROR_NONE];
144  b1->error =
145  node->errors[next1 ==
146  OSI_INPUT_NEXT_DROP ? OSI_ERROR_UNKNOWN_PROTOCOL :
147  OSI_ERROR_NONE];
148 
149  enqueue_code = (next0 != next_index) + 2 * (next1 != next_index);
150 
151  if (PREDICT_FALSE (enqueue_code != 0))
152  {
153  switch (enqueue_code)
154  {
155  case 1:
156  /* A B A */
157  to_next[-2] = bi1;
158  to_next -= 1;
159  n_left_to_next += 1;
160  vlib_set_next_frame_buffer (vm, node, next0, bi0);
161  break;
162 
163  case 2:
164  /* A A B */
165  to_next -= 1;
166  n_left_to_next += 1;
167  vlib_set_next_frame_buffer (vm, node, next1, bi1);
168  break;
169 
170  case 3:
171  /* A B B or A B C */
172  to_next -= 2;
173  n_left_to_next += 2;
174  vlib_set_next_frame_buffer (vm, node, next0, bi0);
175  vlib_set_next_frame_buffer (vm, node, next1, bi1);
176  if (next0 == next1)
177  {
178  vlib_put_next_frame (vm, node, next_index,
179  n_left_to_next);
180  next_index = next1;
181  vlib_get_next_frame (vm, node, next_index, to_next,
182  n_left_to_next);
183  }
184  }
185  }
186  }
187 
188  while (n_left_from > 0 && n_left_to_next > 0)
189  {
190  u32 bi0;
191  vlib_buffer_t *b0;
192  osi_header_t *h0;
193  u8 next0;
194 
195  bi0 = from[0];
196  to_next[0] = bi0;
197  from += 1;
198  to_next += 1;
199  n_left_from -= 1;
200  n_left_to_next -= 1;
201 
202  b0 = vlib_get_buffer (vm, bi0);
203 
204  h0 = (void *) (b0->data + b0->current_data);
205 
206  next0 = lm->input_next_by_protocol[h0->protocol];
207 
208  b0->error =
209  node->errors[next0 ==
210  OSI_INPUT_NEXT_DROP ? OSI_ERROR_UNKNOWN_PROTOCOL :
211  OSI_ERROR_NONE];
212 
213  /* Sent packet to wrong next? */
214  if (PREDICT_FALSE (next0 != next_index))
215  {
216  /* Return old frame; remove incorrectly enqueued packet. */
217  vlib_put_next_frame (vm, node, next_index, n_left_to_next + 1);
218 
219  /* Send to correct next. */
220  next_index = next0;
221  vlib_get_next_frame (vm, node, next_index, to_next,
222  n_left_to_next);
223 
224  to_next[0] = bi0;
225  to_next += 1;
226  n_left_to_next -= 1;
227  }
228  }
229 
230  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
231  }
232 
233  return from_frame->n_vectors;
234 }
235 
236 static char *osi_error_strings[] = {
237 #define _(f,s) s,
239 #undef _
240 };
241 
242 /* *INDENT-OFF* */
244  .function = osi_input,
245  .name = "osi-input",
246  /* Takes a vector of packets. */
247  .vector_size = sizeof (u32),
248 
249  .n_errors = OSI_N_ERROR,
250  .error_strings = osi_error_strings,
251 
252  .n_next_nodes = OSI_INPUT_N_NEXT,
253  .next_nodes = {
254 #define _(s,n) [OSI_INPUT_NEXT_##s] = n,
256 #undef _
257  },
258 
259  .format_buffer = format_osi_header_with_length,
260  .format_trace = format_osi_input_trace,
261  .unformat_buffer = unformat_osi_header,
262 };
263 /* *INDENT-ON* */
264 
265 static clib_error_t *
267 {
268  clib_error_t *error = 0;
269  osi_main_t *lm = &osi_main;
270 
271  if ((error = vlib_call_init_function (vm, osi_init)))
272  return error;
273 
274  osi_setup_node (vm, osi_input_node.index);
275 
276  {
277  int i;
278  for (i = 0; i < ARRAY_LEN (lm->input_next_by_protocol); i++)
279  lm->input_next_by_protocol[i] = OSI_INPUT_NEXT_DROP;
280  }
281 
282  ppp_register_input_protocol (vm, PPP_PROTOCOL_osi, osi_input_node.index);
283  hdlc_register_input_protocol (vm, HDLC_PROTOCOL_osi, osi_input_node.index);
284  llc_register_input_protocol (vm, LLC_PROTOCOL_osi_layer1,
285  osi_input_node.index);
286  llc_register_input_protocol (vm, LLC_PROTOCOL_osi_layer2,
287  osi_input_node.index);
288  llc_register_input_protocol (vm, LLC_PROTOCOL_osi_layer3,
289  osi_input_node.index);
290  llc_register_input_protocol (vm, LLC_PROTOCOL_osi_layer4,
291  osi_input_node.index);
292  llc_register_input_protocol (vm, LLC_PROTOCOL_osi_layer5,
293  osi_input_node.index);
294 
295  return 0;
296 }
297 
299 
300 void
302 {
303  osi_main_t *lm = &osi_main;
304  vlib_main_t *vm = lm->vlib_main;
306 
307  {
309  if (error)
310  clib_error_report (error);
311  }
312 
313  pi = osi_get_protocol_info (lm, protocol);
314  pi->node_index = node_index;
315  pi->next_index = vlib_node_add_next (vm, osi_input_node.index, node_index);
316 
317  lm->input_next_by_protocol[protocol] = pi->next_index;
318 }
319 
320 /*
321  * fd.io coding-style-patch-verification: ON
322  *
323  * Local Variables:
324  * eval: (c-set-style "gnu")
325  * End:
326  */
u32 next_index
Definition: osi.h:94
u32 node_index
Definition: osi.h:91
#define CLIB_UNUSED(x)
Definition: clib.h:82
u8 packet_data[32]
Definition: node.c:61
static u8 * format_osi_input_trace(u8 *s, va_list *va)
Definition: node.c:65
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
unformat_function_t unformat_osi_header
Definition: osi.h:142
format_function_t format_osi_header_with_length
Definition: osi.h:136
u8 protocol
Definition: osi.h:77
osi_input_next_t
Definition: node.c:51
int i
void llc_register_input_protocol(vlib_main_t *vm, llc_protocol_t protocol, u32 node_index)
Definition: node.c:302
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
static char * osi_error_strings[]
Definition: node.c:236
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:493
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1092
unsigned char u8
Definition: types.h:56
#define foreach_osi_error
Definition: osi.h:97
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:188
unsigned int u32
Definition: types.h:88
osi_protocol_t
Definition: osi.h:68
#define vlib_call_init_function(vm, x)
Definition: init.h:260
vlib_main_t * vlib_main
Definition: osi.h:111
osi_main_t osi_main
Definition: osi.c:44
static osi_protocol_info_t * osi_get_protocol_info(osi_main_t *m, osi_protocol_t protocol)
Definition: osi.h:123
static clib_error_t * osi_input_init(vlib_main_t *vm)
Definition: node.c:266
void osi_register_input_protocol(osi_protocol_t protocol, u32 node_index)
Definition: node.c:301
static void osi_setup_node(vlib_main_t *vm, u32 node_index)
Definition: osi.h:146
#define PREDICT_FALSE(x)
Definition: clib.h:111
vlib_node_registration_t osi_input_node
(constructor) VLIB_REGISTER_NODE (osi_input_node)
Definition: node.c:243
#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
static uword osi_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: node.c:77
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:139
static clib_error_t * osi_init(vlib_main_t *vm)
Definition: osi.c:170
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:420
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:79
vlib_main_t * vm
Definition: buffer.c:301
#define ARRAY_LEN(x)
Definition: clib.h:62
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:452
#define foreach_osi_input_next
Definition: node.c:47
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:537
#define clib_error_report(e)
Definition: error.h:113
void vlib_trace_frame_buffers_only(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, uword n_buffers, uword next_buffer_stride, uword n_buffer_data_bytes_in_trace)
Definition: trace.c:47
void hdlc_register_input_protocol(vlib_main_t *vm, hdlc_protocol_t protocol, u32 node_index)
Definition: node.c:351
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
u8 data[0]
Packet data.
Definition: buffer.h:176
u8 input_next_by_protocol[256]
Definition: osi.h:119
void ppp_register_input_protocol(vlib_main_t *vm, ppp_protocol_t protocol, u32 node_index)
Definition: node.c:338
u16 flags
Copy of main node flags.
Definition: node.h:531
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:326
format_function_t format_osi_header
Definition: osi.h:135
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:62