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