]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_static.c
*: use clang's 'ForEachMacros' format style option
[mirror_frr.git] / zebra / zebra_static.c
CommitLineData
28f6dde8
DS
1/*
2 * Static Routing Information code
3 * Copyright (C) 2016 Cumulus Networks
4 * Donald Sharp
5 *
6 * This file is part of Quagga.
7 *
8 * Quagga is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
11 * later version.
12 *
13 * Quagga is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
896014f4
DL
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28f6dde8
DS
21 */
22#include <zebra.h>
23
24#include <lib/nexthop.h>
25#include <lib/memory.h>
c423229b 26#include <lib/srcdest_table.h>
c3c04063 27#include <lib/if.h>
28f6dde8 28
82f97584 29#include "vty.h"
28f6dde8
DS
30#include "zebra/debug.h"
31#include "zebra/rib.h"
32#include "zebra/zserv.h"
33#include "zebra/zebra_vrf.h"
34#include "zebra/zebra_static.h"
35#include "zebra/zebra_rnh.h"
36#include "zebra/redistribute.h"
4a1ab8e4 37#include "zebra/zebra_memory.h"
28f6dde8
DS
38
39/* Install static route into rib. */
d62a17ae 40void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
41 struct prefix_ipv6 *src_p, struct static_route *si)
28f6dde8 42{
d62a17ae 43 struct route_entry *re;
44 struct route_node *rn;
45 struct route_table *table;
46 struct prefix nh_p;
47 struct nexthop *nexthop = NULL;
9aabb2ea 48 enum blackhole_type bh_type = 0;
d62a17ae 49
50 /* Lookup table. */
51 table = zebra_vrf_table(afi, safi, si->vrf_id);
52 if (!table)
53 return;
54
55 memset(&nh_p, 0, sizeof(nh_p));
9aabb2ea
RW
56 if (si->type == STATIC_BLACKHOLE) {
57 switch (si->bh_type) {
58 case STATIC_BLACKHOLE_DROP:
59 case STATIC_BLACKHOLE_NULL:
60 bh_type = BLACKHOLE_NULL;
61 break;
62 case STATIC_BLACKHOLE_REJECT:
63 bh_type = BLACKHOLE_REJECT;
64 break;
65 }
66 }
d62a17ae 67
68 /* Lookup existing route */
69 rn = srcdest_rnode_get(table, p, src_p);
a2addae8 70 RNODE_FOREACH_RE (rn, re) {
d62a17ae 71 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
72 continue;
73
74 if (re->type == ZEBRA_ROUTE_STATIC
75 && re->distance == si->distance)
76 break;
77 }
78
79 if (re) {
80 /* if tag value changed , update old value in RIB */
81 if (re->tag != si->tag)
82 re->tag = si->tag;
83
84 /* Same distance static route is there. Update it with new
85 nexthop. */
86 route_unlock_node(rn);
87 switch (si->type) {
88 case STATIC_IPV4_GATEWAY:
89 nexthop = route_entry_nexthop_ipv4_add(
90 re, &si->addr.ipv4, NULL);
91 nh_p.family = AF_INET;
92 nh_p.prefixlen = IPV4_MAX_BITLEN;
93 nh_p.u.prefix4 = si->addr.ipv4;
94 zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
95 break;
23443030 96 case STATIC_IPV4_GATEWAY_IFNAME:
599186ad
RW
97 nexthop = route_entry_nexthop_ipv4_ifindex_add(
98 re, &si->addr.ipv4, NULL, si->ifindex);
99 break;
23443030 100 case STATIC_IFNAME:
d62a17ae 101 nexthop = route_entry_nexthop_ifindex_add(re,
102 si->ifindex);
103 break;
104 case STATIC_BLACKHOLE:
60466a63 105 nexthop = route_entry_nexthop_blackhole_add(
9aabb2ea 106 re, bh_type);
d62a17ae 107 break;
108 case STATIC_IPV6_GATEWAY:
109 nexthop = route_entry_nexthop_ipv6_add(re,
110 &si->addr.ipv6);
111 nh_p.family = AF_INET6;
112 nh_p.prefixlen = IPV6_MAX_BITLEN;
113 nh_p.u.prefix6 = si->addr.ipv6;
114 zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
115 break;
23443030 116 case STATIC_IPV6_GATEWAY_IFNAME:
d62a17ae 117 nexthop = route_entry_nexthop_ipv6_ifindex_add(
118 re, &si->addr.ipv6, si->ifindex);
119 break;
120 }
121 /* Update label(s), if present. */
122 if (si->snh_label.num_labels)
123 nexthop_add_labels(nexthop, ZEBRA_LSP_STATIC,
124 si->snh_label.num_labels,
125 &si->snh_label.label[0]);
126
127 if (IS_ZEBRA_DEBUG_RIB) {
128 char buf[INET6_ADDRSTRLEN];
129 if (IS_ZEBRA_DEBUG_RIB) {
130 inet_ntop(p->family, &p->u.prefix, buf,
131 INET6_ADDRSTRLEN);
132 zlog_debug(
133 "%u:%s/%d: Modifying route rn %p, re %p (type %d)",
134 si->vrf_id, buf, p->prefixlen, rn, re,
135 re->type);
136 }
137 }
138 /* Schedule route for processing or invoke NHT, as appropriate.
139 */
140 if (si->type == STATIC_IPV4_GATEWAY
141 || si->type == STATIC_IPV6_GATEWAY)
142 zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1,
143 RNH_NEXTHOP_TYPE, &nh_p);
144 else
145 rib_queue_add(rn);
146 } else {
147 /* This is new static route. */
148 re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
149
150 re->type = ZEBRA_ROUTE_STATIC;
151 re->instance = 0;
152 re->distance = si->distance;
153 re->metric = 0;
154 re->mtu = 0;
155 re->vrf_id = si->vrf_id;
156 re->table =
157 si->vrf_id
158 ? (zebra_vrf_lookup_by_id(si->vrf_id))->table_id
159 : zebrad.rtm_table_default;
160 re->nexthop_num = 0;
161 re->tag = si->tag;
162
163 switch (si->type) {
164 case STATIC_IPV4_GATEWAY:
165 nexthop = route_entry_nexthop_ipv4_add(
166 re, &si->addr.ipv4, NULL);
167 nh_p.family = AF_INET;
168 nh_p.prefixlen = IPV4_MAX_BITLEN;
169 nh_p.u.prefix4 = si->addr.ipv4;
170 zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
171 break;
23443030 172 case STATIC_IPV4_GATEWAY_IFNAME:
599186ad
RW
173 nexthop = route_entry_nexthop_ipv4_ifindex_add(
174 re, &si->addr.ipv4, NULL, si->ifindex);
175 break;
23443030 176 case STATIC_IFNAME:
d62a17ae 177 nexthop = route_entry_nexthop_ifindex_add(re,
178 si->ifindex);
179 break;
180 case STATIC_BLACKHOLE:
60466a63 181 nexthop = route_entry_nexthop_blackhole_add(
9aabb2ea 182 re, bh_type);
d62a17ae 183 break;
184 case STATIC_IPV6_GATEWAY:
185 nexthop = route_entry_nexthop_ipv6_add(re,
186 &si->addr.ipv6);
187 nh_p.family = AF_INET6;
188 nh_p.prefixlen = IPV6_MAX_BITLEN;
189 nh_p.u.prefix6 = si->addr.ipv6;
190 zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
191 break;
23443030 192 case STATIC_IPV6_GATEWAY_IFNAME:
d62a17ae 193 nexthop = route_entry_nexthop_ipv6_ifindex_add(
194 re, &si->addr.ipv6, si->ifindex);
195 break;
196 }
197 /* Update label(s), if present. */
198 if (si->snh_label.num_labels)
199 nexthop_add_labels(nexthop, ZEBRA_LSP_STATIC,
200 si->snh_label.num_labels,
201 &si->snh_label.label[0]);
202
d62a17ae 203 if (IS_ZEBRA_DEBUG_RIB) {
204 char buf[INET6_ADDRSTRLEN];
205 if (IS_ZEBRA_DEBUG_RIB) {
206 inet_ntop(p->family, &p->u.prefix, buf,
207 INET6_ADDRSTRLEN);
208 zlog_debug(
209 "%u:%s/%d: Inserting route rn %p, re %p (type %d)",
210 si->vrf_id, buf, p->prefixlen, rn, re,
211 re->type);
212 }
213 }
214 /* Link this re to the tree. Schedule for processing or invoke
215 * NHT,
216 * as appropriate.
217 */
218 if (si->type == STATIC_IPV4_GATEWAY
219 || si->type == STATIC_IPV6_GATEWAY) {
220 rib_addnode(rn, re, 0);
221 zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1,
222 RNH_NEXTHOP_TYPE, &nh_p);
223 } else
224 rib_addnode(rn, re, 1);
225 }
28f6dde8 226}
a22f3f5d 227
c3c04063
DL
228/* this works correctly with IFNAME<>IFINDEX because a static route on a
229 * non-active interface will have IFINDEX_INTERNAL and thus compare false
230 */
d62a17ae 231static int static_nexthop_same(struct nexthop *nexthop, struct static_route *si)
28f6dde8 232{
d62a17ae 233 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
234 && si->type == STATIC_BLACKHOLE)
235 return 1;
236
237 if (nexthop->type == NEXTHOP_TYPE_IPV4
238 && si->type == STATIC_IPV4_GATEWAY
239 && IPV4_ADDR_SAME(&nexthop->gate.ipv4, &si->addr.ipv4))
240 return 1;
599186ad 241 else if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
23443030 242 && si->type == STATIC_IPV4_GATEWAY_IFNAME
599186ad
RW
243 && IPV4_ADDR_SAME(&nexthop->gate.ipv4, &si->addr.ipv4)
244 && nexthop->ifindex == si->ifindex)
245 return 1;
d62a17ae 246 else if (nexthop->type == NEXTHOP_TYPE_IFINDEX
23443030 247 && si->type == STATIC_IFNAME
d62a17ae 248 && nexthop->ifindex == si->ifindex)
249 return 1;
250 else if (nexthop->type == NEXTHOP_TYPE_IPV6
251 && si->type == STATIC_IPV6_GATEWAY
252 && IPV6_ADDR_SAME(&nexthop->gate.ipv6, &si->addr.ipv6))
253 return 1;
254 else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
23443030 255 && si->type == STATIC_IPV6_GATEWAY_IFNAME
d62a17ae 256 && IPV6_ADDR_SAME(&nexthop->gate.ipv6, &si->addr.ipv6)
257 && nexthop->ifindex == si->ifindex)
258 return 1;
259
260 return 0;
28f6dde8
DS
261}
262
263/* Uninstall static route from RIB. */
d62a17ae 264void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p,
265 struct prefix_ipv6 *src_p, struct static_route *si)
28f6dde8 266{
d62a17ae 267 struct route_node *rn;
268 struct route_entry *re;
269 struct nexthop *nexthop;
270 struct route_table *table;
271 struct prefix nh_p;
272
273 /* Lookup table. */
274 table = zebra_vrf_table(afi, safi, si->vrf_id);
275 if (!table)
276 return;
277
278 /* Lookup existing route with type and distance. */
279 rn = srcdest_rnode_lookup(table, p, src_p);
280 if (!rn)
281 return;
282
a2addae8 283 RNODE_FOREACH_RE (rn, re) {
d62a17ae 284 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
285 continue;
286
287 if (re->type == ZEBRA_ROUTE_STATIC
288 && re->distance == si->distance && re->tag == si->tag)
289 break;
28f6dde8 290 }
d62a17ae 291
292 if (!re) {
293 route_unlock_node(rn);
294 return;
28f6dde8 295 }
28f6dde8 296
d62a17ae 297 /* Lookup nexthop. */
298 for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next)
299 if (static_nexthop_same(nexthop, si))
300 break;
301
302 /* Can't find nexthop. */
303 if (!nexthop) {
304 route_unlock_node(rn);
305 return;
28f6dde8 306 }
d62a17ae 307
308 /* Check nexthop. */
309 if (re->nexthop_num == 1)
310 rib_delnode(rn, re);
311 else {
312 /* Mark this nexthop as inactive and reinstall the route. Then,
313 * delete
314 * the nexthop. There is no need to re-evaluate the route for
315 * this
316 * scenario.
317 */
318 if (IS_ZEBRA_DEBUG_RIB) {
319 char buf[INET6_ADDRSTRLEN];
320 if (IS_ZEBRA_DEBUG_RIB) {
321 inet_ntop(p->family, &p->u.prefix, buf,
322 INET6_ADDRSTRLEN);
323 zlog_debug(
324 "%u:%s/%d: Modifying route rn %p, re %p (type %d)",
325 si->vrf_id, buf, p->prefixlen, rn, re,
326 re->type);
327 }
328 }
329 UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
330 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) {
331 /* If there are other active nexthops, do an update. */
332 if (re->nexthop_active_num > 1) {
333 /* Update route in kernel if it's in fib */
334 if (CHECK_FLAG(re->status,
335 ROUTE_ENTRY_SELECTED_FIB))
336 rib_install_kernel(rn, re, re);
337 /* Update redistribution if it's selected */
338 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
339 redistribute_update(
340 p, (struct prefix *)src_p, re,
341 NULL);
342 } else {
343 /* Remove from redistribute if selected route
344 * becomes inactive */
345 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
346 redistribute_delete(
347 p, (struct prefix *)src_p, re);
348 /* Remove from kernel if fib route becomes
349 * inactive */
350 if (CHECK_FLAG(re->status,
351 ROUTE_ENTRY_SELECTED_FIB))
352 rib_uninstall_kernel(rn, re);
353 }
354 }
355
356 if (afi == AFI_IP) {
357 /* Delete the nexthop and dereg from NHT */
358 nh_p.family = AF_INET;
359 nh_p.prefixlen = IPV4_MAX_BITLEN;
360 nh_p.u.prefix4 = nexthop->gate.ipv4;
361 } else {
362 nh_p.family = AF_INET6;
363 nh_p.prefixlen = IPV6_MAX_BITLEN;
364 nh_p.u.prefix6 = nexthop->gate.ipv6;
365 }
366 route_entry_nexthop_delete(re, nexthop);
367 zebra_deregister_rnh_static_nh(si->vrf_id, &nh_p, rn);
368 nexthop_free(nexthop);
28f6dde8 369 }
d62a17ae 370 /* Unlock node. */
371 route_unlock_node(rn);
28f6dde8
DS
372}
373
d62a17ae 374int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
375 struct prefix_ipv6 *src_p, union g_addr *gate,
9aabb2ea 376 const char *ifname, enum static_blackhole_type bh_type,
dc9ffce8 377 route_tag_t tag, u_char distance, struct zebra_vrf *zvrf,
a22f3f5d 378 struct static_nh_label *snh_label)
28f6dde8 379{
d62a17ae 380 struct route_node *rn;
381 struct static_route *si;
382 struct static_route *pp;
383 struct static_route *cp;
384 struct static_route *update = NULL;
385 struct route_table *stable = zvrf->stable[afi][safi];
386
387 if (!stable)
388 return -1;
389
599186ad
RW
390 if (!gate
391 && (type == STATIC_IPV4_GATEWAY
23443030 392 || type == STATIC_IPV4_GATEWAY_IFNAME
599186ad 393 || type == STATIC_IPV6_GATEWAY
23443030 394 || type == STATIC_IPV6_GATEWAY_IFNAME))
d62a17ae 395 return -1;
396
c3c04063 397 if (!ifname
23443030
DL
398 && (type == STATIC_IFNAME
399 || type == STATIC_IPV4_GATEWAY_IFNAME
400 || type == STATIC_IPV6_GATEWAY_IFNAME))
d62a17ae 401 return -1;
402
403 /* Lookup static route prefix. */
404 rn = srcdest_rnode_get(stable, p, src_p);
405
406 /* Do nothing if there is a same static route. */
407 for (si = rn->info; si; si = si->next) {
408 if (type == si->type
9d303b37 409 && (!gate || ((afi == AFI_IP
19aad877 410 && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
9d303b37
DL
411 || (afi == AFI_IP6
412 && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
c3c04063 413 && (!strcmp (ifname ? ifname : "", si->ifname))) {
d62a17ae 414 if ((distance == si->distance) && (tag == si->tag)
415 && !memcmp(&si->snh_label, snh_label,
416 sizeof(struct static_nh_label))
a8309422 417 && si->bh_type == bh_type) {
d62a17ae 418 route_unlock_node(rn);
419 return 0;
420 } else
421 update = si;
422 }
423 }
424
425 /* Distance or tag or label changed, delete existing first. */
426 if (update)
c3c04063 427 static_delete_route(afi, safi, type, p, src_p, gate, ifname,
d62a17ae 428 update->tag, update->distance, zvrf,
429 &update->snh_label);
430
431 /* Make new static route structure. */
432 si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route));
433
434 si->type = type;
435 si->distance = distance;
a8309422 436 si->bh_type = bh_type;
d62a17ae 437 si->tag = tag;
438 si->vrf_id = zvrf_id(zvrf);
c3c04063
DL
439 if (ifname)
440 strlcpy(si->ifname, ifname, sizeof(si->ifname));
441 si->ifindex = IFINDEX_INTERNAL;
d62a17ae 442
443 switch (type) {
444 case STATIC_IPV4_GATEWAY:
23443030 445 case STATIC_IPV4_GATEWAY_IFNAME:
d62a17ae 446 si->addr.ipv4 = gate->ipv4;
447 break;
448 case STATIC_IPV6_GATEWAY:
23443030 449 case STATIC_IPV6_GATEWAY_IFNAME:
d62a17ae 450 si->addr.ipv6 = gate->ipv6;
451 break;
23443030 452 case STATIC_IFNAME:
d62a17ae 453 break;
454 }
455
456 /* Save labels, if any. */
457 memcpy(&si->snh_label, snh_label, sizeof(struct static_nh_label));
458
459 /* Add new static route information to the tree with sort by
460 distance value and gateway address. */
461 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) {
462 if (si->distance < cp->distance)
463 break;
464 if (si->distance > cp->distance)
465 continue;
466 if (si->type == STATIC_IPV4_GATEWAY
467 && cp->type == STATIC_IPV4_GATEWAY) {
468 if (ntohl(si->addr.ipv4.s_addr)
469 < ntohl(cp->addr.ipv4.s_addr))
470 break;
471 if (ntohl(si->addr.ipv4.s_addr)
472 > ntohl(cp->addr.ipv4.s_addr))
473 continue;
474 }
475 }
476
477 /* Make linked list. */
478 if (pp)
479 pp->next = si;
480 else
481 rn->info = si;
482 if (cp)
483 cp->prev = si;
484 si->prev = pp;
485 si->next = cp;
486
c3c04063
DL
487 /* check whether interface exists in system & install if it does */
488 if (!ifname)
489 static_install_route(afi, safi, p, src_p, si);
490 else {
491 struct interface *ifp;
492
493 ifp = if_lookup_by_name(ifname, zvrf_id(zvrf));
494 if (ifp && ifp->ifindex != IFINDEX_INTERNAL) {
495 si->ifindex = ifp->ifindex;
496 static_install_route(afi, safi, p, src_p, si);
497 }
498 }
d62a17ae 499
500 return 1;
501}
502
503int static_delete_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
504 struct prefix_ipv6 *src_p, union g_addr *gate,
c3c04063 505 const char *ifname, route_tag_t tag, u_char distance,
d62a17ae 506 struct zebra_vrf *zvrf,
507 struct static_nh_label *snh_label)
508{
509 struct route_node *rn;
510 struct static_route *si;
511 struct route_table *stable;
512
513 /* Lookup table. */
514 stable = zebra_vrf_static_table(afi, safi, zvrf);
515 if (!stable)
516 return -1;
517
518 /* Lookup static route prefix. */
519 rn = srcdest_rnode_lookup(stable, p, src_p);
520 if (!rn)
521 return 0;
522
523 /* Find same static route is the tree */
524 for (si = rn->info; si; si = si->next)
525 if (type == si->type
9d303b37 526 && (!gate || ((afi == AFI_IP
19aad877 527 && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
9d303b37
DL
528 || (afi == AFI_IP6
529 && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
c3c04063 530 && (!strcmp(ifname ? ifname : "", si->ifname))
d62a17ae 531 && (!tag || (tag == si->tag))
532 && (!snh_label->num_labels
533 || !memcmp(&si->snh_label, snh_label,
534 sizeof(struct static_nh_label))))
535 break;
536
537 /* Can't find static route. */
538 if (!si) {
539 route_unlock_node(rn);
540 return 0;
541 }
542
c3c04063
DL
543 /* Uninstall from rib. */
544 if (!si->ifname[0] || si->ifindex != IFINDEX_INTERNAL)
545 static_uninstall_route(afi, safi, p, src_p, si);
d62a17ae 546
547 /* Unlink static route from linked list. */
548 if (si->prev)
549 si->prev->next = si->next;
550 else
551 rn->info = si->next;
552 if (si->next)
553 si->next->prev = si->prev;
554 route_unlock_node(rn);
555
556 /* Free static route configuration. */
557 XFREE(MTYPE_STATIC_ROUTE, si);
558
559 route_unlock_node(rn);
560
561 return 1;
28f6dde8 562}
c3c04063
DL
563
564static void static_ifindex_update_af(struct interface *ifp, bool up,
565 afi_t afi, safi_t safi)
566{
567 struct route_table *stable;
568 struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
569 struct route_node *rn;
570 struct static_route *si;
571 struct prefix *p, *src_pp;
572 struct prefix_ipv6 *src_p;
573
574 stable = zebra_vrf_static_table(afi, safi, zvrf);
575 if (!stable)
576 return;
577
578 for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) {
579 srcdest_rnode_prefixes(rn, &p, &src_pp);
580 src_p = (struct prefix_ipv6 *)src_pp;
581
582 for (si = rn->info; si; si = si->next) {
583 if (!si->ifname[0])
584 continue;
585 if (up) {
586 if (strcmp(si->ifname, ifp->name))
587 continue;
588 si->ifindex = ifp->ifindex;
589 static_install_route(afi, safi, p, src_p, si);
590 } else {
591 if (si->ifindex != ifp->ifindex)
592 continue;
593 static_uninstall_route(afi, safi, p, src_p,
594 si);
595 si->ifindex = IFINDEX_INTERNAL;
596 }
597 }
598 }
599}
600
601/* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
602void static_ifindex_update(struct interface *ifp, bool up)
603{
604 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_UNICAST);
605 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_MULTICAST);
606 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_UNICAST);
607 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_MULTICAST);
608}