1/* 2 * OSPF6 Area Data Structure 3 * Copyright (C) 1999-2002 Yasuhiro Ohara 4 * 5 * This file is part of GNU Zebra. 6 * 7 * GNU Zebra is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; either version 2, or (at your option) any 10 * later version. 11 * 12 * GNU Zebra is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with GNU Zebra; see the file COPYING. If not, write to the 19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 20 * Boston, MA 02111-1307, USA. 21 */ 22 23#include "ospf6d.h" 24 25static int area_index; 26#define IS_OSPF6_DUMP_AREA (ospf6_dump_is_on (area_index)) 27 28static void 29ospf6_area_foreach_interface (struct ospf6_area *o6a, void *arg, int val, 30 void (*func) (void *, int, void *)) 31{ 32 listnode node; 33 struct ospf6_interface *o6i; 34 35 for (node = listhead (o6a->if_list); node; nextnode (node)) 36 { 37 o6i = (struct ospf6_interface *) getdata (node); 38 (*func) (arg, val, o6i); 39 } 40} 41 42static void 43ospf6_area_foreach_neighbor (struct ospf6_area *o6a, void *arg, int val, 44 void (*func) (void *, int, void *)) 45{ 46 listnode node; 47 struct ospf6_interface *o6i; 48 49 for (node = listhead (o6a->if_list); node; nextnode (node)) 50 { 51 o6i = (struct ospf6_interface *) getdata (node); 52 (*o6i->foreach_nei) (o6i, arg, val, func); 53 } 54} 55 56static int 57ospf6_area_maxage_remover (struct thread *t) 58{ 59 int count; 60 struct ospf6_area *o6a = (struct ospf6_area *) THREAD_ARG (t); 61 62 o6a->maxage_remover = (struct thread *) NULL; 63 64 count = 0; 65 o6a->foreach_nei (o6a, &count, NBS_EXCHANGE, ospf6_count_state); 66 o6a->foreach_nei (o6a, &count, NBS_LOADING, ospf6_count_state); 67 if (count != 0) 68 return 0; 69 70 ospf6_lsdb_remove_maxage (o6a->lsdb); 71 return 0; 72} 73 74void 75ospf6_area_schedule_maxage_remover (void *arg, int val, void *obj) 76{ 77 struct ospf6_area *o6a = (struct ospf6_area *) obj; 78 79 if (o6a->maxage_remover != NULL) 80 return; 81 82 o6a->maxage_remover = 83 thread_add_event (master, ospf6_area_maxage_remover, o6a, 0); 84} 85 86int 87ospf6_area_is_stub (struct ospf6_area *o6a) 88{ 89 if (OSPF6_OPT_ISSET (o6a->options, OSPF6_OPT_E)) 90 return 0; 91 return 1; 92} 93 94int 95ospf6_area_is_transit (struct ospf6_area *o6a) 96{ 97 return 0; 98} 99 100 101 102void 103ospf6_area_intra_topo_add (struct ospf6_route_req *topo_entry) 104{ 105 if (topo_entry->route.type == OSPF6_DEST_TYPE_ROUTER) 106 { 107 if (CHECK_FLAG (topo_entry->path.router_bits, OSPF6_ROUTER_LSA_BIT_B)) 108 ospf6_abr_abr_entry_add (topo_entry); 109 } 110 CALL_ADD_HOOK (&intra_topology_hook, topo_entry); 111} 112 113void 114ospf6_area_intra_topo_remove (struct ospf6_route_req *topo_entry) 115{ 116 if (topo_entry->route.type == OSPF6_DEST_TYPE_ROUTER) 117 { 118 if (CHECK_FLAG (topo_entry->path.router_bits, OSPF6_ROUTER_LSA_BIT_E)) 119 ospf6_abr_abr_entry_add (topo_entry); 120 } 121 CALL_REMOVE_HOOK (&intra_topology_hook, topo_entry); 122} 123 124void 125ospf6_area_route_add (void *data) 126{ 127 struct ospf6_route_req *route = data; 128 struct in6_addr local; 129 130 inet_pton (AF_INET6, "::1", &local); 131 if (! memcmp (&route->nexthop.address, &local, sizeof (struct in6_addr))) 132 { 133 if (IS_OSPF6_DUMP_AREA) 134 zlog_info ("AREA: Self-originated route add, ignore"); 135 return; 136 } 137 138 ospf6_route_add (route, ospf6->route_table); 139} 140 141void 142ospf6_area_route_remove (void *data) 143{ 144 struct ospf6_route_req *route = data; 145 struct in6_addr local; 146 147 inet_pton (AF_INET6, "::1", &local); 148 if (! memcmp (&route->nexthop.address, &local, sizeof (struct in6_addr))) 149 { 150 if (IS_OSPF6_DUMP_AREA) 151 zlog_info ("AREA: Self-originated route remove, ignore"); 152 return; 153 } 154 155 ospf6_route_remove (route, ospf6->route_table); 156} 157 158/* Make new area structure */ 159struct ospf6_area * 160ospf6_area_create (u_int32_t area_id) 161{ 162 struct ospf6_area *o6a; 163 char namebuf[64]; 164 165 /* allocate memory */ 166 o6a = XCALLOC (MTYPE_OSPF6_AREA, sizeof (struct ospf6_area)); 167 168 /* initialize */ 169 inet_ntop (AF_INET, &area_id, o6a->str, sizeof (o6a->str)); 170 o6a->area_id = area_id; 171 o6a->if_list = list_new (); 172 173 o6a->lsdb = ospf6_lsdb_create (); 174 o6a->spf_tree = ospf6_spftree_create (); 175 176 snprintf (namebuf, sizeof (namebuf), "Area %s's route table", o6a->str); 177 o6a->route_table = ospf6_route_table_create (namebuf); 178 o6a->route_table->hook_add = ospf6_area_route_add; 179 o6a->route_table->hook_change = ospf6_area_route_add; 180 o6a->route_table->hook_remove = ospf6_area_route_remove; 181 182 snprintf (namebuf, sizeof (namebuf), "Area %s's topology table", o6a->str); 183 o6a->table_topology = ospf6_route_table_create (namebuf); 184 o6a->table_topology->hook_add = ospf6_intra_topology_add; 185 o6a->table_topology->hook_change = ospf6_intra_topology_add; 186 o6a->table_topology->hook_remove = ospf6_intra_topology_remove; 187 188 /* xxx, set options */ 189 OSPF6_OPT_SET (o6a->options, OSPF6_OPT_V6); 190 OSPF6_OPT_SET (o6a->options, OSPF6_OPT_E); 191 OSPF6_OPT_SET (o6a->options, OSPF6_OPT_R); 192 193 o6a->foreach_if = ospf6_area_foreach_interface; 194 o6a->foreach_nei = ospf6_area_foreach_neighbor; 195 196 return o6a; 197} 198 199void 200ospf6_area_bind_top (struct ospf6_area *o6a, struct ospf6 *o6) 201{ 202 o6a->ospf6 = o6; 203 CALL_CHANGE_HOOK (&area_hook, o6a); 204 return; 205} 206 207void 208ospf6_area_delete (struct ospf6_area *o6a) 209{ 210 listnode n; 211 struct ospf6_interface *o6i; 212 213 CALL_REMOVE_HOOK (&area_hook, o6a); 214 215 /* ospf6 interface list */ 216 for (n = listhead (o6a->if_list); n; nextnode (n)) 217 { 218 o6i = (struct ospf6_interface *) getdata (n); 219 /* ospf6_interface_delete (o6i); */ 220 } 221 list_delete (o6a->if_list); 222 223 /* terminate LSDB */ 224 ospf6_lsdb_remove_all (o6a->lsdb); 225 226 /* spf tree terminate */ 227 /* xxx */ 228 229 /* threads */ 230 if (o6a->spf_calc) 231 thread_cancel (o6a->spf_calc); 232 o6a->spf_calc = (struct thread *) NULL; 233 if (o6a->route_calc) 234 thread_cancel (o6a->route_calc); 235 o6a->route_calc = (struct thread *) NULL; 236 237 /* new */ 238 ospf6_route_table_delete (o6a->route_table); 239 240 ospf6_spftree_delete (o6a->spf_tree); 241 ospf6_route_table_delete (o6a->table_topology); 242 243 /* free area */ 244 XFREE (MTYPE_OSPF6_AREA, o6a); 245} 246 247struct ospf6_area * 248ospf6_area_lookup (u_int32_t area_id, struct ospf6 *o6) 249{ 250 struct ospf6_area *o6a; 251 listnode n; 252 253 for (n = listhead (o6->area_list); n; nextnode (n)) 254 { 255 o6a = (struct ospf6_area *) getdata (n); 256 if (o6a->area_id == area_id) 257 return o6a; 258 } 259 260 return (struct ospf6_area *) NULL; 261} 262 263void 264ospf6_area_show (struct vty *vty, struct ospf6_area *o6a) 265{ 266 listnode i; 267 struct ospf6_interface *o6i; 268 269 vty_out (vty, " Area %s%s", o6a->str, VTY_NEWLINE); 270 vty_out (vty, " Number of Area scoped LSAs is %u%s", 271 o6a->lsdb->count, VTY_NEWLINE); 272 273 ospf6_spf_statistics_show (vty, o6a->spf_tree); 274 275 vty_out (vty, " Interface attached to this area:"); 276 for (i = listhead (o6a->if_list); i; nextnode (i)) 277 { 278 o6i = (struct ospf6_interface *) getdata (i); 279 vty_out (vty, " %s", o6i->interface->name); 280 } 281 vty_out (vty, "%s", VTY_NEWLINE); 282 283 for (i = listhead (o6a->if_list); i; nextnode (i)) 284 { 285 o6i = (struct ospf6_interface *) getdata (i); 286 if (listcount (o6i->neighbor_list) != 0) 287 ospf6_interface_statistics_show (vty, o6i); 288 } 289} 290 291void 292ospf6_area_statistics_show (struct vty *vty, struct ospf6_area *o6a) 293{ 294#if 0 295 listnode node; 296 struct ospf6_interface *o6i; 297 298 vty_out (vty, " Statistics of Area %s%s", o6a->str, VTY_NEWLINE); 299#endif 300} 301 302DEFUN (show_ipv6_ospf6_area_route, 303 show_ipv6_ospf6_area_route_cmd, 304 "show ipv6 ospf6 area A.B.C.D route", 305 SHOW_STR 306 IP6_STR 307 OSPF6_STR 308 OSPF6_AREA_STR 309 OSPF6_AREA_ID_STR 310 ROUTE_STR 311 ) 312{ 313 struct ospf6_area *o6a; 314 u_int32_t area_id; 315 316 OSPF6_CMD_CHECK_RUNNING (); 317 318 inet_pton (AF_INET, argv[0], &area_id); 319 o6a = ospf6_area_lookup (area_id, ospf6); 320 321 if (! o6a) 322 return CMD_SUCCESS; 323 324 argc -= 1; 325 argv += 1; 326 327 return ospf6_route_table_show (vty, argc, argv, o6a->route_table); 328} 329 330ALIAS (show_ipv6_ospf6_area_route, 331 show_ipv6_ospf6_area_route_prefix_cmd, 332 "show ipv6 ospf6 area A.B.C.D route (X::X|detail)", 333 SHOW_STR 334 IP6_STR 335 OSPF6_STR 336 OSPF6_AREA_STR 337 OSPF6_AREA_ID_STR 338 ROUTE_STR 339 "Specify IPv6 address\n" 340 "Detailed information\n" 341 ) 342 343void 344ospf6_area_init () 345{ 346 area_index = ospf6_dump_install ("area", "Area information\n"); 347 348 install_element (VIEW_NODE, &show_ipv6_ospf6_area_route_cmd); 349 install_element (VIEW_NODE, &show_ipv6_ospf6_area_route_prefix_cmd); 350 install_element (ENABLE_NODE, &show_ipv6_ospf6_area_route_cmd); 351 install_element (ENABLE_NODE, &show_ipv6_ospf6_area_route_prefix_cmd); 352} 353 354 355