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