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