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 : #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 127 : fib_node_type_get_name (fib_node_type_t type)
39 : {
40 127 : if ((type < vec_len(fn_type_names)) &&
41 127 : (NULL != fn_type_names[type]))
42 : {
43 127 : return (fn_type_names[type]);
44 : }
45 : else
46 : {
47 0 : 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 16771 : 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 16771 : if (vec_len(fn_vfts) > type)
65 9503 : ASSERT(NULL == fn_vfts[type].fnv_get);
66 :
67 : /*
68 : * Assert that we are getting each of the required functions
69 : */
70 16771 : ASSERT(NULL != vft->fnv_get);
71 16771 : ASSERT(NULL != vft->fnv_last_lock);
72 :
73 16771 : vec_validate(fn_vfts, type);
74 16771 : fn_vfts[type] = *vft;
75 16771 : vec_validate(fn_type_names, type);
76 16771 : fn_type_names[type] = name;
77 16771 : }
78 :
79 : /**
80 : * fib_node_register_type
81 : *
82 : * Register the function table for a given type
83 : */
84 : void
85 10621 : fib_node_register_type (fib_node_type_t type,
86 : const fib_node_vft_t *vft)
87 : {
88 10621 : fib_node_register_type_i(type, fn_type_builtin_names[type], vft);
89 10621 : }
90 :
91 : fib_node_type_t
92 6150 : 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 6150 : new_type = ++last_new_type;
98 :
99 6150 : fib_node_register_type_i(new_type, name, vft);
100 :
101 6150 : return (new_type);
102 : }
103 :
104 : static u8*
105 10 : fib_node_format (fib_node_ptr_t *fnp, u8*s)
106 : {
107 10 : return (format(s, "{%s:%d}", fn_type_names[fnp->fnp_type], fnp->fnp_index));
108 : }
109 :
110 : u32
111 231137 : 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 231137 : parent = fn_vfts[parent_type].fnv_get(parent_index);
119 :
120 : /*
121 : * return the index of the sibling in the child list
122 : */
123 231137 : fib_node_lock(parent);
124 :
125 231137 : if (FIB_NODE_INDEX_INVALID == parent->fn_children)
126 : {
127 129430 : parent->fn_children = fib_node_list_create();
128 : }
129 :
130 231137 : return (fib_node_list_push_front(parent->fn_children,
131 : 0, type,
132 : index));
133 : }
134 :
135 : void
136 211813 : 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 211813 : parent = fn_vfts[parent_type].fnv_get(parent_index);
143 :
144 211813 : fib_node_list_remove(parent->fn_children, sibling_index);
145 :
146 211813 : if (0 == fib_node_list_get_size(parent->fn_children))
147 : {
148 111020 : fib_node_list_destroy(&parent->fn_children);
149 : }
150 :
151 211813 : fib_node_unlock(parent);
152 211813 : }
153 :
154 : u32
155 320122 : 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 320122 : parent = fn_vfts[parent_type].fnv_get(parent_index);
161 :
162 320122 : return (fib_node_list_get_size(parent->fn_children));
163 : }
164 :
165 :
166 : fib_node_back_walk_rc_t
167 78580 : 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 78580 : node = fn_vfts[ptr->fnp_type].fnv_get(ptr->fnp_index);
173 :
174 78580 : return (fn_vfts[ptr->fnp_type].fnv_back_walk(node, ctx));
175 : }
176 :
177 : static walk_rc_t
178 10 : fib_node_ptr_format_one_child (fib_node_ptr_t *ptr,
179 : void *arg)
180 : {
181 10 : u8 **s = (u8**) arg;
182 :
183 10 : *s = fib_node_format(ptr, *s);
184 :
185 10 : return (WALK_CONTINUE);
186 : }
187 :
188 : u8*
189 8 : fib_node_children_format (fib_node_list_t list,
190 : u8 *s)
191 : {
192 8 : fib_node_list_walk(list, fib_node_ptr_format_one_child, (void*)&s);
193 :
194 8 : return (s);
195 : }
196 :
197 : void
198 316171 : 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 316171 : node->fn_type = type;
205 316171 : node->fn_locks = 0;
206 316171 : node->fn_children = FIB_NODE_INDEX_INVALID;
207 316171 : }
208 :
209 : void
210 256168 : fib_node_deinit (fib_node_t *node)
211 : {
212 256168 : fib_node_list_destroy(&node->fn_children);
213 256168 : }
214 :
215 : void
216 861715 : fib_node_lock (fib_node_t *node)
217 : {
218 861715 : node->fn_locks++;
219 861715 : }
220 :
221 : void
222 790931 : fib_node_unlock (fib_node_t *node)
223 : {
224 790931 : node->fn_locks--;
225 :
226 790931 : if (0 == node->fn_locks)
227 : {
228 108169 : fn_vfts[node->fn_type].fnv_last_lock(node);
229 : }
230 790931 : }
231 :
232 : void
233 9 : fib_show_memory_usage (const char *name,
234 : u32 in_use_elts,
235 : u32 allocd_elts,
236 : size_t size_elt)
237 : {
238 9 : 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 9 : }
243 :
244 : static clib_error_t *
245 1 : 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 1 : vlib_cli_output (vm, "FIB memory");
252 1 : vlib_cli_output (vm, " Tables:");
253 1 : vlib_cli_output (vm, "%=30s %=6s %=12s", "SAFI", "Number", "Bytes");
254 1 : vlib_cli_output (vm, "%U", format_fib_table_memory);
255 1 : vlib_cli_output (vm, "%U", format_mfib_table_memory);
256 1 : vlib_cli_output (vm, " Nodes:");
257 1 : vlib_cli_output (vm, "%=30s %=5s %=8s/%=9s totals",
258 : "Name","Size", "in-use", "allocated");
259 :
260 35 : vec_foreach(vft, fn_vfts)
261 : {
262 34 : if (NULL != vft->fnv_mem_show)
263 5 : vft->fnv_mem_show();
264 : }
265 :
266 1 : fib_node_list_memory_show();
267 :
268 1 : return (NULL);
269 : }
270 :
271 : /* *INDENT-OFF* */
272 : /*?
273 : * The '<em>sh fib memory </em>' command displays the memory usage for each
274 : * FIB object type.
275 : *
276 : * @cliexpar
277 : * @cliexstart{show fib memory}
278 : *FIB memory
279 : * Tables:
280 : * SAFI Number Bytes
281 : * IPv4 unicast 2 673066
282 : * IPv6 unicast 2 1054608
283 : * MPLS 1 4194312
284 : * IPv4 multicast 2 2322
285 : * IPv6 multicast 2 ???
286 : * Nodes:
287 : * Name Size in-use /allocated totals
288 : * Entry 96 20 / 20 1920/1920
289 : * Entry Source 32 0 / 0 0/0
290 : * Entry Path-Extensions 60 0 / 0 0/0
291 : * multicast-Entry 192 12 / 12 2304/2304
292 : * Path-list 40 28 / 28 1120/1120
293 : * uRPF-list 16 20 / 20 320/320
294 : * Path 72 28 / 28 2016/2016
295 : * Node-list elements 20 28 / 28 560/560
296 : * Node-list heads 8 30 / 30 240/240
297 : * @cliexend
298 : ?*/
299 272887 : VLIB_CLI_COMMAND (show_fib_memory, static) = {
300 : .path = "show fib memory",
301 : .function = fib_memory_show,
302 : .short_help = "show fib memory",
303 : };
304 : /* *INDENT-ON* */
|