Coverage Report

Created: 2025-07-14 06:48

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