]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_vrf.c
Merge branch 'stable/3.0' into tmp-3.0-master-merge
[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"
13d60d35 40#include "zebra/zebra_vxlan.h"
7c551956
DS
41
42extern struct zebra_t zebrad;
43
44/* VRF information update. */
d62a17ae 45static void zebra_vrf_add_update(struct zebra_vrf *zvrf)
7c551956 46{
d62a17ae 47 struct listnode *node, *nnode;
48 struct zserv *client;
7c551956 49
d62a17ae 50 if (IS_ZEBRA_DEBUG_EVENT)
51 zlog_debug("MESSAGE: ZEBRA_VRF_ADD %s", zvrf_name(zvrf));
7c551956 52
d62a17ae 53 for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))
54 zsend_vrf_add(client, zvrf);
7c551956
DS
55}
56
d62a17ae 57static void zebra_vrf_delete_update(struct zebra_vrf *zvrf)
7c551956 58{
d62a17ae 59 struct listnode *node, *nnode;
60 struct zserv *client;
7c551956 61
d62a17ae 62 if (IS_ZEBRA_DEBUG_EVENT)
63 zlog_debug("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf_name(zvrf));
7c551956 64
d62a17ae 65 for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))
66 zsend_vrf_delete(client, zvrf);
7c551956
DS
67}
68
d62a17ae 69void zebra_vrf_update_all(struct zserv *client)
7c551956 70{
d62a17ae 71 struct vrf *vrf;
7c551956 72
d62a17ae 73 RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id)
74 {
75 if (vrf->vrf_id)
76 zsend_vrf_add(client, vrf_info_lookup(vrf->vrf_id));
77 }
7c551956
DS
78}
79
80/* Callback upon creating a new VRF. */
d62a17ae 81static int zebra_vrf_new(struct vrf *vrf)
7c551956 82{
d62a17ae 83 struct zebra_vrf *zvrf;
7c551956 84
d62a17ae 85 if (IS_ZEBRA_DEBUG_EVENT)
86 zlog_info("ZVRF %s with id %u", vrf->name, vrf->vrf_id);
7c551956 87
d62a17ae 88 zvrf = zebra_vrf_alloc();
89 zvrf->zns = zebra_ns_lookup(
90 NS_DEFAULT); /* Point to the global (single) NS */
91 router_id_init(zvrf);
92 vrf->info = zvrf;
93 zvrf->vrf = vrf;
34f8e6af 94
d62a17ae 95 return 0;
7c551956
DS
96}
97
98/* Callback upon enabling a VRF. */
d62a17ae 99static int zebra_vrf_enable(struct vrf *vrf)
7c551956 100{
d62a17ae 101 struct zebra_vrf *zvrf = vrf->info;
102 struct route_table *stable;
103 struct route_node *rn;
104 struct static_route *si;
105 struct interface *ifp;
106 afi_t afi;
107 safi_t safi;
108
109 assert(zvrf);
110
111 zebra_vrf_add_update(zvrf);
112
113 for (afi = AFI_IP; afi < AFI_MAX; afi++)
114 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
115 stable = zvrf->stable[afi][safi];
116 if (!stable)
117 continue;
118
119 for (rn = route_top(stable); rn; rn = route_next(rn))
120 for (si = rn->info; si; si = si->next) {
121 si->vrf_id = vrf->vrf_id;
122 if (si->ifindex) {
123 ifp = if_lookup_by_name(
124 si->ifname, si->vrf_id);
125 if (ifp)
126 si->ifindex =
127 ifp->ifindex;
128 else
129 continue;
130 }
131 static_install_route(afi, safi, &rn->p,
132 NULL, si);
133 }
fb148af4 134 }
2414ffe5 135
d62a17ae 136 return 0;
7c551956
DS
137}
138
139/* Callback upon disabling a VRF. */
d62a17ae 140static int zebra_vrf_disable(struct vrf *vrf)
7c551956 141{
d62a17ae 142 struct zebra_vrf *zvrf = vrf->info;
143 struct route_table *stable;
144 struct route_node *rn;
145 struct static_route *si;
146 afi_t afi;
147 safi_t safi;
148
149 if (IS_ZEBRA_DEBUG_KERNEL)
150 zlog_debug("VRF %s id %u is now disabled.", zvrf_name(zvrf),
151 zvrf_id(zvrf));
152
153 for (afi = AFI_IP; afi < AFI_MAX; afi++)
154 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
155 stable = zvrf->stable[afi][safi];
156 if (!stable)
157 continue;
158
159 for (rn = route_top(stable); rn; rn = route_next(rn))
160 for (si = rn->info; si; si = si->next)
161 static_uninstall_route(
162 afi, safi, &rn->p, NULL, si);
163 }
164
165 return 0;
7c551956
DS
166}
167
d62a17ae 168static int zebra_vrf_delete(struct vrf *vrf)
7c551956 169{
d62a17ae 170 struct zebra_vrf *zvrf = vrf->info;
171 struct route_table *table;
172 u_int32_t table_id;
173 afi_t afi;
174 safi_t safi;
175 unsigned i;
176
177 assert(zvrf);
178
179 zebra_vrf_delete_update(zvrf);
180
181 /* uninstall everything */
182 if (!CHECK_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN)) {
183 struct listnode *node;
184 struct interface *ifp;
185
186 for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
187 for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST;
188 safi++)
189 rib_close_table(zvrf->table[afi][safi]);
190
191 if (vrf->vrf_id == VRF_DEFAULT)
192 for (table_id = 0;
193 table_id < ZEBRA_KERNEL_TABLE_MAX;
194 table_id++)
195 if (zvrf->other_table[afi][table_id])
196 rib_close_table(
197 zvrf->other_table
198 [afi]
199 [table_id]);
200 }
7c551956 201
d62a17ae 202 /* Cleanup Vxlan table and update kernel */
203 zebra_vxlan_close_tables(zvrf);
7c551956 204
d62a17ae 205 zebra_mpls_close_tables(zvrf);
6833ae01 206 zebra_pw_exit(zvrf);
5a8dfcd8 207
d62a17ae 208 for (ALL_LIST_ELEMENTS_RO(vrf->iflist, node, ifp))
209 if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
5a8dfcd8
RW
210 }
211
d62a17ae 212 /* clean-up work queues */
213 for (i = 0; i < MQ_SIZE; i++) {
214 struct listnode *lnode, *nnode;
215 struct route_node *rnode;
216 rib_dest_t *dest;
217
218 for (ALL_LIST_ELEMENTS(zebrad.mq->subq[i], lnode, nnode,
219 rnode)) {
220 dest = rib_dest_from_rnode(rnode);
221 if (dest && rib_dest_vrf(dest) == zvrf) {
222 route_unlock_node(rnode);
223 list_delete_node(zebrad.mq->subq[i], lnode);
224 zebrad.mq->size--;
225 }
226 }
5a8dfcd8 227 }
5a8dfcd8 228
d62a17ae 229 /* release allocated memory */
230 for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
231 void *table_info;
0f124559 232
d62a17ae 233 for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
234 table = zvrf->table[afi][safi];
235 table_info = table->info;
236 route_table_finish(table);
237 XFREE(MTYPE_RIB_TABLE_INFO, table_info);
238
239 table = zvrf->stable[afi][safi];
240 route_table_finish(table);
241 }
5a8dfcd8 242
d62a17ae 243 for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX;
244 table_id++)
245 if (zvrf->other_table[afi][table_id]) {
246 table = zvrf->other_table[afi][table_id];
247 table_info = table->info;
248 route_table_finish(table);
249 XFREE(MTYPE_RIB_TABLE_INFO, table_info);
250 }
251
252 route_table_finish(zvrf->rnh_table[afi]);
253 route_table_finish(zvrf->import_check_table[afi]);
5a8dfcd8 254 }
d62a17ae 255 list_delete_all_node(zvrf->rid_all_sorted_list);
256 list_delete_all_node(zvrf->rid_lo_sorted_list);
257 XFREE(MTYPE_ZEBRA_VRF, zvrf);
258 vrf->info = NULL;
5a8dfcd8 259
d62a17ae 260 return 0;
7c551956
DS
261}
262
263/* Lookup the routing table in a VRF based on both VRF-Id and table-id.
264 * NOTE: Table-id is relevant only in the Default VRF.
265 */
d62a17ae 266struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi,
267 vrf_id_t vrf_id,
268 u_int32_t table_id)
7c551956 269{
d62a17ae 270 struct route_table *table = NULL;
271
272 if (afi >= AFI_MAX || safi >= SAFI_MAX)
273 return NULL;
274
275 if (vrf_id == VRF_DEFAULT) {
276 if (table_id == RT_TABLE_MAIN
277 || table_id == zebrad.rtm_table_default)
278 table = zebra_vrf_table(afi, safi, vrf_id);
279 else
280 table = zebra_vrf_other_route_table(afi, table_id,
281 vrf_id);
282 } else
283 table = zebra_vrf_table(afi, safi, vrf_id);
284
285 return table;
7c551956
DS
286}
287
d62a17ae 288static void zebra_rtable_node_cleanup(struct route_table *table,
289 struct route_node *node)
5a8dfcd8 290{
d62a17ae 291 struct route_entry *re, *next;
5a8dfcd8 292
d62a17ae 293 RNODE_FOREACH_RE_SAFE(node, re, next)
294 rib_unlink(node, re);
5a8dfcd8 295
d62a17ae 296 if (node->info)
297 XFREE(MTYPE_RIB_DEST, node->info);
5a8dfcd8
RW
298}
299
d62a17ae 300static void zebra_stable_node_cleanup(struct route_table *table,
301 struct route_node *node)
5a8dfcd8 302{
d62a17ae 303 struct static_route *si, *next;
304
305 if (node->info)
306 for (si = node->info; si; si = next) {
307 next = si->next;
308 XFREE(MTYPE_STATIC_ROUTE, si);
309 }
5a8dfcd8
RW
310}
311
d62a17ae 312static void zebra_rnhtable_node_cleanup(struct route_table *table,
313 struct route_node *node)
5a8dfcd8 314{
d62a17ae 315 if (node->info)
316 zebra_free_rnh(node->info);
5a8dfcd8
RW
317}
318
7c551956
DS
319/*
320 * Create a routing table for the specific AFI/SAFI in the given VRF.
321 */
d62a17ae 322static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi,
323 safi_t safi)
7c551956 324{
d62a17ae 325 rib_table_info_t *info;
326 struct route_table *table;
327
328 assert(!zvrf->table[afi][safi]);
329
330 if (afi == AFI_IP6)
331 table = srcdest_table_init();
332 else
333 table = route_table_init();
334 table->cleanup = zebra_rtable_node_cleanup;
335 zvrf->table[afi][safi] = table;
336
337 info = XCALLOC(MTYPE_RIB_TABLE_INFO, sizeof(*info));
338 info->zvrf = zvrf;
339 info->afi = afi;
340 info->safi = safi;
341 table->info = info;
7c551956
DS
342}
343
344/* Allocate new zebra VRF. */
d62a17ae 345struct zebra_vrf *zebra_vrf_alloc(void)
7c551956 346{
d62a17ae 347 struct zebra_vrf *zvrf;
348 afi_t afi;
349 safi_t safi;
350 struct route_table *table;
351
352 zvrf = XCALLOC(MTYPE_ZEBRA_VRF, sizeof(struct zebra_vrf));
353
354 for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
355 for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
356 zebra_vrf_table_create(zvrf, afi, safi);
357 if (afi == AFI_IP6)
358 table = srcdest_table_init();
359 else
360 table = route_table_init();
361 table->cleanup = zebra_stable_node_cleanup;
362 zvrf->stable[afi][safi] = table;
363 }
364
365 table = route_table_init();
366 table->cleanup = zebra_rnhtable_node_cleanup;
367 zvrf->rnh_table[afi] = table;
368
369 table = route_table_init();
370 table->cleanup = zebra_rnhtable_node_cleanup;
371 zvrf->import_check_table[afi] = table;
372 }
373
374 zebra_vxlan_init_tables(zvrf);
375 zebra_mpls_init_tables(zvrf);
6833ae01 376 zebra_pw_init(zvrf);
d62a17ae 377
378 return zvrf;
7c551956
DS
379}
380
381/* Lookup VRF by identifier. */
d62a17ae 382struct zebra_vrf *zebra_vrf_lookup_by_id(vrf_id_t vrf_id)
7c551956 383{
d62a17ae 384 return vrf_info_lookup(vrf_id);
7c551956
DS
385}
386
51bdc5f8 387/* Lookup VRF by name. */
d62a17ae 388struct zebra_vrf *zebra_vrf_lookup_by_name(const char *name)
871d39b3 389{
d62a17ae 390 struct vrf *vrf;
871d39b3 391
d62a17ae 392 if (!name)
393 name = VRF_DEFAULT_NAME;
a3d21ef3 394
d62a17ae 395 vrf = vrf_lookup_by_name(name);
396 if (vrf)
397 return ((struct zebra_vrf *)vrf->info);
51bdc5f8 398
d62a17ae 399 return NULL;
871d39b3
DS
400}
401
7c551956 402/* Lookup the routing table in an enabled VRF. */
d62a17ae 403struct route_table *zebra_vrf_table(afi_t afi, safi_t safi, vrf_id_t vrf_id)
7c551956 404{
d62a17ae 405 struct zebra_vrf *zvrf = vrf_info_lookup(vrf_id);
7c551956 406
d62a17ae 407 if (!zvrf)
408 return NULL;
7c551956 409
d62a17ae 410 if (afi >= AFI_MAX || safi >= SAFI_MAX)
411 return NULL;
7c551956 412
d62a17ae 413 return zvrf->table[afi][safi];
7c551956
DS
414}
415
416/* Lookup the static routing table in a VRF. */
d62a17ae 417struct route_table *zebra_vrf_static_table(afi_t afi, safi_t safi,
418 struct zebra_vrf *zvrf)
7c551956 419{
d62a17ae 420 if (!zvrf)
421 return NULL;
7c551956 422
d62a17ae 423 if (afi >= AFI_MAX || safi >= SAFI_MAX)
424 return NULL;
7c551956 425
d62a17ae 426 return zvrf->stable[afi][safi];
7c551956
DS
427}
428
d62a17ae 429struct route_table *zebra_vrf_other_route_table(afi_t afi, u_int32_t table_id,
430 vrf_id_t vrf_id)
7c551956 431{
d62a17ae 432 struct zebra_vrf *zvrf;
433 rib_table_info_t *info;
434 struct route_table *table;
435
436 zvrf = vrf_info_lookup(vrf_id);
437 if (!zvrf)
438 return NULL;
439
440 if (afi >= AFI_MAX)
441 return NULL;
442
443 if (table_id >= ZEBRA_KERNEL_TABLE_MAX)
444 return NULL;
445
446 if ((vrf_id == VRF_DEFAULT) && (table_id != RT_TABLE_MAIN)
447 && (table_id != zebrad.rtm_table_default)) {
448 if (zvrf->other_table[afi][table_id] == NULL) {
449 table = (afi == AFI_IP6) ? srcdest_table_init()
450 : route_table_init();
451 info = XCALLOC(MTYPE_RIB_TABLE_INFO, sizeof(*info));
452 info->zvrf = zvrf;
453 info->afi = afi;
454 info->safi = SAFI_UNICAST;
455 table->info = info;
456 zvrf->other_table[afi][table_id] = table;
457 }
458
459 return (zvrf->other_table[afi][table_id]);
460 }
461
462 return zvrf->table[afi][SAFI_UNICAST];
7c551956
DS
463}
464
d62a17ae 465static int vrf_config_write(struct vty *vty)
f30c50b9 466{
d62a17ae 467 struct vrf *vrf;
468 struct zebra_vrf *zvrf;
469
470 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
471 {
472 zvrf = vrf->info;
473 if (!zvrf || strcmp(zvrf_name(zvrf), VRF_DEFAULT_NAME)) {
474 vty_out(vty, "vrf %s\n", zvrf_name(zvrf));
475 vty_out(vty, "!\n");
476 }
477 }
478 return 0;
f30c50b9
RW
479}
480
7c551956 481/* Zebra VRF initialization. */
d62a17ae 482void zebra_vrf_init(void)
7c551956 483{
d62a17ae 484 vrf_init(zebra_vrf_new, zebra_vrf_enable, zebra_vrf_disable,
485 zebra_vrf_delete);
7c551956 486
d62a17ae 487 vrf_cmd_init(vrf_config_write);
7c551956 488}