Adj: VFTs for adjacency sub-blocks
[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 static adj_delegate_t *
26 adj_delegate_find_i (const ip_adjacency_t *adj,
27                      adj_delegate_type_t type,
28                      u32 *index)
29 {
30     adj_delegate_t *delegate;
31     int ii;
32
33     ii = 0;
34     vec_foreach(delegate, adj->ia_delegates)
35     {
36         if (delegate->ad_type == type)
37         {
38             if (NULL != index)
39                 *index = ii;
40
41             return (delegate);
42         }
43         else
44         {
45             ii++;
46         }
47     }
48
49     return (NULL);
50 }
51
52 adj_delegate_t *
53 adj_delegate_get (const ip_adjacency_t *adj,
54                   adj_delegate_type_t type)
55 {
56     return (adj_delegate_find_i(adj, type, NULL));
57 }
58
59 void
60 adj_delegate_remove (ip_adjacency_t *adj,
61                      adj_delegate_type_t type)
62 {
63     adj_delegate_t *aed;
64     u32 index = ~0;
65
66     aed = adj_delegate_find_i(adj, type, &index);
67
68     ASSERT(NULL != aed);
69
70     vec_del1(adj->ia_delegates, index);
71 }
72
73 static int
74 adj_delegate_cmp_for_sort (void * v1,
75                            void * v2)
76 {
77     adj_delegate_t *delegate1 = v1, *delegate2 = v2;
78
79     return (delegate1->ad_type - delegate2->ad_type);
80 }
81
82 static void
83 adj_delegate_init (ip_adjacency_t *adj,
84                    adj_delegate_type_t type)
85
86 {
87     adj_delegate_t delegate = {
88         .ad_adj_index = adj_get_index(adj),
89         .ad_type = type,
90     };
91
92     vec_add1(adj->ia_delegates, delegate);
93     vec_sort_with_function(adj->ia_delegates,
94                            adj_delegate_cmp_for_sort);
95 }
96
97 adj_delegate_t *
98 adj_delegate_find_or_add (ip_adjacency_t *adj,
99                           adj_delegate_type_t adt)
100 {
101     adj_delegate_t *delegate;
102
103     delegate = adj_delegate_get(adj, adt);
104
105     if (NULL == delegate)
106     {
107         adj_delegate_init(adj, adt);
108     }
109
110     return (adj_delegate_get(adj, adt));
111 }
112
113 void adj_delegate_vft_lock_gone (ip_adjacency_t *adj)
114 {
115     adj_delegate_t *delegate;
116     vec_foreach(delegate, adj->ia_delegates) {
117       if (ad_vfts[delegate->ad_type].adv_last_lock)
118         ad_vfts[delegate->ad_type].adv_last_lock(adj, delegate);
119     }
120 }
121
122 u8 *
123 format_adj_delegate (u8 * s, va_list * args)
124 {
125     adj_delegate_t *aed;
126
127     aed = va_arg (*args, adj_delegate_t *);
128     if (ad_vfts[aed->ad_type].adv_format)
129       return ad_vfts[aed->ad_type].adv_format(aed, s);
130     return format(s, "unknown delegate");
131 }
132
133 /**
134  * adj_delegate_register_type
135  *
136  * Register the function table for a given type
137  */
138
139 void
140 adj_delegate_register_type (adj_delegate_type_t type,
141                             const adj_delegate_vft_t *vft)
142 {
143   /*
144    * assert that one only registration is made per-node type
145    */
146   if (vec_len(ad_vfts) > type)
147     ASSERT(NULL == ad_vfts[type].adv_last_lock);
148
149   vec_validate(ad_vfts, type);
150   ad_vfts[type] = *vft;
151 }