Line data Source code
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 along
17 : * with this program; see the file COPYING; if not, write to the Free Software
18 : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 : */
20 :
21 : #include <zebra.h>
22 :
23 : #include "log.h"
24 : #include "memory.h"
25 : #include "linklist.h"
26 : #include "thread.h"
27 : #include "vty.h"
28 : #include "command.h"
29 : #include "if.h"
30 : #include "prefix.h"
31 : #include "table.h"
32 : #include "plist.h"
33 : #include "filter.h"
34 :
35 : #include "ospf6_proto.h"
36 : #include "ospf6_lsa.h"
37 : #include "ospf6_lsdb.h"
38 : #include "ospf6_route.h"
39 : #include "ospf6_spf.h"
40 : #include "ospf6_top.h"
41 : #include "ospf6_area.h"
42 : #include "ospf6_message.h"
43 : #include "ospf6_neighbor.h"
44 : #include "ospf6_interface.h"
45 : #include "ospf6_intra.h"
46 : #include "ospf6_abr.h"
47 : #include "ospf6_asbr.h"
48 : #include "ospf6_zebra.h"
49 : #include "ospf6d.h"
50 : #include "lib/json.h"
51 : #include "ospf6_nssa.h"
52 : #include "ospf6_vlink.h"
53 : #include "ospf6d/ospf6_area_clippy.c"
54 :
55 48 : DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AREA, "OSPF6 area");
56 48 : DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PLISTNAME, "Prefix list name");
57 :
58 29 : int str2area_id(const char *str, uint32_t *area_id, int *area_id_fmt)
59 : {
60 29 : char *ep;
61 :
62 29 : *area_id = htonl(strtoul(str, &ep, 10));
63 29 : if (*ep && inet_pton(AF_INET, str, area_id) != 1)
64 : return -1;
65 :
66 58 : *area_id_fmt =
67 29 : !*ep ? OSPF6_AREA_FMT_DECIMAL : OSPF6_AREA_FMT_DOTTEDQUAD;
68 :
69 29 : return 0;
70 : }
71 :
72 0 : void area_id2str(char *buf, int len, uint32_t area_id, int area_id_fmt)
73 : {
74 0 : if (area_id_fmt == OSPF6_AREA_FMT_DECIMAL)
75 0 : snprintf(buf, len, "%u", ntohl(area_id));
76 : else
77 0 : inet_ntop(AF_INET, &area_id, buf, len);
78 0 : }
79 :
80 3 : int ospf6_area_cmp(void *va, void *vb)
81 : {
82 3 : struct ospf6_area *oa = (struct ospf6_area *)va;
83 3 : struct ospf6_area *ob = (struct ospf6_area *)vb;
84 3 : return (ntohl(oa->area_id) < ntohl(ob->area_id) ? -1 : 1);
85 : }
86 :
87 : /* schedule routing table recalculation */
88 307 : static void ospf6_area_lsdb_hook_add(struct ospf6_lsa *lsa)
89 : {
90 307 : switch (ntohs(lsa->header->type)) {
91 :
92 204 : case OSPF6_LSTYPE_ROUTER:
93 : case OSPF6_LSTYPE_NETWORK:
94 204 : if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type)) {
95 0 : zlog_debug("%s Examin LSA %s", __func__, lsa->name);
96 0 : zlog_debug(" Schedule SPF Calculation for %s",
97 : OSPF6_AREA(lsa->lsdb->data)->name);
98 : }
99 204 : ospf6_spf_schedule(
100 204 : OSPF6_PROCESS(OSPF6_AREA(lsa->lsdb->data)->ospf6),
101 : ospf6_lsadd_to_spf_reason(lsa));
102 204 : break;
103 :
104 77 : case OSPF6_LSTYPE_INTRA_PREFIX:
105 77 : ospf6_intra_prefix_lsa_add(lsa);
106 77 : break;
107 :
108 26 : case OSPF6_LSTYPE_INTER_PREFIX:
109 : case OSPF6_LSTYPE_INTER_ROUTER:
110 26 : ospf6_abr_examin_summary(lsa,
111 26 : (struct ospf6_area *)lsa->lsdb->data);
112 26 : break;
113 :
114 0 : case OSPF6_LSTYPE_TYPE_7:
115 0 : ospf6_asbr_lsa_add(lsa);
116 0 : break;
117 :
118 : default:
119 : break;
120 : }
121 307 : }
122 :
123 388 : static void ospf6_area_lsdb_hook_remove(struct ospf6_lsa *lsa)
124 : {
125 388 : switch (ntohs(lsa->header->type)) {
126 242 : case OSPF6_LSTYPE_ROUTER:
127 : case OSPF6_LSTYPE_NETWORK:
128 242 : if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type)) {
129 0 : zlog_debug("LSA disappearing: %s", lsa->name);
130 0 : zlog_debug("Schedule SPF Calculation for %s",
131 : OSPF6_AREA(lsa->lsdb->data)->name);
132 : }
133 242 : ospf6_spf_schedule(
134 242 : OSPF6_PROCESS(OSPF6_AREA(lsa->lsdb->data)->ospf6),
135 : ospf6_lsremove_to_spf_reason(lsa));
136 242 : break;
137 :
138 98 : case OSPF6_LSTYPE_INTRA_PREFIX:
139 98 : ospf6_intra_prefix_lsa_remove(lsa);
140 98 : break;
141 :
142 48 : case OSPF6_LSTYPE_INTER_PREFIX:
143 : case OSPF6_LSTYPE_INTER_ROUTER:
144 48 : ospf6_abr_examin_summary(lsa,
145 48 : (struct ospf6_area *)lsa->lsdb->data);
146 48 : break;
147 0 : case OSPF6_LSTYPE_TYPE_7:
148 0 : ospf6_asbr_lsa_remove(lsa, NULL);
149 0 : break;
150 : default:
151 : break;
152 : }
153 388 : }
154 :
155 225 : static void ospf6_area_route_hook_add(struct ospf6_route *route)
156 : {
157 225 : struct ospf6_area *oa = route->table->scope;
158 225 : struct ospf6 *ospf6 = oa->ospf6;
159 225 : struct ospf6_route *copy;
160 :
161 225 : copy = ospf6_route_copy(route);
162 225 : ospf6_route_add(copy, ospf6->route_table);
163 225 : }
164 :
165 54 : static void ospf6_area_route_hook_remove(struct ospf6_route *route)
166 : {
167 54 : struct ospf6_area *oa = route->table->scope;
168 54 : struct ospf6 *ospf6 = oa->ospf6;
169 54 : struct ospf6_route *copy;
170 :
171 54 : copy = ospf6_route_lookup_identical(route, ospf6->route_table);
172 54 : if (copy)
173 54 : ospf6_route_remove(copy, ospf6->route_table);
174 54 : }
175 :
176 0 : static void ospf6_area_stub_update(struct ospf6_area *area)
177 : {
178 :
179 0 : if (IS_AREA_STUB(area)) {
180 0 : if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
181 0 : zlog_debug("Stubbing out area for area %s", area->name);
182 0 : OSPF6_OPT_CLEAR(area->options, OSPF6_OPT_E);
183 0 : ospf6_asbr_remove_externals_from_area(area);
184 0 : } else if (IS_AREA_ENABLED(area)) {
185 0 : if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
186 0 : zlog_debug("Normal area for area %s", area->name);
187 0 : OSPF6_OPT_SET(area->options, OSPF6_OPT_E);
188 0 : ospf6_asbr_send_externals_to_area(area);
189 : }
190 :
191 0 : OSPF6_ROUTER_LSA_SCHEDULE(area);
192 0 : }
193 :
194 0 : static int ospf6_area_stub_set(struct ospf6 *ospf6, struct ospf6_area *area)
195 : {
196 0 : if (!IS_AREA_STUB(area)) {
197 : /* Disable NSSA first. */
198 0 : ospf6_area_nssa_unset(ospf6, area);
199 :
200 0 : SET_FLAG(area->flag, OSPF6_AREA_STUB);
201 0 : ospf6_area_stub_update(area);
202 : }
203 :
204 0 : return 1;
205 : }
206 :
207 0 : void ospf6_area_stub_unset(struct ospf6 *ospf6, struct ospf6_area *area)
208 : {
209 0 : if (IS_AREA_STUB(area)) {
210 0 : UNSET_FLAG(area->flag, OSPF6_AREA_STUB);
211 0 : ospf6_area_stub_update(area);
212 : }
213 0 : }
214 :
215 0 : static void ospf6_area_no_summary_set(struct ospf6 *ospf6,
216 : struct ospf6_area *area)
217 : {
218 0 : if (area) {
219 0 : if (!area->no_summary) {
220 0 : area->no_summary = 1;
221 0 : ospf6_abr_range_reset_cost(ospf6);
222 0 : ospf6_abr_prefix_resummarize(ospf6);
223 : }
224 : }
225 0 : }
226 :
227 0 : static void ospf6_area_no_summary_unset(struct ospf6 *ospf6,
228 : struct ospf6_area *area)
229 : {
230 0 : if (area) {
231 0 : if (area->no_summary) {
232 0 : area->no_summary = 0;
233 0 : ospf6_abr_range_reset_cost(ospf6);
234 0 : ospf6_abr_prefix_resummarize(ospf6);
235 : }
236 : }
237 0 : }
238 :
239 0 : static void ospf6_nssa_default_originate_set(struct ospf6 *ospf6,
240 : struct ospf6_area *area,
241 : int metric, int metric_type)
242 : {
243 0 : if (!area->nssa_default_originate.enabled) {
244 0 : area->nssa_default_originate.enabled = true;
245 0 : if (++ospf6->nssa_default_import_check.refcnt == 1) {
246 0 : ospf6->nssa_default_import_check.status = false;
247 0 : ospf6_zebra_import_default_route(ospf6, false);
248 : }
249 : }
250 :
251 0 : area->nssa_default_originate.metric_value = metric;
252 0 : area->nssa_default_originate.metric_type = metric_type;
253 0 : }
254 :
255 0 : static void ospf6_nssa_default_originate_unset(struct ospf6 *ospf6,
256 : struct ospf6_area *area)
257 : {
258 0 : if (area->nssa_default_originate.enabled) {
259 0 : area->nssa_default_originate.enabled = false;
260 0 : if (--ospf6->nssa_default_import_check.refcnt == 0) {
261 0 : ospf6->nssa_default_import_check.status = false;
262 0 : ospf6_zebra_import_default_route(ospf6, true);
263 : }
264 0 : area->nssa_default_originate.metric_value = -1;
265 0 : area->nssa_default_originate.metric_type = -1;
266 : }
267 0 : }
268 :
269 : /**
270 : * Make new area structure.
271 : *
272 : * @param area_id - ospf6 area ID
273 : * @param o - ospf6 instance
274 : * @param df - display format for area ID
275 : */
276 19 : struct ospf6_area *ospf6_area_create(uint32_t area_id, struct ospf6 *o, int df)
277 : {
278 19 : struct ospf6_area *oa;
279 :
280 19 : oa = XCALLOC(MTYPE_OSPF6_AREA, sizeof(struct ospf6_area));
281 :
282 19 : switch (df) {
283 0 : case OSPF6_AREA_FMT_DECIMAL:
284 0 : snprintf(oa->name, sizeof(oa->name), "%u", ntohl(area_id));
285 0 : break;
286 19 : default:
287 : case OSPF6_AREA_FMT_DOTTEDQUAD:
288 19 : inet_ntop(AF_INET, &area_id, oa->name, sizeof(oa->name));
289 19 : break;
290 : }
291 :
292 19 : oa->area_id = area_id;
293 19 : oa->if_list = list_new();
294 :
295 19 : ospf6_vlink_area_init(oa);
296 :
297 19 : oa->lsdb = ospf6_lsdb_create(oa);
298 19 : oa->lsdb->hook_add = ospf6_area_lsdb_hook_add;
299 19 : oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove;
300 19 : oa->lsdb_self = ospf6_lsdb_create(oa);
301 19 : oa->temp_router_lsa_lsdb = ospf6_lsdb_create(oa);
302 :
303 19 : oa->spf_table = OSPF6_ROUTE_TABLE_CREATE(AREA, SPF_RESULTS);
304 19 : oa->spf_table->scope = oa;
305 19 : oa->route_table = OSPF6_ROUTE_TABLE_CREATE(AREA, ROUTES);
306 19 : oa->route_table->scope = oa;
307 19 : oa->route_table->hook_add = ospf6_area_route_hook_add;
308 19 : oa->route_table->hook_remove = ospf6_area_route_hook_remove;
309 :
310 19 : oa->range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
311 19 : oa->range_table->scope = oa;
312 19 : oa->nssa_range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
313 19 : oa->nssa_range_table->scope = oa;
314 19 : oa->summary_prefix = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_PREFIXES);
315 19 : oa->summary_prefix->scope = oa;
316 19 : oa->summary_router = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_ROUTERS);
317 19 : oa->summary_router->scope = oa;
318 19 : oa->router_lsa_size_limit = 1024 + 256;
319 :
320 : /* set default options */
321 19 : if (CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER)) {
322 0 : OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_V6);
323 0 : OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_R);
324 : } else {
325 19 : OSPF6_OPT_SET(oa->options, OSPF6_OPT_V6);
326 19 : OSPF6_OPT_SET(oa->options, OSPF6_OPT_R);
327 : }
328 :
329 19 : OSPF6_OPT_SET(oa->options, OSPF6_OPT_E);
330 :
331 19 : SET_FLAG(oa->flag, OSPF6_AREA_ACTIVE);
332 19 : SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
333 :
334 19 : oa->ospf6 = o;
335 19 : listnode_add_sort(o->area_list, oa);
336 :
337 19 : if (area_id == OSPF_AREA_BACKBONE) {
338 9 : o->backbone = oa;
339 : }
340 :
341 19 : return oa;
342 : }
343 :
344 19 : void ospf6_area_delete(struct ospf6_area *oa)
345 : {
346 19 : struct listnode *n;
347 19 : struct ospf6_interface *oi;
348 :
349 19 : ospf6_vlink_area_fini(oa);
350 :
351 : /* The ospf6_interface structs store configuration
352 : * information which should not be lost/reset when
353 : * deleting an area.
354 : * So just detach the interface from the area and
355 : * keep it around. */
356 67 : for (ALL_LIST_ELEMENTS_RO(oa->if_list, n, oi)) {
357 29 : oi->area = NULL;
358 :
359 29 : struct listnode *node;
360 29 : struct listnode *nnode;
361 29 : struct ospf6_neighbor *on;
362 :
363 58 : for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
364 0 : ospf6_neighbor_delete(on);
365 : }
366 :
367 19 : list_delete(&oa->if_list);
368 :
369 19 : ospf6_lsdb_delete(oa->lsdb);
370 19 : ospf6_lsdb_delete(oa->lsdb_self);
371 19 : ospf6_lsdb_delete(oa->temp_router_lsa_lsdb);
372 :
373 19 : ospf6_spf_table_finish(oa->spf_table);
374 19 : ospf6_route_table_delete(oa->spf_table);
375 19 : ospf6_route_table_delete(oa->route_table);
376 :
377 19 : ospf6_route_table_delete(oa->range_table);
378 19 : ospf6_route_table_delete(oa->nssa_range_table);
379 19 : ospf6_route_table_delete(oa->summary_prefix);
380 19 : ospf6_route_table_delete(oa->summary_router);
381 :
382 19 : listnode_delete(oa->ospf6->area_list, oa);
383 19 : oa->ospf6 = NULL;
384 :
385 : /* free area */
386 19 : XFREE(MTYPE_OSPF6_AREA, oa);
387 19 : }
388 :
389 0 : struct ospf6_area *ospf6_area_lookup_by_area_id(uint32_t area_id)
390 : {
391 0 : struct ospf6_area *oa;
392 0 : struct listnode *n, *node, *nnode;
393 0 : struct ospf6 *ospf6;
394 :
395 0 : for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
396 0 : for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa))
397 0 : if (oa->area_id == area_id)
398 0 : return oa;
399 : }
400 : return (struct ospf6_area *)NULL;
401 : }
402 :
403 589 : struct ospf6_area *ospf6_area_lookup(uint32_t area_id, struct ospf6 *ospf6)
404 : {
405 589 : struct ospf6_area *oa;
406 589 : struct listnode *n;
407 :
408 1242 : for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa))
409 634 : if (oa->area_id == area_id)
410 570 : return oa;
411 :
412 : return (struct ospf6_area *)NULL;
413 : }
414 :
415 0 : void ospf6_area_enable(struct ospf6_area *oa)
416 : {
417 0 : struct listnode *node, *nnode;
418 0 : struct ospf6_interface *oi;
419 :
420 0 : SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
421 :
422 0 : for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
423 0 : ospf6_interface_enable(oi);
424 0 : ospf6_abr_enable_area(oa);
425 0 : }
426 :
427 19 : void ospf6_area_disable(struct ospf6_area *oa)
428 : {
429 19 : struct listnode *node, *nnode;
430 19 : struct ospf6_interface *oi;
431 :
432 19 : UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
433 :
434 67 : for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
435 29 : ospf6_interface_disable(oi);
436 :
437 19 : ospf6_abr_disable_area(oa);
438 19 : ospf6_lsdb_remove_all(oa->lsdb);
439 19 : ospf6_lsdb_remove_all(oa->lsdb_self);
440 :
441 19 : ospf6_spf_table_finish(oa->spf_table);
442 19 : ospf6_route_remove_all(oa->route_table);
443 :
444 19 : THREAD_OFF(oa->thread_router_lsa);
445 19 : THREAD_OFF(oa->thread_intra_prefix_lsa);
446 19 : }
447 :
448 :
449 0 : void ospf6_area_show(struct vty *vty, struct ospf6_area *oa,
450 : json_object *json_areas, bool use_json)
451 : {
452 0 : struct listnode *i;
453 0 : struct ospf6_interface *oi;
454 0 : unsigned long result;
455 0 : json_object *json_area;
456 0 : json_object *array_interfaces;
457 :
458 0 : if (use_json) {
459 0 : json_area = json_object_new_object();
460 0 : json_object_boolean_add(json_area, "areaIsStub",
461 0 : IS_AREA_STUB(oa));
462 0 : json_object_boolean_add(json_area, "areaIsNSSA",
463 0 : IS_AREA_NSSA(oa));
464 0 : if (IS_AREA_STUB(oa) || IS_AREA_NSSA(oa)) {
465 0 : json_object_boolean_add(json_area, "areaNoSummary",
466 0 : oa->no_summary);
467 : }
468 :
469 0 : json_object_int_add(json_area, "numberOfAreaScopedLsa",
470 0 : oa->lsdb->count);
471 0 : json_object_object_add(
472 : json_area, "lsaStatistics",
473 0 : JSON_OBJECT_NEW_ARRAY(json_object_new_int,
474 : oa->lsdb->stats,
475 : OSPF6_LSTYPE_SIZE));
476 :
477 : /* Interfaces Attached */
478 0 : array_interfaces = json_object_new_array();
479 0 : for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi))
480 0 : json_object_array_add(
481 : array_interfaces,
482 : json_object_new_string(ospf6_ifname(oi)));
483 :
484 0 : json_object_object_add(json_area, "interfacesAttachedToArea",
485 : array_interfaces);
486 :
487 0 : if (oa->ts_spf.tv_sec || oa->ts_spf.tv_usec) {
488 0 : json_object_boolean_true_add(json_area, "spfHasRun");
489 0 : result = monotime_since(&oa->ts_spf, NULL);
490 0 : if (result / TIMER_SECOND_MICRO > 0) {
491 0 : json_object_int_add(
492 : json_area, "spfLastExecutedSecs",
493 0 : result / TIMER_SECOND_MICRO);
494 :
495 0 : json_object_int_add(
496 : json_area, "spfLastExecutedMicroSecs",
497 0 : result % TIMER_SECOND_MICRO);
498 : } else {
499 0 : json_object_int_add(json_area,
500 : "spfLastExecutedSecs", 0);
501 0 : json_object_int_add(json_area,
502 : "spfLastExecutedMicroSecs",
503 : result);
504 : }
505 : } else
506 0 : json_object_boolean_false_add(json_area, "spfHasRun");
507 :
508 :
509 0 : json_object_object_add(json_areas, oa->name, json_area);
510 :
511 : } else {
512 :
513 0 : if (!IS_AREA_STUB(oa) && !IS_AREA_NSSA(oa))
514 0 : vty_out(vty, " Area %s\n", oa->name);
515 : else {
516 0 : if (oa->no_summary) {
517 0 : vty_out(vty, " Area %s[%s, No Summary]\n",
518 0 : oa->name,
519 : IS_AREA_STUB(oa) ? "Stub" : "NSSA");
520 : } else {
521 0 : vty_out(vty, " Area %s[%s]\n", oa->name,
522 : IS_AREA_STUB(oa) ? "Stub" : "NSSA");
523 : }
524 : }
525 0 : vty_out(vty, " Number of Area scoped LSAs is %u\n",
526 0 : oa->lsdb->count);
527 :
528 0 : vty_out(vty, " Interface attached to this area:");
529 0 : for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi))
530 0 : vty_out(vty, " %pOI", oi);
531 0 : vty_out(vty, "\n");
532 :
533 0 : if (oa->ts_spf.tv_sec || oa->ts_spf.tv_usec) {
534 0 : result = monotime_since(&oa->ts_spf, NULL);
535 0 : if (result / TIMER_SECOND_MICRO > 0) {
536 0 : vty_out(vty,
537 : " SPF last executed %ld.%lds ago\n",
538 : result / TIMER_SECOND_MICRO,
539 : result % TIMER_SECOND_MICRO);
540 : } else {
541 0 : vty_out(vty,
542 : " SPF last executed %ldus ago\n",
543 : result);
544 : }
545 : } else
546 0 : vty_out(vty, "SPF has not been run\n");
547 : }
548 0 : }
549 :
550 0 : DEFUN (area_range,
551 : area_range_cmd,
552 : "area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
553 : "OSPF6 area parameters\n"
554 : "OSPF6 area ID in IP address format\n"
555 : "OSPF6 area ID as a decimal value\n"
556 : "Configured address range\n"
557 : "Specify IPv6 prefix\n"
558 : "Advertise\n"
559 : "Do not advertise\n"
560 : "User specified metric for this range\n"
561 : "Advertised metric for this range\n")
562 : {
563 0 : int idx_ipv4 = 1;
564 0 : int idx_ipv6_prefixlen = 3;
565 0 : int idx_type = 4;
566 0 : int ret;
567 0 : struct ospf6_area *oa;
568 0 : struct prefix prefix;
569 0 : struct ospf6_route *range;
570 0 : uint32_t cost;
571 :
572 0 : VTY_DECLVAR_CONTEXT(ospf6, ospf6);
573 :
574 0 : OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa, ospf6);
575 :
576 0 : ret = str2prefix(argv[idx_ipv6_prefixlen]->arg, &prefix);
577 0 : if (ret != 1 || prefix.family != AF_INET6) {
578 0 : vty_out(vty, "Malformed argument: %s\n",
579 0 : argv[idx_ipv6_prefixlen]->arg);
580 0 : return CMD_SUCCESS;
581 : }
582 :
583 0 : range = ospf6_route_lookup(&prefix, oa->range_table);
584 0 : if (range == NULL) {
585 0 : range = ospf6_route_create(ospf6);
586 0 : range->type = OSPF6_DEST_TYPE_RANGE;
587 0 : range->prefix = prefix;
588 0 : range->path.area_id = oa->area_id;
589 0 : range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
590 : }
591 :
592 : /* default settings */
593 0 : cost = OSPF_AREA_RANGE_COST_UNSPEC;
594 0 : UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
595 :
596 0 : if (argc > idx_type) {
597 0 : if (strmatch(argv[idx_type]->text, "not-advertise"))
598 0 : SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
599 0 : else if (strmatch(argv[idx_type]->text, "cost"))
600 0 : cost = strtoul(argv[5]->arg, NULL, 10);
601 : }
602 :
603 0 : range->path.u.cost_config = cost;
604 :
605 0 : if (range->rnode == NULL) {
606 0 : ospf6_route_add(range, oa->range_table);
607 : }
608 :
609 0 : if (ospf6_check_and_set_router_abr(ospf6)) {
610 : /* Redo summaries if required */
611 0 : ospf6_abr_prefix_resummarize(ospf6);
612 : }
613 :
614 : return CMD_SUCCESS;
615 : }
616 :
617 0 : DEFUN (no_area_range,
618 : no_area_range_cmd,
619 : "no area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
620 : NO_STR
621 : "OSPF6 area parameters\n"
622 : "OSPF6 area ID in IP address format\n"
623 : "OSPF6 area ID as a decimal value\n"
624 : "Configured address range\n"
625 : "Specify IPv6 prefix\n"
626 : "Advertise\n"
627 : "Do not advertise\n"
628 : "User specified metric for this range\n"
629 : "Advertised metric for this range\n")
630 : {
631 0 : int idx_ipv4 = 2;
632 0 : int idx_ipv6 = 4;
633 0 : int ret;
634 0 : struct ospf6_area *oa;
635 0 : struct prefix prefix;
636 0 : struct ospf6_route *range, *route;
637 :
638 0 : VTY_DECLVAR_CONTEXT(ospf6, ospf6);
639 :
640 0 : OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa, ospf6);
641 :
642 0 : ret = str2prefix(argv[idx_ipv6]->arg, &prefix);
643 0 : if (ret != 1 || prefix.family != AF_INET6) {
644 0 : vty_out(vty, "Malformed argument: %s\n", argv[idx_ipv6]->arg);
645 0 : return CMD_SUCCESS;
646 : }
647 :
648 0 : range = ospf6_route_lookup(&prefix, oa->range_table);
649 0 : if (range == NULL) {
650 0 : vty_out(vty, "Range %s does not exists.\n",
651 0 : argv[idx_ipv6]->arg);
652 0 : return CMD_SUCCESS;
653 : }
654 :
655 0 : if (ospf6_check_and_set_router_abr(oa->ospf6)) {
656 : /* Blow away the aggregated LSA and route */
657 0 : SET_FLAG(range->flag, OSPF6_ROUTE_REMOVE);
658 :
659 : /* Redo summaries if required */
660 0 : for (route = ospf6_route_head(oa->ospf6->route_table); route;
661 0 : route = ospf6_route_next(route))
662 0 : ospf6_abr_originate_summary(route, oa->ospf6);
663 :
664 : /* purge the old aggregated summary LSA */
665 0 : ospf6_abr_originate_summary(range, oa->ospf6);
666 : }
667 0 : ospf6_route_remove(range, oa->range_table);
668 :
669 0 : return CMD_SUCCESS;
670 : }
671 :
672 0 : void ospf6_area_config_write(struct vty *vty, struct ospf6 *ospf6)
673 : {
674 0 : struct listnode *node;
675 0 : struct ospf6_area *oa;
676 0 : struct ospf6_route *range;
677 :
678 0 : for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
679 0 : for (range = ospf6_route_head(oa->range_table); range;
680 0 : range = ospf6_route_next(range)) {
681 0 : vty_out(vty, " area %s range %pFX", oa->name,
682 : &range->prefix);
683 :
684 0 : if (CHECK_FLAG(range->flag,
685 : OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
686 0 : vty_out(vty, " not-advertise");
687 : } else {
688 : // "advertise" is the default so we do not
689 : // display it
690 0 : if (range->path.u.cost_config
691 : != OSPF_AREA_RANGE_COST_UNSPEC)
692 0 : vty_out(vty, " cost %d",
693 : range->path.u.cost_config);
694 : }
695 0 : vty_out(vty, "\n");
696 : }
697 0 : if (IS_AREA_STUB(oa)) {
698 0 : if (oa->no_summary)
699 0 : vty_out(vty, " area %s stub no-summary\n",
700 0 : oa->name);
701 : else
702 0 : vty_out(vty, " area %s stub\n", oa->name);
703 : }
704 0 : if (IS_AREA_NSSA(oa)) {
705 0 : vty_out(vty, " area %s nssa", oa->name);
706 0 : if (oa->nssa_default_originate.enabled) {
707 0 : vty_out(vty, " default-information-originate");
708 0 : if (oa->nssa_default_originate.metric_value
709 : != -1)
710 0 : vty_out(vty, " metric %d",
711 : oa->nssa_default_originate
712 : .metric_value);
713 0 : if (oa->nssa_default_originate.metric_type
714 : != DEFAULT_METRIC_TYPE)
715 0 : vty_out(vty, " metric-type 1");
716 : }
717 0 : if (oa->no_summary)
718 0 : vty_out(vty, " no-summary");
719 0 : vty_out(vty, "\n");
720 : }
721 0 : for (range = ospf6_route_head(oa->nssa_range_table); range;
722 0 : range = ospf6_route_next(range)) {
723 0 : vty_out(vty, " area %s nssa range %pFX", oa->name,
724 : &range->prefix);
725 :
726 0 : if (CHECK_FLAG(range->flag,
727 : OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
728 0 : vty_out(vty, " not-advertise");
729 : } else {
730 0 : if (range->path.u.cost_config
731 : != OSPF_AREA_RANGE_COST_UNSPEC)
732 0 : vty_out(vty, " cost %u",
733 : range->path.u.cost_config);
734 : }
735 0 : vty_out(vty, "\n");
736 : }
737 0 : if (PREFIX_NAME_IN(oa))
738 0 : vty_out(vty, " area %s filter-list prefix %s in\n",
739 0 : oa->name, PREFIX_NAME_IN(oa));
740 0 : if (PREFIX_NAME_OUT(oa))
741 0 : vty_out(vty, " area %s filter-list prefix %s out\n",
742 0 : oa->name, PREFIX_NAME_OUT(oa));
743 0 : if (IMPORT_NAME(oa))
744 0 : vty_out(vty, " area %s import-list %s\n", oa->name,
745 : IMPORT_NAME(oa));
746 0 : if (EXPORT_NAME(oa))
747 0 : vty_out(vty, " area %s export-list %s\n", oa->name,
748 : EXPORT_NAME(oa));
749 0 : ospf6_vlink_area_config(oa, vty);
750 : }
751 0 : }
752 :
753 0 : DEFUN (area_filter_list,
754 : area_filter_list_cmd,
755 : "area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST_NAME <in|out>",
756 : "OSPF6 area parameters\n"
757 : "OSPF6 area ID in IP address format\n"
758 : "OSPF6 area ID as a decimal value\n"
759 : "Filter networks between OSPF6 areas\n"
760 : "Filter prefixes between OSPF6 areas\n"
761 : "Name of an IPv6 prefix-list\n"
762 : "Filter networks sent to this area\n"
763 : "Filter networks sent from this area\n")
764 : {
765 0 : char *inout = argv[argc - 1]->text;
766 0 : char *areaid = argv[1]->arg;
767 0 : char *plistname = argv[4]->arg;
768 :
769 0 : struct ospf6_area *area;
770 0 : struct prefix_list *plist;
771 :
772 0 : VTY_DECLVAR_CONTEXT(ospf6, ospf6);
773 :
774 0 : OSPF6_CMD_AREA_GET(areaid, area, ospf6);
775 :
776 0 : plist = prefix_list_lookup(AFI_IP6, plistname);
777 0 : if (strmatch(inout, "in")) {
778 0 : PREFIX_LIST_IN(area) = plist;
779 0 : XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
780 0 : PREFIX_NAME_IN(area) =
781 0 : XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
782 : } else {
783 0 : PREFIX_LIST_OUT(area) = plist;
784 0 : XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
785 0 : PREFIX_NAME_OUT(area) =
786 0 : XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
787 : }
788 :
789 : /* Redo summaries if required */
790 0 : if (ospf6_check_and_set_router_abr(area->ospf6))
791 0 : ospf6_schedule_abr_task(ospf6);
792 :
793 : return CMD_SUCCESS;
794 : }
795 :
796 0 : DEFUN (no_area_filter_list,
797 : no_area_filter_list_cmd,
798 : "no area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST_NAME <in|out>",
799 : NO_STR
800 : "OSPF6 area parameters\n"
801 : "OSPF6 area ID in IP address format\n"
802 : "OSPF6 area ID as a decimal value\n"
803 : "Filter networks between OSPF6 areas\n"
804 : "Filter prefixes between OSPF6 areas\n"
805 : "Name of an IPv6 prefix-list\n"
806 : "Filter networks sent to this area\n"
807 : "Filter networks sent from this area\n")
808 : {
809 0 : char *inout = argv[argc - 1]->text;
810 0 : char *areaid = argv[2]->arg;
811 0 : char *plistname = argv[5]->arg;
812 :
813 0 : struct ospf6_area *area;
814 :
815 0 : VTY_DECLVAR_CONTEXT(ospf6, ospf6);
816 0 : OSPF6_CMD_AREA_GET(areaid, area, ospf6);
817 :
818 0 : if (strmatch(inout, "in")) {
819 0 : if (PREFIX_NAME_IN(area))
820 0 : if (!strmatch(PREFIX_NAME_IN(area), plistname))
821 : return CMD_SUCCESS;
822 :
823 0 : PREFIX_LIST_IN(area) = NULL;
824 0 : XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
825 : } else {
826 0 : if (PREFIX_NAME_OUT(area))
827 0 : if (!strmatch(PREFIX_NAME_OUT(area), plistname))
828 : return CMD_SUCCESS;
829 :
830 0 : XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
831 0 : PREFIX_LIST_OUT(area) = NULL;
832 : }
833 :
834 : /* Redo summaries if required */
835 0 : if (ospf6_check_and_set_router_abr(area->ospf6))
836 0 : ospf6_schedule_abr_task(ospf6);
837 :
838 : return CMD_SUCCESS;
839 : }
840 :
841 0 : void ospf6_filter_update(struct access_list *access)
842 : {
843 0 : struct ospf6_area *oa;
844 0 : struct listnode *n, *node, *nnode;
845 0 : struct ospf6 *ospf6;
846 :
847 0 : for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
848 0 : bool update = false;
849 :
850 0 : for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
851 0 : if (IMPORT_NAME(oa)
852 0 : && strcmp(IMPORT_NAME(oa), access->name) == 0) {
853 0 : IMPORT_LIST(oa) = access_list_lookup(
854 : AFI_IP6, IMPORT_NAME(oa));
855 0 : update = true;
856 : }
857 :
858 0 : if (EXPORT_NAME(oa)
859 0 : && strcmp(EXPORT_NAME(oa), access->name) == 0) {
860 0 : EXPORT_LIST(oa) = access_list_lookup(
861 : AFI_IP6, EXPORT_NAME(oa));
862 0 : update = true;
863 : }
864 : }
865 :
866 0 : if (update && ospf6_check_and_set_router_abr(ospf6))
867 0 : ospf6_schedule_abr_task(ospf6);
868 : }
869 0 : }
870 :
871 0 : void ospf6_plist_update(struct prefix_list *plist)
872 : {
873 0 : struct listnode *node, *nnode;
874 0 : struct ospf6_area *oa;
875 0 : struct listnode *n;
876 0 : const char *name = prefix_list_name(plist);
877 0 : struct ospf6 *ospf6 = NULL;
878 :
879 0 : if (prefix_list_afi(plist) != AFI_IP6)
880 : return;
881 :
882 0 : for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
883 0 : bool update = false;
884 :
885 0 : for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
886 0 : if (PREFIX_NAME_IN(oa)
887 0 : && !strcmp(PREFIX_NAME_IN(oa), name)) {
888 0 : PREFIX_LIST_IN(oa) = prefix_list_lookup(
889 : AFI_IP6, PREFIX_NAME_IN(oa));
890 0 : update = true;
891 : }
892 0 : if (PREFIX_NAME_OUT(oa)
893 0 : && !strcmp(PREFIX_NAME_OUT(oa), name)) {
894 0 : PREFIX_LIST_OUT(oa) = prefix_list_lookup(
895 : AFI_IP6, PREFIX_NAME_OUT(oa));
896 0 : update = true;
897 : }
898 : }
899 :
900 0 : if (update && ospf6_check_and_set_router_abr(ospf6))
901 0 : ospf6_schedule_abr_task(ospf6);
902 : }
903 : }
904 :
905 0 : DEFUN (area_import_list,
906 : area_import_list_cmd,
907 : "area <A.B.C.D|(0-4294967295)> import-list ACCESSLIST6_NAME",
908 : "OSPF6 area parameters\n"
909 : "OSPF6 area ID in IP address format\n"
910 : "OSPF6 area ID as a decimal value\n"
911 : "Set the filter for networks from other areas announced to the specified one\n"
912 : "Name of the access-list\n")
913 : {
914 0 : int idx_ipv4 = 1;
915 0 : int idx_name = 3;
916 0 : struct ospf6_area *area;
917 0 : struct access_list *list;
918 :
919 0 : VTY_DECLVAR_CONTEXT(ospf6, ospf6);
920 :
921 0 : OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
922 :
923 0 : list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
924 :
925 0 : IMPORT_LIST(area) = list;
926 :
927 0 : if (IMPORT_NAME(area))
928 0 : free(IMPORT_NAME(area));
929 :
930 0 : IMPORT_NAME(area) = strdup(argv[idx_name]->arg);
931 0 : if (ospf6_check_and_set_router_abr(area->ospf6))
932 0 : ospf6_schedule_abr_task(ospf6);
933 :
934 : return CMD_SUCCESS;
935 : }
936 :
937 0 : DEFUN (no_area_import_list,
938 : no_area_import_list_cmd,
939 : "no area <A.B.C.D|(0-4294967295)> import-list ACCESSLIST6_NAME",
940 : NO_STR
941 : "OSPF6 area parameters\n"
942 : "OSPF6 area ID in IP address format\n"
943 : "OSPF6 area ID as a decimal value\n"
944 : "Unset the filter for networks announced to other areas\n"
945 : "Name of the access-list\n")
946 : {
947 0 : int idx_ipv4 = 2;
948 0 : struct ospf6_area *area;
949 :
950 0 : VTY_DECLVAR_CONTEXT(ospf6, ospf6);
951 :
952 0 : OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
953 :
954 0 : IMPORT_LIST(area) = NULL;
955 :
956 0 : if (IMPORT_NAME(area))
957 0 : free(IMPORT_NAME(area));
958 :
959 0 : IMPORT_NAME(area) = NULL;
960 0 : if (ospf6_check_and_set_router_abr(area->ospf6))
961 0 : ospf6_schedule_abr_task(ospf6);
962 :
963 : return CMD_SUCCESS;
964 : }
965 :
966 0 : DEFUN (area_export_list,
967 : area_export_list_cmd,
968 : "area <A.B.C.D|(0-4294967295)> export-list ACCESSLIST6_NAME",
969 : "OSPF6 area parameters\n"
970 : "OSPF6 area ID in IP address format\n"
971 : "OSPF6 area ID as a decimal value\n"
972 : "Set the filter for networks announced to other areas\n"
973 : "Name of the access-list\n")
974 : {
975 0 : int idx_ipv4 = 1;
976 0 : int idx_name = 3;
977 0 : struct ospf6_area *area;
978 0 : struct access_list *list;
979 :
980 0 : VTY_DECLVAR_CONTEXT(ospf6, ospf6);
981 :
982 0 : OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
983 :
984 0 : list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
985 :
986 0 : EXPORT_LIST(area) = list;
987 :
988 0 : if (EXPORT_NAME(area))
989 0 : free(EXPORT_NAME(area));
990 :
991 0 : EXPORT_NAME(area) = strdup(argv[idx_name]->arg);
992 :
993 : /* Redo summaries if required */
994 0 : if (ospf6_check_and_set_router_abr(area->ospf6))
995 0 : ospf6_schedule_abr_task(ospf6);
996 :
997 : return CMD_SUCCESS;
998 : }
999 :
1000 0 : DEFUN (no_area_export_list,
1001 : no_area_export_list_cmd,
1002 : "no area <A.B.C.D|(0-4294967295)> export-list ACCESSLIST6_NAME",
1003 : NO_STR
1004 : "OSPF6 area parameters\n"
1005 : "OSPF6 area ID in IP address format\n"
1006 : "OSPF6 area ID as a decimal value\n"
1007 : "Unset the filter for networks announced to other areas\n"
1008 : "Name of the access-list\n")
1009 : {
1010 0 : int idx_ipv4 = 2;
1011 0 : struct ospf6_area *area;
1012 :
1013 0 : VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1014 :
1015 0 : OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
1016 :
1017 0 : EXPORT_LIST(area) = NULL;
1018 :
1019 0 : if (EXPORT_NAME(area))
1020 0 : free(EXPORT_NAME(area));
1021 :
1022 0 : EXPORT_NAME(area) = NULL;
1023 0 : if (ospf6_check_and_set_router_abr(area->ospf6))
1024 0 : ospf6_schedule_abr_task(ospf6);
1025 :
1026 : return CMD_SUCCESS;
1027 : }
1028 :
1029 0 : static int ipv6_ospf6_spf_tree_common(struct vty *vty, struct ospf6 *ospf6,
1030 : bool uj)
1031 : {
1032 0 : struct listnode *node;
1033 0 : struct ospf6_area *oa;
1034 0 : struct prefix prefix;
1035 0 : struct ospf6_vertex *root;
1036 0 : struct ospf6_route *route;
1037 0 : json_object *json = NULL;
1038 0 : json_object *json_area = NULL;
1039 0 : json_object *json_head = NULL;
1040 :
1041 0 : if (uj)
1042 0 : json = json_object_new_object();
1043 0 : ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
1044 0 : for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
1045 0 : if (uj) {
1046 0 : json_area = json_object_new_object();
1047 0 : json_head = json_object_new_object();
1048 : }
1049 0 : route = ospf6_route_lookup(&prefix, oa->spf_table);
1050 0 : if (route == NULL) {
1051 0 : if (uj) {
1052 0 : json_object_string_add(
1053 0 : json, oa->name,
1054 : "LS entry for not not found");
1055 0 : json_object_free(json_head);
1056 0 : json_object_free(json_area);
1057 : } else
1058 0 : vty_out(vty,
1059 : "LS entry for root not found in area %s\n",
1060 0 : oa->name);
1061 0 : continue;
1062 : }
1063 0 : root = (struct ospf6_vertex *)route->route_option;
1064 0 : ospf6_spf_display_subtree(vty, "", 0, root, json_head, uj);
1065 :
1066 0 : if (uj) {
1067 0 : json_object_object_add(json_area, root->name,
1068 : json_head);
1069 0 : json_object_object_add(json, oa->name, json_area);
1070 : }
1071 : }
1072 :
1073 0 : if (uj)
1074 0 : vty_json(vty, json);
1075 :
1076 0 : return CMD_SUCCESS;
1077 : }
1078 :
1079 0 : DEFUN(show_ipv6_ospf6_spf_tree, show_ipv6_ospf6_spf_tree_cmd,
1080 : "show ipv6 ospf6 [vrf <NAME|all>] spf tree [json]",
1081 : SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1082 : "All VRFs\n"
1083 : "Shortest Path First calculation\n"
1084 : "Show SPF tree\n" JSON_STR)
1085 : {
1086 0 : struct listnode *node;
1087 0 : struct ospf6 *ospf6;
1088 0 : const char *vrf_name = NULL;
1089 0 : bool all_vrf = false;
1090 0 : int idx_vrf = 0;
1091 0 : bool uj = use_json(argc, argv);
1092 :
1093 0 : OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1094 :
1095 0 : for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1096 0 : if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1097 0 : ipv6_ospf6_spf_tree_common(vty, ospf6, uj);
1098 0 : if (!all_vrf)
1099 : break;
1100 : }
1101 : }
1102 :
1103 0 : OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1104 :
1105 : return CMD_SUCCESS;
1106 : }
1107 :
1108 0 : static int show_ospf6_area_spf_tree_common(struct vty *vty,
1109 : struct cmd_token **argv,
1110 : struct ospf6 *ospf6,
1111 : uint32_t area_id, int idx_ipv4)
1112 : {
1113 :
1114 0 : struct ospf6_area *oa;
1115 0 : struct prefix prefix;
1116 0 : struct ospf6_vertex *root;
1117 0 : struct ospf6_route *route;
1118 :
1119 0 : ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
1120 :
1121 0 : oa = ospf6_area_lookup(area_id, ospf6);
1122 0 : if (oa == NULL) {
1123 0 : vty_out(vty, "No such Area: %s\n", argv[idx_ipv4]->arg);
1124 0 : return CMD_SUCCESS;
1125 : }
1126 :
1127 0 : route = ospf6_route_lookup(&prefix, oa->spf_table);
1128 0 : if (route == NULL) {
1129 0 : vty_out(vty, "LS entry for root not found in area %s\n",
1130 0 : oa->name);
1131 0 : return CMD_SUCCESS;
1132 : }
1133 0 : root = (struct ospf6_vertex *)route->route_option;
1134 0 : ospf6_spf_display_subtree(vty, "", 0, root, NULL, false);
1135 :
1136 0 : return CMD_SUCCESS;
1137 : }
1138 :
1139 0 : DEFUN(show_ipv6_ospf6_area_spf_tree, show_ipv6_ospf6_area_spf_tree_cmd,
1140 : "show ipv6 ospf6 [vrf <NAME|all>] area A.B.C.D spf tree",
1141 : SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1142 : "All VRFs\n" OSPF6_AREA_STR OSPF6_AREA_ID_STR
1143 : "Shortest Path First calculation\n"
1144 : "Show SPF tree\n")
1145 : {
1146 0 : int idx_ipv4 = 4;
1147 0 : uint32_t area_id;
1148 0 : struct ospf6 *ospf6;
1149 0 : struct listnode *node;
1150 0 : const char *vrf_name = NULL;
1151 0 : bool all_vrf = false;
1152 0 : int idx_vrf = 0;
1153 :
1154 0 : OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1155 0 : if (idx_vrf > 0)
1156 0 : idx_ipv4 += 2;
1157 :
1158 0 : if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) {
1159 0 : vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
1160 0 : return CMD_SUCCESS;
1161 : }
1162 :
1163 0 : for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1164 0 : if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1165 0 : show_ospf6_area_spf_tree_common(vty, argv, ospf6,
1166 : area_id, idx_ipv4);
1167 0 : if (!all_vrf)
1168 : break;
1169 : }
1170 : }
1171 :
1172 0 : OSPF6_CMD_CHECK_VRF(false, all_vrf, ospf6);
1173 :
1174 : return CMD_SUCCESS;
1175 : }
1176 :
1177 : static int
1178 0 : show_ospf6_simulate_spf_tree_commen(struct vty *vty, struct cmd_token **argv,
1179 : struct ospf6 *ospf6, uint32_t router_id,
1180 : uint32_t area_id, struct prefix prefix,
1181 : int idx_ipv4, int idx_ipv4_2)
1182 : {
1183 0 : struct ospf6_area *oa;
1184 0 : struct ospf6_vertex *root;
1185 0 : struct ospf6_route *route;
1186 0 : struct ospf6_route_table *spf_table;
1187 0 : unsigned char tmp_debug_ospf6_spf = 0;
1188 :
1189 0 : oa = ospf6_area_lookup(area_id, ospf6);
1190 0 : if (oa == NULL) {
1191 0 : vty_out(vty, "No such Area: %s\n", argv[idx_ipv4_2]->arg);
1192 0 : return CMD_SUCCESS;
1193 : }
1194 :
1195 0 : tmp_debug_ospf6_spf = conf_debug_ospf6_spf;
1196 0 : conf_debug_ospf6_spf = 0;
1197 :
1198 0 : spf_table = OSPF6_ROUTE_TABLE_CREATE(NONE, SPF_RESULTS);
1199 0 : ospf6_spf_calculation(router_id, spf_table, oa);
1200 :
1201 0 : conf_debug_ospf6_spf = tmp_debug_ospf6_spf;
1202 :
1203 0 : route = ospf6_route_lookup(&prefix, spf_table);
1204 0 : if (route == NULL) {
1205 0 : ospf6_spf_table_finish(spf_table);
1206 0 : ospf6_route_table_delete(spf_table);
1207 0 : return CMD_SUCCESS;
1208 : }
1209 0 : root = (struct ospf6_vertex *)route->route_option;
1210 0 : ospf6_spf_display_subtree(vty, "", 0, root, NULL, false);
1211 :
1212 0 : ospf6_spf_table_finish(spf_table);
1213 0 : ospf6_route_table_delete(spf_table);
1214 :
1215 0 : return CMD_SUCCESS;
1216 : }
1217 :
1218 0 : DEFUN(show_ipv6_ospf6_simulate_spf_tree_root,
1219 : show_ipv6_ospf6_simulate_spf_tree_root_cmd,
1220 : "show ipv6 ospf6 [vrf <NAME|all>] simulate spf-tree A.B.C.D area A.B.C.D",
1221 : SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1222 : "All VRFs\n"
1223 : "Shortest Path First calculation\n"
1224 : "Show SPF tree\n"
1225 : "Specify root's router-id to calculate another router's SPF tree\n"
1226 : "OSPF6 area parameters\n" OSPF6_AREA_ID_STR)
1227 : {
1228 0 : int idx_ipv4 = 5;
1229 0 : int idx_ipv4_2 = 7;
1230 0 : uint32_t area_id;
1231 0 : struct prefix prefix;
1232 0 : uint32_t router_id;
1233 0 : struct ospf6 *ospf6;
1234 0 : struct listnode *node;
1235 0 : const char *vrf_name = NULL;
1236 0 : bool all_vrf = false;
1237 0 : int idx_vrf = 0;
1238 :
1239 0 : OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1240 0 : if (idx_vrf > 0) {
1241 0 : idx_ipv4 += 2;
1242 0 : idx_ipv4_2 += 2;
1243 : }
1244 0 : inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id);
1245 0 : ospf6_linkstate_prefix(router_id, htonl(0), &prefix);
1246 :
1247 0 : if (inet_pton(AF_INET, argv[idx_ipv4_2]->arg, &area_id) != 1) {
1248 0 : vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4_2]->arg);
1249 0 : return CMD_SUCCESS;
1250 : }
1251 :
1252 0 : for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1253 0 : if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1254 0 : show_ospf6_simulate_spf_tree_commen(
1255 : vty, argv, ospf6, router_id, area_id, prefix,
1256 : idx_ipv4, idx_ipv4_2);
1257 0 : if (!all_vrf)
1258 : break;
1259 : }
1260 : }
1261 :
1262 0 : OSPF6_CMD_CHECK_VRF(false, all_vrf, ospf6);
1263 :
1264 : return CMD_SUCCESS;
1265 : }
1266 :
1267 0 : DEFUN (ospf6_area_stub,
1268 : ospf6_area_stub_cmd,
1269 : "area <A.B.C.D|(0-4294967295)> stub",
1270 : "OSPF6 area parameters\n"
1271 : "OSPF6 area ID in IP address format\n"
1272 : "OSPF6 area ID as a decimal value\n"
1273 : "Configure OSPF6 area as stub\n")
1274 : {
1275 0 : int idx_ipv4_number = 1;
1276 0 : struct ospf6_area *area;
1277 :
1278 0 : VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1279 :
1280 0 : OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
1281 :
1282 0 : if (!ospf6_area_stub_set(ospf6, area)) {
1283 0 : vty_out(vty,
1284 : "First deconfigure all virtual link through this area\n");
1285 0 : return CMD_WARNING_CONFIG_FAILED;
1286 : }
1287 :
1288 0 : ospf6_area_no_summary_unset(ospf6, area);
1289 :
1290 0 : return CMD_SUCCESS;
1291 : }
1292 :
1293 0 : DEFUN (ospf6_area_stub_no_summary,
1294 : ospf6_area_stub_no_summary_cmd,
1295 : "area <A.B.C.D|(0-4294967295)> stub no-summary",
1296 : "OSPF6 stub parameters\n"
1297 : "OSPF6 area ID in IP address format\n"
1298 : "OSPF6 area ID as a decimal value\n"
1299 : "Configure OSPF6 area as stub\n"
1300 : "Do not inject inter-area routes into stub\n")
1301 : {
1302 0 : int idx_ipv4_number = 1;
1303 0 : struct ospf6_area *area;
1304 :
1305 0 : VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1306 :
1307 0 : OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
1308 :
1309 0 : if (!ospf6_area_stub_set(ospf6, area)) {
1310 0 : vty_out(vty,
1311 : "First deconfigure all virtual link through this area\n");
1312 0 : return CMD_WARNING_CONFIG_FAILED;
1313 : }
1314 :
1315 0 : ospf6_area_no_summary_set(ospf6, area);
1316 :
1317 0 : return CMD_SUCCESS;
1318 : }
1319 :
1320 0 : DEFUN (no_ospf6_area_stub,
1321 : no_ospf6_area_stub_cmd,
1322 : "no area <A.B.C.D|(0-4294967295)> stub",
1323 : NO_STR
1324 : "OSPF6 area parameters\n"
1325 : "OSPF6 area ID in IP address format\n"
1326 : "OSPF6 area ID as a decimal value\n"
1327 : "Configure OSPF6 area as stub\n")
1328 : {
1329 0 : int idx_ipv4_number = 2;
1330 0 : struct ospf6_area *area;
1331 :
1332 0 : VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1333 :
1334 0 : OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
1335 :
1336 0 : ospf6_area_stub_unset(ospf6, area);
1337 0 : ospf6_area_no_summary_unset(ospf6, area);
1338 :
1339 0 : return CMD_SUCCESS;
1340 : }
1341 :
1342 0 : DEFUN (no_ospf6_area_stub_no_summary,
1343 : no_ospf6_area_stub_no_summary_cmd,
1344 : "no area <A.B.C.D|(0-4294967295)> stub no-summary",
1345 : NO_STR
1346 : "OSPF6 area parameters\n"
1347 : "OSPF6 area ID in IP address format\n"
1348 : "OSPF6 area ID as a decimal value\n"
1349 : "Configure OSPF6 area as stub\n"
1350 : "Do not inject inter-area routes into area\n")
1351 : {
1352 0 : int idx_ipv4_number = 2;
1353 0 : struct ospf6_area *area;
1354 :
1355 0 : VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1356 :
1357 0 : OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
1358 :
1359 0 : ospf6_area_stub_unset(ospf6, area);
1360 0 : ospf6_area_no_summary_unset(ospf6, area);
1361 :
1362 0 : return CMD_SUCCESS;
1363 : }
1364 :
1365 0 : DEFPY(ospf6_area_nssa, ospf6_area_nssa_cmd,
1366 : "area <A.B.C.D|(0-4294967295)>$area_str nssa\
1367 : [{\
1368 : default-information-originate$dflt_originate [{metric (0-16777214)$mval|metric-type (1-2)$mtype}]\
1369 : |no-summary$no_summary\
1370 : }]",
1371 : "OSPF6 area parameters\n"
1372 : "OSPF6 area ID in IP address format\n"
1373 : "OSPF6 area ID as a decimal value\n"
1374 : "Configure OSPF6 area as nssa\n"
1375 : "Originate Type 7 default into NSSA area\n"
1376 : "OSPFv3 default metric\n"
1377 : "OSPFv3 metric\n"
1378 : "OSPFv3 metric type for default routes\n"
1379 : "Set OSPFv3 External Type 1/2 metrics\n"
1380 : "Do not inject inter-area routes into area\n")
1381 : {
1382 0 : struct ospf6_area *area;
1383 :
1384 0 : VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1385 0 : OSPF6_CMD_AREA_GET(area_str, area, ospf6);
1386 :
1387 0 : if (!ospf6_area_nssa_set(ospf6, area)) {
1388 0 : vty_out(vty,
1389 : "First deconfigure all virtual link through this area\n");
1390 0 : return CMD_WARNING_CONFIG_FAILED;
1391 : }
1392 :
1393 0 : if (dflt_originate) {
1394 0 : if (mval_str == NULL)
1395 0 : mval = -1;
1396 0 : if (mtype_str == NULL)
1397 0 : mtype = DEFAULT_METRIC_TYPE;
1398 0 : ospf6_nssa_default_originate_set(ospf6, area, mval, mtype);
1399 : } else
1400 0 : ospf6_nssa_default_originate_unset(ospf6, area);
1401 :
1402 0 : if (no_summary)
1403 0 : ospf6_area_no_summary_set(ospf6, area);
1404 : else
1405 0 : ospf6_area_no_summary_unset(ospf6, area);
1406 :
1407 0 : if (ospf6_check_and_set_router_abr(ospf6)) {
1408 0 : ospf6_abr_defaults_to_stub(ospf6);
1409 0 : ospf6_abr_nssa_type_7_defaults(ospf6);
1410 : }
1411 :
1412 : return CMD_SUCCESS;
1413 : }
1414 :
1415 0 : DEFPY(no_ospf6_area_nssa, no_ospf6_area_nssa_cmd,
1416 : "no area <A.B.C.D|(0-4294967295)>$area_str nssa\
1417 : [{\
1418 : default-information-originate [{metric (0-16777214)|metric-type (1-2)}]\
1419 : |no-summary\
1420 : }]",
1421 : NO_STR
1422 : "OSPF6 area parameters\n"
1423 : "OSPF6 area ID in IP address format\n"
1424 : "OSPF6 area ID as a decimal value\n"
1425 : "Configure OSPF6 area as nssa\n"
1426 : "Originate Type 7 default into NSSA area\n"
1427 : "OSPFv3 default metric\n"
1428 : "OSPFv3 metric\n"
1429 : "OSPFv3 metric type for default routes\n"
1430 : "Set OSPFv3 External Type 1/2 metrics\n"
1431 : "Do not inject inter-area routes into area\n")
1432 : {
1433 0 : struct ospf6_area *area;
1434 :
1435 0 : VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1436 0 : OSPF6_CMD_AREA_GET(area_str, area, ospf6);
1437 :
1438 0 : ospf6_area_nssa_unset(ospf6, area);
1439 0 : ospf6_area_no_summary_unset(ospf6, area);
1440 0 : ospf6_nssa_default_originate_unset(ospf6, area);
1441 :
1442 0 : return CMD_SUCCESS;
1443 : }
1444 :
1445 :
1446 16 : void ospf6_area_init(void)
1447 : {
1448 16 : install_element(VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd);
1449 16 : install_element(VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
1450 16 : install_element(VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
1451 :
1452 16 : install_element(OSPF6_NODE, &area_range_cmd);
1453 16 : install_element(OSPF6_NODE, &no_area_range_cmd);
1454 16 : install_element(OSPF6_NODE, &ospf6_area_stub_no_summary_cmd);
1455 16 : install_element(OSPF6_NODE, &ospf6_area_stub_cmd);
1456 16 : install_element(OSPF6_NODE, &no_ospf6_area_stub_no_summary_cmd);
1457 16 : install_element(OSPF6_NODE, &no_ospf6_area_stub_cmd);
1458 :
1459 :
1460 16 : install_element(OSPF6_NODE, &area_import_list_cmd);
1461 16 : install_element(OSPF6_NODE, &no_area_import_list_cmd);
1462 16 : install_element(OSPF6_NODE, &area_export_list_cmd);
1463 16 : install_element(OSPF6_NODE, &no_area_export_list_cmd);
1464 :
1465 16 : install_element(OSPF6_NODE, &area_filter_list_cmd);
1466 16 : install_element(OSPF6_NODE, &no_area_filter_list_cmd);
1467 :
1468 : /* "area nssa" commands. */
1469 16 : install_element(OSPF6_NODE, &ospf6_area_nssa_cmd);
1470 16 : install_element(OSPF6_NODE, &no_ospf6_area_nssa_cmd);
1471 16 : }
1472 :
1473 29 : void ospf6_area_interface_delete(struct ospf6_interface *oi)
1474 : {
1475 29 : struct ospf6_area *oa;
1476 29 : struct listnode *node, *nnode;
1477 29 : struct ospf6 *ospf6;
1478 :
1479 58 : for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
1480 0 : for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
1481 0 : if (listnode_lookup(oa->if_list, oi))
1482 0 : listnode_delete(oa->if_list, oi);
1483 : }
1484 29 : }
|