]> git.proxmox.com Git - mirror_frr.git/blob - staticd/static_routes.c
Merge pull request #5200 from ton31337/feature/doc_access-list_sequence_numbers
[mirror_frr.git] / staticd / static_routes.c
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 "static_vrf.h"
31 #include "static_routes.h"
32 #include "static_memory.h"
33 #include "static_zebra.h"
34
35 /* Install static route into rib. */
36 static void static_install_route(struct route_node *rn,
37 struct static_route *si_changed, safi_t safi)
38 {
39 struct static_route *si;
40
41 for (si = rn->info; si; si = si->next)
42 static_zebra_nht_register(rn, si, true);
43
44 si = rn->info;
45 if (si)
46 static_zebra_route_add(rn, si_changed, si->vrf_id, safi, true);
47
48 }
49
50 /* Uninstall static route from RIB. */
51 static void static_uninstall_route(vrf_id_t vrf_id, safi_t safi,
52 struct route_node *rn,
53 struct static_route *si_changed)
54 {
55
56 if (rn->info)
57 static_zebra_route_add(rn, si_changed, vrf_id, safi, true);
58 else
59 static_zebra_route_add(rn, si_changed, vrf_id, safi, false);
60 }
61
62 int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
63 struct prefix_ipv6 *src_p, union g_addr *gate,
64 const char *ifname, enum static_blackhole_type bh_type,
65 route_tag_t tag, uint8_t distance, struct static_vrf *svrf,
66 struct static_vrf *nh_svrf,
67 struct static_nh_label *snh_label, uint32_t table_id,
68 bool onlink)
69 {
70 struct route_node *rn;
71 struct static_route *si;
72 struct static_route *pp;
73 struct static_route *cp;
74 struct static_route *update = NULL;
75 struct route_table *stable = svrf->stable[afi][safi];
76 struct interface *ifp;
77
78 if (!stable)
79 return -1;
80
81 if (!gate && (type == STATIC_IPV4_GATEWAY
82 || type == STATIC_IPV4_GATEWAY_IFNAME
83 || type == STATIC_IPV6_GATEWAY
84 || type == STATIC_IPV6_GATEWAY_IFNAME))
85 return -1;
86
87 if (!ifname
88 && (type == STATIC_IFNAME || type == STATIC_IPV4_GATEWAY_IFNAME
89 || type == STATIC_IPV6_GATEWAY_IFNAME))
90 return -1;
91
92 /* Lookup static route prefix. */
93 rn = srcdest_rnode_get(stable, p, src_p);
94
95 /* Do nothing if there is a same static route. */
96 for (si = rn->info; si; si = si->next) {
97 if (type == si->type
98 && (!gate
99 || ((afi == AFI_IP
100 && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
101 || (afi == AFI_IP6
102 && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
103 && (!strcmp(ifname ? ifname : "", si->ifname))
104 && nh_svrf->vrf->vrf_id == si->nh_vrf_id) {
105 if ((distance == si->distance) && (tag == si->tag)
106 && (table_id == si->table_id)
107 && !memcmp(&si->snh_label, snh_label,
108 sizeof(struct static_nh_label))
109 && si->bh_type == bh_type && si->onlink == onlink) {
110 route_unlock_node(rn);
111 return 0;
112 }
113 update = si;
114 }
115 }
116
117 /* Distance or tag or label changed, delete existing first. */
118 if (update)
119 static_delete_route(afi, safi, type, p, src_p, gate, ifname,
120 update->tag, update->distance, svrf,
121 &update->snh_label, table_id);
122
123 /* Make new static route structure. */
124 si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route));
125
126 si->type = type;
127 si->distance = distance;
128 si->bh_type = bh_type;
129 si->tag = tag;
130 si->vrf_id = svrf->vrf->vrf_id;
131 si->nh_vrf_id = nh_svrf->vrf->vrf_id;
132 strlcpy(si->nh_vrfname, nh_svrf->vrf->name, sizeof(si->nh_vrfname));
133 si->table_id = table_id;
134 si->onlink = onlink;
135
136 if (ifname)
137 strlcpy(si->ifname, ifname, sizeof(si->ifname));
138 si->ifindex = IFINDEX_INTERNAL;
139
140 switch (type) {
141 case STATIC_IPV4_GATEWAY:
142 case STATIC_IPV4_GATEWAY_IFNAME:
143 si->addr.ipv4 = gate->ipv4;
144 break;
145 case STATIC_IPV6_GATEWAY:
146 case STATIC_IPV6_GATEWAY_IFNAME:
147 si->addr.ipv6 = gate->ipv6;
148 break;
149 case STATIC_IFNAME:
150 break;
151 }
152
153 /* Save labels, if any. */
154 memcpy(&si->snh_label, snh_label, sizeof(struct static_nh_label));
155
156 /*
157 * Add new static route information to the tree with sort by
158 * distance value and gateway address.
159 */
160 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) {
161 if (si->distance < cp->distance)
162 break;
163 if (si->distance > cp->distance)
164 continue;
165 if (si->type == STATIC_IPV4_GATEWAY
166 && cp->type == STATIC_IPV4_GATEWAY) {
167 if (ntohl(si->addr.ipv4.s_addr)
168 < ntohl(cp->addr.ipv4.s_addr))
169 break;
170 if (ntohl(si->addr.ipv4.s_addr)
171 > ntohl(cp->addr.ipv4.s_addr))
172 continue;
173 }
174 }
175
176 /* Make linked list. */
177 if (pp)
178 pp->next = si;
179 else
180 rn->info = si;
181 if (cp)
182 cp->prev = si;
183 si->prev = pp;
184 si->next = cp;
185
186 /* check whether interface exists in system & install if it does */
187 switch (si->type) {
188 case STATIC_IPV4_GATEWAY:
189 case STATIC_IPV6_GATEWAY:
190 static_zebra_nht_register(rn, si, true);
191 break;
192 case STATIC_IPV4_GATEWAY_IFNAME:
193 case STATIC_IPV6_GATEWAY_IFNAME:
194 ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id);
195 if (ifp && ifp->ifindex != IFINDEX_INTERNAL)
196 si->ifindex = ifp->ifindex;
197 else
198 zlog_warn("Static Route using %s interface not installed because the interface does not exist in specified vrf",
199 ifname);
200
201 static_zebra_nht_register(rn, si, true);
202 break;
203 case STATIC_BLACKHOLE:
204 static_install_route(rn, si, safi);
205 break;
206 case STATIC_IFNAME:
207 ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id);
208 if (ifp && ifp->ifindex != IFINDEX_INTERNAL) {
209 si->ifindex = ifp->ifindex;
210 static_install_route(rn, si, safi);
211 } else
212 zlog_warn("Static Route using %s interface not installed because the interface does not exist in specified vrf",
213 ifname);
214
215 break;
216 }
217
218 return 1;
219 }
220
221 int static_delete_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
222 struct prefix_ipv6 *src_p, union g_addr *gate,
223 const char *ifname, route_tag_t tag, uint8_t distance,
224 struct static_vrf *svrf,
225 struct static_nh_label *snh_label,
226 uint32_t table_id)
227 {
228 struct route_node *rn;
229 struct static_route *si;
230 struct route_table *stable;
231
232 /* Lookup table. */
233 stable = static_vrf_static_table(afi, safi, svrf);
234 if (!stable)
235 return -1;
236
237 /* Lookup static route prefix. */
238 rn = srcdest_rnode_lookup(stable, p, src_p);
239 if (!rn)
240 return 0;
241
242 /* Find same static route is the tree */
243 for (si = rn->info; si; si = si->next)
244 if (type == si->type
245 && (!gate
246 || ((afi == AFI_IP
247 && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
248 || (afi == AFI_IP6
249 && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
250 && (!strcmp(ifname ? ifname : "", si->ifname))
251 && (!tag || (tag == si->tag))
252 && (table_id == si->table_id)
253 && (!snh_label->num_labels
254 || !memcmp(&si->snh_label, snh_label,
255 sizeof(struct static_nh_label))))
256 break;
257
258 /* Can't find static route. */
259 if (!si) {
260 route_unlock_node(rn);
261 return 0;
262 }
263
264 static_zebra_nht_register(rn, si, false);
265
266 /* Unlink static route from linked list. */
267 if (si->prev)
268 si->prev->next = si->next;
269 else
270 rn->info = si->next;
271 if (si->next)
272 si->next->prev = si->prev;
273
274 /*
275 * If we have other si nodes then route replace
276 * else delete the route
277 */
278 static_uninstall_route(si->vrf_id, safi, rn, si);
279 route_unlock_node(rn);
280
281 /* Free static route configuration. */
282 XFREE(MTYPE_STATIC_ROUTE, si);
283
284 route_unlock_node(rn);
285
286 return 1;
287 }
288
289 static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi,
290 safi_t safi)
291 {
292 struct route_table *stable;
293 struct route_node *rn;
294 struct static_route *si;
295 struct vrf *vrf;
296
297 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
298 struct static_vrf *svrf;
299
300 svrf = vrf->info;
301
302 stable = static_vrf_static_table(afi, safi, svrf);
303 if (!stable)
304 continue;
305
306 for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) {
307 for (si = rn->info; si; si = si->next) {
308 if (!si->ifname[0])
309 continue;
310 if (up) {
311 if (strcmp(si->ifname, ifp->name))
312 continue;
313 if (si->nh_vrf_id != ifp->vrf_id)
314 continue;
315 si->ifindex = ifp->ifindex;
316 } else {
317 if (si->ifindex != ifp->ifindex)
318 continue;
319 if (si->nh_vrf_id != ifp->vrf_id)
320 continue;
321 si->ifindex = IFINDEX_INTERNAL;
322 }
323
324 static_install_route(rn, si, safi);
325 }
326 }
327 }
328 }
329
330 /*
331 * This function looks at a svrf's stable and notices if any of the
332 * nexthops we are using are part of the vrf coming up.
333 * If we are using them then cleanup the nexthop vrf id
334 * to be the new value and then re-installs them
335 *
336 *
337 * stable -> The table we are looking at.
338 * svrf -> The newly changed vrf.
339 * afi -> The afi to look at
340 * safi -> the safi to look at
341 */
342 static void static_fixup_vrf(struct static_vrf *svrf,
343 struct route_table *stable, afi_t afi, safi_t safi)
344 {
345 struct route_node *rn;
346 struct static_route *si;
347 struct interface *ifp;
348
349 for (rn = route_top(stable); rn; rn = route_next(rn)) {
350 for (si = rn->info; si; si = si->next) {
351 if (strcmp(svrf->vrf->name, si->nh_vrfname) != 0)
352 continue;
353
354 si->nh_vrf_id = svrf->vrf->vrf_id;
355 si->nh_registered = false;
356 if (si->ifindex) {
357 ifp = if_lookup_by_name(si->ifname,
358 si->nh_vrf_id);
359 if (ifp)
360 si->ifindex = ifp->ifindex;
361 else
362 continue;
363 }
364
365 static_install_route(rn, si, safi);
366 }
367 }
368 }
369
370 /*
371 * This function enables static routes in a svrf as it
372 * is coming up. It sets the new vrf_id as appropriate.
373 *
374 * svrf -> The svrf that is being brought up and enabled by the kernel
375 * stable -> The stable we are looking at.
376 * afi -> the afi in question
377 * safi -> the safi in question
378 */
379 static void static_enable_vrf(struct static_vrf *svrf,
380 struct route_table *stable,
381 afi_t afi, safi_t safi)
382 {
383 struct route_node *rn;
384 struct static_route *si;
385 struct interface *ifp;
386 struct vrf *vrf = svrf->vrf;
387
388 for (rn = route_top(stable); rn; rn = route_next(rn)) {
389 for (si = rn->info; si; si = si->next) {
390 si->vrf_id = vrf->vrf_id;
391 if (si->ifindex) {
392 ifp = if_lookup_by_name(si->ifname,
393 si->nh_vrf_id);
394 if (ifp)
395 si->ifindex = ifp->ifindex;
396 else
397 continue;
398 }
399 static_install_route(rn, si, safi);
400 }
401 }
402 }
403
404 /*
405 * When a vrf is being enabled by the kernel, go through all the
406 * static routes in the system that use this vrf (both nexthops vrfs
407 * and the routes vrf )
408 *
409 * enable_svrf -> the vrf being enabled
410 */
411 void static_fixup_vrf_ids(struct static_vrf *enable_svrf)
412 {
413 struct route_table *stable;
414 struct vrf *vrf;
415 afi_t afi;
416 safi_t safi;
417
418 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
419 struct static_vrf *svrf;
420
421 svrf = vrf->info;
422 /* Install any static routes configured for this VRF. */
423 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
424 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
425 stable = svrf->stable[afi][safi];
426 if (!stable)
427 continue;
428
429 static_fixup_vrf(enable_svrf, stable,
430 afi, safi);
431
432 if (enable_svrf == svrf)
433 static_enable_vrf(svrf, stable,
434 afi, safi);
435 }
436 }
437 }
438 }
439
440 /*
441 * Look at the specified stable and if any of the routes in
442 * this table are using the svrf as the nexthop, uninstall
443 * those routes.
444 *
445 * svrf -> the vrf being disabled
446 * stable -> the table we need to look at.
447 * afi -> the afi in question
448 * safi -> the safi in question
449 */
450 static void static_cleanup_vrf(struct static_vrf *svrf,
451 struct route_table *stable,
452 afi_t afi, safi_t safi)
453 {
454 struct route_node *rn;
455 struct static_route *si;
456
457 for (rn = route_top(stable); rn; rn = route_next(rn)) {
458 for (si = rn->info; si; si = si->next) {
459 if (strcmp(svrf->vrf->name, si->nh_vrfname) != 0)
460 continue;
461
462 static_uninstall_route(si->vrf_id, safi, rn, si);
463 }
464 }
465 }
466
467 /*
468 * Look at all static routes in this table and uninstall
469 * them.
470 *
471 * stable -> The table to uninstall from
472 * afi -> The afi in question
473 * safi -> the safi in question
474 */
475 static void static_disable_vrf(struct route_table *stable,
476 afi_t afi, safi_t safi)
477 {
478 struct route_node *rn;
479 struct static_route *si;
480
481 for (rn = route_top(stable); rn; rn = route_next(rn))
482 for (si = rn->info; si; si = si->next)
483 static_uninstall_route(si->vrf_id, safi, rn, si);
484 }
485
486 /*
487 * When the disable_svrf is shutdown by the kernel, we call
488 * this function and it cleans up all static routes using
489 * this vrf as a nexthop as well as all static routes
490 * in it's stables.
491 *
492 * disable_svrf - The vrf being disabled
493 */
494 void static_cleanup_vrf_ids(struct static_vrf *disable_svrf)
495 {
496 struct vrf *vrf;
497 afi_t afi;
498 safi_t safi;
499
500 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
501 struct static_vrf *svrf;
502
503 svrf = vrf->info;
504
505 /* Uninstall any static routes configured for this VRF. */
506 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
507 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
508 struct route_table *stable;
509
510 stable = svrf->stable[afi][safi];
511 if (!stable)
512 continue;
513
514 static_cleanup_vrf(disable_svrf, stable,
515 afi, safi);
516
517 if (disable_svrf == svrf)
518 static_disable_vrf(stable, afi, safi);
519 }
520 }
521 }
522 }
523
524 /*
525 * This function enables static routes when an interface it relies
526 * on in a different vrf is coming up.
527 *
528 * stable -> The stable we are looking at.
529 * ifp -> interface coming up
530 * afi -> the afi in question
531 * safi -> the safi in question
532 */
533 static void static_fixup_intf_nh(struct route_table *stable,
534 struct interface *ifp,
535 afi_t afi, safi_t safi)
536 {
537 struct route_node *rn;
538 struct static_route *si;
539
540 for (rn = route_top(stable); rn; rn = route_next(rn)) {
541 for (si = rn->info; si; si = si->next) {
542 if (si->nh_vrf_id != ifp->vrf_id)
543 continue;
544
545 if (si->ifindex != ifp->ifindex)
546 continue;
547
548 static_install_route(rn, si, safi);
549 }
550 }
551 }
552
553 /*
554 * This function enables static routes that rely on an interface in
555 * a different vrf when that interface comes up.
556 */
557 void static_install_intf_nh(struct interface *ifp)
558 {
559 struct route_table *stable;
560 struct vrf *vrf;
561 afi_t afi;
562 safi_t safi;
563
564 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
565 struct static_vrf *svrf = vrf->info;
566
567 /* Not needed if same vrf since happens naturally */
568 if (vrf->vrf_id == ifp->vrf_id)
569 continue;
570
571 /* Install any static routes configured for this interface. */
572 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
573 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
574 stable = svrf->stable[afi][safi];
575 if (!stable)
576 continue;
577
578 static_fixup_intf_nh(stable, ifp, afi, safi);
579 }
580 }
581 }
582 }
583
584 /* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
585 void static_ifindex_update(struct interface *ifp, bool up)
586 {
587 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_UNICAST);
588 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_MULTICAST);
589 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_UNICAST);
590 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_MULTICAST);
591 }