]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_static.c
zebra: When displaying nexthop information show correct vrf
[mirror_frr.git] / zebra / zebra_static.c
1 /*
2 * Static Routing Information code
3 * Copyright (C) 2016 Cumulus Networks
4 * Donald Sharp
5 *
6 * This file is part of Quagga.
7 *
8 * Quagga is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
11 * later version.
12 *
13 * Quagga is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22 #include <zebra.h>
23
24 #include <lib/nexthop.h>
25 #include <lib/memory.h>
26 #include <lib/srcdest_table.h>
27 #include <lib/if.h>
28
29 #include "vty.h"
30 #include "zebra/debug.h"
31 #include "zebra/rib.h"
32 #include "zebra/zserv.h"
33 #include "zebra/zebra_vrf.h"
34 #include "zebra/zebra_static.h"
35 #include "zebra/zebra_rnh.h"
36 #include "zebra/redistribute.h"
37 #include "zebra/zebra_memory.h"
38
39 /* Install static route into rib. */
40 void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
41 struct prefix_ipv6 *src_p, struct static_route *si)
42 {
43 struct route_entry *re;
44 struct route_node *rn;
45 struct route_table *table;
46 struct prefix nh_p;
47 struct nexthop *nexthop = NULL;
48 enum blackhole_type bh_type = 0;
49
50 /* Lookup table. */
51 table = zebra_vrf_table(afi, safi, si->vrf_id);
52 if (!table)
53 return;
54
55 memset(&nh_p, 0, sizeof(nh_p));
56 if (si->type == STATIC_BLACKHOLE) {
57 switch (si->bh_type) {
58 case STATIC_BLACKHOLE_DROP:
59 case STATIC_BLACKHOLE_NULL:
60 bh_type = BLACKHOLE_NULL;
61 break;
62 case STATIC_BLACKHOLE_REJECT:
63 bh_type = BLACKHOLE_REJECT;
64 break;
65 }
66 }
67
68 /* Lookup existing route */
69 rn = srcdest_rnode_get(table, p, src_p);
70 RNODE_FOREACH_RE (rn, re) {
71 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
72 continue;
73
74 if (re->type == ZEBRA_ROUTE_STATIC
75 && re->distance == si->distance)
76 break;
77 }
78
79 if (re) {
80 /* if tag value changed , update old value in RIB */
81 if (re->tag != si->tag)
82 re->tag = si->tag;
83
84 /* Same distance static route is there. Update it with new
85 nexthop. */
86 route_unlock_node(rn);
87 switch (si->type) {
88 case STATIC_IPV4_GATEWAY:
89 nexthop = route_entry_nexthop_ipv4_add(
90 re, &si->addr.ipv4, NULL);
91 nh_p.family = AF_INET;
92 nh_p.prefixlen = IPV4_MAX_BITLEN;
93 nh_p.u.prefix4 = si->addr.ipv4;
94 zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
95 break;
96 case STATIC_IPV4_GATEWAY_IFNAME:
97 nexthop = route_entry_nexthop_ipv4_ifindex_add(
98 re, &si->addr.ipv4, NULL, si->ifindex);
99 break;
100 case STATIC_IFNAME:
101 nexthop = route_entry_nexthop_ifindex_add(re,
102 si->ifindex);
103 break;
104 case STATIC_BLACKHOLE:
105 nexthop = route_entry_nexthop_blackhole_add(
106 re, bh_type);
107 break;
108 case STATIC_IPV6_GATEWAY:
109 nexthop = route_entry_nexthop_ipv6_add(re,
110 &si->addr.ipv6);
111 nh_p.family = AF_INET6;
112 nh_p.prefixlen = IPV6_MAX_BITLEN;
113 nh_p.u.prefix6 = si->addr.ipv6;
114 zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
115 break;
116 case STATIC_IPV6_GATEWAY_IFNAME:
117 nexthop = route_entry_nexthop_ipv6_ifindex_add(
118 re, &si->addr.ipv6, si->ifindex);
119 break;
120 }
121 /* Update label(s), if present. */
122 if (si->snh_label.num_labels)
123 nexthop_add_labels(nexthop, ZEBRA_LSP_STATIC,
124 si->snh_label.num_labels,
125 &si->snh_label.label[0]);
126
127 if (IS_ZEBRA_DEBUG_RIB) {
128 char buf[INET6_ADDRSTRLEN];
129 if (IS_ZEBRA_DEBUG_RIB) {
130 inet_ntop(p->family, &p->u.prefix, buf,
131 INET6_ADDRSTRLEN);
132 zlog_debug(
133 "%u:%s/%d: Modifying route rn %p, re %p (type %d)",
134 si->vrf_id, buf, p->prefixlen, rn, re,
135 re->type);
136 }
137 }
138
139 re->uptime = time(NULL);
140 /* Schedule route for processing or invoke NHT, as appropriate.
141 */
142 if (si->type == STATIC_IPV4_GATEWAY
143 || si->type == STATIC_IPV6_GATEWAY)
144 zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1,
145 RNH_NEXTHOP_TYPE, &nh_p);
146 else
147 rib_queue_add(rn);
148 } else {
149 /* This is new static route. */
150 re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
151
152 re->type = ZEBRA_ROUTE_STATIC;
153 re->instance = 0;
154 re->distance = si->distance;
155 re->metric = 0;
156 re->mtu = 0;
157 re->vrf_id = si->vrf_id;
158 re->nh_vrf_id = si->vrf_id;
159 re->table =
160 si->vrf_id
161 ? (zebra_vrf_lookup_by_id(si->vrf_id))->table_id
162 : zebrad.rtm_table_default;
163 re->nexthop_num = 0;
164 re->tag = si->tag;
165
166 switch (si->type) {
167 case STATIC_IPV4_GATEWAY:
168 nexthop = route_entry_nexthop_ipv4_add(
169 re, &si->addr.ipv4, NULL);
170 nh_p.family = AF_INET;
171 nh_p.prefixlen = IPV4_MAX_BITLEN;
172 nh_p.u.prefix4 = si->addr.ipv4;
173 zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
174 break;
175 case STATIC_IPV4_GATEWAY_IFNAME:
176 nexthop = route_entry_nexthop_ipv4_ifindex_add(
177 re, &si->addr.ipv4, NULL, si->ifindex);
178 break;
179 case STATIC_IFNAME:
180 nexthop = route_entry_nexthop_ifindex_add(re,
181 si->ifindex);
182 break;
183 case STATIC_BLACKHOLE:
184 nexthop = route_entry_nexthop_blackhole_add(
185 re, bh_type);
186 break;
187 case STATIC_IPV6_GATEWAY:
188 nexthop = route_entry_nexthop_ipv6_add(re,
189 &si->addr.ipv6);
190 nh_p.family = AF_INET6;
191 nh_p.prefixlen = IPV6_MAX_BITLEN;
192 nh_p.u.prefix6 = si->addr.ipv6;
193 zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
194 break;
195 case STATIC_IPV6_GATEWAY_IFNAME:
196 nexthop = route_entry_nexthop_ipv6_ifindex_add(
197 re, &si->addr.ipv6, si->ifindex);
198 break;
199 }
200 /* Update label(s), if present. */
201 if (si->snh_label.num_labels)
202 nexthop_add_labels(nexthop, ZEBRA_LSP_STATIC,
203 si->snh_label.num_labels,
204 &si->snh_label.label[0]);
205
206 if (IS_ZEBRA_DEBUG_RIB) {
207 char buf[INET6_ADDRSTRLEN];
208 if (IS_ZEBRA_DEBUG_RIB) {
209 inet_ntop(p->family, &p->u.prefix, buf,
210 INET6_ADDRSTRLEN);
211 zlog_debug(
212 "%u:%s/%d: Inserting route rn %p, re %p (type %d)",
213 si->vrf_id, buf, p->prefixlen, rn, re,
214 re->type);
215 }
216 }
217 re->uptime = time(NULL);
218 /* Link this re to the tree. Schedule for processing or invoke
219 * NHT,
220 * as appropriate.
221 */
222 if (si->type == STATIC_IPV4_GATEWAY
223 || si->type == STATIC_IPV6_GATEWAY) {
224 rib_addnode(rn, re, 0);
225 zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1,
226 RNH_NEXTHOP_TYPE, &nh_p);
227 } else
228 rib_addnode(rn, re, 1);
229 }
230 }
231
232 /* this works correctly with IFNAME<>IFINDEX because a static route on a
233 * non-active interface will have IFINDEX_INTERNAL and thus compare false
234 */
235 static int static_nexthop_same(struct nexthop *nexthop, struct static_route *si)
236 {
237 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
238 && si->type == STATIC_BLACKHOLE)
239 return 1;
240
241 if (nexthop->type == NEXTHOP_TYPE_IPV4
242 && si->type == STATIC_IPV4_GATEWAY
243 && IPV4_ADDR_SAME(&nexthop->gate.ipv4, &si->addr.ipv4))
244 return 1;
245 else if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
246 && si->type == STATIC_IPV4_GATEWAY_IFNAME
247 && IPV4_ADDR_SAME(&nexthop->gate.ipv4, &si->addr.ipv4)
248 && nexthop->ifindex == si->ifindex)
249 return 1;
250 else if (nexthop->type == NEXTHOP_TYPE_IFINDEX
251 && si->type == STATIC_IFNAME
252 && nexthop->ifindex == si->ifindex)
253 return 1;
254 else if (nexthop->type == NEXTHOP_TYPE_IPV6
255 && si->type == STATIC_IPV6_GATEWAY
256 && IPV6_ADDR_SAME(&nexthop->gate.ipv6, &si->addr.ipv6))
257 return 1;
258 else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
259 && si->type == STATIC_IPV6_GATEWAY_IFNAME
260 && IPV6_ADDR_SAME(&nexthop->gate.ipv6, &si->addr.ipv6)
261 && nexthop->ifindex == si->ifindex)
262 return 1;
263
264 return 0;
265 }
266
267 /* Uninstall static route from RIB. */
268 void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p,
269 struct prefix_ipv6 *src_p, struct static_route *si)
270 {
271 struct route_node *rn;
272 struct route_entry *re;
273 struct nexthop *nexthop;
274 struct route_table *table;
275 struct prefix nh_p;
276
277 /* Lookup table. */
278 table = zebra_vrf_table(afi, safi, si->vrf_id);
279 if (!table)
280 return;
281
282 /* Lookup existing route with type and distance. */
283 rn = srcdest_rnode_lookup(table, p, src_p);
284 if (!rn)
285 return;
286
287 RNODE_FOREACH_RE (rn, re) {
288 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
289 continue;
290
291 if (re->type == ZEBRA_ROUTE_STATIC
292 && re->distance == si->distance && re->tag == si->tag)
293 break;
294 }
295
296 if (!re) {
297 route_unlock_node(rn);
298 return;
299 }
300
301 /* Lookup nexthop. */
302 for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next)
303 if (static_nexthop_same(nexthop, si))
304 break;
305
306 /* Can't find nexthop. */
307 if (!nexthop) {
308 route_unlock_node(rn);
309 return;
310 }
311
312 /* Check nexthop. */
313 if (re->nexthop_num == 1)
314 rib_delnode(rn, re);
315 else {
316 /* Mark this nexthop as inactive and reinstall the route. Then,
317 * delete
318 * the nexthop. There is no need to re-evaluate the route for
319 * this
320 * scenario.
321 */
322 if (IS_ZEBRA_DEBUG_RIB) {
323 char buf[INET6_ADDRSTRLEN];
324 if (IS_ZEBRA_DEBUG_RIB) {
325 inet_ntop(p->family, &p->u.prefix, buf,
326 INET6_ADDRSTRLEN);
327 zlog_debug(
328 "%u:%s/%d: Modifying route rn %p, re %p (type %d)",
329 si->vrf_id, buf, p->prefixlen, rn, re,
330 re->type);
331 }
332 }
333 UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
334 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) {
335 rib_dest_t *dest = rib_dest_from_rnode(rn);
336
337 /* If there are other active nexthops, do an update. */
338 if (re->nexthop_active_num > 1) {
339 /* Update route in kernel if it's in fib */
340 if (dest->selected_fib)
341 rib_install_kernel(rn, re, re);
342 /* Update redistribution if it's selected */
343 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
344 redistribute_update(
345 p, (struct prefix *)src_p, re,
346 NULL);
347 } else {
348 /* Remove from redistribute if selected route
349 * becomes inactive */
350 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
351 redistribute_delete(
352 p, (struct prefix *)src_p, re);
353 /* Remove from kernel if fib route becomes
354 * inactive */
355 if (dest->selected_fib)
356 rib_uninstall_kernel(rn, re);
357 }
358 }
359
360 if (afi == AFI_IP) {
361 /* Delete the nexthop and dereg from NHT */
362 nh_p.family = AF_INET;
363 nh_p.prefixlen = IPV4_MAX_BITLEN;
364 nh_p.u.prefix4 = nexthop->gate.ipv4;
365 } else {
366 nh_p.family = AF_INET6;
367 nh_p.prefixlen = IPV6_MAX_BITLEN;
368 nh_p.u.prefix6 = nexthop->gate.ipv6;
369 }
370 route_entry_nexthop_delete(re, nexthop);
371 zebra_deregister_rnh_static_nh(si->vrf_id, &nh_p, rn);
372 nexthop_free(nexthop);
373 }
374 /* Unlock node. */
375 route_unlock_node(rn);
376 }
377
378 int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
379 struct prefix_ipv6 *src_p, union g_addr *gate,
380 const char *ifname, enum static_blackhole_type bh_type,
381 route_tag_t tag, u_char distance, struct zebra_vrf *zvrf,
382 struct static_nh_label *snh_label)
383 {
384 struct route_node *rn;
385 struct static_route *si;
386 struct static_route *pp;
387 struct static_route *cp;
388 struct static_route *update = NULL;
389 struct route_table *stable = zvrf->stable[afi][safi];
390
391 if (!stable)
392 return -1;
393
394 if (!gate
395 && (type == STATIC_IPV4_GATEWAY
396 || type == STATIC_IPV4_GATEWAY_IFNAME
397 || type == STATIC_IPV6_GATEWAY
398 || type == STATIC_IPV6_GATEWAY_IFNAME))
399 return -1;
400
401 if (!ifname
402 && (type == STATIC_IFNAME
403 || type == STATIC_IPV4_GATEWAY_IFNAME
404 || type == STATIC_IPV6_GATEWAY_IFNAME))
405 return -1;
406
407 /* Lookup static route prefix. */
408 rn = srcdest_rnode_get(stable, p, src_p);
409
410 /* Do nothing if there is a same static route. */
411 for (si = rn->info; si; si = si->next) {
412 if (type == si->type
413 && (!gate || ((afi == AFI_IP
414 && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
415 || (afi == AFI_IP6
416 && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
417 && (!strcmp (ifname ? ifname : "", si->ifname))) {
418 if ((distance == si->distance) && (tag == si->tag)
419 && !memcmp(&si->snh_label, snh_label,
420 sizeof(struct static_nh_label))
421 && si->bh_type == bh_type) {
422 route_unlock_node(rn);
423 return 0;
424 } else
425 update = si;
426 }
427 }
428
429 /* Distance or tag or label changed, delete existing first. */
430 if (update)
431 static_delete_route(afi, safi, type, p, src_p, gate, ifname,
432 update->tag, update->distance, zvrf,
433 &update->snh_label);
434
435 /* Make new static route structure. */
436 si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route));
437
438 si->type = type;
439 si->distance = distance;
440 si->bh_type = bh_type;
441 si->tag = tag;
442 si->vrf_id = zvrf_id(zvrf);
443 if (ifname)
444 strlcpy(si->ifname, ifname, sizeof(si->ifname));
445 si->ifindex = IFINDEX_INTERNAL;
446
447 switch (type) {
448 case STATIC_IPV4_GATEWAY:
449 case STATIC_IPV4_GATEWAY_IFNAME:
450 si->addr.ipv4 = gate->ipv4;
451 break;
452 case STATIC_IPV6_GATEWAY:
453 case STATIC_IPV6_GATEWAY_IFNAME:
454 si->addr.ipv6 = gate->ipv6;
455 break;
456 case STATIC_IFNAME:
457 break;
458 }
459
460 /* Save labels, if any. */
461 memcpy(&si->snh_label, snh_label, sizeof(struct static_nh_label));
462
463 /* Add new static route information to the tree with sort by
464 distance value and gateway address. */
465 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) {
466 if (si->distance < cp->distance)
467 break;
468 if (si->distance > cp->distance)
469 continue;
470 if (si->type == STATIC_IPV4_GATEWAY
471 && cp->type == STATIC_IPV4_GATEWAY) {
472 if (ntohl(si->addr.ipv4.s_addr)
473 < ntohl(cp->addr.ipv4.s_addr))
474 break;
475 if (ntohl(si->addr.ipv4.s_addr)
476 > ntohl(cp->addr.ipv4.s_addr))
477 continue;
478 }
479 }
480
481 /* Make linked list. */
482 if (pp)
483 pp->next = si;
484 else
485 rn->info = si;
486 if (cp)
487 cp->prev = si;
488 si->prev = pp;
489 si->next = cp;
490
491 /* check whether interface exists in system & install if it does */
492 if (!ifname)
493 static_install_route(afi, safi, p, src_p, si);
494 else {
495 struct interface *ifp;
496
497 ifp = if_lookup_by_name(ifname, zvrf_id(zvrf));
498 if (ifp && ifp->ifindex != IFINDEX_INTERNAL) {
499 si->ifindex = ifp->ifindex;
500 static_install_route(afi, safi, p, src_p, si);
501 }
502 }
503
504 return 1;
505 }
506
507 int static_delete_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
508 struct prefix_ipv6 *src_p, union g_addr *gate,
509 const char *ifname, route_tag_t tag, u_char distance,
510 struct zebra_vrf *zvrf,
511 struct static_nh_label *snh_label)
512 {
513 struct route_node *rn;
514 struct static_route *si;
515 struct route_table *stable;
516
517 /* Lookup table. */
518 stable = zebra_vrf_static_table(afi, safi, zvrf);
519 if (!stable)
520 return -1;
521
522 /* Lookup static route prefix. */
523 rn = srcdest_rnode_lookup(stable, p, src_p);
524 if (!rn)
525 return 0;
526
527 /* Find same static route is the tree */
528 for (si = rn->info; si; si = si->next)
529 if (type == si->type
530 && (!gate || ((afi == AFI_IP
531 && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
532 || (afi == AFI_IP6
533 && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
534 && (!strcmp(ifname ? ifname : "", si->ifname))
535 && (!tag || (tag == si->tag))
536 && (!snh_label->num_labels
537 || !memcmp(&si->snh_label, snh_label,
538 sizeof(struct static_nh_label))))
539 break;
540
541 /* Can't find static route. */
542 if (!si) {
543 route_unlock_node(rn);
544 return 0;
545 }
546
547 /* Uninstall from rib. */
548 if (!si->ifname[0] || si->ifindex != IFINDEX_INTERNAL)
549 static_uninstall_route(afi, safi, p, src_p, si);
550
551 /* Unlink static route from linked list. */
552 if (si->prev)
553 si->prev->next = si->next;
554 else
555 rn->info = si->next;
556 if (si->next)
557 si->next->prev = si->prev;
558 route_unlock_node(rn);
559
560 /* Free static route configuration. */
561 XFREE(MTYPE_STATIC_ROUTE, si);
562
563 route_unlock_node(rn);
564
565 return 1;
566 }
567
568 static void static_ifindex_update_af(struct interface *ifp, bool up,
569 afi_t afi, safi_t safi)
570 {
571 struct route_table *stable;
572 struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
573 struct route_node *rn;
574 struct static_route *si;
575 struct prefix *p, *src_pp;
576 struct prefix_ipv6 *src_p;
577
578 stable = zebra_vrf_static_table(afi, safi, zvrf);
579 if (!stable)
580 return;
581
582 for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) {
583 srcdest_rnode_prefixes(rn, &p, &src_pp);
584 src_p = (struct prefix_ipv6 *)src_pp;
585
586 for (si = rn->info; si; si = si->next) {
587 if (!si->ifname[0])
588 continue;
589 if (up) {
590 if (strcmp(si->ifname, ifp->name))
591 continue;
592 si->ifindex = ifp->ifindex;
593 static_install_route(afi, safi, p, src_p, si);
594 } else {
595 if (si->ifindex != ifp->ifindex)
596 continue;
597 static_uninstall_route(afi, safi, p, src_p,
598 si);
599 si->ifindex = IFINDEX_INTERNAL;
600 }
601 }
602 }
603 }
604
605 /* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
606 void static_ifindex_update(struct interface *ifp, bool up)
607 {
608 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_UNICAST);
609 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_MULTICAST);
610 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_UNICAST);
611 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_MULTICAST);
612 }