blob: db3e22bb3b8cf4921ac6cacb7e91bdd950cd61db [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>
18
19/*
20 * The per-type vector of virtual function tables
21 */
22static fib_node_vft_t *fn_vfts;
23
24/**
25 * The last registered new type
26 */
27static fib_node_type_t last_new_type = FIB_NODE_TYPE_LAST;
28
29/*
30 * the node type names
31 */
32static const char *fn_type_names[] = FIB_NODE_TYPES;
33
34const char*
35fib_node_type_get_name (fib_node_type_t type)
36{
37 if (type < FIB_NODE_TYPE_LAST)
38 return (fn_type_names[type]);
39 else
40 {
41 if (NULL != fn_vfts[type].fnv_format)
42 {
43 return ("fixme");
44 }
45 else
46 {
47 return ("unknown");
48 }
49 }
50}
51
52/**
53 * fib_node_register_type
54 *
55 * Register the function table for a given type
56 */
57void
58fib_node_register_type (fib_node_type_t type,
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}
76
77fib_node_type_t
78fib_node_register_new_type (const fib_node_vft_t *vft)
79{
80 fib_node_type_t new_type;
81
82 new_type = ++last_new_type;
83
84 fib_node_register_type(new_type, vft);
85
86 return (new_type);
87}
88
89static u8*
90fib_node_format (fib_node_ptr_t *fnp, u8*s)
91{
92 return (format(s, "{%s:%d}", fn_type_names[fnp->fnp_type], fnp->fnp_index));
93}
94
95u32
96fib_node_child_add (fib_node_type_t parent_type,
97 fib_node_index_t parent_index,
98 fib_node_type_t type,
99 fib_node_index_t index)
100{
101 fib_node_t *parent;
102
103 parent = fn_vfts[parent_type].fnv_get(parent_index);
104
105 /*
106 * return the index of the sibling in the child list
107 */
108 fib_node_lock(parent);
109
110 if (FIB_NODE_INDEX_INVALID == parent->fn_children)
111 {
112 parent->fn_children = fib_node_list_create();
113 }
114
115 return (fib_node_list_push_front(parent->fn_children,
116 0, type,
117 index));
118}
119
120void
121fib_node_child_remove (fib_node_type_t parent_type,
122 fib_node_index_t parent_index,
123 fib_node_index_t sibling_index)
124{
125 fib_node_t *parent;
126
127 parent = fn_vfts[parent_type].fnv_get(parent_index);
128
129 fib_node_list_remove(parent->fn_children, sibling_index);
130
131 if (0 == fib_node_list_get_size(parent->fn_children))
132 {
133 fib_node_list_destroy(&parent->fn_children);
134 }
135
136 fib_node_unlock(parent);
137}
138
Neale Rannsad422ed2016-11-02 14:20:04 +0000139u32
140fib_node_get_n_children (fib_node_type_t parent_type,
141 fib_node_index_t parent_index)
142{
143 fib_node_t *parent;
144
145 parent = fn_vfts[parent_type].fnv_get(parent_index);
146
147 return (fib_node_list_get_size(parent->fn_children));
148}
149
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100150
151fib_node_back_walk_rc_t
152fib_node_back_walk_one (fib_node_ptr_t *ptr,
153 fib_node_back_walk_ctx_t *ctx)
154{
155 fib_node_t *node;
156
157 node = fn_vfts[ptr->fnp_type].fnv_get(ptr->fnp_index);
158
159 return (fn_vfts[ptr->fnp_type].fnv_back_walk(node, ctx));
160}
161
162static int
163fib_node_ptr_format_one_child (fib_node_ptr_t *ptr,
164 void *arg)
165{
166 u8 **s = (u8**) arg;
167
168 *s = fib_node_format(ptr, *s);
169
170 return (1);
171}
172
173u8*
174fib_node_children_format (fib_node_list_t list,
175 u8 *s)
176{
177 fib_node_list_walk(list, fib_node_ptr_format_one_child, (void*)&s);
178
179 return (s);
180}
181
182void
183fib_node_init (fib_node_t *node,
184 fib_node_type_t type)
185{
186#if CLIB_DEBUG > 0
187 /**
188 * The node's type. make sure we are dynamic/down casting correctly
189 */
190 node->fn_type = type;
191#endif
192 node->fn_locks = 0;
193 node->fn_vft = &fn_vfts[type];
194 node->fn_children = FIB_NODE_INDEX_INVALID;
195}
196
197void
198fib_node_deinit (fib_node_t *node)
199{
200 fib_node_list_destroy(&node->fn_children);
201}
202
203void
204fib_node_lock (fib_node_t *node)
205{
206 node->fn_locks++;
207}
208
209void
210fib_node_unlock (fib_node_t *node)
211{
212 node->fn_locks--;
213
214 if (0 == node->fn_locks)
215 {
216 node->fn_vft->fnv_last_lock(node);
217 }
218}
Neale Ranns6c3ebcc2016-10-02 21:20:15 +0100219
220void
221fib_show_memory_usage (const char *name,
222 u32 in_use_elts,
223 u32 allocd_elts,
224 size_t size_elt)
225{
226 vlib_cli_output (vlib_get_main(), "%=30s %=5d %=8d/%=9d %d/%d ",
227 name, size_elt,
228 in_use_elts, allocd_elts,
229 in_use_elts*size_elt, allocd_elts*size_elt);
230}
231
232static clib_error_t *
233fib_memory_show (vlib_main_t * vm,
234 unformat_input_t * input,
235 vlib_cli_command_t * cmd)
236{
237 fib_node_vft_t *vft;
238
239 vlib_cli_output (vm, "FIB memory");
240 vlib_cli_output (vm, "%=30s %=5s %=8s/%=9s totals",
241 "Name","Size", "in-use", "allocated");
242
243 vec_foreach(vft, fn_vfts)
244 {
245 if (NULL != vft->fnv_mem_show)
246 vft->fnv_mem_show();
247 }
248
249 fib_node_list_memory_show();
250
251 return (NULL);
252}
253
254/* *INDENT-OFF* */
255/*?
256 * The '<em>sh fib memory </em>' command displays the memory usage for each
257 * FIB object type.
258 *
259 * @cliexpar
260 * @cliexstart{show fib memory}
261 * FIB memory
262 * Name Size in-use /allocated totals
263 * Entry 120 11 / 11 1320/1320
264 * Entry Source 32 11 / 11 352/352
265 * Entry Path-Extensions 44 0 / 0 0/0
266 * Path-list 40 11 / 11 440/440
267 * Path 88 11 / 11 968/968
268 * Node-list elements 20 11 / 11 220/220
269 * Node-list heads 8 13 / 13 104/104
270 * @cliexend
271?*/
272VLIB_CLI_COMMAND (show_fib_memory, static) = {
273 .path = "show fib memory",
274 .function = fib_memory_show,
275 .short_help = "show fib memory",
276};
277/* *INDENT-ON* */