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