Adjacency Delegate updates
[vpp.git] / src / vnet / adj / adj_delegate.c
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 delegeate value
27  */
28 static adj_delegate_type_t ad_max_id = ADJ_DELEGATE_BFD;
29
30 static adj_delegate_t *
31 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     ii = 0;
39     vec_foreach(delegate, adj->ia_delegates)
40     {
41         if ((*delegate)->ad_type == type)
42         {
43             if (NULL != index)
44                 *index = ii;
45
46             return (*delegate);
47         }
48         else
49         {
50             ii++;
51         }
52     }
53
54     return (NULL);
55 }
56
57 adj_delegate_t *
58 adj_delegate_get (const ip_adjacency_t *adj,
59                   adj_delegate_type_t type)
60 {
61     return (adj_delegate_find_i(adj, type, NULL));
62 }
63
64 void
65 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     u32 index = ~0;
71
72     adj = adj_get(ai);
73     aed = adj_delegate_find_i(adj, type, &index);
74
75     ASSERT(NULL != aed);
76
77     vec_del1(adj->ia_delegates, index);
78 }
79
80 static int
81 adj_delegate_cmp_for_sort (void * v1,
82                            void * v2)
83 {
84     adj_delegate_t **delegate1 = v1, **delegate2 = v2;
85
86     return ((*delegate1)->ad_type - (*delegate2)->ad_type);
87 }
88
89 static void
90 adj_delegate_init (ip_adjacency_t *adj,
91                    adj_delegate_type_t adt,
92                    adj_delegate_t *aed)
93
94 {
95     aed->ad_adj_index = adj_get_index(adj);
96     aed->ad_type = adt;
97
98     vec_add1(adj->ia_delegates, aed);
99     vec_sort_with_function(adj->ia_delegates,
100                            adj_delegate_cmp_for_sort);
101 }
102
103 int
104 adj_delegate_add (ip_adjacency_t *adj,
105                   adj_delegate_type_t adt,
106                   adj_delegate_t *ad)
107 {
108     adj_delegate_t *delegate;
109
110     delegate = adj_delegate_get(adj, adt);
111
112     if (NULL == delegate)
113     {
114         adj_delegate_init(adj, adt, ad);
115     }
116     else
117     {
118         return (-1);
119     }
120
121     return (0);
122 }
123
124 void
125 adj_delegate_adj_deleted (ip_adjacency_t *adj)
126 {
127     adj_delegate_t **delegate;
128
129     vec_foreach(delegate, adj->ia_delegates)
130     {
131         if (ad_vfts[(*delegate)->ad_type].adv_adj_deleted)
132         {
133             ad_vfts[(*delegate)->ad_type].adv_adj_deleted(*delegate);
134         }
135     }
136
137     vec_reset_length(adj->ia_delegates);
138 }
139
140 u8*
141 adj_delegate_format (u8* s, ip_adjacency_t *adj)
142 {
143     adj_delegate_t **aed;
144
145     vec_foreach(aed, adj->ia_delegates)
146     {
147         if (ad_vfts[(*aed)->ad_type].adv_format)
148         {
149             s = format(s, "{");
150             s = ad_vfts[(*aed)->ad_type].adv_format(*aed, s);
151             s = format(s, "}");
152         }
153         else
154         {
155             s = format(s, "{unknown delegate}");
156         }
157     }
158
159     return (s);
160 }
161
162 /**
163  * adj_delegate_register_type
164  *
165  * Register the function table for a given type
166  */
167 void
168 adj_delegate_register_type (adj_delegate_type_t type,
169                             const adj_delegate_vft_t *vft)
170 {
171     /*
172      * assert that one only registration is made per-node type
173      */
174     if (vec_len(ad_vfts) > type)
175         ASSERT(NULL == ad_vfts[type].adv_adj_deleted);
176
177     vec_validate(ad_vfts, type);
178     ad_vfts[type] = *vft;
179 }
180
181 /**
182  * adj_delegate_register_new_type
183  *
184  * Register the function table for a new type
185  */
186 adj_delegate_type_t
187 adj_delegate_register_new_type (const adj_delegate_vft_t *vft)
188 {
189     adj_delegate_type_t type;
190
191     type = ++ad_max_id;
192
193     vec_validate(ad_vfts, type);
194     ad_vfts[type] = *vft;
195
196     return (type);
197 }