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