Line data Source code
1 : /*
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/adj/adj_delegate.h>
17 : #include <vnet/adj/adj.h>
18 : #include <vnet/adj/adj_internal.h>
19 :
20 : /*
21 : * The per-type vector of virtual function tables
22 : */
23 : static adj_delegate_vft_t *ad_vfts;
24 :
25 : /**
26 : * The value of the last dynamically allocated delegate value
27 : */
28 : static adj_delegate_type_t ad_max_id = ADJ_DELEGATE_LAST;
29 :
30 : static adj_delegate_t *
31 15252 : adj_delegate_find_i (const ip_adjacency_t *adj,
32 : adj_delegate_type_t type,
33 : u32 *index)
34 : {
35 : adj_delegate_t *delegate;
36 : int ii;
37 :
38 15252 : ii = 0;
39 16340 : vec_foreach(delegate, adj->ia_delegates)
40 : {
41 2397 : if (delegate->ad_type == type)
42 : {
43 1309 : if (NULL != index)
44 431 : *index = ii;
45 :
46 1309 : return (delegate);
47 : }
48 : else
49 : {
50 1088 : ii++;
51 : }
52 : }
53 :
54 13943 : return (NULL);
55 : }
56 :
57 : adj_delegate_t *
58 14821 : adj_delegate_get (const ip_adjacency_t *adj,
59 : adj_delegate_type_t type)
60 : {
61 14821 : return (adj_delegate_find_i(adj, type, NULL));
62 : }
63 :
64 : void
65 431 : adj_delegate_remove (adj_index_t ai,
66 : adj_delegate_type_t type)
67 : {
68 : ip_adjacency_t *adj;
69 : adj_delegate_t *aed;
70 431 : u32 index = ~0;
71 :
72 431 : adj = adj_get(ai);
73 431 : aed = adj_delegate_find_i(adj, type, &index);
74 :
75 431 : ASSERT(NULL != aed);
76 :
77 431 : vec_del1(adj->ia_delegates, index);
78 431 : }
79 :
80 : static int
81 301 : adj_delegate_cmp_for_sort (void * v1,
82 : void * v2)
83 : {
84 301 : adj_delegate_t *aed1 = v1, *aed2 = v2;
85 :
86 301 : return (aed1->ad_type - aed2->ad_type);
87 : }
88 :
89 : static void
90 810 : adj_delegate_init (ip_adjacency_t *adj,
91 : adj_delegate_type_t adt,
92 : index_t adi)
93 :
94 : {
95 810 : adj_delegate_t aed = {
96 810 : .ad_adj_index = adj_get_index(adj),
97 : .ad_type = adt,
98 : .ad_index = adi,
99 : };
100 :
101 810 : vec_add1(adj->ia_delegates, aed);
102 810 : vec_sort_with_function(adj->ia_delegates,
103 : adj_delegate_cmp_for_sort);
104 810 : }
105 :
106 : int
107 810 : adj_delegate_add (ip_adjacency_t *adj,
108 : adj_delegate_type_t adt,
109 : index_t adi)
110 : {
111 : adj_delegate_t *delegate;
112 :
113 810 : delegate = adj_delegate_get(adj, adt);
114 :
115 810 : if (NULL == delegate)
116 : {
117 810 : adj_delegate_init(adj, adt, adi);
118 : }
119 : else
120 : {
121 0 : return (-1);
122 : }
123 :
124 810 : return (0);
125 : }
126 :
127 : void
128 27662 : adj_delegate_adj_modified (ip_adjacency_t *adj)
129 : {
130 : adj_delegate_t *aed;
131 :
132 27873 : vec_foreach(aed, adj->ia_delegates)
133 : {
134 211 : if (ad_vfts[aed->ad_type].adv_adj_modified)
135 : {
136 81 : ad_vfts[aed->ad_type].adv_adj_modified(aed);
137 : }
138 : }
139 27662 : }
140 :
141 : void
142 16972 : adj_delegate_adj_deleted (ip_adjacency_t *adj)
143 : {
144 : adj_delegate_t *aed;
145 :
146 17390 : vec_foreach(aed, adj->ia_delegates)
147 : {
148 418 : if (ad_vfts[aed->ad_type].adv_adj_deleted)
149 : {
150 418 : ad_vfts[aed->ad_type].adv_adj_deleted(aed);
151 : }
152 : }
153 :
154 16972 : vec_reset_length(adj->ia_delegates);
155 16972 : }
156 :
157 : void
158 46303 : adj_delegate_adj_created (ip_adjacency_t *adj)
159 : {
160 : adj_delegate_vft_t *vft;
161 :
162 277896 : vec_foreach(vft, ad_vfts)
163 : {
164 231593 : if (vft->adv_adj_created)
165 : {
166 92684 : vft->adv_adj_created(adj_get_index(adj));
167 : }
168 : }
169 46303 : }
170 :
171 : u8*
172 7 : adj_delegate_format (u8* s, ip_adjacency_t *adj)
173 : {
174 : adj_delegate_t *aed;
175 :
176 11 : vec_foreach(aed, adj->ia_delegates)
177 : {
178 4 : if (ad_vfts[aed->ad_type].adv_format)
179 : {
180 4 : s = format(s, "\n {");
181 4 : s = ad_vfts[aed->ad_type].adv_format(aed, s);
182 4 : s = format(s, "}");
183 : }
184 : else
185 : {
186 0 : s = format(s, "\n {unknown delegate}");
187 : }
188 : }
189 :
190 7 : return (s);
191 : }
192 :
193 : /**
194 : * adj_delegate_register_type
195 : *
196 : * Register the function table for a given type
197 : */
198 : void
199 1118 : adj_delegate_register_type (adj_delegate_type_t type,
200 : const adj_delegate_vft_t *vft)
201 : {
202 : /*
203 : * assert that one only registration is made per-node type
204 : */
205 1118 : if (vec_len(ad_vfts) > type)
206 1118 : ASSERT(NULL == ad_vfts[type].adv_adj_deleted);
207 :
208 1118 : vec_validate(ad_vfts, type);
209 1118 : ad_vfts[type] = *vft;
210 1118 : }
211 :
212 : /**
213 : * adj_delegate_register_new_type
214 : *
215 : * Register the function table for a new type
216 : */
217 : adj_delegate_type_t
218 1679 : adj_delegate_register_new_type (const adj_delegate_vft_t *vft)
219 : {
220 : adj_delegate_type_t type;
221 :
222 1679 : type = ++ad_max_id;
223 :
224 1679 : vec_validate(ad_vfts, type);
225 1679 : ad_vfts[type] = *vft;
226 :
227 1679 : return (type);
228 : }
|