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 15179 : 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 15179 : ii = 0;
39 16267 : vec_foreach(delegate, adj->ia_delegates)
40 : {
41 2232 : if (delegate->ad_type == type)
42 : {
43 1144 : if (NULL != index)
44 404 : *index = ii;
45 :
46 1144 : return (delegate);
47 : }
48 : else
49 : {
50 1088 : ii++;
51 : }
52 : }
53 :
54 14035 : return (NULL);
55 : }
56 :
57 : adj_delegate_t *
58 14775 : adj_delegate_get (const ip_adjacency_t *adj,
59 : adj_delegate_type_t type)
60 : {
61 14775 : return (adj_delegate_find_i(adj, type, NULL));
62 : }
63 :
64 : void
65 404 : 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 404 : u32 index = ~0;
71 :
72 404 : adj = adj_get(ai);
73 404 : aed = adj_delegate_find_i(adj, type, &index);
74 :
75 404 : ASSERT(NULL != aed);
76 :
77 404 : vec_del1(adj->ia_delegates, index);
78 404 : }
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 783 : adj_delegate_init (ip_adjacency_t *adj,
91 : adj_delegate_type_t adt,
92 : index_t adi)
93 :
94 : {
95 783 : adj_delegate_t aed = {
96 783 : .ad_adj_index = adj_get_index(adj),
97 : .ad_type = adt,
98 : .ad_index = adi,
99 : };
100 :
101 783 : vec_add1(adj->ia_delegates, aed);
102 783 : vec_sort_with_function(adj->ia_delegates,
103 : adj_delegate_cmp_for_sort);
104 783 : }
105 :
106 : int
107 783 : 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 783 : delegate = adj_delegate_get(adj, adt);
114 :
115 783 : if (NULL == delegate)
116 : {
117 783 : adj_delegate_init(adj, adt, adi);
118 : }
119 : else
120 : {
121 0 : return (-1);
122 : }
123 :
124 783 : return (0);
125 : }
126 :
127 : void
128 28158 : adj_delegate_adj_modified (ip_adjacency_t *adj)
129 : {
130 : adj_delegate_t *aed;
131 :
132 28369 : 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 28158 : }
140 :
141 : void
142 15760 : adj_delegate_adj_deleted (ip_adjacency_t *adj)
143 : {
144 : adj_delegate_t *aed;
145 :
146 16178 : 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 15760 : vec_reset_length(adj->ia_delegates);
155 15760 : }
156 :
157 : void
158 47098 : adj_delegate_adj_created (ip_adjacency_t *adj)
159 : {
160 : adj_delegate_vft_t *vft;
161 :
162 282666 : vec_foreach(vft, ad_vfts)
163 : {
164 235568 : if (vft->adv_adj_created)
165 : {
166 94274 : vft->adv_adj_created(adj_get_index(adj));
167 : }
168 : }
169 47098 : }
170 :
171 : u8*
172 7 : adj_delegate_format (u8* s, ip_adjacency_t *adj)
173 : {
174 : adj_delegate_t *aed;
175 :
176 12 : vec_foreach(aed, adj->ia_delegates)
177 : {
178 5 : if (ad_vfts[aed->ad_type].adv_format)
179 : {
180 5 : s = format(s, "\n {");
181 5 : s = ad_vfts[aed->ad_type].adv_format(aed, s);
182 5 : 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 1150 : 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 1150 : if (vec_len(ad_vfts) > type)
206 1150 : ASSERT(NULL == ad_vfts[type].adv_adj_deleted);
207 :
208 1150 : vec_validate(ad_vfts, type);
209 1150 : ad_vfts[type] = *vft;
210 1150 : }
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 1727 : adj_delegate_register_new_type (const adj_delegate_vft_t *vft)
219 : {
220 : adj_delegate_type_t type;
221 :
222 1727 : type = ++ad_max_id;
223 :
224 1727 : vec_validate(ad_vfts, type);
225 1727 : ad_vfts[type] = *vft;
226 :
227 1727 : return (type);
228 : }
|