]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_vrf.c
lib: convert vrf code to use red-black trees as well
[mirror_frr.git] / zebra / zebra_vrf.c
1 /*
2 * Copyright (C) 2016 CumulusNetworks
3 * Donald Sharp
4 *
5 * This file is part of Quagga
6 *
7 * Quagga is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * Quagga 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 Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22 #include <zebra.h>
23
24 #include "log.h"
25 #include "linklist.h"
26 #include "command.h"
27 #include "memory.h"
28
29 #include "zebra/debug.h"
30 #include "zebra/zserv.h"
31 #include "zebra/rib.h"
32 #include "zebra/zebra_vrf.h"
33 #include "zebra/router-id.h"
34 #include "zebra/zebra_memory.h"
35 #include "zebra/zebra_static.h"
36 #include "zebra/zebra_mpls.h"
37
38 extern struct zebra_t zebrad;
39
40 /* VRF information update. */
41 static void
42 zebra_vrf_add_update (struct zebra_vrf *zvrf)
43 {
44 struct listnode *node, *nnode;
45 struct zserv *client;
46
47 if (IS_ZEBRA_DEBUG_EVENT)
48 zlog_debug ("MESSAGE: ZEBRA_VRF_ADD %s", zvrf->name);
49
50 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
51 zsend_vrf_add (client, zvrf);
52 }
53
54 static void
55 zebra_vrf_delete_update (struct zebra_vrf *zvrf)
56 {
57 struct listnode *node, *nnode;
58 struct zserv *client;
59
60 if (IS_ZEBRA_DEBUG_EVENT)
61 zlog_debug ("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf->name);
62
63 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
64 zsend_vrf_delete (client, zvrf);
65 }
66
67 void
68 zebra_vrf_update_all (struct zserv *client)
69 {
70 struct vrf *vrf;
71
72 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
73 {
74 if (vrf->vrf_id)
75 zsend_vrf_add (client, vrf_info_lookup (vrf->vrf_id));
76 }
77 }
78
79 /* Callback upon creating a new VRF. */
80 static int
81 zebra_vrf_new (vrf_id_t vrf_id, const char *name, void **info)
82 {
83 struct zebra_vrf *zvrf = *info;
84
85 if (IS_ZEBRA_DEBUG_EVENT)
86 zlog_info ("ZVRF %s with id %u", name, vrf_id);
87
88 if (! zvrf)
89 {
90 zvrf = zebra_vrf_list_lookup_by_name (name);
91 if (!zvrf)
92 {
93 zvrf = zebra_vrf_alloc (vrf_id, name);
94 zvrf->zns = zebra_ns_lookup (NS_DEFAULT); /* Point to the global (single) NS */
95 *info = (void *)zvrf;
96 router_id_init (zvrf);
97 }
98 else
99 {
100 *info = (void *)zvrf;
101 router_id_init (zvrf);
102 }
103 }
104
105 if (zvrf->vrf_id == VRF_UNKNOWN)
106 zvrf->vrf_id = vrf_id;
107
108 return 0;
109 }
110
111 /*
112 * Moving an interface amongst different vrf's
113 * causes the interface to get a new ifindex
114 * so we need to find static routes with
115 * the old ifindex and replace with new
116 * ifindex to insert back into the table
117 */
118 void
119 zebra_vrf_static_route_interface_fixup (struct interface *ifp)
120 {
121 afi_t afi;
122 safi_t safi;
123 struct zebra_vrf *zvrf = zebra_vrf_lookup (ifp->vrf_id);
124 struct route_table *stable = NULL;
125 struct route_node *rn = NULL;
126 struct static_route *si = NULL;
127
128 if (!zvrf)
129 return;
130
131 for (afi = AFI_IP; afi < AFI_MAX; afi++)
132 {
133 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
134 {
135 stable = zvrf->stable[afi][safi];
136 if (stable)
137 for (rn = route_top (stable); rn; rn = route_next (rn))
138 {
139 if (rn->info)
140 {
141 si = rn->info;
142 if ((strcmp (si->ifname, ifp->name) == 0) &&
143 (si->ifindex != ifp->ifindex))
144 {
145 si->ifindex = ifp->ifindex;
146 static_install_route (afi, safi, &rn->p, si);
147 }
148 }
149 }
150 }
151 }
152
153 }
154
155 /* Callback upon enabling a VRF. */
156 static int
157 zebra_vrf_enable (vrf_id_t vrf_id, const char *name, void **info)
158 {
159 struct zebra_vrf *zvrf = (struct zebra_vrf *) (*info);
160 struct route_table *stable = NULL;
161 struct route_node *rn = NULL;
162 struct static_route *si = NULL;
163 struct interface *ifp = NULL;
164 afi_t afi;
165 safi_t safi;
166
167 assert (zvrf);
168
169 zebra_vrf_add_update (zvrf);
170
171 for (afi = AFI_IP; afi < AFI_MAX; afi++)
172 {
173 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
174 {
175 stable = zvrf->stable[afi][safi];
176 if (stable)
177 {
178 for (rn = route_top (stable); rn; rn = route_next (rn))
179 {
180 if (rn->info)
181 {
182 si = rn->info;
183 si->vrf_id = vrf_id;
184 if (si->ifindex)
185 {
186 ifp = if_lookup_by_name_vrf (si->ifname, si->vrf_id);
187 if (ifp)
188 si->ifindex = ifp->ifindex;
189 else
190 continue;
191 }
192 static_install_route (afi, safi, &rn->p, si);
193 }
194 }
195 }
196 }
197 }
198 return 0;
199 }
200
201 /* Callback upon disabling a VRF. */
202 static int
203 zebra_vrf_disable (vrf_id_t vrf_id, const char *name, void **info)
204 {
205 struct zebra_vrf *zvrf = (struct zebra_vrf *)(*info);
206 struct route_table *stable = NULL;
207 struct route_node *rn = NULL;
208 afi_t afi;
209 safi_t safi;
210
211 if (IS_ZEBRA_DEBUG_KERNEL)
212 zlog_debug ("VRF %s id %u is now disabled.",
213 zvrf->name, zvrf->vrf_id);
214
215 for (afi = AFI_IP; afi < AFI_MAX; afi++)
216 {
217 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
218 {
219 stable = zvrf->stable[afi][safi];
220 if (stable)
221 {
222 for (rn = route_top (stable); rn; rn = route_next (rn))
223 {
224 if (rn->info)
225 static_uninstall_route(afi, safi, &rn->p, rn->info);
226 }
227 }
228 }
229 }
230 return 0;
231 }
232
233 static int
234 zebra_vrf_delete (vrf_id_t vrf_id, const char *name, void **info)
235 {
236 struct zebra_vrf *zvrf = (struct zebra_vrf *) (*info);
237
238 assert (zvrf);
239
240 zebra_vrf_delete_update (zvrf);
241
242 rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
243 rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
244
245 list_delete_all_node (zvrf->rid_all_sorted_list);
246 list_delete_all_node (zvrf->rid_lo_sorted_list);
247
248 zvrf->vrf_id = VRF_UNKNOWN;
249
250 *info = NULL;
251 return 0;
252 }
253
254 /* Lookup the routing table in a VRF based on both VRF-Id and table-id.
255 * NOTE: Table-id is relevant only in the Default VRF.
256 */
257 struct route_table *
258 zebra_vrf_table_with_table_id (afi_t afi, safi_t safi,
259 vrf_id_t vrf_id, u_int32_t table_id)
260 {
261 struct route_table *table = NULL;
262
263 if (afi >= AFI_MAX || safi >= SAFI_MAX)
264 return NULL;
265
266 if (vrf_id == VRF_DEFAULT)
267 {
268 if (table_id == RT_TABLE_MAIN ||
269 table_id == zebrad.rtm_table_default)
270 table = zebra_vrf_table (afi, safi, vrf_id);
271 else
272 table = zebra_vrf_other_route_table (afi, table_id, vrf_id);
273 }
274 else
275 table = zebra_vrf_table (afi, safi, vrf_id);
276
277 return table;
278 }
279
280 /*
281 * Create a routing table for the specific AFI/SAFI in the given VRF.
282 */
283 static void
284 zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi)
285 {
286 rib_table_info_t *info;
287 struct route_table *table;
288
289 assert (!zvrf->table[afi][safi]);
290
291 table = route_table_init ();
292 zvrf->table[afi][safi] = table;
293
294 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
295 info->zvrf = zvrf;
296 info->afi = afi;
297 info->safi = safi;
298 table->info = info;
299 }
300
301 /* Allocate new zebra VRF. */
302 struct zebra_vrf *
303 zebra_vrf_alloc (vrf_id_t vrf_id, const char *name)
304 {
305 struct zebra_vrf *zvrf;
306
307 zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf));
308
309 /* Allocate routing table and static table. */
310 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_UNICAST);
311 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_UNICAST);
312 zvrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
313 zvrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
314 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_MULTICAST);
315 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_MULTICAST);
316 zvrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
317 zvrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
318
319 zvrf->rnh_table[AFI_IP] = route_table_init();
320 zvrf->rnh_table[AFI_IP6] = route_table_init();
321
322 zvrf->import_check_table[AFI_IP] = route_table_init();
323 zvrf->import_check_table[AFI_IP6] = route_table_init();
324
325 /* Set VRF ID */
326 zvrf->vrf_id = vrf_id;
327
328 if (name)
329 {
330 strncpy (zvrf->name, name, strlen(name));
331 zvrf->name[strlen(name)] = '\0';
332 }
333
334 zebra_mpls_init_tables (zvrf);
335
336 return zvrf;
337 }
338
339 /* Lookup VRF by identifier. */
340 struct zebra_vrf *
341 zebra_vrf_lookup (vrf_id_t vrf_id)
342 {
343 return vrf_info_lookup (vrf_id);
344 }
345
346 /* Lookup VRF by name. */
347 struct zebra_vrf *
348 zebra_vrf_list_lookup_by_name (const char *name)
349 {
350 struct vrf *vrf;
351
352 if (!name)
353 name = VRF_DEFAULT_NAME;
354
355 vrf = vrf_list_lookup_by_name (name);
356 if (vrf)
357 return ((struct zebra_vrf *) vrf->info);
358
359 return NULL;
360 }
361
362 /* Lookup the routing table in an enabled VRF. */
363 struct route_table *
364 zebra_vrf_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
365 {
366 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
367
368 if (!zvrf)
369 return NULL;
370
371 if (afi >= AFI_MAX || safi >= SAFI_MAX)
372 return NULL;
373
374 return zvrf->table[afi][safi];
375 }
376
377 /* Lookup the static routing table in a VRF. */
378 struct route_table *
379 zebra_vrf_static_table (afi_t afi, safi_t safi, struct zebra_vrf *zvrf)
380 {
381 if (!zvrf)
382 return NULL;
383
384 if (afi >= AFI_MAX || safi >= SAFI_MAX)
385 return NULL;
386
387 return zvrf->stable[afi][safi];
388 }
389
390 struct route_table *
391 zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id, vrf_id_t vrf_id)
392 {
393 struct zebra_vrf *zvrf;
394 rib_table_info_t *info;
395 struct route_table *table;
396
397 zvrf = vrf_info_lookup (vrf_id);
398 if (! zvrf)
399 return NULL;
400
401 if(afi >= AFI_MAX)
402 return NULL;
403
404 if (table_id >= ZEBRA_KERNEL_TABLE_MAX)
405 return NULL;
406
407 if ((vrf_id == VRF_DEFAULT) && (table_id != RT_TABLE_MAIN) && (table_id != zebrad.rtm_table_default))
408 {
409 if (zvrf->other_table[afi][table_id] == NULL)
410 {
411 table = route_table_init();
412 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
413 info->zvrf = zvrf;
414 info->afi = afi;
415 info->safi = SAFI_UNICAST;
416 table->info = info;
417 zvrf->other_table[afi][table_id] = table;
418 }
419
420 return (zvrf->other_table[afi][table_id]);
421 }
422
423 return zvrf->table[afi][SAFI_UNICAST];
424 }
425
426 /* Wrapper hook point for zebra daemon so that ifindex can be set
427 * DEFUN macro not used as extract.pl HAS to ignore this
428 * See also interface_cmd in lib/if.c
429 */
430 DEFUN_NOSH (zebra_vrf,
431 zebra_vrf_cmd,
432 "vrf NAME",
433 "Select a VRF to configure\n"
434 "VRF's name\n")
435 {
436 // VTY_DECLVAR_CONTEXT (vrf, vrfp);
437 int ret;
438
439 /* Call lib vrf() */
440 if ((ret = vrf_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS)
441 return ret;
442
443 return ret;
444 }
445
446 static int
447 vrf_config_write (struct vty *vty)
448 {
449 struct listnode *node;
450 struct vrf *vrf;
451 struct zebra_vrf *zvrf;
452
453 for (ALL_LIST_ELEMENTS_RO (vrf_list, node, vrf))
454 {
455 zvrf = vrf->info;
456 if (! zvrf || strcmp (zvrf->name, VRF_DEFAULT_NAME))
457 {
458 vty_out (vty, "vrf %s%s", zvrf->name, VTY_NEWLINE);
459 vty_out (vty, "!%s", VTY_NEWLINE);
460 }
461 }
462 return 0;
463 }
464
465 struct cmd_node vrf_node =
466 {
467 VRF_NODE,
468 "%s(config-vrf)# ",
469 1
470 };
471
472 /* Zebra VRF initialization. */
473 void
474 zebra_vrf_init (void)
475 {
476 vrf_add_hook (VRF_NEW_HOOK, zebra_vrf_new);
477 vrf_add_hook (VRF_ENABLE_HOOK, zebra_vrf_enable);
478 vrf_add_hook (VRF_DISABLE_HOOK, zebra_vrf_disable);
479 vrf_add_hook (VRF_DELETE_HOOK, zebra_vrf_delete);
480
481 vrf_init ();
482
483 install_node (&vrf_node, vrf_config_write);
484 install_default (VRF_NODE);
485 install_element (CONFIG_NODE, &zebra_vrf_cmd);
486 install_element (CONFIG_NODE, &no_vrf_cmd);
487 }