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