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