ospfd: Tighten up the connected check for redistribution
[jleu-quagga.git] / ospf6d / ospf6_top.c
blobc4cc9fac8f7bca978013a86a56ba3965482cbc70
1 /*
2 * Copyright (C) 2003 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.
22 #include <zebra.h>
24 #include "log.h"
25 #include "memory.h"
26 #include "vty.h"
27 #include "linklist.h"
28 #include "prefix.h"
29 #include "table.h"
30 #include "thread.h"
31 #include "command.h"
33 #include "ospf6_proto.h"
34 #include "ospf6_message.h"
35 #include "ospf6_lsa.h"
36 #include "ospf6_lsdb.h"
37 #include "ospf6_route.h"
38 #include "ospf6_zebra.h"
40 #include "ospf6_top.h"
41 #include "ospf6_area.h"
42 #include "ospf6_interface.h"
43 #include "ospf6_neighbor.h"
45 #include "ospf6_flood.h"
46 #include "ospf6_asbr.h"
47 #include "ospf6_abr.h"
48 #include "ospf6_intra.h"
49 #include "ospf6d.h"
51 /* global ospf6d variable */
52 struct ospf6 *ospf6;
54 static void
55 ospf6_top_lsdb_hook_add (struct ospf6_lsa *lsa)
57 switch (ntohs (lsa->header->type))
59 case OSPF6_LSTYPE_AS_EXTERNAL:
60 ospf6_asbr_lsa_add (lsa);
61 break;
63 default:
64 break;
68 static void
69 ospf6_top_lsdb_hook_remove (struct ospf6_lsa *lsa)
71 switch (ntohs (lsa->header->type))
73 case OSPF6_LSTYPE_AS_EXTERNAL:
74 ospf6_asbr_lsa_remove (lsa);
75 break;
77 default:
78 break;
82 static void
83 ospf6_top_route_hook_add (struct ospf6_route *route)
85 ospf6_abr_originate_summary (route);
86 ospf6_zebra_route_update_add (route);
89 static void
90 ospf6_top_route_hook_remove (struct ospf6_route *route)
92 ospf6_abr_originate_summary (route);
93 ospf6_zebra_route_update_remove (route);
96 static void
97 ospf6_top_brouter_hook_add (struct ospf6_route *route)
99 ospf6_abr_examin_brouter (ADV_ROUTER_IN_PREFIX (&route->prefix));
100 ospf6_asbr_lsentry_add (route);
101 ospf6_abr_originate_summary (route);
104 static void
105 ospf6_top_brouter_hook_remove (struct ospf6_route *route)
107 ospf6_abr_examin_brouter (ADV_ROUTER_IN_PREFIX (&route->prefix));
108 ospf6_asbr_lsentry_remove (route);
109 ospf6_abr_originate_summary (route);
112 static struct ospf6 *
113 ospf6_create (void)
115 struct ospf6 *o;
117 o = XCALLOC (MTYPE_OSPF6_TOP, sizeof (struct ospf6));
119 /* initialize */
120 quagga_gettime (QUAGGA_CLK_MONOTONIC, &o->starttime);
121 o->area_list = list_new ();
122 o->area_list->cmp = ospf6_area_cmp;
123 o->lsdb = ospf6_lsdb_create (o);
124 o->lsdb_self = ospf6_lsdb_create (o);
125 o->lsdb->hook_add = ospf6_top_lsdb_hook_add;
126 o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove;
128 o->route_table = OSPF6_ROUTE_TABLE_CREATE (GLOBAL, ROUTES);
129 o->route_table->scope = o;
130 o->route_table->hook_add = ospf6_top_route_hook_add;
131 o->route_table->hook_remove = ospf6_top_route_hook_remove;
133 o->brouter_table = OSPF6_ROUTE_TABLE_CREATE (GLOBAL, BORDER_ROUTERS);
134 o->brouter_table->scope = o;
135 o->brouter_table->hook_add = ospf6_top_brouter_hook_add;
136 o->brouter_table->hook_remove = ospf6_top_brouter_hook_remove;
138 o->external_table = OSPF6_ROUTE_TABLE_CREATE (GLOBAL, EXTERNAL_ROUTES);
139 o->external_table->scope = o;
141 o->external_id_table = route_table_init ();
143 return o;
146 static void
147 ospf6_delete (struct ospf6 *o)
149 struct listnode *node, *nnode;
150 struct ospf6_area *oa;
152 for (ALL_LIST_ELEMENTS (o->area_list, node, nnode, oa))
153 ospf6_area_delete (oa);
155 ospf6_lsdb_delete (o->lsdb);
156 ospf6_lsdb_delete (o->lsdb_self);
158 ospf6_route_table_delete (o->route_table);
159 ospf6_route_table_delete (o->brouter_table);
161 ospf6_route_table_delete (o->external_table);
162 route_table_finish (o->external_id_table);
164 XFREE (MTYPE_OSPF6_TOP, o);
167 static void
168 ospf6_enable (struct ospf6 *o)
170 struct listnode *node, *nnode;
171 struct ospf6_area *oa;
173 if (CHECK_FLAG (o->flag, OSPF6_DISABLED))
175 UNSET_FLAG (o->flag, OSPF6_DISABLED);
176 for (ALL_LIST_ELEMENTS (o->area_list, node, nnode, oa))
177 ospf6_area_enable (oa);
181 static void
182 ospf6_disable (struct ospf6 *o)
184 struct listnode *node, *nnode;
185 struct ospf6_area *oa;
187 if (! CHECK_FLAG (o->flag, OSPF6_DISABLED))
189 SET_FLAG (o->flag, OSPF6_DISABLED);
191 for (ALL_LIST_ELEMENTS (o->area_list, node, nnode, oa))
192 ospf6_area_disable (oa);
194 ospf6_lsdb_remove_all (o->lsdb);
195 ospf6_route_remove_all (o->route_table);
196 ospf6_route_remove_all (o->brouter_table);
200 static int
201 ospf6_maxage_remover (struct thread *thread)
203 struct ospf6 *o = (struct ospf6 *) THREAD_ARG (thread);
204 struct ospf6_area *oa;
205 struct ospf6_interface *oi;
206 struct ospf6_neighbor *on;
207 struct listnode *i, *j, *k;
209 o->maxage_remover = (struct thread *) NULL;
211 for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa))
213 for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi))
215 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, k, on))
217 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
218 on->state != OSPF6_NEIGHBOR_LOADING)
219 continue;
221 return 0;
226 for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa))
228 for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi))
229 OSPF6_LSDB_MAXAGE_REMOVER (oi->lsdb);
231 OSPF6_LSDB_MAXAGE_REMOVER (oa->lsdb);
233 OSPF6_LSDB_MAXAGE_REMOVER (o->lsdb);
235 return 0;
238 void
239 ospf6_maxage_remove (struct ospf6 *o)
241 if (o && ! o->maxage_remover)
242 o->maxage_remover = thread_add_event (master, ospf6_maxage_remover, o, 0);
245 /* start ospf6 */
246 DEFUN (router_ospf6,
247 router_ospf6_cmd,
248 "router ospf6",
249 ROUTER_STR
250 OSPF6_STR)
252 if (ospf6 == NULL)
253 ospf6 = ospf6_create ();
254 if (CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
255 ospf6_enable (ospf6);
257 /* set current ospf point. */
258 vty->node = OSPF6_NODE;
259 vty->index = ospf6;
261 return CMD_SUCCESS;
264 /* stop ospf6 */
265 DEFUN (no_router_ospf6,
266 no_router_ospf6_cmd,
267 "no router ospf6",
268 NO_STR
269 OSPF6_ROUTER_STR)
271 if (ospf6 == NULL || CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
272 vty_out (vty, "OSPFv3 is not running%s", VNL);
273 else
274 ospf6_disable (ospf6);
276 /* return to config node . */
277 vty->node = CONFIG_NODE;
278 vty->index = NULL;
280 return CMD_SUCCESS;
283 /* change Router_ID commands. */
284 DEFUN (ospf6_router_id,
285 ospf6_router_id_cmd,
286 "router-id A.B.C.D",
287 "Configure OSPF Router-ID\n"
288 V4NOTATION_STR)
290 int ret;
291 u_int32_t router_id;
292 struct ospf6 *o;
294 o = (struct ospf6 *) vty->index;
296 ret = inet_pton (AF_INET, argv[0], &router_id);
297 if (ret == 0)
299 vty_out (vty, "malformed OSPF Router-ID: %s%s", argv[0], VNL);
300 return CMD_SUCCESS;
303 o->router_id_static = router_id;
304 if (o->router_id == 0)
305 o->router_id = router_id;
307 return CMD_SUCCESS;
310 DEFUN (ospf6_interface_area,
311 ospf6_interface_area_cmd,
312 "interface IFNAME area A.B.C.D",
313 "Enable routing on an IPv6 interface\n"
314 IFNAME_STR
315 "Specify the OSPF6 area ID\n"
316 "OSPF6 area ID in IPv4 address notation\n"
319 struct ospf6 *o;
320 struct ospf6_area *oa;
321 struct ospf6_interface *oi;
322 struct interface *ifp;
323 u_int32_t area_id;
325 o = (struct ospf6 *) vty->index;
327 /* find/create ospf6 interface */
328 ifp = if_get_by_name (argv[0]);
329 oi = (struct ospf6_interface *) ifp->info;
330 if (oi == NULL)
331 oi = ospf6_interface_create (ifp);
332 if (oi->area)
334 vty_out (vty, "%s already attached to Area %s%s",
335 oi->interface->name, oi->area->name, VNL);
336 return CMD_SUCCESS;
339 /* parse Area-ID */
340 if (inet_pton (AF_INET, argv[1], &area_id) != 1)
342 vty_out (vty, "Invalid Area-ID: %s%s", argv[1], VNL);
343 return CMD_SUCCESS;
346 /* find/create ospf6 area */
347 oa = ospf6_area_lookup (area_id, o);
348 if (oa == NULL)
349 oa = ospf6_area_create (area_id, o);
351 /* attach interface to area */
352 listnode_add (oa->if_list, oi); /* sort ?? */
353 oi->area = oa;
355 SET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
357 /* start up */
358 thread_add_event (master, interface_up, oi, 0);
360 /* If the router is ABR, originate summary routes */
361 if (ospf6_is_router_abr (o))
362 ospf6_abr_enable_area (oa);
364 return CMD_SUCCESS;
367 DEFUN (no_ospf6_interface_area,
368 no_ospf6_interface_area_cmd,
369 "no interface IFNAME area A.B.C.D",
370 NO_STR
371 "Disable routing on an IPv6 interface\n"
372 IFNAME_STR
373 "Specify the OSPF6 area ID\n"
374 "OSPF6 area ID in IPv4 address notation\n"
377 struct ospf6 *o;
378 struct ospf6_interface *oi;
379 struct ospf6_area *oa;
380 struct interface *ifp;
381 u_int32_t area_id;
383 o = (struct ospf6 *) vty->index;
385 ifp = if_lookup_by_name (argv[0]);
386 if (ifp == NULL)
388 vty_out (vty, "No such interface %s%s", argv[0], VNL);
389 return CMD_SUCCESS;
392 oi = (struct ospf6_interface *) ifp->info;
393 if (oi == NULL)
395 vty_out (vty, "Interface %s not enabled%s", ifp->name, VNL);
396 return CMD_SUCCESS;
399 /* parse Area-ID */
400 if (inet_pton (AF_INET, argv[1], &area_id) != 1)
402 vty_out (vty, "Invalid Area-ID: %s%s", argv[1], VNL);
403 return CMD_SUCCESS;
406 /* Verify Area */
407 if (oi->area == NULL)
409 vty_out (vty, "No such Area-ID: %s%s", argv[1], VNL);
410 return CMD_SUCCESS;
413 if (oi->area->area_id != area_id)
415 vty_out (vty, "Wrong Area-ID: %s is attached to area %s%s",
416 oi->interface->name, oi->area->name, VNL);
417 return CMD_SUCCESS;
420 thread_execute (master, interface_down, oi, 0);
422 oa = oi->area;
423 listnode_delete (oi->area->if_list, oi);
424 oi->area = (struct ospf6_area *) NULL;
426 /* Withdraw inter-area routes from this area, if necessary */
427 if (oa->if_list->count == 0)
429 UNSET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
430 ospf6_abr_disable_area (oa);
433 return CMD_SUCCESS;
436 static void
437 ospf6_show (struct vty *vty, struct ospf6 *o)
439 struct listnode *n;
440 struct ospf6_area *oa;
441 char router_id[16], duration[32];
442 struct timeval now, running;
444 /* process id, router id */
445 inet_ntop (AF_INET, &o->router_id, router_id, sizeof (router_id));
446 vty_out (vty, " OSPFv3 Routing Process (0) with Router-ID %s%s",
447 router_id, VNL);
449 /* running time */
450 quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
451 timersub (&now, &o->starttime, &running);
452 timerstring (&running, duration, sizeof (duration));
453 vty_out (vty, " Running %s%s", duration, VNL);
455 /* Redistribute configuration */
456 /* XXX */
458 /* LSAs */
459 vty_out (vty, " Number of AS scoped LSAs is %u%s",
460 o->lsdb->count, VNL);
462 /* Areas */
463 vty_out (vty, " Number of areas in this router is %u%s",
464 listcount (o->area_list), VNL);
466 for (ALL_LIST_ELEMENTS_RO (o->area_list, n, oa))
467 ospf6_area_show (vty, oa);
470 /* show top level structures */
471 DEFUN (show_ipv6_ospf6,
472 show_ipv6_ospf6_cmd,
473 "show ipv6 ospf6",
474 SHOW_STR
475 IP6_STR
476 OSPF6_STR)
478 OSPF6_CMD_CHECK_RUNNING ();
480 ospf6_show (vty, ospf6);
481 return CMD_SUCCESS;
484 DEFUN (show_ipv6_ospf6_route,
485 show_ipv6_ospf6_route_cmd,
486 "show ipv6 ospf6 route",
487 SHOW_STR
488 IP6_STR
489 OSPF6_STR
490 ROUTE_STR
493 ospf6_route_table_show (vty, argc, argv, ospf6->route_table);
494 return CMD_SUCCESS;
497 ALIAS (show_ipv6_ospf6_route,
498 show_ipv6_ospf6_route_detail_cmd,
499 "show ipv6 ospf6 route (X:X::X:X|X:X::X:X/M|detail|summary)",
500 SHOW_STR
501 IP6_STR
502 OSPF6_STR
503 ROUTE_STR
504 "Specify IPv6 address\n"
505 "Specify IPv6 prefix\n"
506 "Detailed information\n"
507 "Summary of route table\n"
510 DEFUN (show_ipv6_ospf6_route_match,
511 show_ipv6_ospf6_route_match_cmd,
512 "show ipv6 ospf6 route X:X::X:X/M match",
513 SHOW_STR
514 IP6_STR
515 OSPF6_STR
516 ROUTE_STR
517 "Specify IPv6 prefix\n"
518 "Display routes which match the specified route\n"
521 const char *sargv[CMD_ARGC_MAX];
522 int i, sargc;
524 /* copy argv to sargv and then append "match" */
525 for (i = 0; i < argc; i++)
526 sargv[i] = argv[i];
527 sargc = argc;
528 sargv[sargc++] = "match";
529 sargv[sargc] = NULL;
531 ospf6_route_table_show (vty, sargc, sargv, ospf6->route_table);
532 return CMD_SUCCESS;
535 DEFUN (show_ipv6_ospf6_route_match_detail,
536 show_ipv6_ospf6_route_match_detail_cmd,
537 "show ipv6 ospf6 route X:X::X:X/M match detail",
538 SHOW_STR
539 IP6_STR
540 OSPF6_STR
541 ROUTE_STR
542 "Specify IPv6 prefix\n"
543 "Display routes which match the specified route\n"
544 "Detailed information\n"
547 const char *sargv[CMD_ARGC_MAX];
548 int i, sargc;
550 /* copy argv to sargv and then append "match" and "detail" */
551 for (i = 0; i < argc; i++)
552 sargv[i] = argv[i];
553 sargc = argc;
554 sargv[sargc++] = "match";
555 sargv[sargc++] = "detail";
556 sargv[sargc] = NULL;
558 ospf6_route_table_show (vty, sargc, sargv, ospf6->route_table);
559 return CMD_SUCCESS;
562 ALIAS (show_ipv6_ospf6_route_match,
563 show_ipv6_ospf6_route_longer_cmd,
564 "show ipv6 ospf6 route X:X::X:X/M longer",
565 SHOW_STR
566 IP6_STR
567 OSPF6_STR
568 ROUTE_STR
569 "Specify IPv6 prefix\n"
570 "Display routes longer than the specified route\n"
573 DEFUN (show_ipv6_ospf6_route_match_detail,
574 show_ipv6_ospf6_route_longer_detail_cmd,
575 "show ipv6 ospf6 route X:X::X:X/M longer detail",
576 SHOW_STR
577 IP6_STR
578 OSPF6_STR
579 ROUTE_STR
580 "Specify IPv6 prefix\n"
581 "Display routes longer than the specified route\n"
582 "Detailed information\n"
585 ALIAS (show_ipv6_ospf6_route,
586 show_ipv6_ospf6_route_type_cmd,
587 "show ipv6 ospf6 route (intra-area|inter-area|external-1|external-2)",
588 SHOW_STR
589 IP6_STR
590 OSPF6_STR
591 ROUTE_STR
592 "Dispaly Intra-Area routes\n"
593 "Dispaly Inter-Area routes\n"
594 "Dispaly Type-1 External routes\n"
595 "Dispaly Type-2 External routes\n"
598 DEFUN (show_ipv6_ospf6_route_type_detail,
599 show_ipv6_ospf6_route_type_detail_cmd,
600 "show ipv6 ospf6 route (intra-area|inter-area|external-1|external-2) detail",
601 SHOW_STR
602 IP6_STR
603 OSPF6_STR
604 ROUTE_STR
605 "Dispaly Intra-Area routes\n"
606 "Dispaly Inter-Area routes\n"
607 "Dispaly Type-1 External routes\n"
608 "Dispaly Type-2 External routes\n"
609 "Detailed information\n"
612 const char *sargv[CMD_ARGC_MAX];
613 int i, sargc;
615 /* copy argv to sargv and then append "detail" */
616 for (i = 0; i < argc; i++)
617 sargv[i] = argv[i];
618 sargc = argc;
619 sargv[sargc++] = "detail";
620 sargv[sargc] = NULL;
622 ospf6_route_table_show (vty, sargc, sargv, ospf6->route_table);
623 return CMD_SUCCESS;
626 /* OSPF configuration write function. */
627 static int
628 config_write_ospf6 (struct vty *vty)
630 char router_id[16];
631 struct listnode *j, *k;
632 struct ospf6_area *oa;
633 struct ospf6_interface *oi;
635 /* OSPFv6 configuration. */
636 if (ospf6 == NULL)
637 return CMD_SUCCESS;
638 if (CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
639 return CMD_SUCCESS;
641 inet_ntop (AF_INET, &ospf6->router_id_static, router_id, sizeof (router_id));
642 vty_out (vty, "router ospf6%s", VNL);
643 if (ospf6->router_id_static != 0)
644 vty_out (vty, " router-id %s%s", router_id, VNL);
646 ospf6_redistribute_config_write (vty);
647 ospf6_area_config_write (vty);
649 for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, j, oa))
651 for (ALL_LIST_ELEMENTS_RO (oa->if_list, k, oi))
652 vty_out (vty, " interface %s area %s%s",
653 oi->interface->name, oa->name, VNL);
655 vty_out (vty, "!%s", VNL);
656 return 0;
659 /* OSPF6 node structure. */
660 static struct cmd_node ospf6_node =
662 OSPF6_NODE,
663 "%s(config-ospf6)# ",
664 1 /* VTYSH */
667 /* Install ospf related commands. */
668 void
669 ospf6_top_init (void)
671 /* Install ospf6 top node. */
672 install_node (&ospf6_node, config_write_ospf6);
674 install_element (VIEW_NODE, &show_ipv6_ospf6_cmd);
675 install_element (ENABLE_NODE, &show_ipv6_ospf6_cmd);
676 install_element (CONFIG_NODE, &router_ospf6_cmd);
677 install_element (CONFIG_NODE, &no_router_ospf6_cmd);
679 install_element (VIEW_NODE, &show_ipv6_ospf6_route_cmd);
680 install_element (VIEW_NODE, &show_ipv6_ospf6_route_detail_cmd);
681 install_element (VIEW_NODE, &show_ipv6_ospf6_route_match_cmd);
682 install_element (VIEW_NODE, &show_ipv6_ospf6_route_match_detail_cmd);
683 install_element (VIEW_NODE, &show_ipv6_ospf6_route_longer_cmd);
684 install_element (VIEW_NODE, &show_ipv6_ospf6_route_longer_detail_cmd);
685 install_element (VIEW_NODE, &show_ipv6_ospf6_route_type_cmd);
686 install_element (VIEW_NODE, &show_ipv6_ospf6_route_type_detail_cmd);
687 install_element (ENABLE_NODE, &show_ipv6_ospf6_route_cmd);
688 install_element (ENABLE_NODE, &show_ipv6_ospf6_route_detail_cmd);
689 install_element (ENABLE_NODE, &show_ipv6_ospf6_route_match_cmd);
690 install_element (ENABLE_NODE, &show_ipv6_ospf6_route_match_detail_cmd);
691 install_element (ENABLE_NODE, &show_ipv6_ospf6_route_longer_cmd);
692 install_element (ENABLE_NODE, &show_ipv6_ospf6_route_longer_detail_cmd);
693 install_element (ENABLE_NODE, &show_ipv6_ospf6_route_type_cmd);
694 install_element (ENABLE_NODE, &show_ipv6_ospf6_route_type_detail_cmd);
696 install_default (OSPF6_NODE);
697 install_element (OSPF6_NODE, &ospf6_router_id_cmd);
698 install_element (OSPF6_NODE, &ospf6_interface_area_cmd);
699 install_element (OSPF6_NODE, &no_ospf6_interface_area_cmd);