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