]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_vrf.c
lib: Rework vrf_get
[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
27 #include "zebra/debug.h"
28 #include "zebra/zserv.h"
29 #include "zebra/rib.h"
30 #include "zebra/zebra_vrf.h"
31 #include "zebra/router-id.h"
32
33 extern struct zebra_t zebrad;
34
35 /* VRF information update. */
36 static void
37 zebra_vrf_add_update (struct zebra_vrf *zvrf)
38 {
39 struct listnode *node, *nnode;
40 struct zserv *client;
41
42 if (IS_ZEBRA_DEBUG_EVENT)
43 zlog_debug ("MESSAGE: ZEBRA_VRF_ADD %s", zvrf->name);
44
45 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
46 zsend_vrf_add (client, zvrf);
47 }
48
49 static void
50 zebra_vrf_delete_update (struct zebra_vrf *zvrf)
51 {
52 struct listnode *node, *nnode;
53 struct zserv *client;
54
55 if (IS_ZEBRA_DEBUG_EVENT)
56 zlog_debug ("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf->name);
57
58 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
59 zsend_vrf_delete (client, zvrf);
60 }
61
62 void
63 zebra_vrf_update_all (struct zserv *client)
64 {
65 struct vrf *vrf;
66 vrf_iter_t iter;
67
68 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
69 {
70 if ((vrf = vrf_iter2vrf (iter)) && vrf->vrf_id)
71 zsend_vrf_add (client, vrf_info_lookup (vrf->vrf_id));
72 }
73 }
74
75 /* Callback upon creating a new VRF. */
76 static int
77 zebra_vrf_new (vrf_id_t vrf_id, const char *name, void **info)
78 {
79 struct zebra_vrf *zvrf = *info;
80
81 zlog_info ("ZVRF %s with id %u", name, vrf_id);
82
83 if (! zvrf)
84 {
85 zvrf = zebra_vrf_alloc (vrf_id, name);
86 zvrf->zns = zebra_ns_lookup (NS_DEFAULT); /* Point to the global (single) NS */
87 *info = (void *)zvrf;
88 router_id_init (zvrf);
89 }
90
91 if (zvrf->vrf_id == VRF_UNKNOWN)
92 zvrf->vrf_id = vrf_id;
93
94 return 0;
95 }
96
97 /* Callback upon enabling a VRF. */
98 static int
99 zebra_vrf_enable (vrf_id_t vrf_id, const char *name, void **info)
100 {
101 struct zebra_vrf *zvrf = (struct zebra_vrf *) (*info);
102
103 assert (zvrf);
104
105 zebra_vrf_add_update (zvrf);
106
107 return 0;
108 }
109
110 /* Callback upon disabling a VRF. */
111 static int
112 zebra_vrf_disable (vrf_id_t vrf_id, const char *name, void **info)
113 {
114 struct zebra_vrf *zvrf = (struct zebra_vrf *)(*info);
115
116 if (IS_ZEBRA_DEBUG_KERNEL)
117 zlog_debug ("VRF %s id %u is now disabled.",
118 zvrf->name, zvrf->vrf_id);
119
120 return 0;
121 }
122
123 static int
124 zebra_vrf_delete (vrf_id_t vrf_id, const char *name, void **info)
125 {
126 struct zebra_vrf *zvrf = (struct zebra_vrf *) (*info);
127
128 assert (zvrf);
129
130 zebra_vrf_delete_update (zvrf);
131
132 rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
133 rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
134
135 list_delete_all_node (zvrf->rid_all_sorted_list);
136 list_delete_all_node (zvrf->rid_lo_sorted_list);
137
138 XFREE (MTYPE_ZEBRA_VRF, zvrf);
139
140 return 0;
141 }
142
143 /* Lookup the routing table in a VRF based on both VRF-Id and table-id.
144 * NOTE: Table-id is relevant only in the Default VRF.
145 */
146 struct route_table *
147 zebra_vrf_table_with_table_id (afi_t afi, safi_t safi,
148 vrf_id_t vrf_id, u_int32_t table_id)
149 {
150 struct route_table *table = NULL;
151
152 if (afi >= AFI_MAX || safi >= SAFI_MAX)
153 return NULL;
154
155 if (vrf_id == VRF_DEFAULT)
156 {
157 if (table_id == RT_TABLE_MAIN ||
158 table_id == zebrad.rtm_table_default)
159 table = zebra_vrf_table (afi, safi, vrf_id);
160 else
161 table = zebra_vrf_other_route_table (afi, table_id, vrf_id);
162 }
163 else
164 table = zebra_vrf_table (afi, safi, vrf_id);
165
166 return table;
167 }
168
169 /*
170 * Create a routing table for the specific AFI/SAFI in the given VRF.
171 */
172 static void
173 zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi)
174 {
175 rib_table_info_t *info;
176 struct route_table *table;
177
178 assert (!zvrf->table[afi][safi]);
179
180 table = route_table_init ();
181 zvrf->table[afi][safi] = table;
182
183 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
184 info->zvrf = zvrf;
185 info->afi = afi;
186 info->safi = safi;
187 table->info = info;
188 }
189
190 /* Allocate new zebra VRF. */
191 struct zebra_vrf *
192 zebra_vrf_alloc (vrf_id_t vrf_id, const char *name)
193 {
194 struct zebra_vrf *zvrf;
195
196 zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf));
197
198 /* Allocate routing table and static table. */
199 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_UNICAST);
200 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_UNICAST);
201 zvrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
202 zvrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
203 zebra_vrf_table_create (zvrf, AFI_IP, SAFI_MULTICAST);
204 zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_MULTICAST);
205 zvrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
206 zvrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
207
208 zvrf->rnh_table[AFI_IP] = route_table_init();
209 zvrf->rnh_table[AFI_IP6] = route_table_init();
210
211 zvrf->import_check_table[AFI_IP] = route_table_init();
212 zvrf->import_check_table[AFI_IP6] = route_table_init();
213
214 /* Set VRF ID */
215 zvrf->vrf_id = vrf_id;
216
217 if (name)
218 {
219 strncpy (zvrf->name, name, strlen(name));
220 zvrf->name[strlen(name)] = '\0';
221 }
222
223 return zvrf;
224 }
225
226 /* Lookup VRF by identifier. */
227 struct zebra_vrf *
228 zebra_vrf_lookup (vrf_id_t vrf_id)
229 {
230 return vrf_info_lookup (vrf_id);
231 }
232
233 /* Lookup the routing table in an enabled VRF. */
234 struct route_table *
235 zebra_vrf_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
236 {
237 struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
238
239 if (!zvrf)
240 return NULL;
241
242 if (afi >= AFI_MAX || safi >= SAFI_MAX)
243 return NULL;
244
245 return zvrf->table[afi][safi];
246 }
247
248 /* Lookup the static routing table in a VRF. */
249 struct route_table *
250 zebra_vrf_static_table (afi_t afi, safi_t safi, struct zebra_vrf *zvrf)
251 {
252 if (!zvrf)
253 return NULL;
254
255 if (afi >= AFI_MAX || safi >= SAFI_MAX)
256 return NULL;
257
258 return zvrf->stable[afi][safi];
259 }
260
261 struct route_table *
262 zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id, vrf_id_t vrf_id)
263 {
264 struct zebra_vrf *zvrf;
265 rib_table_info_t *info;
266 struct route_table *table;
267
268 zvrf = vrf_info_lookup (vrf_id);
269 if (! zvrf)
270 return NULL;
271
272 if(afi >= AFI_MAX)
273 return NULL;
274
275 if (table_id >= ZEBRA_KERNEL_TABLE_MAX)
276 return NULL;
277
278 if ((vrf_id == VRF_DEFAULT) && (table_id != RT_TABLE_MAIN) && (table_id != zebrad.rtm_table_default))
279 {
280 if (zvrf->other_table[afi][table_id] == NULL)
281 {
282 table = route_table_init();
283 info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
284 info->zvrf = zvrf;
285 info->afi = afi;
286 info->safi = SAFI_UNICAST;
287 table->info = info;
288 zvrf->other_table[afi][table_id] = table;
289 }
290
291 return (zvrf->other_table[afi][table_id]);
292 }
293
294 return zvrf->table[afi][SAFI_UNICAST];
295 }
296
297 /* Zebra VRF initialization. */
298 void
299 zebra_vrf_init (void)
300 {
301 vrf_add_hook (VRF_NEW_HOOK, zebra_vrf_new);
302 vrf_add_hook (VRF_ENABLE_HOOK, zebra_vrf_enable);
303 vrf_add_hook (VRF_DISABLE_HOOK, zebra_vrf_disable);
304 vrf_add_hook (VRF_DELETE_HOOK, zebra_vrf_delete);
305
306 vrf_init ();
307 }