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