Reorganize source tree to use single autotools instance
[vpp.git] / src / vnet / cop / node1.c
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 <vnet/cop/cop.h>
17
18 typedef struct {
19   u32 next_index;
20   u32 sw_if_index;
21 } cop_input_trace_t;
22
23 /* packet trace format function */
24 static u8 * format_cop_input_trace (u8 * s, va_list * args)
25 {
26   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
27   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
28   cop_input_trace_t * t = va_arg (*args, cop_input_trace_t *);
29   
30   s = format (s, "COP_INPUT: sw_if_index %d, next index %d",
31               t->sw_if_index, t->next_index);
32   return s;
33 }
34
35 vlib_node_registration_t cop_input_node;
36
37 #define foreach_cop_input_error \
38 _(PROCESSED, "COP input packets processed")
39
40 typedef enum {
41 #define _(sym,str) COP_INPUT_ERROR_##sym,
42   foreach_cop_input_error
43 #undef _
44   COP_INPUT_N_ERROR,
45 } cop_input_error_t;
46
47 static char * cop_input_error_strings[] = {
48 #define _(sym,string) string,
49   foreach_cop_input_error
50 #undef _
51 };
52
53 static uword
54 cop_input_node_fn (vlib_main_t * vm,
55                   vlib_node_runtime_t * node,
56                   vlib_frame_t * frame)
57 {
58   u32 n_left_from, * from, * to_next;
59   cop_feature_type_t next_index;
60   cop_main_t *cm = &cop_main;
61
62   from = vlib_frame_vector_args (frame);
63   n_left_from = frame->n_vectors;
64   next_index = node->cached_next_index;
65
66   while (n_left_from > 0)
67     {
68       u32 n_left_to_next;
69
70       vlib_get_next_frame (vm, node, next_index,
71                            to_next, n_left_to_next);
72
73       while (n_left_from >= 4 && n_left_to_next >= 2)
74         {
75           u32 bi0, bi1;
76           vlib_buffer_t * b0, * b1;
77           u32 next0, next1;
78           u32 sw_if_index0, sw_if_index1;
79           ethernet_header_t * en0, * en1;
80           cop_config_main_t * ccm0, * ccm1;
81           u32 advance0, advance1;
82           int proto0, proto1;
83           
84           /* Prefetch next iteration. */
85           {
86             vlib_buffer_t * p2, * p3;
87             
88             p2 = vlib_get_buffer (vm, from[2]);
89             p3 = vlib_get_buffer (vm, from[3]);
90             
91             vlib_prefetch_buffer_header (p2, LOAD);
92             vlib_prefetch_buffer_header (p3, LOAD);
93
94             CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
95             CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
96           }
97
98           /* speculatively enqueue b0 and b1 to the current next frame */
99           to_next[0] = bi0 = from[0];
100           to_next[1] = bi1 = from[1];
101           from += 2;
102           to_next += 2;
103           n_left_from -= 2;
104           n_left_to_next -= 2;
105
106           b0 = vlib_get_buffer (vm, bi0);
107           b1 = vlib_get_buffer (vm, bi1);
108
109           en0 = vlib_buffer_get_current (b0);
110           en1 = vlib_buffer_get_current (b1);
111
112           sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
113           sw_if_index1 = vnet_buffer(b1)->sw_if_index[VLIB_RX];
114
115           proto0 = VNET_COP_DEFAULT;
116           proto1 = VNET_COP_DEFAULT;
117           advance0 = 0;
118           advance1 = 0;
119
120           if (en0->type == clib_host_to_net_u16(ETHERNET_TYPE_IP4))
121             {
122               proto0 = VNET_COP_IP4;
123               advance0 = sizeof(ethernet_header_t);
124             }
125           else if (en0->type == clib_host_to_net_u16(ETHERNET_TYPE_IP6))
126             {
127               proto0 = VNET_COP_IP6;
128               advance0 = sizeof(ethernet_header_t);
129             }
130
131           if (en1->type == clib_host_to_net_u16(ETHERNET_TYPE_IP4))
132             {
133               proto1 = VNET_COP_IP4;
134               advance1 = sizeof(ethernet_header_t);
135             }
136           else if (en1->type == clib_host_to_net_u16(ETHERNET_TYPE_IP6))
137             {
138               proto1 = VNET_COP_IP6;
139               advance1 = sizeof(ethernet_header_t);
140             }
141
142           ccm0 = cm->cop_config_mains + proto0;
143           ccm1 = cm->cop_config_mains + proto1;
144           vnet_buffer(b0)->cop.current_config_index = 
145             ccm0->config_index_by_sw_if_index [sw_if_index0];
146
147           vnet_buffer(b1)->cop.current_config_index = 
148             ccm1->config_index_by_sw_if_index [sw_if_index1];
149
150           vlib_buffer_advance (b0, advance0);
151           vlib_buffer_advance (b1, advance1);
152
153           vnet_get_config_data (&ccm0->config_main,
154                                 &vnet_buffer(b0)->cop.current_config_index,
155                                 &next0, 0 /* bytes of config data */);
156
157           vnet_get_config_data (&ccm1->config_main,
158                                 &vnet_buffer(b1)->cop.current_config_index,
159                                 &next1, 0 /* bytes of config data */);
160
161           if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE) 
162                             && (b0->flags & VLIB_BUFFER_IS_TRACED))) 
163             {
164               cop_input_trace_t *t = 
165                  vlib_add_trace (vm, node, b0, sizeof (*t));
166               t->sw_if_index = sw_if_index0;
167               t->next_index = next0;
168             }
169
170           if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE) 
171                             && (b1->flags & VLIB_BUFFER_IS_TRACED))) 
172             {
173               cop_input_trace_t *t = 
174                  vlib_add_trace (vm, node, b1, sizeof (*t));
175               t->sw_if_index = sw_if_index1;
176               t->next_index = next1;
177             }
178           /* verify speculative enqueues, maybe switch current next frame */
179           vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
180                                            to_next, n_left_to_next,
181                                            bi0, bi1, next0, next1);
182         }
183
184       while (n_left_from > 0 && n_left_to_next > 0)
185         {
186           u32 bi0;
187           vlib_buffer_t * b0;
188           u32 next0;
189           u32 sw_if_index0;
190           ethernet_header_t *en0;
191           cop_config_main_t *ccm0;
192           u32 advance0;
193           int proto0;
194
195           /* speculatively enqueue b0 to the current next frame */
196           bi0 = from[0];
197           to_next[0] = bi0;
198           from += 1;
199           to_next += 1;
200           n_left_from -= 1;
201           n_left_to_next -= 1;
202
203           b0 = vlib_get_buffer (vm, bi0);
204
205           /* 
206            * Direct from the driver, we should be at offset 0
207            * aka at &b0->data[0]
208            */
209           ASSERT (b0->current_data == 0);
210
211           en0 = vlib_buffer_get_current (b0);
212
213           sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
214
215           proto0 = VNET_COP_DEFAULT;
216           advance0 = 0;
217
218           if (en0->type == clib_host_to_net_u16(ETHERNET_TYPE_IP4))
219             {
220               proto0 = VNET_COP_IP4;
221               advance0 = sizeof(ethernet_header_t);
222             }
223           else if (en0->type == clib_host_to_net_u16(ETHERNET_TYPE_IP6))
224             {
225               proto0 = VNET_COP_IP6;
226               advance0 = sizeof(ethernet_header_t);
227             }
228
229           ccm0 = cm->cop_config_mains + proto0;
230           vnet_buffer(b0)->cop.current_config_index = 
231             ccm0->config_index_by_sw_if_index [sw_if_index0];
232
233           vlib_buffer_advance (b0, advance0);
234
235           vnet_get_config_data (&ccm0->config_main,
236                                 &vnet_buffer(b0)->cop.current_config_index,
237                                 &next0, 0 /* bytes of config data */);
238
239           if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE) 
240                             && (b0->flags & VLIB_BUFFER_IS_TRACED))) 
241             {
242               cop_input_trace_t *t = 
243                  vlib_add_trace (vm, node, b0, sizeof (*t));
244               t->sw_if_index = sw_if_index0;
245               t->next_index = next0;
246             }
247             
248           /* verify speculative enqueue, maybe switch current next frame */
249           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
250                                            to_next, n_left_to_next,
251                                            bi0, next0);
252         }
253
254       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
255     }
256   vlib_node_increment_counter (vm, cop_input_node.index, 
257                                COP_INPUT_ERROR_PROCESSED, frame->n_vectors);
258   return frame->n_vectors;
259 }
260
261 VLIB_REGISTER_NODE (cop_input_node) = {
262   .function = cop_input_node_fn,
263   .name = "cop-input",
264   .vector_size = sizeof (u32),
265   .format_trace = format_cop_input_trace,
266   .type = VLIB_NODE_TYPE_INTERNAL,
267   
268   .n_errors = ARRAY_LEN(cop_input_error_strings),
269   .error_strings = cop_input_error_strings,
270
271   .n_next_nodes = COP_RX_N_FEATURES,
272
273   /* edit / add dispositions here */
274   .next_nodes = {
275     [IP4_RX_COP_WHITELIST] = "ip4-cop-whitelist",
276     [IP6_RX_COP_WHITELIST] = "ip6-cop-whitelist",
277     [DEFAULT_RX_COP_WHITELIST] = "default-cop-whitelist",
278     [IP4_RX_COP_INPUT] = "ip4-input",
279     [IP6_RX_COP_INPUT] = "ip6-input",
280     [DEFAULT_RX_COP_INPUT] = "ethernet-input",
281     [RX_COP_DROP] = "error-drop",
282   },
283 };
284
285 VLIB_NODE_FUNCTION_MULTIARCH (cop_input_node, cop_input_node_fn)
286
287 #define foreach_cop_stub                        \
288 _(default-cop-whitelist, default_cop_whitelist)
289
290 #define _(n,f)                                  \
291                                                 \
292 static uword                                    \
293 f##_node_fn (vlib_main_t * vm,                  \
294              vlib_node_runtime_t * node,        \
295              vlib_frame_t * frame)              \
296 {                                               \
297   clib_warning ("BUG: stub function called");   \
298   return 0;                                     \
299 }                                               \
300                                                 \
301 VLIB_REGISTER_NODE (f##_input_node) = {         \
302   .function = f##_node_fn,                      \
303   .name = #n,                                   \
304   .vector_size = sizeof (u32),                  \
305   .type = VLIB_NODE_TYPE_INTERNAL,              \
306                                                 \
307   .n_errors = 0,                                \
308   .error_strings = 0,                           \
309                                                 \
310   .n_next_nodes = 0,                            \
311 };
312
313 foreach_cop_stub;
314
315
316
317
318
319