]> git.proxmox.com Git - mirror_frr.git/blob - staticd/static_routes.c
Merge pull request #4949 from opensourcerouting/mpls-zapi-improvements
[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 si->ifindex = ifp->ifindex;
314 } else {
315 if (si->ifindex != ifp->ifindex)
316 continue;
317 si->ifindex = IFINDEX_INTERNAL;
318 }
319
320 static_install_route(rn, si, safi);
321 }
322 }
323 }
324 }
325
326 /*
327 * This function looks at a svrf's stable and notices if any of the
328 * nexthops we are using are part of the vrf coming up.
329 * If we are using them then cleanup the nexthop vrf id
330 * to be the new value and then re-installs them
331 *
332 *
333 * stable -> The table we are looking at.
334 * svrf -> The newly changed vrf.
335 * afi -> The afi to look at
336 * safi -> the safi to look at
337 */
338 static void static_fixup_vrf(struct static_vrf *svrf,
339 struct route_table *stable, afi_t afi, safi_t safi)
340 {
341 struct route_node *rn;
342 struct static_route *si;
343 struct interface *ifp;
344
345 for (rn = route_top(stable); rn; rn = route_next(rn)) {
346 for (si = rn->info; si; si = si->next) {
347 if (strcmp(svrf->vrf->name, si->nh_vrfname) != 0)
348 continue;
349
350 si->nh_vrf_id = svrf->vrf->vrf_id;
351 si->nh_registered = false;
352 if (si->ifindex) {
353 ifp = if_lookup_by_name(si->ifname,
354 si->nh_vrf_id);
355 if (ifp)
356 si->ifindex = ifp->ifindex;
357 else
358 continue;
359 }
360
361 static_install_route(rn, si, safi);
362 }
363 }
364 }
365
366 /*
367 * This function enables static routes in a svrf as it
368 * is coming up. It sets the new vrf_id as appropriate.
369 *
370 * svrf -> The svrf that is being brought up and enabled by the kernel
371 * stable -> The stable we are looking at.
372 * afi -> the afi in question
373 * safi -> the safi in question
374 */
375 static void static_enable_vrf(struct static_vrf *svrf,
376 struct route_table *stable,
377 afi_t afi, safi_t safi)
378 {
379 struct route_node *rn;
380 struct static_route *si;
381 struct interface *ifp;
382 struct vrf *vrf = svrf->vrf;
383
384 for (rn = route_top(stable); rn; rn = route_next(rn)) {
385 for (si = rn->info; si; si = si->next) {
386 si->vrf_id = vrf->vrf_id;
387 if (si->ifindex) {
388 ifp = if_lookup_by_name(si->ifname,
389 si->nh_vrf_id);
390 if (ifp)
391 si->ifindex = ifp->ifindex;
392 else
393 continue;
394 }
395 static_install_route(rn, si, safi);
396 }
397 }
398 }
399
400 /*
401 * When a vrf is being enabled by the kernel, go through all the
402 * static routes in the system that use this vrf (both nexthops vrfs
403 * and the routes vrf )
404 *
405 * enable_svrf -> the vrf being enabled
406 */
407 void static_fixup_vrf_ids(struct static_vrf *enable_svrf)
408 {
409 struct route_table *stable;
410 struct vrf *vrf;
411 afi_t afi;
412 safi_t safi;
413
414 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
415 struct static_vrf *svrf;
416
417 svrf = vrf->info;
418 /* Install any static routes configured for this VRF. */
419 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
420 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
421 stable = svrf->stable[afi][safi];
422 if (!stable)
423 continue;
424
425 static_fixup_vrf(enable_svrf, stable,
426 afi, safi);
427
428 if (enable_svrf == svrf)
429 static_enable_vrf(svrf, stable,
430 afi, safi);
431 }
432 }
433 }
434 }
435
436 /*
437 * Look at the specified stable and if any of the routes in
438 * this table are using the svrf as the nexthop, uninstall
439 * those routes.
440 *
441 * svrf -> the vrf being disabled
442 * stable -> the table we need to look at.
443 * afi -> the afi in question
444 * safi -> the safi in question
445 */
446 static void static_cleanup_vrf(struct static_vrf *svrf,
447 struct route_table *stable,
448 afi_t afi, safi_t safi)
449 {
450 struct route_node *rn;
451 struct static_route *si;
452
453 for (rn = route_top(stable); rn; rn = route_next(rn)) {
454 for (si = rn->info; si; si = si->next) {
455 if (strcmp(svrf->vrf->name, si->nh_vrfname) != 0)
456 continue;
457
458 static_uninstall_route(si->vrf_id, safi, rn, si);
459 }
460 }
461 }
462
463 /*
464 * Look at all static routes in this table and uninstall
465 * them.
466 *
467 * stable -> The table to uninstall from
468 * afi -> The afi in question
469 * safi -> the safi in question
470 */
471 static void static_disable_vrf(struct route_table *stable,
472 afi_t afi, safi_t safi)
473 {
474 struct route_node *rn;
475 struct static_route *si;
476
477 for (rn = route_top(stable); rn; rn = route_next(rn))
478 for (si = rn->info; si; si = si->next)
479 static_uninstall_route(si->vrf_id, safi, rn, si);
480 }
481
482 /*
483 * When the disable_svrf is shutdown by the kernel, we call
484 * this function and it cleans up all static routes using
485 * this vrf as a nexthop as well as all static routes
486 * in it's stables.
487 *
488 * disable_svrf - The vrf being disabled
489 */
490 void static_cleanup_vrf_ids(struct static_vrf *disable_svrf)
491 {
492 struct vrf *vrf;
493 afi_t afi;
494 safi_t safi;
495
496 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
497 struct static_vrf *svrf;
498
499 svrf = vrf->info;
500
501 /* Uninstall any static routes configured for this VRF. */
502 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
503 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
504 struct route_table *stable;
505
506 stable = svrf->stable[afi][safi];
507 if (!stable)
508 continue;
509
510 static_cleanup_vrf(disable_svrf, stable,
511 afi, safi);
512
513 if (disable_svrf == svrf)
514 static_disable_vrf(stable, afi, safi);
515 }
516 }
517 }
518 }
519
520 /*
521 * This function enables static routes when an interface it relies
522 * on in a different vrf is coming up.
523 *
524 * stable -> The stable we are looking at.
525 * ifp -> interface coming up
526 * afi -> the afi in question
527 * safi -> the safi in question
528 */
529 static void static_fixup_intf_nh(struct route_table *stable,
530 struct interface *ifp,
531 afi_t afi, safi_t safi)
532 {
533 struct route_node *rn;
534 struct static_route *si;
535
536 for (rn = route_top(stable); rn; rn = route_next(rn)) {
537 for (si = rn->info; si; si = si->next) {
538 if (si->nh_vrf_id != ifp->vrf_id)
539 continue;
540
541 if (si->ifindex != ifp->ifindex)
542 continue;
543
544 static_install_route(rn, si, safi);
545 }
546 }
547 }
548
549 /*
550 * This function enables static routes that rely on an interface in
551 * a different vrf when that interface comes up.
552 */
553 void static_install_intf_nh(struct interface *ifp)
554 {
555 struct route_table *stable;
556 struct vrf *vrf;
557 afi_t afi;
558 safi_t safi;
559
560 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
561 struct static_vrf *svrf = vrf->info;
562
563 /* Not needed if same vrf since happens naturally */
564 if (vrf->vrf_id == ifp->vrf_id)
565 continue;
566
567 /* Install any static routes configured for this interface. */
568 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
569 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
570 stable = svrf->stable[afi][safi];
571 if (!stable)
572 continue;
573
574 static_fixup_intf_nh(stable, ifp, afi, safi);
575 }
576 }
577 }
578 }
579
580 /* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
581 void static_ifindex_update(struct interface *ifp, bool up)
582 {
583 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_UNICAST);
584 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_MULTICAST);
585 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_UNICAST);
586 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_MULTICAST);
587 }