]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_route.c
ospfd: changes for code maintainability
[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,
b538baf3 366 struct ospf_area *area, bool add_all)
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". */
b538baf3
CH
391 if (!add_all && !IS_ROUTER_LSA_BORDER(lsa) &&
392 !IS_ROUTER_LSA_EXTERNAL(lsa)) {
d62a17ae 393 if (IS_DEBUG_OSPF_EVENT)
394 zlog_debug(
3efd0893 395 "ospf_intra_add_router: this router is neither ASBR nor ABR, skipping it");
d62a17ae 396 return;
397 }
398
399 /* Update ABR and ASBR count in this area. */
400 if (IS_ROUTER_LSA_BORDER(lsa))
401 area->abr_count++;
402 if (IS_ROUTER_LSA_EXTERNAL(lsa))
403 area->asbr_count++;
404
405 /* The Options field found in the associated router-LSA is copied
406 into the routing table entry's Optional capabilities field. Call
407 the newly added vertex Router X. */
408 or = ospf_route_new();
409
410 or->id = v->id;
411 or->u.std.area_id = area->area_id;
412 or->u.std.external_routing = area->external_routing;
413 or->path_type = OSPF_PATH_INTRA_AREA;
414 or->cost = v->distance;
415 or->type = OSPF_DESTINATION_ROUTER;
416 or->u.std.origin = (struct lsa_header *)lsa;
417 or->u.std.options = lsa->header.options;
418 or->u.std.flags = lsa->flags;
419
420 /* If Router X is the endpoint of one of the calculating router's
421 virtual links, and the virtual link uses Area A as Transit area:
422 the virtual link is declared up, the IP address of the virtual
423 interface is set to the IP address of the outgoing interface
424 calculated above for Router X, and the virtual neighbor's IP
425 address is set to Router X's interface address (contained in
426 Router X's router-LSA) that points back to the root of the
427 shortest- path tree; equivalently, this is the interface that
428 points back to Router X's parent vertex on the shortest-path tree
429 (similar to the calculation in Section 16.1.1). */
430
431 p.family = AF_INET;
432 p.prefix = v->id;
433 p.prefixlen = IPV4_MAX_BITLEN;
a6435618 434 apply_mask_ipv4(&p);
d62a17ae 435
436 if (IS_DEBUG_OSPF_EVENT)
96b663a3 437 zlog_debug("ospf_intra_add_router: talking about %pFX", &p);
d62a17ae 438
439 rn = route_node_get(rt, (struct prefix *)&p);
440
441 /* Note that we keep all routes to ABRs and ASBRs, not only the best */
442 if (rn->info == NULL)
443 rn->info = list_new();
444 else
445 route_unlock_node(rn);
446
1d376ff5 447 ospf_route_copy_nexthops_from_vertex(area, or, v);
d62a17ae 448
449 listnode_add(rn->info, or);
450
451 if (IS_DEBUG_OSPF_EVENT)
452 zlog_debug("ospf_intra_add_router: Stop");
718e3744 453}
454
455/* RFC2328 16.1. (4). For transit network. */
d62a17ae 456void ospf_intra_add_transit(struct route_table *rt, struct vertex *v,
457 struct ospf_area *area)
718e3744 458{
d62a17ae 459 struct route_node *rn;
460 struct ospf_route * or ;
461 struct prefix_ipv4 p;
462 struct network_lsa *lsa;
463
464 lsa = (struct network_lsa *)v->lsa;
465
466 /* If the newly added vertex is a transit network, the routing table
467 entry for the network is located. The entry's Destination ID is
468 the IP network number, which can be obtained by masking the
469 Vertex ID (Link State ID) with its associated subnet mask (found
470 in the body of the associated network-LSA). */
471 p.family = AF_INET;
472 p.prefix = v->id;
473 p.prefixlen = ip_masklen(lsa->mask);
474 apply_mask_ipv4(&p);
475
476 rn = route_node_get(rt, (struct prefix *)&p);
477
478 /* If the routing table entry already exists (i.e., there is already
479 an intra-area route to the destination installed in the routing
480 table), multiple vertices have mapped to the same IP network.
481 For example, this can occur when a new Designated Router is being
482 established. In this case, the current routing table entry
483 should be overwritten if and only if the newly found path is just
484 as short and the current routing table entry's Link State Origin
485 has a smaller Link State ID than the newly added vertex' LSA. */
486 if (rn->info) {
487 struct ospf_route *cur_or;
488
489 route_unlock_node(rn);
490 cur_or = rn->info;
491
492 if (v->distance > cur_or->cost
493 || IPV4_ADDR_CMP(&cur_or->u.std.origin->id, &lsa->header.id)
494 > 0)
495 return;
496
497 ospf_route_free(rn->info);
498 }
499
500 or = ospf_route_new();
501
502 or->id = v->id;
503 or->u.std.area_id = area->area_id;
504 or->u.std.external_routing = area->external_routing;
505 or->path_type = OSPF_PATH_INTRA_AREA;
506 or->cost = v->distance;
507 or->type = OSPF_DESTINATION_NETWORK;
508 or->u.std.origin = (struct lsa_header *)lsa;
509
1d376ff5 510 ospf_route_copy_nexthops_from_vertex(area, or, v);
d62a17ae 511
512 rn->info = or ;
718e3744 513}
514
515/* RFC2328 16.1. second stage. */
d62a17ae 516void ospf_intra_add_stub(struct route_table *rt, struct router_lsa_link *link,
517 struct vertex *v, struct ospf_area *area,
518 int parent_is_root, int lsa_pos)
718e3744 519{
d7c0a89a 520 uint32_t cost;
d62a17ae 521 struct route_node *rn;
522 struct ospf_route * or ;
523 struct prefix_ipv4 p;
524 struct router_lsa *lsa;
1d376ff5 525 struct ospf_interface *oi = NULL;
d62a17ae 526 struct ospf_path *path;
527
528 if (IS_DEBUG_OSPF_EVENT)
529 zlog_debug("ospf_intra_add_stub(): Start");
530
531 lsa = (struct router_lsa *)v->lsa;
532
533 p.family = AF_INET;
534 p.prefix = link->link_id;
535 p.prefixlen = ip_masklen(link->link_data);
536 apply_mask_ipv4(&p);
537
538 if (IS_DEBUG_OSPF_EVENT)
96b663a3
MS
539 zlog_debug("ospf_intra_add_stub(): processing route to %pFX",
540 &p);
d62a17ae 541
542 /* (1) Calculate the distance D of stub network from the root. D is
543 equal to the distance from the root to the router vertex
544 (calculated in stage 1), plus the stub network link's advertised
545 cost. */
546 cost = v->distance + ntohs(link->m[0].metric);
547
548 if (IS_DEBUG_OSPF_EVENT)
549 zlog_debug(
550 "ospf_intra_add_stub(): calculated cost is %d + %d = %d",
551 v->distance, ntohs(link->m[0].metric), cost);
552
553 /* PtP links with /32 masks adds host routes to remote, directly
554 * connected hosts, see RFC 2328, 12.4.1.1, Option 1.
555 * Such routes can just be ignored for the sake of tidyness.
556 */
557 if (parent_is_root && link->link_data.s_addr == 0xffffffff
558 && ospf_if_lookup_by_local_addr(area->ospf, NULL, link->link_id)) {
559 if (IS_DEBUG_OSPF_EVENT)
96b663a3
MS
560 zlog_debug("%s: ignoring host route %pI4/32 to self.",
561 __func__, &link->link_id);
d62a17ae 562 return;
718e3744 563 }
564
d62a17ae 565 rn = route_node_get(rt, (struct prefix *)&p);
718e3744 566
d62a17ae 567 /* Lookup current routing table. */
568 if (rn->info) {
569 struct ospf_route *cur_or;
718e3744 570
d62a17ae 571 route_unlock_node(rn);
718e3744 572
d62a17ae 573 cur_or = rn->info;
718e3744 574
d62a17ae 575 if (IS_DEBUG_OSPF_EVENT)
576 zlog_debug(
3efd0893 577 "ospf_intra_add_stub(): another route to the same prefix found with cost %u",
d62a17ae 578 cur_or->cost);
579
580 /* Compare this distance to the current best cost to the stub
581 network. This is done by looking up the stub network's
582 current routing table entry. If the calculated distance D is
583 larger, go on to examine the next stub network link in the
584 LSA. */
585 if (cost > cur_or->cost) {
586 if (IS_DEBUG_OSPF_EVENT)
587 zlog_debug(
588 "ospf_intra_add_stub(): old route is better, exit");
589 return;
590 }
718e3744 591
d62a17ae 592 /* (2) If this step is reached, the stub network's routing table
593 entry must be updated. Calculate the set of next hops that
594 would result from using the stub network link. This
595 calculation is shown in Section 16.1.1; input to this
596 calculation is the destination (the stub network) and the
597 parent vertex (the router vertex). If the distance D is the
598 same as the current routing table cost, simply add this set
599 of next hops to the routing table entry's list of next hops.
600 In this case, the routing table already has a Link State
601 Origin. If this Link State Origin is a router-LSA whose Link
602 State ID is smaller than V's Router ID, reset the Link State
603 Origin to V's router-LSA. */
604
605 if (cost == cur_or->cost) {
606 if (IS_DEBUG_OSPF_EVENT)
607 zlog_debug(
608 "ospf_intra_add_stub(): routes are equal, merge");
609
1d376ff5 610 ospf_route_copy_nexthops_from_vertex(area, cur_or, v);
d62a17ae 611
612 if (IPV4_ADDR_CMP(&cur_or->u.std.origin->id,
613 &lsa->header.id)
614 < 0)
615 cur_or->u.std.origin = (struct lsa_header *)lsa;
616 return;
617 }
718e3744 618
d62a17ae 619 /* Otherwise D is smaller than the routing table cost.
620 Overwrite the current routing table entry by setting the
621 routing table entry's cost to D, and by setting the entry's
622 list of next hops to the newly calculated set. Set the
623 routing table entry's Link State Origin to V's router-LSA.
624 Then go on to examine the next stub network link. */
718e3744 625
d62a17ae 626 if (cost < cur_or->cost) {
627 if (IS_DEBUG_OSPF_EVENT)
628 zlog_debug(
629 "ospf_intra_add_stub(): new route is better, set it");
718e3744 630
d62a17ae 631 cur_or->cost = cost;
632
633 list_delete_all_node(cur_or->paths);
634
1d376ff5 635 ospf_route_copy_nexthops_from_vertex(area, cur_or, v);
d62a17ae 636
637 cur_or->u.std.origin = (struct lsa_header *)lsa;
638 return;
639 }
718e3744 640 }
d62a17ae 641
642 if (IS_DEBUG_OSPF_EVENT)
643 zlog_debug("ospf_intra_add_stub(): installing new route");
644
645 or = ospf_route_new();
646
647 or->id = v->id;
648 or->u.std.area_id = area->area_id;
649 or->u.std.external_routing = area->external_routing;
650 or->path_type = OSPF_PATH_INTRA_AREA;
651 or->cost = cost;
652 or->type = OSPF_DESTINATION_NETWORK;
653 or->u.std.origin = (struct lsa_header *)lsa;
654
655 /* Nexthop is depend on connection type. */
656 if (v != area->spf) {
657 if (IS_DEBUG_OSPF_EVENT)
658 zlog_debug(
659 "ospf_intra_add_stub(): this network is on remote router");
1d376ff5 660 ospf_route_copy_nexthops_from_vertex(area, or, v);
d62a17ae 661 } else {
662 if (IS_DEBUG_OSPF_EVENT)
663 zlog_debug(
664 "ospf_intra_add_stub(): this network is on this router");
665
1d376ff5
G
666 /*
667 * Only deal with interface data when we
668 * don't do a dry run
669 */
670 if (!area->spf_dry_run)
671 oi = ospf_if_lookup_by_lsa_pos(area, lsa_pos);
672
673 if (oi || area->spf_dry_run) {
d62a17ae 674 if (IS_DEBUG_OSPF_EVENT)
675 zlog_debug(
1d376ff5
G
676 "ospf_intra_add_stub(): the lsa pos is %d",
677 lsa_pos);
d62a17ae 678
679 path = ospf_path_new();
975a328e 680 path->nexthop.s_addr = INADDR_ANY;
1d376ff5
G
681
682 if (oi) {
683 path->ifindex = oi->ifp->ifindex;
684 if (CHECK_FLAG(oi->connected->flags,
685 ZEBRA_IFA_UNNUMBERED))
686 path->unnumbered = 1;
687 }
688
d62a17ae 689 listnode_add(or->paths, path);
690 } else {
691 if (IS_DEBUG_OSPF_EVENT)
692 zlog_debug(
693 "ospf_intra_add_stub(): where's the interface ?");
694 }
718e3744 695 }
718e3744 696
d62a17ae 697 rn->info = or ;
718e3744 698
d62a17ae 699 if (IS_DEBUG_OSPF_EVENT)
700 zlog_debug("ospf_intra_add_stub(): Stop");
718e3744 701}
702
2b64873d
DL
703static const char *const ospf_path_type_str[] = {
704 "unknown-type", "intra-area", "inter-area", "type1-external",
705 "type2-external"
706};
d62a17ae 707
708void ospf_route_table_dump(struct route_table *rt)
718e3744 709{
d62a17ae 710 struct route_node *rn;
711 struct ospf_route * or ;
d62a17ae 712 struct listnode *pnode;
713 struct ospf_path *path;
718e3744 714
d62a17ae 715 zlog_debug("========== OSPF routing table ==========");
716 for (rn = route_top(rt); rn; rn = route_next(rn))
717 if ((or = rn->info) != NULL) {
718 if (or->type == OSPF_DESTINATION_NETWORK) {
d6951e5e
DL
719 zlog_debug("N %-18pFX %-15pI4 %s %d", &rn->p,
720 &or->u.std.area_id,
d62a17ae 721 ospf_path_type_str[or->path_type],
722 or->cost);
723 for (ALL_LIST_ELEMENTS_RO(or->paths, pnode,
724 path))
96b663a3
MS
725 zlog_debug(" -> %pI4",
726 &path->nexthop);
d62a17ae 727 } else
d6951e5e
DL
728 zlog_debug("R %-18pI4 %-15pI4 %s %d",
729 &rn->p.u.prefix4,
730 &or->u.std.area_id,
d62a17ae 731 ospf_path_type_str[or->path_type],
732 or->cost);
733 }
734 zlog_debug("========================================");
718e3744 735}
736
b538baf3
CH
737void ospf_router_route_table_dump(struct route_table *rt)
738{
739 struct route_node *rn;
740 struct ospf_route *or;
741 struct listnode *node;
742
743 zlog_debug("========== OSPF routing table ==========");
744 for (rn = route_top(rt); rn; rn = route_next(rn)) {
745 for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node, or)) {
746 assert(or->type == OSPF_DESTINATION_ROUTER);
747 zlog_debug("R %-18pI4 %-15pI4 %s %d", &rn->p.u.prefix4,
748 &or->u.std.area_id,
749 ospf_path_type_str[or->path_type], or->cost);
750 }
751 }
752 zlog_debug("========================================");
753}
754
718e3744 755/* This is 16.4.1 implementation.
756 o Intra-area paths using non-backbone areas are always the most preferred.
757 o The other paths, intra-area backbone paths and inter-area paths,
758 are of equal preference. */
d62a17ae 759static int ospf_asbr_route_cmp(struct ospf *ospf, struct ospf_route *r1,
760 struct ospf_route *r2)
718e3744 761{
d7c0a89a 762 uint8_t r1_type, r2_type;
718e3744 763
d62a17ae 764 r1_type = r1->path_type;
765 r2_type = r2->path_type;
718e3744 766
d62a17ae 767 /* r1/r2 itself is backbone, and it's Inter-area path. */
768 if (OSPF_IS_AREA_ID_BACKBONE(r1->u.std.area_id))
769 r1_type = OSPF_PATH_INTER_AREA;
770 if (OSPF_IS_AREA_ID_BACKBONE(r2->u.std.area_id))
771 r2_type = OSPF_PATH_INTER_AREA;
718e3744 772
d62a17ae 773 return (r1_type - r2_type);
718e3744 774}
775
776/* Compare two routes.
777 ret < 0 -- r1 is better.
778 ret == 0 -- r1 and r2 are the same.
779 ret > 0 -- r2 is better. */
d62a17ae 780int ospf_route_cmp(struct ospf *ospf, struct ospf_route *r1,
781 struct ospf_route *r2)
718e3744 782{
d62a17ae 783 int ret = 0;
784
785 /* Path types of r1 and r2 are not the same. */
786 if ((ret = (r1->path_type - r2->path_type)))
787 return ret;
788
789 if (IS_DEBUG_OSPF_EVENT)
790 zlog_debug("Route[Compare]: Path types are the same.");
791 /* Path types are the same, compare any cost. */
792 switch (r1->path_type) {
793 case OSPF_PATH_INTRA_AREA:
794 case OSPF_PATH_INTER_AREA:
795 break;
796 case OSPF_PATH_TYPE1_EXTERNAL:
797 if (!CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) {
798 ret = ospf_asbr_route_cmp(ospf, r1->u.ext.asbr,
799 r2->u.ext.asbr);
800 if (ret != 0)
801 return ret;
802 }
803 break;
804 case OSPF_PATH_TYPE2_EXTERNAL:
805 if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
806 return ret;
807
808 if (!CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) {
809 ret = ospf_asbr_route_cmp(ospf, r1->u.ext.asbr,
810 r2->u.ext.asbr);
811 if (ret != 0)
812 return ret;
813 }
814 break;
718e3744 815 }
718e3744 816
d62a17ae 817 /* Anyway, compare the costs. */
818 return (r1->cost - r2->cost);
718e3744 819}
820
d62a17ae 821static int ospf_path_exist(struct list *plist, struct in_addr nexthop,
822 struct ospf_interface *oi)
718e3744 823{
d62a17ae 824 struct listnode *node, *nnode;
825 struct ospf_path *path;
718e3744 826
d62a17ae 827 for (ALL_LIST_ELEMENTS(plist, node, nnode, path))
828 if (IPV4_ADDR_SAME(&path->nexthop, &nexthop)
829 && path->ifindex == oi->ifp->ifindex)
830 return 1;
718e3744 831
d62a17ae 832 return 0;
718e3744 833}
834
1d376ff5
G
835void ospf_route_copy_nexthops_from_vertex(struct ospf_area *area,
836 struct ospf_route *to,
d62a17ae 837 struct vertex *v)
718e3744 838{
d62a17ae 839 struct listnode *node;
840 struct ospf_path *path;
841 struct vertex_nexthop *nexthop;
842 struct vertex_parent *vp;
1d376ff5 843 struct ospf_interface *oi = NULL;
d62a17ae 844
845 assert(to->paths);
846
847 for (ALL_LIST_ELEMENTS_RO(v->parents, node, vp)) {
848 nexthop = vp->nexthop;
849
1d376ff5
G
850 /*
851 * Only deal with interface data when we
852 * don't do a dry run
853 */
854 if (!area->spf_dry_run)
855 oi = ospf_if_lookup_by_lsa_pos(area, nexthop->lsa_pos);
856
857 if ((oi && !ospf_path_exist(to->paths, nexthop->router, oi))
858 || area->spf_dry_run) {
859 path = ospf_path_new();
860 path->nexthop = nexthop->router;
7fd0729f 861 path->adv_router = v->id;
1d376ff5
G
862
863 if (oi) {
864 path->ifindex = oi->ifp->ifindex;
865 if (CHECK_FLAG(oi->connected->flags,
d62a17ae 866 ZEBRA_IFA_UNNUMBERED))
867 path->unnumbered = 1;
d62a17ae 868 }
1d376ff5
G
869
870 listnode_add(to->paths, path);
d62a17ae 871 }
718e3744 872 }
718e3744 873}
874
d62a17ae 875struct ospf_path *ospf_path_lookup(struct list *plist, struct ospf_path *path)
718e3744 876{
d62a17ae 877 struct listnode *node;
878 struct ospf_path *op;
879
880 for (ALL_LIST_ELEMENTS_RO(plist, node, op)) {
881 if (!IPV4_ADDR_SAME(&op->nexthop, &path->nexthop))
882 continue;
883 if (!IPV4_ADDR_SAME(&op->adv_router, &path->adv_router))
884 continue;
885 if (op->ifindex != path->ifindex)
886 continue;
887 return op;
888 }
889 return NULL;
718e3744 890}
891
d62a17ae 892void ospf_route_copy_nexthops(struct ospf_route *to, struct list *from)
718e3744 893{
d62a17ae 894 struct listnode *node, *nnode;
895 struct ospf_path *path;
718e3744 896
d62a17ae 897 assert(to->paths);
718e3744 898
d62a17ae 899 for (ALL_LIST_ELEMENTS(from, node, nnode, path))
900 /* The same routes are just discarded. */
901 if (!ospf_path_lookup(to->paths, path))
902 listnode_add(to->paths, ospf_path_dup(path));
718e3744 903}
904
d62a17ae 905void ospf_route_subst_nexthops(struct ospf_route *to, struct list *from)
718e3744 906{
718e3744 907
d62a17ae 908 list_delete_all_node(to->paths);
909 ospf_route_copy_nexthops(to, from);
718e3744 910}
911
d62a17ae 912void ospf_route_subst(struct route_node *rn, struct ospf_route *new_or,
913 struct ospf_route *over)
718e3744 914{
d62a17ae 915 route_lock_node(rn);
916 ospf_route_free(rn->info);
718e3744 917
d62a17ae 918 ospf_route_copy_nexthops(new_or, over->paths);
919 rn->info = new_or;
920 route_unlock_node(rn);
718e3744 921}
922
d62a17ae 923void ospf_route_add(struct route_table *rt, struct prefix_ipv4 *p,
924 struct ospf_route *new_or, struct ospf_route *over)
718e3744 925{
d62a17ae 926 struct route_node *rn;
718e3744 927
d62a17ae 928 rn = route_node_get(rt, (struct prefix *)p);
718e3744 929
d62a17ae 930 ospf_route_copy_nexthops(new_or, over->paths);
931
932 if (rn->info) {
933 if (IS_DEBUG_OSPF_EVENT)
934 zlog_debug("ospf_route_add(): something's wrong !");
935 route_unlock_node(rn);
936 return;
937 }
718e3744 938
d62a17ae 939 rn->info = new_or;
940}
718e3744 941
d62a17ae 942void ospf_prune_unreachable_networks(struct route_table *rt)
943{
944 struct route_node *rn, *next;
945 struct ospf_route * or ;
946
947 if (IS_DEBUG_OSPF_EVENT)
948 zlog_debug("Pruning unreachable networks");
949
950 for (rn = route_top(rt); rn; rn = next) {
951 next = route_next(rn);
952 if (rn->info != NULL) {
953 or = rn->info;
954 if (listcount(or->paths) == 0) {
955 if (IS_DEBUG_OSPF_EVENT)
96b663a3
MS
956 zlog_debug("Pruning route to %pFX",
957 &rn->p);
d62a17ae 958
959 ospf_route_free(or);
960 rn->info = NULL;
961 route_unlock_node(rn);
962 }
963 }
964 }
718e3744 965}
966
d62a17ae 967void ospf_prune_unreachable_routers(struct route_table *rtrs)
718e3744 968{
d62a17ae 969 struct route_node *rn, *next;
970 struct ospf_route * or ;
971 struct listnode *node, *nnode;
972 struct list *paths;
973
974 if (IS_DEBUG_OSPF_EVENT)
975 zlog_debug("Pruning unreachable routers");
976
977 for (rn = route_top(rtrs); rn; rn = next) {
978 next = route_next(rn);
979 if ((paths = rn->info) == NULL)
980 continue;
981
982 for (ALL_LIST_ELEMENTS(paths, node, nnode, or)) {
983 if (listcount(or->paths) == 0) {
984 if (IS_DEBUG_OSPF_EVENT) {
96b663a3
MS
985 zlog_debug("Pruning route to rtr %pI4",
986 &rn->p.u.prefix4);
d62a17ae 987 zlog_debug(
96b663a3
MS
988 " via area %pI4",
989 &or->u.std.area_id);
d62a17ae 990 }
991
992 listnode_delete(paths, or);
993 ospf_route_free(or);
994 }
995 }
718e3744 996
d62a17ae 997 if (listcount(paths) == 0) {
998 if (IS_DEBUG_OSPF_EVENT)
96b663a3
MS
999 zlog_debug("Pruning router node %pI4",
1000 &rn->p.u.prefix4);
718e3744 1001
6a154c88 1002 list_delete(&paths);
d62a17ae 1003 rn->info = NULL;
1004 route_unlock_node(rn);
1005 }
718e3744 1006 }
718e3744 1007}
1008
b5a8894d 1009int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt,
996c9314 1010 struct ospf_area *area, struct prefix_ipv4 *p)
718e3744 1011{
d62a17ae 1012 struct route_node *rn;
1013 struct ospf_route * or, *new_or;
718e3744 1014
d62a17ae 1015 rn = route_node_get(rt, (struct prefix *)p);
718e3744 1016
d62a17ae 1017 if (rn == NULL) {
1018 if (IS_DEBUG_OSPF_EVENT)
1019 zlog_debug(
1020 "ospf_add_discard_route(): router installation error");
1021 return 0;
1022 }
718e3744 1023
d62a17ae 1024 if (rn->info) /* If the route to the same destination is found */
718e3744 1025 {
d62a17ae 1026 route_unlock_node(rn);
718e3744 1027
d62a17ae 1028 or = rn->info;
718e3744 1029
d62a17ae 1030 if (or->path_type == OSPF_PATH_INTRA_AREA) {
1031 if (IS_DEBUG_OSPF_EVENT)
1032 zlog_debug(
3efd0893 1033 "ospf_add_discard_route(): an intra-area route exists");
d62a17ae 1034 return 0;
1035 }
718e3744 1036
d62a17ae 1037 if (or->type == OSPF_DESTINATION_DISCARD) {
1038 if (IS_DEBUG_OSPF_EVENT)
1039 zlog_debug(
3efd0893 1040 "ospf_add_discard_route(): discard entry already installed");
d62a17ae 1041 return 0;
1042 }
718e3744 1043
d62a17ae 1044 ospf_route_free(rn->info);
1045 }
718e3744 1046
d62a17ae 1047 if (IS_DEBUG_OSPF_EVENT)
ae32e1c2 1048 zlog_debug("ospf_add_discard_route(): adding %pFX", p);
718e3744 1049
d62a17ae 1050 new_or = ospf_route_new();
1051 new_or->type = OSPF_DESTINATION_DISCARD;
975a328e 1052 new_or->id.s_addr = INADDR_ANY;
d62a17ae 1053 new_or->cost = 0;
1054 new_or->u.std.area_id = area->area_id;
1055 new_or->u.std.external_routing = area->external_routing;
1056 new_or->path_type = OSPF_PATH_INTER_AREA;
1057 rn->info = new_or;
718e3744 1058
b5a8894d 1059 ospf_zebra_add_discard(ospf, p);
718e3744 1060
d62a17ae 1061 return 1;
1062}
718e3744 1063
b5a8894d
CS
1064void ospf_delete_discard_route(struct ospf *ospf, struct route_table *rt,
1065 struct prefix_ipv4 *p)
d62a17ae 1066{
1067 struct route_node *rn;
1068 struct ospf_route * or ;
1069
1070 if (IS_DEBUG_OSPF_EVENT)
ae32e1c2 1071 zlog_debug("ospf_delete_discard_route(): deleting %pFX", p);
d62a17ae 1072
1073 rn = route_node_lookup(rt, (struct prefix *)p);
1074
1075 if (rn == NULL) {
1076 if (IS_DEBUG_OSPF_EVENT)
1077 zlog_debug(
1078 "ospf_delete_discard_route(): no route found");
1079 return;
718e3744 1080 }
1081
d62a17ae 1082 or = rn->info;
1083
1084 if (or->path_type == OSPF_PATH_INTRA_AREA) {
1085 if (IS_DEBUG_OSPF_EVENT)
1086 zlog_debug(
3efd0893 1087 "ospf_delete_discard_route(): an intra-area route exists");
d62a17ae 1088 return;
718e3744 1089 }
1090
d62a17ae 1091 if (or->type != OSPF_DESTINATION_DISCARD) {
1092 if (IS_DEBUG_OSPF_EVENT)
1093 zlog_debug(
3efd0893 1094 "ospf_delete_discard_route(): not a discard entry");
d62a17ae 1095 return;
1096 }
718e3744 1097
d62a17ae 1098 /* free the route entry and the route node */
1099 ospf_route_free(rn->info);
8fc9e007 1100
d62a17ae 1101 rn->info = NULL;
1102 route_unlock_node(rn);
1103 route_unlock_node(rn);
718e3744 1104
d62a17ae 1105 /* remove the discard entry from the rib */
b5a8894d 1106 ospf_zebra_delete_discard(ospf, p);
718e3744 1107
d62a17ae 1108 return;
718e3744 1109}