]> git.proxmox.com Git - mirror_frr.git/blame - lib/vrf.c
lib, zebra: move "struct vrf" to be a lib module
[mirror_frr.git] / lib / vrf.c
CommitLineData
b72ede27
FL
1/*
2 * VRF functions.
3 * Copyright (C) 2014 6WIND S.A.
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2, or (at your
10 * option) any later version.
11 *
12 * GNU Zebra 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
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "vrf.h"
26#include "prefix.h"
27#include "table.h"
28#include "log.h"
29#include "memory.h"
30
31struct vrf
32{
33 /* Identifier, same as the vector index */
34 vrf_id_t vrf_id;
35 /* Name */
36 char *name;
37
38 /* User data */
39 void *info;
40};
41
42/* Holding VRF hooks */
43struct vrf_master
44{
45 int (*vrf_new_hook) (vrf_id_t, void **);
46 int (*vrf_delete_hook) (vrf_id_t, void **);
47} vrf_master = {0,};
48
49/* VRF table */
50struct route_table *vrf_table = NULL;
51
52/* Build the table key */
53static void
54vrf_build_key (vrf_id_t vrf_id, struct prefix *p)
55{
56 p->family = AF_INET;
57 p->prefixlen = IPV4_MAX_BITLEN;
58 p->u.prefix4.s_addr = vrf_id;
59}
60
61/* Get a VRF. If not found, create one. */
62static struct vrf *
63vrf_get (vrf_id_t vrf_id)
64{
65 struct prefix p;
66 struct route_node *rn;
67 struct vrf *vrf;
68
69 vrf_build_key (vrf_id, &p);
70 rn = route_node_get (vrf_table, &p);
71 if (rn->info)
72 {
73 vrf = (struct vrf *)rn->info;
74 route_unlock_node (rn); /* get */
75 return vrf;
76 }
77
78 vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
79 vrf->vrf_id = vrf_id;
80 rn->info = vrf;
81
82 zlog_info ("VRF %u is created.", vrf_id);
83
84 if (vrf_master.vrf_new_hook)
85 (*vrf_master.vrf_new_hook) (vrf_id, &vrf->info);
86
87 return vrf;
88}
89
90/* Delete a VRF. This is called in vrf_terminate(). */
91static void
92vrf_delete (struct vrf *vrf)
93{
94 zlog_info ("VRF %u is to be deleted.", vrf->vrf_id);
95
96 if (vrf_master.vrf_delete_hook)
97 (*vrf_master.vrf_delete_hook) (vrf->vrf_id, &vrf->info);
98
99 if (vrf->name)
100 XFREE (MTYPE_VRF_NAME, vrf->name);
101
102 XFREE (MTYPE_VRF, vrf);
103}
104
105/* Look up a VRF by identifier. */
106static struct vrf *
107vrf_lookup (vrf_id_t vrf_id)
108{
109 struct prefix p;
110 struct route_node *rn;
111 struct vrf *vrf = NULL;
112
113 vrf_build_key (vrf_id, &p);
114 rn = route_node_lookup (vrf_table, &p);
115 if (rn)
116 {
117 vrf = (struct vrf *)rn->info;
118 route_unlock_node (rn); /* lookup */
119 }
120 return vrf;
121}
122
123/* Add a VRF hook. Please add hooks before calling vrf_init(). */
124void
125vrf_add_hook (int type, int (*func)(vrf_id_t, void **))
126{
127 switch (type) {
128 case VRF_NEW_HOOK:
129 vrf_master.vrf_new_hook = func;
130 break;
131 case VRF_DELETE_HOOK:
132 vrf_master.vrf_delete_hook = func;
133 break;
134 default:
135 break;
136 }
137}
138
139/* Return the iterator of the first VRF. */
140vrf_iter_t
141vrf_first (void)
142{
143 struct route_node *rn;
144
145 for (rn = route_top (vrf_table); rn; rn = route_next (rn))
146 if (rn->info)
147 {
148 route_unlock_node (rn); /* top/next */
149 return (vrf_iter_t)rn;
150 }
151 return VRF_ITER_INVALID;
152}
153
154/* Return the next VRF iterator to the given iterator. */
155vrf_iter_t
156vrf_next (vrf_iter_t iter)
157{
158 struct route_node *rn = NULL;
159
160 /* Lock it first because route_next() will unlock it. */
161 if (iter != VRF_ITER_INVALID)
162 rn = route_next (route_lock_node ((struct route_node *)iter));
163
164 for (; rn; rn = route_next (rn))
165 if (rn->info)
166 {
167 route_unlock_node (rn); /* next */
168 return (vrf_iter_t)rn;
169 }
170 return VRF_ITER_INVALID;
171}
172
173/* Return the VRF iterator of the given VRF ID. If it does not exist,
174 * the iterator of the next existing VRF is returned. */
175vrf_iter_t
176vrf_iterator (vrf_id_t vrf_id)
177{
178 struct prefix p;
179 struct route_node *rn;
180
181 vrf_build_key (vrf_id, &p);
182 rn = route_node_get (vrf_table, &p);
183 if (rn->info)
184 {
185 /* OK, the VRF exists. */
186 route_unlock_node (rn); /* get */
187 return (vrf_iter_t)rn;
188 }
189
190 /* Find the next VRF. */
191 for (rn = route_next (rn); rn; rn = route_next (rn))
192 if (rn->info)
193 {
194 route_unlock_node (rn); /* next */
195 return (vrf_iter_t)rn;
196 }
197
198 return VRF_ITER_INVALID;
199}
200
201/* Obtain the VRF ID from the given VRF iterator. */
202vrf_id_t
203vrf_iter2id (vrf_iter_t iter)
204{
205 struct route_node *rn = (struct route_node *) iter;
206 return (rn && rn->info) ? ((struct vrf *)rn->info)->vrf_id : VRF_DEFAULT;
207}
208
209/* Obtain the data pointer from the given VRF iterator. */
210void *
211vrf_iter2info (vrf_iter_t iter)
212{
213 struct route_node *rn = (struct route_node *) iter;
214 return (rn && rn->info) ? ((struct vrf *)rn->info)->info : NULL;
215}
216
217/* Get the data pointer of the specified VRF. If not found, create one. */
218void *
219vrf_info_get (vrf_id_t vrf_id)
220{
221 struct vrf *vrf = vrf_get (vrf_id);
222 return vrf->info;
223}
224
225/* Look up the data pointer of the specified VRF. */
226void *
227vrf_info_lookup (vrf_id_t vrf_id)
228{
229 struct vrf *vrf = vrf_lookup (vrf_id);
230 return vrf ? vrf->info : NULL;
231}
232
233/* Initialize VRF module. */
234void
235vrf_init (void)
236{
237 struct vrf *default_vrf;
238
239 /* Allocate VRF table. */
240 vrf_table = route_table_init ();
241
242 /* The default VRF always exists. */
243 default_vrf = vrf_get (VRF_DEFAULT);
244 if (!default_vrf)
245 {
246 zlog_err ("vrf_init: failed to create the default VRF!");
247 exit (1);
248 }
249
250 /* Set the default VRF name. */
251 default_vrf->name = XSTRDUP (MTYPE_VRF_NAME, "Default-IP-Routing-Table");
252}
253
254/* Terminate VRF module. */
255void
256vrf_terminate (void)
257{
258 struct route_node *rn;
259 struct vrf *vrf;
260
261 for (rn = route_top (vrf_table); rn; rn = route_next (rn))
262 if ((vrf = rn->info) != NULL)
263 vrf_delete (vrf);
264
265 route_table_finish (vrf_table);
266 vrf_table = NULL;
267}
268