Line data Source code
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 : #ifndef included_features_h
17 : #define included_features_h
18 :
19 : #include <vnet/vnet.h>
20 : #include <vnet/api_errno.h>
21 : #include <vnet/devices/devices.h>
22 :
23 : /** feature registration object */
24 : typedef struct _vnet_feature_arc_registration
25 : {
26 : /** next registration in list of all registrations*/
27 : struct _vnet_feature_arc_registration *next;
28 : /** Feature Arc name */
29 : char *arc_name;
30 : /** Start nodes */
31 : char **start_nodes;
32 : int n_start_nodes;
33 : /** End of the arc (optional, for consistency-checking) */
34 : char *last_in_arc;
35 : /* Feature arc index, assigned by init function */
36 : u8 feature_arc_index;
37 : u8 *arc_index_ptr;
38 : } vnet_feature_arc_registration_t;
39 :
40 : /* Enable feature callback. */
41 : typedef clib_error_t *(vnet_feature_enable_disable_function_t)
42 : (u32 sw_if_index, int enable_disable);
43 :
44 : /** feature registration object */
45 : typedef struct _vnet_feature_registration
46 : {
47 : /** next registration in list of all registrations*/
48 : struct _vnet_feature_registration *next, *next_in_arc;
49 : /** Feature arc name */
50 : char *arc_name;
51 : /** Graph node name */
52 : char *node_name;
53 : /** Pointer to this feature index, filled in by vnet_feature_arc_init */
54 : u32 *feature_index_ptr;
55 : u32 feature_index;
56 : /** Constraints of the form "this feature runs before X" */
57 : char **runs_before;
58 : /** Constraints of the form "this feature runs after Y" */
59 : char **runs_after;
60 :
61 : /** Function to enable/disable feature **/
62 : vnet_feature_enable_disable_function_t *enable_disable_cb;
63 : } vnet_feature_registration_t;
64 :
65 : /** constraint registration object */
66 : typedef struct _vnet_feature_constraint_registration
67 : {
68 : /** next constraint set in list of all registrations*/
69 : struct _vnet_feature_constraint_registration *next, *next_in_arc;
70 : /** Feature arc name */
71 : char *arc_name;
72 :
73 : /** Feature arc index, assigned by init function */
74 : u8 feature_arc_index;
75 :
76 : /** Node names, to run in the specified order */
77 : char **node_names;
78 : } vnet_feature_constraint_registration_t;
79 :
80 : typedef struct vnet_feature_config_main_t_
81 : {
82 : vnet_config_main_t config_main;
83 : u32 *config_index_by_sw_if_index;
84 : } vnet_feature_config_main_t;
85 :
86 : typedef struct
87 : {
88 : /** feature arc configuration list */
89 : vnet_feature_arc_registration_t *next_arc;
90 : uword **arc_index_by_name;
91 :
92 : /** feature path configuration lists */
93 : vnet_feature_registration_t *next_feature;
94 : vnet_feature_registration_t **next_feature_by_arc;
95 : vnet_feature_constraint_registration_t *next_constraint;
96 : vnet_feature_constraint_registration_t **next_constraint_by_arc;
97 : uword **next_feature_by_name;
98 :
99 : /** feature config main objects */
100 : vnet_feature_config_main_t *feature_config_mains;
101 :
102 : /** Save partial order results for show command */
103 : char ***feature_nodes;
104 :
105 : /** bitmap of interfaces which have driver rx features configured */
106 : uword **sw_if_index_has_features;
107 :
108 : /** feature reference counts by interface */
109 : i16 **feature_count_by_sw_if_index;
110 :
111 : /** Feature arc index for device-input */
112 : u8 device_input_feature_arc_index;
113 :
114 : /** convenience */
115 : vlib_main_t *vlib_main;
116 : vnet_main_t *vnet_main;
117 : } vnet_feature_main_t;
118 :
119 : extern vnet_feature_main_t feature_main;
120 :
121 : #ifndef CLIB_MARCH_VARIANT
122 : #define VNET_FEATURE_ARC_INIT(x,...) \
123 : __VA_ARGS__ vnet_feature_arc_registration_t vnet_feat_arc_##x;\
124 : static void __vnet_add_feature_arc_registration_##x (void) \
125 : __attribute__((__constructor__)) ; \
126 : static void __vnet_add_feature_arc_registration_##x (void) \
127 : { \
128 : vnet_feature_main_t * fm = &feature_main; \
129 : vnet_feat_arc_##x.next = fm->next_arc; \
130 : fm->next_arc = & vnet_feat_arc_##x; \
131 : } \
132 : static void __vnet_rm_feature_arc_registration_##x (void) \
133 : __attribute__((__destructor__)) ; \
134 : static void __vnet_rm_feature_arc_registration_##x (void) \
135 : { \
136 : vnet_feature_main_t * fm = &feature_main; \
137 : vnet_feature_arc_registration_t *r = &vnet_feat_arc_##x; \
138 : VLIB_REMOVE_FROM_LINKED_LIST (fm->next_arc, r, next); \
139 : } \
140 : __VA_ARGS__ vnet_feature_arc_registration_t vnet_feat_arc_##x
141 :
142 : #define VNET_FEATURE_INIT(x,...) \
143 : __VA_ARGS__ vnet_feature_registration_t vnet_feat_##x; \
144 : static void __vnet_add_feature_registration_##x (void) \
145 : __attribute__((__constructor__)) ; \
146 : static void __vnet_add_feature_registration_##x (void) \
147 : { \
148 : vnet_feature_main_t * fm = &feature_main; \
149 : vnet_feat_##x.next = fm->next_feature; \
150 : fm->next_feature = & vnet_feat_##x; \
151 : } \
152 : static void __vnet_rm_feature_registration_##x (void) \
153 : __attribute__((__destructor__)) ; \
154 : static void __vnet_rm_feature_registration_##x (void) \
155 : { \
156 : vnet_feature_main_t * fm = &feature_main; \
157 : vnet_feature_registration_t *r = &vnet_feat_##x; \
158 : VLIB_REMOVE_FROM_LINKED_LIST (fm->next_feature, r, next); \
159 : } \
160 : __VA_ARGS__ vnet_feature_registration_t vnet_feat_##x
161 :
162 : #define VNET_FEATURE_ARC_ORDER(x,...) \
163 : __VA_ARGS__ vnet_feature_constraint_registration_t \
164 : vnet_feature_constraint_##x; \
165 : static void __vnet_add_constraint_registration_##x (void) \
166 : __attribute__((__constructor__)) ; \
167 : static void __vnet_add_constraint_registration_##x (void) \
168 : { \
169 : vnet_feature_main_t * fm = &feature_main; \
170 : vnet_feature_constraint_##x.next = fm->next_constraint; \
171 : fm->next_constraint = & vnet_feature_constraint_##x; \
172 : } \
173 : static void __vnet_rm_constraint_registration_##x (void) \
174 : __attribute__((__destructor__)) ; \
175 : static void __vnet_rm_constraint_registration_##x (void) \
176 : { \
177 : vnet_feature_main_t * fm = &feature_main; \
178 : vnet_feature_constraint_registration_t *r = &vnet_feature_constraint_##x; \
179 : VLIB_REMOVE_FROM_LINKED_LIST (fm->next_constraint, r, next); \
180 : } \
181 : __VA_ARGS__ vnet_feature_constraint_registration_t vnet_feature_constraint_##x
182 :
183 : #else
184 : #define VNET_FEATURE_ARC_INIT(x,...) \
185 : extern vnet_feature_arc_registration_t __clib_unused vnet_feat_arc_##x; \
186 : static vnet_feature_arc_registration_t __clib_unused __clib_unused_vnet_feat_arc_##x
187 : #define VNET_FEATURE_INIT(x,...) \
188 : extern vnet_feature_registration_t __clib_unused vnet_feat_##x; \
189 : static vnet_feature_registration_t __clib_unused __clib_unused_vnet_feat_##x
190 :
191 : #define VNET_FEATURE_ARC_ORDER(x,...) \
192 : extern vnet_feature_constraint_registration_t \
193 : __clib_unused vnet_feature_constraint_##x; \
194 : static vnet_feature_constraint_registration_t __clib_unused \
195 : __clib_unused_vnet_feature_constraint_##x
196 :
197 :
198 : #endif
199 :
200 : void
201 : vnet_config_update_feature_count (vnet_feature_main_t * fm, u8 arc,
202 : u32 sw_if_index, int is_add);
203 :
204 : u32 vnet_get_feature_index (u8 arc, const char *s);
205 : u8 vnet_get_feature_arc_index (const char *s);
206 : vnet_feature_registration_t *vnet_get_feature_reg (const char *arc_name,
207 : const char *node_name);
208 :
209 :
210 : int
211 : vnet_feature_enable_disable_with_index (u8 arc_index, u32 feature_index,
212 : u32 sw_if_index, int enable_disable,
213 : void *feature_config,
214 : u32 n_feature_config_bytes);
215 :
216 : int
217 : vnet_feature_enable_disable (const char *arc_name, const char *node_name,
218 : u32 sw_if_index, int enable_disable,
219 : void *feature_config,
220 : u32 n_feature_config_bytes);
221 :
222 : u32
223 : vnet_feature_modify_end_node (u8 arc_index, u32 sw_if_index, u32 node_index);
224 :
225 : u32 vnet_feature_get_end_node (u8 arc_index, u32 sw_if_index);
226 :
227 : u32 vnet_feature_reset_end_node (u8 arc_index, u32 sw_if_index);
228 :
229 : static_always_inline u32
230 0 : vnet_get_feature_count (u8 arc, u32 sw_if_index)
231 : {
232 0 : vnet_feature_main_t *fm = &feature_main;
233 0 : return (fm->feature_count_by_sw_if_index[arc][sw_if_index]);
234 : }
235 :
236 : static inline vnet_feature_config_main_t *
237 352 : vnet_get_feature_arc_config_main (u8 arc_index)
238 : {
239 352 : vnet_feature_main_t *fm = &feature_main;
240 :
241 352 : if (arc_index == (u8) ~ 0)
242 0 : return 0;
243 :
244 352 : return &fm->feature_config_mains[arc_index];
245 : }
246 :
247 : static_always_inline vnet_feature_config_main_t *
248 2180 : vnet_feature_get_config_main (u16 arc)
249 : {
250 2180 : vnet_feature_main_t *fm = &feature_main;
251 2180 : return &fm->feature_config_mains[arc];
252 : }
253 :
254 : static_always_inline int
255 53484523 : vnet_have_features (u8 arc, u32 sw_if_index)
256 : {
257 53484523 : vnet_feature_main_t *fm = &feature_main;
258 53484523 : return clib_bitmap_get (fm->sw_if_index_has_features[arc], sw_if_index);
259 : }
260 :
261 : static_always_inline u32
262 9 : vnet_get_feature_config_index (u8 arc, u32 sw_if_index)
263 : {
264 9 : vnet_feature_main_t *fm = &feature_main;
265 9 : vnet_feature_config_main_t *cm = &fm->feature_config_mains[arc];
266 9 : return vec_elt (cm->config_index_by_sw_if_index, sw_if_index);
267 : }
268 :
269 : static_always_inline void *
270 30113735 : vnet_feature_arc_start_with_data (u8 arc, u32 sw_if_index, u32 * next,
271 : vlib_buffer_t * b, u32 n_data_bytes)
272 : {
273 30113735 : vnet_feature_main_t *fm = &feature_main;
274 : vnet_feature_config_main_t *cm;
275 30113735 : cm = &fm->feature_config_mains[arc];
276 :
277 30113735 : if (PREDICT_FALSE (vnet_have_features (arc, sw_if_index)))
278 : {
279 21380351 : vnet_buffer (b)->feature_arc_index = arc;
280 21380330 : b->current_config_index =
281 21380351 : vec_elt (cm->config_index_by_sw_if_index, sw_if_index);
282 21380330 : return vnet_get_config_data (&cm->config_main, &b->current_config_index,
283 : next, n_data_bytes);
284 : }
285 8733425 : return 0;
286 : }
287 :
288 : static_always_inline void *
289 3383100 : vnet_feature_arc_start_w_cfg_index (u8 arc,
290 : u32 sw_if_index,
291 : u32 * next,
292 : vlib_buffer_t * b, u32 cfg_index)
293 : {
294 3383100 : vnet_feature_main_t *fm = &feature_main;
295 : vnet_feature_config_main_t *cm;
296 3383100 : cm = &fm->feature_config_mains[arc];
297 :
298 3383100 : vnet_buffer (b)->feature_arc_index = arc;
299 3383100 : b->current_config_index = cfg_index;
300 :
301 3383100 : return vnet_get_config_data (&cm->config_main, &b->current_config_index,
302 : next, 0);
303 : }
304 :
305 : static_always_inline void
306 30113725 : vnet_feature_arc_start (u8 arc, u32 sw_if_index, u32 * next0,
307 : vlib_buffer_t * b0)
308 : {
309 30113725 : vnet_feature_arc_start_with_data (arc, sw_if_index, next0, b0, 0);
310 30113735 : }
311 :
312 : static_always_inline void *
313 30224176 : vnet_feature_next_with_data (u32 * next0, vlib_buffer_t * b0,
314 : u32 n_data_bytes)
315 : {
316 30224176 : vnet_feature_main_t *fm = &feature_main;
317 30224176 : u8 arc = vnet_buffer (b0)->feature_arc_index;
318 30224176 : vnet_feature_config_main_t *cm = &fm->feature_config_mains[arc];
319 :
320 30224176 : return vnet_get_config_data (&cm->config_main,
321 : &b0->current_config_index, next0,
322 : n_data_bytes);
323 : }
324 :
325 : static_always_inline void
326 29798443 : vnet_feature_next (u32 * next0, vlib_buffer_t * b0)
327 : {
328 29798443 : vnet_feature_next_with_data (next0, b0, 0);
329 29798474 : }
330 :
331 : static_always_inline void
332 12360 : vnet_feature_next_u16 (u16 * next0, vlib_buffer_t * b0)
333 : {
334 : u32 next32;
335 12360 : vnet_feature_next_with_data (&next32, b0, 0);
336 12360 : *next0 = next32;
337 12360 : }
338 :
339 : static_always_inline int
340 0 : vnet_device_input_have_features (u32 sw_if_index)
341 : {
342 0 : vnet_feature_main_t *fm = &feature_main;
343 0 : return vnet_have_features (fm->device_input_feature_arc_index, sw_if_index);
344 : }
345 :
346 : static_always_inline void
347 1873551 : vnet_feature_start_device_input_x1 (u32 sw_if_index, u32 * next0,
348 : vlib_buffer_t * b0)
349 : {
350 1873551 : vnet_feature_main_t *fm = &feature_main;
351 : vnet_feature_config_main_t *cm;
352 1873551 : u8 feature_arc_index = fm->device_input_feature_arc_index;
353 1873551 : cm = &fm->feature_config_mains[feature_arc_index];
354 :
355 1873551 : if (PREDICT_FALSE
356 : (clib_bitmap_get
357 : (fm->sw_if_index_has_features[feature_arc_index], sw_if_index)))
358 : {
359 : /*
360 : * Save next0 so that the last feature in the chain
361 : * can skip ethernet-input if indicated...
362 : */
363 : u16 adv;
364 :
365 21 : adv = device_input_next_node_advance[*next0];
366 21 : vlib_buffer_advance (b0, -adv);
367 :
368 21 : vnet_buffer (b0)->feature_arc_index = feature_arc_index;
369 21 : b0->current_config_index =
370 21 : vec_elt (cm->config_index_by_sw_if_index, sw_if_index);
371 21 : vnet_get_config_data (&cm->config_main, &b0->current_config_index,
372 : next0, /* # bytes of config data */ 0);
373 : }
374 1873551 : }
375 :
376 : static_always_inline void
377 : vnet_feature_start_device_input_x2 (u32 sw_if_index,
378 : u32 * next0,
379 : u32 * next1,
380 : vlib_buffer_t * b0, vlib_buffer_t * b1)
381 : {
382 : vnet_feature_main_t *fm = &feature_main;
383 : vnet_feature_config_main_t *cm;
384 : u8 feature_arc_index = fm->device_input_feature_arc_index;
385 : cm = &fm->feature_config_mains[feature_arc_index];
386 :
387 : if (PREDICT_FALSE
388 : (clib_bitmap_get
389 : (fm->sw_if_index_has_features[feature_arc_index], sw_if_index)))
390 : {
391 : /*
392 : * Save next0 so that the last feature in the chain
393 : * can skip ethernet-input if indicated...
394 : */
395 : u16 adv;
396 :
397 : adv = device_input_next_node_advance[*next0];
398 : vlib_buffer_advance (b0, -adv);
399 :
400 : adv = device_input_next_node_advance[*next1];
401 : vlib_buffer_advance (b1, -adv);
402 :
403 : vnet_buffer (b0)->feature_arc_index = feature_arc_index;
404 : vnet_buffer (b1)->feature_arc_index = feature_arc_index;
405 : b0->current_config_index =
406 : vec_elt (cm->config_index_by_sw_if_index, sw_if_index);
407 : b1->current_config_index = b0->current_config_index;
408 : vnet_get_config_data (&cm->config_main, &b0->current_config_index,
409 : next0, /* # bytes of config data */ 0);
410 : vnet_get_config_data (&cm->config_main, &b1->current_config_index,
411 : next1, /* # bytes of config data */ 0);
412 : }
413 : }
414 :
415 : static_always_inline void
416 : vnet_feature_start_device_input_x4 (u32 sw_if_index,
417 : u32 * next0,
418 : u32 * next1,
419 : u32 * next2,
420 : u32 * next3,
421 : vlib_buffer_t * b0,
422 : vlib_buffer_t * b1,
423 : vlib_buffer_t * b2, vlib_buffer_t * b3)
424 : {
425 : vnet_feature_main_t *fm = &feature_main;
426 : vnet_feature_config_main_t *cm;
427 : u8 feature_arc_index = fm->device_input_feature_arc_index;
428 : cm = &fm->feature_config_mains[feature_arc_index];
429 :
430 : if (PREDICT_FALSE
431 : (clib_bitmap_get
432 : (fm->sw_if_index_has_features[feature_arc_index], sw_if_index)))
433 : {
434 : /*
435 : * Save next0 so that the last feature in the chain
436 : * can skip ethernet-input if indicated...
437 : */
438 : u16 adv;
439 :
440 : adv = device_input_next_node_advance[*next0];
441 : vlib_buffer_advance (b0, -adv);
442 :
443 : adv = device_input_next_node_advance[*next1];
444 : vlib_buffer_advance (b1, -adv);
445 :
446 : adv = device_input_next_node_advance[*next2];
447 : vlib_buffer_advance (b2, -adv);
448 :
449 : adv = device_input_next_node_advance[*next3];
450 : vlib_buffer_advance (b3, -adv);
451 :
452 : vnet_buffer (b0)->feature_arc_index = feature_arc_index;
453 : vnet_buffer (b1)->feature_arc_index = feature_arc_index;
454 : vnet_buffer (b2)->feature_arc_index = feature_arc_index;
455 : vnet_buffer (b3)->feature_arc_index = feature_arc_index;
456 :
457 : b0->current_config_index =
458 : vec_elt (cm->config_index_by_sw_if_index, sw_if_index);
459 : b1->current_config_index = b0->current_config_index;
460 : b2->current_config_index = b0->current_config_index;
461 : b3->current_config_index = b0->current_config_index;
462 :
463 : vnet_get_config_data (&cm->config_main, &b0->current_config_index,
464 : next0, /* # bytes of config data */ 0);
465 : vnet_get_config_data (&cm->config_main, &b1->current_config_index,
466 : next1, /* # bytes of config data */ 0);
467 : vnet_get_config_data (&cm->config_main, &b2->current_config_index,
468 : next2, /* # bytes of config data */ 0);
469 : vnet_get_config_data (&cm->config_main, &b3->current_config_index,
470 : next3, /* # bytes of config data */ 0);
471 : }
472 : }
473 :
474 : #define VNET_FEATURES(...) (char*[]) { __VA_ARGS__, 0}
475 :
476 : clib_error_t *vnet_feature_arc_init
477 : (vlib_main_t * vm,
478 : vnet_config_main_t * vcm,
479 : char **feature_start_nodes,
480 : int num_feature_start_nodes,
481 : char *last_in_arc,
482 : vnet_feature_registration_t * first_reg,
483 : vnet_feature_constraint_registration_t * first_const_set,
484 : char ***in_feature_nodes);
485 :
486 : void vnet_interface_features_show (vlib_main_t * vm, u32 sw_if_index,
487 : int verbose);
488 :
489 : typedef void (*vnet_feature_update_cb_t) (u32 sw_if_index,
490 : u8 arc_index,
491 : u8 is_enable, void *cb);
492 :
493 : extern void vnet_feature_register (vnet_feature_update_cb_t cb, void *data);
494 :
495 : int
496 : vnet_feature_is_enabled (const char *arc_name, const char *feature_node_name,
497 : u32 sw_if_index);
498 :
499 : #endif /* included_feature_h */
500 :
501 : /*
502 : * fd.io coding-style-patch-verification: ON
503 : *
504 : * Local Variables:
505 : * eval: (c-set-style "gnu")
506 : * End:
507 : */
|