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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include <vnet/fib/fib_node.h>
17 #include <vnet/fib/fib_node_list.h>
20 * The per-type vector of virtual function tables
22 static fib_node_vft_t *fn_vfts;
25 * The last registered new type
27 static fib_node_type_t last_new_type = FIB_NODE_TYPE_LAST;
32 static const char *fn_type_names[] = FIB_NODE_TYPES;
35 fib_node_type_get_name (fib_node_type_t type)
37 if (type < FIB_NODE_TYPE_LAST)
38 return (fn_type_names[type]);
41 if (NULL != fn_vfts[type].fnv_format)
53 * fib_node_register_type
55 * Register the function table for a given type
58 fib_node_register_type (fib_node_type_t type,
59 const fib_node_vft_t *vft)
62 * assert that one only registration is made per-node type
64 if (vec_len(fn_vfts) > type)
65 ASSERT(NULL == fn_vfts[type].fnv_get);
68 * Assert that we are getting each of the required functions
70 ASSERT(NULL != vft->fnv_get);
71 ASSERT(NULL != vft->fnv_last_lock);
73 vec_validate(fn_vfts, type);
78 fib_node_register_new_type (const fib_node_vft_t *vft)
80 fib_node_type_t new_type;
82 new_type = ++last_new_type;
84 fib_node_register_type(new_type, vft);
90 fib_node_format (fib_node_ptr_t *fnp, u8*s)
92 return (format(s, "{%s:%d}", fn_type_names[fnp->fnp_type], fnp->fnp_index));
96 fib_node_child_add (fib_node_type_t parent_type,
97 fib_node_index_t parent_index,
99 fib_node_index_t index)
103 parent = fn_vfts[parent_type].fnv_get(parent_index);
106 * return the index of the sibling in the child list
108 fib_node_lock(parent);
110 if (FIB_NODE_INDEX_INVALID == parent->fn_children)
112 parent->fn_children = fib_node_list_create();
115 return (fib_node_list_push_front(parent->fn_children,
121 fib_node_child_remove (fib_node_type_t parent_type,
122 fib_node_index_t parent_index,
123 fib_node_index_t sibling_index)
127 parent = fn_vfts[parent_type].fnv_get(parent_index);
129 fib_node_list_remove(parent->fn_children, sibling_index);
131 if (0 == fib_node_list_get_size(parent->fn_children))
133 fib_node_list_destroy(&parent->fn_children);
136 fib_node_unlock(parent);
140 fib_node_back_walk_rc_t
141 fib_node_back_walk_one (fib_node_ptr_t *ptr,
142 fib_node_back_walk_ctx_t *ctx)
146 node = fn_vfts[ptr->fnp_type].fnv_get(ptr->fnp_index);
148 return (fn_vfts[ptr->fnp_type].fnv_back_walk(node, ctx));
152 fib_node_ptr_format_one_child (fib_node_ptr_t *ptr,
157 *s = fib_node_format(ptr, *s);
163 fib_node_children_format (fib_node_list_t list,
166 fib_node_list_walk(list, fib_node_ptr_format_one_child, (void*)&s);
172 fib_node_init (fib_node_t *node,
173 fib_node_type_t type)
177 * The node's type. make sure we are dynamic/down casting correctly
179 node->fn_type = type;
182 node->fn_vft = &fn_vfts[type];
183 node->fn_children = FIB_NODE_INDEX_INVALID;
187 fib_node_deinit (fib_node_t *node)
189 fib_node_list_destroy(&node->fn_children);
193 fib_node_lock (fib_node_t *node)
199 fib_node_unlock (fib_node_t *node)
203 if (0 == node->fn_locks)
205 node->fn_vft->fnv_last_lock(node);