]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_route.c
*: un-split strings across lines
[mirror_frr.git] / ospfd / ospf_route.c
CommitLineData
718e3744 1/*
2 * OSPF routing table.
3 * Copyright (C) 1999, 2000 Toshiaki Takada
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
896014f4
DL
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
718e3744 20 */
21
22#include <zebra.h>
23
24#include "prefix.h"
25#include "table.h"
26#include "memory.h"
27#include "linklist.h"
28#include "log.h"
29#include "if.h"
30#include "command.h"
31#include "sockunion.h"
32
33#include "ospfd/ospfd.h"
34#include "ospfd/ospf_interface.h"
35#include "ospfd/ospf_asbr.h"
36#include "ospfd/ospf_lsa.h"
37#include "ospfd/ospf_route.h"
38#include "ospfd/ospf_spf.h"
39#include "ospfd/ospf_zebra.h"
40#include "ospfd/ospf_dump.h"
41
4d762f26 42struct ospf_route *ospf_route_new(void)
718e3744 43{
d62a17ae 44 struct ospf_route *new;
718e3744 45
d62a17ae 46 new = XCALLOC(MTYPE_OSPF_ROUTE, sizeof(struct ospf_route));
718e3744 47
d62a17ae 48 new->paths = list_new();
49 new->paths->del = (void (*)(void *))ospf_path_free;
718e3744 50
d62a17ae 51 return new;
718e3744 52}
53
4d762f26 54void ospf_route_free(struct ospf_route *or)
718e3744 55{
d62a17ae 56 if (or->paths)
6a154c88 57 list_delete(& or->paths);
718e3744 58
d62a17ae 59 XFREE(MTYPE_OSPF_ROUTE, or);
718e3744 60}
61
4d762f26 62struct ospf_path *ospf_path_new(void)
718e3744 63{
d62a17ae 64 struct ospf_path *new;
718e3744 65
d62a17ae 66 new = XCALLOC(MTYPE_OSPF_PATH, sizeof(struct ospf_path));
718e3744 67
d62a17ae 68 return new;
718e3744 69}
70
d62a17ae 71static struct ospf_path *ospf_path_dup(struct ospf_path *path)
718e3744 72{
d62a17ae 73 struct ospf_path *new;
718e3744 74
d62a17ae 75 new = ospf_path_new();
76 memcpy(new, path, sizeof(struct ospf_path));
718e3744 77
d62a17ae 78 return new;
718e3744 79}
80
d62a17ae 81void ospf_path_free(struct ospf_path *op)
718e3744 82{
d62a17ae 83 XFREE(MTYPE_OSPF_PATH, op);
718e3744 84}
85
b5a8894d 86void ospf_route_delete(struct ospf *ospf, struct route_table *rt)
718e3744 87{
d62a17ae 88 struct route_node *rn;
89 struct ospf_route * or ;
90
91 for (rn = route_top(rt); rn; rn = route_next(rn))
92 if ((or = rn->info) != NULL) {
93 if (or->type == OSPF_DESTINATION_NETWORK)
996c9314
LB
94 ospf_zebra_delete(
95 ospf, (struct prefix_ipv4 *)&rn->p, or);
d62a17ae 96 else if (or->type == OSPF_DESTINATION_DISCARD)
996c9314
LB
97 ospf_zebra_delete_discard(
98 ospf, (struct prefix_ipv4 *)&rn->p);
d62a17ae 99 }
718e3744 100}
101
d62a17ae 102void ospf_route_table_free(struct route_table *rt)
718e3744 103{
d62a17ae 104 struct route_node *rn;
105 struct ospf_route * or ;
718e3744 106
d62a17ae 107 for (rn = route_top(rt); rn; rn = route_next(rn))
108 if ((or = rn->info) != NULL) {
109 ospf_route_free(or);
718e3744 110
d62a17ae 111 rn->info = NULL;
112 route_unlock_node(rn);
113 }
718e3744 114
d62a17ae 115 route_table_finish(rt);
718e3744 116}
117
16a86b3e
AB
118/* If a prefix exists in the new routing table, then return 1,
119 otherwise return 0. Since the ZEBRA-RIB does an implicit
120 withdraw, it is not necessary to send a delete, an add later
121 will act like an implicit delete. */
d62a17ae 122static int ospf_route_exist_new_table(struct route_table *rt,
123 struct prefix_ipv4 *prefix)
16a86b3e 124{
d62a17ae 125 struct route_node *rn;
16a86b3e 126
d62a17ae 127 assert(rt);
128 assert(prefix);
16a86b3e 129
d62a17ae 130 rn = route_node_lookup(rt, (struct prefix *)prefix);
131 if (!rn) {
132 return 0;
133 }
134 route_unlock_node(rn);
16a86b3e 135
d62a17ae 136 if (!rn->info) {
137 return 0;
138 }
16a86b3e 139
d62a17ae 140 return 1;
16a86b3e
AB
141}
142
718e3744 143/* If a prefix and a nexthop match any route in the routing table,
144 then return 1, otherwise return 0. */
d62a17ae 145int ospf_route_match_same(struct route_table *rt, struct prefix_ipv4 *prefix,
146 struct ospf_route *newor)
718e3744 147{
d62a17ae 148 struct route_node *rn;
149 struct ospf_route * or ;
150 struct ospf_path *op;
151 struct ospf_path *newop;
152 struct listnode *n1;
153 struct listnode *n2;
154
155 if (!rt || !prefix)
156 return 0;
157
158 rn = route_node_lookup(rt, (struct prefix *)prefix);
159 if (!rn || !rn->info)
160 return 0;
161
162 route_unlock_node(rn);
163
164 or = rn->info;
165 if (or->type == newor->type && or->cost == newor->cost) {
166 if (or->type == OSPF_DESTINATION_NETWORK) {
167 if (or->paths->count != newor->paths->count)
168 return 0;
169
170 /* Check each path. */
171 for (n1 = listhead(or->paths),
172 n2 = listhead(newor->paths);
39050c7e 173 n1 && n2; n1 = listnextnode_unchecked(n1),
174 n2 = listnextnode_unchecked(n2)) {
d62a17ae 175 op = listgetdata(n1);
176 newop = listgetdata(n2);
177
178 if (!IPV4_ADDR_SAME(&op->nexthop,
179 &newop->nexthop))
180 return 0;
181 if (op->ifindex != newop->ifindex)
182 return 0;
183 }
184 return 1;
185 } else if (prefix_same(&rn->p, (struct prefix *)prefix))
186 return 1;
187 }
188 return 0;
718e3744 189}
190
6d1fab63 191/* delete routes generated from AS-External routes if there is a inter/intra
192 * area route
193 */
b5a8894d
CS
194static void ospf_route_delete_same_ext(struct ospf *ospf,
195 struct route_table *external_routes,
d62a17ae 196 struct route_table *routes)
6d1fab63 197{
d62a17ae 198 struct route_node *rn, *ext_rn;
199
200 if ((external_routes == NULL) || (routes == NULL))
201 return;
202
203 /* Remove deleted routes */
204 for (rn = route_top(routes); rn; rn = route_next(rn)) {
205 if (rn && rn->info) {
206 struct prefix_ipv4 *p = (struct prefix_ipv4 *)(&rn->p);
207 if ((ext_rn = route_node_lookup(external_routes,
208 (struct prefix *)p))) {
209 if (ext_rn->info) {
b5a8894d
CS
210 ospf_zebra_delete(ospf, p,
211 ext_rn->info);
d62a17ae 212 ospf_route_free(ext_rn->info);
213 ext_rn->info = NULL;
214 }
215 route_unlock_node(ext_rn);
216 }
217 }
218 }
6d1fab63 219}
220
718e3744 221/* rt: Old, cmprt: New */
b5a8894d 222static void ospf_route_delete_uniq(struct ospf *ospf, struct route_table *rt,
d62a17ae 223 struct route_table *cmprt)
718e3744 224{
d62a17ae 225 struct route_node *rn;
226 struct ospf_route * or ;
227
228 for (rn = route_top(rt); rn; rn = route_next(rn))
229 if ((or = rn->info) != NULL)
230 if (or->path_type == OSPF_PATH_INTRA_AREA ||
231 or->path_type == OSPF_PATH_INTER_AREA) {
232 if (or->type == OSPF_DESTINATION_NETWORK) {
233 if (!ospf_route_exist_new_table(
9d303b37
DL
234 cmprt,
235 (struct prefix_ipv4 *)&rn
236 ->p))
996c9314
LB
237 ospf_zebra_delete(
238 ospf,
d62a17ae 239 (struct prefix_ipv4
240 *)&rn->p,
241 or);
242 } else if (or->type == OSPF_DESTINATION_DISCARD)
243 if (!ospf_route_exist_new_table(
9d303b37
DL
244 cmprt,
245 (struct prefix_ipv4 *)&rn
246 ->p))
996c9314
LB
247 ospf_zebra_delete_discard(
248 ospf,
d62a17ae 249 (struct prefix_ipv4
250 *)&rn->p);
251 }
718e3744 252}
253
254/* Install routes to table. */
d62a17ae 255void ospf_route_install(struct ospf *ospf, struct route_table *rt)
718e3744 256{
d62a17ae 257 struct route_node *rn;
258 struct ospf_route * or ;
259
260 /* rt contains new routing table, new_table contains an old one.
261 updating pointers */
262 if (ospf->old_table)
263 ospf_route_table_free(ospf->old_table);
264
265 ospf->old_table = ospf->new_table;
266 ospf->new_table = rt;
267
268 /* Delete old routes. */
269 if (ospf->old_table)
b5a8894d 270 ospf_route_delete_uniq(ospf, ospf->old_table, rt);
d62a17ae 271 if (ospf->old_external_route)
b5a8894d 272 ospf_route_delete_same_ext(ospf, ospf->old_external_route, rt);
d62a17ae 273
274 /* Install new routes. */
275 for (rn = route_top(rt); rn; rn = route_next(rn))
276 if ((or = rn->info) != NULL) {
277 if (or->type == OSPF_DESTINATION_NETWORK) {
278 if (!ospf_route_match_same(
279 ospf->old_table,
280 (struct prefix_ipv4 *)&rn->p, or))
996c9314
LB
281 ospf_zebra_add(
282 ospf,
d62a17ae 283 (struct prefix_ipv4 *)&rn->p,
284 or);
285 } else if (or->type == OSPF_DESTINATION_DISCARD)
286 if (!ospf_route_match_same(
287 ospf->old_table,
288 (struct prefix_ipv4 *)&rn->p, or))
996c9314
LB
289 ospf_zebra_add_discard(
290 ospf,
d62a17ae 291 (struct prefix_ipv4 *)&rn->p);
292 }
718e3744 293}
294
718e3744 295/* RFC2328 16.1. (4). For "router". */
d62a17ae 296void ospf_intra_add_router(struct route_table *rt, struct vertex *v,
297 struct ospf_area *area)
718e3744 298{
d62a17ae 299 struct route_node *rn;
300 struct ospf_route * or ;
301 struct prefix_ipv4 p;
302 struct router_lsa *lsa;
303
304 if (IS_DEBUG_OSPF_EVENT)
305 zlog_debug("ospf_intra_add_router: Start");
306
307 lsa = (struct router_lsa *)v->lsa;
308
309 if (IS_DEBUG_OSPF_EVENT)
310 zlog_debug("ospf_intra_add_router: LS ID: %s",
311 inet_ntoa(lsa->header.id));
312
313 if (!OSPF_IS_AREA_BACKBONE(area))
314 ospf_vl_up_check(area, lsa->header.id, v);
315
316 if (!CHECK_FLAG(lsa->flags, ROUTER_LSA_SHORTCUT))
317 area->shortcut_capability = 0;
318
319 /* If the newly added vertex is an area border router or AS boundary
320 router, a routing table entry is added whose destination type is
321 "router". */
322 if (!IS_ROUTER_LSA_BORDER(lsa) && !IS_ROUTER_LSA_EXTERNAL(lsa)) {
323 if (IS_DEBUG_OSPF_EVENT)
324 zlog_debug(
3efd0893 325 "ospf_intra_add_router: this router is neither ASBR nor ABR, skipping it");
d62a17ae 326 return;
327 }
328
329 /* Update ABR and ASBR count in this area. */
330 if (IS_ROUTER_LSA_BORDER(lsa))
331 area->abr_count++;
332 if (IS_ROUTER_LSA_EXTERNAL(lsa))
333 area->asbr_count++;
334
335 /* The Options field found in the associated router-LSA is copied
336 into the routing table entry's Optional capabilities field. Call
337 the newly added vertex Router X. */
338 or = ospf_route_new();
339
340 or->id = v->id;
341 or->u.std.area_id = area->area_id;
342 or->u.std.external_routing = area->external_routing;
343 or->path_type = OSPF_PATH_INTRA_AREA;
344 or->cost = v->distance;
345 or->type = OSPF_DESTINATION_ROUTER;
346 or->u.std.origin = (struct lsa_header *)lsa;
347 or->u.std.options = lsa->header.options;
348 or->u.std.flags = lsa->flags;
349
350 /* If Router X is the endpoint of one of the calculating router's
351 virtual links, and the virtual link uses Area A as Transit area:
352 the virtual link is declared up, the IP address of the virtual
353 interface is set to the IP address of the outgoing interface
354 calculated above for Router X, and the virtual neighbor's IP
355 address is set to Router X's interface address (contained in
356 Router X's router-LSA) that points back to the root of the
357 shortest- path tree; equivalently, this is the interface that
358 points back to Router X's parent vertex on the shortest-path tree
359 (similar to the calculation in Section 16.1.1). */
360
361 p.family = AF_INET;
362 p.prefix = v->id;
363 p.prefixlen = IPV4_MAX_BITLEN;
a6435618 364 apply_mask_ipv4(&p);
d62a17ae 365
366 if (IS_DEBUG_OSPF_EVENT)
367 zlog_debug("ospf_intra_add_router: talking about %s/%d",
368 inet_ntoa(p.prefix), p.prefixlen);
369
370 rn = route_node_get(rt, (struct prefix *)&p);
371
372 /* Note that we keep all routes to ABRs and ASBRs, not only the best */
373 if (rn->info == NULL)
374 rn->info = list_new();
375 else
376 route_unlock_node(rn);
377
378 ospf_route_copy_nexthops_from_vertex(or, v);
379
380 listnode_add(rn->info, or);
381
382 if (IS_DEBUG_OSPF_EVENT)
383 zlog_debug("ospf_intra_add_router: Stop");
718e3744 384}
385
386/* RFC2328 16.1. (4). For transit network. */
d62a17ae 387void ospf_intra_add_transit(struct route_table *rt, struct vertex *v,
388 struct ospf_area *area)
718e3744 389{
d62a17ae 390 struct route_node *rn;
391 struct ospf_route * or ;
392 struct prefix_ipv4 p;
393 struct network_lsa *lsa;
394
395 lsa = (struct network_lsa *)v->lsa;
396
397 /* If the newly added vertex is a transit network, the routing table
398 entry for the network is located. The entry's Destination ID is
399 the IP network number, which can be obtained by masking the
400 Vertex ID (Link State ID) with its associated subnet mask (found
401 in the body of the associated network-LSA). */
402 p.family = AF_INET;
403 p.prefix = v->id;
404 p.prefixlen = ip_masklen(lsa->mask);
405 apply_mask_ipv4(&p);
406
407 rn = route_node_get(rt, (struct prefix *)&p);
408
409 /* If the routing table entry already exists (i.e., there is already
410 an intra-area route to the destination installed in the routing
411 table), multiple vertices have mapped to the same IP network.
412 For example, this can occur when a new Designated Router is being
413 established. In this case, the current routing table entry
414 should be overwritten if and only if the newly found path is just
415 as short and the current routing table entry's Link State Origin
416 has a smaller Link State ID than the newly added vertex' LSA. */
417 if (rn->info) {
418 struct ospf_route *cur_or;
419
420 route_unlock_node(rn);
421 cur_or = rn->info;
422
423 if (v->distance > cur_or->cost
424 || IPV4_ADDR_CMP(&cur_or->u.std.origin->id, &lsa->header.id)
425 > 0)
426 return;
427
428 ospf_route_free(rn->info);
429 }
430
431 or = ospf_route_new();
432
433 or->id = v->id;
434 or->u.std.area_id = area->area_id;
435 or->u.std.external_routing = area->external_routing;
436 or->path_type = OSPF_PATH_INTRA_AREA;
437 or->cost = v->distance;
438 or->type = OSPF_DESTINATION_NETWORK;
439 or->u.std.origin = (struct lsa_header *)lsa;
440
441 ospf_route_copy_nexthops_from_vertex(or, v);
442
443 rn->info = or ;
718e3744 444}
445
446/* RFC2328 16.1. second stage. */
d62a17ae 447void ospf_intra_add_stub(struct route_table *rt, struct router_lsa_link *link,
448 struct vertex *v, struct ospf_area *area,
449 int parent_is_root, int lsa_pos)
718e3744 450{
d7c0a89a 451 uint32_t cost;
d62a17ae 452 struct route_node *rn;
453 struct ospf_route * or ;
454 struct prefix_ipv4 p;
455 struct router_lsa *lsa;
456 struct ospf_interface *oi;
457 struct ospf_path *path;
458
459 if (IS_DEBUG_OSPF_EVENT)
460 zlog_debug("ospf_intra_add_stub(): Start");
461
462 lsa = (struct router_lsa *)v->lsa;
463
464 p.family = AF_INET;
465 p.prefix = link->link_id;
466 p.prefixlen = ip_masklen(link->link_data);
467 apply_mask_ipv4(&p);
468
469 if (IS_DEBUG_OSPF_EVENT)
470 zlog_debug("ospf_intra_add_stub(): processing route to %s/%d",
471 inet_ntoa(p.prefix), p.prefixlen);
472
473 /* (1) Calculate the distance D of stub network from the root. D is
474 equal to the distance from the root to the router vertex
475 (calculated in stage 1), plus the stub network link's advertised
476 cost. */
477 cost = v->distance + ntohs(link->m[0].metric);
478
479 if (IS_DEBUG_OSPF_EVENT)
480 zlog_debug(
481 "ospf_intra_add_stub(): calculated cost is %d + %d = %d",
482 v->distance, ntohs(link->m[0].metric), cost);
483
484 /* PtP links with /32 masks adds host routes to remote, directly
485 * connected hosts, see RFC 2328, 12.4.1.1, Option 1.
486 * Such routes can just be ignored for the sake of tidyness.
487 */
488 if (parent_is_root && link->link_data.s_addr == 0xffffffff
489 && ospf_if_lookup_by_local_addr(area->ospf, NULL, link->link_id)) {
490 if (IS_DEBUG_OSPF_EVENT)
491 zlog_debug("%s: ignoring host route %s/32 to self.",
492 __func__, inet_ntoa(link->link_id));
493 return;
718e3744 494 }
495
d62a17ae 496 rn = route_node_get(rt, (struct prefix *)&p);
718e3744 497
d62a17ae 498 /* Lookup current routing table. */
499 if (rn->info) {
500 struct ospf_route *cur_or;
718e3744 501
d62a17ae 502 route_unlock_node(rn);
718e3744 503
d62a17ae 504 cur_or = rn->info;
718e3744 505
d62a17ae 506 if (IS_DEBUG_OSPF_EVENT)
507 zlog_debug(
3efd0893 508 "ospf_intra_add_stub(): another route to the same prefix found with cost %u",
d62a17ae 509 cur_or->cost);
510
511 /* Compare this distance to the current best cost to the stub
512 network. This is done by looking up the stub network's
513 current routing table entry. If the calculated distance D is
514 larger, go on to examine the next stub network link in the
515 LSA. */
516 if (cost > cur_or->cost) {
517 if (IS_DEBUG_OSPF_EVENT)
518 zlog_debug(
519 "ospf_intra_add_stub(): old route is better, exit");
520 return;
521 }
718e3744 522
d62a17ae 523 /* (2) If this step is reached, the stub network's routing table
524 entry must be updated. Calculate the set of next hops that
525 would result from using the stub network link. This
526 calculation is shown in Section 16.1.1; input to this
527 calculation is the destination (the stub network) and the
528 parent vertex (the router vertex). If the distance D is the
529 same as the current routing table cost, simply add this set
530 of next hops to the routing table entry's list of next hops.
531 In this case, the routing table already has a Link State
532 Origin. If this Link State Origin is a router-LSA whose Link
533 State ID is smaller than V's Router ID, reset the Link State
534 Origin to V's router-LSA. */
535
536 if (cost == cur_or->cost) {
537 if (IS_DEBUG_OSPF_EVENT)
538 zlog_debug(
539 "ospf_intra_add_stub(): routes are equal, merge");
540
541 ospf_route_copy_nexthops_from_vertex(cur_or, v);
542
543 if (IPV4_ADDR_CMP(&cur_or->u.std.origin->id,
544 &lsa->header.id)
545 < 0)
546 cur_or->u.std.origin = (struct lsa_header *)lsa;
547 return;
548 }
718e3744 549
d62a17ae 550 /* Otherwise D is smaller than the routing table cost.
551 Overwrite the current routing table entry by setting the
552 routing table entry's cost to D, and by setting the entry's
553 list of next hops to the newly calculated set. Set the
554 routing table entry's Link State Origin to V's router-LSA.
555 Then go on to examine the next stub network link. */
718e3744 556
d62a17ae 557 if (cost < cur_or->cost) {
558 if (IS_DEBUG_OSPF_EVENT)
559 zlog_debug(
560 "ospf_intra_add_stub(): new route is better, set it");
718e3744 561
d62a17ae 562 cur_or->cost = cost;
563
564 list_delete_all_node(cur_or->paths);
565
566 ospf_route_copy_nexthops_from_vertex(cur_or, v);
567
568 cur_or->u.std.origin = (struct lsa_header *)lsa;
569 return;
570 }
718e3744 571 }
d62a17ae 572
573 if (IS_DEBUG_OSPF_EVENT)
574 zlog_debug("ospf_intra_add_stub(): installing new route");
575
576 or = ospf_route_new();
577
578 or->id = v->id;
579 or->u.std.area_id = area->area_id;
580 or->u.std.external_routing = area->external_routing;
581 or->path_type = OSPF_PATH_INTRA_AREA;
582 or->cost = cost;
583 or->type = OSPF_DESTINATION_NETWORK;
584 or->u.std.origin = (struct lsa_header *)lsa;
585
586 /* Nexthop is depend on connection type. */
587 if (v != area->spf) {
588 if (IS_DEBUG_OSPF_EVENT)
589 zlog_debug(
590 "ospf_intra_add_stub(): this network is on remote router");
591 ospf_route_copy_nexthops_from_vertex(or, v);
592 } else {
593 if (IS_DEBUG_OSPF_EVENT)
594 zlog_debug(
595 "ospf_intra_add_stub(): this network is on this router");
596
597 if ((oi = ospf_if_lookup_by_lsa_pos(area, lsa_pos))) {
598 if (IS_DEBUG_OSPF_EVENT)
599 zlog_debug(
600 "ospf_intra_add_stub(): the interface is %s",
601 IF_NAME(oi));
602
603 path = ospf_path_new();
975a328e 604 path->nexthop.s_addr = INADDR_ANY;
d62a17ae 605 path->ifindex = oi->ifp->ifindex;
606 if (CHECK_FLAG(oi->connected->flags,
607 ZEBRA_IFA_UNNUMBERED))
608 path->unnumbered = 1;
609 listnode_add(or->paths, path);
610 } else {
611 if (IS_DEBUG_OSPF_EVENT)
612 zlog_debug(
613 "ospf_intra_add_stub(): where's the interface ?");
614 }
718e3744 615 }
718e3744 616
d62a17ae 617 rn->info = or ;
718e3744 618
d62a17ae 619 if (IS_DEBUG_OSPF_EVENT)
620 zlog_debug("ospf_intra_add_stub(): Stop");
718e3744 621}
622
2b64873d
DL
623static const char *const ospf_path_type_str[] = {
624 "unknown-type", "intra-area", "inter-area", "type1-external",
625 "type2-external"
626};
d62a17ae 627
628void ospf_route_table_dump(struct route_table *rt)
718e3744 629{
d62a17ae 630 struct route_node *rn;
631 struct ospf_route * or ;
d62a17ae 632 struct listnode *pnode;
633 struct ospf_path *path;
718e3744 634
d62a17ae 635 zlog_debug("========== OSPF routing table ==========");
636 for (rn = route_top(rt); rn; rn = route_next(rn))
637 if ((or = rn->info) != NULL) {
638 if (or->type == OSPF_DESTINATION_NETWORK) {
d6951e5e
DL
639 zlog_debug("N %-18pFX %-15pI4 %s %d", &rn->p,
640 &or->u.std.area_id,
d62a17ae 641 ospf_path_type_str[or->path_type],
642 or->cost);
643 for (ALL_LIST_ELEMENTS_RO(or->paths, pnode,
644 path))
645 zlog_debug(" -> %s",
646 inet_ntoa(path->nexthop));
647 } else
d6951e5e
DL
648 zlog_debug("R %-18pI4 %-15pI4 %s %d",
649 &rn->p.u.prefix4,
650 &or->u.std.area_id,
d62a17ae 651 ospf_path_type_str[or->path_type],
652 or->cost);
653 }
654 zlog_debug("========================================");
718e3744 655}
656
718e3744 657/* This is 16.4.1 implementation.
658 o Intra-area paths using non-backbone areas are always the most preferred.
659 o The other paths, intra-area backbone paths and inter-area paths,
660 are of equal preference. */
d62a17ae 661static int ospf_asbr_route_cmp(struct ospf *ospf, struct ospf_route *r1,
662 struct ospf_route *r2)
718e3744 663{
d7c0a89a 664 uint8_t r1_type, r2_type;
718e3744 665
d62a17ae 666 r1_type = r1->path_type;
667 r2_type = r2->path_type;
718e3744 668
d62a17ae 669 /* r1/r2 itself is backbone, and it's Inter-area path. */
670 if (OSPF_IS_AREA_ID_BACKBONE(r1->u.std.area_id))
671 r1_type = OSPF_PATH_INTER_AREA;
672 if (OSPF_IS_AREA_ID_BACKBONE(r2->u.std.area_id))
673 r2_type = OSPF_PATH_INTER_AREA;
718e3744 674
d62a17ae 675 return (r1_type - r2_type);
718e3744 676}
677
678/* Compare two routes.
679 ret < 0 -- r1 is better.
680 ret == 0 -- r1 and r2 are the same.
681 ret > 0 -- r2 is better. */
d62a17ae 682int ospf_route_cmp(struct ospf *ospf, struct ospf_route *r1,
683 struct ospf_route *r2)
718e3744 684{
d62a17ae 685 int ret = 0;
686
687 /* Path types of r1 and r2 are not the same. */
688 if ((ret = (r1->path_type - r2->path_type)))
689 return ret;
690
691 if (IS_DEBUG_OSPF_EVENT)
692 zlog_debug("Route[Compare]: Path types are the same.");
693 /* Path types are the same, compare any cost. */
694 switch (r1->path_type) {
695 case OSPF_PATH_INTRA_AREA:
696 case OSPF_PATH_INTER_AREA:
697 break;
698 case OSPF_PATH_TYPE1_EXTERNAL:
699 if (!CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) {
700 ret = ospf_asbr_route_cmp(ospf, r1->u.ext.asbr,
701 r2->u.ext.asbr);
702 if (ret != 0)
703 return ret;
704 }
705 break;
706 case OSPF_PATH_TYPE2_EXTERNAL:
707 if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
708 return ret;
709
710 if (!CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) {
711 ret = ospf_asbr_route_cmp(ospf, r1->u.ext.asbr,
712 r2->u.ext.asbr);
713 if (ret != 0)
714 return ret;
715 }
716 break;
718e3744 717 }
718e3744 718
d62a17ae 719 /* Anyway, compare the costs. */
720 return (r1->cost - r2->cost);
718e3744 721}
722
d62a17ae 723static int ospf_path_exist(struct list *plist, struct in_addr nexthop,
724 struct ospf_interface *oi)
718e3744 725{
d62a17ae 726 struct listnode *node, *nnode;
727 struct ospf_path *path;
718e3744 728
d62a17ae 729 for (ALL_LIST_ELEMENTS(plist, node, nnode, path))
730 if (IPV4_ADDR_SAME(&path->nexthop, &nexthop)
731 && path->ifindex == oi->ifp->ifindex)
732 return 1;
718e3744 733
d62a17ae 734 return 0;
718e3744 735}
736
d62a17ae 737void ospf_route_copy_nexthops_from_vertex(struct ospf_route *to,
738 struct vertex *v)
718e3744 739{
d62a17ae 740 struct listnode *node;
741 struct ospf_path *path;
742 struct vertex_nexthop *nexthop;
743 struct vertex_parent *vp;
744
745 assert(to->paths);
746
747 for (ALL_LIST_ELEMENTS_RO(v->parents, node, vp)) {
748 nexthop = vp->nexthop;
749
750 if (nexthop->oi != NULL) {
751 if (!ospf_path_exist(to->paths, nexthop->router,
752 nexthop->oi)) {
753 path = ospf_path_new();
754 path->nexthop = nexthop->router;
755 path->ifindex = nexthop->oi->ifp->ifindex;
756 if (CHECK_FLAG(nexthop->oi->connected->flags,
757 ZEBRA_IFA_UNNUMBERED))
758 path->unnumbered = 1;
759 listnode_add(to->paths, path);
760 }
761 }
718e3744 762 }
718e3744 763}
764
d62a17ae 765struct ospf_path *ospf_path_lookup(struct list *plist, struct ospf_path *path)
718e3744 766{
d62a17ae 767 struct listnode *node;
768 struct ospf_path *op;
769
770 for (ALL_LIST_ELEMENTS_RO(plist, node, op)) {
771 if (!IPV4_ADDR_SAME(&op->nexthop, &path->nexthop))
772 continue;
773 if (!IPV4_ADDR_SAME(&op->adv_router, &path->adv_router))
774 continue;
775 if (op->ifindex != path->ifindex)
776 continue;
777 return op;
778 }
779 return NULL;
718e3744 780}
781
d62a17ae 782void ospf_route_copy_nexthops(struct ospf_route *to, struct list *from)
718e3744 783{
d62a17ae 784 struct listnode *node, *nnode;
785 struct ospf_path *path;
718e3744 786
d62a17ae 787 assert(to->paths);
718e3744 788
d62a17ae 789 for (ALL_LIST_ELEMENTS(from, node, nnode, path))
790 /* The same routes are just discarded. */
791 if (!ospf_path_lookup(to->paths, path))
792 listnode_add(to->paths, ospf_path_dup(path));
718e3744 793}
794
d62a17ae 795void ospf_route_subst_nexthops(struct ospf_route *to, struct list *from)
718e3744 796{
718e3744 797
d62a17ae 798 list_delete_all_node(to->paths);
799 ospf_route_copy_nexthops(to, from);
718e3744 800}
801
d62a17ae 802void ospf_route_subst(struct route_node *rn, struct ospf_route *new_or,
803 struct ospf_route *over)
718e3744 804{
d62a17ae 805 route_lock_node(rn);
806 ospf_route_free(rn->info);
718e3744 807
d62a17ae 808 ospf_route_copy_nexthops(new_or, over->paths);
809 rn->info = new_or;
810 route_unlock_node(rn);
718e3744 811}
812
d62a17ae 813void ospf_route_add(struct route_table *rt, struct prefix_ipv4 *p,
814 struct ospf_route *new_or, struct ospf_route *over)
718e3744 815{
d62a17ae 816 struct route_node *rn;
718e3744 817
d62a17ae 818 rn = route_node_get(rt, (struct prefix *)p);
718e3744 819
d62a17ae 820 ospf_route_copy_nexthops(new_or, over->paths);
821
822 if (rn->info) {
823 if (IS_DEBUG_OSPF_EVENT)
824 zlog_debug("ospf_route_add(): something's wrong !");
825 route_unlock_node(rn);
826 return;
827 }
718e3744 828
d62a17ae 829 rn->info = new_or;
830}
718e3744 831
d62a17ae 832void ospf_prune_unreachable_networks(struct route_table *rt)
833{
834 struct route_node *rn, *next;
835 struct ospf_route * or ;
836
837 if (IS_DEBUG_OSPF_EVENT)
838 zlog_debug("Pruning unreachable networks");
839
840 for (rn = route_top(rt); rn; rn = next) {
841 next = route_next(rn);
842 if (rn->info != NULL) {
843 or = rn->info;
844 if (listcount(or->paths) == 0) {
845 if (IS_DEBUG_OSPF_EVENT)
846 zlog_debug("Pruning route to %s/%d",
847 inet_ntoa(rn->p.u.prefix4),
848 rn->p.prefixlen);
849
850 ospf_route_free(or);
851 rn->info = NULL;
852 route_unlock_node(rn);
853 }
854 }
855 }
718e3744 856}
857
d62a17ae 858void ospf_prune_unreachable_routers(struct route_table *rtrs)
718e3744 859{
d62a17ae 860 struct route_node *rn, *next;
861 struct ospf_route * or ;
862 struct listnode *node, *nnode;
863 struct list *paths;
864
865 if (IS_DEBUG_OSPF_EVENT)
866 zlog_debug("Pruning unreachable routers");
867
868 for (rn = route_top(rtrs); rn; rn = next) {
869 next = route_next(rn);
870 if ((paths = rn->info) == NULL)
871 continue;
872
873 for (ALL_LIST_ELEMENTS(paths, node, nnode, or)) {
874 if (listcount(or->paths) == 0) {
875 if (IS_DEBUG_OSPF_EVENT) {
876 zlog_debug("Pruning route to rtr %s",
877 inet_ntoa(rn->p.u.prefix4));
878 zlog_debug(
879 " via area %s",
880 inet_ntoa(or->u.std.area_id));
881 }
882
883 listnode_delete(paths, or);
884 ospf_route_free(or);
885 }
886 }
718e3744 887
d62a17ae 888 if (listcount(paths) == 0) {
889 if (IS_DEBUG_OSPF_EVENT)
890 zlog_debug("Pruning router node %s",
891 inet_ntoa(rn->p.u.prefix4));
718e3744 892
6a154c88 893 list_delete(&paths);
d62a17ae 894 rn->info = NULL;
895 route_unlock_node(rn);
896 }
718e3744 897 }
718e3744 898}
899
b5a8894d 900int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt,
996c9314 901 struct ospf_area *area, struct prefix_ipv4 *p)
718e3744 902{
d62a17ae 903 struct route_node *rn;
904 struct ospf_route * or, *new_or;
718e3744 905
d62a17ae 906 rn = route_node_get(rt, (struct prefix *)p);
718e3744 907
d62a17ae 908 if (rn == NULL) {
909 if (IS_DEBUG_OSPF_EVENT)
910 zlog_debug(
911 "ospf_add_discard_route(): router installation error");
912 return 0;
913 }
718e3744 914
d62a17ae 915 if (rn->info) /* If the route to the same destination is found */
718e3744 916 {
d62a17ae 917 route_unlock_node(rn);
718e3744 918
d62a17ae 919 or = rn->info;
718e3744 920
d62a17ae 921 if (or->path_type == OSPF_PATH_INTRA_AREA) {
922 if (IS_DEBUG_OSPF_EVENT)
923 zlog_debug(
3efd0893 924 "ospf_add_discard_route(): an intra-area route exists");
d62a17ae 925 return 0;
926 }
718e3744 927
d62a17ae 928 if (or->type == OSPF_DESTINATION_DISCARD) {
929 if (IS_DEBUG_OSPF_EVENT)
930 zlog_debug(
3efd0893 931 "ospf_add_discard_route(): discard entry already installed");
d62a17ae 932 return 0;
933 }
718e3744 934
d62a17ae 935 ospf_route_free(rn->info);
936 }
718e3744 937
d62a17ae 938 if (IS_DEBUG_OSPF_EVENT)
939 zlog_debug(
3efd0893 940 "ospf_add_discard_route(): adding %s/%d",
d62a17ae 941 inet_ntoa(p->prefix), p->prefixlen);
718e3744 942
d62a17ae 943 new_or = ospf_route_new();
944 new_or->type = OSPF_DESTINATION_DISCARD;
975a328e 945 new_or->id.s_addr = INADDR_ANY;
d62a17ae 946 new_or->cost = 0;
947 new_or->u.std.area_id = area->area_id;
948 new_or->u.std.external_routing = area->external_routing;
949 new_or->path_type = OSPF_PATH_INTER_AREA;
950 rn->info = new_or;
718e3744 951
b5a8894d 952 ospf_zebra_add_discard(ospf, p);
718e3744 953
d62a17ae 954 return 1;
955}
718e3744 956
b5a8894d
CS
957void ospf_delete_discard_route(struct ospf *ospf, struct route_table *rt,
958 struct prefix_ipv4 *p)
d62a17ae 959{
960 struct route_node *rn;
961 struct ospf_route * or ;
962
963 if (IS_DEBUG_OSPF_EVENT)
964 zlog_debug(
3efd0893 965 "ospf_delete_discard_route(): deleting %s/%d",
d62a17ae 966 inet_ntoa(p->prefix), p->prefixlen);
967
968 rn = route_node_lookup(rt, (struct prefix *)p);
969
970 if (rn == NULL) {
971 if (IS_DEBUG_OSPF_EVENT)
972 zlog_debug(
973 "ospf_delete_discard_route(): no route found");
974 return;
718e3744 975 }
976
d62a17ae 977 or = rn->info;
978
979 if (or->path_type == OSPF_PATH_INTRA_AREA) {
980 if (IS_DEBUG_OSPF_EVENT)
981 zlog_debug(
3efd0893 982 "ospf_delete_discard_route(): an intra-area route exists");
d62a17ae 983 return;
718e3744 984 }
985
d62a17ae 986 if (or->type != OSPF_DESTINATION_DISCARD) {
987 if (IS_DEBUG_OSPF_EVENT)
988 zlog_debug(
3efd0893 989 "ospf_delete_discard_route(): not a discard entry");
d62a17ae 990 return;
991 }
718e3744 992
d62a17ae 993 /* free the route entry and the route node */
994 ospf_route_free(rn->info);
8fc9e007 995
d62a17ae 996 rn->info = NULL;
997 route_unlock_node(rn);
998 route_unlock_node(rn);
718e3744 999
d62a17ae 1000 /* remove the discard entry from the rib */
b5a8894d 1001 ospf_zebra_delete_discard(ospf, p);
718e3744 1002
d62a17ae 1003 return;
718e3744 1004}