]> git.proxmox.com Git - mirror_frr.git/blame - staticd/static_routes.c
Merge pull request #5327 from lkrishnamoor/rm_rd_filter
[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))))
9c0bcd0d
DT
103 && (!strcmp(ifname ? ifname : "", si->ifname))
104 && nh_svrf->vrf->vrf_id == si->nh_vrf_id) {
7e24fdf3
DS
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))
02dc8ba3 109 && si->bh_type == bh_type && si->onlink == onlink) {
7e24fdf3
DS
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;
2dfe5a07 132 strlcpy(si->nh_vrfname, nh_svrf->vrf->name, sizeof(si->nh_vrfname));
7e24fdf3 133 si->table_id = table_id;
02dc8ba3 134 si->onlink = onlink;
7e24fdf3
DS
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 */
a6e85307
DS
187 switch (si->type) {
188 case STATIC_IPV4_GATEWAY:
189 case STATIC_IPV6_GATEWAY:
6f5db0b1 190 static_zebra_nht_register(rn, si, true);
a6e85307
DS
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);
7e24fdf3 200
a6e85307
DS
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:
a36898e7 207 ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id);
7e24fdf3
DS
208 if (ifp && ifp->ifindex != IFINDEX_INTERNAL) {
209 si->ifindex = ifp->ifindex;
8bc8de2c 210 static_install_route(rn, si, safi);
7e24fdf3
DS
211 } else
212 zlog_warn("Static Route using %s interface not installed because the interface does not exist in specified vrf",
213 ifname);
a6e85307
DS
214
215 break;
7e24fdf3
DS
216 }
217
218 return 1;
219}
220
221int 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
27da3044 264 static_zebra_nht_register(rn, si, false);
7e24fdf3
DS
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 */
8bc8de2c 278 static_uninstall_route(si->vrf_id, safi, rn, si);
7e24fdf3
DS
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
289static 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;
9eb8b14c
PG
313 if (si->nh_vrf_id != ifp->vrf_id)
314 continue;
7e24fdf3
DS
315 si->ifindex = ifp->ifindex;
316 } else {
317 if (si->ifindex != ifp->ifindex)
318 continue;
9eb8b14c
PG
319 if (si->nh_vrf_id != ifp->vrf_id)
320 continue;
7e24fdf3
DS
321 si->ifindex = IFINDEX_INTERNAL;
322 }
7e24fdf3 323
0b70cb10
DS
324 static_install_route(rn, si, safi);
325 }
7e24fdf3
DS
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 */
342static 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;
7e24fdf3
DS
348
349 for (rn = route_top(stable); rn; rn = route_next(rn)) {
7e24fdf3
DS
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;
6d2a4f37 355 si->nh_registered = false;
7e24fdf3 356 if (si->ifindex) {
a36898e7
DS
357 ifp = if_lookup_by_name(si->ifname,
358 si->nh_vrf_id);
7e24fdf3
DS
359 if (ifp)
360 si->ifindex = ifp->ifindex;
361 else
362 continue;
363 }
7e24fdf3 364
8bc8de2c 365 static_install_route(rn, si, safi);
0b70cb10 366 }
7e24fdf3
DS
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 */
379static 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;
7e24fdf3
DS
387
388 for (rn = route_top(stable); rn; rn = route_next(rn)) {
7e24fdf3
DS
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,
a36898e7 393 si->nh_vrf_id);
7e24fdf3
DS
394 if (ifp)
395 si->ifindex = ifp->ifindex;
396 else
397 continue;
398 }
8bc8de2c 399 static_install_route(rn, si, safi);
0b70cb10 400 }
7e24fdf3
DS
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 */
411void 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 */
450static 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
8bc8de2c 462 static_uninstall_route(si->vrf_id, safi, rn, si);
7e24fdf3
DS
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 */
475static 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)
8bc8de2c 483 static_uninstall_route(si->vrf_id, safi, rn, si);
7e24fdf3
DS
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 */
494void 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
a9be49bc
DS
524/*
525 * This function enables static routes when an interface it relies
526 * on in a different vrf is coming up.
527 *
a9be49bc
DS
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 */
533static 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) {
a36898e7 542 if (si->nh_vrf_id != ifp->vrf_id)
a9be49bc
DS
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 */
557void 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 */
a36898e7 568 if (vrf->vrf_id == ifp->vrf_id)
a9be49bc
DS
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
7e24fdf3
DS
584/* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
585void 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}