]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_vrf.c
Merge pull request #750 from donaldsharp/bgp_buffer
[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 *
896014f4
DL
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7c551956
DS
20 */
21#include <zebra.h>
22
23#include "log.h"
24#include "linklist.h"
f30c50b9 25#include "command.h"
4a1ab8e4 26#include "memory.h"
05737783 27#include "srcdest_table.h"
7c551956 28
82f97584 29#include "vty.h"
7c551956
DS
30#include "zebra/debug.h"
31#include "zebra/zserv.h"
32#include "zebra/rib.h"
33#include "zebra/zebra_vrf.h"
5a8dfcd8 34#include "zebra/zebra_rnh.h"
7c551956 35#include "zebra/router-id.h"
4a1ab8e4 36#include "zebra/zebra_memory.h"
28f6dde8 37#include "zebra/zebra_static.h"
5a8dfcd8 38#include "zebra/interface.h"
7758e3f3 39#include "zebra/zebra_mpls.h"
7c551956
DS
40
41extern struct zebra_t zebrad;
42
43/* VRF information update. */
44static void
45zebra_vrf_add_update (struct zebra_vrf *zvrf)
46{
47 struct listnode *node, *nnode;
48 struct zserv *client;
49
50 if (IS_ZEBRA_DEBUG_EVENT)
661512bf 51 zlog_debug ("MESSAGE: ZEBRA_VRF_ADD %s", zvrf_name (zvrf));
7c551956
DS
52
53 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
54 zsend_vrf_add (client, zvrf);
55}
56
57static void
58zebra_vrf_delete_update (struct zebra_vrf *zvrf)
59{
60 struct listnode *node, *nnode;
61 struct zserv *client;
62
63 if (IS_ZEBRA_DEBUG_EVENT)
661512bf 64 zlog_debug ("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf_name (zvrf));
7c551956
DS
65
66 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
67 zsend_vrf_delete (client, zvrf);
68}
69
70void
71zebra_vrf_update_all (struct zserv *client)
72{
73 struct vrf *vrf;
7c551956 74
1a1a7065 75 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
7c551956 76 {
1a1a7065 77 if (vrf->vrf_id)
7c551956
DS
78 zsend_vrf_add (client, vrf_info_lookup (vrf->vrf_id));
79 }
80}
81
82/* Callback upon creating a new VRF. */
83static int
661512bf 84zebra_vrf_new (struct vrf *vrf)
7c551956 85{
661512bf 86 struct zebra_vrf *zvrf;
7c551956 87
3f6d6a5d 88 if (IS_ZEBRA_DEBUG_EVENT)
661512bf 89 zlog_info ("ZVRF %s with id %u", vrf->name, vrf->vrf_id);
7c551956 90
661512bf
RW
91 zvrf = zebra_vrf_alloc ();
92 zvrf->zns = zebra_ns_lookup (NS_DEFAULT); /* Point to the global (single) NS */
93 router_id_init (zvrf);
94 vrf->info = zvrf;
95 zvrf->vrf = vrf;
34f8e6af 96
7c551956
DS
97 return 0;
98}
99
fb148af4
DS
100/*
101 * Moving an interface amongst different vrf's
102 * causes the interface to get a new ifindex
103 * so we need to find static routes with
104 * the old ifindex and replace with new
105 * ifindex to insert back into the table
106 */
107void
108zebra_vrf_static_route_interface_fixup (struct interface *ifp)
109{
110 afi_t afi;
111 safi_t safi;
5f3d1bdf 112 struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id (ifp->vrf_id);
fb148af4
DS
113 struct route_table *stable = NULL;
114 struct route_node *rn = NULL;
115 struct static_route *si = NULL;
116
117 if (!zvrf)
118 return;
119
120 for (afi = AFI_IP; afi < AFI_MAX; afi++)
121 {
122 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
123 {
124 stable = zvrf->stable[afi][safi];
125 if (stable)
126 for (rn = route_top (stable); rn; rn = route_next (rn))
127 {
128 if (rn->info)
129 {
130 si = rn->info;
131 if ((strcmp (si->ifname, ifp->name) == 0) &&
132 (si->ifindex != ifp->ifindex))
133 {
134 si->ifindex = ifp->ifindex;
c423229b 135 static_install_route (afi, safi, &rn->p, NULL, si);
fb148af4
DS
136 }
137 }
138 }
139 }
140 }
141
142}
143
7c551956
DS
144/* Callback upon enabling a VRF. */
145static int
661512bf 146zebra_vrf_enable (struct vrf *vrf)
7c551956 147{
661512bf 148 struct zebra_vrf *zvrf = vrf->info;
2414ffe5
RW
149 struct route_table *stable;
150 struct route_node *rn;
151 struct static_route *si;
152 struct interface *ifp;
fb148af4
DS
153 afi_t afi;
154 safi_t safi;
7c551956
DS
155
156 assert (zvrf);
157
158 zebra_vrf_add_update (zvrf);
159
fb148af4 160 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2414ffe5
RW
161 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
162 {
163 stable = zvrf->stable[afi][safi];
164 if (! stable)
165 continue;
166
167 for (rn = route_top (stable); rn; rn = route_next (rn))
168 for (si = rn->info; si; si = si->next)
fb148af4 169 {
2414ffe5
RW
170 si->vrf_id = vrf->vrf_id;
171 if (si->ifindex)
fb148af4 172 {
1306c09a 173 ifp = if_lookup_by_name (si->ifname, si->vrf_id);
2414ffe5
RW
174 if (ifp)
175 si->ifindex = ifp->ifindex;
176 else
177 continue;
fb148af4 178 }
c423229b 179 static_install_route (afi, safi, &rn->p, NULL, si);
fb148af4 180 }
2414ffe5
RW
181 }
182
7c551956
DS
183 return 0;
184}
185
186/* Callback upon disabling a VRF. */
187static int
661512bf 188zebra_vrf_disable (struct vrf *vrf)
7c551956 189{
661512bf 190 struct zebra_vrf *zvrf = vrf->info;
2414ffe5
RW
191 struct route_table *stable;
192 struct route_node *rn;
193 struct static_route *si;
fb148af4
DS
194 afi_t afi;
195 safi_t safi;
7c551956
DS
196
197 if (IS_ZEBRA_DEBUG_KERNEL)
198 zlog_debug ("VRF %s id %u is now disabled.",
661512bf 199 zvrf_name (zvrf), zvrf_id (zvrf));
7c551956 200
fb148af4 201 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2414ffe5
RW
202 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
203 {
204 stable = zvrf->stable[afi][safi];
205 if (! stable)
206 continue;
207
208 for (rn = route_top (stable); rn; rn = route_next (rn))
209 for (si = rn->info; si; si = si->next)
c423229b 210 static_uninstall_route(afi, safi, &rn->p, NULL, si);
2414ffe5
RW
211 }
212
7c551956
DS
213 return 0;
214}
215
216static int
661512bf 217zebra_vrf_delete (struct vrf *vrf)
7c551956 218{
661512bf 219 struct zebra_vrf *zvrf = vrf->info;
5a8dfcd8
RW
220 struct route_table *table;
221 u_int32_t table_id;
222 afi_t afi;
223 safi_t safi;
224 unsigned i;
7c551956
DS
225
226 assert (zvrf);
227
228 zebra_vrf_delete_update (zvrf);
229
5a8dfcd8
RW
230 /* uninstall everything */
231 if (! CHECK_FLAG (zvrf->flags, ZEBRA_VRF_RETAIN))
232 {
233 struct listnode *node;
234 struct interface *ifp;
7c551956 235
5a8dfcd8
RW
236 for (afi = AFI_IP; afi <= AFI_IP6; afi++)
237 {
238 for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
239 rib_close_table (zvrf->table[afi][safi]);
240
241 if (vrf->vrf_id == VRF_DEFAULT)
242 for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++)
243 if (zvrf->other_table[afi][table_id])
244 rib_close_table (zvrf->other_table[afi][table_id]);
245 }
246
247 zebra_mpls_close_tables (zvrf);
7c551956 248
5a8dfcd8
RW
249 for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp))
250 if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp);
251 }
252
253 /* clean-up work queues */
254 for (i = 0; i < MQ_SIZE; i++)
255 {
256 struct listnode *lnode, *nnode;
257 struct route_node *rnode;
258 rib_dest_t *dest;
259
260 for (ALL_LIST_ELEMENTS (zebrad.mq->subq[i], lnode, nnode, rnode))
261 {
262 dest = rib_dest_from_rnode (rnode);
263 if (dest && rib_dest_vrf (dest) == zvrf)
264 {
265 route_unlock_node (rnode);
266 list_delete_node (zebrad.mq->subq[i], lnode);
06b57ec2 267 zebrad.mq->size--;
5a8dfcd8
RW
268 }
269 }
270 }
271
272 /* release allocated memory */
273 for (afi = AFI_IP; afi <= AFI_IP6; afi++)
274 {
0f124559
RW
275 void *table_info;
276
5a8dfcd8
RW
277 for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
278 {
279 table = zvrf->table[afi][safi];
0f124559 280 table_info = table->info;
5a8dfcd8 281 route_table_finish (table);
0f124559 282 XFREE (MTYPE_RIB_TABLE_INFO, table_info);
5a8dfcd8
RW
283
284 table = zvrf->stable[afi][safi];
285 route_table_finish (table);
286 }
287
288 for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++)
289 if (zvrf->other_table[afi][table_id])
290 {
291 table = zvrf->other_table[afi][table_id];
0f124559 292 table_info = table->info;
5a8dfcd8 293 route_table_finish (table);
0f124559 294 XFREE (MTYPE_RIB_TABLE_INFO, table_info);
5a8dfcd8
RW
295 }
296
297 route_table_finish (zvrf->rnh_table[afi]);
298 route_table_finish (zvrf->import_check_table[afi]);
299 }
7c551956
DS
300 list_delete_all_node (zvrf->rid_all_sorted_list);
301 list_delete_all_node (zvrf->rid_lo_sorted_list);
5a8dfcd8 302 XFREE (MTYPE_ZEBRA_VRF, zvrf);
661512bf 303 vrf->info = NULL;
7c551956 304
7c551956
DS
305 return 0;
306}
307
308/* Lookup the routing table in a VRF based on both VRF-Id and table-id.
309 * NOTE: Table-id is relevant only in the Default VRF.
310 */
311struct route_table *
312zebra_vrf_table_with_table_id (afi_t afi, safi_t safi,
313 vrf_id_t vrf_id, u_int32_t table_id)
314{
315 struct route_table *table = NULL;
316
317 if (afi >= AFI_MAX || safi >= SAFI_MAX)
318 return NULL;
319
320 if (vrf_id == VRF_DEFAULT)
321 {
322 if (table_id == RT_TABLE_MAIN ||
323 table_id == zebrad.rtm_table_default)
324 table = zebra_vrf_table (afi, safi, vrf_id);
325 else
326 table = zebra_vrf_other_route_table (afi, table_id, vrf_id);
327 }
328 else
329 table = zebra_vrf_table (afi, safi, vrf_id);
330
331 return table;
332}
333
5a8dfcd8 334static void
05737783 335zebra_rtable_node_cleanup (struct route_table *table, struct route_node *node)
5a8dfcd8 336{
f0f77c9a 337 struct route_entry *re, *next;
5a8dfcd8 338
f0f77c9a
DS
339 RNODE_FOREACH_RE_SAFE (node, re, next)
340 rib_unlink (node, re);
5a8dfcd8
RW
341
342 if (node->info)
343 XFREE (MTYPE_RIB_DEST, node->info);
5a8dfcd8
RW
344}
345
346static void
c423229b 347zebra_stable_node_cleanup (struct route_table *table, struct route_node *node)
5a8dfcd8
RW
348{
349 struct static_route *si, *next;
350
351 if (node->info)
352 for (si = node->info; si; si = next)
353 {
354 next = si->next;
355 XFREE (MTYPE_STATIC_ROUTE, si);
356 }
5a8dfcd8
RW
357}
358
359static void
05737783 360zebra_rnhtable_node_cleanup (struct route_table *table, struct route_node *node)
5a8dfcd8
RW
361{
362 if (node->info)
363 zebra_free_rnh (node->info);
5a8dfcd8
RW
364}
365
7c551956
DS
366/*
367 * Create a routing table for the specific AFI/SAFI in the given VRF.
368 */
369static void
370zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi)
371{
372 rib_table_info_t *info;
373 struct route_table *table;
374
375 assert (!zvrf->table[afi][safi]);
376
05737783
CF
377 if (afi == AFI_IP6)
378 table = srcdest_table_init();
379 else
380 table = route_table_init();
381 table->cleanup = zebra_rtable_node_cleanup;
7c551956
DS
382 zvrf->table[afi][safi] = table;
383
384 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
385 info->zvrf = zvrf;
386 info->afi = afi;
387 info->safi = safi;
388 table->info = info;
389}
390
391/* Allocate new zebra VRF. */
392struct zebra_vrf *
661512bf 393zebra_vrf_alloc (void)
7c551956
DS
394{
395 struct zebra_vrf *zvrf;
5a8dfcd8
RW
396 afi_t afi;
397 safi_t safi;
05737783 398 struct route_table *table;
7c551956
DS
399
400 zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf));
401
5a8dfcd8 402 for (afi = AFI_IP; afi <= AFI_IP6; afi++)
7c551956 403 {
5a8dfcd8 404 for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
c423229b
CF
405 {
406 zebra_vrf_table_create (zvrf, afi, safi);
407 if (afi == AFI_IP6)
408 table = srcdest_table_init();
409 else
410 table = route_table_init();
411 table->cleanup = zebra_stable_node_cleanup;
412 zvrf->stable[afi][safi] = table;
413 }
5a8dfcd8 414
05737783
CF
415 table = route_table_init();
416 table->cleanup = zebra_rnhtable_node_cleanup;
417 zvrf->rnh_table[afi] = table;
418
419 table = route_table_init();
420 table->cleanup = zebra_rnhtable_node_cleanup;
421 zvrf->import_check_table[afi] = table;
7c551956
DS
422 }
423
7758e3f3 424 zebra_mpls_init_tables (zvrf);
425
7c551956
DS
426 return zvrf;
427}
428
429/* Lookup VRF by identifier. */
430struct zebra_vrf *
5f3d1bdf 431zebra_vrf_lookup_by_id (vrf_id_t vrf_id)
7c551956
DS
432{
433 return vrf_info_lookup (vrf_id);
434}
435
51bdc5f8 436/* Lookup VRF by name. */
871d39b3 437struct zebra_vrf *
05e8e11e 438zebra_vrf_lookup_by_name (const char *name)
871d39b3 439{
51bdc5f8 440 struct vrf *vrf;
871d39b3 441
a3d21ef3
DS
442 if (!name)
443 name = VRF_DEFAULT_NAME;
444
05e8e11e 445 vrf = vrf_lookup_by_name (name);
51bdc5f8
RW
446 if (vrf)
447 return ((struct zebra_vrf *) vrf->info);
448
871d39b3
DS
449 return NULL;
450}
451
7c551956
DS
452/* Lookup the routing table in an enabled VRF. */
453struct route_table *
454zebra_vrf_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
455{
456 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
457
458 if (!zvrf)
459 return NULL;
460
461 if (afi >= AFI_MAX || safi >= SAFI_MAX)
462 return NULL;
463
464 return zvrf->table[afi][safi];
465}
466
467/* Lookup the static routing table in a VRF. */
468struct route_table *
01bb6d57 469zebra_vrf_static_table (afi_t afi, safi_t safi, struct zebra_vrf *zvrf)
7c551956 470{
7c551956
DS
471 if (!zvrf)
472 return NULL;
473
474 if (afi >= AFI_MAX || safi >= SAFI_MAX)
475 return NULL;
476
477 return zvrf->stable[afi][safi];
478}
479
480struct route_table *
481zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id, vrf_id_t vrf_id)
482{
483 struct zebra_vrf *zvrf;
484 rib_table_info_t *info;
485 struct route_table *table;
486
487 zvrf = vrf_info_lookup (vrf_id);
488 if (! zvrf)
489 return NULL;
490
491 if(afi >= AFI_MAX)
492 return NULL;
493
494 if (table_id >= ZEBRA_KERNEL_TABLE_MAX)
495 return NULL;
496
497 if ((vrf_id == VRF_DEFAULT) && (table_id != RT_TABLE_MAIN) && (table_id != zebrad.rtm_table_default))
498 {
499 if (zvrf->other_table[afi][table_id] == NULL)
500 {
05737783 501 table = (afi == AFI_IP6) ? srcdest_table_init() : route_table_init();
7c551956
DS
502 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
503 info->zvrf = zvrf;
504 info->afi = afi;
505 info->safi = SAFI_UNICAST;
506 table->info = info;
507 zvrf->other_table[afi][table_id] = table;
508 }
509
510 return (zvrf->other_table[afi][table_id]);
511 }
512
513 return zvrf->table[afi][SAFI_UNICAST];
514}
515
f30c50b9
RW
516static int
517vrf_config_write (struct vty *vty)
518{
51bdc5f8 519 struct vrf *vrf;
f30c50b9
RW
520 struct zebra_vrf *zvrf;
521
806f8760 522 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
f30c50b9 523 {
51bdc5f8 524 zvrf = vrf->info;
661512bf 525 if (! zvrf || strcmp (zvrf_name (zvrf), VRF_DEFAULT_NAME))
f30c50b9 526 {
96ade3ed
QY
527 vty_outln (vty, "vrf %s", zvrf_name(zvrf));
528 vty_outln (vty, "!");
f30c50b9
RW
529 }
530 }
531 return 0;
532}
533
7c551956
DS
534/* Zebra VRF initialization. */
535void
536zebra_vrf_init (void)
537{
6df85364
DS
538 vrf_init (zebra_vrf_new,
539 zebra_vrf_enable,
540 zebra_vrf_disable,
541 zebra_vrf_delete);
7c551956 542
7ddcfca4 543 vrf_cmd_init (vrf_config_write);
7c551956 544}