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