]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_static.c
zebra: add packet length into pbr support
[mirror_frr.git] / zebra / zebra_static.c
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 *
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
21 */
22 #include <zebra.h>
23
24 #include <lib/nexthop.h>
25 #include <lib/memory.h>
26 #include <lib/srcdest_table.h>
27 #include <lib/if.h>
28
29 #include "vty.h"
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"
37 #include "zebra/zebra_memory.h"
38
39 /* Install static route into rib. */
40 void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
41 struct prefix_ipv6 *src_p, struct static_route *si)
42 {
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;
48 enum blackhole_type bh_type = 0;
49 struct vrf *nh_vrf;
50
51 /* Lookup table. */
52 table = zebra_vrf_table(afi, safi, si->vrf_id);
53 if (!table)
54 return;
55
56 /*
57 * If a specific vrf is coming up and the nexthop vrf we are
58 * looking at using hasn't been brought up yet, just don't
59 * install the static route yet.
60 * When the nexthop vrf comes up we will get another call
61 * back to do the right thing. I'm putting this check
62 * here because we are calling static_install_route a bunch
63 * from a bunch of different callpaths.
64 */
65 nh_vrf = vrf_lookup_by_id(si->nh_vrf_id);
66 if (!nh_vrf)
67 return;
68
69 memset(&nh_p, 0, sizeof(nh_p));
70 if (si->type == STATIC_BLACKHOLE) {
71 switch (si->bh_type) {
72 case STATIC_BLACKHOLE_DROP:
73 case STATIC_BLACKHOLE_NULL:
74 bh_type = BLACKHOLE_NULL;
75 break;
76 case STATIC_BLACKHOLE_REJECT:
77 bh_type = BLACKHOLE_REJECT;
78 break;
79 }
80 }
81
82 /* Lookup existing route */
83 rn = srcdest_rnode_get(table, p, src_p);
84 RNODE_FOREACH_RE (rn, re) {
85 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
86 continue;
87
88 if (re->type == ZEBRA_ROUTE_STATIC
89 && re->distance == si->distance)
90 break;
91 }
92
93 if (re) {
94 /* if tag value changed , update old value in RIB */
95 if (re->tag != si->tag)
96 re->tag = si->tag;
97
98 /* Same distance static route is there. Update it with new
99 nexthop. */
100 route_unlock_node(rn);
101 switch (si->type) {
102 case STATIC_IPV4_GATEWAY:
103 nexthop = route_entry_nexthop_ipv4_add(
104 re, &si->addr.ipv4, NULL, si->nh_vrf_id);
105 nh_p.family = AF_INET;
106 nh_p.prefixlen = IPV4_MAX_BITLEN;
107 nh_p.u.prefix4 = si->addr.ipv4;
108 zebra_register_rnh_static_nh(si->nh_vrf_id, &nh_p, rn);
109 break;
110 case STATIC_IPV4_GATEWAY_IFNAME:
111 nexthop = route_entry_nexthop_ipv4_ifindex_add(
112 re, &si->addr.ipv4, NULL, si->ifindex,
113 si->nh_vrf_id);
114 break;
115 case STATIC_IFNAME:
116 nexthop = route_entry_nexthop_ifindex_add(
117 re, si->ifindex, si->nh_vrf_id);
118 break;
119 case STATIC_BLACKHOLE:
120 nexthop =
121 route_entry_nexthop_blackhole_add(re, bh_type);
122 break;
123 case STATIC_IPV6_GATEWAY:
124 nexthop = route_entry_nexthop_ipv6_add(
125 re, &si->addr.ipv6, si->nh_vrf_id);
126 nh_p.family = AF_INET6;
127 nh_p.prefixlen = IPV6_MAX_BITLEN;
128 nh_p.u.prefix6 = si->addr.ipv6;
129 zebra_register_rnh_static_nh(si->nh_vrf_id, &nh_p, rn);
130 break;
131 case STATIC_IPV6_GATEWAY_IFNAME:
132 nexthop = route_entry_nexthop_ipv6_ifindex_add(
133 re, &si->addr.ipv6, si->ifindex, si->nh_vrf_id);
134 break;
135 }
136 /* Update label(s), if present. */
137 if (si->snh_label.num_labels)
138 nexthop_add_labels(nexthop, ZEBRA_LSP_STATIC,
139 si->snh_label.num_labels,
140 &si->snh_label.label[0]);
141
142 if (IS_ZEBRA_DEBUG_RIB) {
143 char buf[INET6_ADDRSTRLEN];
144 if (IS_ZEBRA_DEBUG_RIB) {
145 inet_ntop(p->family, &p->u.prefix, buf,
146 INET6_ADDRSTRLEN);
147 zlog_debug(
148 "%u:%s/%d: Modifying route rn %p, re %p (type %d)",
149 si->vrf_id, buf, p->prefixlen, rn, re,
150 re->type);
151 }
152 }
153
154 re->uptime = time(NULL);
155 /* Schedule route for processing or invoke NHT, as appropriate.
156 */
157 if (si->type == STATIC_IPV4_GATEWAY
158 || si->type == STATIC_IPV6_GATEWAY)
159 zebra_evaluate_rnh(si->nh_vrf_id, nh_p.family, 1,
160 RNH_NEXTHOP_TYPE, &nh_p);
161 else
162 rib_queue_add(rn);
163 } else {
164 /* This is new static route. */
165 re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
166
167 re->type = ZEBRA_ROUTE_STATIC;
168 re->instance = 0;
169 re->distance = si->distance;
170 re->metric = 0;
171 re->mtu = 0;
172 re->vrf_id = si->vrf_id;
173 re->table =
174 (si->vrf_id != VRF_DEFAULT)
175 ? (zebra_vrf_lookup_by_id(si->vrf_id))->table_id
176 : zebrad.rtm_table_default;
177 re->nexthop_num = 0;
178 re->tag = si->tag;
179
180 switch (si->type) {
181 case STATIC_IPV4_GATEWAY:
182 nexthop = route_entry_nexthop_ipv4_add(
183 re, &si->addr.ipv4, NULL, si->nh_vrf_id);
184 nh_p.family = AF_INET;
185 nh_p.prefixlen = IPV4_MAX_BITLEN;
186 nh_p.u.prefix4 = si->addr.ipv4;
187 zebra_register_rnh_static_nh(si->nh_vrf_id, &nh_p, rn);
188 break;
189 case STATIC_IPV4_GATEWAY_IFNAME:
190 nexthop = route_entry_nexthop_ipv4_ifindex_add(
191 re, &si->addr.ipv4, NULL, si->ifindex,
192 si->nh_vrf_id);
193 break;
194 case STATIC_IFNAME:
195 nexthop = route_entry_nexthop_ifindex_add(
196 re, si->ifindex, si->nh_vrf_id);
197 break;
198 case STATIC_BLACKHOLE:
199 nexthop =
200 route_entry_nexthop_blackhole_add(re, bh_type);
201 break;
202 case STATIC_IPV6_GATEWAY:
203 nexthop = route_entry_nexthop_ipv6_add(
204 re, &si->addr.ipv6, si->nh_vrf_id);
205 nh_p.family = AF_INET6;
206 nh_p.prefixlen = IPV6_MAX_BITLEN;
207 nh_p.u.prefix6 = si->addr.ipv6;
208 zebra_register_rnh_static_nh(si->nh_vrf_id, &nh_p, rn);
209 break;
210 case STATIC_IPV6_GATEWAY_IFNAME:
211 nexthop = route_entry_nexthop_ipv6_ifindex_add(
212 re, &si->addr.ipv6, si->ifindex, si->nh_vrf_id);
213 break;
214 }
215 /* Update label(s), if present. */
216 if (si->snh_label.num_labels)
217 nexthop_add_labels(nexthop, ZEBRA_LSP_STATIC,
218 si->snh_label.num_labels,
219 &si->snh_label.label[0]);
220
221 if (IS_ZEBRA_DEBUG_RIB) {
222 char buf[INET6_ADDRSTRLEN];
223 if (IS_ZEBRA_DEBUG_RIB) {
224 inet_ntop(p->family, &p->u.prefix, buf,
225 INET6_ADDRSTRLEN);
226 zlog_debug(
227 "%u:%s/%d: Inserting route rn %p, re %p (type %d)",
228 si->vrf_id, buf, p->prefixlen, rn, re,
229 re->type);
230 }
231 }
232 re->uptime = time(NULL);
233 /* Link this re to the tree. Schedule for processing or invoke
234 * NHT,
235 * as appropriate.
236 */
237 if (si->type == STATIC_IPV4_GATEWAY
238 || si->type == STATIC_IPV6_GATEWAY) {
239 rib_addnode(rn, re, 0);
240 zebra_evaluate_rnh(si->nh_vrf_id, nh_p.family, 1,
241 RNH_NEXTHOP_TYPE, &nh_p);
242 } else
243 rib_addnode(rn, re, 1);
244 }
245 }
246
247 /* this works correctly with IFNAME<>IFINDEX because a static route on a
248 * non-active interface will have IFINDEX_INTERNAL and thus compare false
249 */
250 static int static_nexthop_same(struct nexthop *nexthop, struct static_route *si)
251 {
252 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
253 && si->type == STATIC_BLACKHOLE)
254 return 1;
255
256 if (nexthop->type == NEXTHOP_TYPE_IPV4
257 && si->type == STATIC_IPV4_GATEWAY
258 && IPV4_ADDR_SAME(&nexthop->gate.ipv4, &si->addr.ipv4))
259 return 1;
260 else if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
261 && si->type == STATIC_IPV4_GATEWAY_IFNAME
262 && IPV4_ADDR_SAME(&nexthop->gate.ipv4, &si->addr.ipv4)
263 && nexthop->ifindex == si->ifindex)
264 return 1;
265 else if (nexthop->type == NEXTHOP_TYPE_IFINDEX
266 && si->type == STATIC_IFNAME
267 && nexthop->ifindex == si->ifindex)
268 return 1;
269 else if (nexthop->type == NEXTHOP_TYPE_IPV6
270 && si->type == STATIC_IPV6_GATEWAY
271 && IPV6_ADDR_SAME(&nexthop->gate.ipv6, &si->addr.ipv6))
272 return 1;
273 else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
274 && si->type == STATIC_IPV6_GATEWAY_IFNAME
275 && IPV6_ADDR_SAME(&nexthop->gate.ipv6, &si->addr.ipv6)
276 && nexthop->ifindex == si->ifindex)
277 return 1;
278
279 return 0;
280 }
281
282 /* Uninstall static route from RIB. */
283 void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p,
284 struct prefix_ipv6 *src_p, struct static_route *si)
285 {
286 struct route_node *rn;
287 struct route_entry *re;
288 struct nexthop *nexthop;
289 struct route_table *table;
290 struct prefix nh_p;
291
292 /* Lookup table. */
293 table = zebra_vrf_table(afi, safi, si->vrf_id);
294 if (!table)
295 return;
296
297 /* Lookup existing route with type and distance. */
298 rn = srcdest_rnode_lookup(table, p, src_p);
299 if (!rn)
300 return;
301
302 RNODE_FOREACH_RE (rn, re) {
303 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
304 continue;
305
306 if (re->type == ZEBRA_ROUTE_STATIC
307 && re->distance == si->distance && re->tag == si->tag)
308 break;
309 }
310
311 if (!re) {
312 route_unlock_node(rn);
313 return;
314 }
315
316 /* Lookup nexthop. */
317 for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next)
318 if (static_nexthop_same(nexthop, si))
319 break;
320
321 /* Can't find nexthop. */
322 if (!nexthop) {
323 route_unlock_node(rn);
324 return;
325 }
326
327 /* Check nexthop. */
328 if (re->nexthop_num == 1)
329 rib_delnode(rn, re);
330 else {
331 /* Mark this nexthop as inactive and reinstall the route. Then,
332 * delete
333 * the nexthop. There is no need to re-evaluate the route for
334 * this
335 * scenario.
336 */
337 if (IS_ZEBRA_DEBUG_RIB) {
338 char buf[INET6_ADDRSTRLEN];
339 if (IS_ZEBRA_DEBUG_RIB) {
340 inet_ntop(p->family, &p->u.prefix, buf,
341 INET6_ADDRSTRLEN);
342 zlog_debug(
343 "%u:%s/%d: Modifying route rn %p, re %p (type %d)",
344 si->vrf_id, buf, p->prefixlen, rn, re,
345 re->type);
346 }
347 }
348 UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
349 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) {
350 rib_dest_t *dest = rib_dest_from_rnode(rn);
351
352 /* If there are other active nexthops, do an update. */
353 if (re->nexthop_active_num > 1) {
354 /* Update route in kernel if it's in fib */
355 if (dest->selected_fib)
356 rib_install_kernel(rn, re, re);
357 /* Update redistribution if it's selected */
358 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
359 redistribute_update(
360 p, (struct prefix *)src_p, re,
361 NULL);
362 } else {
363 /* Remove from redistribute if selected route
364 * becomes inactive */
365 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
366 redistribute_delete(
367 p, (struct prefix *)src_p, re);
368 /* Remove from kernel if fib route becomes
369 * inactive */
370 if (dest->selected_fib)
371 rib_uninstall_kernel(rn, re);
372 }
373 }
374
375 if (afi == AFI_IP) {
376 /* Delete the nexthop and dereg from NHT */
377 nh_p.family = AF_INET;
378 nh_p.prefixlen = IPV4_MAX_BITLEN;
379 nh_p.u.prefix4 = nexthop->gate.ipv4;
380 } else {
381 nh_p.family = AF_INET6;
382 nh_p.prefixlen = IPV6_MAX_BITLEN;
383 nh_p.u.prefix6 = nexthop->gate.ipv6;
384 }
385 route_entry_nexthop_delete(re, nexthop);
386 zebra_deregister_rnh_static_nh(si->nh_vrf_id, &nh_p, rn);
387 nexthop_free(nexthop);
388 }
389 /* Unlock node. */
390 route_unlock_node(rn);
391 }
392
393 int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
394 struct prefix_ipv6 *src_p, union g_addr *gate,
395 const char *ifname, enum static_blackhole_type bh_type,
396 route_tag_t tag, uint8_t distance, struct zebra_vrf *zvrf,
397 struct zebra_vrf *nh_zvrf,
398 struct static_nh_label *snh_label)
399 {
400 struct route_node *rn;
401 struct static_route *si;
402 struct static_route *pp;
403 struct static_route *cp;
404 struct static_route *update = NULL;
405 struct route_table *stable = zvrf->stable[afi][safi];
406
407 if (!stable)
408 return -1;
409
410 if (!gate && (type == STATIC_IPV4_GATEWAY
411 || type == STATIC_IPV4_GATEWAY_IFNAME
412 || type == STATIC_IPV6_GATEWAY
413 || type == STATIC_IPV6_GATEWAY_IFNAME))
414 return -1;
415
416 if (!ifname
417 && (type == STATIC_IFNAME || type == STATIC_IPV4_GATEWAY_IFNAME
418 || type == STATIC_IPV6_GATEWAY_IFNAME))
419 return -1;
420
421 /* Lookup static route prefix. */
422 rn = srcdest_rnode_get(stable, p, src_p);
423
424 /* Do nothing if there is a same static route. */
425 for (si = rn->info; si; si = si->next) {
426 if (type == si->type
427 && (!gate
428 || ((afi == AFI_IP
429 && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
430 || (afi == AFI_IP6
431 && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
432 && (!strcmp(ifname ? ifname : "", si->ifname))) {
433 if ((distance == si->distance) && (tag == si->tag)
434 && !memcmp(&si->snh_label, snh_label,
435 sizeof(struct static_nh_label))
436 && si->bh_type == bh_type) {
437 route_unlock_node(rn);
438 return 0;
439 } else
440 update = si;
441 }
442 }
443
444 /* Distance or tag or label changed, delete existing first. */
445 if (update)
446 static_delete_route(afi, safi, type, p, src_p, gate, ifname,
447 update->tag, update->distance, zvrf,
448 &update->snh_label);
449
450 /* Make new static route structure. */
451 si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route));
452
453 si->type = type;
454 si->distance = distance;
455 si->bh_type = bh_type;
456 si->tag = tag;
457 si->vrf_id = zvrf_id(zvrf);
458 si->nh_vrf_id = zvrf_id(nh_zvrf);
459 strcpy(si->nh_vrfname, nh_zvrf->vrf->name);
460
461 if (ifname)
462 strlcpy(si->ifname, ifname, sizeof(si->ifname));
463 si->ifindex = IFINDEX_INTERNAL;
464
465 switch (type) {
466 case STATIC_IPV4_GATEWAY:
467 case STATIC_IPV4_GATEWAY_IFNAME:
468 si->addr.ipv4 = gate->ipv4;
469 break;
470 case STATIC_IPV6_GATEWAY:
471 case STATIC_IPV6_GATEWAY_IFNAME:
472 si->addr.ipv6 = gate->ipv6;
473 break;
474 case STATIC_IFNAME:
475 break;
476 }
477
478 /* Save labels, if any. */
479 memcpy(&si->snh_label, snh_label, sizeof(struct static_nh_label));
480
481 /* Add new static route information to the tree with sort by
482 distance value and gateway address. */
483 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) {
484 if (si->distance < cp->distance)
485 break;
486 if (si->distance > cp->distance)
487 continue;
488 if (si->type == STATIC_IPV4_GATEWAY
489 && cp->type == STATIC_IPV4_GATEWAY) {
490 if (ntohl(si->addr.ipv4.s_addr)
491 < ntohl(cp->addr.ipv4.s_addr))
492 break;
493 if (ntohl(si->addr.ipv4.s_addr)
494 > ntohl(cp->addr.ipv4.s_addr))
495 continue;
496 }
497 }
498
499 /* Make linked list. */
500 if (pp)
501 pp->next = si;
502 else
503 rn->info = si;
504 if (cp)
505 cp->prev = si;
506 si->prev = pp;
507 si->next = cp;
508
509 /* check whether interface exists in system & install if it does */
510 if (!ifname)
511 static_install_route(afi, safi, p, src_p, si);
512 else {
513 struct interface *ifp;
514
515 ifp = if_lookup_by_name(ifname, zvrf_id(nh_zvrf));
516 if (ifp && ifp->ifindex != IFINDEX_INTERNAL) {
517 si->ifindex = ifp->ifindex;
518 static_install_route(afi, safi, p, src_p, si);
519 } else
520 zlog_warn("Static Route using %s interface not installed because the interface does not exist in specified vrf",
521 ifname);
522 }
523
524 return 1;
525 }
526
527 int static_delete_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
528 struct prefix_ipv6 *src_p, union g_addr *gate,
529 const char *ifname, route_tag_t tag, uint8_t distance,
530 struct zebra_vrf *zvrf,
531 struct static_nh_label *snh_label)
532 {
533 struct route_node *rn;
534 struct static_route *si;
535 struct route_table *stable;
536
537 /* Lookup table. */
538 stable = zebra_vrf_static_table(afi, safi, zvrf);
539 if (!stable)
540 return -1;
541
542 /* Lookup static route prefix. */
543 rn = srcdest_rnode_lookup(stable, p, src_p);
544 if (!rn)
545 return 0;
546
547 /* Find same static route is the tree */
548 for (si = rn->info; si; si = si->next)
549 if (type == si->type
550 && (!gate
551 || ((afi == AFI_IP
552 && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
553 || (afi == AFI_IP6
554 && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
555 && (!strcmp(ifname ? ifname : "", si->ifname))
556 && (!tag || (tag == si->tag))
557 && (!snh_label->num_labels
558 || !memcmp(&si->snh_label, snh_label,
559 sizeof(struct static_nh_label))))
560 break;
561
562 /* Can't find static route. */
563 if (!si) {
564 route_unlock_node(rn);
565 return 0;
566 }
567
568 /* Uninstall from rib. */
569 if (!si->ifname[0] || si->ifindex != IFINDEX_INTERNAL)
570 static_uninstall_route(afi, safi, p, src_p, si);
571
572 /* Unlink static route from linked list. */
573 if (si->prev)
574 si->prev->next = si->next;
575 else
576 rn->info = si->next;
577 if (si->next)
578 si->next->prev = si->prev;
579 route_unlock_node(rn);
580
581 /* Free static route configuration. */
582 XFREE(MTYPE_STATIC_ROUTE, si);
583
584 route_unlock_node(rn);
585
586 return 1;
587 }
588
589 static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi,
590 safi_t safi)
591 {
592 struct route_table *stable;
593 struct route_node *rn;
594 struct static_route *si;
595 struct prefix *p, *src_pp;
596 struct prefix_ipv6 *src_p;
597 struct vrf *vrf;
598
599 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
600 struct zebra_vrf *zvrf;
601
602 zvrf = vrf->info;
603
604 stable = zebra_vrf_static_table(afi, safi, zvrf);
605 if (!stable)
606 continue;
607
608 for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) {
609 srcdest_rnode_prefixes(rn, &p, &src_pp);
610 src_p = (struct prefix_ipv6 *)src_pp;
611
612 for (si = rn->info; si; si = si->next) {
613 if (!si->ifname[0])
614 continue;
615 if (up) {
616 if (strcmp(si->ifname, ifp->name))
617 continue;
618 si->ifindex = ifp->ifindex;
619 static_install_route(afi, safi, p, src_p, si);
620 } else {
621 if (si->ifindex != ifp->ifindex)
622 continue;
623 static_uninstall_route(afi, safi, p, src_p, si);
624 si->ifindex = IFINDEX_INTERNAL;
625 }
626 }
627 }
628 }
629 }
630
631 /*
632 * This function looks at a zvrf's stable and notices if any of the
633 * nexthops we are using are part of the vrf coming up.
634 * If we are using them then cleanup the nexthop vrf id
635 * to be the new value and then re-installs them
636 *
637 *
638 * stable -> The table we are looking at.
639 * zvrf -> The newly changed vrf.
640 * afi -> The afi to look at
641 * safi -> the safi to look at
642 */
643 static void static_fixup_vrf(struct zebra_vrf *zvrf,
644 struct route_table *stable, afi_t afi, safi_t safi)
645 {
646 struct route_node *rn;
647 struct static_route *si;
648 struct interface *ifp;
649
650 for (rn = route_top(stable); rn; rn = route_next(rn)) {
651 for (si = rn->info; si; si = si->next) {
652 if (strcmp(zvrf->vrf->name, si->nh_vrfname) != 0)
653 continue;
654
655 si->nh_vrf_id = zvrf->vrf->vrf_id;
656 if (si->ifindex) {
657 ifp = if_lookup_by_name(si->ifname,
658 si->nh_vrf_id);
659 if (ifp)
660 si->ifindex = ifp->ifindex;
661 else
662 continue;
663 }
664 static_install_route(afi, safi, &rn->p, NULL, si);
665 }
666 }
667 }
668
669 /*
670 * This function enables static routes in a zvrf as it
671 * is coming up. It sets the new vrf_id as appropriate.
672 *
673 * zvrf -> The zvrf that is being brought up and enabled by the kernel
674 * stable -> The stable we are looking at.
675 * afi -> the afi in question
676 * safi -> the safi in question
677 */
678 static void static_enable_vrf(struct zebra_vrf *zvrf,
679 struct route_table *stable,
680 afi_t afi, safi_t safi)
681 {
682 struct route_node *rn;
683 struct static_route *si;
684 struct interface *ifp;
685 struct vrf *vrf = zvrf->vrf;
686
687 for (rn = route_top(stable); rn; rn = route_next(rn)) {
688 for (si = rn->info; si; si = si->next) {
689 si->vrf_id = vrf->vrf_id;
690 if (si->ifindex) {
691 ifp = if_lookup_by_name(si->ifname,
692 si->nh_vrf_id);
693 if (ifp)
694 si->ifindex = ifp->ifindex;
695 else
696 continue;
697 }
698 static_install_route(afi, safi, &rn->p, NULL, si);
699 }
700 }
701 }
702
703 /*
704 * When a vrf is being enabled by the kernel, go through all the
705 * static routes in the system that use this vrf (both nexthops vrfs
706 * and the routes vrf )
707 *
708 * enable_zvrf -> the vrf being enabled
709 */
710 void static_fixup_vrf_ids(struct zebra_vrf *enable_zvrf)
711 {
712 struct route_table *stable;
713 struct vrf *vrf;
714 afi_t afi;
715 safi_t safi;
716
717 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
718 struct zebra_vrf *zvrf;
719
720 zvrf = vrf->info;
721 /* Install any static routes configured for this VRF. */
722 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
723 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
724 stable = zvrf->stable[afi][safi];
725 if (!stable)
726 continue;
727
728 static_fixup_vrf(enable_zvrf, stable,
729 afi, safi);
730
731 if (enable_zvrf == zvrf)
732 static_enable_vrf(zvrf, stable,
733 afi, safi);
734 }
735 }
736 }
737 }
738
739 /*
740 * Look at the specified stable and if any of the routes in
741 * this table are using the zvrf as the nexthop, uninstall
742 * those routes.
743 *
744 * zvrf -> the vrf being disabled
745 * stable -> the table we need to look at.
746 * afi -> the afi in question
747 * safi -> the safi in question
748 */
749 static void static_cleanup_vrf(struct zebra_vrf *zvrf,
750 struct route_table *stable,
751 afi_t afi, safi_t safi)
752 {
753 struct route_node *rn;
754 struct static_route *si;
755
756 for (rn = route_top(stable); rn; rn = route_next(rn)) {
757 for (si = rn->info; si; si = si->next) {
758 if (strcmp(zvrf->vrf->name, si->nh_vrfname) != 0)
759 continue;
760
761 static_uninstall_route(afi, safi, &rn->p, NULL, si);
762 }
763 }
764 }
765
766 /*
767 * Look at all static routes in this table and uninstall
768 * them.
769 *
770 * stable -> The table to uninstall from
771 * afi -> The afi in question
772 * safi -> the safi in question
773 */
774 static void static_disable_vrf(struct route_table *stable,
775 afi_t afi, safi_t safi)
776 {
777 struct route_node *rn;
778 struct static_route *si;
779
780 for (rn = route_top(stable); rn; rn = route_next(rn)) {
781 for (si = rn->info; si; si = si->next) {
782 static_uninstall_route(afi, safi, &rn->p, NULL, si);
783 }
784 }
785 }
786
787 /*
788 * When the disable_zvrf is shutdown by the kernel, we call
789 * this function and it cleans up all static routes using
790 * this vrf as a nexthop as well as all static routes
791 * in it's stables.
792 *
793 * disable_zvrf - The vrf being disabled
794 */
795 void static_cleanup_vrf_ids(struct zebra_vrf *disable_zvrf)
796 {
797 struct vrf *vrf;
798 afi_t afi;
799 safi_t safi;
800
801 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
802 struct zebra_vrf *zvrf;
803
804 zvrf = vrf->info;
805
806 /* Uninstall any static routes configured for this VRF. */
807 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
808 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
809 struct route_table *stable;
810
811 stable = zvrf->stable[afi][safi];
812 if (!stable)
813 continue;
814
815 static_cleanup_vrf(disable_zvrf, stable,
816 afi, safi);
817
818 if (disable_zvrf == zvrf)
819 static_disable_vrf(stable, afi, safi);
820 }
821 }
822 }
823 }
824
825 /* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
826 void static_ifindex_update(struct interface *ifp, bool up)
827 {
828 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_UNICAST);
829 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_MULTICAST);
830 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_UNICAST);
831 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_MULTICAST);
832 }