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