]> git.proxmox.com Git - mirror_frr.git/blob - staticd/static_routes.c
staticd: correct update static route when specify nexthop-vrf
[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(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
77 if (!stable)
78 return -1;
79
80 if (!gate && (type == STATIC_IPV4_GATEWAY
81 || type == STATIC_IPV4_GATEWAY_IFNAME
82 || type == STATIC_IPV6_GATEWAY
83 || type == STATIC_IPV6_GATEWAY_IFNAME))
84 return -1;
85
86 if (!ifname
87 && (type == STATIC_IFNAME || type == STATIC_IPV4_GATEWAY_IFNAME
88 || type == STATIC_IPV6_GATEWAY_IFNAME))
89 return -1;
90
91 /* Lookup static route prefix. */
92 rn = srcdest_rnode_get(stable, p, src_p);
93
94 /* Do nothing if there is a same static route. */
95 for (si = rn->info; si; si = si->next) {
96 if (type == si->type
97 && (!gate
98 || ((afi == AFI_IP
99 && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
100 || (afi == AFI_IP6
101 && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
102 && (!strcmp(ifname ? ifname : "", si->ifname))
103 && nh_svrf->vrf->vrf_id == si->nh_vrf_id) {
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))
108 && si->bh_type == bh_type && si->onlink == onlink) {
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;
131 strlcpy(si->nh_vrfname, nh_svrf->vrf->name, sizeof(si->nh_vrfname));
132 si->table_id = table_id;
133 si->onlink = onlink;
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 */
186 if (!ifname)
187 static_install_route(rn, si, safi);
188 else {
189 struct interface *ifp;
190
191 ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id);
192 if (ifp && ifp->ifindex != IFINDEX_INTERNAL) {
193 si->ifindex = ifp->ifindex;
194 static_install_route(rn, si, safi);
195 } else
196 zlog_warn("Static Route using %s interface not installed because the interface does not exist in specified vrf",
197 ifname);
198 }
199
200 return 1;
201 }
202
203 int static_delete_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
204 struct prefix_ipv6 *src_p, union g_addr *gate,
205 const char *ifname, route_tag_t tag, uint8_t distance,
206 struct static_vrf *svrf,
207 struct static_nh_label *snh_label,
208 uint32_t table_id)
209 {
210 struct route_node *rn;
211 struct static_route *si;
212 struct route_table *stable;
213
214 /* Lookup table. */
215 stable = static_vrf_static_table(afi, safi, svrf);
216 if (!stable)
217 return -1;
218
219 /* Lookup static route prefix. */
220 rn = srcdest_rnode_lookup(stable, p, src_p);
221 if (!rn)
222 return 0;
223
224 /* Find same static route is the tree */
225 for (si = rn->info; si; si = si->next)
226 if (type == si->type
227 && (!gate
228 || ((afi == AFI_IP
229 && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
230 || (afi == AFI_IP6
231 && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
232 && (!strcmp(ifname ? ifname : "", si->ifname))
233 && (!tag || (tag == si->tag))
234 && (table_id == si->table_id)
235 && (!snh_label->num_labels
236 || !memcmp(&si->snh_label, snh_label,
237 sizeof(struct static_nh_label))))
238 break;
239
240 /* Can't find static route. */
241 if (!si) {
242 route_unlock_node(rn);
243 return 0;
244 }
245
246 static_zebra_nht_register(si, false);
247
248 /* Unlink static route from linked list. */
249 if (si->prev)
250 si->prev->next = si->next;
251 else
252 rn->info = si->next;
253 if (si->next)
254 si->next->prev = si->prev;
255
256 /*
257 * If we have other si nodes then route replace
258 * else delete the route
259 */
260 static_uninstall_route(si->vrf_id, safi, rn, si);
261 route_unlock_node(rn);
262
263 /* Free static route configuration. */
264 XFREE(MTYPE_STATIC_ROUTE, si);
265
266 route_unlock_node(rn);
267
268 return 1;
269 }
270
271 static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi,
272 safi_t safi)
273 {
274 struct route_table *stable;
275 struct route_node *rn;
276 struct static_route *si;
277 struct vrf *vrf;
278
279 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
280 struct static_vrf *svrf;
281
282 svrf = vrf->info;
283
284 stable = static_vrf_static_table(afi, safi, svrf);
285 if (!stable)
286 continue;
287
288 for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) {
289 for (si = rn->info; si; si = si->next) {
290 if (!si->ifname[0])
291 continue;
292 if (up) {
293 if (strcmp(si->ifname, ifp->name))
294 continue;
295 si->ifindex = ifp->ifindex;
296 } else {
297 if (si->ifindex != ifp->ifindex)
298 continue;
299 si->ifindex = IFINDEX_INTERNAL;
300 }
301
302 static_install_route(rn, si, safi);
303 }
304 }
305 }
306 }
307
308 /*
309 * This function looks at a svrf's stable and notices if any of the
310 * nexthops we are using are part of the vrf coming up.
311 * If we are using them then cleanup the nexthop vrf id
312 * to be the new value and then re-installs them
313 *
314 *
315 * stable -> The table we are looking at.
316 * svrf -> The newly changed vrf.
317 * afi -> The afi to look at
318 * safi -> the safi to look at
319 */
320 static void static_fixup_vrf(struct static_vrf *svrf,
321 struct route_table *stable, afi_t afi, safi_t safi)
322 {
323 struct route_node *rn;
324 struct static_route *si;
325 struct interface *ifp;
326
327 for (rn = route_top(stable); rn; rn = route_next(rn)) {
328 for (si = rn->info; si; si = si->next) {
329 if (strcmp(svrf->vrf->name, si->nh_vrfname) != 0)
330 continue;
331
332 si->nh_vrf_id = svrf->vrf->vrf_id;
333 si->nh_registered = false;
334 if (si->ifindex) {
335 ifp = if_lookup_by_name(si->ifname,
336 si->nh_vrf_id);
337 if (ifp)
338 si->ifindex = ifp->ifindex;
339 else
340 continue;
341 }
342
343 static_install_route(rn, si, safi);
344 }
345 }
346 }
347
348 /*
349 * This function enables static routes in a svrf as it
350 * is coming up. It sets the new vrf_id as appropriate.
351 *
352 * svrf -> The svrf that is being brought up and enabled by the kernel
353 * stable -> The stable we are looking at.
354 * afi -> the afi in question
355 * safi -> the safi in question
356 */
357 static void static_enable_vrf(struct static_vrf *svrf,
358 struct route_table *stable,
359 afi_t afi, safi_t safi)
360 {
361 struct route_node *rn;
362 struct static_route *si;
363 struct interface *ifp;
364 struct vrf *vrf = svrf->vrf;
365
366 for (rn = route_top(stable); rn; rn = route_next(rn)) {
367 for (si = rn->info; si; si = si->next) {
368 si->vrf_id = vrf->vrf_id;
369 if (si->ifindex) {
370 ifp = if_lookup_by_name(si->ifname,
371 si->nh_vrf_id);
372 if (ifp)
373 si->ifindex = ifp->ifindex;
374 else
375 continue;
376 }
377 static_install_route(rn, si, safi);
378 }
379 }
380 }
381
382 /*
383 * When a vrf is being enabled by the kernel, go through all the
384 * static routes in the system that use this vrf (both nexthops vrfs
385 * and the routes vrf )
386 *
387 * enable_svrf -> the vrf being enabled
388 */
389 void static_fixup_vrf_ids(struct static_vrf *enable_svrf)
390 {
391 struct route_table *stable;
392 struct vrf *vrf;
393 afi_t afi;
394 safi_t safi;
395
396 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
397 struct static_vrf *svrf;
398
399 svrf = vrf->info;
400 /* Install any static routes configured for this VRF. */
401 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
402 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
403 stable = svrf->stable[afi][safi];
404 if (!stable)
405 continue;
406
407 static_fixup_vrf(enable_svrf, stable,
408 afi, safi);
409
410 if (enable_svrf == svrf)
411 static_enable_vrf(svrf, stable,
412 afi, safi);
413 }
414 }
415 }
416 }
417
418 /*
419 * Look at the specified stable and if any of the routes in
420 * this table are using the svrf as the nexthop, uninstall
421 * those routes.
422 *
423 * svrf -> the vrf being disabled
424 * stable -> the table we need to look at.
425 * afi -> the afi in question
426 * safi -> the safi in question
427 */
428 static void static_cleanup_vrf(struct static_vrf *svrf,
429 struct route_table *stable,
430 afi_t afi, safi_t safi)
431 {
432 struct route_node *rn;
433 struct static_route *si;
434
435 for (rn = route_top(stable); rn; rn = route_next(rn)) {
436 for (si = rn->info; si; si = si->next) {
437 if (strcmp(svrf->vrf->name, si->nh_vrfname) != 0)
438 continue;
439
440 static_uninstall_route(si->vrf_id, safi, rn, si);
441 }
442 }
443 }
444
445 /*
446 * Look at all static routes in this table and uninstall
447 * them.
448 *
449 * stable -> The table to uninstall from
450 * afi -> The afi in question
451 * safi -> the safi in question
452 */
453 static void static_disable_vrf(struct route_table *stable,
454 afi_t afi, safi_t safi)
455 {
456 struct route_node *rn;
457 struct static_route *si;
458
459 for (rn = route_top(stable); rn; rn = route_next(rn))
460 for (si = rn->info; si; si = si->next)
461 static_uninstall_route(si->vrf_id, safi, rn, si);
462 }
463
464 /*
465 * When the disable_svrf is shutdown by the kernel, we call
466 * this function and it cleans up all static routes using
467 * this vrf as a nexthop as well as all static routes
468 * in it's stables.
469 *
470 * disable_svrf - The vrf being disabled
471 */
472 void static_cleanup_vrf_ids(struct static_vrf *disable_svrf)
473 {
474 struct vrf *vrf;
475 afi_t afi;
476 safi_t safi;
477
478 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
479 struct static_vrf *svrf;
480
481 svrf = vrf->info;
482
483 /* Uninstall any static routes configured for this VRF. */
484 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
485 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
486 struct route_table *stable;
487
488 stable = svrf->stable[afi][safi];
489 if (!stable)
490 continue;
491
492 static_cleanup_vrf(disable_svrf, stable,
493 afi, safi);
494
495 if (disable_svrf == svrf)
496 static_disable_vrf(stable, afi, safi);
497 }
498 }
499 }
500 }
501
502 /*
503 * This function enables static routes when an interface it relies
504 * on in a different vrf is coming up.
505 *
506 * stable -> The stable we are looking at.
507 * ifp -> interface coming up
508 * afi -> the afi in question
509 * safi -> the safi in question
510 */
511 static void static_fixup_intf_nh(struct route_table *stable,
512 struct interface *ifp,
513 afi_t afi, safi_t safi)
514 {
515 struct route_node *rn;
516 struct static_route *si;
517
518 for (rn = route_top(stable); rn; rn = route_next(rn)) {
519 for (si = rn->info; si; si = si->next) {
520 if (si->nh_vrf_id != ifp->vrf_id)
521 continue;
522
523 if (si->ifindex != ifp->ifindex)
524 continue;
525
526 static_install_route(rn, si, safi);
527 }
528 }
529 }
530
531 /*
532 * This function enables static routes that rely on an interface in
533 * a different vrf when that interface comes up.
534 */
535 void static_install_intf_nh(struct interface *ifp)
536 {
537 struct route_table *stable;
538 struct vrf *vrf;
539 afi_t afi;
540 safi_t safi;
541
542 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
543 struct static_vrf *svrf = vrf->info;
544
545 /* Not needed if same vrf since happens naturally */
546 if (vrf->vrf_id == ifp->vrf_id)
547 continue;
548
549 /* Install any static routes configured for this interface. */
550 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
551 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
552 stable = svrf->stable[afi][safi];
553 if (!stable)
554 continue;
555
556 static_fixup_intf_nh(stable, ifp, afi, safi);
557 }
558 }
559 }
560 }
561
562 /* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
563 void static_ifindex_update(struct interface *ifp, bool up)
564 {
565 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_UNICAST);
566 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_MULTICAST);
567 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_UNICAST);
568 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_MULTICAST);
569 }