feature: add new feature handling code and device-input features
[vpp.git] / vnet / 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
21 /** feature registration object */
22 typedef struct _vnet_feature_arc_registration
23 {
24   /** next registration in list of all registrations*/
25   struct _vnet_feature_arc_registration *next;
26   /** Feature Arc name */
27   char *arc_name;
28   /** Start nodes */
29   char **start_nodes;
30   int n_start_nodes;
31   /* Feature arc index, assigned by init function */
32   u16 feature_arc_index;
33 } vnet_feature_arc_registration_t;
34
35 /** feature registration object */
36 typedef struct _vnet_feature_registration
37 {
38   /** next registration in list of all registrations*/
39   struct _vnet_feature_registration *next;
40   /** Feature arc name */
41   char *arc_name;
42   /** Graph node name */
43   char *node_name;
44   /** Pointer to this feature index, filled in by vnet_feature_arc_init */
45   u32 *feature_index;
46   u32 feature_index_u32;
47   /** Constraints of the form "this feature runs before X" */
48   char **runs_before;
49   /** Constraints of the form "this feature runs after Y" */
50   char **runs_after;
51 } vnet_feature_registration_t;
52
53 typedef struct vnet_feature_config_main_t_
54 {
55   vnet_config_main_t config_main;
56   u32 *config_index_by_sw_if_index;
57 } vnet_feature_config_main_t;
58
59 typedef struct
60 {
61   /** feature arc configuration list */
62   vnet_feature_arc_registration_t *next_arc;
63   uword **arc_index_by_name;
64
65   /** feature path configuration lists */
66   vnet_feature_registration_t *next_feature;
67   vnet_feature_registration_t **next_feature_by_arc;
68   uword **next_feature_by_name;
69
70   /** feature config main objects */
71   vnet_feature_config_main_t *feature_config_mains;
72
73   /** Save partial order results for show command */
74   char ***feature_nodes;
75
76   /** bitmap of interfaces which have driver rx features configured */
77   uword **sw_if_index_has_features;
78
79   /** feature reference counts by interface */
80   i16 **feature_count_by_sw_if_index;
81
82   /** convenience */
83   vlib_main_t *vlib_main;
84   vnet_main_t *vnet_main;
85 } vnet_feature_main_t;
86
87 extern vnet_feature_main_t feature_main;
88
89 #define VNET_FEATURE_ARC_INIT(x,...)                            \
90   __VA_ARGS__ vnet_feature_arc_registration_t vnet_feat_arc_##x;\
91 static void __vnet_add_feature_arc_registration_##x (void)      \
92   __attribute__((__constructor__)) ;                            \
93 static void __vnet_add_feature_arc_registration_##x (void)      \
94 {                                                               \
95   vnet_feature_main_t * fm = &feature_main;                     \
96   vnet_feat_arc_##x.next = fm->next_arc;                        \
97   fm->next_arc = & vnet_feat_arc_##x;                           \
98 }                                                               \
99 __VA_ARGS__ vnet_feature_arc_registration_t vnet_feat_arc_##x
100
101 #define VNET_FEATURE_INIT(x,...)                                \
102   __VA_ARGS__ vnet_feature_registration_t vnet_feat_##x;        \
103 static void __vnet_add_feature_registration_##x (void)          \
104   __attribute__((__constructor__)) ;                            \
105 static void __vnet_add_feature_registration_##x (void)          \
106 {                                                               \
107   vnet_feature_main_t * fm = &feature_main;                     \
108   vnet_feat_##x.next = fm->next_feature;                        \
109   fm->next_feature = & vnet_feat_##x;                           \
110 }                                                               \
111 __VA_ARGS__ vnet_feature_registration_t vnet_feat_##x
112
113 void
114 vnet_config_update_feature_count (vnet_feature_main_t * fm, u16 arc,
115                                   u32 sw_if_index, int is_add);
116
117 u32 vnet_feature_index_from_node_name (u16 type, const char *s);
118
119 void
120 vnet_feature_enable_disable (const char *arc_name, const char *node_name,
121                              u32 sw_if_index, int enable_disable,
122                              void *feature_config,
123                              u32 n_feature_config_bytes);
124
125
126 static_always_inline int
127 vnet_have_features (u32 arc, u32 sw_if_index)
128 {
129   vnet_feature_main_t *fm = &feature_main;
130   return clib_bitmap_get (fm->sw_if_index_has_features[arc], sw_if_index);
131 }
132
133 static_always_inline u32
134 vnet_feature_get_config_index (u16 arc, u32 sw_if_index)
135 {
136   vnet_feature_main_t *fm = &feature_main;
137   vnet_feature_config_main_t *cm = &fm->feature_config_mains[arc];
138   return vec_elt (cm->config_index_by_sw_if_index, sw_if_index);
139 }
140
141 static_always_inline void
142 vnet_feature_redirect (u16 arc, u32 sw_if_index, u32 * next0,
143                        vlib_buffer_t * b0)
144 {
145   vnet_feature_main_t *fm = &feature_main;
146   vnet_feature_config_main_t *cm = &fm->feature_config_mains[arc];
147
148   if (PREDICT_FALSE (vnet_have_features (arc, sw_if_index)))
149     {
150       b0->current_config_index =
151         vec_elt (cm->config_index_by_sw_if_index, sw_if_index);
152       vnet_get_config_data (&cm->config_main, &b0->current_config_index,
153                             next0, /* # bytes of config data */ 0);
154     }
155 }
156
157 static_always_inline void
158 vnet_feature_device_input_redirect_x1 (vlib_node_runtime_t * node,
159                                        u32 sw_if_index, u32 * next0,
160                                        vlib_buffer_t * b0,
161                                        u16 buffer_advanced0)
162 {
163   vnet_feature_main_t *fm = &feature_main;
164   vnet_feature_config_main_t *cm;
165
166   ASSERT (node->feature_arc_index != ~(u16) 0);
167   cm = &fm->feature_config_mains[node->feature_arc_index];
168
169   if (PREDICT_FALSE
170       (clib_bitmap_get
171        (fm->sw_if_index_has_features[node->feature_arc_index], sw_if_index)))
172     {
173       /*
174        * Save next0 so that the last feature in the chain
175        * can skip ethernet-input if indicated...
176        */
177       vnet_buffer (b0)->device_input_feat.saved_next_index = *next0;
178       vnet_buffer (b0)->device_input_feat.buffer_advance = buffer_advanced0;
179       vlib_buffer_advance (b0, -buffer_advanced0);
180
181       b0->current_config_index =
182         vec_elt (cm->config_index_by_sw_if_index, sw_if_index);
183       vnet_get_config_data (&cm->config_main, &b0->current_config_index,
184                             next0, /* # bytes of config data */ 0);
185     }
186 }
187
188 #define ORDER_CONSTRAINTS (char*[])
189 #define VNET_FEATURES(...)  (char*[]) { __VA_ARGS__, 0}
190
191 clib_error_t *vnet_feature_arc_init (vlib_main_t * vm,
192                                      vnet_config_main_t * vcm,
193                                      char **feature_start_nodes,
194                                      int num_feature_start_nodes,
195                                      vnet_feature_registration_t *
196                                      first_reg, char ***feature_nodes);
197
198 void vnet_interface_features_show (vlib_main_t * vm, u32 sw_if_index);
199
200 #endif /* included_feature_h */
201
202 /*
203  * fd.io coding-style-patch-verification: ON
204  *
205  * Local Variables:
206  * eval: (c-set-style "gnu")
207  * End:
208  */