blob: 35fe9c828a64ed40e4a1576b155751e760aff956 [file] [log] [blame]
Neale Ranns1f50bf82019-07-16 15:28:52 +00001/*
2 * Copyright (c) 2019 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_entry_track.h>
17#include <vnet/fib/fib_table.h>
18#include <vnet/fib/fib_entry_delegate.h>
19#include <vnet/fib/fib_walk.h>
20
21static fib_entry_delegate_t *
22fib_entry_track_delegate_add (u32 fib_index,
23 const fib_prefix_t *prefix)
24{
25 fib_entry_delegate_t *fed;
26 fib_node_index_t fei;
27
28 fei = fib_table_entry_special_add(fib_index,
29 prefix,
30 FIB_SOURCE_RR,
31 FIB_ENTRY_FLAG_NONE);
32
33 fed = fib_entry_delegate_find_or_add(fib_entry_get(fei),
34 FIB_ENTRY_DELEGATE_TRACK);
35
36 fib_node_init(&fed->fd_track.fedt_node,
37 FIB_NODE_TYPE_ENTRY_TRACK);
38
39 fed->fd_entry_index = fei;
40 fed->fd_track.fedt_sibling =
41 fib_entry_child_add(fei,
42 FIB_NODE_TYPE_ENTRY_TRACK,
43 fib_entry_delegate_get_index(fed));
44
45 return (fed);
46}
47
48fib_node_index_t
49fib_entry_track (u32 fib_index,
50 const fib_prefix_t *prefix,
51 fib_node_type_t child_type,
52 index_t child_index,
53 u32 *sibling)
54{
55 fib_entry_delegate_t *fed;
56 fib_node_index_t fei;
57
58 fei = fib_table_lookup_exact_match(fib_index, prefix);
59
60 if (INDEX_INVALID == fei ||
61 NULL == (fed = fib_entry_delegate_find(fib_entry_get(fei),
62 FIB_ENTRY_DELEGATE_TRACK)))
63 {
64 fed = fib_entry_track_delegate_add(fib_index, prefix);
65 }
66
67 /*
68 * add this child to the entry's delegate
69 */
70 *sibling = fib_node_child_add(FIB_NODE_TYPE_ENTRY_TRACK,
71 fib_entry_delegate_get_index(fed),
72 child_type,
73 child_index);
74
75 return (fed->fd_entry_index);
76}
77
78void
79fib_entry_untrack (fib_node_index_t fei,
80 u32 sibling)
81{
82 fib_entry_delegate_t *fed;
83
84 fed = fib_entry_delegate_find(fib_entry_get(fei),
85 FIB_ENTRY_DELEGATE_TRACK);
86
87 if (NULL != fed)
88 {
89 fib_node_child_remove(FIB_NODE_TYPE_ENTRY_TRACK,
90 fib_entry_delegate_get_index(fed),
91 sibling);
92 /* if this is the last child the delegate will be removed. */
93 }
94 /* else untracked */
95}
96
97static fib_node_t *
98fib_entry_track_get_node (fib_node_index_t index)
99{
100 fib_entry_delegate_t *fed;
101
102 fed = fib_entry_delegate_get(index);
103 return (&fed->fd_track.fedt_node);
104}
105
106static fib_entry_delegate_t*
107fib_entry_delegate_from_fib_node (fib_node_t *node)
108{
109 ASSERT(FIB_NODE_TYPE_ENTRY_TRACK == node->fn_type);
110 return ((fib_entry_delegate_t *) (((char *) node) -
111 STRUCT_OFFSET_OF (fib_entry_delegate_t,
112 fd_track.fedt_node)));
113}
114
115static void
116fib_entry_track_last_lock_gone (fib_node_t *node)
117{
118 fib_entry_delegate_t *fed;
119 fib_node_index_t fei;
120 u32 sibling;
121
122 fed = fib_entry_delegate_from_fib_node(node);
123 fei = fed->fd_entry_index;
124 sibling = fed->fd_track.fedt_sibling;
125
126 /*
127 * the tracker has no more children so it can be removed,
128 * and the FIB entry unsourced.
129 * remove the delegate first, then unlock the fib entry,
130 * since the delegate may be holding the last lock
131 */
132 fib_entry_delegate_remove(fib_entry_get(fei),
133 FIB_ENTRY_DELEGATE_TRACK);
134 /* having removed the deletegate the fed object is now toast */
135 fib_entry_child_remove(fei, sibling);
136
137 fib_table_entry_delete_index(fei, FIB_SOURCE_RR);
138}
139
140static fib_node_back_walk_rc_t
141fib_entry_track_back_walk_notify (fib_node_t *node,
142 fib_node_back_walk_ctx_t *ctx)
143{
144 fib_entry_delegate_t *fed;
145
146 fed = fib_entry_delegate_from_fib_node(node);
147
148 /*
149 * propagate the walk to the delgate's children
150 */
151
152 fib_walk_sync(FIB_NODE_TYPE_ENTRY_TRACK,
153 fib_entry_delegate_get_index(fed),
154 ctx);
155
156 return (FIB_NODE_BACK_WALK_CONTINUE);
157}
158
159static void
160fib_entry_track_show_memory (void)
161{
162}
163
164/*
165 * The FIB entry tracker's graph node virtual function table
166 */
167static const fib_node_vft_t fib_entry_track_vft = {
168 .fnv_get = fib_entry_track_get_node,
169 .fnv_last_lock = fib_entry_track_last_lock_gone,
170 .fnv_back_walk = fib_entry_track_back_walk_notify,
171 .fnv_mem_show = fib_entry_track_show_memory,
172};
173
174void
175fib_entry_track_module_init (void)
176{
177 fib_node_register_type(FIB_NODE_TYPE_ENTRY_TRACK, &fib_entry_track_vft);
178}