]> git.proxmox.com Git - mirror_frr.git/blob - staticd/static_routes.c
staticd: Start the addition of a staticd
[mirror_frr.git] / staticd / static_routes.c
1 /*
2 * STATICd - vrf code
3 * Copyright (C) 2018 Cumulus Networks, Inc.
4 * Donald Sharp
5 *
6 * FRR is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * FRR is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 #include <zebra.h>
21
22 #include <lib/nexthop.h>
23 #include <lib/memory.h>
24 #include <lib/srcdest_table.h>
25 #include <lib/if.h>
26 #include <lib/vty.h>
27 #include <lib/vrf.h>
28 #include <lib/memory.h>
29
30 #include "static_vrf.h"
31 #include "static_routes.h"
32 #include "static_memory.h"
33 #include "static_zebra.h"
34
35 /* Install static route into rib. */
36 static void static_install_route(struct route_node *rn, safi_t safi)
37 {
38 struct static_route *si;
39
40 for (si = rn->info; si; si = si->next)
41 static_zebra_nht_register(si, true);
42
43 si = rn->info;
44 if (si)
45 static_zebra_route_add(rn, si->vrf_id, safi, true);
46
47 }
48
49 /* Uninstall static route from RIB. */
50 static void static_uninstall_route(vrf_id_t vrf_id, safi_t safi,
51 struct route_node *rn)
52 {
53
54 if (rn->info)
55 static_zebra_route_add(rn, vrf_id, safi, true);
56 else
57 static_zebra_route_add(rn, vrf_id, safi, false);
58 }
59
60 int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
61 struct prefix_ipv6 *src_p, union g_addr *gate,
62 const char *ifname, enum static_blackhole_type bh_type,
63 route_tag_t tag, uint8_t distance, struct static_vrf *svrf,
64 struct static_vrf *nh_svrf,
65 struct static_nh_label *snh_label,
66 uint32_t table_id)
67 {
68 struct route_node *rn;
69 struct static_route *si;
70 struct static_route *pp;
71 struct static_route *cp;
72 struct static_route *update = NULL;
73 struct route_table *stable = svrf->stable[afi][safi];
74
75 if (!stable)
76 return -1;
77
78 if (!gate && (type == STATIC_IPV4_GATEWAY
79 || type == STATIC_IPV4_GATEWAY_IFNAME
80 || type == STATIC_IPV6_GATEWAY
81 || type == STATIC_IPV6_GATEWAY_IFNAME))
82 return -1;
83
84 if (!ifname
85 && (type == STATIC_IFNAME || type == STATIC_IPV4_GATEWAY_IFNAME
86 || type == STATIC_IPV6_GATEWAY_IFNAME))
87 return -1;
88
89 /* Lookup static route prefix. */
90 rn = srcdest_rnode_get(stable, p, src_p);
91
92 /* Do nothing if there is a same static route. */
93 for (si = rn->info; si; si = si->next) {
94 if (type == si->type
95 && (!gate
96 || ((afi == AFI_IP
97 && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
98 || (afi == AFI_IP6
99 && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
100 && (!strcmp(ifname ? ifname : "", si->ifname))) {
101 if ((distance == si->distance) && (tag == si->tag)
102 && (table_id == si->table_id)
103 && !memcmp(&si->snh_label, snh_label,
104 sizeof(struct static_nh_label))
105 && si->bh_type == bh_type) {
106 route_unlock_node(rn);
107 return 0;
108 }
109 update = si;
110 }
111 }
112
113 /* Distance or tag or label changed, delete existing first. */
114 if (update)
115 static_delete_route(afi, safi, type, p, src_p, gate, ifname,
116 update->tag, update->distance, svrf,
117 &update->snh_label, table_id);
118
119 /* Make new static route structure. */
120 si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route));
121
122 si->type = type;
123 si->distance = distance;
124 si->bh_type = bh_type;
125 si->tag = tag;
126 si->vrf_id = svrf->vrf->vrf_id;
127 si->nh_vrf_id = nh_svrf->vrf->vrf_id;
128 strcpy(si->nh_vrfname, nh_svrf->vrf->name);
129 si->table_id = table_id;
130
131 if (ifname)
132 strlcpy(si->ifname, ifname, sizeof(si->ifname));
133 si->ifindex = IFINDEX_INTERNAL;
134
135 switch (type) {
136 case STATIC_IPV4_GATEWAY:
137 case STATIC_IPV4_GATEWAY_IFNAME:
138 si->addr.ipv4 = gate->ipv4;
139 break;
140 case STATIC_IPV6_GATEWAY:
141 case STATIC_IPV6_GATEWAY_IFNAME:
142 si->addr.ipv6 = gate->ipv6;
143 break;
144 case STATIC_IFNAME:
145 break;
146 }
147
148 /* Save labels, if any. */
149 memcpy(&si->snh_label, snh_label, sizeof(struct static_nh_label));
150
151 /*
152 * Add new static route information to the tree with sort by
153 * distance value and gateway address.
154 */
155 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) {
156 if (si->distance < cp->distance)
157 break;
158 if (si->distance > cp->distance)
159 continue;
160 if (si->type == STATIC_IPV4_GATEWAY
161 && cp->type == STATIC_IPV4_GATEWAY) {
162 if (ntohl(si->addr.ipv4.s_addr)
163 < ntohl(cp->addr.ipv4.s_addr))
164 break;
165 if (ntohl(si->addr.ipv4.s_addr)
166 > ntohl(cp->addr.ipv4.s_addr))
167 continue;
168 }
169 }
170
171 /* Make linked list. */
172 if (pp)
173 pp->next = si;
174 else
175 rn->info = si;
176 if (cp)
177 cp->prev = si;
178 si->prev = pp;
179 si->next = cp;
180
181 /* check whether interface exists in system & install if it does */
182 if (!ifname)
183 static_install_route(rn, safi);
184 else {
185 struct interface *ifp;
186
187 ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id);
188 if (ifp && ifp->ifindex != IFINDEX_INTERNAL) {
189 si->ifindex = ifp->ifindex;
190 static_install_route(rn, safi);
191 } else
192 zlog_warn("Static Route using %s interface not installed because the interface does not exist in specified vrf",
193 ifname);
194 }
195
196 return 1;
197 }
198
199 int static_delete_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
200 struct prefix_ipv6 *src_p, union g_addr *gate,
201 const char *ifname, route_tag_t tag, uint8_t distance,
202 struct static_vrf *svrf,
203 struct static_nh_label *snh_label,
204 uint32_t table_id)
205 {
206 struct route_node *rn;
207 struct static_route *si;
208 struct route_table *stable;
209
210 /* Lookup table. */
211 stable = static_vrf_static_table(afi, safi, svrf);
212 if (!stable)
213 return -1;
214
215 /* Lookup static route prefix. */
216 rn = srcdest_rnode_lookup(stable, p, src_p);
217 if (!rn)
218 return 0;
219
220 /* Find same static route is the tree */
221 for (si = rn->info; si; si = si->next)
222 if (type == si->type
223 && (!gate
224 || ((afi == AFI_IP
225 && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
226 || (afi == AFI_IP6
227 && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
228 && (!strcmp(ifname ? ifname : "", si->ifname))
229 && (!tag || (tag == si->tag))
230 && (table_id == si->table_id)
231 && (!snh_label->num_labels
232 || !memcmp(&si->snh_label, snh_label,
233 sizeof(struct static_nh_label))))
234 break;
235
236 /* Can't find static route. */
237 if (!si) {
238 route_unlock_node(rn);
239 return 0;
240 }
241
242 static_zebra_nht_register(si, false);
243
244 /* Unlink static route from linked list. */
245 if (si->prev)
246 si->prev->next = si->next;
247 else
248 rn->info = si->next;
249 if (si->next)
250 si->next->prev = si->prev;
251
252 /*
253 * If we have other si nodes then route replace
254 * else delete the route
255 */
256 static_uninstall_route(si->vrf_id, safi, rn);
257 route_unlock_node(rn);
258
259 /* Free static route configuration. */
260 XFREE(MTYPE_STATIC_ROUTE, si);
261
262 route_unlock_node(rn);
263
264 return 1;
265 }
266
267 static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi,
268 safi_t safi)
269 {
270 struct route_table *stable;
271 struct route_node *rn;
272 struct static_route *si;
273 struct vrf *vrf;
274
275 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
276 struct static_vrf *svrf;
277
278 svrf = vrf->info;
279
280 stable = static_vrf_static_table(afi, safi, svrf);
281 if (!stable)
282 continue;
283
284 for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) {
285 for (si = rn->info; si; si = si->next) {
286 if (!si->ifname[0])
287 continue;
288 if (up) {
289 if (strcmp(si->ifname, ifp->name))
290 continue;
291 si->ifindex = ifp->ifindex;
292 } else {
293 if (si->ifindex != ifp->ifindex)
294 continue;
295 si->ifindex = IFINDEX_INTERNAL;
296 }
297 }
298
299 static_install_route(rn, safi);
300 }
301 }
302 }
303
304 /*
305 * This function looks at a svrf's stable and notices if any of the
306 * nexthops we are using are part of the vrf coming up.
307 * If we are using them then cleanup the nexthop vrf id
308 * to be the new value and then re-installs them
309 *
310 *
311 * stable -> The table we are looking at.
312 * svrf -> The newly changed vrf.
313 * afi -> The afi to look at
314 * safi -> the safi to look at
315 */
316 static void static_fixup_vrf(struct static_vrf *svrf,
317 struct route_table *stable, afi_t afi, safi_t safi)
318 {
319 struct route_node *rn;
320 struct static_route *si;
321 struct interface *ifp;
322 bool install;
323
324 for (rn = route_top(stable); rn; rn = route_next(rn)) {
325 install = false;
326 for (si = rn->info; si; si = si->next) {
327 if (strcmp(svrf->vrf->name, si->nh_vrfname) != 0)
328 continue;
329
330 si->nh_vrf_id = svrf->vrf->vrf_id;
331 install = true;
332 if (si->ifindex) {
333 ifp = if_lookup_by_name(si->ifname,
334 si->nh_vrf_id);
335 if (ifp)
336 si->ifindex = ifp->ifindex;
337 else
338 continue;
339 }
340 }
341
342 if (install)
343 static_install_route(rn, safi);
344 }
345 }
346
347 /*
348 * This function enables static routes in a svrf as it
349 * is coming up. It sets the new vrf_id as appropriate.
350 *
351 * svrf -> The svrf that is being brought up and enabled by the kernel
352 * stable -> The stable we are looking at.
353 * afi -> the afi in question
354 * safi -> the safi in question
355 */
356 static void static_enable_vrf(struct static_vrf *svrf,
357 struct route_table *stable,
358 afi_t afi, safi_t safi)
359 {
360 struct route_node *rn;
361 struct static_route *si;
362 struct interface *ifp;
363 struct vrf *vrf = svrf->vrf;
364 bool install;
365
366 for (rn = route_top(stable); rn; rn = route_next(rn)) {
367 install = false;
368 for (si = rn->info; si; si = si->next) {
369 si->vrf_id = vrf->vrf_id;
370 if (si->ifindex) {
371 ifp = if_lookup_by_name(si->ifname,
372 si->nh_vrf_id);
373 if (ifp)
374 si->ifindex = ifp->ifindex;
375 else
376 continue;
377 }
378 install = true;
379 }
380
381 if (install)
382 static_install_route(rn, safi);
383 }
384 }
385
386 /*
387 * When a vrf is being enabled by the kernel, go through all the
388 * static routes in the system that use this vrf (both nexthops vrfs
389 * and the routes vrf )
390 *
391 * enable_svrf -> the vrf being enabled
392 */
393 void static_fixup_vrf_ids(struct static_vrf *enable_svrf)
394 {
395 struct route_table *stable;
396 struct vrf *vrf;
397 afi_t afi;
398 safi_t safi;
399
400 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
401 struct static_vrf *svrf;
402
403 svrf = vrf->info;
404 /* Install any static routes configured for this VRF. */
405 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
406 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
407 stable = svrf->stable[afi][safi];
408 if (!stable)
409 continue;
410
411 static_fixup_vrf(enable_svrf, stable,
412 afi, safi);
413
414 if (enable_svrf == svrf)
415 static_enable_vrf(svrf, stable,
416 afi, safi);
417 }
418 }
419 }
420 }
421
422 /*
423 * Look at the specified stable and if any of the routes in
424 * this table are using the svrf as the nexthop, uninstall
425 * those routes.
426 *
427 * svrf -> the vrf being disabled
428 * stable -> the table we need to look at.
429 * afi -> the afi in question
430 * safi -> the safi in question
431 */
432 static void static_cleanup_vrf(struct static_vrf *svrf,
433 struct route_table *stable,
434 afi_t afi, safi_t safi)
435 {
436 struct route_node *rn;
437 struct static_route *si;
438
439 for (rn = route_top(stable); rn; rn = route_next(rn)) {
440 for (si = rn->info; si; si = si->next) {
441 if (strcmp(svrf->vrf->name, si->nh_vrfname) != 0)
442 continue;
443
444 static_uninstall_route(si->vrf_id, safi, rn);
445 }
446 }
447 }
448
449 /*
450 * Look at all static routes in this table and uninstall
451 * them.
452 *
453 * stable -> The table to uninstall from
454 * afi -> The afi in question
455 * safi -> the safi in question
456 */
457 static void static_disable_vrf(struct route_table *stable,
458 afi_t afi, safi_t safi)
459 {
460 struct route_node *rn;
461 struct static_route *si;
462
463 for (rn = route_top(stable); rn; rn = route_next(rn))
464 for (si = rn->info; si; si = si->next)
465 static_uninstall_route(si->vrf_id, safi, rn);
466 }
467
468 /*
469 * When the disable_svrf is shutdown by the kernel, we call
470 * this function and it cleans up all static routes using
471 * this vrf as a nexthop as well as all static routes
472 * in it's stables.
473 *
474 * disable_svrf - The vrf being disabled
475 */
476 void static_cleanup_vrf_ids(struct static_vrf *disable_svrf)
477 {
478 struct vrf *vrf;
479 afi_t afi;
480 safi_t safi;
481
482 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
483 struct static_vrf *svrf;
484
485 svrf = vrf->info;
486
487 /* Uninstall any static routes configured for this VRF. */
488 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
489 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
490 struct route_table *stable;
491
492 stable = svrf->stable[afi][safi];
493 if (!stable)
494 continue;
495
496 static_cleanup_vrf(disable_svrf, stable,
497 afi, safi);
498
499 if (disable_svrf == svrf)
500 static_disable_vrf(stable, afi, safi);
501 }
502 }
503 }
504 }
505
506 /* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
507 void static_ifindex_update(struct interface *ifp, bool up)
508 {
509 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_UNICAST);
510 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_MULTICAST);
511 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_UNICAST);
512 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_MULTICAST);
513 }