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