hs-test: more debug output in http3 test
[vpp.git] / src / vnet / fib / fib_node.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/fib/fib_node.h>
17 #include <vnet/fib/fib_node_list.h>
18 #include <vnet/fib/fib_table.h>
19 #include <vnet/mfib/mfib_table.h>
20
21 /*
22  * The per-type vector of virtual function tables
23  */
24 static fib_node_vft_t *fn_vfts;
25
26 /**
27  * The last registered new type
28  */
29 static fib_node_type_t last_new_type = FIB_NODE_TYPE_LAST;
30
31 /*
32  * the node type names
33  */
34 static const char *fn_type_builtin_names[] = FIB_NODE_TYPES;
35 static const char **fn_type_names;
36
37 const char*
38 fib_node_type_get_name (fib_node_type_t type)
39 {
40     if ((type < vec_len(fn_type_names)) &&
41          (NULL != fn_type_names[type]))
42     {
43         return (fn_type_names[type]);
44     }
45     else
46     {
47         return ("unknown");
48     }
49 }
50
51 /**
52  * fib_node_register_type
53  *
54  * Register the function table for a given type
55  */
56 static void
57 fib_node_register_type_i (fib_node_type_t type,
58                           const char *name,
59                           const fib_node_vft_t *vft)
60 {
61     /*
62      * assert that one only registration is made per-node type
63      */
64     if (vec_len(fn_vfts) > type)
65         ASSERT(NULL == fn_vfts[type].fnv_get);
66
67     /*
68      * Assert that we are getting each of the required functions
69      */
70     ASSERT(NULL != vft->fnv_get);
71     ASSERT(NULL != vft->fnv_last_lock);
72
73     vec_validate(fn_vfts, type);
74     fn_vfts[type] = *vft;
75     vec_validate(fn_type_names, type);
76     fn_type_names[type] = name;
77 }
78
79 /**
80  * fib_node_register_type
81  *
82  * Register the function table for a given type
83  */
84 void
85 fib_node_register_type (fib_node_type_t type,
86                         const fib_node_vft_t *vft)
87 {
88     fib_node_register_type_i(type, fn_type_builtin_names[type], vft);
89 }
90
91 fib_node_type_t
92 fib_node_register_new_type (const char *name,
93                             const fib_node_vft_t *vft)
94 {
95     fib_node_type_t new_type;
96
97     new_type = ++last_new_type;
98
99     fib_node_register_type_i(new_type, name, vft);
100
101     return (new_type);
102 }   
103
104 static u8*
105 fib_node_format (fib_node_ptr_t *fnp, u8*s)
106 {
107     return (format(s, "{%s:%d}", fn_type_names[fnp->fnp_type], fnp->fnp_index)); 
108 }
109
110 u32
111 fib_node_child_add (fib_node_type_t parent_type,
112                     fib_node_index_t parent_index,
113                     fib_node_type_t type,
114                     fib_node_index_t index)
115 {
116     fib_node_t *parent;
117
118     parent = fn_vfts[parent_type].fnv_get(parent_index);
119
120     /*
121      * return the index of the sibling in the child list
122      */
123     fib_node_lock(parent);
124
125     if (FIB_NODE_INDEX_INVALID == parent->fn_children)
126     {
127         parent->fn_children = fib_node_list_create();
128     }   
129
130     return (fib_node_list_push_front(parent->fn_children,
131                                      0, type,
132                                      index));
133 }
134
135 void
136 fib_node_child_remove (fib_node_type_t parent_type,
137                        fib_node_index_t parent_index,
138                        fib_node_index_t sibling_index)
139 {
140     fib_node_t *parent;
141
142     parent = fn_vfts[parent_type].fnv_get(parent_index);
143
144     fib_node_list_remove(parent->fn_children, sibling_index);
145
146     if (0 == fib_node_list_get_size(parent->fn_children))
147     {
148         fib_node_list_destroy(&parent->fn_children);
149     }
150
151     fib_node_unlock(parent);
152 }
153
154 u32
155 fib_node_get_n_children (fib_node_type_t parent_type,
156                          fib_node_index_t parent_index)
157 {
158     fib_node_t *parent;
159
160     parent = fn_vfts[parent_type].fnv_get(parent_index);
161
162     return (fib_node_list_get_size(parent->fn_children));
163 }
164
165
166 fib_node_back_walk_rc_t
167 fib_node_back_walk_one (fib_node_ptr_t *ptr,
168                         fib_node_back_walk_ctx_t *ctx)
169 {
170     fib_node_t *node;
171
172     node = fn_vfts[ptr->fnp_type].fnv_get(ptr->fnp_index);
173
174     return (fn_vfts[ptr->fnp_type].fnv_back_walk(node, ctx));
175 }
176
177 static walk_rc_t
178 fib_node_ptr_format_one_child (fib_node_ptr_t *ptr,
179                                void *arg)
180 {
181     u8 **s = (u8**) arg;
182
183     *s = fib_node_format(ptr, *s);
184
185     return (WALK_CONTINUE);
186 }
187
188 u8*
189 fib_node_children_format (fib_node_list_t list,
190                           u8 *s)
191 {
192     fib_node_list_walk(list, fib_node_ptr_format_one_child, (void*)&s);
193
194     return (s);
195 }
196
197 void
198 fib_node_init (fib_node_t *node,
199                fib_node_type_t type)
200 {
201     /**
202      * The node's type. used to retrieve the VFT.
203      */
204     node->fn_type = type;
205     node->fn_locks = 0;
206     node->fn_children = FIB_NODE_INDEX_INVALID;
207 }
208
209 void
210 fib_node_deinit (fib_node_t *node)
211 {
212     fib_node_list_destroy(&node->fn_children);
213 }
214
215 void
216 fib_node_lock (fib_node_t *node)
217 {
218     node->fn_locks++;
219 }
220
221 void
222 fib_node_unlock (fib_node_t *node)
223 {
224     node->fn_locks--;
225
226     if (0 == node->fn_locks)
227     {
228         fn_vfts[node->fn_type].fnv_last_lock(node);
229     }
230 }
231
232 void
233 fib_show_memory_usage (const char *name,
234                        u32 in_use_elts,
235                        u32 allocd_elts,
236                        size_t size_elt)
237 {
238     vlib_cli_output (vlib_get_main(), "%=30s %=5d %=8d/%=9d   %d/%d ",
239                      name, size_elt,
240                      in_use_elts, allocd_elts,
241                      in_use_elts*size_elt, allocd_elts*size_elt);
242 }
243
244 static clib_error_t *
245 fib_memory_show (vlib_main_t * vm,
246                  unformat_input_t * input,
247                  vlib_cli_command_t * cmd)
248 {
249     fib_node_vft_t *vft;
250
251     vlib_cli_output (vm, "FIB memory");
252     vlib_cli_output (vm, "  Tables:");
253     vlib_cli_output (vm, "%=30s %=6s %=12s", "SAFI", "Number", "Bytes");
254     vlib_cli_output (vm, "%U", format_fib_table_memory);
255     vlib_cli_output (vm, "%U", format_mfib_table_memory);
256     vlib_cli_output (vm, "  Nodes:");
257     vlib_cli_output (vm, "%=30s %=5s %=8s/%=9s   totals",
258                      "Name","Size", "in-use", "allocated");
259
260     vec_foreach(vft, fn_vfts)
261     {
262         if (NULL != vft->fnv_mem_show)
263             vft->fnv_mem_show();
264     }
265
266     fib_node_list_memory_show();
267
268     return (NULL);
269 }
270
271 /*?
272  * The '<em>sh fib memory </em>' command displays the memory usage for each
273  * FIB object type.
274  *
275  * @cliexpar
276  * @cliexstart{show fib memory}
277  *FIB memory
278  * Tables:
279  *            SAFI              Number   Bytes
280  *        IPv4 unicast             2    673066
281  *        IPv6 unicast             2    1054608
282  *            MPLS                 1    4194312
283  *       IPv4 multicast            2     2322
284  *       IPv6 multicast            2      ???
285  * Nodes:
286  *            Name               Size  in-use /allocated   totals
287  *            Entry               96     20   /    20      1920/1920
288  *        Entry Source            32      0   /    0       0/0
289  *    Entry Path-Extensions       60      0   /    0       0/0
290  *       multicast-Entry         192     12   /    12      2304/2304
291  *          Path-list             40     28   /    28      1120/1120
292  *          uRPF-list             16     20   /    20      320/320
293  *            Path                72     28   /    28      2016/2016
294  *     Node-list elements         20     28   /    28      560/560
295  *       Node-list heads          8      30   /    30      240/240
296  * @cliexend
297 ?*/
298 VLIB_CLI_COMMAND (show_fib_memory, static) = {
299     .path = "show fib memory",
300     .function = fib_memory_show,
301     .short_help = "show fib memory",
302 };