]> git.sommitrealweird.co.uk Git - quagga-debian.git/blob - ospf6d/ospf6_route.c
New upstream release and new maintainer
[quagga-debian.git] / ospf6d / ospf6_route.c
1 /*
2  * Copyright (C) 2003 Yasuhiro Ohara
3  *
4  * This file is part of GNU Zebra.
5  *
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.
10  *
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.
15  *
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.  
20  */
21
22 #include <zebra.h>
23
24 #include "log.h"
25 #include "memory.h"
26 #include "prefix.h"
27 #include "table.h"
28 #include "vty.h"
29 #include "command.h"
30 #include "linklist.h"
31
32 #include "ospf6_proto.h"
33 #include "ospf6_lsa.h"
34 #include "ospf6_lsdb.h"
35 #include "ospf6_route.h"
36 #include "ospf6_top.h"
37 #include "ospf6_area.h"
38 #include "ospf6_interface.h"
39 #include "ospf6d.h"
40
41 unsigned char conf_debug_ospf6_route = 0;
42
43 static char *
44 ospf6_route_table_name (struct ospf6_route_table *table)
45 {
46   static char name[32];
47   switch (table->scope_type)
48     {
49       case OSPF6_SCOPE_TYPE_GLOBAL:
50         {
51           switch (table->table_type)
52             {
53               case OSPF6_TABLE_TYPE_ROUTES:
54                 snprintf (name, sizeof (name), "global route table");
55                 break;
56               case OSPF6_TABLE_TYPE_BORDER_ROUTERS:
57                 snprintf (name, sizeof (name), "global brouter table");
58                 break;
59               case OSPF6_TABLE_TYPE_EXTERNAL_ROUTES:
60                 snprintf (name, sizeof (name), "global external table");
61                 break;
62               default:
63                 snprintf (name, sizeof (name), "global unknown table");
64                 break;
65             }
66         }
67         break;
68
69       case OSPF6_SCOPE_TYPE_AREA:
70         {
71           struct ospf6_area *oa = (struct ospf6_area *) table->scope;
72           switch (table->table_type)
73             {
74               case OSPF6_TABLE_TYPE_SPF_RESULTS:
75                 snprintf (name, sizeof (name),
76                           "area %s spf table", oa->name);
77                 break;
78               case OSPF6_TABLE_TYPE_ROUTES:
79                 snprintf (name, sizeof (name),
80                           "area %s route table", oa->name);
81                 break;
82               case OSPF6_TABLE_TYPE_PREFIX_RANGES:
83                 snprintf (name, sizeof (name),
84                           "area %s range table", oa->name);
85                 break;
86               case OSPF6_TABLE_TYPE_SUMMARY_PREFIXES:
87                 snprintf (name, sizeof (name),
88                           "area %s summary prefix table", oa->name);
89                 break;
90               case OSPF6_TABLE_TYPE_SUMMARY_ROUTERS:
91                 snprintf (name, sizeof (name),
92                           "area %s summary router table", oa->name);
93                 break;
94               default:
95                 snprintf (name, sizeof (name),
96                           "area %s unknown table", oa->name);
97                 break;
98             }
99         }
100         break;
101
102       case OSPF6_SCOPE_TYPE_INTERFACE:
103         {
104           struct ospf6_interface *oi = (struct ospf6_interface *) table->scope;
105           switch (table->table_type)
106             {
107               case OSPF6_TABLE_TYPE_CONNECTED_ROUTES:
108                 snprintf (name, sizeof (name), "interface %s connected table",
109                           oi->interface->name);
110                 break;
111               default:
112                 snprintf (name, sizeof (name), "interface %s unknown table",
113                           oi->interface->name);
114                 break;
115             }
116         }
117         break;
118
119       default:
120         {
121           switch (table->table_type)
122             {
123               case OSPF6_TABLE_TYPE_SPF_RESULTS:
124                 snprintf (name, sizeof (name), "temporary spf table");
125                 break;
126               default:
127                 snprintf (name, sizeof (name), "temporary unknown table");
128                 break;
129             }
130         }
131         break;
132     }
133   return name;
134 }
135
136 void
137 ospf6_linkstate_prefix (u_int32_t adv_router, u_int32_t id,
138                         struct prefix *prefix)
139 {
140   memset (prefix, 0, sizeof (struct prefix));
141   prefix->family = AF_INET6;
142   prefix->prefixlen = 64;
143   memcpy (&prefix->u.prefix6.s6_addr[0], &adv_router, 4);
144   memcpy (&prefix->u.prefix6.s6_addr[4], &id, 4);
145 }
146
147 void
148 ospf6_linkstate_prefix2str (struct prefix *prefix, char *buf, int size)
149 {
150   u_int32_t adv_router, id;
151   char adv_router_str[16], id_str[16];
152   memcpy (&adv_router, &prefix->u.prefix6.s6_addr[0], 4);
153   memcpy (&id, &prefix->u.prefix6.s6_addr[4], 4);
154   inet_ntop (AF_INET, &adv_router, adv_router_str, sizeof (adv_router_str));
155   inet_ntop (AF_INET, &id, id_str, sizeof (id_str));
156   if (ntohl (id))
157     snprintf (buf, size, "%s Net-ID: %s", adv_router_str, id_str);
158   else
159     snprintf (buf, size, "%s", adv_router_str);
160 }
161
162 /* Global strings for logging */
163 const char *ospf6_dest_type_str[OSPF6_DEST_TYPE_MAX] =
164 { "Unknown", "Router", "Network", "Discard", "Linkstate", "AddressRange", };
165
166 const char *ospf6_dest_type_substr[OSPF6_DEST_TYPE_MAX] =
167 { "?", "R", "N", "D", "L", "A", };
168
169 const char *ospf6_path_type_str[OSPF6_PATH_TYPE_MAX] =
170 { "Unknown", "Intra-Area", "Inter-Area", "External-1", "External-2", };
171
172 const char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX] =
173 { "??", "IA", "IE", "E1", "E2", };
174
175
176 struct ospf6_route *
177 ospf6_route_create (void)
178 {
179   struct ospf6_route *route;
180   route = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route));
181   return route;
182 }
183
184 void
185 ospf6_route_delete (struct ospf6_route *route)
186 {
187   XFREE (MTYPE_OSPF6_ROUTE, route);
188 }
189
190 struct ospf6_route *
191 ospf6_route_copy (struct ospf6_route *route)
192 {
193   struct ospf6_route *new;
194
195   new = ospf6_route_create ();
196   memcpy (new, route, sizeof (struct ospf6_route));
197   new->rnode = NULL;
198   new->prev = NULL;
199   new->next = NULL;
200   new->table = NULL;
201   new->lock = 0;
202   return new;
203 }
204
205 void
206 ospf6_route_lock (struct ospf6_route *route)
207 {
208   route->lock++;
209 }
210
211 void
212 ospf6_route_unlock (struct ospf6_route *route)
213 {
214   assert (route->lock > 0);
215   route->lock--;
216   if (route->lock == 0)
217     {
218       /* Can't detach from the table until here
219          because ospf6_route_next () will use
220          the 'route->table' pointer for logging */
221       route->table = NULL;
222       ospf6_route_delete (route);
223     }
224 }
225
226 /* Route compare function. If ra is more preferred, it returns
227    less than 0. If rb is more preferred returns greater than 0.
228    Otherwise (neither one is preferred), returns 0 */
229 static int
230 ospf6_route_cmp (struct ospf6_route *ra, struct ospf6_route *rb)
231 {
232   assert (ospf6_route_is_same (ra, rb));
233   assert (OSPF6_PATH_TYPE_NONE < ra->path.type &&
234           ra->path.type < OSPF6_PATH_TYPE_MAX);
235   assert (OSPF6_PATH_TYPE_NONE < rb->path.type &&
236           rb->path.type < OSPF6_PATH_TYPE_MAX);
237
238   if (ra->type != rb->type)
239     return (ra->type - rb->type);
240
241   if (ra->path.area_id != rb->path.area_id)
242     return (ntohl (ra->path.area_id) - ntohl (rb->path.area_id));
243
244   if (ra->path.type != rb->path.type)
245     return (ra->path.type - rb->path.type);
246
247   if (ra->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
248     {
249       if (ra->path.cost_e2 != rb->path.cost_e2)
250         return (ra->path.cost_e2 - rb->path.cost_e2);
251     }
252   else
253     {
254       if (ra->path.cost != rb->path.cost)
255         return (ra->path.cost - rb->path.cost);
256     }
257
258   return 0;
259 }
260
261 struct ospf6_route *
262 ospf6_route_lookup (struct prefix *prefix,
263                     struct ospf6_route_table *table)
264 {
265   struct route_node *node;
266   struct ospf6_route *route;
267
268   node = route_node_lookup (table->table, prefix);
269   if (node == NULL)
270     return NULL;
271
272   route = (struct ospf6_route *) node->info;
273   return route;
274 }
275
276 struct ospf6_route *
277 ospf6_route_lookup_identical (struct ospf6_route *route,
278                               struct ospf6_route_table *table)
279 {
280   struct ospf6_route *target;
281
282   for (target = ospf6_route_lookup (&route->prefix, table);
283        target; target = target->next)
284     {
285       if (ospf6_route_is_identical (target, route))
286         return target;
287     }
288   return NULL;
289 }
290
291 struct ospf6_route *
292 ospf6_route_lookup_bestmatch (struct prefix *prefix,
293                               struct ospf6_route_table *table)
294 {
295   struct route_node *node;
296   struct ospf6_route *route;
297
298   node = route_node_match (table->table, prefix);
299   if (node == NULL)
300     return NULL;
301   route_unlock_node (node);
302
303   route = (struct ospf6_route *) node->info;
304   return route;
305 }
306
307 #ifdef DEBUG
308 static void
309 route_table_assert (struct ospf6_route_table *table)
310 {
311   struct ospf6_route *prev, *r, *next;
312   char buf[64];
313   unsigned int link_error = 0, num = 0;
314   
315   r = ospf6_route_head (table);
316   prev = NULL;
317   while (r)
318     {
319       if (r->prev != prev)
320         link_error++;
321       
322       next = ospf6_route_next (r);
323       
324       if (r->next != next)
325         link_error++;
326       
327       prev = r;
328       r = next;
329     }
330   
331   for (r = ospf6_route_head (table); r; r = ospf6_route_next (r))
332     num++;
333   
334   if (link_error == 0 && num == table->count)
335     return;
336
337   zlog_err ("PANIC !!");
338   zlog_err ("Something has gone wrong with ospf6_route_table[%p]", table);
339   zlog_debug ("table count = %d, real number = %d", table->count, num);
340   zlog_debug ("DUMP START");
341   for (r = ospf6_route_head (table); r; r = ospf6_route_next (r))
342     {
343       prefix2str (&r->prefix, buf, sizeof (buf));
344       zlog_info ("%p<-[%p]->%p : %s", r->prev, r, r->next, buf);
345     }
346   zlog_debug ("DUMP END");
347
348   assert (link_error == 0 && num == table->count);
349 }
350 #define ospf6_route_table_assert(t) (route_table_assert (t))
351 #else
352 #define ospf6_route_table_assert(t) ((void) 0)
353 #endif /*DEBUG*/
354
355 struct ospf6_route *
356 ospf6_route_add (struct ospf6_route *route,
357                  struct ospf6_route_table *table)
358 {
359   struct route_node *node, *nextnode, *prevnode;
360   struct ospf6_route *current = NULL;
361   struct ospf6_route *prev = NULL, *old = NULL, *next = NULL;
362   char buf[64];
363   struct timeval now;
364
365   assert (route->rnode == NULL);
366   assert (route->lock == 0);
367   assert (route->next == NULL);
368   assert (route->prev == NULL);
369
370   if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
371     ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
372   else
373     prefix2str (&route->prefix, buf, sizeof (buf));
374
375   if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
376     zlog_debug ("%s %p: route add %p: %s", ospf6_route_table_name (table),
377                 (void *)table, (void *)route, buf);
378   else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
379     zlog_debug ("%s: route add: %s", ospf6_route_table_name (table), buf);
380
381   quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
382
383   node = route_node_get (table->table, &route->prefix);
384   route->rnode = node;
385
386   /* find place to insert */
387   for (current = node->info; current; current = current->next)
388     {
389       if (! ospf6_route_is_same (current, route))
390         next = current;
391       else if (current->type != route->type)
392         prev = current;
393       else if (ospf6_route_is_same_origin (current, route))
394         old = current;
395       else if (ospf6_route_cmp (current, route) > 0)
396         next = current;
397       else
398         prev = current;
399
400       if (old || next)
401         break;
402     }
403
404   if (old)
405     {
406       /* if route does not actually change, return unchanged */
407       if (ospf6_route_is_identical (old, route))
408         {
409           if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
410             zlog_debug ("%s %p: route add %p: needless update of %p",
411                         ospf6_route_table_name (table),
412                         (void *)table, (void *)route, (void *)old);
413           else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
414             zlog_debug ("%s: route add: needless update",
415                         ospf6_route_table_name (table));
416
417           ospf6_route_delete (route);
418           SET_FLAG (old->flag, OSPF6_ROUTE_ADD);
419           ospf6_route_table_assert (table);
420
421           return old;
422         }
423
424       if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
425         zlog_debug ("%s %p: route add %p: update of %p",
426                     ospf6_route_table_name (table),
427                     (void *)table, (void *)route, (void *)old);
428       else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
429         zlog_debug ("%s: route add: update",
430                     ospf6_route_table_name (table));
431
432       /* replace old one if exists */
433       if (node->info == old)
434         {
435           node->info = route;
436           SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
437         }
438
439       if (old->prev)
440         old->prev->next = route;
441       route->prev = old->prev;
442       if (old->next)
443         old->next->prev = route;
444       route->next = old->next;
445
446       route->installed = old->installed;
447       route->changed = now;
448       assert (route->table == NULL);
449       route->table = table;
450
451       ospf6_route_unlock (old); /* will be deleted later */
452       ospf6_route_lock (route);
453
454       SET_FLAG (route->flag, OSPF6_ROUTE_CHANGE);
455       ospf6_route_table_assert (table);
456
457       if (table->hook_add)
458         (*table->hook_add) (route);
459
460       return route;
461     }
462
463   /* insert if previous or next node found */
464   if (prev || next)
465     {
466       if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
467         zlog_debug ("%s %p: route add %p: another path: prev %p, next %p",
468                     ospf6_route_table_name (table),
469                     (void *)table, (void *)route, (void *)prev, (void *)next);
470       else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
471         zlog_debug ("%s: route add: another path found",
472                     ospf6_route_table_name (table));
473
474       if (prev == NULL)
475         prev = next->prev;
476       if (next == NULL)
477         next = prev->next;
478
479       if (prev)
480         prev->next = route;
481       route->prev = prev;
482       if (next)
483         next->prev = route;
484       route->next = next;
485
486       if (node->info == next)
487         {
488           assert (next->rnode == node);
489           node->info = route;
490           UNSET_FLAG (next->flag, OSPF6_ROUTE_BEST);
491           SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
492           if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
493             zlog_info ("%s %p: route add %p: replacing previous best: %p",
494                        ospf6_route_table_name (table),
495                        (void *)table, (void *)route, (void *)next);
496         }
497
498       route->installed = now;
499       route->changed = now;
500       assert (route->table == NULL);
501       route->table = table;
502
503       ospf6_route_lock (route);
504       table->count++;
505       ospf6_route_table_assert (table);
506
507       SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
508       if (table->hook_add)
509         (*table->hook_add) (route);
510
511       return route;
512     }
513
514   /* Else, this is the brand new route regarding to the prefix */
515   if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
516     zlog_debug ("%s %p: route add %p: brand new route",
517                 ospf6_route_table_name (table), (void *)table, (void *)route);
518   else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
519     zlog_debug ("%s: route add: brand new route",
520                 ospf6_route_table_name (table));
521
522   assert (node->info == NULL);
523   node->info = route;
524   SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
525   ospf6_route_lock (route);
526   route->installed = now;
527   route->changed = now;
528   assert (route->table == NULL);
529   route->table = table;
530
531   /* lookup real existing next route */
532   nextnode = node;
533   route_lock_node (nextnode);
534   do {
535     nextnode = route_next (nextnode);
536   } while (nextnode && nextnode->info == NULL);
537
538   /* set next link */
539   if (nextnode == NULL)
540     route->next = NULL;
541   else
542     {
543       route_unlock_node (nextnode);
544
545       next = nextnode->info;
546       route->next = next;
547       next->prev = route;
548     }
549
550   /* lookup real existing prev route */
551   prevnode = node;
552   route_lock_node (prevnode);
553   do {
554     prevnode = route_prev (prevnode);
555   } while (prevnode && prevnode->info == NULL);
556
557   /* set prev link */
558   if (prevnode == NULL)
559     route->prev = NULL;
560   else
561     {
562       route_unlock_node (prevnode);
563
564       prev = prevnode->info;
565       while (prev->next && ospf6_route_is_same (prev, prev->next))
566         prev = prev->next;
567       route->prev = prev;
568       prev->next = route;
569     }
570
571   table->count++;
572   ospf6_route_table_assert (table);
573
574   SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
575   if (table->hook_add)
576     (*table->hook_add) (route);
577
578   return route;
579 }
580
581 void
582 ospf6_route_remove (struct ospf6_route *route,
583                     struct ospf6_route_table *table)
584 {
585   struct route_node *node;
586   struct ospf6_route *current;
587   char buf[64];
588
589   if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
590     ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
591   else
592     prefix2str (&route->prefix, buf, sizeof (buf));
593
594   if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
595     zlog_debug ("%s %p: route remove %p: %s",
596                 ospf6_route_table_name (table),
597                 (void *)table, (void *)route, buf);
598   else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
599     zlog_debug ("%s: route remove: %s", ospf6_route_table_name (table), buf);
600
601   node = route_node_lookup (table->table, &route->prefix);
602   assert (node);
603
604   /* find the route to remove, making sure that the route pointer
605      is from the route table. */
606   current = node->info;
607   while (current && ospf6_route_is_same (current, route))
608     {
609       if (current == route)
610         break;
611       current = current->next;
612     }
613   assert (current == route);
614
615   /* adjust doubly linked list */
616   if (route->prev)
617     route->prev->next = route->next;
618   if (route->next)
619     route->next->prev = route->prev;
620
621   if (node->info == route)
622     {
623       if (route->next && route->next->rnode == node)
624         {
625           node->info = route->next;
626           SET_FLAG (route->next->flag, OSPF6_ROUTE_BEST);
627         }
628       else
629         node->info = NULL; /* should unlock route_node here ? */
630     }
631
632   table->count--;
633   ospf6_route_table_assert (table);
634
635   SET_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED);
636
637   if (table->hook_remove)
638     (*table->hook_remove) (route);
639
640   ospf6_route_unlock (route);
641 }
642
643 struct ospf6_route *
644 ospf6_route_head (struct ospf6_route_table *table)
645 {
646   struct route_node *node;
647   struct ospf6_route *route;
648
649   node = route_top (table->table);
650   if (node == NULL)
651     return NULL;
652
653   /* skip to the real existing entry */
654   while (node && node->info == NULL)
655     node = route_next (node);
656   if (node == NULL)
657     return NULL;
658
659   route_unlock_node (node);
660   assert (node->info);
661
662   route = (struct ospf6_route *) node->info;
663   assert (route->prev == NULL);
664   assert (route->table == table);
665   ospf6_route_lock (route);
666
667   if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
668     zlog_info ("%s %p: route head: %p<-[%p]->%p",
669                ospf6_route_table_name (table), (void *)table,
670                (void *)route->prev, (void *)route, (void *)route->next);
671
672   return route;
673 }
674
675 struct ospf6_route *
676 ospf6_route_next (struct ospf6_route *route)
677 {
678   struct ospf6_route *next = route->next;
679
680   if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
681     zlog_info ("%s %p: route next: %p<-[%p]->%p",
682                ospf6_route_table_name (route->table), (void *)route->table,
683                (void *)route->prev, (void *)route, (void *)route->next);
684
685   ospf6_route_unlock (route);
686   if (next)
687     ospf6_route_lock (next);
688
689   return next;
690 }
691
692 struct ospf6_route *
693 ospf6_route_best_next (struct ospf6_route *route)
694 {
695   struct route_node *rnode;
696   struct ospf6_route *next;
697
698   ospf6_route_unlock (route);
699
700   rnode = route->rnode;
701   route_lock_node (rnode);
702   rnode = route_next (rnode);
703   while (rnode && rnode->info == NULL)
704     rnode = route_next (rnode);
705   if (rnode == NULL)
706     return NULL;
707   route_unlock_node (rnode);
708
709   assert (rnode->info);
710   next = (struct ospf6_route *) rnode->info;
711   ospf6_route_lock (next);
712   return next;
713 }
714
715 struct ospf6_route *
716 ospf6_route_match_head (struct prefix *prefix,
717                         struct ospf6_route_table *table)
718 {
719   struct route_node *node;
720   struct ospf6_route *route;
721
722   /* Walk down tree. */
723   node = table->table->top;
724   while (node && node->p.prefixlen < prefix->prefixlen &&
725          prefix_match (&node->p, prefix))
726     node = node->link[prefix_bit(&prefix->u.prefix, node->p.prefixlen)];
727
728   if (node)
729     route_lock_node (node);
730   while (node && node->info == NULL)
731     node = route_next (node);
732   if (node == NULL)
733     return NULL;
734   route_unlock_node (node);
735
736   if (! prefix_match (prefix, &node->p))
737     return NULL;
738
739   route = node->info;
740   ospf6_route_lock (route);
741   return route;
742 }
743
744 struct ospf6_route *
745 ospf6_route_match_next (struct prefix *prefix,
746                         struct ospf6_route *route)
747 {
748   struct ospf6_route *next;
749
750   next = ospf6_route_next (route);
751   if (next && ! prefix_match (prefix, &next->prefix))
752     {
753       ospf6_route_unlock (next);
754       next = NULL;
755     }
756
757   return next;
758 }
759
760 void
761 ospf6_route_remove_all (struct ospf6_route_table *table)
762 {
763   struct ospf6_route *route;
764   for (route = ospf6_route_head (table); route;
765        route = ospf6_route_next (route))
766     ospf6_route_remove (route, table);
767 }
768
769 struct ospf6_route_table *
770 ospf6_route_table_create (int s, int t)
771 {
772   struct ospf6_route_table *new;
773   new = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table));
774   new->table = route_table_init ();
775   new->scope_type = s;
776   new->table_type = t;
777   return new;
778 }
779
780 void
781 ospf6_route_table_delete (struct ospf6_route_table *table)
782 {
783   ospf6_route_remove_all (table);
784   route_table_finish (table->table);
785   XFREE (MTYPE_OSPF6_ROUTE, table);
786 }
787
788
789 /* VTY commands */
790 void
791 ospf6_route_show (struct vty *vty, struct ospf6_route *route)
792 {
793   int i;
794   char destination[64], nexthop[64];
795   char duration[16];
796   const char *ifname;
797   struct timeval now, res;
798
799   quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
800   timersub (&now, &route->changed, &res);
801   timerstring (&res, duration, sizeof (duration));
802
803   /* destination */
804   if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
805     ospf6_linkstate_prefix2str (&route->prefix, destination,
806                                 sizeof (destination));
807   else if (route->type == OSPF6_DEST_TYPE_ROUTER)
808     inet_ntop (route->prefix.family, &route->prefix.u.prefix,
809                destination, sizeof (destination));
810   else
811     prefix2str (&route->prefix, destination, sizeof (destination));
812
813   /* nexthop */
814   inet_ntop (AF_INET6, &route->nexthop[0].address, nexthop,
815              sizeof (nexthop));
816   ifname = ifindex2ifname (route->nexthop[0].ifindex);
817
818   vty_out (vty, "%c%1s %2s %-30s %-25s %6.*s %s%s",
819            (ospf6_route_is_best (route) ? '*' : ' '),
820            OSPF6_DEST_TYPE_SUBSTR (route->type),
821            OSPF6_PATH_TYPE_SUBSTR (route->path.type),
822            destination, nexthop, IFNAMSIZ, ifname, duration, VNL);
823
824   for (i = 1; i < OSPF6_MULTI_PATH_LIMIT &&
825        ospf6_nexthop_is_set (&route->nexthop[i]); i++)
826     {
827       /* nexthop */
828       inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
829                  sizeof (nexthop));
830       ifname = ifindex2ifname (route->nexthop[i].ifindex);
831
832       vty_out (vty, "%c%1s %2s %-30s %-25s %6.*s %s%s",
833                ' ', "", "", "", nexthop, IFNAMSIZ, ifname, "", VNL);
834     }
835 }
836
837 void
838 ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route)
839 {
840   const char *ifname;
841   char destination[64], nexthop[64];
842   char area_id[16], id[16], adv_router[16], capa[16], options[16];
843   struct timeval now, res;
844   char duration[16];
845   int i;
846
847   quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
848
849   /* destination */
850   if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
851     ospf6_linkstate_prefix2str (&route->prefix, destination,
852                                 sizeof (destination));
853   else if (route->type == OSPF6_DEST_TYPE_ROUTER)
854     inet_ntop (route->prefix.family, &route->prefix.u.prefix,
855                destination, sizeof (destination));
856   else
857     prefix2str (&route->prefix, destination, sizeof (destination));
858   vty_out (vty, "Destination: %s%s", destination, VNL);
859
860   /* destination type */
861   vty_out (vty, "Destination type: %s%s",
862            OSPF6_DEST_TYPE_NAME (route->type),
863            VNL);
864
865   /* Time */
866   timersub (&now, &route->installed, &res);
867   timerstring (&res, duration, sizeof (duration));
868   vty_out (vty, "Installed Time: %s ago%s", duration, VNL);
869
870   timersub (&now, &route->changed, &res);
871   timerstring (&res, duration, sizeof (duration));
872   vty_out (vty, "  Changed Time: %s ago%s", duration, VNL);
873
874   /* Debugging info */
875   vty_out (vty, "Lock: %d Flags: %s%s%s%s%s", route->lock,
876            (CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST)   ? "B" : "-"),
877            (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD)    ? "A" : "-"),
878            (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
879            (CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"),
880            VNL);
881   vty_out (vty, "Memory: prev: %p this: %p next: %p%s",
882            (void *)route->prev, (void *)route, (void *)route->next, VNL);
883
884   /* Path section */
885
886   /* Area-ID */
887   inet_ntop (AF_INET, &route->path.area_id, area_id, sizeof (area_id));
888   vty_out (vty, "Associated Area: %s%s", area_id, VNL);
889
890   /* Path type */
891   vty_out (vty, "Path Type: %s%s",
892            OSPF6_PATH_TYPE_NAME (route->path.type), VNL);
893
894   /* LS Origin */
895   inet_ntop (AF_INET, &route->path.origin.id, id, sizeof (id));
896   inet_ntop (AF_INET, &route->path.origin.adv_router, adv_router,
897              sizeof (adv_router));
898   vty_out (vty, "LS Origin: %s Id: %s Adv: %s%s",
899            ospf6_lstype_name (route->path.origin.type),
900            id, adv_router, VNL);
901
902   /* Options */
903   ospf6_options_printbuf (route->path.options, options, sizeof (options));
904   vty_out (vty, "Options: %s%s", options, VNL);
905
906   /* Router Bits */
907   ospf6_capability_printbuf (route->path.router_bits, capa, sizeof (capa));
908   vty_out (vty, "Router Bits: %s%s", capa, VNL);
909
910   /* Prefix Options */
911   vty_out (vty, "Prefix Options: xxx%s", VNL);
912
913   /* Metrics */
914   vty_out (vty, "Metric Type: %d%s", route->path.metric_type,
915            VNL);
916   vty_out (vty, "Metric: %d (%d)%s",
917            route->path.cost, route->path.cost_e2, VNL);
918
919   /* Nexthops */
920   vty_out (vty, "Nexthop:%s", VNL);
921   for (i = 0; i < OSPF6_MULTI_PATH_LIMIT &&
922        ospf6_nexthop_is_set (&route->nexthop[i]); i++)
923     {
924       /* nexthop */
925       inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
926                  sizeof (nexthop));
927       ifname = ifindex2ifname (route->nexthop[i].ifindex);
928       vty_out (vty, "  %s %.*s%s", nexthop, IFNAMSIZ, ifname, VNL);
929     }
930   vty_out (vty, "%s", VNL);
931 }
932
933 static void
934 ospf6_route_show_table_summary (struct vty *vty,
935                                 struct ospf6_route_table *table)
936 {
937   struct ospf6_route *route, *prev = NULL;
938   int i, pathtype[OSPF6_PATH_TYPE_MAX];
939   unsigned int number = 0;
940   int nhinval = 0, ecmp = 0;
941   int alternative = 0, destination = 0;
942
943   for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
944     pathtype[i] = 0;
945
946   for (route = ospf6_route_head (table); route;
947        route = ospf6_route_next (route))
948     {
949       if (prev == NULL || ! ospf6_route_is_same (prev, route))
950         destination++;
951       else
952         alternative++;
953       if (! ospf6_nexthop_is_set (&route->nexthop[0]))
954         nhinval++;
955       else if (ospf6_nexthop_is_set (&route->nexthop[1]))
956         ecmp++;
957       pathtype[route->path.type]++;
958       number++;
959
960       prev = route;
961     }
962
963   assert (number == table->count);
964
965   vty_out (vty, "Number of OSPFv3 routes: %d%s", number, VNL);
966   vty_out (vty, "Number of Destination: %d%s", destination, VNL);
967   vty_out (vty, "Number of Alternative routes: %d%s", alternative, VNL);
968   vty_out (vty, "Number of Equal Cost Multi Path: %d%s", ecmp, VNL);
969   for (i = OSPF6_PATH_TYPE_INTRA; i <= OSPF6_PATH_TYPE_EXTERNAL2; i++)
970     {
971       vty_out (vty, "Number of %s routes: %d%s",
972                OSPF6_PATH_TYPE_NAME (i), pathtype[i], VNL);
973     }
974 }
975
976 static void
977 ospf6_route_show_table_prefix (struct vty *vty,
978                                struct prefix *prefix,
979                                struct ospf6_route_table *table)
980 {
981   struct ospf6_route *route;
982
983   route = ospf6_route_lookup (prefix, table);
984   if (route == NULL)
985     return;
986
987   ospf6_route_lock (route);
988   while (route && ospf6_route_is_prefix (prefix, route))
989     {
990       /* Specifying a prefix will always display details */
991       ospf6_route_show_detail (vty, route);
992       route = ospf6_route_next (route);
993     }
994   if (route)
995     ospf6_route_unlock (route);
996 }
997
998 static void
999 ospf6_route_show_table_address (struct vty *vty,
1000                                 struct prefix *prefix,
1001                                 struct ospf6_route_table *table)
1002 {
1003   struct ospf6_route *route;
1004
1005   route = ospf6_route_lookup_bestmatch (prefix, table);
1006   if (route == NULL)
1007     return;
1008
1009   prefix = &route->prefix;
1010   ospf6_route_lock (route);
1011   while (route && ospf6_route_is_prefix (prefix, route))
1012     {
1013       /* Specifying a prefix will always display details */
1014       ospf6_route_show_detail (vty, route);
1015       route = ospf6_route_next (route);
1016     }
1017   if (route)
1018     ospf6_route_unlock (route);
1019 }
1020
1021 static void
1022 ospf6_route_show_table_match (struct vty *vty, int detail,
1023                               struct prefix *prefix,
1024                               struct ospf6_route_table *table)
1025 {
1026   struct ospf6_route *route;
1027   assert (prefix->family);
1028
1029   route = ospf6_route_match_head (prefix, table);
1030   while (route)
1031     {
1032       if (detail)
1033         ospf6_route_show_detail (vty, route);
1034       else
1035         ospf6_route_show (vty, route);
1036       route = ospf6_route_match_next (prefix, route);
1037     }
1038 }
1039
1040 static void
1041 ospf6_route_show_table_type (struct vty *vty, int detail, u_char type,
1042                              struct ospf6_route_table *table)
1043 {
1044   struct ospf6_route *route;
1045
1046   route = ospf6_route_head (table);
1047   while (route)
1048     {
1049       if (route->path.type == type)
1050         {
1051           if (detail)
1052             ospf6_route_show_detail (vty, route);
1053           else
1054             ospf6_route_show (vty, route);
1055         }
1056       route = ospf6_route_next (route);
1057     }
1058 }
1059
1060 static void
1061 ospf6_route_show_table (struct vty *vty, int detail,
1062                         struct ospf6_route_table *table)
1063 {
1064   struct ospf6_route *route;
1065
1066   route = ospf6_route_head (table);
1067   while (route)
1068     {
1069       if (detail)
1070         ospf6_route_show_detail (vty, route);
1071       else
1072         ospf6_route_show (vty, route);
1073       route = ospf6_route_next (route);
1074     }
1075 }
1076
1077 int
1078 ospf6_route_table_show (struct vty *vty, int argc, const char *argv[],
1079                         struct ospf6_route_table *table)
1080 {
1081   int summary = 0;
1082   int match = 0;
1083   int detail = 0;
1084   int slash = 0;
1085   int isprefix = 0;
1086   int i, ret;
1087   struct prefix prefix;
1088   u_char type = 0;
1089
1090   memset (&prefix, 0, sizeof (struct prefix));
1091
1092   for (i = 0; i < argc; i++)
1093     {
1094       if (! strcmp (argv[i], "summary"))
1095         {
1096           summary++;
1097           continue;
1098         }
1099
1100       if (! strcmp (argv[i], "intra-area"))
1101         {
1102           type = OSPF6_PATH_TYPE_INTRA;
1103           continue;
1104         }
1105
1106       if (! strcmp (argv[i], "inter-area"))
1107         {
1108           type = OSPF6_PATH_TYPE_INTER;
1109           continue;
1110         }
1111
1112       if (! strcmp (argv[i], "external-1"))
1113         {
1114           type = OSPF6_PATH_TYPE_EXTERNAL1;
1115           continue;
1116         }
1117
1118       if (! strcmp (argv[i], "external-2"))
1119         {
1120           type = OSPF6_PATH_TYPE_EXTERNAL2;
1121           continue;
1122         }
1123
1124       if (! strcmp (argv[i], "detail"))
1125         {
1126           detail++;
1127           continue;
1128         }
1129
1130       if (! strcmp (argv[i], "match"))
1131         {
1132           match++;
1133           continue;
1134         }
1135
1136       ret = str2prefix (argv[i], &prefix);
1137       if (ret == 1 && prefix.family == AF_INET6)
1138         {
1139           isprefix++;
1140           if (strchr (argv[i], '/'))
1141             slash++;
1142           continue;
1143         }
1144
1145       vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
1146       return CMD_SUCCESS;
1147     }
1148
1149   /* Give summary of this route table */
1150   if (summary)
1151     {
1152       ospf6_route_show_table_summary (vty, table);
1153       return CMD_SUCCESS;
1154     }
1155
1156   /* Give exact prefix-match route */
1157   if (isprefix && ! match)
1158     {
1159       /* If exact address, give best matching route */
1160       if (! slash)
1161         ospf6_route_show_table_address (vty, &prefix, table);
1162       else
1163         ospf6_route_show_table_prefix (vty, &prefix, table);
1164
1165       return CMD_SUCCESS;
1166     }
1167
1168   if (match)
1169     ospf6_route_show_table_match (vty, detail, &prefix, table);
1170   else if (type)
1171     ospf6_route_show_table_type (vty, detail, type, table);
1172   else
1173     ospf6_route_show_table (vty, detail, table);
1174
1175   return CMD_SUCCESS;
1176 }
1177
1178 static void
1179 ospf6_linkstate_show_header (struct vty *vty)
1180 {
1181   vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %s%s",
1182            "Type", "Router-ID", "Net-ID", "Rtr-Bits", "Options", "Cost", VNL);
1183 }
1184
1185 static void
1186 ospf6_linkstate_show (struct vty *vty, struct ospf6_route *route)
1187 {
1188   u_int32_t router, id;
1189   char routername[16], idname[16], rbits[16], options[16];
1190
1191   router = ospf6_linkstate_prefix_adv_router (&route->prefix);
1192   inet_ntop (AF_INET, &router, routername, sizeof (routername));
1193   id = ospf6_linkstate_prefix_id (&route->prefix);
1194   inet_ntop (AF_INET, &id, idname, sizeof (idname));
1195
1196   ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
1197   ospf6_options_printbuf (route->path.options, options, sizeof (options));
1198
1199   if (ntohl (id))
1200     vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu%s",
1201              "Network", routername, idname, rbits, options,
1202              (unsigned long) route->path.cost, VNL);
1203   else
1204     vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu%s",
1205              "Router", routername, idname, rbits, options,
1206              (unsigned long) route->path.cost, VNL);
1207 }
1208
1209
1210 static void
1211 ospf6_linkstate_show_table_exact (struct vty *vty,
1212                                   struct prefix *prefix,
1213                                   struct ospf6_route_table *table)
1214 {
1215   struct ospf6_route *route;
1216
1217   route = ospf6_route_lookup (prefix, table);
1218   if (route == NULL)
1219     return;
1220
1221   ospf6_route_lock (route);
1222   while (route && ospf6_route_is_prefix (prefix, route))
1223     {
1224       /* Specifying a prefix will always display details */
1225       ospf6_route_show_detail (vty, route);
1226       route = ospf6_route_next (route);
1227     }
1228   if (route)
1229     ospf6_route_unlock (route);
1230 }
1231
1232 static void
1233 ospf6_linkstate_show_table (struct vty *vty, int detail,
1234                             struct ospf6_route_table *table)
1235 {
1236   struct ospf6_route *route;
1237
1238   if (! detail)
1239     ospf6_linkstate_show_header (vty);
1240
1241   route = ospf6_route_head (table);
1242   while (route)
1243     {
1244       if (detail)
1245         ospf6_route_show_detail (vty, route);
1246       else
1247         ospf6_linkstate_show (vty, route);
1248       route = ospf6_route_next (route);
1249     }
1250 }
1251
1252 int
1253 ospf6_linkstate_table_show (struct vty *vty, int argc, const char *argv[],
1254                             struct ospf6_route_table *table)
1255 {
1256   int detail = 0;
1257   int is_id = 0;
1258   int is_router = 0;
1259   int i, ret;
1260   struct prefix router, id, prefix;
1261
1262   memset (&router, 0, sizeof (struct prefix));
1263   memset (&id, 0, sizeof (struct prefix));
1264   memset (&prefix, 0, sizeof (struct prefix));
1265
1266   for (i = 0; i < argc; i++)
1267     {
1268       if (! strcmp (argv[i], "detail"))
1269         {
1270           detail++;
1271           continue;
1272         }
1273
1274       if (! is_router)
1275         {
1276           ret = str2prefix (argv[i], &router);
1277           if (ret == 1 && router.family == AF_INET)
1278             {
1279               is_router++;
1280               continue;
1281             }
1282           vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
1283           return CMD_SUCCESS;
1284         }
1285
1286       if (! is_id)
1287         {
1288           ret = str2prefix (argv[i], &id);
1289           if (ret == 1 && id.family == AF_INET)
1290             {
1291               is_id++;
1292               continue;
1293             }
1294           vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
1295           return CMD_SUCCESS;
1296         }
1297
1298       vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
1299       return CMD_SUCCESS;
1300     }
1301
1302   if (is_router)
1303     ospf6_linkstate_prefix (router.u.prefix4.s_addr,
1304                             id.u.prefix4.s_addr, &prefix);
1305
1306   if (prefix.family)
1307     ospf6_linkstate_show_table_exact (vty, &prefix, table);
1308   else
1309     ospf6_linkstate_show_table (vty, detail, table);
1310
1311   return CMD_SUCCESS;
1312 }
1313
1314
1315 void
1316 ospf6_brouter_show_header (struct vty *vty)
1317 {
1318   vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1319            "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL);
1320 }
1321
1322 void
1323 ospf6_brouter_show (struct vty *vty, struct ospf6_route *route)
1324 {
1325   u_int32_t adv_router;
1326   char adv[16], rbits[16], options[16], area[16];
1327
1328   adv_router = ospf6_linkstate_prefix_adv_router (&route->prefix);
1329   inet_ntop (AF_INET, &adv_router, adv, sizeof (adv));
1330   ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
1331   ospf6_options_printbuf (route->path.options, options, sizeof (options));
1332   inet_ntop (AF_INET, &route->path.area_id, area, sizeof (area));
1333
1334   /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1335            "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL); */
1336   vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1337            adv, rbits, options, OSPF6_PATH_TYPE_NAME (route->path.type),
1338            area, VNL);
1339 }
1340
1341 DEFUN (debug_ospf6_route,
1342        debug_ospf6_route_cmd,
1343        "debug ospf6 route (table|intra-area|inter-area|memory)",
1344        DEBUG_STR
1345        OSPF6_STR
1346        "Debug route table calculation\n"
1347        "Debug detail\n"
1348        "Debug intra-area route calculation\n"
1349        "Debug inter-area route calculation\n"
1350        "Debug route memory use\n"
1351        )
1352 {
1353   unsigned char level = 0;
1354
1355   if (! strncmp (argv[0], "table", 5))
1356     level = OSPF6_DEBUG_ROUTE_TABLE;
1357   else if (! strncmp (argv[0], "intra", 5))
1358     level = OSPF6_DEBUG_ROUTE_INTRA;
1359   else if (! strncmp (argv[0], "inter", 5))
1360     level = OSPF6_DEBUG_ROUTE_INTER;
1361   else if (! strncmp (argv[0], "memor", 5))
1362     level = OSPF6_DEBUG_ROUTE_MEMORY;
1363   OSPF6_DEBUG_ROUTE_ON (level);
1364   return CMD_SUCCESS;
1365 }
1366
1367 DEFUN (no_debug_ospf6_route,
1368        no_debug_ospf6_route_cmd,
1369        "no debug ospf6 route (table|intra-area|inter-area|memory)",
1370        NO_STR
1371        DEBUG_STR
1372        OSPF6_STR
1373        "Debug route table calculation\n"
1374        "Debug intra-area route calculation\n"
1375        "Debug route memory use\n")
1376 {
1377   unsigned char level = 0;
1378
1379   if (! strncmp (argv[0], "table", 5))
1380     level = OSPF6_DEBUG_ROUTE_TABLE;
1381   else if (! strncmp (argv[0], "intra", 5))
1382     level = OSPF6_DEBUG_ROUTE_INTRA;
1383   else if (! strncmp (argv[0], "inter", 5))
1384     level = OSPF6_DEBUG_ROUTE_INTER;
1385   else if (! strncmp (argv[0], "memor", 5))
1386     level = OSPF6_DEBUG_ROUTE_MEMORY;
1387   OSPF6_DEBUG_ROUTE_OFF (level);
1388   return CMD_SUCCESS;
1389 }
1390
1391 int
1392 config_write_ospf6_debug_route (struct vty *vty)
1393 {
1394   if (IS_OSPF6_DEBUG_ROUTE (TABLE))
1395     vty_out (vty, "debug ospf6 route table%s", VNL);
1396   if (IS_OSPF6_DEBUG_ROUTE (INTRA))
1397     vty_out (vty, "debug ospf6 route intra-area%s", VNL);
1398   if (IS_OSPF6_DEBUG_ROUTE (INTER))
1399     vty_out (vty, "debug ospf6 route inter-area%s", VNL);
1400   return 0;
1401 }
1402
1403 void
1404 install_element_ospf6_debug_route (void)
1405 {
1406   install_element (ENABLE_NODE, &debug_ospf6_route_cmd);
1407   install_element (ENABLE_NODE, &no_debug_ospf6_route_cmd);
1408   install_element (CONFIG_NODE, &debug_ospf6_route_cmd);
1409   install_element (CONFIG_NODE, &no_debug_ospf6_route_cmd);
1410 }
1411
1412
1413