]>
Commit | Line | Data |
---|---|---|
b72ede27 FL |
1 | /* |
2 | * VRF functions. | |
3 | * Copyright (C) 2014 6WIND S.A. | |
4 | * | |
5 | * This file is part of GNU Zebra. | |
6 | * | |
7 | * GNU Zebra is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published | |
9 | * by the Free Software Foundation; either version 2, or (at your | |
10 | * option) any later version. | |
11 | * | |
12 | * GNU Zebra is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with GNU Zebra; see the file COPYING. If not, write to the | |
19 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 | * Boston, MA 02111-1307, USA. | |
21 | */ | |
22 | ||
23 | #include <zebra.h> | |
24 | ||
6a69b354 | 25 | #include "if.h" |
b72ede27 FL |
26 | #include "vrf.h" |
27 | #include "prefix.h" | |
28 | #include "table.h" | |
29 | #include "log.h" | |
30 | #include "memory.h" | |
19dc275e DS |
31 | #include "command.h" |
32 | ||
33 | /* | |
34 | * Turn on/off debug code | |
35 | * for vrf. | |
36 | */ | |
37 | int debug_vrf = 0; | |
b72ede27 | 38 | |
b72ede27 FL |
39 | /* Holding VRF hooks */ |
40 | struct vrf_master | |
41 | { | |
216b18ef DS |
42 | int (*vrf_new_hook) (vrf_id_t, const char *, void **); |
43 | int (*vrf_delete_hook) (vrf_id_t, const char *, void **); | |
44 | int (*vrf_enable_hook) (vrf_id_t, const char *, void **); | |
45 | int (*vrf_disable_hook) (vrf_id_t, const char *, void **); | |
b72ede27 FL |
46 | } vrf_master = {0,}; |
47 | ||
48 | /* VRF table */ | |
49 | struct route_table *vrf_table = NULL; | |
50 | ||
216b18ef DS |
51 | /* VRF is part of a list too to store it before its actually active */ |
52 | struct list *vrf_list; | |
53 | ||
e5bf3e1e | 54 | static int vrf_is_enabled (struct vrf *vrf); |
e5bf3e1e FL |
55 | static void vrf_disable (struct vrf *vrf); |
56 | ||
216b18ef DS |
57 | /* VRF list existance check by name. */ |
58 | struct vrf * | |
59 | vrf_list_lookup_by_name (const char *name) | |
60 | { | |
61 | struct listnode *node; | |
62 | struct vrf *vrfp; | |
63 | ||
64 | if (name) | |
65 | for (ALL_LIST_ELEMENTS_RO (vrf_list, node, vrfp)) | |
66 | { | |
67 | if (strcmp(name, vrfp->name) == 0) | |
68 | return vrfp; | |
69 | } | |
70 | return NULL; | |
71 | } | |
72 | ||
b72ede27 FL |
73 | /* Build the table key */ |
74 | static void | |
75 | vrf_build_key (vrf_id_t vrf_id, struct prefix *p) | |
76 | { | |
77 | p->family = AF_INET; | |
78 | p->prefixlen = IPV4_MAX_BITLEN; | |
79 | p->u.prefix4.s_addr = vrf_id; | |
80 | } | |
81 | ||
216b18ef DS |
82 | /* Get a VRF. If not found, create one. |
83 | * Arg: name | |
84 | * Description: Please note that this routine can be called with just the name | |
85 | and 0 vrf-id */ | |
86 | struct vrf * | |
87 | vrf_get (vrf_id_t vrf_id, const char *name) | |
b72ede27 FL |
88 | { |
89 | struct prefix p; | |
c88a8b75 | 90 | struct route_node *rn = NULL; |
216b18ef | 91 | struct vrf *vrf = NULL; |
0f48374b | 92 | size_t namelen = 0; |
b72ede27 | 93 | |
c88a8b75 DS |
94 | /* Only create a route node if the vrf was learned from the kernel */ |
95 | if (vrf_id != VRF_UNKNOWN) | |
b72ede27 | 96 | { |
c88a8b75 DS |
97 | vrf_build_key (vrf_id, &p); |
98 | rn = route_node_get (vrf_table, &p); | |
216b18ef | 99 | |
c88a8b75 | 100 | if (rn->info) |
216b18ef | 101 | { |
c88a8b75 DS |
102 | vrf = (struct vrf *)rn->info; |
103 | route_unlock_node (rn); /* get */ | |
104 | ||
105 | if (name) | |
106 | { | |
107 | strncpy (vrf->name, name, strlen(name)); | |
108 | vrf->name[strlen(name)] = '\0'; | |
109 | if (vrf_list_lookup_by_name (vrf->name) == NULL) | |
110 | listnode_add_sort (vrf_list, vrf); | |
111 | } | |
112 | if (debug_vrf) | |
113 | zlog_debug ("VRF(%u) %s Found %p", vrf_id, (name) ? name : "(NULL)", | |
114 | vrf); | |
216b18ef | 115 | } |
c88a8b75 DS |
116 | } |
117 | ||
118 | if (name && !vrf) | |
119 | vrf = vrf_list_lookup_by_name(name); | |
120 | ||
121 | if (vrf) | |
122 | { | |
19dc275e | 123 | if (debug_vrf) |
c88a8b75 DS |
124 | zlog_debug ("VRF(%u) %s lookup by name is successful", |
125 | vrf_id, (name) ? name : "(NULL)"); | |
b72ede27 | 126 | } |
216b18ef DS |
127 | else |
128 | { | |
129 | if (name) | |
c88a8b75 DS |
130 | { |
131 | namelen = strlen (name); | |
132 | if (namelen > VRF_NAMSIZ) | |
8087b296 | 133 | { |
c88a8b75 DS |
134 | zlog_err("Attempt to get/create VRF %u name %s - name too long", |
135 | vrf_id, name); | |
136 | return NULL; | |
8087b296 | 137 | } |
c88a8b75 | 138 | } |
8087b296 | 139 | |
c88a8b75 DS |
140 | vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf)); |
141 | if (debug_vrf) | |
142 | zlog_debug ("VRF(%u) %s is created.", | |
143 | vrf_id, (name) ? name : "(NULL)"); | |
144 | if (name) | |
145 | { | |
146 | strncpy (vrf->name, name, namelen); | |
147 | vrf->name[namelen] = '\0'; | |
148 | listnode_add_sort (vrf_list, vrf); | |
149 | } | |
150 | ||
151 | if ((vrf_id != VRF_UNKNOWN) && (rn != NULL)) | |
152 | { | |
153 | rn->info = vrf; | |
154 | vrf->node = rn; | |
155 | } | |
216b18ef | 156 | vrf->vrf_id = vrf_id; |
8736158a | 157 | |
216b18ef | 158 | /* Initialize interfaces. */ |
b2d7c082 | 159 | if_init (&vrf->iflist); |
216b18ef | 160 | } |
b72ede27 | 161 | |
c88a8b75 DS |
162 | if (vrf_master.vrf_new_hook && name) |
163 | { | |
164 | (*vrf_master.vrf_new_hook) (vrf_id, name, &vrf->info); | |
165 | ||
166 | if (vrf->info) | |
167 | zlog_info ("zvrf is created."); | |
168 | } | |
216b18ef | 169 | |
b72ede27 FL |
170 | return vrf; |
171 | } | |
172 | ||
173 | /* Delete a VRF. This is called in vrf_terminate(). */ | |
216b18ef | 174 | void |
b72ede27 FL |
175 | vrf_delete (struct vrf *vrf) |
176 | { | |
19dc275e DS |
177 | if (debug_vrf) |
178 | zlog_debug ("VRF %u is to be deleted.", vrf->vrf_id); | |
b72ede27 | 179 | |
e5bf3e1e FL |
180 | if (vrf_is_enabled (vrf)) |
181 | vrf_disable (vrf); | |
182 | ||
b72ede27 | 183 | if (vrf_master.vrf_delete_hook) |
216b18ef DS |
184 | (*vrf_master.vrf_delete_hook) (vrf->vrf_id, vrf->name, &vrf->info); |
185 | ||
79694123 | 186 | if (CHECK_FLAG (vrf->status, VRF_ACTIVE)) |
b2d7c082 | 187 | if_terminate (&vrf->iflist); |
b72ede27 | 188 | |
216b18ef DS |
189 | if (vrf->node) |
190 | { | |
191 | vrf->node->info = NULL; | |
192 | route_unlock_node(vrf->node); | |
193 | } | |
8736158a | 194 | |
216b18ef | 195 | listnode_delete (vrf_list, vrf); |
b72ede27 FL |
196 | |
197 | XFREE (MTYPE_VRF, vrf); | |
198 | } | |
199 | ||
200 | /* Look up a VRF by identifier. */ | |
216b18ef | 201 | struct vrf * |
b72ede27 FL |
202 | vrf_lookup (vrf_id_t vrf_id) |
203 | { | |
204 | struct prefix p; | |
205 | struct route_node *rn; | |
206 | struct vrf *vrf = NULL; | |
207 | ||
208 | vrf_build_key (vrf_id, &p); | |
209 | rn = route_node_lookup (vrf_table, &p); | |
210 | if (rn) | |
211 | { | |
212 | vrf = (struct vrf *)rn->info; | |
213 | route_unlock_node (rn); /* lookup */ | |
214 | } | |
215 | return vrf; | |
216 | } | |
217 | ||
e5bf3e1e FL |
218 | /* |
219 | * Check whether the VRF is enabled - that is, whether the VRF | |
220 | * is ready to allocate resources. Currently there's only one | |
221 | * type of resource: socket. | |
222 | */ | |
223 | static int | |
224 | vrf_is_enabled (struct vrf *vrf) | |
225 | { | |
79694123 | 226 | return vrf && CHECK_FLAG (vrf->status, VRF_ACTIVE); |
216b18ef DS |
227 | |
228 | /*Pending: figure out the real use of this routine.. it used to be.. | |
e5bf3e1e | 229 | return vrf && vrf->vrf_id == VRF_DEFAULT; |
216b18ef | 230 | */ |
e5bf3e1e FL |
231 | } |
232 | ||
233 | /* | |
234 | * Enable a VRF - that is, let the VRF be ready to use. | |
235 | * The VRF_ENABLE_HOOK callback will be called to inform | |
236 | * that they can allocate resources in this VRF. | |
237 | * | |
238 | * RETURN: 1 - enabled successfully; otherwise, 0. | |
239 | */ | |
216b18ef | 240 | int |
e5bf3e1e FL |
241 | vrf_enable (struct vrf *vrf) |
242 | { | |
19dc275e DS |
243 | if (debug_vrf) |
244 | zlog_debug ("VRF %u is enabled.", vrf->vrf_id); | |
e5bf3e1e | 245 | |
e2b1be64 DS |
246 | if (!CHECK_FLAG (vrf->status, VRF_ACTIVE)) |
247 | SET_FLAG (vrf->status, VRF_ACTIVE); | |
e5bf3e1e | 248 | |
e2b1be64 DS |
249 | if (vrf_master.vrf_enable_hook) |
250 | (*vrf_master.vrf_enable_hook) (vrf->vrf_id, vrf->name, &vrf->info); | |
e5bf3e1e | 251 | |
e2b1be64 | 252 | return 1; |
e5bf3e1e FL |
253 | } |
254 | ||
255 | /* | |
256 | * Disable a VRF - that is, let the VRF be unusable. | |
257 | * The VRF_DELETE_HOOK callback will be called to inform | |
258 | * that they must release the resources in the VRF. | |
259 | */ | |
260 | static void | |
261 | vrf_disable (struct vrf *vrf) | |
262 | { | |
e74f14fc | 263 | UNSET_FLAG (vrf->status, VRF_ACTIVE); |
e5bf3e1e FL |
264 | if (vrf_is_enabled (vrf)) |
265 | { | |
19dc275e DS |
266 | if (debug_vrf) |
267 | zlog_debug ("VRF %u is to be disabled.", vrf->vrf_id); | |
e5bf3e1e FL |
268 | |
269 | /* Till now, nothing to be done for the default VRF. */ | |
216b18ef | 270 | //Pending: see why this statement. |
e5bf3e1e FL |
271 | |
272 | if (vrf_master.vrf_disable_hook) | |
216b18ef | 273 | (*vrf_master.vrf_disable_hook) (vrf->vrf_id, vrf->name, &vrf->info); |
e5bf3e1e | 274 | } |
e74f14fc | 275 | |
e5bf3e1e FL |
276 | } |
277 | ||
278 | ||
b72ede27 FL |
279 | /* Add a VRF hook. Please add hooks before calling vrf_init(). */ |
280 | void | |
216b18ef | 281 | vrf_add_hook (int type, int (*func)(vrf_id_t, const char *, void **)) |
b72ede27 | 282 | { |
19dc275e DS |
283 | if (debug_vrf) |
284 | zlog_debug ("%s: Add Hook %d to function %p", __PRETTY_FUNCTION__, | |
285 | type, func); | |
286 | ||
b72ede27 FL |
287 | switch (type) { |
288 | case VRF_NEW_HOOK: | |
289 | vrf_master.vrf_new_hook = func; | |
290 | break; | |
291 | case VRF_DELETE_HOOK: | |
292 | vrf_master.vrf_delete_hook = func; | |
293 | break; | |
e5bf3e1e FL |
294 | case VRF_ENABLE_HOOK: |
295 | vrf_master.vrf_enable_hook = func; | |
296 | break; | |
297 | case VRF_DISABLE_HOOK: | |
298 | vrf_master.vrf_disable_hook = func; | |
299 | break; | |
b72ede27 FL |
300 | default: |
301 | break; | |
302 | } | |
303 | } | |
304 | ||
305 | /* Return the iterator of the first VRF. */ | |
306 | vrf_iter_t | |
307 | vrf_first (void) | |
308 | { | |
309 | struct route_node *rn; | |
310 | ||
311 | for (rn = route_top (vrf_table); rn; rn = route_next (rn)) | |
312 | if (rn->info) | |
313 | { | |
314 | route_unlock_node (rn); /* top/next */ | |
315 | return (vrf_iter_t)rn; | |
316 | } | |
317 | return VRF_ITER_INVALID; | |
318 | } | |
319 | ||
320 | /* Return the next VRF iterator to the given iterator. */ | |
321 | vrf_iter_t | |
322 | vrf_next (vrf_iter_t iter) | |
323 | { | |
324 | struct route_node *rn = NULL; | |
325 | ||
326 | /* Lock it first because route_next() will unlock it. */ | |
327 | if (iter != VRF_ITER_INVALID) | |
328 | rn = route_next (route_lock_node ((struct route_node *)iter)); | |
329 | ||
330 | for (; rn; rn = route_next (rn)) | |
331 | if (rn->info) | |
332 | { | |
333 | route_unlock_node (rn); /* next */ | |
334 | return (vrf_iter_t)rn; | |
335 | } | |
336 | return VRF_ITER_INVALID; | |
337 | } | |
338 | ||
339 | /* Return the VRF iterator of the given VRF ID. If it does not exist, | |
340 | * the iterator of the next existing VRF is returned. */ | |
341 | vrf_iter_t | |
342 | vrf_iterator (vrf_id_t vrf_id) | |
343 | { | |
344 | struct prefix p; | |
345 | struct route_node *rn; | |
346 | ||
347 | vrf_build_key (vrf_id, &p); | |
348 | rn = route_node_get (vrf_table, &p); | |
349 | if (rn->info) | |
350 | { | |
351 | /* OK, the VRF exists. */ | |
352 | route_unlock_node (rn); /* get */ | |
353 | return (vrf_iter_t)rn; | |
354 | } | |
355 | ||
356 | /* Find the next VRF. */ | |
357 | for (rn = route_next (rn); rn; rn = route_next (rn)) | |
358 | if (rn->info) | |
359 | { | |
360 | route_unlock_node (rn); /* next */ | |
361 | return (vrf_iter_t)rn; | |
362 | } | |
363 | ||
364 | return VRF_ITER_INVALID; | |
365 | } | |
366 | ||
367 | /* Obtain the VRF ID from the given VRF iterator. */ | |
368 | vrf_id_t | |
369 | vrf_iter2id (vrf_iter_t iter) | |
370 | { | |
371 | struct route_node *rn = (struct route_node *) iter; | |
372 | return (rn && rn->info) ? ((struct vrf *)rn->info)->vrf_id : VRF_DEFAULT; | |
373 | } | |
374 | ||
216b18ef DS |
375 | struct vrf * |
376 | vrf_iter2vrf (vrf_iter_t iter) | |
377 | { | |
378 | struct route_node *rn = (struct route_node *) iter; | |
379 | return (rn && rn->info) ? (struct vrf *)rn->info : NULL; | |
380 | } | |
381 | ||
b72ede27 FL |
382 | /* Obtain the data pointer from the given VRF iterator. */ |
383 | void * | |
384 | vrf_iter2info (vrf_iter_t iter) | |
385 | { | |
386 | struct route_node *rn = (struct route_node *) iter; | |
387 | return (rn && rn->info) ? ((struct vrf *)rn->info)->info : NULL; | |
388 | } | |
389 | ||
8736158a FL |
390 | /* Obtain the interface list from the given VRF iterator. */ |
391 | struct list * | |
392 | vrf_iter2iflist (vrf_iter_t iter) | |
393 | { | |
394 | struct route_node *rn = (struct route_node *) iter; | |
395 | return (rn && rn->info) ? ((struct vrf *)rn->info)->iflist : NULL; | |
396 | } | |
397 | ||
216b18ef DS |
398 | /* Look up a VRF by name. */ |
399 | struct vrf * | |
400 | vrf_lookup_by_name (const char *name) | |
401 | { | |
402 | struct vrf *vrf = NULL; | |
403 | vrf_iter_t iter; | |
404 | ||
405 | for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) | |
406 | { | |
407 | vrf = vrf_iter2vrf (iter); | |
408 | if (vrf && !strcmp(vrf->name, name)) | |
2e447c86 | 409 | return vrf; |
216b18ef DS |
410 | } |
411 | ||
2e447c86 | 412 | return NULL; |
216b18ef DS |
413 | } |
414 | ||
415 | vrf_id_t | |
416 | vrf_name_to_id (const char *name) | |
417 | { | |
418 | struct vrf *vrf; | |
419 | vrf_id_t vrf_id = VRF_DEFAULT; //Pending: need a way to return invalid id/ routine not used. | |
420 | ||
421 | vrf = vrf_lookup_by_name (name); | |
422 | if (vrf) | |
423 | vrf_id = vrf->vrf_id; | |
424 | ||
425 | return vrf_id; | |
426 | } | |
427 | ||
b72ede27 FL |
428 | /* Get the data pointer of the specified VRF. If not found, create one. */ |
429 | void * | |
430 | vrf_info_get (vrf_id_t vrf_id) | |
431 | { | |
216b18ef | 432 | struct vrf *vrf = vrf_get (vrf_id, NULL); |
b72ede27 FL |
433 | return vrf->info; |
434 | } | |
435 | ||
436 | /* Look up the data pointer of the specified VRF. */ | |
437 | void * | |
438 | vrf_info_lookup (vrf_id_t vrf_id) | |
439 | { | |
440 | struct vrf *vrf = vrf_lookup (vrf_id); | |
441 | return vrf ? vrf->info : NULL; | |
442 | } | |
443 | ||
8736158a FL |
444 | /* Look up the interface list in a VRF. */ |
445 | struct list * | |
446 | vrf_iflist (vrf_id_t vrf_id) | |
447 | { | |
448 | struct vrf * vrf = vrf_lookup (vrf_id); | |
449 | return vrf ? vrf->iflist : NULL; | |
450 | } | |
451 | ||
452 | /* Get the interface list of the specified VRF. Create one if not find. */ | |
453 | struct list * | |
454 | vrf_iflist_get (vrf_id_t vrf_id) | |
455 | { | |
216b18ef | 456 | struct vrf * vrf = vrf_get (vrf_id, NULL); |
8736158a FL |
457 | return vrf->iflist; |
458 | } | |
459 | ||
b33adb7c | 460 | /* Create the interface list for the specified VRF, if needed. */ |
461 | void | |
462 | vrf_iflist_create (vrf_id_t vrf_id) | |
463 | { | |
464 | struct vrf * vrf = vrf_lookup (vrf_id); | |
465 | if (vrf && !vrf->iflist) | |
b2d7c082 | 466 | if_init (&vrf->iflist); |
b33adb7c | 467 | } |
468 | ||
009b18fc | 469 | /* Free the interface list of the specified VRF. */ |
470 | void | |
471 | vrf_iflist_terminate (vrf_id_t vrf_id) | |
472 | { | |
473 | struct vrf * vrf = vrf_lookup (vrf_id); | |
474 | if (vrf && vrf->iflist) | |
b2d7c082 | 475 | if_terminate (&vrf->iflist); |
009b18fc | 476 | } |
477 | ||
7076bb2f FL |
478 | /* |
479 | * VRF bit-map | |
480 | */ | |
481 | ||
482 | #define VRF_BITMAP_NUM_OF_GROUPS 8 | |
483 | #define VRF_BITMAP_NUM_OF_BITS_IN_GROUP \ | |
484 | (UINT16_MAX / VRF_BITMAP_NUM_OF_GROUPS) | |
485 | #define VRF_BITMAP_NUM_OF_BYTES_IN_GROUP \ | |
486 | (VRF_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */ | |
487 | ||
488 | #define VRF_BITMAP_GROUP(_id) \ | |
489 | ((_id) / VRF_BITMAP_NUM_OF_BITS_IN_GROUP) | |
490 | #define VRF_BITMAP_BIT_OFFSET(_id) \ | |
491 | ((_id) % VRF_BITMAP_NUM_OF_BITS_IN_GROUP) | |
492 | ||
493 | #define VRF_BITMAP_INDEX_IN_GROUP(_bit_offset) \ | |
494 | ((_bit_offset) / CHAR_BIT) | |
495 | #define VRF_BITMAP_FLAG(_bit_offset) \ | |
496 | (((u_char)1) << ((_bit_offset) % CHAR_BIT)) | |
497 | ||
498 | struct vrf_bitmap | |
499 | { | |
500 | u_char *groups[VRF_BITMAP_NUM_OF_GROUPS]; | |
501 | }; | |
502 | ||
503 | vrf_bitmap_t | |
504 | vrf_bitmap_init (void) | |
505 | { | |
506 | return (vrf_bitmap_t) XCALLOC (MTYPE_VRF_BITMAP, sizeof (struct vrf_bitmap)); | |
507 | } | |
508 | ||
509 | void | |
510 | vrf_bitmap_free (vrf_bitmap_t bmap) | |
511 | { | |
512 | struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap; | |
513 | int i; | |
514 | ||
515 | if (bmap == VRF_BITMAP_NULL) | |
516 | return; | |
517 | ||
518 | for (i = 0; i < VRF_BITMAP_NUM_OF_GROUPS; i++) | |
519 | if (bm->groups[i]) | |
520 | XFREE (MTYPE_VRF_BITMAP, bm->groups[i]); | |
521 | ||
522 | XFREE (MTYPE_VRF_BITMAP, bm); | |
523 | } | |
524 | ||
525 | void | |
526 | vrf_bitmap_set (vrf_bitmap_t bmap, vrf_id_t vrf_id) | |
527 | { | |
528 | struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap; | |
529 | u_char group = VRF_BITMAP_GROUP (vrf_id); | |
530 | u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id); | |
531 | ||
532 | if (bmap == VRF_BITMAP_NULL) | |
533 | return; | |
534 | ||
535 | if (bm->groups[group] == NULL) | |
536 | bm->groups[group] = XCALLOC (MTYPE_VRF_BITMAP, | |
537 | VRF_BITMAP_NUM_OF_BYTES_IN_GROUP); | |
538 | ||
539 | SET_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)], | |
540 | VRF_BITMAP_FLAG (offset)); | |
541 | } | |
542 | ||
543 | void | |
544 | vrf_bitmap_unset (vrf_bitmap_t bmap, vrf_id_t vrf_id) | |
545 | { | |
546 | struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap; | |
547 | u_char group = VRF_BITMAP_GROUP (vrf_id); | |
548 | u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id); | |
549 | ||
550 | if (bmap == VRF_BITMAP_NULL || bm->groups[group] == NULL) | |
551 | return; | |
552 | ||
553 | UNSET_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)], | |
554 | VRF_BITMAP_FLAG (offset)); | |
555 | } | |
556 | ||
557 | int | |
558 | vrf_bitmap_check (vrf_bitmap_t bmap, vrf_id_t vrf_id) | |
559 | { | |
560 | struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap; | |
561 | u_char group = VRF_BITMAP_GROUP (vrf_id); | |
562 | u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id); | |
563 | ||
564 | if (bmap == VRF_BITMAP_NULL || bm->groups[group] == NULL) | |
565 | return 0; | |
566 | ||
567 | return CHECK_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)], | |
568 | VRF_BITMAP_FLAG (offset)) ? 1 : 0; | |
569 | } | |
570 | ||
216b18ef DS |
571 | /* Compare interface names, returning an integer greater than, equal to, or |
572 | * less than 0, (following the strcmp convention), according to the | |
573 | * relationship between vrfp1 and vrfp2. Interface names consist of an | |
574 | * alphabetic prefix and a numeric suffix. The primary sort key is | |
575 | * lexicographic by name, and then numeric by number. No number sorts | |
576 | * before all numbers. Examples: de0 < de1, de100 < fxp0 < xl0, devpty < | |
577 | * devpty0, de0 < del0 | |
578 | */ | |
974fc9d2 | 579 | static int |
216b18ef DS |
580 | vrf_cmp_func (struct vrf *vrfp1, struct vrf *vrfp2) |
581 | { | |
974fc9d2 | 582 | return if_cmp_name_func (vrfp1->name, vrfp2->name); |
216b18ef DS |
583 | } |
584 | ||
b72ede27 FL |
585 | /* Initialize VRF module. */ |
586 | void | |
587 | vrf_init (void) | |
588 | { | |
589 | struct vrf *default_vrf; | |
590 | ||
19dc275e DS |
591 | if (debug_vrf) |
592 | zlog_debug ("%s: Initializing VRF subsystem", __PRETTY_FUNCTION__); | |
593 | ||
216b18ef DS |
594 | vrf_list = list_new (); |
595 | vrf_list->cmp = (int (*)(void *, void *))vrf_cmp_func; | |
596 | ||
b72ede27 FL |
597 | /* Allocate VRF table. */ |
598 | vrf_table = route_table_init (); | |
599 | ||
600 | /* The default VRF always exists. */ | |
216b18ef | 601 | default_vrf = vrf_get (VRF_DEFAULT, VRF_DEFAULT_NAME); |
b72ede27 FL |
602 | if (!default_vrf) |
603 | { | |
604 | zlog_err ("vrf_init: failed to create the default VRF!"); | |
605 | exit (1); | |
606 | } | |
607 | ||
e5bf3e1e FL |
608 | /* Enable the default VRF. */ |
609 | if (!vrf_enable (default_vrf)) | |
610 | { | |
611 | zlog_err ("vrf_init: failed to enable the default VRF!"); | |
612 | exit (1); | |
613 | } | |
b72ede27 FL |
614 | } |
615 | ||
616 | /* Terminate VRF module. */ | |
617 | void | |
618 | vrf_terminate (void) | |
619 | { | |
620 | struct route_node *rn; | |
621 | struct vrf *vrf; | |
622 | ||
19dc275e DS |
623 | if (debug_vrf) |
624 | zlog_debug ("%s: Shutting down vrf subsystem", __PRETTY_FUNCTION__); | |
625 | ||
b72ede27 FL |
626 | for (rn = route_top (vrf_table); rn; rn = route_next (rn)) |
627 | if ((vrf = rn->info) != NULL) | |
628 | vrf_delete (vrf); | |
629 | ||
630 | route_table_finish (vrf_table); | |
631 | vrf_table = NULL; | |
632 | } | |
633 | ||
e5bf3e1e FL |
634 | /* Create a socket for the VRF. */ |
635 | int | |
636 | vrf_socket (int domain, int type, int protocol, vrf_id_t vrf_id) | |
637 | { | |
638 | int ret = -1; | |
639 | ||
19dc275e | 640 | ret = socket (domain, type, protocol); |
e5bf3e1e FL |
641 | |
642 | return ret; | |
643 | } | |
644 | ||
19dc275e DS |
645 | /* |
646 | * Debug CLI for vrf's | |
647 | */ | |
648 | DEFUN (vrf_debug, | |
649 | vrf_debug_cmd, | |
650 | "debug vrf", | |
651 | DEBUG_STR | |
652 | "VRF Debugging\n") | |
653 | { | |
654 | debug_vrf = 1; | |
655 | ||
656 | return CMD_SUCCESS; | |
657 | } | |
658 | ||
659 | DEFUN (no_vrf_debug, | |
660 | no_vrf_debug_cmd, | |
661 | "no debug vrf", | |
662 | NO_STR | |
663 | DEBUG_STR | |
664 | "VRF Debugging\n") | |
665 | { | |
666 | debug_vrf = 0; | |
667 | ||
668 | return CMD_SUCCESS; | |
669 | } | |
670 | ||
671 | static int | |
672 | vrf_write_host (struct vty *vty) | |
673 | { | |
674 | if (debug_vrf) | |
675 | vty_out (vty, "debug vrf%s", VTY_NEWLINE); | |
676 | ||
677 | return 1; | |
678 | } | |
679 | ||
680 | static struct cmd_node vrf_debug_node = | |
681 | { | |
682 | VRF_DEBUG_NODE, | |
683 | "", | |
684 | 1 | |
685 | }; | |
686 | ||
687 | void | |
688 | vrf_install_commands (void) | |
689 | { | |
690 | install_node (&vrf_debug_node, vrf_write_host); | |
691 | ||
692 | install_element (CONFIG_NODE, &vrf_debug_cmd); | |
693 | install_element (ENABLE_NODE, &vrf_debug_cmd); | |
694 | install_element (CONFIG_NODE, &no_vrf_debug_cmd); | |
695 | install_element (ENABLE_NODE, &no_vrf_debug_cmd); | |
696 | } |