]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_top.c
2005-04-07 Paul Jakma <paul.jakma@sun.com>
[mirror_frr.git] / ospf6d / ospf6_top.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 "vty.h"
27 #include "linklist.h"
28 #include "prefix.h"
29 #include "table.h"
30 #include "thread.h"
31 #include "command.h"
32
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"
39
40 #include "ospf6_top.h"
41 #include "ospf6_area.h"
42 #include "ospf6_interface.h"
43 #include "ospf6_neighbor.h"
44
45 #include "ospf6_flood.h"
46 #include "ospf6_asbr.h"
47 #include "ospf6_abr.h"
48 #include "ospf6_intra.h"
49 #include "ospf6d.h"
50
51 /* global ospf6d variable */
52 struct ospf6 *ospf6;
53
54 void
55 ospf6_top_lsdb_hook_add (struct ospf6_lsa *lsa)
56 {
57 switch (ntohs (lsa->header->type))
58 {
59 case OSPF6_LSTYPE_AS_EXTERNAL:
60 ospf6_asbr_lsa_add (lsa);
61 break;
62
63 default:
64 break;
65 }
66 }
67
68 void
69 ospf6_top_lsdb_hook_remove (struct ospf6_lsa *lsa)
70 {
71 switch (ntohs (lsa->header->type))
72 {
73 case OSPF6_LSTYPE_AS_EXTERNAL:
74 ospf6_asbr_lsa_remove (lsa);
75 break;
76
77 default:
78 break;
79 }
80 }
81
82 void
83 ospf6_top_route_hook_add (struct ospf6_route *route)
84 {
85 ospf6_abr_originate_summary (route);
86 ospf6_zebra_route_update_add (route);
87 }
88
89 void
90 ospf6_top_route_hook_remove (struct ospf6_route *route)
91 {
92 ospf6_abr_originate_summary (route);
93 ospf6_zebra_route_update_remove (route);
94 }
95
96 void
97 ospf6_top_brouter_hook_add (struct ospf6_route *route)
98 {
99 ospf6_abr_examin_brouter (ADV_ROUTER_IN_PREFIX (&route->prefix));
100 ospf6_asbr_lsentry_add (route);
101 ospf6_abr_originate_summary (route);
102 }
103
104 void
105 ospf6_top_brouter_hook_remove (struct ospf6_route *route)
106 {
107 ospf6_abr_examin_brouter (ADV_ROUTER_IN_PREFIX (&route->prefix));
108 ospf6_asbr_lsentry_remove (route);
109 ospf6_abr_originate_summary (route);
110 }
111
112 struct ospf6 *
113 ospf6_create ()
114 {
115 struct ospf6 *o;
116
117 o = XMALLOC (MTYPE_OSPF6_TOP, sizeof (struct ospf6));
118 memset (o, 0, sizeof (struct ospf6));
119
120 /* initialize */
121 gettimeofday (&o->starttime, (struct timezone *) NULL);
122 o->area_list = list_new ();
123 o->area_list->cmp = ospf6_area_cmp;
124 o->lsdb = ospf6_lsdb_create (o);
125 o->lsdb_self = ospf6_lsdb_create (o);
126 o->lsdb->hook_add = ospf6_top_lsdb_hook_add;
127 o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove;
128
129 o->route_table = ospf6_route_table_create ();
130 o->route_table->hook_add = ospf6_top_route_hook_add;
131 o->route_table->hook_remove = ospf6_top_route_hook_remove;
132
133 o->brouter_table = ospf6_route_table_create ();
134 o->brouter_table->hook_add = ospf6_top_brouter_hook_add;
135 o->brouter_table->hook_remove = ospf6_top_brouter_hook_remove;
136
137 o->external_table = ospf6_route_table_create ();
138 o->external_id_table = route_table_init ();
139
140 return o;
141 }
142
143 void
144 ospf6_delete (struct ospf6 *o)
145 {
146 struct listnode *node, *nnode;
147 struct ospf6_area *oa;
148
149 for (ALL_LIST_ELEMENTS (o->area_list, node, nnode, oa))
150 ospf6_area_delete (oa);
151
152 ospf6_lsdb_delete (o->lsdb);
153 ospf6_lsdb_delete (o->lsdb_self);
154
155 ospf6_route_table_delete (o->route_table);
156 ospf6_route_table_delete (o->brouter_table);
157
158 ospf6_route_table_delete (o->external_table);
159 route_table_finish (o->external_id_table);
160
161 XFREE (MTYPE_OSPF6_TOP, o);
162 }
163
164 void
165 ospf6_enable (struct ospf6 *o)
166 {
167 struct listnode *node, *nnode;
168 struct ospf6_area *oa;
169
170 if (CHECK_FLAG (o->flag, OSPF6_DISABLED))
171 {
172 UNSET_FLAG (o->flag, OSPF6_DISABLED);
173 for (ALL_LIST_ELEMENTS (o->area_list, node, nnode, oa))
174 ospf6_area_enable (oa);
175 }
176 }
177
178 void
179 ospf6_disable (struct ospf6 *o)
180 {
181 struct listnode *node, *nnode;
182 struct ospf6_area *oa;
183
184 if (! CHECK_FLAG (o->flag, OSPF6_DISABLED))
185 {
186 SET_FLAG (o->flag, OSPF6_DISABLED);
187
188 for (ALL_LIST_ELEMENTS (o->area_list, node, nnode, oa))
189 ospf6_area_disable (oa);
190
191 ospf6_lsdb_remove_all (o->lsdb);
192 ospf6_route_remove_all (o->route_table);
193 ospf6_route_remove_all (o->brouter_table);
194 }
195 }
196
197 int
198 ospf6_maxage_remover (struct thread *thread)
199 {
200 struct ospf6 *o = (struct ospf6 *) THREAD_ARG (thread);
201 struct ospf6_area *oa;
202 struct ospf6_interface *oi;
203 struct ospf6_neighbor *on;
204 struct listnode *i, *j, *k;
205
206 o->maxage_remover = (struct thread *) NULL;
207
208 for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa))
209 {
210 for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi))
211 {
212 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, k, on))
213 {
214 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
215 on->state != OSPF6_NEIGHBOR_LOADING)
216 continue;
217
218 return 0;
219 }
220 }
221 }
222
223 for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa))
224 {
225 for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi))
226 OSPF6_LSDB_MAXAGE_REMOVER (oi->lsdb);
227
228 OSPF6_LSDB_MAXAGE_REMOVER (oa->lsdb);
229 }
230 OSPF6_LSDB_MAXAGE_REMOVER (o->lsdb);
231
232 return 0;
233 }
234
235 void
236 ospf6_maxage_remove (struct ospf6 *o)
237 {
238 if (o && ! o->maxage_remover)
239 o->maxage_remover = thread_add_event (master, ospf6_maxage_remover, o, 0);
240 }
241
242 /* start ospf6 */
243 DEFUN (router_ospf6,
244 router_ospf6_cmd,
245 "router ospf6",
246 ROUTER_STR
247 OSPF6_STR)
248 {
249 if (ospf6 == NULL)
250 ospf6 = ospf6_create ();
251 if (CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
252 ospf6_enable (ospf6);
253
254 /* set current ospf point. */
255 vty->node = OSPF6_NODE;
256 vty->index = ospf6;
257
258 return CMD_SUCCESS;
259 }
260
261 /* stop ospf6 */
262 DEFUN (no_router_ospf6,
263 no_router_ospf6_cmd,
264 "no router ospf6",
265 NO_STR
266 OSPF6_ROUTER_STR)
267 {
268 if (ospf6 == NULL || CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
269 vty_out (vty, "OSPFv3 is not running%s", VNL);
270 else
271 ospf6_disable (ospf6);
272
273 /* return to config node . */
274 vty->node = CONFIG_NODE;
275 vty->index = NULL;
276
277 return CMD_SUCCESS;
278 }
279
280 /* change Router_ID commands. */
281 DEFUN (ospf6_router_id,
282 ospf6_router_id_cmd,
283 "router-id A.B.C.D",
284 "Configure OSPF Router-ID\n"
285 V4NOTATION_STR)
286 {
287 int ret;
288 u_int32_t router_id;
289 struct ospf6 *o;
290
291 o = (struct ospf6 *) vty->index;
292
293 ret = inet_pton (AF_INET, argv[0], &router_id);
294 if (ret == 0)
295 {
296 vty_out (vty, "malformed OSPF Router-ID: %s%s", argv[0], VNL);
297 return CMD_SUCCESS;
298 }
299
300 o->router_id_static = router_id;
301 if (o->router_id == 0)
302 o->router_id = router_id;
303
304 return CMD_SUCCESS;
305 }
306
307 DEFUN (ospf6_interface_area,
308 ospf6_interface_area_cmd,
309 "interface IFNAME area A.B.C.D",
310 "Enable routing on an IPv6 interface\n"
311 IFNAME_STR
312 "Specify the OSPF6 area ID\n"
313 "OSPF6 area ID in IPv4 address notation\n"
314 )
315 {
316 struct ospf6 *o;
317 struct ospf6_area *oa;
318 struct ospf6_interface *oi;
319 struct interface *ifp;
320 u_int32_t area_id;
321
322 o = (struct ospf6 *) vty->index;
323
324 /* find/create ospf6 interface */
325 ifp = if_get_by_name (argv[0]);
326 oi = (struct ospf6_interface *) ifp->info;
327 if (oi == NULL)
328 oi = ospf6_interface_create (ifp);
329 if (oi->area)
330 {
331 vty_out (vty, "%s already attached to Area %s%s",
332 oi->interface->name, oi->area->name, VNL);
333 return CMD_SUCCESS;
334 }
335
336 /* parse Area-ID */
337 if (inet_pton (AF_INET, argv[1], &area_id) != 1)
338 {
339 vty_out (vty, "Invalid Area-ID: %s%s", argv[1], VNL);
340 return CMD_SUCCESS;
341 }
342
343 /* find/create ospf6 area */
344 oa = ospf6_area_lookup (area_id, o);
345 if (oa == NULL)
346 oa = ospf6_area_create (area_id, o);
347
348 /* attach interface to area */
349 listnode_add (oa->if_list, oi); /* sort ?? */
350 oi->area = oa;
351
352 SET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
353
354 /* start up */
355 thread_add_event (master, interface_up, oi, 0);
356
357 /* If the router is ABR, originate summary routes */
358 if (ospf6_is_router_abr (o))
359 ospf6_abr_enable_area (oa);
360
361 return CMD_SUCCESS;
362 }
363
364 DEFUN (no_ospf6_interface_area,
365 no_ospf6_interface_area_cmd,
366 "no interface IFNAME area A.B.C.D",
367 NO_STR
368 "Disable routing on an IPv6 interface\n"
369 IFNAME_STR
370 "Specify the OSPF6 area ID\n"
371 "OSPF6 area ID in IPv4 address notation\n"
372 )
373 {
374 struct ospf6 *o;
375 struct ospf6_interface *oi;
376 struct ospf6_area *oa;
377 struct interface *ifp;
378 u_int32_t area_id;
379
380 o = (struct ospf6 *) vty->index;
381
382 ifp = if_lookup_by_name (argv[0]);
383 if (ifp == NULL)
384 {
385 vty_out (vty, "No such interface %s%s", argv[0], VNL);
386 return CMD_SUCCESS;
387 }
388
389 oi = (struct ospf6_interface *) ifp->info;
390 if (oi == NULL)
391 {
392 vty_out (vty, "Interface %s not enabled%s", ifp->name, VNL);
393 return CMD_SUCCESS;
394 }
395
396 /* parse Area-ID */
397 if (inet_pton (AF_INET, argv[1], &area_id) != 1)
398 {
399 vty_out (vty, "Invalid Area-ID: %s%s", argv[1], VNL);
400 return CMD_SUCCESS;
401 }
402
403 if (oi->area->area_id != area_id)
404 {
405 vty_out (vty, "Wrong Area-ID: %s is attached to area %s%s",
406 oi->interface->name, oi->area->name, VNL);
407 return CMD_SUCCESS;
408 }
409
410 thread_execute (master, interface_down, oi, 0);
411
412 oa = oi->area;
413 listnode_delete (oi->area->if_list, oi);
414 oi->area = (struct ospf6_area *) NULL;
415
416 /* Withdraw inter-area routes from this area, if necessary */
417 if (oa->if_list->count == 0)
418 {
419 UNSET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
420 ospf6_abr_disable_area (oa);
421 }
422
423 return CMD_SUCCESS;
424 }
425
426 void
427 ospf6_show (struct vty *vty, struct ospf6 *o)
428 {
429 struct listnode *n;
430 struct ospf6_area *oa;
431 char router_id[16], duration[32];
432 struct timeval now, running;
433
434 /* process id, router id */
435 inet_ntop (AF_INET, &o->router_id, router_id, sizeof (router_id));
436 vty_out (vty, " OSPFv3 Routing Process (0) with Router-ID %s%s",
437 router_id, VNL);
438
439 /* running time */
440 gettimeofday (&now, (struct timezone *)NULL);
441 timersub (&now, &o->starttime, &running);
442 timerstring (&running, duration, sizeof (duration));
443 vty_out (vty, " Running %s%s", duration, VNL);
444
445 /* Redistribute configuration */
446 /* XXX */
447
448 /* LSAs */
449 vty_out (vty, " Number of AS scoped LSAs is %u%s",
450 o->lsdb->count, VNL);
451
452 /* Areas */
453 vty_out (vty, " Number of areas in this router is %u%s",
454 listcount (o->area_list), VNL);
455
456 for (ALL_LIST_ELEMENTS_RO (o->area_list, n, oa))
457 ospf6_area_show (vty, oa);
458 }
459
460 /* show top level structures */
461 DEFUN (show_ipv6_ospf6,
462 show_ipv6_ospf6_cmd,
463 "show ipv6 ospf6",
464 SHOW_STR
465 IP6_STR
466 OSPF6_STR)
467 {
468 OSPF6_CMD_CHECK_RUNNING ();
469
470 ospf6_show (vty, ospf6);
471 return CMD_SUCCESS;
472 }
473
474 DEFUN (show_ipv6_ospf6_route,
475 show_ipv6_ospf6_route_cmd,
476 "show ipv6 ospf6 route",
477 SHOW_STR
478 IP6_STR
479 OSPF6_STR
480 ROUTE_STR
481 )
482 {
483 ospf6_route_table_show (vty, argc, argv, ospf6->route_table);
484 return CMD_SUCCESS;
485 }
486
487 ALIAS (show_ipv6_ospf6_route,
488 show_ipv6_ospf6_route_detail_cmd,
489 "show ipv6 ospf6 route (X:X::X:X|X:X::X:X/M|detail|summary)",
490 SHOW_STR
491 IP6_STR
492 OSPF6_STR
493 ROUTE_STR
494 "Specify IPv6 address\n"
495 "Specify IPv6 prefix\n"
496 "Detailed information\n"
497 "Summary of route table\n"
498 );
499
500 DEFUN (show_ipv6_ospf6_route_match,
501 show_ipv6_ospf6_route_match_cmd,
502 "show ipv6 ospf6 route X:X::X:X/M match",
503 SHOW_STR
504 IP6_STR
505 OSPF6_STR
506 ROUTE_STR
507 "Specify IPv6 prefix\n"
508 "Display routes which match the specified route\n"
509 )
510 {
511 const char *sargv[CMD_ARGC_MAX];
512 int i, sargc;
513
514 /* copy argv to sargv and then append "match" */
515 for (i = 0; i < argc; i++)
516 sargv[i] = argv[i];
517 sargc = argc;
518 sargv[sargc++] = "match";
519 sargv[sargc] = NULL;
520
521 ospf6_route_table_show (vty, sargc, sargv, ospf6->route_table);
522 return CMD_SUCCESS;
523 }
524
525 DEFUN (show_ipv6_ospf6_route_match_detail,
526 show_ipv6_ospf6_route_match_detail_cmd,
527 "show ipv6 ospf6 route X:X::X:X/M match detail",
528 SHOW_STR
529 IP6_STR
530 OSPF6_STR
531 ROUTE_STR
532 "Specify IPv6 prefix\n"
533 "Display routes which match the specified route\n"
534 "Detailed information\n"
535 )
536 {
537 const char *sargv[CMD_ARGC_MAX];
538 int i, sargc;
539
540 /* copy argv to sargv and then append "match" and "detail" */
541 for (i = 0; i < argc; i++)
542 sargv[i] = argv[i];
543 sargc = argc;
544 sargv[sargc++] = "match";
545 sargv[sargc++] = "detail";
546 sargv[sargc] = NULL;
547
548 ospf6_route_table_show (vty, sargc, sargv, ospf6->route_table);
549 return CMD_SUCCESS;
550 }
551
552 ALIAS (show_ipv6_ospf6_route,
553 show_ipv6_ospf6_route_type_cmd,
554 "show ipv6 ospf6 route (intra-area|inter-area|external-1|external-2)",
555 SHOW_STR
556 IP6_STR
557 OSPF6_STR
558 ROUTE_STR
559 "Dispaly Intra-Area routes\n"
560 "Dispaly Inter-Area routes\n"
561 "Dispaly Type-1 External routes\n"
562 "Dispaly Type-2 External routes\n"
563 );
564
565 DEFUN (show_ipv6_ospf6_route_type_detail,
566 show_ipv6_ospf6_route_type_detail_cmd,
567 "show ipv6 ospf6 route (intra-area|inter-area|external-1|external-2) detail",
568 SHOW_STR
569 IP6_STR
570 OSPF6_STR
571 ROUTE_STR
572 "Dispaly Intra-Area routes\n"
573 "Dispaly Inter-Area routes\n"
574 "Dispaly Type-1 External routes\n"
575 "Dispaly Type-2 External routes\n"
576 "Detailed information\n"
577 )
578 {
579 const char *sargv[CMD_ARGC_MAX];
580 int i, sargc;
581
582 /* copy argv to sargv and then append "detail" */
583 for (i = 0; i < argc; i++)
584 sargv[i] = argv[i];
585 sargc = argc;
586 sargv[sargc++] = "detail";
587 sargv[sargc] = NULL;
588
589 ospf6_route_table_show (vty, sargc, sargv, ospf6->route_table);
590 return CMD_SUCCESS;
591 }
592
593 /* OSPF configuration write function. */
594 int
595 config_write_ospf6 (struct vty *vty)
596 {
597 char router_id[16];
598 struct listnode *j, *k;
599 struct ospf6_area *oa;
600 struct ospf6_interface *oi;
601
602 /* OSPFv6 configuration. */
603 if (ospf6 == NULL)
604 return CMD_SUCCESS;
605 if (CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
606 return CMD_SUCCESS;
607
608 inet_ntop (AF_INET, &ospf6->router_id_static, router_id, sizeof (router_id));
609 vty_out (vty, "router ospf6%s", VNL);
610 if (ospf6->router_id_static != 0)
611 vty_out (vty, " router-id %s%s", router_id, VNL);
612
613 ospf6_redistribute_config_write (vty);
614 ospf6_area_config_write (vty);
615
616 for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, j, oa))
617 {
618 for (ALL_LIST_ELEMENTS_RO (oa->if_list, k, oi))
619 vty_out (vty, " interface %s area %s%s",
620 oi->interface->name, oa->name, VNL);
621 }
622 vty_out (vty, "!%s", VNL);
623 return 0;
624 }
625
626 /* OSPF6 node structure. */
627 struct cmd_node ospf6_node =
628 {
629 OSPF6_NODE,
630 "%s(config-ospf6)# ",
631 1 /* VTYSH */
632 };
633
634 /* Install ospf related commands. */
635 void
636 ospf6_top_init ()
637 {
638 /* Install ospf6 top node. */
639 install_node (&ospf6_node, config_write_ospf6);
640
641 install_element (VIEW_NODE, &show_ipv6_ospf6_cmd);
642 install_element (ENABLE_NODE, &show_ipv6_ospf6_cmd);
643 install_element (CONFIG_NODE, &router_ospf6_cmd);
644
645 install_element (VIEW_NODE, &show_ipv6_ospf6_route_cmd);
646 install_element (VIEW_NODE, &show_ipv6_ospf6_route_detail_cmd);
647 install_element (VIEW_NODE, &show_ipv6_ospf6_route_match_cmd);
648 install_element (VIEW_NODE, &show_ipv6_ospf6_route_match_detail_cmd);
649 install_element (VIEW_NODE, &show_ipv6_ospf6_route_type_cmd);
650 install_element (VIEW_NODE, &show_ipv6_ospf6_route_type_detail_cmd);
651 install_element (ENABLE_NODE, &show_ipv6_ospf6_route_cmd);
652 install_element (ENABLE_NODE, &show_ipv6_ospf6_route_detail_cmd);
653 install_element (ENABLE_NODE, &show_ipv6_ospf6_route_match_cmd);
654 install_element (ENABLE_NODE, &show_ipv6_ospf6_route_match_detail_cmd);
655 install_element (ENABLE_NODE, &show_ipv6_ospf6_route_type_cmd);
656 install_element (ENABLE_NODE, &show_ipv6_ospf6_route_type_detail_cmd);
657
658 install_default (OSPF6_NODE);
659 install_element (OSPF6_NODE, &ospf6_router_id_cmd);
660 install_element (OSPF6_NODE, &ospf6_interface_area_cmd);
661 install_element (OSPF6_NODE, &no_ospf6_interface_area_cmd);
662 install_element (OSPF6_NODE, &no_router_ospf6_cmd);
663 }
664
665