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