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 <lisp/lisp-gpe/lisp_gpe_tenant.h>
17 :
18 : /**
19 : * The pool of all tenants
20 : */
21 : static lisp_gpe_tenant_t *lisp_gpe_tenant_pool;
22 :
23 : /**
24 : * The hash table of all tenants: key:{VNI}.
25 : */
26 : uword *lisp_gpe_tenant_db;
27 :
28 : static lisp_gpe_tenant_t *
29 4 : lisp_gpe_tenant_find (u32 vni)
30 : {
31 : uword *p;
32 :
33 4 : p = hash_get (lisp_gpe_tenant_db, vni);
34 :
35 4 : if (NULL == p)
36 1 : return (NULL);
37 :
38 3 : return (pool_elt_at_index (lisp_gpe_tenant_pool, p[0]));
39 : }
40 :
41 : static lisp_gpe_tenant_t *
42 2 : lisp_gpe_tenant_find_or_create_i (u32 vni)
43 : {
44 : lisp_gpe_tenant_t *lt;
45 :
46 2 : lt = lisp_gpe_tenant_find (vni);
47 :
48 2 : if (NULL == lt)
49 : {
50 1 : pool_get (lisp_gpe_tenant_pool, lt);
51 1 : clib_memset (lt, 0, sizeof (*lt));
52 :
53 1 : lt->lt_vni = vni;
54 1 : lt->lt_table_id = ~0;
55 1 : lt->lt_bd_id = ~0;
56 :
57 1 : hash_set (lisp_gpe_tenant_db, vni, lt - lisp_gpe_tenant_pool);
58 : }
59 :
60 2 : return (lt);
61 : }
62 :
63 : /**
64 : * @brief Find or create a tenant for the given VNI
65 : */
66 : u32
67 1 : lisp_gpe_tenant_find_or_create (u32 vni)
68 : {
69 : lisp_gpe_tenant_t *lt;
70 :
71 1 : lt = lisp_gpe_tenant_find (vni);
72 :
73 1 : if (NULL == lt)
74 : {
75 0 : lt = lisp_gpe_tenant_find_or_create_i (vni);
76 : }
77 :
78 1 : return (lt - lisp_gpe_tenant_pool);
79 : }
80 :
81 : /**
82 : * @brief If there are no more locks/users of te tenant, then delete it
83 : */
84 : static void
85 1 : lisp_gpe_tenant_delete_if_empty (lisp_gpe_tenant_t * lt)
86 : {
87 : int i;
88 :
89 2 : for (i = 0; i < LISP_GPE_TENANT_LOCK_NUM; i++)
90 : {
91 2 : if (lt->lt_locks[i])
92 1 : return;
93 : }
94 :
95 0 : hash_unset (lisp_gpe_tenant_db, lt->lt_vni);
96 0 : pool_put (lisp_gpe_tenant_pool, lt);
97 : }
98 :
99 : /**
100 : * @brief Add/create and lock a new or find and lock the existing L3
101 : * interface for the tenant
102 : *
103 : * @paran vni The tenant's VNI
104 : * @param table_id the Tenant's L3 table ID.
105 : * @param with_default_route Install default route for the interface
106 : *
107 : * @return the SW IF index of the L3 interface
108 : */
109 : u32
110 2 : lisp_gpe_tenant_l3_iface_add_or_lock (u32 vni, u32 table_id,
111 : u8 with_default_route)
112 : {
113 : lisp_gpe_tenant_t *lt;
114 :
115 2 : lt = lisp_gpe_tenant_find_or_create_i (vni);
116 :
117 2 : if (~0 == lt->lt_table_id)
118 1 : lt->lt_table_id = table_id;
119 :
120 2 : ASSERT (lt->lt_table_id == table_id);
121 :
122 2 : if (0 == lt->lt_locks[LISP_GPE_TENANT_LOCK_L3_IFACE])
123 : {
124 : /* create the l3 interface since there are currently no users of it */
125 1 : lt->lt_l3_sw_if_index =
126 1 : lisp_gpe_add_l3_iface (&lisp_gpe_main, vni, table_id,
127 : with_default_route);
128 : }
129 :
130 2 : lt->lt_locks[LISP_GPE_TENANT_LOCK_L3_IFACE]++;
131 :
132 2 : return (lt->lt_l3_sw_if_index);
133 : }
134 :
135 : /**
136 : * @brief Release the lock held on the tenant's L3 interface
137 : */
138 : void
139 1 : lisp_gpe_tenant_l3_iface_unlock (u32 vni)
140 : {
141 : lisp_gpe_tenant_t *lt;
142 :
143 1 : lt = lisp_gpe_tenant_find (vni);
144 :
145 1 : if (NULL == lt)
146 : {
147 0 : clib_warning ("No tenant for VNI %d", vni);
148 0 : return;
149 : }
150 :
151 1 : if (0 == lt->lt_locks[LISP_GPE_TENANT_LOCK_L3_IFACE])
152 : {
153 0 : clib_warning ("No L3 interface for tenant VNI %d", vni);
154 0 : return;
155 : }
156 :
157 1 : lt->lt_locks[LISP_GPE_TENANT_LOCK_L3_IFACE]--;
158 :
159 1 : if (0 == lt->lt_locks[LISP_GPE_TENANT_LOCK_L3_IFACE])
160 : {
161 : /* the last user has gone, so delete the l3 interface */
162 0 : lisp_gpe_del_l3_iface (&lisp_gpe_main, vni, lt->lt_table_id);
163 : }
164 :
165 : /*
166 : * If there are no more locks on any tenant managed resource, then
167 : * this tenant is toast.
168 : */
169 1 : lisp_gpe_tenant_delete_if_empty (lt);
170 : }
171 :
172 : /**
173 : * @brief Add/create and lock a new or find and lock the existing L2
174 : * interface for the tenant
175 : *
176 : * @paran vni The tenant's VNI
177 : * @param table_id the Tenant's L2 Bridge Domain ID.
178 : *
179 : * @return the SW IF index of the L2 interface
180 : */
181 : u32
182 0 : lisp_gpe_tenant_l2_iface_add_or_lock (u32 vni, u32 bd_id)
183 : {
184 : lisp_gpe_tenant_t *lt;
185 :
186 0 : lt = lisp_gpe_tenant_find_or_create_i (vni);
187 :
188 0 : if (NULL == lt)
189 : {
190 0 : clib_warning ("No tenant for VNI %d", vni);
191 0 : return ~0;
192 : }
193 :
194 0 : if (~0 == lt->lt_bd_id)
195 0 : lt->lt_bd_id = bd_id;
196 :
197 0 : ASSERT (lt->lt_bd_id == bd_id);
198 :
199 0 : if (0 == lt->lt_locks[LISP_GPE_TENANT_LOCK_L2_IFACE])
200 : {
201 : /* create the l2 interface since there are currently no users of it */
202 0 : lt->lt_l2_sw_if_index =
203 0 : lisp_gpe_add_l2_iface (&lisp_gpe_main, vni, bd_id);
204 : }
205 :
206 0 : lt->lt_locks[LISP_GPE_TENANT_LOCK_L2_IFACE]++;
207 :
208 0 : return (lt->lt_l2_sw_if_index);
209 : }
210 :
211 : /**
212 : * @brief Release the lock held on the tenant's L3 interface
213 : */
214 : void
215 0 : lisp_gpe_tenant_l2_iface_unlock (u32 vni)
216 : {
217 : lisp_gpe_tenant_t *lt;
218 :
219 0 : lt = lisp_gpe_tenant_find (vni);
220 :
221 0 : if (NULL == lt)
222 : {
223 0 : clib_warning ("No tenant for VNI %d", vni);
224 0 : return;
225 : }
226 :
227 0 : if (0 == lt->lt_locks[LISP_GPE_TENANT_LOCK_L2_IFACE])
228 : {
229 0 : clib_warning ("No L2 interface for tenant VNI %d", vni);
230 0 : return;
231 : }
232 :
233 0 : lt->lt_locks[LISP_GPE_TENANT_LOCK_L2_IFACE]--;
234 :
235 0 : if (0 == lt->lt_locks[LISP_GPE_TENANT_LOCK_L2_IFACE])
236 : {
237 : /* the last user has gone, so delete the l2 interface */
238 0 : lisp_gpe_del_l2_iface (&lisp_gpe_main, vni, lt->lt_bd_id);
239 : }
240 :
241 : /*
242 : * If there are no more locks on any tenant managed resource, then
243 : * this tenant is toast.
244 : */
245 0 : lisp_gpe_tenant_delete_if_empty (lt);
246 : }
247 :
248 : /**
249 : * @brief get a const pointer to the tenant object
250 : */
251 : const lisp_gpe_tenant_t *
252 0 : lisp_gpe_tenant_get (u32 index)
253 : {
254 0 : return (pool_elt_at_index (lisp_gpe_tenant_pool, index));
255 : }
256 :
257 : /**
258 : * @brief Flush/delete ALL the tenants
259 : */
260 : void
261 0 : lisp_gpe_tenant_flush (void)
262 : {
263 : lisp_gpe_tenant_t *lt;
264 :
265 : /* *INDENT-OFF* */
266 0 : pool_foreach (lt, lisp_gpe_tenant_pool)
267 : {
268 0 : lisp_gpe_tenant_l2_iface_unlock(lt->lt_vni);
269 0 : lisp_gpe_tenant_l3_iface_unlock(lt->lt_vni);
270 : }
271 : /* *INDENT-ON* */
272 0 : }
273 :
274 : /**
275 : * @brief Show/display one tenant
276 : */
277 : static u8 *
278 0 : format_lisp_gpe_tenant (u8 * s, va_list * ap)
279 : {
280 0 : const lisp_gpe_tenant_t *lt = va_arg (*ap, lisp_gpe_tenant_t *);
281 :
282 0 : s = format (s, "VNI:%d ", lt->lt_vni);
283 :
284 0 : if (lt->lt_table_id != ~0)
285 : {
286 0 : s = format (s, "VRF:%d ", lt->lt_table_id);
287 0 : s = format (s, "L3-SW-IF:%d ", lt->lt_l3_sw_if_index);
288 : }
289 :
290 0 : if (lt->lt_bd_id != ~0)
291 : {
292 0 : s = format (s, "BD-ID:%d ", lt->lt_bd_id);
293 0 : s = format (s, "L2-SW-IF:%d ", lt->lt_l2_sw_if_index);
294 : }
295 :
296 0 : return (s);
297 : }
298 :
299 : /**
300 : * @brief CLI command to show LISP-GPE tenant.
301 : */
302 : static clib_error_t *
303 0 : lisp_gpe_tenant_show (vlib_main_t * vm,
304 : unformat_input_t * input, vlib_cli_command_t * cmd)
305 : {
306 : lisp_gpe_tenant_t *lt;
307 :
308 : /* *INDENT-OFF* */
309 0 : pool_foreach (lt, lisp_gpe_tenant_pool)
310 : {
311 0 : vlib_cli_output (vm, "%U", format_lisp_gpe_tenant, lt);
312 : }
313 : /* *INDENT-ON* */
314 :
315 0 : return 0;
316 : }
317 :
318 : /* *INDENT-OFF* */
319 116069 : VLIB_CLI_COMMAND (lisp_gpe_tenant_command) = {
320 : .path = "show gpe tenant",
321 : .short_help = "show gpe tenant",
322 : .function = lisp_gpe_tenant_show,
323 : };
324 : /* *INDENT-ON* */
325 :
326 :
327 : /*
328 : * fd.io coding-style-patch-verification: ON
329 : *
330 : * Local Variables:
331 : * eval: (c-set-style "gnu")
332 : * End:
333 : */
|