]> git.proxmox.com Git - mirror_frr.git/blame - staticd/static_routes.c
Revert "tools: stop zebra daemon last"
[mirror_frr.git] / staticd / static_routes.c
CommitLineData
7e24fdf3 1/*
8d5cbee9 2 * STATICd - route code
7e24fdf3
DS
3 * Copyright (C) 2018 Cumulus Networks, Inc.
4 * Donald Sharp
5 *
8d5cbee9
DS
6 * This program 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 Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
7e24fdf3 10 *
8d5cbee9
DS
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
7e24fdf3
DS
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
b2f6ab67 30#include "printfrr.h"
31
7e24fdf3
DS
32#include "static_vrf.h"
33#include "static_routes.h"
7e24fdf3 34#include "static_zebra.h"
b2f6ab67 35#include "static_debug.h"
7e24fdf3 36
8392606e
DL
37DEFINE_MGROUP(STATIC, "staticd");
38
39DEFINE_MTYPE_STATIC(STATIC, STATIC_ROUTE, "Static Route Info");
40DEFINE_MTYPE_STATIC(STATIC, STATIC_PATH, "Static Path");
41DEFINE_MTYPE_STATIC(STATIC, STATIC_NEXTHOP, "Static Nexthop");
42
43void zebra_stable_node_cleanup(struct route_table *table,
44 struct route_node *node)
45{
46 struct static_nexthop *nh;
47 struct static_path *pn;
48 struct static_route_info *si;
49 struct route_table *src_table;
50 struct route_node *src_node;
51 struct static_path *src_pn;
52 struct static_route_info *src_si;
53
54 si = node->info;
55
56 if (si) {
57 frr_each_safe(static_path_list, &si->path_list, pn) {
58 frr_each_safe(static_nexthop_list, &pn->nexthop_list,
59 nh) {
60 static_nexthop_list_del(&pn->nexthop_list, nh);
61 XFREE(MTYPE_STATIC_NEXTHOP, nh);
62 }
63 static_path_list_del(&si->path_list, pn);
64 XFREE(MTYPE_STATIC_PATH, pn);
65 }
66
67 /* clean up for dst table */
68 src_table = srcdest_srcnode_table(node);
69 if (src_table) {
70 /* This means the route_node is part of the top
71 * hierarchy and refers to a destination prefix.
72 */
73 for (src_node = route_top(src_table); src_node;
74 src_node = route_next(src_node)) {
75 src_si = src_node->info;
76
77 frr_each_safe(static_path_list,
78 &src_si->path_list, src_pn) {
79 frr_each_safe(static_nexthop_list,
80 &src_pn->nexthop_list,
81 nh) {
82 static_nexthop_list_del(
83 &src_pn->nexthop_list,
84 nh);
85 XFREE(MTYPE_STATIC_NEXTHOP, nh);
86 }
87 static_path_list_del(&src_si->path_list,
88 src_pn);
89 XFREE(MTYPE_STATIC_PATH, src_pn);
90 }
91
92 XFREE(MTYPE_STATIC_ROUTE, src_node->info);
93 }
94 }
95
96 XFREE(MTYPE_STATIC_ROUTE, node->info);
97 }
98}
7e24fdf3 99
88fa5104 100/* Install static path into rib. */
4067e951 101void static_install_path(struct static_path *pn)
88fa5104 102{
103 struct static_nexthop *nh;
7e24fdf3 104
88fa5104 105 frr_each(static_nexthop_list, &pn->nexthop_list, nh)
4067e951 106 static_zebra_nht_register(nh, true);
7e24fdf3 107
4067e951
IR
108 if (static_nexthop_list_count(&pn->nexthop_list))
109 static_zebra_route_add(pn, true);
7e24fdf3
DS
110}
111
88fa5104 112/* Uninstall static path from RIB. */
4067e951 113static void static_uninstall_path(struct static_path *pn)
7e24fdf3 114{
88fa5104 115 if (static_nexthop_list_count(&pn->nexthop_list))
4067e951 116 static_zebra_route_add(pn, true);
7e24fdf3 117 else
4067e951 118 static_zebra_route_add(pn, false);
7e24fdf3
DS
119}
120
88fa5104 121struct route_node *static_add_route(afi_t afi, safi_t safi, struct prefix *p,
122 struct prefix_ipv6 *src_p,
123 struct static_vrf *svrf)
7e24fdf3
DS
124{
125 struct route_node *rn;
88fa5104 126 struct static_route_info *si;
7e24fdf3
DS
127 struct route_table *stable = svrf->stable[afi][safi];
128
aaddf974 129 assert(stable);
7e24fdf3
DS
130
131 /* Lookup static route prefix. */
132 rn = srcdest_rnode_get(stable, p, src_p);
133
88fa5104 134 si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route_info));
4067e951
IR
135
136 si->svrf = svrf;
137 si->safi = safi;
138 static_path_list_init(&(si->path_list));
88fa5104 139
140 rn->info = si;
141
88fa5104 142 return rn;
143}
144
145/* To delete the srcnodes */
4067e951 146static void static_del_src_route(struct route_node *rn)
88fa5104 147{
148 struct static_path *pn;
149 struct static_route_info *si;
150
151 si = rn->info;
152
153 frr_each_safe(static_path_list, &si->path_list, pn) {
4067e951 154 static_del_path(pn);
88fa5104 155 }
156
157 XFREE(MTYPE_STATIC_ROUTE, rn->info);
158 route_unlock_node(rn);
88fa5104 159}
160
4067e951 161void static_del_route(struct route_node *rn)
88fa5104 162{
163 struct static_path *pn;
164 struct static_route_info *si;
165 struct route_table *src_table;
166 struct route_node *src_node;
167
168 si = rn->info;
169
170 frr_each_safe(static_path_list, &si->path_list, pn) {
4067e951 171 static_del_path(pn);
88fa5104 172 }
173
174 /* clean up for dst table */
175 src_table = srcdest_srcnode_table(rn);
176 if (src_table) {
177 /* This means the route_node is part of the top hierarchy
178 * and refers to a destination prefix.
179 */
180 for (src_node = route_top(src_table); src_node;
181 src_node = route_next(src_node)) {
4067e951 182 static_del_src_route(src_node);
7e24fdf3
DS
183 }
184 }
88fa5104 185 XFREE(MTYPE_STATIC_ROUTE, rn->info);
186 route_unlock_node(rn);
88fa5104 187}
188
9ccaa12d
IR
189bool static_add_nexthop_validate(const char *nh_vrf_name,
190 enum static_nh_type type,
88fa5104 191 struct ipaddr *ipaddr)
192{
ddd45515
IR
193 struct vrf *vrf;
194
195 vrf = vrf_lookup_by_name(nh_vrf_name);
196 if (!vrf)
197 return true;
198
88fa5104 199 switch (type) {
200 case STATIC_IPV4_GATEWAY:
201 case STATIC_IPV4_GATEWAY_IFNAME:
1e9044be
DL
202 if (if_address_is_local(&ipaddr->ipaddr_v4, AF_INET,
203 vrf->vrf_id))
88fa5104 204 return false;
205 break;
206 case STATIC_IPV6_GATEWAY:
207 case STATIC_IPV6_GATEWAY_IFNAME:
1e9044be
DL
208 if (if_address_is_local(&ipaddr->ipaddr_v6, AF_INET6,
209 vrf->vrf_id))
88fa5104 210 return false;
211 break;
212 default:
213 break;
214 }
215
216 return true;
217}
218
ef4b6b22 219struct static_path *static_add_path(struct route_node *rn, uint32_t table_id,
220 uint8_t distance)
88fa5104 221{
222 struct static_path *pn;
223 struct static_route_info *si;
224
225 route_lock_node(rn);
226
227 /* Make new static route structure. */
228 pn = XCALLOC(MTYPE_STATIC_PATH, sizeof(struct static_path));
229
4067e951 230 pn->rn = rn;
88fa5104 231 pn->distance = distance;
ef4b6b22 232 pn->table_id = table_id;
88fa5104 233 static_nexthop_list_init(&(pn->nexthop_list));
234
235 si = rn->info;
236 static_path_list_add_head(&(si->path_list), pn);
237
238 return pn;
239}
240
4067e951 241void static_del_path(struct static_path *pn)
88fa5104 242{
4067e951 243 struct route_node *rn = pn->rn;
88fa5104 244 struct static_route_info *si;
245 struct static_nexthop *nh;
246
247 si = rn->info;
248
249 static_path_list_del(&si->path_list, pn);
250
251 frr_each_safe(static_nexthop_list, &pn->nexthop_list, nh) {
4067e951 252 static_delete_nexthop(nh);
88fa5104 253 }
254
255 route_unlock_node(rn);
256
257 XFREE(MTYPE_STATIC_PATH, pn);
258}
259
4067e951 260struct static_nexthop *static_add_nexthop(struct static_path *pn,
9ccaa12d 261 enum static_nh_type type,
4067e951
IR
262 struct ipaddr *ipaddr,
263 const char *ifname,
264 const char *nh_vrf, uint32_t color)
88fa5104 265{
4067e951 266 struct route_node *rn = pn->rn;
88fa5104 267 struct static_nexthop *nh;
268 struct static_vrf *nh_svrf;
269 struct interface *ifp;
270 struct static_nexthop *cp;
271
272 route_lock_node(rn);
273
eec2baa0 274 nh_svrf = static_vrf_lookup_by_name(nh_vrf);
7e24fdf3
DS
275
276 /* Make new static route structure. */
88fa5104 277 nh = XCALLOC(MTYPE_STATIC_NEXTHOP, sizeof(struct static_nexthop));
278
4067e951
IR
279 nh->pn = pn;
280
88fa5104 281 nh->type = type;
065276ae 282 nh->color = color;
88fa5104 283
7ea5c534 284 if (nh->type == STATIC_BLACKHOLE)
285 nh->bh_type = STATIC_BLACKHOLE_NULL;
286
eec2baa0
IR
287 nh->nh_vrf_id = nh_svrf ? nh_svrf->vrf->vrf_id : VRF_UNKNOWN;
288 strlcpy(nh->nh_vrfname, nh_vrf, sizeof(nh->nh_vrfname));
7e24fdf3
DS
289
290 if (ifname)
88fa5104 291 strlcpy(nh->ifname, ifname, sizeof(nh->ifname));
292 nh->ifindex = IFINDEX_INTERNAL;
7e24fdf3
DS
293
294 switch (type) {
295 case STATIC_IPV4_GATEWAY:
296 case STATIC_IPV4_GATEWAY_IFNAME:
88fa5104 297 nh->addr.ipv4 = ipaddr->ipaddr_v4;
7e24fdf3
DS
298 break;
299 case STATIC_IPV6_GATEWAY:
300 case STATIC_IPV6_GATEWAY_IFNAME:
88fa5104 301 nh->addr.ipv6 = ipaddr->ipaddr_v6;
7e24fdf3 302 break;
88fa5104 303 default:
7e24fdf3
DS
304 break;
305 }
7e24fdf3
DS
306 /*
307 * Add new static route information to the tree with sort by
88fa5104 308 * gateway address.
7e24fdf3 309 */
88fa5104 310 frr_each(static_nexthop_list, &pn->nexthop_list, cp) {
311 if (nh->type == STATIC_IPV4_GATEWAY
7e24fdf3 312 && cp->type == STATIC_IPV4_GATEWAY) {
88fa5104 313 if (ntohl(nh->addr.ipv4.s_addr)
7e24fdf3
DS
314 < ntohl(cp->addr.ipv4.s_addr))
315 break;
88fa5104 316 if (ntohl(nh->addr.ipv4.s_addr)
7e24fdf3
DS
317 > ntohl(cp->addr.ipv4.s_addr))
318 continue;
319 }
320 }
88fa5104 321 static_nexthop_list_add_after(&(pn->nexthop_list), cp, nh);
7e24fdf3 322
eec2baa0 323 if (nh->nh_vrf_id == VRF_UNKNOWN) {
b2f6ab67 324 zlog_warn(
325 "Static Route to %pFX not installed currently because dependent config not fully available",
326 &rn->p);
88fa5104 327 return nh;
b2f6ab67 328 }
7e24fdf3
DS
329
330 /* check whether interface exists in system & install if it does */
88fa5104 331 switch (nh->type) {
a6e85307
DS
332 case STATIC_IPV4_GATEWAY:
333 case STATIC_IPV6_GATEWAY:
7ea5c534 334 case STATIC_BLACKHOLE:
a6e85307
DS
335 break;
336 case STATIC_IPV4_GATEWAY_IFNAME:
337 case STATIC_IPV6_GATEWAY_IFNAME:
32c0a2dd 338 case STATIC_IFNAME:
eec2baa0 339 ifp = if_lookup_by_name(ifname, nh->nh_vrf_id);
a6e85307 340 if (ifp && ifp->ifindex != IFINDEX_INTERNAL)
88fa5104 341 nh->ifindex = ifp->ifindex;
a6e85307 342 else
88fa5104 343 zlog_warn(
344 "Static Route using %s interface not installed because the interface does not exist in specified vrf",
345 ifname);
a6e85307 346 break;
7e24fdf3
DS
347 }
348
88fa5104 349 return nh;
7e24fdf3
DS
350}
351
4067e951 352void static_install_nexthop(struct static_nexthop *nh)
7e24fdf3 353{
4067e951
IR
354 struct static_path *pn = nh->pn;
355 struct route_node *rn = pn->rn;
88fa5104 356 struct interface *ifp;
7e24fdf3 357
eec2baa0 358 if (nh->nh_vrf_id == VRF_UNKNOWN) {
b2f6ab67 359 char nexthop_str[NEXTHOP_STR];
360
361 static_get_nh_str(nh, nexthop_str, sizeof(nexthop_str));
362 DEBUGD(&static_dbg_route,
363 "Static Route %pFX not installed for %s vrf %s is unknown",
eec2baa0 364 &rn->p, nexthop_str, nh->nh_vrfname);
88fa5104 365 return;
b2f6ab67 366 }
88fa5104 367
368 /* check whether interface exists in system & install if it does */
369 switch (nh->type) {
370 case STATIC_IPV4_GATEWAY:
371 case STATIC_IPV6_GATEWAY:
f75d3925 372 static_zebra_nht_register(nh, true);
88fa5104 373 break;
374 case STATIC_IPV4_GATEWAY_IFNAME:
375 case STATIC_IPV6_GATEWAY_IFNAME:
f75d3925 376 static_zebra_nht_register(nh, true);
88fa5104 377 break;
378 case STATIC_BLACKHOLE:
4067e951 379 static_install_path(pn);
88fa5104 380 break;
381 case STATIC_IFNAME:
4067e951 382 ifp = if_lookup_by_name(nh->ifname, nh->nh_vrf_id);
88fa5104 383 if (ifp && ifp->ifindex != IFINDEX_INTERNAL)
4067e951 384 static_install_path(pn);
88fa5104 385
386 break;
7e24fdf3 387 }
88fa5104 388}
7e24fdf3 389
4067e951 390void static_delete_nexthop(struct static_nexthop *nh)
88fa5104 391{
4067e951
IR
392 struct static_path *pn = nh->pn;
393 struct route_node *rn = pn->rn;
394
88fa5104 395 static_nexthop_list_del(&(pn->nexthop_list), nh);
396
eec2baa0 397 if (nh->nh_vrf_id == VRF_UNKNOWN)
88fa5104 398 goto EXIT;
7e24fdf3 399
4067e951 400 static_zebra_nht_register(nh, false);
7e24fdf3
DS
401 /*
402 * If we have other si nodes then route replace
403 * else delete the route
404 */
4067e951 405 static_uninstall_path(pn);
7e24fdf3 406
88fa5104 407EXIT:
7e24fdf3 408 route_unlock_node(rn);
88fa5104 409 /* Free static route configuration. */
410 XFREE(MTYPE_STATIC_NEXTHOP, nh);
7e24fdf3
DS
411}
412
7aa6f9cd 413static void static_ifindex_update_nh(struct interface *ifp, bool up,
414 struct route_node *rn,
415 struct static_path *pn,
416 struct static_nexthop *nh,
417 struct static_vrf *svrf, safi_t safi)
418{
419 if (!nh->ifname[0])
420 return;
421 if (up) {
422 if (strcmp(nh->ifname, ifp->name))
423 return;
096f7609 424 if (nh->nh_vrf_id != ifp->vrf->vrf_id)
7aa6f9cd 425 return;
426 nh->ifindex = ifp->ifindex;
427 } else {
428 if (nh->ifindex != ifp->ifindex)
429 return;
096f7609 430 if (nh->nh_vrf_id != ifp->vrf->vrf_id)
7aa6f9cd 431 return;
432 nh->ifindex = IFINDEX_INTERNAL;
433 }
434
4067e951 435 static_install_path(pn);
7aa6f9cd 436}
437
7e24fdf3
DS
438static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi,
439 safi_t safi)
440{
441 struct route_table *stable;
442 struct route_node *rn;
88fa5104 443 struct static_nexthop *nh;
444 struct static_path *pn;
7e24fdf3 445 struct vrf *vrf;
88fa5104 446 struct static_route_info *si;
7e24fdf3
DS
447
448 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
449 struct static_vrf *svrf;
450
451 svrf = vrf->info;
452
453 stable = static_vrf_static_table(afi, safi, svrf);
454 if (!stable)
455 continue;
7e24fdf3 456 for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) {
88fa5104 457 si = static_route_info_from_rnode(rn);
458 if (!si)
459 continue;
460 frr_each(static_path_list, &si->path_list, pn) {
461 frr_each(static_nexthop_list,
462 &pn->nexthop_list, nh) {
7aa6f9cd 463 static_ifindex_update_nh(ifp, up, rn,
464 pn, nh, svrf,
465 safi);
7e24fdf3 466 }
0b70cb10 467 }
7e24fdf3
DS
468 }
469 }
470}
471
472/*
473 * This function looks at a svrf's stable and notices if any of the
474 * nexthops we are using are part of the vrf coming up.
475 * If we are using them then cleanup the nexthop vrf id
476 * to be the new value and then re-installs them
477 *
478 *
479 * stable -> The table we are looking at.
480 * svrf -> The newly changed vrf.
481 * afi -> The afi to look at
482 * safi -> the safi to look at
483 */
484static void static_fixup_vrf(struct static_vrf *svrf,
485 struct route_table *stable, afi_t afi, safi_t safi)
486{
487 struct route_node *rn;
88fa5104 488 struct static_nexthop *nh;
7e24fdf3 489 struct interface *ifp;
88fa5104 490 struct static_path *pn;
491 struct static_route_info *si;
7e24fdf3
DS
492
493 for (rn = route_top(stable); rn; rn = route_next(rn)) {
88fa5104 494 si = static_route_info_from_rnode(rn);
495 if (!si)
496 continue;
497 frr_each(static_path_list, &si->path_list, pn) {
498 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
499 if (strcmp(svrf->vrf->name, nh->nh_vrfname)
500 != 0)
7e24fdf3 501 continue;
7e24fdf3 502
88fa5104 503 nh->nh_vrf_id = svrf->vrf->vrf_id;
504 nh->nh_registered = false;
505 if (nh->ifindex) {
506 ifp = if_lookup_by_name(nh->ifname,
507 nh->nh_vrf_id);
508 if (ifp)
509 nh->ifindex = ifp->ifindex;
510 else
511 continue;
512 }
513
4067e951 514 static_install_path(pn);
88fa5104 515 }
0b70cb10 516 }
7e24fdf3
DS
517 }
518}
519
520/*
521 * This function enables static routes in a svrf as it
522 * is coming up. It sets the new vrf_id as appropriate.
523 *
524 * svrf -> The svrf that is being brought up and enabled by the kernel
525 * stable -> The stable we are looking at.
526 * afi -> the afi in question
527 * safi -> the safi in question
528 */
529static void static_enable_vrf(struct static_vrf *svrf,
88fa5104 530 struct route_table *stable, afi_t afi,
531 safi_t safi)
7e24fdf3
DS
532{
533 struct route_node *rn;
88fa5104 534 struct static_nexthop *nh;
7e24fdf3 535 struct interface *ifp;
88fa5104 536 struct static_path *pn;
537 struct static_route_info *si;
7e24fdf3
DS
538
539 for (rn = route_top(stable); rn; rn = route_next(rn)) {
88fa5104 540 si = static_route_info_from_rnode(rn);
541 if (!si)
542 continue;
543 frr_each(static_path_list, &si->path_list, pn) {
544 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
545 if (nh->ifindex) {
546 ifp = if_lookup_by_name(nh->ifname,
547 nh->nh_vrf_id);
548 if (ifp)
549 nh->ifindex = ifp->ifindex;
550 else
551 continue;
552 }
cb3f5e18
IR
553 if (nh->nh_vrf_id == VRF_UNKNOWN)
554 continue;
4067e951 555 static_install_path(pn);
7e24fdf3 556 }
0b70cb10 557 }
7e24fdf3
DS
558 }
559}
560
561/*
562 * When a vrf is being enabled by the kernel, go through all the
563 * static routes in the system that use this vrf (both nexthops vrfs
564 * and the routes vrf )
565 *
566 * enable_svrf -> the vrf being enabled
567 */
568void static_fixup_vrf_ids(struct static_vrf *enable_svrf)
569{
570 struct route_table *stable;
571 struct vrf *vrf;
572 afi_t afi;
573 safi_t safi;
574
575 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
576 struct static_vrf *svrf;
577
578 svrf = vrf->info;
579 /* Install any static routes configured for this VRF. */
f18ba3cd
DS
580 FOREACH_AFI_SAFI (afi, safi) {
581 stable = svrf->stable[afi][safi];
582 if (!stable)
583 continue;
7e24fdf3 584
f18ba3cd 585 static_fixup_vrf(enable_svrf, stable, afi, safi);
7e24fdf3 586
f18ba3cd
DS
587 if (enable_svrf == svrf)
588 static_enable_vrf(svrf, stable, afi, safi);
7e24fdf3
DS
589 }
590 }
591}
592
593/*
594 * Look at the specified stable and if any of the routes in
595 * this table are using the svrf as the nexthop, uninstall
596 * those routes.
597 *
598 * svrf -> the vrf being disabled
599 * stable -> the table we need to look at.
600 * afi -> the afi in question
601 * safi -> the safi in question
602 */
603static void static_cleanup_vrf(struct static_vrf *svrf,
604 struct route_table *stable,
605 afi_t afi, safi_t safi)
606{
607 struct route_node *rn;
88fa5104 608 struct static_nexthop *nh;
609 struct static_path *pn;
610 struct static_route_info *si;
7e24fdf3
DS
611
612 for (rn = route_top(stable); rn; rn = route_next(rn)) {
88fa5104 613 si = static_route_info_from_rnode(rn);
614 if (!si)
615 continue;
616 frr_each(static_path_list, &si->path_list, pn) {
617 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
618 if (strcmp(svrf->vrf->name, nh->nh_vrfname)
619 != 0)
620 continue;
7e24fdf3 621
4067e951 622 static_uninstall_path(pn);
88fa5104 623 }
7e24fdf3
DS
624 }
625 }
626}
627
628/*
629 * Look at all static routes in this table and uninstall
630 * them.
631 *
632 * stable -> The table to uninstall from
633 * afi -> The afi in question
634 * safi -> the safi in question
635 */
636static void static_disable_vrf(struct route_table *stable,
637 afi_t afi, safi_t safi)
638{
639 struct route_node *rn;
88fa5104 640 struct static_nexthop *nh;
641 struct static_path *pn;
88fa5104 642 struct static_route_info *si;
7e24fdf3 643
88fa5104 644 for (rn = route_top(stable); rn; rn = route_next(rn)) {
645 si = static_route_info_from_rnode(rn);
646 if (!si)
647 continue;
648 frr_each(static_path_list, &si->path_list, pn) {
649 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
4067e951 650 static_uninstall_path(pn);
88fa5104 651 }
652 }
653 }
7e24fdf3
DS
654}
655
656/*
657 * When the disable_svrf is shutdown by the kernel, we call
658 * this function and it cleans up all static routes using
659 * this vrf as a nexthop as well as all static routes
660 * in it's stables.
661 *
662 * disable_svrf - The vrf being disabled
663 */
664void static_cleanup_vrf_ids(struct static_vrf *disable_svrf)
665{
666 struct vrf *vrf;
667 afi_t afi;
668 safi_t safi;
669
670 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
671 struct static_vrf *svrf;
672
673 svrf = vrf->info;
674
675 /* Uninstall any static routes configured for this VRF. */
f18ba3cd
DS
676 FOREACH_AFI_SAFI (afi, safi) {
677 struct route_table *stable;
7e24fdf3 678
f18ba3cd
DS
679 stable = svrf->stable[afi][safi];
680 if (!stable)
681 continue;
7e24fdf3 682
f18ba3cd 683 static_cleanup_vrf(disable_svrf, stable, afi, safi);
7e24fdf3 684
f18ba3cd
DS
685 if (disable_svrf == svrf)
686 static_disable_vrf(stable, afi, safi);
7e24fdf3
DS
687 }
688 }
689}
690
a9be49bc
DS
691/*
692 * This function enables static routes when an interface it relies
693 * on in a different vrf is coming up.
694 *
a9be49bc
DS
695 * stable -> The stable we are looking at.
696 * ifp -> interface coming up
697 * afi -> the afi in question
698 * safi -> the safi in question
699 */
700static void static_fixup_intf_nh(struct route_table *stable,
701 struct interface *ifp,
702 afi_t afi, safi_t safi)
703{
704 struct route_node *rn;
88fa5104 705 struct static_nexthop *nh;
706 struct static_path *pn;
707 struct static_route_info *si;
708
a9be49bc 709 for (rn = route_top(stable); rn; rn = route_next(rn)) {
88fa5104 710 si = static_route_info_from_rnode(rn);
711 if (!si)
712 continue;
713 frr_each(static_path_list, &si->path_list, pn) {
714 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
096f7609 715 if (nh->nh_vrf_id != ifp->vrf->vrf_id)
88fa5104 716 continue;
a9be49bc 717
88fa5104 718 if (nh->ifindex != ifp->ifindex)
719 continue;
a9be49bc 720
4067e951 721 static_install_path(pn);
88fa5104 722 }
a9be49bc
DS
723 }
724 }
725}
726
727/*
728 * This function enables static routes that rely on an interface in
729 * a different vrf when that interface comes up.
730 */
731void static_install_intf_nh(struct interface *ifp)
732{
733 struct route_table *stable;
734 struct vrf *vrf;
735 afi_t afi;
736 safi_t safi;
737
738 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
739 struct static_vrf *svrf = vrf->info;
740
741 /* Not needed if same vrf since happens naturally */
096f7609 742 if (vrf->vrf_id == ifp->vrf->vrf_id)
a9be49bc
DS
743 continue;
744
745 /* Install any static routes configured for this interface. */
f18ba3cd
DS
746 FOREACH_AFI_SAFI (afi, safi) {
747 stable = svrf->stable[afi][safi];
748 if (!stable)
749 continue;
a9be49bc 750
f18ba3cd 751 static_fixup_intf_nh(stable, ifp, afi, safi);
a9be49bc
DS
752 }
753 }
754}
755
7e24fdf3
DS
756/* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
757void static_ifindex_update(struct interface *ifp, bool up)
758{
759 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_UNICAST);
760 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_MULTICAST);
761 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_UNICAST);
762 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_MULTICAST);
763}
88fa5104 764
9ccaa12d 765void static_get_nh_type(enum static_nh_type stype, char *type, size_t size)
88fa5104 766{
767 switch (stype) {
768 case STATIC_IFNAME:
769 strlcpy(type, "ifindex", size);
770 break;
771 case STATIC_IPV4_GATEWAY:
772 strlcpy(type, "ip4", size);
773 break;
774 case STATIC_IPV4_GATEWAY_IFNAME:
775 strlcpy(type, "ip4-ifindex", size);
776 break;
777 case STATIC_BLACKHOLE:
778 strlcpy(type, "blackhole", size);
779 break;
780 case STATIC_IPV6_GATEWAY:
781 strlcpy(type, "ip6", size);
782 break;
783 case STATIC_IPV6_GATEWAY_IFNAME:
784 strlcpy(type, "ip6-ifindex", size);
785 break;
786 };
787}
788
789struct stable_info *static_get_stable_info(struct route_node *rn)
790{
791 struct route_table *table;
792
793 table = srcdest_rnode_table(rn);
794 return table->info;
795}
796
b2f6ab67 797void static_get_nh_str(struct static_nexthop *nh, char *nexthop, size_t size)
798{
799 switch (nh->type) {
800 case STATIC_IFNAME:
801 snprintfrr(nexthop, size, "ifindex : %s", nh->ifname);
802 break;
803 case STATIC_IPV4_GATEWAY:
804 snprintfrr(nexthop, size, "ip4 : %pI4", &nh->addr.ipv4);
805 break;
806 case STATIC_IPV4_GATEWAY_IFNAME:
807 snprintfrr(nexthop, size, "ip4-ifindex : %pI4 : %s",
808 &nh->addr.ipv4, nh->ifname);
809 break;
810 case STATIC_BLACKHOLE:
811 snprintfrr(nexthop, size, "blackhole : %d", nh->bh_type);
812 break;
813 case STATIC_IPV6_GATEWAY:
814 snprintfrr(nexthop, size, "ip6 : %pI6", &nh->addr.ipv6);
815 break;
816 case STATIC_IPV6_GATEWAY_IFNAME:
817 snprintfrr(nexthop, size, "ip6-ifindex : %pI6 : %s",
818 &nh->addr.ipv6, nh->ifname);
819 break;
820 };
821}