]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_static.c
Merge pull request #1756 from qlyoung/stylechecker
[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(
4a7371e9 90 re, &si->addr.ipv4, NULL, si->nh_vrf_id);
d62a17ae 91 nh_p.family = AF_INET;
92 nh_p.prefixlen = IPV4_MAX_BITLEN;
93 nh_p.u.prefix4 = si->addr.ipv4;
5bdd34db 94 zebra_register_rnh_static_nh(si->nh_vrf_id, &nh_p, rn);
d62a17ae 95 break;
23443030 96 case STATIC_IPV4_GATEWAY_IFNAME:
599186ad 97 nexthop = route_entry_nexthop_ipv4_ifindex_add(
4a7371e9
DS
98 re, &si->addr.ipv4, NULL, si->ifindex,
99 si->nh_vrf_id);
599186ad 100 break;
23443030 101 case STATIC_IFNAME:
4a7371e9
DS
102 nexthop = route_entry_nexthop_ifindex_add(
103 re, si->ifindex, si->nh_vrf_id);
d62a17ae 104 break;
105 case STATIC_BLACKHOLE:
60466a63 106 nexthop = route_entry_nexthop_blackhole_add(
9aabb2ea 107 re, bh_type);
d62a17ae 108 break;
109 case STATIC_IPV6_GATEWAY:
4a7371e9
DS
110 nexthop = route_entry_nexthop_ipv6_add(
111 re, &si->addr.ipv6, si->nh_vrf_id);
d62a17ae 112 nh_p.family = AF_INET6;
113 nh_p.prefixlen = IPV6_MAX_BITLEN;
114 nh_p.u.prefix6 = si->addr.ipv6;
5bdd34db 115 zebra_register_rnh_static_nh(si->nh_vrf_id, &nh_p, rn);
d62a17ae 116 break;
23443030 117 case STATIC_IPV6_GATEWAY_IFNAME:
d62a17ae 118 nexthop = route_entry_nexthop_ipv6_ifindex_add(
4a7371e9 119 re, &si->addr.ipv6, si->ifindex, si->nh_vrf_id);
d62a17ae 120 break;
121 }
122 /* Update label(s), if present. */
123 if (si->snh_label.num_labels)
124 nexthop_add_labels(nexthop, ZEBRA_LSP_STATIC,
125 si->snh_label.num_labels,
126 &si->snh_label.label[0]);
127
128 if (IS_ZEBRA_DEBUG_RIB) {
129 char buf[INET6_ADDRSTRLEN];
130 if (IS_ZEBRA_DEBUG_RIB) {
131 inet_ntop(p->family, &p->u.prefix, buf,
132 INET6_ADDRSTRLEN);
133 zlog_debug(
134 "%u:%s/%d: Modifying route rn %p, re %p (type %d)",
135 si->vrf_id, buf, p->prefixlen, rn, re,
136 re->type);
137 }
138 }
d1ca0f1d
DS
139
140 re->uptime = time(NULL);
d62a17ae 141 /* Schedule route for processing or invoke NHT, as appropriate.
142 */
143 if (si->type == STATIC_IPV4_GATEWAY
144 || si->type == STATIC_IPV6_GATEWAY)
5bdd34db 145 zebra_evaluate_rnh(si->nh_vrf_id, nh_p.family, 1,
d62a17ae 146 RNH_NEXTHOP_TYPE, &nh_p);
147 else
148 rib_queue_add(rn);
149 } else {
150 /* This is new static route. */
151 re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
152
153 re->type = ZEBRA_ROUTE_STATIC;
154 re->instance = 0;
155 re->distance = si->distance;
156 re->metric = 0;
157 re->mtu = 0;
158 re->vrf_id = si->vrf_id;
159 re->table =
90ac32c2 160 (si->vrf_id != VRF_DEFAULT)
d62a17ae 161 ? (zebra_vrf_lookup_by_id(si->vrf_id))->table_id
162 : zebrad.rtm_table_default;
163 re->nexthop_num = 0;
164 re->tag = si->tag;
165
166 switch (si->type) {
167 case STATIC_IPV4_GATEWAY:
168 nexthop = route_entry_nexthop_ipv4_add(
4a7371e9 169 re, &si->addr.ipv4, NULL, si->nh_vrf_id);
d62a17ae 170 nh_p.family = AF_INET;
171 nh_p.prefixlen = IPV4_MAX_BITLEN;
172 nh_p.u.prefix4 = si->addr.ipv4;
5bdd34db 173 zebra_register_rnh_static_nh(si->nh_vrf_id, &nh_p, rn);
d62a17ae 174 break;
23443030 175 case STATIC_IPV4_GATEWAY_IFNAME:
599186ad 176 nexthop = route_entry_nexthop_ipv4_ifindex_add(
4a7371e9
DS
177 re, &si->addr.ipv4, NULL, si->ifindex,
178 si->nh_vrf_id);
599186ad 179 break;
23443030 180 case STATIC_IFNAME:
4a7371e9
DS
181 nexthop = route_entry_nexthop_ifindex_add(
182 re, si->ifindex, si->nh_vrf_id);
d62a17ae 183 break;
184 case STATIC_BLACKHOLE:
60466a63 185 nexthop = route_entry_nexthop_blackhole_add(
9aabb2ea 186 re, bh_type);
d62a17ae 187 break;
188 case STATIC_IPV6_GATEWAY:
4a7371e9
DS
189 nexthop = route_entry_nexthop_ipv6_add(
190 re, &si->addr.ipv6, si->nh_vrf_id);
d62a17ae 191 nh_p.family = AF_INET6;
192 nh_p.prefixlen = IPV6_MAX_BITLEN;
193 nh_p.u.prefix6 = si->addr.ipv6;
5bdd34db 194 zebra_register_rnh_static_nh(si->nh_vrf_id, &nh_p, rn);
d62a17ae 195 break;
23443030 196 case STATIC_IPV6_GATEWAY_IFNAME:
d62a17ae 197 nexthop = route_entry_nexthop_ipv6_ifindex_add(
4a7371e9 198 re, &si->addr.ipv6, si->ifindex, si->nh_vrf_id);
d62a17ae 199 break;
200 }
201 /* Update label(s), if present. */
202 if (si->snh_label.num_labels)
203 nexthop_add_labels(nexthop, ZEBRA_LSP_STATIC,
204 si->snh_label.num_labels,
205 &si->snh_label.label[0]);
206
d62a17ae 207 if (IS_ZEBRA_DEBUG_RIB) {
208 char buf[INET6_ADDRSTRLEN];
209 if (IS_ZEBRA_DEBUG_RIB) {
210 inet_ntop(p->family, &p->u.prefix, buf,
211 INET6_ADDRSTRLEN);
212 zlog_debug(
213 "%u:%s/%d: Inserting route rn %p, re %p (type %d)",
214 si->vrf_id, buf, p->prefixlen, rn, re,
215 re->type);
216 }
217 }
d1ca0f1d 218 re->uptime = time(NULL);
d62a17ae 219 /* Link this re to the tree. Schedule for processing or invoke
220 * NHT,
221 * as appropriate.
222 */
223 if (si->type == STATIC_IPV4_GATEWAY
224 || si->type == STATIC_IPV6_GATEWAY) {
225 rib_addnode(rn, re, 0);
5bdd34db 226 zebra_evaluate_rnh(si->nh_vrf_id, nh_p.family, 1,
d62a17ae 227 RNH_NEXTHOP_TYPE, &nh_p);
228 } else
229 rib_addnode(rn, re, 1);
230 }
28f6dde8 231}
a22f3f5d 232
c3c04063
DL
233/* this works correctly with IFNAME<>IFINDEX because a static route on a
234 * non-active interface will have IFINDEX_INTERNAL and thus compare false
235 */
d62a17ae 236static int static_nexthop_same(struct nexthop *nexthop, struct static_route *si)
28f6dde8 237{
d62a17ae 238 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
239 && si->type == STATIC_BLACKHOLE)
240 return 1;
241
242 if (nexthop->type == NEXTHOP_TYPE_IPV4
243 && si->type == STATIC_IPV4_GATEWAY
244 && IPV4_ADDR_SAME(&nexthop->gate.ipv4, &si->addr.ipv4))
245 return 1;
599186ad 246 else if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
23443030 247 && si->type == STATIC_IPV4_GATEWAY_IFNAME
599186ad
RW
248 && IPV4_ADDR_SAME(&nexthop->gate.ipv4, &si->addr.ipv4)
249 && nexthop->ifindex == si->ifindex)
250 return 1;
d62a17ae 251 else if (nexthop->type == NEXTHOP_TYPE_IFINDEX
23443030 252 && si->type == STATIC_IFNAME
d62a17ae 253 && nexthop->ifindex == si->ifindex)
254 return 1;
255 else if (nexthop->type == NEXTHOP_TYPE_IPV6
256 && si->type == STATIC_IPV6_GATEWAY
257 && IPV6_ADDR_SAME(&nexthop->gate.ipv6, &si->addr.ipv6))
258 return 1;
259 else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
23443030 260 && si->type == STATIC_IPV6_GATEWAY_IFNAME
d62a17ae 261 && IPV6_ADDR_SAME(&nexthop->gate.ipv6, &si->addr.ipv6)
262 && nexthop->ifindex == si->ifindex)
263 return 1;
264
265 return 0;
28f6dde8
DS
266}
267
268/* Uninstall static route from RIB. */
d62a17ae 269void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p,
270 struct prefix_ipv6 *src_p, struct static_route *si)
28f6dde8 271{
d62a17ae 272 struct route_node *rn;
273 struct route_entry *re;
274 struct nexthop *nexthop;
275 struct route_table *table;
276 struct prefix nh_p;
277
278 /* Lookup table. */
279 table = zebra_vrf_table(afi, safi, si->vrf_id);
280 if (!table)
281 return;
282
283 /* Lookup existing route with type and distance. */
284 rn = srcdest_rnode_lookup(table, p, src_p);
285 if (!rn)
286 return;
287
a2addae8 288 RNODE_FOREACH_RE (rn, re) {
d62a17ae 289 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
290 continue;
291
292 if (re->type == ZEBRA_ROUTE_STATIC
293 && re->distance == si->distance && re->tag == si->tag)
294 break;
28f6dde8 295 }
d62a17ae 296
297 if (!re) {
298 route_unlock_node(rn);
299 return;
28f6dde8 300 }
28f6dde8 301
d62a17ae 302 /* Lookup nexthop. */
303 for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next)
304 if (static_nexthop_same(nexthop, si))
305 break;
306
307 /* Can't find nexthop. */
308 if (!nexthop) {
309 route_unlock_node(rn);
310 return;
28f6dde8 311 }
d62a17ae 312
313 /* Check nexthop. */
314 if (re->nexthop_num == 1)
315 rib_delnode(rn, re);
316 else {
317 /* Mark this nexthop as inactive and reinstall the route. Then,
318 * delete
319 * the nexthop. There is no need to re-evaluate the route for
320 * this
321 * scenario.
322 */
323 if (IS_ZEBRA_DEBUG_RIB) {
324 char buf[INET6_ADDRSTRLEN];
325 if (IS_ZEBRA_DEBUG_RIB) {
326 inet_ntop(p->family, &p->u.prefix, buf,
327 INET6_ADDRSTRLEN);
328 zlog_debug(
329 "%u:%s/%d: Modifying route rn %p, re %p (type %d)",
330 si->vrf_id, buf, p->prefixlen, rn, re,
331 re->type);
332 }
333 }
334 UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
335 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) {
5f7a4718
DS
336 rib_dest_t *dest = rib_dest_from_rnode(rn);
337
d62a17ae 338 /* If there are other active nexthops, do an update. */
339 if (re->nexthop_active_num > 1) {
340 /* Update route in kernel if it's in fib */
5f7a4718 341 if (dest->selected_fib)
d62a17ae 342 rib_install_kernel(rn, re, re);
343 /* Update redistribution if it's selected */
344 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
345 redistribute_update(
346 p, (struct prefix *)src_p, re,
347 NULL);
348 } else {
349 /* Remove from redistribute if selected route
350 * becomes inactive */
351 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
352 redistribute_delete(
353 p, (struct prefix *)src_p, re);
354 /* Remove from kernel if fib route becomes
355 * inactive */
5f7a4718 356 if (dest->selected_fib)
d62a17ae 357 rib_uninstall_kernel(rn, re);
358 }
359 }
360
361 if (afi == AFI_IP) {
362 /* Delete the nexthop and dereg from NHT */
363 nh_p.family = AF_INET;
364 nh_p.prefixlen = IPV4_MAX_BITLEN;
365 nh_p.u.prefix4 = nexthop->gate.ipv4;
366 } else {
367 nh_p.family = AF_INET6;
368 nh_p.prefixlen = IPV6_MAX_BITLEN;
369 nh_p.u.prefix6 = nexthop->gate.ipv6;
370 }
371 route_entry_nexthop_delete(re, nexthop);
372 zebra_deregister_rnh_static_nh(si->vrf_id, &nh_p, rn);
373 nexthop_free(nexthop);
28f6dde8 374 }
d62a17ae 375 /* Unlock node. */
376 route_unlock_node(rn);
28f6dde8
DS
377}
378
d62a17ae 379int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
380 struct prefix_ipv6 *src_p, union g_addr *gate,
9aabb2ea 381 const char *ifname, enum static_blackhole_type bh_type,
dc9ffce8 382 route_tag_t tag, u_char distance, struct zebra_vrf *zvrf,
cbb0dbf6 383 struct zebra_vrf *nh_zvrf,
a22f3f5d 384 struct static_nh_label *snh_label)
28f6dde8 385{
d62a17ae 386 struct route_node *rn;
387 struct static_route *si;
388 struct static_route *pp;
389 struct static_route *cp;
390 struct static_route *update = NULL;
391 struct route_table *stable = zvrf->stable[afi][safi];
392
393 if (!stable)
394 return -1;
395
599186ad
RW
396 if (!gate
397 && (type == STATIC_IPV4_GATEWAY
23443030 398 || type == STATIC_IPV4_GATEWAY_IFNAME
599186ad 399 || type == STATIC_IPV6_GATEWAY
23443030 400 || type == STATIC_IPV6_GATEWAY_IFNAME))
d62a17ae 401 return -1;
402
c3c04063 403 if (!ifname
23443030
DL
404 && (type == STATIC_IFNAME
405 || type == STATIC_IPV4_GATEWAY_IFNAME
406 || type == STATIC_IPV6_GATEWAY_IFNAME))
d62a17ae 407 return -1;
408
409 /* Lookup static route prefix. */
410 rn = srcdest_rnode_get(stable, p, src_p);
411
412 /* Do nothing if there is a same static route. */
413 for (si = rn->info; si; si = si->next) {
414 if (type == si->type
9d303b37 415 && (!gate || ((afi == AFI_IP
19aad877 416 && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
9d303b37
DL
417 || (afi == AFI_IP6
418 && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
c3c04063 419 && (!strcmp (ifname ? ifname : "", si->ifname))) {
d62a17ae 420 if ((distance == si->distance) && (tag == si->tag)
421 && !memcmp(&si->snh_label, snh_label,
422 sizeof(struct static_nh_label))
a8309422 423 && si->bh_type == bh_type) {
d62a17ae 424 route_unlock_node(rn);
425 return 0;
426 } else
427 update = si;
428 }
429 }
430
431 /* Distance or tag or label changed, delete existing first. */
432 if (update)
c3c04063 433 static_delete_route(afi, safi, type, p, src_p, gate, ifname,
d62a17ae 434 update->tag, update->distance, zvrf,
435 &update->snh_label);
436
437 /* Make new static route structure. */
438 si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route));
439
440 si->type = type;
441 si->distance = distance;
a8309422 442 si->bh_type = bh_type;
d62a17ae 443 si->tag = tag;
444 si->vrf_id = zvrf_id(zvrf);
cbb0dbf6
DS
445 si->nh_vrf_id = zvrf_id(nh_zvrf);
446
c3c04063
DL
447 if (ifname)
448 strlcpy(si->ifname, ifname, sizeof(si->ifname));
449 si->ifindex = IFINDEX_INTERNAL;
d62a17ae 450
451 switch (type) {
452 case STATIC_IPV4_GATEWAY:
23443030 453 case STATIC_IPV4_GATEWAY_IFNAME:
d62a17ae 454 si->addr.ipv4 = gate->ipv4;
455 break;
456 case STATIC_IPV6_GATEWAY:
23443030 457 case STATIC_IPV6_GATEWAY_IFNAME:
d62a17ae 458 si->addr.ipv6 = gate->ipv6;
459 break;
23443030 460 case STATIC_IFNAME:
d62a17ae 461 break;
462 }
463
464 /* Save labels, if any. */
465 memcpy(&si->snh_label, snh_label, sizeof(struct static_nh_label));
466
467 /* Add new static route information to the tree with sort by
468 distance value and gateway address. */
469 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) {
470 if (si->distance < cp->distance)
471 break;
472 if (si->distance > cp->distance)
473 continue;
474 if (si->type == STATIC_IPV4_GATEWAY
475 && cp->type == STATIC_IPV4_GATEWAY) {
476 if (ntohl(si->addr.ipv4.s_addr)
477 < ntohl(cp->addr.ipv4.s_addr))
478 break;
479 if (ntohl(si->addr.ipv4.s_addr)
480 > ntohl(cp->addr.ipv4.s_addr))
481 continue;
482 }
483 }
484
485 /* Make linked list. */
486 if (pp)
487 pp->next = si;
488 else
489 rn->info = si;
490 if (cp)
491 cp->prev = si;
492 si->prev = pp;
493 si->next = cp;
494
c3c04063
DL
495 /* check whether interface exists in system & install if it does */
496 if (!ifname)
497 static_install_route(afi, safi, p, src_p, si);
498 else {
499 struct interface *ifp;
500
cbb0dbf6 501 ifp = if_lookup_by_name(ifname, zvrf_id(nh_zvrf));
c3c04063
DL
502 if (ifp && ifp->ifindex != IFINDEX_INTERNAL) {
503 si->ifindex = ifp->ifindex;
504 static_install_route(afi, safi, p, src_p, si);
505 }
506 }
d62a17ae 507
508 return 1;
509}
510
511int static_delete_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
512 struct prefix_ipv6 *src_p, union g_addr *gate,
c3c04063 513 const char *ifname, route_tag_t tag, u_char distance,
d62a17ae 514 struct zebra_vrf *zvrf,
515 struct static_nh_label *snh_label)
516{
517 struct route_node *rn;
518 struct static_route *si;
519 struct route_table *stable;
520
521 /* Lookup table. */
522 stable = zebra_vrf_static_table(afi, safi, zvrf);
523 if (!stable)
524 return -1;
525
526 /* Lookup static route prefix. */
527 rn = srcdest_rnode_lookup(stable, p, src_p);
528 if (!rn)
529 return 0;
530
531 /* Find same static route is the tree */
532 for (si = rn->info; si; si = si->next)
533 if (type == si->type
9d303b37 534 && (!gate || ((afi == AFI_IP
19aad877 535 && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
9d303b37
DL
536 || (afi == AFI_IP6
537 && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
c3c04063 538 && (!strcmp(ifname ? ifname : "", si->ifname))
d62a17ae 539 && (!tag || (tag == si->tag))
540 && (!snh_label->num_labels
541 || !memcmp(&si->snh_label, snh_label,
542 sizeof(struct static_nh_label))))
543 break;
544
545 /* Can't find static route. */
546 if (!si) {
547 route_unlock_node(rn);
548 return 0;
549 }
550
c3c04063
DL
551 /* Uninstall from rib. */
552 if (!si->ifname[0] || si->ifindex != IFINDEX_INTERNAL)
553 static_uninstall_route(afi, safi, p, src_p, si);
d62a17ae 554
555 /* Unlink static route from linked list. */
556 if (si->prev)
557 si->prev->next = si->next;
558 else
559 rn->info = si->next;
560 if (si->next)
561 si->next->prev = si->prev;
562 route_unlock_node(rn);
563
564 /* Free static route configuration. */
565 XFREE(MTYPE_STATIC_ROUTE, si);
566
567 route_unlock_node(rn);
568
569 return 1;
28f6dde8 570}
c3c04063
DL
571
572static void static_ifindex_update_af(struct interface *ifp, bool up,
573 afi_t afi, safi_t safi)
574{
575 struct route_table *stable;
576 struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
577 struct route_node *rn;
578 struct static_route *si;
579 struct prefix *p, *src_pp;
580 struct prefix_ipv6 *src_p;
581
582 stable = zebra_vrf_static_table(afi, safi, zvrf);
583 if (!stable)
584 return;
585
586 for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) {
587 srcdest_rnode_prefixes(rn, &p, &src_pp);
588 src_p = (struct prefix_ipv6 *)src_pp;
589
590 for (si = rn->info; si; si = si->next) {
591 if (!si->ifname[0])
592 continue;
593 if (up) {
594 if (strcmp(si->ifname, ifp->name))
595 continue;
596 si->ifindex = ifp->ifindex;
597 static_install_route(afi, safi, p, src_p, si);
598 } else {
599 if (si->ifindex != ifp->ifindex)
600 continue;
601 static_uninstall_route(afi, safi, p, src_p,
602 si);
603 si->ifindex = IFINDEX_INTERNAL;
604 }
605 }
606 }
607}
608
609/* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
610void static_ifindex_update(struct interface *ifp, bool up)
611{
612 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_UNICAST);
613 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_MULTICAST);
614 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_UNICAST);
615 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_MULTICAST);
616}