back to topotato report
topotato coverage report
Current view: top level - ospf6d - ospf6_area.c (source / functions) Hit Total Coverage
Test: test_ospf_topo1.py::OSPFTopo1Test Lines: 169 753 22.4 %
Date: 2023-02-24 18:38:32 Functions: 16 50 32.0 %

          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          12 : DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AREA,      "OSPF6 area");
      56          12 : DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PLISTNAME, "Prefix list name");
      57             : 
      58           9 : int str2area_id(const char *str, uint32_t *area_id, int *area_id_fmt)
      59             : {
      60           9 :         char *ep;
      61             : 
      62           9 :         *area_id = htonl(strtoul(str, &ep, 10));
      63           9 :         if (*ep && inet_pton(AF_INET, str, area_id) != 1)
      64             :                 return -1;
      65             : 
      66          18 :         *area_id_fmt =
      67           9 :                 !*ep ? OSPF6_AREA_FMT_DECIMAL : OSPF6_AREA_FMT_DOTTEDQUAD;
      68             : 
      69           9 :         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           1 : int ospf6_area_cmp(void *va, void *vb)
      81             : {
      82           1 :         struct ospf6_area *oa = (struct ospf6_area *)va;
      83           1 :         struct ospf6_area *ob = (struct ospf6_area *)vb;
      84           1 :         return (ntohl(oa->area_id) < ntohl(ob->area_id) ? -1 : 1);
      85             : }
      86             : 
      87             : /* schedule routing table recalculation */
      88          96 : static void ospf6_area_lsdb_hook_add(struct ospf6_lsa *lsa)
      89             : {
      90          96 :         switch (ntohs(lsa->header->type)) {
      91             : 
      92          45 :         case OSPF6_LSTYPE_ROUTER:
      93             :         case OSPF6_LSTYPE_NETWORK:
      94          45 :                 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          45 :                 ospf6_spf_schedule(
     100          45 :                         OSPF6_PROCESS(OSPF6_AREA(lsa->lsdb->data)->ospf6),
     101             :                         ospf6_lsadd_to_spf_reason(lsa));
     102          45 :                 break;
     103             : 
     104          32 :         case OSPF6_LSTYPE_INTRA_PREFIX:
     105          32 :                 ospf6_intra_prefix_lsa_add(lsa);
     106          32 :                 break;
     107             : 
     108          19 :         case OSPF6_LSTYPE_INTER_PREFIX:
     109             :         case OSPF6_LSTYPE_INTER_ROUTER:
     110          19 :                 ospf6_abr_examin_summary(lsa,
     111          19 :                                          (struct ospf6_area *)lsa->lsdb->data);
     112          19 :                 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          96 : }
     122             : 
     123         105 : static void ospf6_area_lsdb_hook_remove(struct ospf6_lsa *lsa)
     124             : {
     125         105 :         switch (ntohs(lsa->header->type)) {
     126          45 :         case OSPF6_LSTYPE_ROUTER:
     127             :         case OSPF6_LSTYPE_NETWORK:
     128          45 :                 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          45 :                 ospf6_spf_schedule(
     134          45 :                         OSPF6_PROCESS(OSPF6_AREA(lsa->lsdb->data)->ospf6),
     135             :                         ospf6_lsremove_to_spf_reason(lsa));
     136          45 :                 break;
     137             : 
     138          27 :         case OSPF6_LSTYPE_INTRA_PREFIX:
     139          27 :                 ospf6_intra_prefix_lsa_remove(lsa);
     140          27 :                 break;
     141             : 
     142          33 :         case OSPF6_LSTYPE_INTER_PREFIX:
     143             :         case OSPF6_LSTYPE_INTER_ROUTER:
     144          33 :                 ospf6_abr_examin_summary(lsa,
     145          33 :                                          (struct ospf6_area *)lsa->lsdb->data);
     146          33 :                 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         105 : }
     154             : 
     155          85 : static void ospf6_area_route_hook_add(struct ospf6_route *route)
     156             : {
     157          85 :         struct ospf6_area *oa = route->table->scope;
     158          85 :         struct ospf6 *ospf6 = oa->ospf6;
     159          85 :         struct ospf6_route *copy;
     160             : 
     161          85 :         copy = ospf6_route_copy(route);
     162          85 :         ospf6_route_add(copy, ospf6->route_table);
     163          85 : }
     164             : 
     165          21 : static void ospf6_area_route_hook_remove(struct ospf6_route *route)
     166             : {
     167          21 :         struct ospf6_area *oa = route->table->scope;
     168          21 :         struct ospf6 *ospf6 = oa->ospf6;
     169          21 :         struct ospf6_route *copy;
     170             : 
     171          21 :         copy = ospf6_route_lookup_identical(route, ospf6->route_table);
     172          21 :         if (copy)
     173          21 :                 ospf6_route_remove(copy, ospf6->route_table);
     174          21 : }
     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           5 : struct ospf6_area *ospf6_area_create(uint32_t area_id, struct ospf6 *o, int df)
     277             : {
     278           5 :         struct ospf6_area *oa;
     279             : 
     280           5 :         oa = XCALLOC(MTYPE_OSPF6_AREA, sizeof(struct ospf6_area));
     281             : 
     282           5 :         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           5 :         default:
     287             :         case OSPF6_AREA_FMT_DOTTEDQUAD:
     288           5 :                 inet_ntop(AF_INET, &area_id, oa->name, sizeof(oa->name));
     289           5 :                 break;
     290             :         }
     291             : 
     292           5 :         oa->area_id = area_id;
     293           5 :         oa->if_list = list_new();
     294             : 
     295           5 :         ospf6_vlink_area_init(oa);
     296             : 
     297           5 :         oa->lsdb = ospf6_lsdb_create(oa);
     298           5 :         oa->lsdb->hook_add = ospf6_area_lsdb_hook_add;
     299           5 :         oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove;
     300           5 :         oa->lsdb_self = ospf6_lsdb_create(oa);
     301           5 :         oa->temp_router_lsa_lsdb = ospf6_lsdb_create(oa);
     302             : 
     303           5 :         oa->spf_table = OSPF6_ROUTE_TABLE_CREATE(AREA, SPF_RESULTS);
     304           5 :         oa->spf_table->scope = oa;
     305           5 :         oa->route_table = OSPF6_ROUTE_TABLE_CREATE(AREA, ROUTES);
     306           5 :         oa->route_table->scope = oa;
     307           5 :         oa->route_table->hook_add = ospf6_area_route_hook_add;
     308           5 :         oa->route_table->hook_remove = ospf6_area_route_hook_remove;
     309             : 
     310           5 :         oa->range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
     311           5 :         oa->range_table->scope = oa;
     312           5 :         oa->nssa_range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
     313           5 :         oa->nssa_range_table->scope = oa;
     314           5 :         oa->summary_prefix = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_PREFIXES);
     315           5 :         oa->summary_prefix->scope = oa;
     316           5 :         oa->summary_router = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_ROUTERS);
     317           5 :         oa->summary_router->scope = oa;
     318           5 :         oa->router_lsa_size_limit = 1024 + 256;
     319             : 
     320             :         /* set default options */
     321           5 :         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           5 :                 OSPF6_OPT_SET(oa->options, OSPF6_OPT_V6);
     326           5 :                 OSPF6_OPT_SET(oa->options, OSPF6_OPT_R);
     327             :         }
     328             : 
     329           5 :         OSPF6_OPT_SET(oa->options, OSPF6_OPT_E);
     330             : 
     331           5 :         SET_FLAG(oa->flag, OSPF6_AREA_ACTIVE);
     332           5 :         SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
     333             : 
     334           5 :         oa->ospf6 = o;
     335           5 :         listnode_add_sort(o->area_list, oa);
     336             : 
     337           5 :         if (area_id == OSPF_AREA_BACKBONE) {
     338           3 :                 o->backbone = oa;
     339             :         }
     340             : 
     341           5 :         return oa;
     342             : }
     343             : 
     344           5 : void ospf6_area_delete(struct ospf6_area *oa)
     345             : {
     346           5 :         struct listnode *n;
     347           5 :         struct ospf6_interface *oi;
     348             : 
     349           5 :         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          19 :         for (ALL_LIST_ELEMENTS_RO(oa->if_list, n, oi)) {
     357           9 :                 oi->area = NULL;
     358             : 
     359           9 :                 struct listnode *node;
     360           9 :                 struct listnode *nnode;
     361           9 :                 struct ospf6_neighbor *on;
     362             : 
     363          18 :                 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
     364           0 :                         ospf6_neighbor_delete(on);
     365             :         }
     366             : 
     367           5 :         list_delete(&oa->if_list);
     368             : 
     369           5 :         ospf6_lsdb_delete(oa->lsdb);
     370           5 :         ospf6_lsdb_delete(oa->lsdb_self);
     371           5 :         ospf6_lsdb_delete(oa->temp_router_lsa_lsdb);
     372             : 
     373           5 :         ospf6_spf_table_finish(oa->spf_table);
     374           5 :         ospf6_route_table_delete(oa->spf_table);
     375           5 :         ospf6_route_table_delete(oa->route_table);
     376             : 
     377           5 :         ospf6_route_table_delete(oa->range_table);
     378           5 :         ospf6_route_table_delete(oa->nssa_range_table);
     379           5 :         ospf6_route_table_delete(oa->summary_prefix);
     380           5 :         ospf6_route_table_delete(oa->summary_router);
     381             : 
     382           5 :         listnode_delete(oa->ospf6->area_list, oa);
     383           5 :         oa->ospf6 = NULL;
     384             : 
     385             :         /* free area */
     386           5 :         XFREE(MTYPE_OSPF6_AREA, oa);
     387           5 : }
     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         392 : struct ospf6_area *ospf6_area_lookup(uint32_t area_id, struct ospf6 *ospf6)
     404             : {
     405         392 :         struct ospf6_area *oa;
     406         392 :         struct listnode *n;
     407             : 
     408         817 :         for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa))
     409         420 :                 if (oa->area_id == area_id)
     410         387 :                         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           5 : void ospf6_area_disable(struct ospf6_area *oa)
     428             : {
     429           5 :         struct listnode *node, *nnode;
     430           5 :         struct ospf6_interface *oi;
     431             : 
     432           5 :         UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
     433             : 
     434          19 :         for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
     435           9 :                 ospf6_interface_disable(oi);
     436             : 
     437           5 :         ospf6_abr_disable_area(oa);
     438           5 :         ospf6_lsdb_remove_all(oa->lsdb);
     439           5 :         ospf6_lsdb_remove_all(oa->lsdb_self);
     440             : 
     441           5 :         ospf6_spf_table_finish(oa->spf_table);
     442           5 :         ospf6_route_remove_all(oa->route_table);
     443             : 
     444           5 :         THREAD_OFF(oa->thread_router_lsa);
     445           5 :         THREAD_OFF(oa->thread_intra_prefix_lsa);
     446           5 : }
     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           4 : void ospf6_area_init(void)
    1447             : {
    1448           4 :         install_element(VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd);
    1449           4 :         install_element(VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
    1450           4 :         install_element(VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
    1451             : 
    1452           4 :         install_element(OSPF6_NODE, &area_range_cmd);
    1453           4 :         install_element(OSPF6_NODE, &no_area_range_cmd);
    1454           4 :         install_element(OSPF6_NODE, &ospf6_area_stub_no_summary_cmd);
    1455           4 :         install_element(OSPF6_NODE, &ospf6_area_stub_cmd);
    1456           4 :         install_element(OSPF6_NODE, &no_ospf6_area_stub_no_summary_cmd);
    1457           4 :         install_element(OSPF6_NODE, &no_ospf6_area_stub_cmd);
    1458             : 
    1459             : 
    1460           4 :         install_element(OSPF6_NODE, &area_import_list_cmd);
    1461           4 :         install_element(OSPF6_NODE, &no_area_import_list_cmd);
    1462           4 :         install_element(OSPF6_NODE, &area_export_list_cmd);
    1463           4 :         install_element(OSPF6_NODE, &no_area_export_list_cmd);
    1464             : 
    1465           4 :         install_element(OSPF6_NODE, &area_filter_list_cmd);
    1466           4 :         install_element(OSPF6_NODE, &no_area_filter_list_cmd);
    1467             : 
    1468             :         /* "area nssa" commands. */
    1469           4 :         install_element(OSPF6_NODE, &ospf6_area_nssa_cmd);
    1470           4 :         install_element(OSPF6_NODE, &no_ospf6_area_nssa_cmd);
    1471           4 : }
    1472             : 
    1473           9 : void ospf6_area_interface_delete(struct ospf6_interface *oi)
    1474             : {
    1475           9 :         struct ospf6_area *oa;
    1476           9 :         struct listnode *node, *nnode;
    1477           9 :         struct ospf6 *ospf6;
    1478             : 
    1479          18 :         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           9 : }

Generated by: LCOV version v1.16-topotato