fix isssues discovered by coverity scan
[vpp.git] / vnet / vnet / feature / feature.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/feature/feature.h>
17
18 vnet_feature_main_t feature_main;
19
20 static clib_error_t *
21 vnet_feature_init (vlib_main_t * vm)
22 {
23   vnet_feature_main_t *fm = &feature_main;
24   vnet_feature_registration_t *freg;
25   vnet_feature_arc_registration_t *areg;
26   u32 arc_index = 0;
27
28   fm->arc_index_by_name = hash_create_string (0, sizeof (uword));
29   areg = fm->next_arc;
30
31   /* process feature arc registrations */
32   while (areg)
33     {
34       char *s;
35       int i = 0;
36       areg->feature_arc_index = arc_index;
37       hash_set_mem (fm->arc_index_by_name, areg->arc_name,
38                     pointer_to_uword (areg));
39
40       /* process start nodes */
41       while ((s = areg->start_nodes[i]))
42         {
43           i++;
44         }
45       areg->n_start_nodes = i;
46
47       /* next */
48       areg = areg->next;
49       arc_index++;
50     }
51
52   vec_validate (fm->next_feature_by_arc, arc_index - 1);
53   vec_validate (fm->feature_nodes, arc_index - 1);
54   vec_validate (fm->feature_config_mains, arc_index - 1);
55   vec_validate (fm->next_feature_by_name, arc_index - 1);
56   vec_validate (fm->sw_if_index_has_features, arc_index - 1);
57   vec_validate (fm->feature_count_by_sw_if_index, arc_index - 1);
58
59   freg = fm->next_feature;
60   while (freg)
61     {
62       uword *p = hash_get_mem (fm->arc_index_by_name, freg->arc_name);
63       if (p == 0)
64         return clib_error_return (0, "Unknown feature arc '%s'",
65                                   freg->arc_name);
66
67       areg = uword_to_pointer (p[0], vnet_feature_arc_registration_t *);
68       arc_index = areg->feature_arc_index;
69
70       vec_add1 (fm->next_feature_by_arc[arc_index], *freg);
71
72       /* next */
73       freg = freg->next;
74     }
75
76   while (areg)
77     {
78       clib_error_t *error;
79       vnet_feature_config_main_t *cm;
80       vnet_config_main_t *vcm;
81
82       arc_index = areg->feature_arc_index;
83       cm = &fm->feature_config_mains[arc_index];
84       vcm = &cm->config_main;
85       if ((error = vnet_feature_arc_init (vm, vcm,
86                                           areg->start_nodes,
87                                           areg->n_start_nodes,
88                                           fm->next_feature_by_arc[arc_index],
89                                           &fm->feature_nodes[arc_index])))
90         {
91           return error;
92         }
93
94       fm->next_feature_by_name[arc_index] =
95         hash_create_string (0, sizeof (uword));
96       freg = fm->next_feature_by_arc[arc_index];
97
98       while (freg)
99         {
100           hash_set_mem (fm->next_feature_by_name[arc_index],
101                         freg->node_name, pointer_to_uword (freg));
102           freg = freg->next;
103         }
104
105       /* next */
106       areg = areg->next;
107       arc_index++;
108     }
109
110   fm->device_input_feature_arc_index =
111     vnet_get_feature_arc_index ("device-input");
112   return 0;
113 }
114
115 VLIB_INIT_FUNCTION (vnet_feature_init);
116
117 void
118 vnet_config_update_feature_count (vnet_feature_main_t * fm, u8 arc,
119                                   u32 sw_if_index, int is_add)
120 {
121   uword bit_value;
122
123   vec_validate (fm->feature_count_by_sw_if_index[arc], sw_if_index);
124
125   fm->feature_count_by_sw_if_index[arc][sw_if_index] += is_add ? 1 : -1;
126
127   ASSERT (fm->feature_count_by_sw_if_index[arc][sw_if_index] >= 0);
128
129   bit_value = fm->feature_count_by_sw_if_index[arc][sw_if_index] > 0;
130
131   fm->sw_if_index_has_features[arc] =
132     clib_bitmap_set (fm->sw_if_index_has_features[arc], sw_if_index,
133                      bit_value);
134 }
135
136 u8
137 vnet_get_feature_arc_index (const char *s)
138 {
139   vnet_feature_main_t *fm = &feature_main;
140   vnet_feature_arc_registration_t *reg;
141   uword *p;
142
143   p = hash_get_mem (fm->arc_index_by_name, s);
144   if (p == 0)
145     return ~0;
146
147   reg = uword_to_pointer (p[0], vnet_feature_arc_registration_t *);
148   return reg->feature_arc_index;
149 }
150
151 u32
152 vnet_get_feature_index (u8 arc, const char *s)
153 {
154   vnet_feature_main_t *fm = &feature_main;
155   vnet_feature_registration_t *reg;
156   uword *p;
157
158   p = hash_get_mem (fm->next_feature_by_name[arc], s);
159   if (p == 0)
160     return ~0;
161
162   reg = uword_to_pointer (p[0], vnet_feature_registration_t *);
163   return reg->feature_index_u32;
164 }
165
166 void
167 vnet_feature_enable_disable (const char *arc_name, const char *node_name,
168                              u32 sw_if_index, int enable_disable,
169                              void *feature_config, u32 n_feature_config_bytes)
170 {
171   vnet_feature_main_t *fm = &feature_main;
172   vnet_feature_config_main_t *cm;
173   u32 feature_index, ci;
174   u8 arc_index;
175
176   arc_index = vnet_get_feature_arc_index (arc_name);
177
178   if (arc_index == ~(u8) 0)
179     return;
180
181   cm = &fm->feature_config_mains[arc_index];
182   vec_validate_init_empty (cm->config_index_by_sw_if_index, sw_if_index, ~0);
183   feature_index = vnet_get_feature_index (arc_index, node_name);
184   if (feature_index == ~0)
185     return;
186   ci = cm->config_index_by_sw_if_index[sw_if_index];
187
188   ci = (enable_disable
189         ? vnet_config_add_feature
190         : vnet_config_del_feature)
191     (vlib_get_main (), &cm->config_main, ci, feature_index, feature_config,
192      n_feature_config_bytes);
193   cm->config_index_by_sw_if_index[sw_if_index] = ci;
194
195   vnet_config_update_feature_count (fm, arc_index, sw_if_index,
196                                     enable_disable);
197
198 }
199
200
201 /** Display the set of available driver features.
202     Useful for verifying that expected features are present
203 */
204
205 static clib_error_t *
206 show_features_command_fn (vlib_main_t * vm,
207                           unformat_input_t * input, vlib_cli_command_t * cmd)
208 {
209   vnet_feature_main_t *fm = &feature_main;
210   vnet_feature_arc_registration_t *areg;
211   vnet_feature_registration_t *freg;
212
213   vlib_cli_output (vm, "Available feature paths");
214
215   areg = fm->next_arc;
216   while (areg)
217     {
218       vlib_cli_output (vm, "%s:", areg->arc_name);
219       vec_foreach (freg, fm->next_feature_by_arc[areg->feature_arc_index])
220       {
221         vlib_cli_output (vm, "  %s\n", freg->node_name);
222       }
223
224
225       /* next */
226       areg = areg->next;
227     }
228
229   return 0;
230 }
231
232 /*?
233  * Display the set of available driver features
234  *
235  * @cliexpar
236  * Example:
237  * @cliexcmd{show ip features}
238  * @cliexend
239  * @endparblock
240 ?*/
241 /* *INDENT-OFF* */
242 VLIB_CLI_COMMAND (show_features_command, static) = {
243   .path = "show features",
244   .short_help = "show features",
245   .function = show_features_command_fn,
246 };
247 /* *INDENT-ON* */
248
249 /** Display the set of driver features configured on a specific interface
250   * Called by "show interface" handler
251  */
252
253 void
254 vnet_interface_features_show (vlib_main_t * vm, u32 sw_if_index)
255 {
256   vnet_feature_main_t *fm = &feature_main;
257   u32 node_index, current_config_index;
258   u16 feature_arc;
259   vnet_feature_config_main_t *cm = fm->feature_config_mains;
260   vnet_feature_arc_registration_t *areg;
261   vnet_config_main_t *vcm;
262   vnet_config_t *cfg;
263   u32 cfg_index;
264   vnet_config_feature_t *feat;
265   vlib_node_t *n;
266   int i;
267
268   vlib_cli_output (vm, "Driver feature paths configured on %U...",
269                    format_vnet_sw_if_index_name,
270                    vnet_get_main (), sw_if_index);
271
272   areg = fm->next_arc;
273   while (areg)
274     {
275       feature_arc = areg->feature_arc_index;
276       vcm = &(cm[feature_arc].config_main);
277
278       vlib_cli_output (vm, "\n%s:", areg->arc_name);
279       areg = areg->next;
280
281       if (NULL == cm[feature_arc].config_index_by_sw_if_index ||
282           vec_len (cm[feature_arc].config_index_by_sw_if_index) <=
283           sw_if_index)
284         {
285           vlib_cli_output (vm, "  none configured");
286           continue;
287         }
288
289       current_config_index =
290         vec_elt (cm[feature_arc].config_index_by_sw_if_index, sw_if_index);
291
292       if (current_config_index == ~0)
293         {
294           vlib_cli_output (vm, "  none configured");
295           continue;
296         }
297
298       ASSERT (current_config_index
299               < vec_len (vcm->config_pool_index_by_user_index));
300
301       cfg_index = vcm->config_pool_index_by_user_index[current_config_index];
302       cfg = pool_elt_at_index (vcm->config_pool, cfg_index);
303
304       for (i = 0; i < vec_len (cfg->features); i++)
305         {
306           feat = cfg->features + i;
307           node_index = feat->node_index;
308           n = vlib_get_node (vm, node_index);
309           vlib_cli_output (vm, "  %v", n->name);
310         }
311     }
312 }
313
314 /*
315  * fd.io coding-style-patch-verification: ON
316  *
317  * Local Variables:
318  * eval: (c-set-style "gnu")
319  * End:
320  */