Tomato 1.28
[tomato.git] / release / src / router / zebra / ospf6d / ospf6_route.c
blobf9cfdeb9fe9410164098e4d8bc1e133855aac4a1
1 /*
2 * Copyright (C) 1999 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
21 /* ospf6 routing table calculation function */
23 #include "ospf6d.h"
25 #include "if.h"
26 #include "table.h"
27 #include "vty.h"
29 #include "ospf6_proto.h"
30 #include "ospf6_prefix.h"
31 #include "ospf6_route.h"
34 /* new */
36 static int
37 ospf6_route_info_is_same_attribute (struct ospf6_route_info *new,
38 struct ospf6_route_info *old)
40 if (new->capability_bits != old->capability_bits)
41 return 0;
42 if (new->opt_capability[0] != old->opt_capability[0])
43 return 0;
44 if (new->opt_capability[1] != old->opt_capability[1])
45 return 0;
46 if (new->opt_capability[2] != old->opt_capability[2])
47 return 0;
48 if (new->area_id != old->area_id)
49 return 0;
50 if (new->path_type != old->path_type)
51 return 0;
52 if (new->cost != old->cost)
53 return 0;
54 if (new->cost_e2 != old->cost_e2)
55 return 0;
56 if (new->origin_id != old->origin_id)
57 return 0;
58 if (new->origin_adv_router != old->origin_adv_router)
59 return 0;
60 return 1;
63 int
64 ospf6_route_info_is_same (struct ospf6_route_info *ri1,
65 struct ospf6_route_info *ri2)
67 listnode node;
68 struct ospf6_nexthop *nexthop;
70 if (! ospf6_route_info_is_same_attribute (ri1, ri2))
71 return 0;
73 for (node = listhead (ri1->nexthop_list); node; nextnode (node))
75 nexthop = (struct ospf6_nexthop *) getdata (node);
76 if (listnode_lookup (ri2->nexthop_list, nexthop) == NULL)
77 return 0;
80 for (node = listhead (ri2->nexthop_list); node; nextnode (node))
82 nexthop = (struct ospf6_nexthop *) getdata (node);
83 if (listnode_lookup (ri1->nexthop_list, nexthop) == NULL)
84 return 0;
87 return 1;
90 struct ospf6_nexthop *
91 ospf6_nexthop_create (unsigned int ifindex, struct in6_addr *ipaddr,
92 u_int32_t adv_router)
94 listnode node;
95 struct ospf6_nexthop *nexthop, *new;
97 char buf [64];
98 inet_ntop (AF_INET6, ipaddr, buf, sizeof (buf));
100 for (node = listhead (ospf6->nexthop_list); node; nextnode (node))
102 nexthop = (struct ospf6_nexthop *) getdata (node);
103 if (nexthop->ifindex != ifindex)
104 continue;
105 if (memcmp (&nexthop->ipaddr, ipaddr, sizeof (struct in6_addr)) != 0)
106 continue;
107 if (nexthop->adv_router != adv_router)
108 continue;
110 nexthop->lock++;
111 return nexthop;
114 new = (struct ospf6_nexthop *) XMALLOC (MTYPE_OSPF6_NEXTHOP,
115 sizeof (struct ospf6_nexthop));
116 if (! new)
118 zlog_err ("ROUTE: Can't allocate memory for nexthop");
119 return (struct ospf6_nexthop *) NULL;
121 memset (new, 0, sizeof (struct ospf6_nexthop));
122 new->ifindex = ifindex;
123 memcpy (&new->ipaddr, ipaddr, sizeof (struct in6_addr));
124 new->adv_router = adv_router;
125 new->lock = 1;
127 listnode_add (ospf6->nexthop_list, new);
128 return new;
131 void
132 ospf6_nexthop_delete (struct ospf6_nexthop *nexthop)
134 nexthop->lock--;
135 if (nexthop->lock == 0)
137 listnode_delete (ospf6->nexthop_list, nexthop);
138 XFREE (MTYPE_OSPF6_NEXTHOP, nexthop);
142 static struct ospf6_route_info *
143 ospf6_route_info_create (u_char opt_capability[3], u_char capability_bits,
144 u_int32_t area_id, u_char path_type,
145 u_int32_t cost, u_int32_t cost_e2,
146 u_int32_t origin_id, u_int32_t origin_adv_router,
147 list nexthop_list)
149 listnode node;
150 struct ospf6_route_info *new;
151 struct ospf6_nexthop *n, *nexthop;
153 new = (struct ospf6_route_info *) XMALLOC (MTYPE_OSPF6_ROUTE,
154 sizeof (struct ospf6_route_info));
155 if (! new)
157 zlog_err ("ROUTE: Can't allocate memory for route info");
158 return (struct ospf6_route_info *) NULL;
160 memset (new, 0, sizeof (struct ospf6_route_info));
162 new->opt_capability[0] = opt_capability[0];
163 new->opt_capability[1] = opt_capability[1];
164 new->opt_capability[2] = opt_capability[2];
165 new->capability_bits = capability_bits;
166 new->area_id = area_id;
167 new->path_type = path_type;
168 new->cost = cost;
169 new->cost_e2 = cost_e2;
170 new->origin_id = origin_id;
171 new->origin_adv_router = origin_adv_router;
172 new->nexthop_list = list_new ();
174 /* nexthop */
175 for (node = listhead (nexthop_list); node; nextnode (node))
177 n = (struct ospf6_nexthop *) getdata (node);
178 nexthop = ospf6_nexthop_create (n->ifindex, &n->ipaddr, n->adv_router);
179 listnode_add (new->nexthop_list, nexthop);
182 return new;
185 static void
186 ospf6_route_info_delete (struct ospf6_route_info *route_info)
188 listnode node;
189 struct ospf6_nexthop *nexthop;
191 for (node = listhead (route_info->nexthop_list); node; nextnode (node))
193 nexthop = (struct ospf6_nexthop *) getdata (node);
194 ospf6_nexthop_delete (nexthop);
196 list_delete (route_info->nexthop_list);
197 XFREE (MTYPE_OSPF6_ROUTE, route_info);
200 static void
201 ospf6_route_info_merge (struct ospf6_route_info *new,
202 struct ospf6_route_info *old)
204 listnode node;
205 struct ospf6_nexthop *nexthop;
207 for (node = listhead (new->nexthop_list); node; nextnode (node))
209 nexthop = (struct ospf6_nexthop *) getdata (node);
210 if (listnode_lookup (old->nexthop_list, nexthop))
211 continue;
212 listnode_add (old->nexthop_list, nexthop);
213 nexthop->lock++;
217 /* RFC2328 section 11 */
218 static int
219 ospf6_route_info_is_new_prefered (struct ospf6_route_info *new,
220 struct ospf6_route_info *old)
222 if (! CHECK_FLAG (old->flag, OSPF6_ROUTE_FLAG_ACTIVE))
223 return 1;
225 if (new->path_type < old->path_type)
226 return 1;
227 else if (new->path_type > old->path_type)
228 return 0;
230 if (new->cost_e2 < old->cost_e2)
231 return 1;
232 else if (new->cost_e2 > old->cost_e2)
233 return 0;
235 if (new->cost < old->cost)
236 return 1;
237 else if (new->cost > old->cost)
238 return 0;
240 zlog_err ("ROUTE: Can't decide if the new route info is prefered");
241 return 1;
244 struct ospf6_route_info *
245 ospf6_route_create (struct prefix *destination, char *string,
246 u_char opt_capability[3], u_char capability_bits,
247 u_int32_t area_id, u_char path_type,
248 u_int32_t cost, u_int32_t cost_e2,
249 u_int32_t origin_id, u_int32_t origin_adv_router,
250 list nexthop_list,
251 struct route_table *table)
253 struct route_node *route_node;
254 struct ospf6_route_info *new, *old;
255 u_char flag;
256 struct ospf6_route_info *route_info;
258 new = ospf6_route_info_create (opt_capability, capability_bits,
259 area_id, path_type, cost, cost_e2,
260 origin_id, origin_adv_router, nexthop_list);
261 if (! new)
263 zlog_err ("ROUTE: Can't create route info for %s", string);
264 return (struct ospf6_route_info *) NULL;
267 route_node = route_node_get (table, destination);
268 old = route_node->info;
270 if (! old)
272 /* this is the first route for this destination */
273 if (IS_OSPF6_DUMP_ROUTE)
274 zlog_info ("ROUTE: route created: %s", string);
276 SET_FLAG (new->flag, OSPF6_ROUTE_FLAG_ACTIVE);
277 route_node->info = new;
278 return new;
281 route_info = (struct ospf6_route_info *) NULL;
282 flag = 0;
284 #if 0
285 if (IS_OSPF6_DUMP_ROUTE)
286 zlog_info ("ROUTE: route already exists: %s", string);
287 #endif
289 if (ospf6_route_info_is_same (new, old))
291 /* the same entry exists, nothing to do */
292 #if 0
293 if (IS_OSPF6_DUMP_ROUTE)
294 zlog_info ("ROUTE: route untouched: %s", string);
295 #endif
296 ospf6_route_info_delete (new);
297 route_info = old;
299 else if (ospf6_route_info_is_same_attribute (new, old))
301 /* merge new's nexthop to old's */
302 if (IS_OSPF6_DUMP_ROUTE)
303 zlog_info ("ROUTE: route merged: %s", string);
304 ospf6_route_info_merge (new, old);
305 ospf6_route_info_delete (new);
306 route_info = old;
308 else if (ospf6_route_info_is_new_prefered (new, old))
310 /* new route is prefered, replace with old one */
311 if (IS_OSPF6_DUMP_ROUTE)
312 zlog_info ("ROUTE: route changed: %s", string);
313 ospf6_route_info_delete (old);
314 route_info = new;
316 else
318 /* there's already better route for this destination */
319 #if 0
320 if (IS_OSPF6_DUMP_ROUTE)
321 zlog_info ("ROUTE: route rejected: %s", string);
322 #endif
323 ospf6_route_info_delete (new);
324 route_info = old;
327 SET_FLAG (route_info->flag, OSPF6_ROUTE_FLAG_ACTIVE);
328 route_node->info = route_info;
329 return route_info;
332 void
333 ospf6_route_delete (struct prefix *destination,
334 struct route_table *table)
336 struct route_node *route_node;
337 struct ospf6_route_info *route_info;
338 char pstring[128];
340 /* for log */
341 prefix2str (destination, pstring, sizeof (pstring));
343 route_node = route_node_get (table, destination);
344 route_info = (struct ospf6_route_info *) route_node->info;
345 if (! route_info)
347 if (IS_OSPF6_DUMP_ROUTE)
348 zlog_info ("ROUTE: Can't delete route %s: doesn't exist", pstring);
349 return;
352 if (CHECK_FLAG (route_info->flag, OSPF6_ROUTE_FLAG_ZEBRA_SYNC))
354 UNSET_FLAG (route_info->flag, OSPF6_ROUTE_FLAG_ACTIVE);
355 #if 0
356 if (IS_OSPF6_DUMP_ROUTE)
357 zlog_info ("ROUTE: delete sync'ed route: %s", pstring);
358 #else
359 if (IS_OSPF6_DUMP_ROUTE)
360 zlog_info ("ROUTE: route delete: %s", pstring);
361 #endif
362 ospf6_zebra_route_update ((struct prefix_ipv6 *) destination,
363 route_info);
366 #if 0
367 if (IS_OSPF6_DUMP_ROUTE)
368 zlog_info ("ROUTE: delete route %s", pstring);
369 #endif
371 ospf6_route_info_delete (route_info);
372 route_node->info = NULL;
375 void
376 ospf6_route_delete_all (struct route_table *table)
378 struct route_node *node;
380 for (node = route_top (table); node; node = route_next (node))
382 if (! node->info)
383 continue;
385 ospf6_route_delete (&node->p, table);
389 static void
390 ospf6_route_intra_area (struct prefix_ls *d, struct ospf6_route_info *ri,
391 struct ospf6_area *o6a)
393 int i;
394 u_int16_t type, cost;
395 struct ospf6_lsa *lsa;
396 struct ospf6_intra_area_prefix_lsa *intra_prefix_lsa;
397 struct ospf6_prefix *ospf6_prefix;
398 struct prefix_ipv6 prefix;
399 char buf[64], node_string[64], prefix_string[64];
400 struct ospf6_lsdb_node *node;
402 if (d->id.s_addr == 0)
403 type = htons (OSPF6_LSA_TYPE_ROUTER);
404 else
405 type = htons (OSPF6_LSA_TYPE_NETWORK);
407 /* for log */
408 inet_ntop (AF_INET, &d->adv_router, buf, sizeof (buf));
409 snprintf (node_string, sizeof (node_string),
410 "%s[%lu]", buf, (unsigned long) ntohl (d->id.s_addr));
412 if (IS_OSPF6_DUMP_ROUTE)
413 zlog_info ("ROUTE: Calculate Route for %s", node_string);
415 /* Foreach appropriate Intra-Area-Prefix-LSA */
416 for (node = ospf6_lsdb_head (o6a->lsdb); node; node = ospf6_lsdb_next (node))
418 lsa = node->lsa;
419 if (ospf6_lsa_is_maxage (lsa))
420 continue;
422 if (lsa->header->type != htons (OSPF6_LSA_TYPE_INTRA_PREFIX))
423 continue;
424 if (lsa->header->adv_router != d->adv_router.s_addr)
425 continue;
427 if (IS_OSPF6_DUMP_ROUTE)
428 zlog_info ("ROUTE: Check %s", lsa->str);
430 /* check LS Reference */
431 intra_prefix_lsa = (struct ospf6_intra_area_prefix_lsa *)
432 (lsa->header + 1);
434 if (intra_prefix_lsa->refer_lstype == htons (OSPF6_LSA_TYPE_NETWORK)
435 && ntohs (type) == OSPF6_LSA_TYPE_ROUTER)
437 zlog_info ("Network Reference while Router");
438 continue;
440 if (intra_prefix_lsa->refer_lstype == htons (OSPF6_LSA_TYPE_ROUTER)
441 && ntohs (type) == OSPF6_LSA_TYPE_NETWORK)
443 zlog_info ("Router Reference while Network ");
444 continue;
447 /* If Network LSA and Reference-ID wrong */
448 if (intra_prefix_lsa->refer_lstype == htons (OSPF6_LSA_TYPE_NETWORK)
449 && intra_prefix_lsa->refer_lsid != 0
450 && intra_prefix_lsa->refer_lsid != d->id.s_addr)
452 if (IS_OSPF6_DUMP_ROUTE)
454 zlog_info ("ROUTE: Network Reference-ID wrong: %s <-> %s",
455 node_string, lsa->str);
456 zlog_info ("ROUTE: intra_prefix_lsa->refer_lsid: %d\n",
457 ntohl (intra_prefix_lsa->refer_lsid));
458 zlog_info ("ROUTE: d->id.s_addr : %d\n",
459 ntohl (d->id.s_addr));
461 continue;
464 /* If Reference-Type is Router and the entry not indicate Router */
465 if (intra_prefix_lsa->refer_lstype == htons (OSPF6_LSA_TYPE_ROUTER)
466 && d->id.s_addr != 0)
468 if (IS_OSPF6_DUMP_ROUTE)
469 zlog_info ("ROUTE: Reference-Type (Router) wrong: %s <-> %s",
470 node_string, lsa->str);
471 zlog_info ("ROUTE: intra_prefix_lsa->refer_lsid: %d\n",
472 ntohl (intra_prefix_lsa->refer_lsid));
473 zlog_info ("ROUTE: d->id.s_addr : %d\n", ntohl (d->id.s_addr));
474 continue;
477 /* If Reference-Type is Network and the entry not indicate Network */
478 if (intra_prefix_lsa->refer_lstype == htons (OSPF6_LSA_TYPE_NETWORK)
479 && d->id.s_addr == 0)
481 if (IS_OSPF6_DUMP_ROUTE)
482 zlog_info ("ROUTE: Reference-Type (Network) wrong: %s <-> %s",
483 node_string, lsa->str);
484 continue;
487 if (IS_OSPF6_DUMP_ROUTE)
488 zlog_info ("ROUTE: %s: Prefix LSA %s", node_string, lsa->str);
490 /* for each ospf6 prefixes */
491 ospf6_prefix = (struct ospf6_prefix *) (intra_prefix_lsa + 1);
492 for (i = 0; i < ntohs (intra_prefix_lsa->prefix_number); i++)
494 memset (&prefix, 0, sizeof (struct prefix_ipv6));
495 prefix.family = AF_INET6;
496 ospf6_prefix_in6_addr (ospf6_prefix, &prefix.prefix);
497 prefix.prefixlen = ospf6_prefix->prefix_length;
498 cost = ri->cost + ntohs (ospf6_prefix->prefix_metric);
500 prefix2str ((struct prefix *) &prefix, prefix_string,
501 sizeof (prefix_string));
503 if (IS_OSPF6_DUMP_ROUTE)
504 zlog_info ("ROUTE: route install %s cost %d", prefix_string, cost);
506 ospf6_route_create ((struct prefix *) &prefix, prefix_string,
507 ri->opt_capability, 0, ri->area_id,
508 OSPF6_ROUTE_PATH_TYPE_INTRA,
509 cost, 0, ri->origin_id, ri->origin_adv_router,
510 ri->nexthop_list, ospf6->route_table);
512 /* examin next prefix */
513 ospf6_prefix = OSPF6_NEXT_PREFIX (ospf6_prefix);
518 void
519 ospf6_route_calculation_intra_area (struct ospf6_area *o6a)
521 struct route_node *node;
522 struct prefix_ls *destination;
523 struct ospf6_route_info *info;
525 for (node = route_top (o6a->table_topology); node; node = route_next (node))
527 destination = (struct prefix_ls *) &node->p;
528 info = (struct ospf6_route_info *) node->info;
529 if (! info)
530 continue;
531 ospf6_route_intra_area (destination, info, o6a);
535 void
536 ospf6_route_calculation_inter_area (struct ospf6_area *o6a)
540 struct ospf6_route_info *
541 ospf6_route_asbr_entry (u_int32_t adv_router, struct ospf6 *o6)
543 listnode l_node;
544 struct route_node *r_node;
545 struct ospf6_area *o6a;
546 struct prefix_ls d;
547 struct ospf6_route_info *ri;
549 for (l_node = listhead (o6->area_list); l_node; nextnode (l_node))
551 o6a = (struct ospf6_area *) getdata (l_node);
552 d.adv_router.s_addr = adv_router;
553 d.id.s_addr = htonl (0);
554 d.prefixlen = 64;
555 d.family = AF_INET6;
557 r_node = route_node_lookup (o6a->table_topology, (struct prefix *) &d);
558 if (! r_node)
559 return (struct ospf6_route_info *) NULL;
561 ri = (struct ospf6_route_info *) r_node->info;
562 if (! ri)
563 return (struct ospf6_route_info *) NULL;
565 if (ri->capability_bits & OSPF6_ROUTER_LSA_BIT_E)
566 return ri;
567 else
568 return (struct ospf6_route_info *) NULL;
570 return (struct ospf6_route_info *) NULL;
573 /* RFC2328 section 16.4 */
574 void
575 ospf6_route_external (struct ospf6_lsa *lsa)
577 struct ospf6_lsa_header *lsa_header;
578 struct ospf6_as_external_lsa *as_external_lsa;
579 struct in6_addr *forwarding_address;
580 struct prefix_ipv6 forwarding, prefix;
581 struct route_node *node;
582 struct ospf6_route_info *ri;
583 u_int16_t cost1, cost2;
584 u_char path_type;
585 char pstring[64];
586 u_char opt_capability[3];
588 /* prepare destination prefix first */
589 lsa_header = (struct ospf6_lsa_header *) lsa->lsa_hdr;
590 as_external_lsa = (struct ospf6_as_external_lsa *) (lsa_header + 1);
591 prefix.family = AF_INET6;
592 prefix.prefixlen = as_external_lsa->ospf6_prefix.prefix_length;
593 ospf6_prefix_in6_addr (&as_external_lsa->ospf6_prefix, &prefix.prefix);
594 prefix2str ((struct prefix *) &prefix, pstring, sizeof (pstring));
595 memset (opt_capability, 0, sizeof (opt_capability));
597 if (lsa_header->advrtr == ospf6->router_id)
599 if (IS_OSPF6_DUMP_ROUTE)
600 zlog_info ("ROUTE: LSA is Self-originated: %s", lsa->str);
601 return;
604 if (ospf6_lsa_is_maxage (lsa))
606 if (IS_OSPF6_DUMP_ROUTE)
607 zlog_info ("ROUTE: %s: MaxAge", lsa->str);
609 /* If we have the route derived from this LSA, delete the route */
610 node = route_node_lookup (ospf6->route_table, (struct prefix *) &prefix);
611 if (node && node->info)
613 ri = (struct ospf6_route_info *) node->info;
614 if (ri->origin_id == lsa_header->ls_id &&
615 ri->origin_adv_router == lsa_header->advrtr)
616 ospf6_route_delete ((struct prefix *) &prefix, ospf6->route_table);
618 return;
621 /* test ASBR entry */
622 ri = ospf6_route_asbr_entry (lsa_header->advrtr, ospf6);
623 if (! ri)
625 if (IS_OSPF6_DUMP_ROUTE)
626 zlog_info ("ROUTE: %s: no ASBR", lsa->str);
627 return;
629 cost1 = ri->cost;
630 cost2 = 0;
632 /* Forwarding Address test */
633 if (as_external_lsa->ase_bits & ASE_LSA_BIT_F)
635 if (IS_OSPF6_DUMP_ROUTE)
636 zlog_info ("ROUTE: Forwarding flag specified");
638 forwarding_address = (struct in6_addr *)
639 OSPF6_NEXT_PREFIX (&as_external_lsa->ospf6_prefix);
640 memcpy (&forwarding.prefix, forwarding_address,
641 sizeof (struct in6_addr));
642 forwarding.family = AF_INET6;
643 forwarding.prefixlen = 128;
645 /* test if forwarding address is on the routing table */
646 node = route_node_match (ospf6->route_table,
647 (struct prefix *) &forwarding);
648 if (! node || ! node->info)
650 if (IS_OSPF6_DUMP_ROUTE)
651 zlog_info ("ROUTE: Fowarding-address not on the table");
652 return;
655 /* overwrite asbr internal cost */
656 ri = (struct ospf6_route_info *) node->info;
657 cost1 = ri->cost;
660 if (as_external_lsa->ase_bits & ASE_LSA_BIT_E)
662 /* type-2 */
663 cost2 = ntohs (as_external_lsa->ase_metric);
664 path_type = OSPF6_ROUTE_PATH_TYPE_EXTERNAL2;
666 else
668 /* type-1 */
669 cost1 += ntohs (as_external_lsa->ase_metric);
670 path_type = OSPF6_ROUTE_PATH_TYPE_EXTERNAL1;
673 ospf6_route_create ((struct prefix *) &prefix, pstring,
674 opt_capability, 0, ri->area_id,
675 path_type, cost1, cost2,
676 lsa_header->ls_id, lsa_header->advrtr,
677 ri->nexthop_list, ospf6->route_table);
680 static void
681 ospf6_route_calculation_external (struct ospf6 *o6)
683 struct ospf6_lsdb_node *node;
685 for (node = ospf6_lsdb_head (o6->lsdb); node; node = ospf6_lsdb_next (node))
687 if (node->lsa->header->type != htons (OSPF6_LSA_TYPE_AS_EXTERNAL))
688 continue;
690 ospf6_route_external (node->lsa);
694 static void
695 ospf6_route_invalidate ()
697 struct route_node *node;
698 struct ospf6_route_info *route_info;
700 if (IS_OSPF6_DUMP_ROUTE)
701 zlog_info ("ROUTE: Invalidate routing table");
703 for (node = route_top (ospf6->route_table); node; node = route_next (node))
705 if (! node->info)
706 continue;
707 route_info = (struct ospf6_route_info *) node->info;
708 UNSET_FLAG (route_info->flag, OSPF6_ROUTE_FLAG_ACTIVE);
712 static void
713 ospf6_route_validate ()
715 struct route_node *node;
716 struct ospf6_route_info *route_info;
717 char prefix_string[64];
719 if (IS_OSPF6_DUMP_ROUTE)
720 zlog_info ("ROUTE: Validate routing table");
722 for (node = route_top (ospf6->route_table); node; node = route_next (node))
724 if (! node->info)
725 continue;
726 route_info = (struct ospf6_route_info *) node->info;
728 prefix2str (&node->p, prefix_string, sizeof (prefix_string));
730 #if 0
731 zlog_info ("ROUTE: DEBUG: update route: %s %s %s",
732 (CHECK_FLAG (route_info->flag, OSPF6_ROUTE_FLAG_ZEBRA_SYNC) ?
733 "sync'ed": "nosync"),
734 (CHECK_FLAG (route_info->flag, OSPF6_ROUTE_FLAG_ACTIVE) ?
735 "active": "inactive"), prefix_string);
736 #endif
738 ospf6_zebra_route_update ((struct prefix_ipv6 *) &node->p,
739 route_info);
741 if (! CHECK_FLAG (route_info->flag, OSPF6_ROUTE_FLAG_ACTIVE))
742 ospf6_route_delete (&node->p, ospf6->route_table);
746 void
747 ospf6_route_calculation_new ()
749 listnode node;
750 struct ospf6_area *o6a;
752 /* stat */
753 ospf6->stat_route_calculation_execed++;
755 /* invalidate current routing table */
756 ospf6_route_invalidate ();
758 /* Intra-Area Routes */
759 for (node = listhead (ospf6->area_list); node; nextnode (node))
761 o6a = (struct ospf6_area *) getdata (node);
762 ospf6_route_calculation_intra_area (o6a);
765 /* Inter-Area Routes */
766 if (listcount (ospf6->area_list) == 1)
768 o6a = (struct ospf6_area *) getdata (listhead (ospf6->area_list));
769 ospf6_route_calculation_inter_area (o6a);
771 else
773 /* calculate Inter-Area routes for backbone */
774 o6a = ospf6_area_lookup (htonl (0), ospf6);
775 ospf6_route_calculation_inter_area (o6a);
778 /* Better Inter-Area Routes if this is Transit Area */
779 for (node = listhead (ospf6->area_list); node; nextnode (node))
781 o6a = (struct ospf6_area *) getdata (node);
782 if (ospf6_area_is_transit (o6a))
783 ospf6_route_calculation_inter_area (o6a);
786 /* External Routes associated with this area */
787 ospf6_route_calculation_external (ospf6);
789 /* update zebra routing table */
790 ospf6_route_validate ();
794 ospf6_route_calculation_thread (struct thread *t)
796 ospf6_route_calculation_new ();
797 ospf6->t_route_calculation = (struct thread *) NULL;
798 return 0;
801 void
802 ospf6_route_calculation_schedule ()
804 if (ospf6->t_route_calculation)
805 return;
807 ospf6->t_route_calculation =
808 thread_add_event (master, ospf6_route_calculation_thread, NULL, 0);
811 void
812 ospf6_route_external_incremental (struct ospf6_lsa *lsa)
814 struct ospf6_lsa_header *lsa_header;
815 lsa_header = (struct ospf6_lsa_header *) lsa->lsa_hdr;
817 if (lsa_header->type != htons (OSPF6_LSA_TYPE_AS_EXTERNAL))
818 return;
820 ospf6_route_external (lsa);
821 ospf6_route_validate ();
824 char *
825 ospf6_route_path_type_string (u_char path_type, char *buf, int size)
827 if (path_type == OSPF6_ROUTE_PATH_TYPE_INTRA)
828 snprintf (buf, size, "IA");
829 else if (path_type == OSPF6_ROUTE_PATH_TYPE_INTER)
830 snprintf (buf, size, "OA");
831 else if (path_type == OSPF6_ROUTE_PATH_TYPE_EXTERNAL1)
832 snprintf (buf, size, "E1");
833 else if (path_type == OSPF6_ROUTE_PATH_TYPE_EXTERNAL2)
834 snprintf (buf, size, "E2");
835 else
836 snprintf (buf, size, "%d", path_type);
837 return buf;
840 void
841 ospf6_route_statistics_show (struct vty *vty, struct route_table *table)
843 struct route_node *node;
844 struct ospf6_route_info *info;
845 u_int route_count, intra_count, inter_count, e1_count, e2_count, ecmp_count;
847 route_count = intra_count = inter_count = e1_count = e2_count = ecmp_count
848 = 0;
849 for (node = route_top (table); node; node = route_next (node))
851 info = (struct ospf6_route_info *) node->info;
852 if (! info)
853 continue;
855 route_count++;
856 if (info->path_type == OSPF6_ROUTE_PATH_TYPE_INTRA)
857 intra_count++;
858 else if (info->path_type == OSPF6_ROUTE_PATH_TYPE_INTER)
859 inter_count++;
860 else if (info->path_type == OSPF6_ROUTE_PATH_TYPE_EXTERNAL1)
861 e1_count++;
862 else if (info->path_type == OSPF6_ROUTE_PATH_TYPE_EXTERNAL2)
863 e2_count++;
865 if (listcount (info->nexthop_list) > 1)
866 ecmp_count++;
869 vty_out (vty, " Current Route count: %d%s",
870 route_count, VTY_NEWLINE);
871 vty_out (vty, " Intra: %d Inter: %d External: %d (Type1 %d/Type2 %d)%s",
872 intra_count, inter_count, e1_count + e2_count,
873 e1_count, e2_count, VTY_NEWLINE);
874 vty_out (vty, " Equal-cost multi-path: %d%s",
875 ecmp_count, VTY_NEWLINE);
878 void
879 ospf6_route_entry_show (struct vty *vty, struct prefix_ipv6 *d,
880 struct ospf6_route_info *ri)
882 listnode node;
883 struct ospf6_nexthop *n;
884 char buf[64], dstring[64], opt_string[16], nstring[64], ifname[16];
885 char astring[32], origin_string[32], pstring[4];
887 /* destination */
888 prefix2str ((struct prefix *) d, dstring, sizeof (dstring));
890 /* optional capability */
891 ospf6_opt_capability_string (ri->opt_capability, opt_string,
892 sizeof (opt_string));
894 /* Area id */
895 inet_ntop (AF_INET, &ri->area_id, astring, sizeof (astring));
897 /* Path Type */
898 ospf6_route_path_type_string (ri->path_type, pstring, sizeof (pstring));
900 /* Link state origin */
901 inet_ntop (AF_INET, &ri->origin_adv_router, buf, sizeof (buf));
902 snprintf (origin_string, sizeof (origin_string),
903 "%s[%lu]", buf, (unsigned long) ntohl (ri->origin_id));
905 for (node = listhead (ri->nexthop_list); node; nextnode (node))
907 n = (struct ospf6_nexthop *) getdata (node);
909 inet_ntop (AF_INET6, &n->ipaddr, nstring, sizeof (nstring));
911 if (if_indextoname (n->ifindex, buf))
912 snprintf (ifname, sizeof (ifname), "%s", buf);
913 else
914 snprintf (ifname, sizeof (ifname), "%d", n->ifindex);
916 vty_out (vty, "%c%2s %-43s %-9s %-8s %4d %-5d %-19s %-25s %4s%s",
917 (CHECK_FLAG (ri->flag, OSPF6_ROUTE_FLAG_ZEBRA_SYNC) ? '*' : ' '),
918 pstring, dstring, opt_string, astring, ri->cost, ri->cost_e2,
919 origin_string, nstring, ifname, VTY_NEWLINE);
923 void
924 ospf6_route_table_show_new (struct vty *vty, struct route_table *table)
926 struct route_node *node;
927 struct ospf6_route_info *info;
929 vty_out (vty, "%3s %-43s %-9s %-8s %4s %-5s %-19s %-25s %4s%s",
930 " ", "Destination", "Options", "Area", "Cost", "Type2",
931 "LS Origin", "Nexthop", "I/F", VTY_NEWLINE);
933 for (node = route_top (table); node; node = route_next (node))
935 info = (struct ospf6_route_info *) node->info;
936 if (! info)
937 continue;
938 ospf6_route_entry_show (vty, (struct prefix_ipv6 *) &node->p, info);
942 DEFUN (show_ipv6_route_ospf6_new,
943 show_ipv6_route_ospf6_new_cmd,
944 "show ipv6 route ospf6",
945 SHOW_STR
946 IP6_STR
947 "Routing table\n"
948 OSPF6_STR
952 OSPF6_CMD_CHECK_RUNNING ();
954 ospf6_route_table_show_new (vty, ospf6->route_table);
955 return CMD_SUCCESS;
958 DEFUN (show_ipv6_route_ospf6_prefix,
959 show_ipv6_route_ospf6_prefix_cmd,
960 "show ipv6 route ospf6 X::X",
961 SHOW_STR
962 IP6_STR
963 "Routing table\n"
964 OSPF6_STR
965 "match IPv6 prefix\n"
968 int ret;
969 struct route_node *node;
970 struct ospf6_route_info *info;
971 struct prefix p;
973 OSPF6_CMD_CHECK_RUNNING ();
976 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &p);
977 if (ret != 1)
978 return CMD_ERR_NO_MATCH;
980 node = route_node_match (ospf6->route_table, &p);
981 if (! node || ! node->info)
983 vty_out (vty, "Route not found%s", VTY_NEWLINE);
984 return CMD_SUCCESS;
987 vty_out (vty, "%3s %-43s %-9s %-8s %4s %-5s %-19s %-25s %4s%s",
988 " ", "Destination", "Options", "Area", "Cost", "Type2",
989 "LS Origin", "Nexthop", "I/F", VTY_NEWLINE);
991 info = (struct ospf6_route_info *) node->info;
992 ospf6_route_entry_show (vty, (struct prefix_ipv6 *) &node->p, info);
993 return CMD_SUCCESS;
996 void
997 ospf6_route_init ()
999 install_element (VIEW_NODE, &show_ipv6_route_ospf6_new_cmd);
1000 install_element (VIEW_NODE, &show_ipv6_route_ospf6_prefix_cmd);
1001 install_element (ENABLE_NODE, &show_ipv6_route_ospf6_new_cmd);
1002 install_element (ENABLE_NODE, &show_ipv6_route_ospf6_prefix_cmd);