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