Line data Source code
1 : /*
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 :
21 : static fib_entry_delegate_t *
22 3905 : fib_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 3905 : fei = fib_table_entry_special_add(fib_index,
29 : prefix,
30 : FIB_SOURCE_RR,
31 : FIB_ENTRY_FLAG_NONE);
32 :
33 3905 : fed = fib_entry_delegate_find_or_add(fib_entry_get(fei),
34 : FIB_ENTRY_DELEGATE_TRACK);
35 :
36 3905 : fib_node_init(&fed->fd_track.fedt_node,
37 : FIB_NODE_TYPE_ENTRY_TRACK);
38 :
39 3905 : fed->fd_entry_index = fei;
40 3905 : fed->fd_track.fedt_sibling =
41 3905 : fib_entry_child_add(fei,
42 : FIB_NODE_TYPE_ENTRY_TRACK,
43 : fib_entry_delegate_get_index(fed));
44 :
45 3905 : return (fed);
46 : }
47 :
48 : fib_node_index_t
49 4357 : fib_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 4357 : fei = fib_table_lookup_exact_match(fib_index, prefix);
59 :
60 8699 : if (INDEX_INVALID == fei ||
61 4342 : NULL == (fed = fib_entry_delegate_find(fib_entry_get(fei),
62 : FIB_ENTRY_DELEGATE_TRACK)))
63 : {
64 3905 : fed = fib_entry_track_delegate_add(fib_index, prefix);
65 : }
66 :
67 : /*
68 : * add this child to the entry's delegate
69 : */
70 4357 : *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 4357 : return (fed->fd_entry_index);
76 : }
77 :
78 : void
79 4300 : fib_entry_untrack (fib_node_index_t fei,
80 : u32 sibling)
81 : {
82 : fib_entry_delegate_t *fed;
83 :
84 4300 : fed = fib_entry_delegate_find(fib_entry_get(fei),
85 : FIB_ENTRY_DELEGATE_TRACK);
86 :
87 4300 : if (NULL != fed)
88 : {
89 4300 : 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 4300 : }
96 :
97 : static fib_node_t *
98 11185 : fib_entry_track_get_node (fib_node_index_t index)
99 : {
100 : fib_entry_delegate_t *fed;
101 :
102 11185 : fed = fib_entry_delegate_get(index);
103 11185 : return (&fed->fd_track.fedt_node);
104 : }
105 :
106 : static fib_entry_delegate_t*
107 4504 : fib_entry_delegate_from_fib_node (fib_node_t *node)
108 : {
109 4504 : ASSERT(FIB_NODE_TYPE_ENTRY_TRACK == node->fn_type);
110 4504 : return ((fib_entry_delegate_t *) (((char *) node) -
111 : STRUCT_OFFSET_OF (fib_entry_delegate_t,
112 : fd_track.fedt_node)));
113 : }
114 :
115 : static void
116 3872 : fib_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 3872 : fed = fib_entry_delegate_from_fib_node(node);
123 3872 : fei = fed->fd_entry_index;
124 3872 : 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 3872 : 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 3872 : fib_entry_child_remove(fei, sibling);
136 :
137 3872 : fib_table_entry_delete_index(fei, FIB_SOURCE_RR);
138 3872 : }
139 :
140 : static fib_node_back_walk_rc_t
141 632 : fib_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 632 : fed = fib_entry_delegate_from_fib_node(node);
147 :
148 : /*
149 : * propagate the walk to the delgate's children
150 : */
151 :
152 632 : fib_walk_sync(FIB_NODE_TYPE_ENTRY_TRACK,
153 : fib_entry_delegate_get_index(fed),
154 : ctx);
155 :
156 632 : return (FIB_NODE_BACK_WALK_CONTINUE);
157 : }
158 :
159 : static void
160 1 : fib_entry_track_show_memory (void)
161 : {
162 1 : }
163 :
164 : /*
165 : * The FIB entry tracker's graph node virtual function table
166 : */
167 : static 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 :
174 : void
175 575 : fib_entry_track_module_init (void)
176 : {
177 575 : fib_node_register_type(FIB_NODE_TYPE_ENTRY_TRACK, &fib_entry_track_vft);
178 575 : }
|