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