]>
git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_vrf.c
2 * Copyright (C) 2016 CumulusNetworks
5 * This file is part of Quagga
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
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.
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
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 #include "zebra/zebra_mpls.h"
38 extern struct zebra_t zebrad
;
39 struct list
*zvrf_list
;
41 /* VRF information update. */
43 zebra_vrf_add_update (struct zebra_vrf
*zvrf
)
45 struct listnode
*node
, *nnode
;
48 if (IS_ZEBRA_DEBUG_EVENT
)
49 zlog_debug ("MESSAGE: ZEBRA_VRF_ADD %s", zvrf
->name
);
51 for (ALL_LIST_ELEMENTS (zebrad
.client_list
, node
, nnode
, client
))
52 zsend_vrf_add (client
, zvrf
);
56 zebra_vrf_delete_update (struct zebra_vrf
*zvrf
)
58 struct listnode
*node
, *nnode
;
61 if (IS_ZEBRA_DEBUG_EVENT
)
62 zlog_debug ("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf
->name
);
64 for (ALL_LIST_ELEMENTS (zebrad
.client_list
, node
, nnode
, client
))
65 zsend_vrf_delete (client
, zvrf
);
69 zebra_vrf_update_all (struct zserv
*client
)
74 for (iter
= vrf_first (); iter
!= VRF_ITER_INVALID
; iter
= vrf_next (iter
))
76 if ((vrf
= vrf_iter2vrf (iter
)) && vrf
->vrf_id
)
77 zsend_vrf_add (client
, vrf_info_lookup (vrf
->vrf_id
));
81 /* Callback upon creating a new VRF. */
83 zebra_vrf_new (vrf_id_t vrf_id
, const char *name
, void **info
)
85 struct zebra_vrf
*zvrf
= *info
;
87 if (IS_ZEBRA_DEBUG_EVENT
)
88 zlog_info ("ZVRF %s with id %u", name
, vrf_id
);
92 zvrf
= zebra_vrf_list_lookup_by_name (name
);
95 zvrf
= zebra_vrf_alloc (vrf_id
, name
);
96 zvrf
->zns
= zebra_ns_lookup (NS_DEFAULT
); /* Point to the global (single) NS */
98 router_id_init (zvrf
);
99 listnode_add_sort (zvrf_list
, zvrf
);
103 *info
= (void *)zvrf
;
104 router_id_init (zvrf
);
108 if (zvrf
->vrf_id
== VRF_UNKNOWN
)
109 zvrf
->vrf_id
= vrf_id
;
115 * Moving an interface amongst different vrf's
116 * causes the interface to get a new ifindex
117 * so we need to find static routes with
118 * the old ifindex and replace with new
119 * ifindex to insert back into the table
122 zebra_vrf_static_route_interface_fixup (struct interface
*ifp
)
126 struct zebra_vrf
*zvrf
= zebra_vrf_lookup (ifp
->vrf_id
);
127 struct route_table
*stable
= NULL
;
128 struct route_node
*rn
= NULL
;
129 struct static_route
*si
= NULL
;
134 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
136 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
138 stable
= zvrf
->stable
[afi
][safi
];
140 for (rn
= route_top (stable
); rn
; rn
= route_next (rn
))
145 if ((strcmp (si
->ifname
, ifp
->name
) == 0) &&
146 (si
->ifindex
!= ifp
->ifindex
))
148 si
->ifindex
= ifp
->ifindex
;
149 static_install_route (afi
, safi
, &rn
->p
, si
);
158 /* Callback upon enabling a VRF. */
160 zebra_vrf_enable (vrf_id_t vrf_id
, const char *name
, void **info
)
162 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*) (*info
);
163 struct route_table
*stable
= NULL
;
164 struct route_node
*rn
= NULL
;
165 struct static_route
*si
= NULL
;
166 struct interface
*ifp
= NULL
;
172 zebra_vrf_add_update (zvrf
);
174 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
176 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
178 stable
= zvrf
->stable
[afi
][safi
];
181 for (rn
= route_top (stable
); rn
; rn
= route_next (rn
))
189 ifp
= if_lookup_by_name_vrf (si
->ifname
, si
->vrf_id
);
191 si
->ifindex
= ifp
->ifindex
;
195 static_install_route (afi
, safi
, &rn
->p
, si
);
204 /* Callback upon disabling a VRF. */
206 zebra_vrf_disable (vrf_id_t vrf_id
, const char *name
, void **info
)
208 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)(*info
);
209 struct route_table
*stable
= NULL
;
210 struct route_node
*rn
= NULL
;
214 if (IS_ZEBRA_DEBUG_KERNEL
)
215 zlog_debug ("VRF %s id %u is now disabled.",
216 zvrf
->name
, zvrf
->vrf_id
);
218 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
220 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
222 stable
= zvrf
->stable
[afi
][safi
];
225 for (rn
= route_top (stable
); rn
; rn
= route_next (rn
))
228 static_uninstall_route(afi
, safi
, &rn
->p
, rn
->info
);
237 zebra_vrf_delete (vrf_id_t vrf_id
, const char *name
, void **info
)
239 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*) (*info
);
243 zebra_vrf_delete_update (zvrf
);
245 rib_close_table (zvrf
->table
[AFI_IP
][SAFI_UNICAST
]);
246 rib_close_table (zvrf
->table
[AFI_IP6
][SAFI_UNICAST
]);
248 list_delete_all_node (zvrf
->rid_all_sorted_list
);
249 list_delete_all_node (zvrf
->rid_lo_sorted_list
);
251 zvrf
->vrf_id
= VRF_UNKNOWN
;
257 /* Lookup the routing table in a VRF based on both VRF-Id and table-id.
258 * NOTE: Table-id is relevant only in the Default VRF.
261 zebra_vrf_table_with_table_id (afi_t afi
, safi_t safi
,
262 vrf_id_t vrf_id
, u_int32_t table_id
)
264 struct route_table
*table
= NULL
;
266 if (afi
>= AFI_MAX
|| safi
>= SAFI_MAX
)
269 if (vrf_id
== VRF_DEFAULT
)
271 if (table_id
== RT_TABLE_MAIN
||
272 table_id
== zebrad
.rtm_table_default
)
273 table
= zebra_vrf_table (afi
, safi
, vrf_id
);
275 table
= zebra_vrf_other_route_table (afi
, table_id
, vrf_id
);
278 table
= zebra_vrf_table (afi
, safi
, vrf_id
);
284 * Create a routing table for the specific AFI/SAFI in the given VRF.
287 zebra_vrf_table_create (struct zebra_vrf
*zvrf
, afi_t afi
, safi_t safi
)
289 rib_table_info_t
*info
;
290 struct route_table
*table
;
292 assert (!zvrf
->table
[afi
][safi
]);
294 table
= route_table_init ();
295 zvrf
->table
[afi
][safi
] = table
;
297 info
= XCALLOC (MTYPE_RIB_TABLE_INFO
, sizeof (*info
));
304 /* Allocate new zebra VRF. */
306 zebra_vrf_alloc (vrf_id_t vrf_id
, const char *name
)
308 struct zebra_vrf
*zvrf
;
310 zvrf
= XCALLOC (MTYPE_ZEBRA_VRF
, sizeof (struct zebra_vrf
));
312 /* Allocate routing table and static table. */
313 zebra_vrf_table_create (zvrf
, AFI_IP
, SAFI_UNICAST
);
314 zebra_vrf_table_create (zvrf
, AFI_IP6
, SAFI_UNICAST
);
315 zvrf
->stable
[AFI_IP
][SAFI_UNICAST
] = route_table_init ();
316 zvrf
->stable
[AFI_IP6
][SAFI_UNICAST
] = route_table_init ();
317 zebra_vrf_table_create (zvrf
, AFI_IP
, SAFI_MULTICAST
);
318 zebra_vrf_table_create (zvrf
, AFI_IP6
, SAFI_MULTICAST
);
319 zvrf
->stable
[AFI_IP
][SAFI_MULTICAST
] = route_table_init ();
320 zvrf
->stable
[AFI_IP6
][SAFI_MULTICAST
] = route_table_init ();
322 zvrf
->rnh_table
[AFI_IP
] = route_table_init();
323 zvrf
->rnh_table
[AFI_IP6
] = route_table_init();
325 zvrf
->import_check_table
[AFI_IP
] = route_table_init();
326 zvrf
->import_check_table
[AFI_IP6
] = route_table_init();
329 zvrf
->vrf_id
= vrf_id
;
333 strncpy (zvrf
->name
, name
, strlen(name
));
334 zvrf
->name
[strlen(name
)] = '\0';
337 zebra_mpls_init_tables (zvrf
);
342 /* Lookup VRF by identifier. */
344 zebra_vrf_lookup (vrf_id_t vrf_id
)
346 return vrf_info_lookup (vrf_id
);
349 /* Lookup the zvrf in the zvrf_list. */
351 zebra_vrf_list_lookup_by_name (const char *name
)
353 struct listnode
*node
;
354 struct zebra_vrf
*zvrf
;
357 name
= VRF_DEFAULT_NAME
;
359 for (ALL_LIST_ELEMENTS_RO (zvrf_list
, node
, zvrf
))
361 if (strcmp(name
, zvrf
->name
) == 0)
367 /* Lookup the routing table in an enabled VRF. */
369 zebra_vrf_table (afi_t afi
, safi_t safi
, vrf_id_t vrf_id
)
371 struct zebra_vrf
*zvrf
= vrf_info_lookup (vrf_id
);
376 if (afi
>= AFI_MAX
|| safi
>= SAFI_MAX
)
379 return zvrf
->table
[afi
][safi
];
382 /* Lookup the static routing table in a VRF. */
384 zebra_vrf_static_table (afi_t afi
, safi_t safi
, struct zebra_vrf
*zvrf
)
389 if (afi
>= AFI_MAX
|| safi
>= SAFI_MAX
)
392 return zvrf
->stable
[afi
][safi
];
396 zebra_vrf_other_route_table (afi_t afi
, u_int32_t table_id
, vrf_id_t vrf_id
)
398 struct zebra_vrf
*zvrf
;
399 rib_table_info_t
*info
;
400 struct route_table
*table
;
402 zvrf
= vrf_info_lookup (vrf_id
);
409 if (table_id
>= ZEBRA_KERNEL_TABLE_MAX
)
412 if ((vrf_id
== VRF_DEFAULT
) && (table_id
!= RT_TABLE_MAIN
) && (table_id
!= zebrad
.rtm_table_default
))
414 if (zvrf
->other_table
[afi
][table_id
] == NULL
)
416 table
= route_table_init();
417 info
= XCALLOC (MTYPE_RIB_TABLE_INFO
, sizeof (*info
));
420 info
->safi
= SAFI_UNICAST
;
422 zvrf
->other_table
[afi
][table_id
] = table
;
425 return (zvrf
->other_table
[afi
][table_id
]);
428 return zvrf
->table
[afi
][SAFI_UNICAST
];
431 /* Zebra VRF initialization. */
433 zebra_vrf_init (void)
435 vrf_add_hook (VRF_NEW_HOOK
, zebra_vrf_new
);
436 vrf_add_hook (VRF_ENABLE_HOOK
, zebra_vrf_enable
);
437 vrf_add_hook (VRF_DISABLE_HOOK
, zebra_vrf_disable
);
438 vrf_add_hook (VRF_DELETE_HOOK
, zebra_vrf_delete
);
440 zvrf_list
= list_new ();