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