back to topotato report
topotato coverage report
Current view: top level - ospf6d - ospf6_top.c (source / functions) Hit Total Coverage
Test: test_ospf6_p2xp.py::PtMPBasic Lines: 300 1160 25.9 %
Date: 2023-02-24 18:38:14 Functions: 26 79 32.9 %

          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 "vty.h"
      26             : #include "linklist.h"
      27             : #include "prefix.h"
      28             : #include "table.h"
      29             : #include "thread.h"
      30             : #include "command.h"
      31             : #include "defaults.h"
      32             : #include "lib/json.h"
      33             : #include "lib_errors.h"
      34             : 
      35             : #include "ospf6_proto.h"
      36             : #include "ospf6_message.h"
      37             : #include "ospf6_lsa.h"
      38             : #include "ospf6_lsdb.h"
      39             : #include "ospf6_route.h"
      40             : #include "ospf6_zebra.h"
      41             : 
      42             : #include "ospf6_top.h"
      43             : #include "ospf6_area.h"
      44             : #include "ospf6_interface.h"
      45             : #include "ospf6_neighbor.h"
      46             : #include "ospf6_network.h"
      47             : 
      48             : #include "ospf6_flood.h"
      49             : #include "ospf6_asbr.h"
      50             : #include "ospf6_abr.h"
      51             : #include "ospf6_intra.h"
      52             : #include "ospf6_spf.h"
      53             : #include "ospf6d.h"
      54             : #include "ospf6_gr.h"
      55             : #include "lib/json.h"
      56             : #include "ospf6_nssa.h"
      57             : #include "ospf6_auth_trailer.h"
      58             : 
      59          12 : DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_TOP, "OSPF6 top");
      60             : 
      61             : DEFINE_QOBJ_TYPE(ospf6);
      62             : 
      63           4 : FRR_CFG_DEFAULT_BOOL(OSPF6_LOG_ADJACENCY_CHANGES,
      64             :         { .val_bool = true, .match_profile = "datacenter", },
      65             :         { .val_bool = false },
      66             : );
      67             : 
      68             : #include "ospf6d/ospf6_top_clippy.c"
      69             : 
      70             : /* global ospf6d variable */
      71             : static struct ospf6_master ospf6_master;
      72             : struct ospf6_master *om6;
      73             : 
      74             : static void ospf6_disable(struct ospf6 *o);
      75             : 
      76           4 : static void ospf6_add(struct ospf6 *ospf6)
      77             : {
      78           4 :         listnode_add(om6->ospf6, ospf6);
      79             : }
      80             : 
      81           4 : static void ospf6_del(struct ospf6 *ospf6)
      82             : {
      83           4 :         listnode_delete(om6->ospf6, ospf6);
      84             : }
      85             : 
      86           0 : const char *ospf6_vrf_id_to_name(vrf_id_t vrf_id)
      87             : {
      88           0 :         struct vrf *vrf = vrf_lookup_by_id(vrf_id);
      89             : 
      90           0 :         return vrf ? vrf->name : "NIL";
      91             : }
      92             : 
      93             : /* Link OSPF instance to VRF. */
      94           4 : void ospf6_vrf_link(struct ospf6 *ospf6, struct vrf *vrf)
      95             : {
      96           4 :         ospf6->vrf_id = vrf->vrf_id;
      97           0 :         if (vrf->info != (void *)ospf6)
      98           4 :                 vrf->info = (void *)ospf6;
      99           0 : }
     100             : 
     101             : /* Unlink OSPF instance from VRF. */
     102           4 : void ospf6_vrf_unlink(struct ospf6 *ospf6, struct vrf *vrf)
     103             : {
     104           0 :         if (vrf->info == (void *)ospf6)
     105           4 :                 vrf->info = NULL;
     106           4 :         ospf6->vrf_id = VRF_UNKNOWN;
     107           4 : }
     108             : 
     109           8 : struct ospf6 *ospf6_lookup_by_vrf_id(vrf_id_t vrf_id)
     110             : {
     111           8 :         struct vrf *vrf = NULL;
     112             : 
     113           8 :         vrf = vrf_lookup_by_id(vrf_id);
     114           8 :         if (!vrf)
     115             :                 return NULL;
     116           8 :         return (vrf->info) ? (struct ospf6 *)vrf->info : NULL;
     117             : }
     118             : 
     119           8 : struct ospf6 *ospf6_lookup_by_vrf_name(const char *name)
     120             : {
     121           8 :         struct ospf6 *o = NULL;
     122           8 :         struct listnode *node, *nnode;
     123             : 
     124          16 :         for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, o)) {
     125           0 :                 if (((o->name == NULL && name == NULL)
     126           0 :                      || (o->name && name && strcmp(o->name, name) == 0)))
     127           0 :                         return o;
     128             :         }
     129             :         return NULL;
     130             : }
     131             : 
     132             : /* This is hook function for vrf create called as part of vrf_init */
     133           4 : static int ospf6_vrf_new(struct vrf *vrf)
     134             : {
     135           4 :         return 0;
     136             : }
     137             : 
     138             : /* This is hook function for vrf delete call as part of vrf_init */
     139           4 : static int ospf6_vrf_delete(struct vrf *vrf)
     140             : {
     141           4 :         return 0;
     142             : }
     143             : 
     144           0 : static void ospf6_set_redist_vrf_bitmaps(struct ospf6 *ospf6, bool set)
     145             : {
     146           0 :         int type;
     147           0 :         struct list *red_list;
     148             : 
     149           0 :         for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
     150           0 :                 red_list = ospf6->redist[type];
     151           0 :                 if (!red_list)
     152           0 :                         continue;
     153           0 :                 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
     154           0 :                         zlog_debug(
     155             :                                 "%s: setting redist vrf %d bitmap for type %d",
     156             :                                 __func__, ospf6->vrf_id, type);
     157           0 :                 if (set)
     158           0 :                         vrf_bitmap_set(zclient->redist[AFI_IP6][type],
     159             :                                        ospf6->vrf_id);
     160             :                 else
     161           0 :                         vrf_bitmap_unset(zclient->redist[AFI_IP6][type],
     162             :                                          ospf6->vrf_id);
     163             :         }
     164             : 
     165           0 :         red_list = ospf6->redist[DEFAULT_ROUTE];
     166           0 :         if (red_list) {
     167           0 :                 if (set)
     168           0 :                         vrf_bitmap_set(zclient->default_information[AFI_IP6],
     169             :                                        ospf6->vrf_id);
     170             :                 else
     171           0 :                         vrf_bitmap_unset(zclient->default_information[AFI_IP6],
     172             :                                          ospf6->vrf_id);
     173             :         }
     174           0 : }
     175             : 
     176             : /* Disable OSPF6 VRF instance */
     177           4 : static int ospf6_vrf_disable(struct vrf *vrf)
     178             : {
     179           4 :         struct ospf6 *ospf6 = NULL;
     180             : 
     181           4 :         if (vrf->vrf_id == VRF_DEFAULT)
     182             :                 return 0;
     183             : 
     184           0 :         ospf6 = ospf6_lookup_by_vrf_name(vrf->name);
     185           0 :         if (ospf6) {
     186           0 :                 ospf6_zebra_vrf_deregister(ospf6);
     187             : 
     188           0 :                 ospf6_set_redist_vrf_bitmaps(ospf6, false);
     189             : 
     190             :                 /* We have instance configured, unlink
     191             :                  * from VRF and make it "down".
     192             :                  */
     193           0 :                 ospf6_vrf_unlink(ospf6, vrf);
     194           0 :                 thread_cancel(&ospf6->t_ospf6_receive);
     195           0 :                 close(ospf6->fd);
     196           0 :                 ospf6->fd = -1;
     197             :         }
     198             : 
     199             :         /* Note: This is a callback, the VRF will be deleted by the caller. */
     200             :         return 0;
     201             : }
     202             : 
     203             : /* Enable OSPF6 VRF instance */
     204           4 : static int ospf6_vrf_enable(struct vrf *vrf)
     205             : {
     206           4 :         struct ospf6 *ospf6 = NULL;
     207           4 :         vrf_id_t old_vrf_id;
     208           4 :         int ret = 0;
     209             : 
     210           4 :         ospf6 = ospf6_lookup_by_vrf_name(vrf->name);
     211           4 :         if (ospf6) {
     212           0 :                 old_vrf_id = ospf6->vrf_id;
     213             :                 /* We have instance configured, link to VRF and make it "up". */
     214           0 :                 ospf6_vrf_link(ospf6, vrf);
     215             : 
     216           0 :                 if (old_vrf_id != ospf6->vrf_id) {
     217           0 :                         ospf6_set_redist_vrf_bitmaps(ospf6, true);
     218             : 
     219             :                         /* start zebra redist to us for new vrf */
     220           0 :                         ospf6_zebra_vrf_register(ospf6);
     221             : 
     222           0 :                         ret = ospf6_serv_sock(ospf6);
     223           0 :                         if (ret < 0 || ospf6->fd <= 0)
     224             :                                 return 0;
     225           0 :                         thread_add_read(master, ospf6_receive, ospf6, ospf6->fd,
     226             :                                         &ospf6->t_ospf6_receive);
     227             : 
     228           0 :                         ospf6_router_id_update(ospf6, true);
     229             :                 }
     230             :         }
     231             : 
     232             :         return 0;
     233             : }
     234             : 
     235           4 : void ospf6_vrf_init(void)
     236             : {
     237           4 :         vrf_init(ospf6_vrf_new, ospf6_vrf_enable, ospf6_vrf_disable,
     238             :                  ospf6_vrf_delete);
     239             : 
     240           4 :         vrf_cmd_init(NULL);
     241           4 : }
     242             : 
     243           0 : static void ospf6_top_lsdb_hook_add(struct ospf6_lsa *lsa)
     244             : {
     245           0 :         switch (ntohs(lsa->header->type)) {
     246           0 :         case OSPF6_LSTYPE_AS_EXTERNAL:
     247           0 :                 ospf6_asbr_lsa_add(lsa);
     248           0 :                 break;
     249             : 
     250             :         default:
     251             :                 break;
     252             :         }
     253           0 : }
     254             : 
     255           0 : static void ospf6_top_lsdb_hook_remove(struct ospf6_lsa *lsa)
     256             : {
     257           0 :         switch (ntohs(lsa->header->type)) {
     258           0 :         case OSPF6_LSTYPE_AS_EXTERNAL:
     259           0 :                 ospf6_asbr_lsa_remove(lsa, NULL);
     260           0 :                 break;
     261             : 
     262             :         default:
     263             :                 break;
     264             :         }
     265           0 : }
     266             : 
     267          30 : static void ospf6_top_route_hook_add(struct ospf6_route *route)
     268             : {
     269          30 :         struct ospf6 *ospf6 = NULL;
     270          30 :         struct ospf6_area *oa = NULL;
     271             : 
     272          30 :         if (route->table->scope_type == OSPF6_SCOPE_TYPE_GLOBAL)
     273          30 :                 ospf6 = route->table->scope;
     274           0 :         else if (route->table->scope_type == OSPF6_SCOPE_TYPE_AREA) {
     275           0 :                 oa = (struct ospf6_area *)route->table->scope;
     276           0 :                 ospf6 = oa->ospf6;
     277             :         } else {
     278           0 :                 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)
     279           0 :                     || IS_OSPF6_DEBUG_BROUTER)
     280           0 :                         zlog_debug(
     281             :                                 "%s: Route is not GLOBAL or scope is not of TYPE_AREA: %pFX",
     282             :                                 __func__, &route->prefix);
     283           0 :                 return;
     284             :         }
     285             : 
     286          30 :         ospf6_abr_originate_summary(route, ospf6);
     287          30 :         ospf6_zebra_route_update_add(route, ospf6);
     288             : }
     289             : 
     290          27 : static void ospf6_top_route_hook_remove(struct ospf6_route *route)
     291             : {
     292          27 :         struct ospf6 *ospf6 = NULL;
     293          27 :         struct ospf6_area *oa = NULL;
     294             : 
     295          27 :         if (route->table->scope_type == OSPF6_SCOPE_TYPE_GLOBAL)
     296          27 :                 ospf6 = route->table->scope;
     297           0 :         else if (route->table->scope_type == OSPF6_SCOPE_TYPE_AREA) {
     298           0 :                 oa = (struct ospf6_area *)route->table->scope;
     299           0 :                 ospf6 = oa->ospf6;
     300             :         } else {
     301           0 :                 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)
     302           0 :                     || IS_OSPF6_DEBUG_BROUTER)
     303           0 :                         zlog_debug(
     304             :                                 "%s: Route is not GLOBAL or scope is not of TYPE_AREA: %pFX",
     305             :                                 __func__, &route->prefix);
     306           0 :                 return;
     307             :         }
     308             : 
     309          27 :         route->flag |= OSPF6_ROUTE_REMOVE;
     310          27 :         ospf6_abr_originate_summary(route, ospf6);
     311          27 :         ospf6_zebra_route_update_remove(route, ospf6);
     312             : }
     313             : 
     314           0 : static void ospf6_top_brouter_hook_add(struct ospf6_route *route)
     315             : {
     316           0 :         struct ospf6 *ospf6 = route->table->scope;
     317             : 
     318           0 :         if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL) ||
     319           0 :             IS_OSPF6_DEBUG_BROUTER) {
     320           0 :                 uint32_t brouter_id;
     321           0 :                 char brouter_name[16];
     322             : 
     323           0 :                 brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
     324           0 :                 inet_ntop(AF_INET, &brouter_id, brouter_name,
     325             :                           sizeof(brouter_name));
     326           0 :                 zlog_debug("%s: brouter %s add with adv router %x nh count %u",
     327             :                            __func__, brouter_name,
     328             :                            route->path.origin.adv_router,
     329             :                            listcount(route->nh_list));
     330             :         }
     331           0 :         ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix), route,
     332             :                                  ospf6);
     333           0 :         ospf6_asbr_lsentry_add(route, ospf6);
     334           0 :         ospf6_abr_originate_summary(route, ospf6);
     335           0 : }
     336             : 
     337           0 : static void ospf6_top_brouter_hook_remove(struct ospf6_route *route)
     338             : {
     339           0 :         struct ospf6 *ospf6 = route->table->scope;
     340             : 
     341           0 :         if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL) ||
     342           0 :             IS_OSPF6_DEBUG_BROUTER) {
     343           0 :                 uint32_t brouter_id;
     344           0 :                 char brouter_name[16];
     345             : 
     346           0 :                 brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
     347           0 :                 inet_ntop(AF_INET, &brouter_id, brouter_name,
     348             :                           sizeof(brouter_name));
     349           0 :                 zlog_debug("%s: brouter %p %s del with adv router %x nh %u",
     350             :                            __func__, (void *)route, brouter_name,
     351             :                            route->path.origin.adv_router,
     352             :                            listcount(route->nh_list));
     353             :         }
     354           0 :         route->flag |= OSPF6_ROUTE_REMOVE;
     355           0 :         ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix), route,
     356             :                                  ospf6);
     357           0 :         ospf6_asbr_lsentry_remove(route, ospf6);
     358           0 :         ospf6_abr_originate_summary(route, ospf6);
     359           0 : }
     360             : 
     361           4 : static struct ospf6 *ospf6_create(const char *name)
     362             : {
     363           4 :         struct ospf6 *o;
     364           4 :         struct vrf *vrf = NULL;
     365             : 
     366           4 :         o = XCALLOC(MTYPE_OSPF6_TOP, sizeof(struct ospf6));
     367             : 
     368           4 :         vrf = vrf_lookup_by_name(name);
     369           4 :         if (vrf) {
     370           4 :                 o->vrf_id = vrf->vrf_id;
     371             :         } else
     372           0 :                 o->vrf_id = VRF_UNKNOWN;
     373             : 
     374             :         /* Freed in ospf6_delete */
     375           4 :         o->name = XSTRDUP(MTYPE_OSPF6_TOP, name);
     376           4 :         if (vrf)
     377           4 :                 ospf6_vrf_link(o, vrf);
     378             : 
     379           4 :         ospf6_zebra_vrf_register(o);
     380             : 
     381             :         /* initialize */
     382           4 :         monotime(&o->starttime);
     383           4 :         o->area_list = list_new();
     384           4 :         o->area_list->cmp = ospf6_area_cmp;
     385           4 :         o->lsdb = ospf6_lsdb_create(o);
     386           4 :         o->lsdb_self = ospf6_lsdb_create(o);
     387           4 :         o->lsdb->hook_add = ospf6_top_lsdb_hook_add;
     388           4 :         o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove;
     389             : 
     390           4 :         o->spf_delay = OSPF_SPF_DELAY_DEFAULT;
     391           4 :         o->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
     392           4 :         o->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
     393           4 :         o->spf_hold_multiplier = 1;
     394             : 
     395           4 :         o->default_originate = DEFAULT_ORIGINATE_NONE;
     396           4 :         o->redistribute = 0;
     397             :         /* LSA timers value init */
     398           4 :         o->lsa_minarrival = OSPF_MIN_LS_ARRIVAL;
     399             : 
     400           4 :         o->route_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, ROUTES);
     401           4 :         o->route_table->scope = o;
     402           4 :         o->route_table->hook_add = ospf6_top_route_hook_add;
     403           4 :         o->route_table->hook_remove = ospf6_top_route_hook_remove;
     404             : 
     405           4 :         o->brouter_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, BORDER_ROUTERS);
     406           4 :         o->brouter_table->scope = o;
     407           4 :         o->brouter_table->hook_add = ospf6_top_brouter_hook_add;
     408           4 :         o->brouter_table->hook_remove = ospf6_top_brouter_hook_remove;
     409             : 
     410           4 :         o->external_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, EXTERNAL_ROUTES);
     411           4 :         o->external_table->scope = o;
     412             :         /* Setting this to 1, so that the LS ID 0 can be considered as invalid
     413             :          * for self originated external LSAs. This helps in differentiating if
     414             :          * an LSA is originated for any route or not in the route data.
     415             :          * rt->route_option->id is by default 0
     416             :          * Consider a route having id as 0 and prefix as 1::1, an external LSA
     417             :          * is originated with ID 0.0.0.0. Now consider another route 2::2
     418             :          * and for this LSA was not originated because of some configuration
     419             :          * but the ID field rt->route_option->id is still 0.Consider now this
     420             :          * 2::2 is being deleted, it will search LSA with LS ID as 0 and it
     421             :          * will find the LSA and hence delete it but the LSA belonged to prefix
     422             :          * 1::1, this happened because of LS ID 0.
     423             :          */
     424           4 :         o->external_id = OSPF6_EXT_INIT_LS_ID;
     425             : 
     426           4 :         o->write_oi_count = OSPF6_WRITE_INTERFACE_COUNT_DEFAULT;
     427           4 :         o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH;
     428             : 
     429           4 :         o->distance_table = route_table_init();
     430             : 
     431           4 :         o->rt_aggr_tbl = route_table_init();
     432           4 :         o->aggr_delay_interval = OSPF6_EXTL_AGGR_DEFAULT_DELAY;
     433           4 :         o->aggr_action = OSPF6_ROUTE_AGGR_NONE;
     434             : 
     435           4 :         o->fd = -1;
     436             : 
     437           4 :         o->max_multipath = MULTIPATH_NUM;
     438             : 
     439           4 :         o->oi_write_q = list_new();
     440             : 
     441           4 :         ospf6_gr_helper_init(o);
     442           4 :         QOBJ_REG(o, ospf6);
     443             : 
     444             :         /* Make ospf protocol socket. */
     445           4 :         ospf6_serv_sock(o);
     446             : 
     447             :         /* If sequence number is stored in persistent storage, read it.
     448             :          */
     449           4 :         if (ospf6_auth_nvm_file_exist() == OSPF6_AUTH_FILE_EXIST) {
     450           0 :                 ospf6_auth_seqno_nvm_read(o);
     451           0 :                 o->seqnum_h = o->seqnum_h + 1;
     452           0 :                 ospf6_auth_seqno_nvm_update(o);
     453             :         } else {
     454           4 :                 o->seqnum_l = o->seqnum_h = 0;
     455           4 :                 ospf6_auth_seqno_nvm_update(o);
     456             :         }
     457             : 
     458           4 :         return o;
     459             : }
     460             : 
     461           4 : struct ospf6 *ospf6_instance_create(const char *name)
     462             : {
     463           4 :         struct ospf6 *ospf6;
     464           4 :         struct vrf *vrf;
     465           4 :         struct interface *ifp;
     466             : 
     467           4 :         ospf6 = ospf6_create(name);
     468           4 :         if (DFLT_OSPF6_LOG_ADJACENCY_CHANGES)
     469           0 :                 SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
     470           4 :         if (ospf6->router_id == 0)
     471           4 :                 ospf6_router_id_update(ospf6, true);
     472           4 :         ospf6_add(ospf6);
     473           4 :         if (ospf6->vrf_id != VRF_UNKNOWN) {
     474           4 :                 vrf = vrf_lookup_by_id(ospf6->vrf_id);
     475          13 :                 FOR_ALL_INTERFACES (vrf, ifp) {
     476           5 :                         if (ifp->info)
     477           5 :                                 ospf6_interface_start(ifp->info);
     478             :                 }
     479             :         }
     480           4 :         if (ospf6->fd < 0)
     481             :                 return ospf6;
     482             : 
     483             :         /*
     484             :          * Read from non-volatile memory whether this instance is performing a
     485             :          * graceful restart or not.
     486             :          */
     487           4 :         ospf6_gr_nvm_read(ospf6);
     488             : 
     489           4 :         thread_add_read(master, ospf6_receive, ospf6, ospf6->fd,
     490             :                         &ospf6->t_ospf6_receive);
     491             : 
     492           4 :         return ospf6;
     493             : }
     494             : 
     495           4 : void ospf6_delete(struct ospf6 *o)
     496             : {
     497           4 :         struct listnode *node, *nnode;
     498           4 :         struct route_node *rn = NULL;
     499           4 :         struct ospf6_area *oa;
     500           4 :         struct vrf *vrf;
     501           4 :         struct ospf6_external_aggr_rt *aggr;
     502             : 
     503           4 :         QOBJ_UNREG(o);
     504             : 
     505           4 :         ospf6_gr_helper_deinit(o);
     506           4 :         if (!o->gr_info.prepare_in_progress)
     507           4 :                 ospf6_flush_self_originated_lsas_now(o);
     508           4 :         ospf6_disable(o);
     509           4 :         ospf6_del(o);
     510             : 
     511           4 :         ospf6_zebra_vrf_deregister(o);
     512             : 
     513           4 :         ospf6_serv_close(&o->fd);
     514             : 
     515          12 :         for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa))
     516           4 :                 ospf6_area_delete(oa);
     517             : 
     518             : 
     519           4 :         list_delete(&o->area_list);
     520             : 
     521           4 :         ospf6_lsdb_delete(o->lsdb);
     522           4 :         ospf6_lsdb_delete(o->lsdb_self);
     523             : 
     524           4 :         ospf6_route_table_delete(o->route_table);
     525           4 :         ospf6_route_table_delete(o->brouter_table);
     526             : 
     527           4 :         ospf6_route_table_delete(o->external_table);
     528             : 
     529           4 :         ospf6_distance_reset(o);
     530           4 :         route_table_finish(o->distance_table);
     531           4 :         list_delete(&o->oi_write_q);
     532             : 
     533           4 :         if (o->vrf_id != VRF_UNKNOWN) {
     534           4 :                 vrf = vrf_lookup_by_id(o->vrf_id);
     535           4 :                 if (vrf)
     536           4 :                         ospf6_vrf_unlink(o, vrf);
     537             :         }
     538             : 
     539           4 :         for (rn = route_top(o->rt_aggr_tbl); rn; rn = route_next(rn))
     540           0 :                 if (rn->info) {
     541           0 :                         aggr = rn->info;
     542           0 :                         ospf6_asbr_summary_config_delete(o, rn);
     543           0 :                         ospf6_external_aggregator_free(aggr);
     544             :                 }
     545           4 :         route_table_finish(o->rt_aggr_tbl);
     546             : 
     547           4 :         XFREE(MTYPE_OSPF6_TOP, o->name);
     548           4 :         XFREE(MTYPE_OSPF6_TOP, o);
     549           4 : }
     550             : 
     551           4 : static void ospf6_disable(struct ospf6 *o)
     552             : {
     553           4 :         struct listnode *node, *nnode;
     554           4 :         struct ospf6_area *oa;
     555             : 
     556           4 :         if (!CHECK_FLAG(o->flag, OSPF6_DISABLED)) {
     557           4 :                 SET_FLAG(o->flag, OSPF6_DISABLED);
     558             : 
     559          12 :                 for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa))
     560           4 :                         ospf6_area_disable(oa);
     561             : 
     562             :                 /* XXX: This also changes persistent settings */
     563             :                 /* Unregister redistribution */
     564           4 :                 ospf6_asbr_redistribute_disable(o);
     565             : 
     566           4 :                 ospf6_lsdb_remove_all(o->lsdb);
     567           4 :                 ospf6_route_remove_all(o->route_table);
     568           4 :                 ospf6_route_remove_all(o->brouter_table);
     569             : 
     570           4 :                 THREAD_OFF(o->maxage_remover);
     571           4 :                 THREAD_OFF(o->t_spf_calc);
     572           4 :                 THREAD_OFF(o->t_ase_calc);
     573           4 :                 THREAD_OFF(o->t_distribute_update);
     574           4 :                 THREAD_OFF(o->t_ospf6_receive);
     575           4 :                 THREAD_OFF(o->t_external_aggr);
     576           4 :                 THREAD_OFF(o->gr_info.t_grace_period);
     577           4 :                 THREAD_OFF(o->t_write);
     578           4 :                 THREAD_OFF(o->t_abr_task);
     579             :         }
     580           4 : }
     581             : 
     582           4 : void ospf6_master_init(struct thread_master *master)
     583             : {
     584           4 :         memset(&ospf6_master, 0, sizeof(ospf6_master));
     585             : 
     586           4 :         om6 = &ospf6_master;
     587           4 :         om6->ospf6 = list_new();
     588           4 :         om6->master = master;
     589           4 : }
     590             : 
     591           0 : static void ospf6_maxage_remover(struct thread *thread)
     592             : {
     593           0 :         struct ospf6 *o = (struct ospf6 *)THREAD_ARG(thread);
     594           0 :         struct ospf6_area *oa;
     595           0 :         struct ospf6_interface *oi;
     596           0 :         struct ospf6_neighbor *on;
     597           0 :         struct listnode *i, *j, *k;
     598           0 :         int reschedule = 0;
     599             : 
     600           0 :         for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) {
     601           0 :                 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) {
     602           0 :                         for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on)) {
     603           0 :                                 if (on->state != OSPF6_NEIGHBOR_EXCHANGE
     604           0 :                                     && on->state != OSPF6_NEIGHBOR_LOADING)
     605           0 :                                         continue;
     606             : 
     607           0 :                                 ospf6_maxage_remove(o);
     608           0 :                                 return;
     609             :                         }
     610             :                 }
     611             :         }
     612             : 
     613           0 :         for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) {
     614           0 :                 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) {
     615             :                         /* virtual links have no LSDB */
     616           0 :                         if (!oi->lsdb)
     617           0 :                                 continue;
     618           0 :                         if (ospf6_lsdb_maxage_remover(oi->lsdb)) {
     619           0 :                                 reschedule = 1;
     620             :                         }
     621             :                 }
     622             : 
     623           0 :                 if (ospf6_lsdb_maxage_remover(oa->lsdb)) {
     624           0 :                         reschedule = 1;
     625             :                 }
     626             :         }
     627             : 
     628           0 :         if (ospf6_lsdb_maxage_remover(o->lsdb)) {
     629             :                 reschedule = 1;
     630             :         }
     631             : 
     632           0 :         if (reschedule) {
     633           0 :                 ospf6_maxage_remove(o);
     634             :         }
     635             : }
     636             : 
     637          31 : void ospf6_maxage_remove(struct ospf6 *o)
     638             : {
     639          31 :         if (o)
     640          31 :                 thread_add_timer(master, ospf6_maxage_remover, o,
     641             :                                  OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT,
     642             :                                  &o->maxage_remover);
     643          31 : }
     644             : 
     645          16 : bool ospf6_router_id_update(struct ospf6 *ospf6, bool init)
     646             : {
     647          16 :         in_addr_t new_router_id;
     648          16 :         struct listnode *node;
     649          16 :         struct ospf6_area *oa;
     650             : 
     651          16 :         if (!ospf6)
     652             :                 return true;
     653             : 
     654          16 :         if (ospf6->router_id_static != 0)
     655             :                 new_router_id = ospf6->router_id_static;
     656             :         else
     657           4 :                 new_router_id = ospf6->router_id_zebra;
     658             : 
     659          16 :         if (ospf6->router_id == new_router_id)
     660             :                 return true;
     661             : 
     662           4 :         if (!init)
     663          12 :                 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
     664           4 :                         if (oa->full_nbrs) {
     665           0 :                                 zlog_err(
     666             :                                         "%s: cannot update router-id. Run the \"clear ipv6 ospf6 process\" command",
     667             :                                         __func__);
     668           0 :                                 return false;
     669             :                         }
     670             :                 }
     671             : 
     672           4 :         ospf6->router_id = new_router_id;
     673           4 :         return true;
     674             : }
     675             : 
     676             : /* start ospf6 */
     677           4 : DEFUN_NOSH(router_ospf6, router_ospf6_cmd, "router ospf6 [vrf NAME]",
     678             :            ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR)
     679             : {
     680           4 :         struct ospf6 *ospf6;
     681           4 :         const char *vrf_name = VRF_DEFAULT_NAME;
     682           4 :         int idx_vrf = 0;
     683             : 
     684           4 :         if (argv_find(argv, argc, "vrf", &idx_vrf)) {
     685           0 :                 vrf_name = argv[idx_vrf + 1]->arg;
     686             :         }
     687             : 
     688           4 :         ospf6 = ospf6_lookup_by_vrf_name(vrf_name);
     689           4 :         if (ospf6 == NULL)
     690           4 :                 ospf6 = ospf6_instance_create(vrf_name);
     691             : 
     692             :         /* set current ospf point. */
     693           4 :         VTY_PUSH_CONTEXT(OSPF6_NODE, ospf6);
     694             : 
     695           4 :         return CMD_SUCCESS;
     696             : }
     697             : 
     698             : /* stop ospf6 */
     699           0 : DEFUN(no_router_ospf6, no_router_ospf6_cmd, "no router ospf6 [vrf NAME]",
     700             :       NO_STR ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR)
     701             : {
     702           0 :         struct ospf6 *ospf6;
     703           0 :         const char *vrf_name = VRF_DEFAULT_NAME;
     704           0 :         int idx_vrf = 0;
     705             : 
     706           0 :         if (argv_find(argv, argc, "vrf", &idx_vrf)) {
     707           0 :                 vrf_name = argv[idx_vrf + 1]->arg;
     708             :         }
     709             : 
     710           0 :         ospf6 = ospf6_lookup_by_vrf_name(vrf_name);
     711           0 :         if (ospf6 == NULL)
     712           0 :                 vty_out(vty, "OSPFv3 is not configured\n");
     713             :         else {
     714           0 :                 ospf6_delete(ospf6);
     715           0 :                 ospf6 = NULL;
     716             :         }
     717             : 
     718             :         /* return to config node . */
     719           0 :         VTY_PUSH_CONTEXT_NULL(CONFIG_NODE);
     720             : 
     721           0 :         return CMD_SUCCESS;
     722             : }
     723             : 
     724           4 : static void ospf6_db_clear(struct ospf6 *ospf6)
     725             : {
     726           4 :         struct ospf6_interface *oi;
     727           4 :         struct interface *ifp;
     728           4 :         struct vrf *vrf = vrf_lookup_by_id(ospf6->vrf_id);
     729           4 :         struct listnode *node, *nnode;
     730           4 :         struct ospf6_area *oa;
     731             : 
     732          13 :         FOR_ALL_INTERFACES (vrf, ifp) {
     733           5 :                 if (if_is_operative(ifp) && ifp->info != NULL) {
     734           0 :                         oi = (struct ospf6_interface *)ifp->info;
     735           0 :                         if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
     736           0 :                                 continue;
     737             : 
     738           0 :                         ospf6_lsdb_remove_all(oi->lsdb);
     739           0 :                         ospf6_lsdb_remove_all(oi->lsdb_self);
     740           0 :                         ospf6_lsdb_remove_all(oi->lsupdate_list);
     741           0 :                         ospf6_lsdb_remove_all(oi->lsack_list);
     742             :                 }
     743             :         }
     744             : 
     745          12 :         for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
     746           4 :                 ospf6_lsdb_remove_all(oa->lsdb);
     747           4 :                 ospf6_lsdb_remove_all(oa->lsdb_self);
     748             : 
     749           4 :                 ospf6_spf_table_finish(oa->spf_table);
     750           4 :                 ospf6_route_remove_all(oa->route_table);
     751             :         }
     752             : 
     753           4 :         ospf6_lsdb_remove_all(ospf6->lsdb);
     754           4 :         ospf6_lsdb_remove_all(ospf6->lsdb_self);
     755           4 :         ospf6_route_remove_all(ospf6->route_table);
     756           4 :         ospf6_route_remove_all(ospf6->brouter_table);
     757           4 : }
     758             : 
     759           4 : static void ospf6_process_reset(struct ospf6 *ospf6)
     760             : {
     761           4 :         struct interface *ifp;
     762           4 :         struct vrf *vrf = vrf_lookup_by_id(ospf6->vrf_id);
     763             : 
     764           4 :         ospf6_unset_all_aggr_flag(ospf6);
     765           4 :         ospf6_flush_self_originated_lsas_now(ospf6);
     766           4 :         ospf6->inst_shutdown = 0;
     767           4 :         ospf6_db_clear(ospf6);
     768             : 
     769           4 :         ospf6_asbr_redistribute_reset(ospf6);
     770          13 :         FOR_ALL_INTERFACES (vrf, ifp)
     771           5 :                 ospf6_interface_clear(ifp);
     772           4 : }
     773             : 
     774           0 : DEFPY (clear_router_ospf6,
     775             :        clear_router_ospf6_cmd,
     776             :        "clear ipv6 ospf6 process [vrf NAME$name]",
     777             :        CLEAR_STR
     778             :        IP6_STR
     779             :        OSPF6_STR
     780             :        "Reset OSPF Process\n"
     781             :        VRF_CMD_HELP_STR)
     782             : {
     783           0 :         struct ospf6 *ospf6;
     784           0 :         const char *vrf_name = VRF_DEFAULT_NAME;
     785             : 
     786           0 :         if (name != NULL)
     787           0 :                 vrf_name = name;
     788             : 
     789           0 :         ospf6 = ospf6_lookup_by_vrf_name(vrf_name);
     790           0 :         if (ospf6 == NULL) {
     791           0 :                 vty_out(vty, "OSPFv3 is not configured\n");
     792             :         } else {
     793           0 :                 ospf6_router_id_update(ospf6, true);
     794           0 :                 ospf6_process_reset(ospf6);
     795             :         }
     796             : 
     797           0 :         return CMD_SUCCESS;
     798             : }
     799             : 
     800             : /* change Router_ID commands. */
     801           4 : DEFUN(ospf6_router_id,
     802             :       ospf6_router_id_cmd,
     803             :       "ospf6 router-id A.B.C.D",
     804             :       OSPF6_STR
     805             :       "Configure OSPF6 Router-ID\n"
     806             :       V4NOTATION_STR)
     807             : {
     808           4 :         VTY_DECLVAR_CONTEXT(ospf6, o);
     809           4 :         int idx = 0;
     810           4 :         int ret;
     811           4 :         const char *router_id_str;
     812           4 :         uint32_t router_id;
     813             : 
     814           4 :         argv_find(argv, argc, "A.B.C.D", &idx);
     815           4 :         router_id_str = argv[idx]->arg;
     816             : 
     817           4 :         ret = inet_pton(AF_INET, router_id_str, &router_id);
     818           4 :         if (ret == 0) {
     819           0 :                 vty_out(vty, "malformed OSPF Router-ID: %s\n", router_id_str);
     820           0 :                 return CMD_SUCCESS;
     821             :         }
     822             : 
     823           4 :         o->router_id_static = router_id;
     824             : 
     825           4 :         if (ospf6_router_id_update(o, false))
     826           4 :                 ospf6_process_reset(o);
     827             :         else
     828           0 :                 vty_out(vty,
     829             :                         "For this router-id change to take effect run the \"clear ipv6 ospf6 process\" command\n");
     830             : 
     831             :         return CMD_SUCCESS;
     832             : }
     833             : 
     834           0 : DEFUN(no_ospf6_router_id,
     835             :       no_ospf6_router_id_cmd,
     836             :       "no ospf6 router-id [A.B.C.D]",
     837             :       NO_STR OSPF6_STR
     838             :       "Configure OSPF6 Router-ID\n"
     839             :       V4NOTATION_STR)
     840             : {
     841           0 :         VTY_DECLVAR_CONTEXT(ospf6, o);
     842             : 
     843           0 :         o->router_id_static = 0;
     844             : 
     845             : 
     846           0 :         if (ospf6_router_id_update(o, false))
     847           0 :                 ospf6_process_reset(o);
     848             :         else
     849           0 :                 vty_out(vty,
     850             :                         "For this router-id change to take effect run the \"clear ipv6 ospf6 process\" command\n");
     851             : 
     852             :         return CMD_SUCCESS;
     853             : }
     854             : 
     855           4 : DEFUN (ospf6_log_adjacency_changes,
     856             :        ospf6_log_adjacency_changes_cmd,
     857             :        "log-adjacency-changes",
     858             :        "Log changes in adjacency state\n")
     859             : {
     860           4 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
     861             : 
     862           4 :         SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
     863           4 :         UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
     864           4 :         return CMD_SUCCESS;
     865             : }
     866             : 
     867           0 : DEFUN (ospf6_log_adjacency_changes_detail,
     868             :        ospf6_log_adjacency_changes_detail_cmd,
     869             :        "log-adjacency-changes detail",
     870             :        "Log changes in adjacency state\n"
     871             :        "Log all state changes\n")
     872             : {
     873           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
     874             : 
     875           0 :         SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
     876           0 :         SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
     877           0 :         return CMD_SUCCESS;
     878             : }
     879             : 
     880           0 : DEFUN (no_ospf6_log_adjacency_changes,
     881             :        no_ospf6_log_adjacency_changes_cmd,
     882             :        "no log-adjacency-changes",
     883             :        NO_STR
     884             :        "Log changes in adjacency state\n")
     885             : {
     886           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
     887             : 
     888           0 :         UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
     889           0 :         UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
     890           0 :         return CMD_SUCCESS;
     891             : }
     892             : 
     893           0 : DEFUN (no_ospf6_log_adjacency_changes_detail,
     894             :        no_ospf6_log_adjacency_changes_detail_cmd,
     895             :        "no log-adjacency-changes detail",
     896             :        NO_STR
     897             :        "Log changes in adjacency state\n"
     898             :        "Log all state changes\n")
     899             : {
     900           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
     901             : 
     902           0 :         UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
     903           0 :         return CMD_SUCCESS;
     904             : }
     905             : 
     906           0 : static void ospf6_reinstall_routes(struct ospf6 *ospf6)
     907             : {
     908           0 :         struct ospf6_route *route;
     909             : 
     910           0 :         for (route = ospf6_route_head(ospf6->route_table); route;
     911           0 :              route = ospf6_route_next(route))
     912           0 :                 ospf6_zebra_route_update_add(route, ospf6);
     913           0 : }
     914             : 
     915           0 : DEFPY (ospf6_send_extra_data,
     916             :        ospf6_send_extra_data_cmd,
     917             :        "[no] ospf6 send-extra-data zebra",
     918             :        NO_STR
     919             :        OSPF6_STR
     920             :        "Extra data to Zebra for display/use\n"
     921             :        "To zebra\n")
     922             : {
     923           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
     924             : 
     925           0 :         if (no
     926           0 :             && CHECK_FLAG(ospf6->config_flags,
     927             :                           OSPF6_SEND_EXTRA_DATA_TO_ZEBRA)) {
     928           0 :                 UNSET_FLAG(ospf6->config_flags, OSPF6_SEND_EXTRA_DATA_TO_ZEBRA);
     929           0 :                 ospf6_reinstall_routes(ospf6);
     930           0 :         } else if (!CHECK_FLAG(ospf6->config_flags,
     931             :                                OSPF6_SEND_EXTRA_DATA_TO_ZEBRA)) {
     932           0 :                 SET_FLAG(ospf6->config_flags, OSPF6_SEND_EXTRA_DATA_TO_ZEBRA);
     933           0 :                 ospf6_reinstall_routes(ospf6);
     934             :         }
     935             : 
     936             :         return CMD_SUCCESS;
     937             : }
     938             : 
     939           0 : DEFUN (ospf6_timers_lsa,
     940             :        ospf6_timers_lsa_cmd,
     941             :        "timers lsa min-arrival (0-600000)",
     942             :        "Adjust routing timers\n"
     943             :        "OSPF6 LSA timers\n"
     944             :        "Minimum delay in receiving new version of a LSA\n"
     945             :        "Delay in milliseconds\n")
     946             : {
     947           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf);
     948           0 :         int idx_number = 3;
     949           0 :         unsigned int minarrival;
     950             : 
     951           0 :         minarrival = strtoul(argv[idx_number]->arg, NULL, 10);
     952           0 :         ospf->lsa_minarrival = minarrival;
     953             : 
     954           0 :         return CMD_SUCCESS;
     955             : }
     956             : 
     957           0 : DEFUN (no_ospf6_timers_lsa,
     958             :        no_ospf6_timers_lsa_cmd,
     959             :        "no timers lsa min-arrival [(0-600000)]",
     960             :        NO_STR
     961             :        "Adjust routing timers\n"
     962             :        "OSPF6 LSA timers\n"
     963             :        "Minimum delay in receiving new version of a LSA\n"
     964             :        "Delay in milliseconds\n")
     965             : {
     966           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf);
     967           0 :         int idx_number = 4;
     968           0 :         unsigned int minarrival;
     969             : 
     970           0 :         if (argc == 5) {
     971           0 :                 minarrival = strtoul(argv[idx_number]->arg, NULL, 10);
     972             : 
     973           0 :                 if (ospf->lsa_minarrival != minarrival
     974           0 :                     || minarrival == OSPF_MIN_LS_ARRIVAL)
     975             :                         return CMD_SUCCESS;
     976             :         }
     977             : 
     978           0 :         ospf->lsa_minarrival = OSPF_MIN_LS_ARRIVAL;
     979             : 
     980           0 :         return CMD_SUCCESS;
     981             : }
     982             : 
     983             : 
     984           0 : DEFUN (ospf6_distance,
     985             :        ospf6_distance_cmd,
     986             :        "distance (1-255)",
     987             :        "Administrative distance\n"
     988             :        "OSPF6 Administrative distance\n")
     989             : {
     990           0 :         VTY_DECLVAR_CONTEXT(ospf6, o);
     991           0 :         uint8_t distance;
     992             : 
     993           0 :         distance = atoi(argv[1]->arg);
     994           0 :         if (o->distance_all != distance) {
     995           0 :                 o->distance_all = distance;
     996           0 :                 ospf6_restart_spf(o);
     997             :         }
     998             : 
     999             :         return CMD_SUCCESS;
    1000             : }
    1001             : 
    1002           0 : DEFUN (no_ospf6_distance,
    1003             :        no_ospf6_distance_cmd,
    1004             :        "no distance (1-255)",
    1005             :        NO_STR
    1006             :        "Administrative distance\n"
    1007             :        "OSPF6 Administrative distance\n")
    1008             : {
    1009           0 :         VTY_DECLVAR_CONTEXT(ospf6, o);
    1010             : 
    1011           0 :         if (o->distance_all) {
    1012           0 :                 o->distance_all = 0;
    1013           0 :                 ospf6_restart_spf(o);
    1014             :         }
    1015             :         return CMD_SUCCESS;
    1016             : }
    1017             : 
    1018           0 : DEFUN (ospf6_distance_ospf6,
    1019             :        ospf6_distance_ospf6_cmd,
    1020             :        "distance ospf6 {intra-area (1-255)|inter-area (1-255)|external (1-255)}",
    1021             :        "Administrative distance\n"
    1022             :        "OSPF6 administrative distance\n"
    1023             :        "Intra-area routes\n"
    1024             :        "Distance for intra-area routes\n"
    1025             :        "Inter-area routes\n"
    1026             :        "Distance for inter-area routes\n"
    1027             :        "External routes\n"
    1028             :        "Distance for external routes\n")
    1029             : {
    1030           0 :         VTY_DECLVAR_CONTEXT(ospf6, o);
    1031           0 :         int idx = 0;
    1032             : 
    1033           0 :         o->distance_intra = 0;
    1034           0 :         o->distance_inter = 0;
    1035           0 :         o->distance_external = 0;
    1036             : 
    1037           0 :         if (argv_find(argv, argc, "intra-area", &idx))
    1038           0 :                 o->distance_intra = atoi(argv[idx + 1]->arg);
    1039           0 :         idx = 0;
    1040           0 :         if (argv_find(argv, argc, "inter-area", &idx))
    1041           0 :                 o->distance_inter = atoi(argv[idx + 1]->arg);
    1042           0 :         idx = 0;
    1043           0 :         if (argv_find(argv, argc, "external", &idx))
    1044           0 :                 o->distance_external = atoi(argv[idx + 1]->arg);
    1045             : 
    1046             :         return CMD_SUCCESS;
    1047             : }
    1048             : 
    1049           0 : DEFUN (no_ospf6_distance_ospf6,
    1050             :        no_ospf6_distance_ospf6_cmd,
    1051             :        "no distance ospf6 [{intra-area [(1-255)]|inter-area [(1-255)]|external [(1-255)]}]",
    1052             :        NO_STR
    1053             :        "Administrative distance\n"
    1054             :        "OSPF6 distance\n"
    1055             :        "Intra-area routes\n"
    1056             :        "Distance for intra-area routes\n"
    1057             :        "Inter-area routes\n"
    1058             :        "Distance for inter-area routes\n"
    1059             :        "External routes\n"
    1060             :        "Distance for external routes\n")
    1061             : {
    1062           0 :         VTY_DECLVAR_CONTEXT(ospf6, o);
    1063           0 :         int idx = 0;
    1064             : 
    1065           0 :         if (argv_find(argv, argc, "intra-area", &idx) || argc == 3)
    1066           0 :                 idx = o->distance_intra = 0;
    1067           0 :         if (argv_find(argv, argc, "inter-area", &idx) || argc == 3)
    1068           0 :                 idx = o->distance_inter = 0;
    1069           0 :         if (argv_find(argv, argc, "external", &idx) || argc == 3)
    1070           0 :                 o->distance_external = 0;
    1071             : 
    1072             :         return CMD_SUCCESS;
    1073             : }
    1074             : 
    1075           0 : DEFUN_HIDDEN (ospf6_interface_area,
    1076             :        ospf6_interface_area_cmd,
    1077             :        "interface IFNAME area <A.B.C.D|(0-4294967295)>",
    1078             :        "Enable routing on an IPv6 interface\n"
    1079             :        IFNAME_STR
    1080             :        "Specify the OSPF6 area ID\n"
    1081             :        "OSPF6 area ID in IPv4 address notation\n"
    1082             :        "OSPF6 area ID in decimal notation\n"
    1083             :       )
    1084             : {
    1085           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
    1086           0 :         int idx_ifname = 1;
    1087           0 :         int idx_ipv4 = 3;
    1088           0 :         struct ospf6_area *oa;
    1089           0 :         struct ospf6_interface *oi;
    1090           0 :         struct interface *ifp;
    1091           0 :         uint32_t area_id;
    1092           0 :         int format;
    1093             : 
    1094           0 :         vty_out(vty,
    1095             :                 "This command is deprecated, because it is not VRF-aware.\n");
    1096           0 :         vty_out(vty,
    1097             :                 "Please, use \"ipv6 ospf6 area\" on an interface instead.\n");
    1098             : 
    1099             :         /* find/create ospf6 interface */
    1100           0 :         ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name);
    1101           0 :         oi = (struct ospf6_interface *)ifp->info;
    1102           0 :         if (oi == NULL)
    1103           0 :                 oi = ospf6_interface_create(ifp);
    1104           0 :         if (oi->area) {
    1105           0 :                 vty_out(vty, "%pOI already attached to Area %s\n", oi,
    1106           0 :                         oi->area->name);
    1107           0 :                 return CMD_SUCCESS;
    1108             :         }
    1109             : 
    1110           0 :         if (str2area_id(argv[idx_ipv4]->arg, &area_id, &format)) {
    1111           0 :                 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
    1112           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1113             :         }
    1114             : 
    1115           0 :         oi->area_id = area_id;
    1116           0 :         oi->area_id_format = format;
    1117             : 
    1118           0 :         oa = ospf6_area_lookup(area_id, ospf6);
    1119           0 :         if (oa == NULL)
    1120           0 :                 oa = ospf6_area_create(area_id, ospf6, format);
    1121             : 
    1122             :         /* attach interface to area */
    1123           0 :         listnode_add(oa->if_list, oi); /* sort ?? */
    1124           0 :         oi->area = oa;
    1125             : 
    1126           0 :         SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
    1127             : 
    1128             :         /* ospf6 process is currently disabled, not much more to do */
    1129           0 :         if (CHECK_FLAG(ospf6->flag, OSPF6_DISABLED))
    1130             :                 return CMD_SUCCESS;
    1131             : 
    1132             :         /* start up */
    1133           0 :         ospf6_interface_enable(oi);
    1134             : 
    1135             :         /* If the router is ABR, originate summary routes */
    1136           0 :         if (ospf6_check_and_set_router_abr(ospf6)) {
    1137           0 :                 ospf6_abr_enable_area(oa);
    1138           0 :                 ospf6_schedule_abr_task(oa->ospf6);
    1139             :         }
    1140             : 
    1141             :         return CMD_SUCCESS;
    1142             : }
    1143             : 
    1144           0 : DEFUN_HIDDEN (no_ospf6_interface_area,
    1145             :        no_ospf6_interface_area_cmd,
    1146             :        "no interface IFNAME area <A.B.C.D|(0-4294967295)>",
    1147             :        NO_STR
    1148             :        "Disable routing on an IPv6 interface\n"
    1149             :        IFNAME_STR
    1150             :        "Specify the OSPF6 area ID\n"
    1151             :        "OSPF6 area ID in IPv4 address notation\n"
    1152             :        "OSPF6 area ID in decimal notation\n"
    1153             :        )
    1154             : {
    1155           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
    1156           0 :         int idx_ifname = 2;
    1157           0 :         int idx_ipv4 = 4;
    1158           0 :         struct ospf6_interface *oi;
    1159           0 :         struct ospf6_area *oa;
    1160           0 :         struct interface *ifp;
    1161           0 :         uint32_t area_id;
    1162             : 
    1163           0 :         vty_out(vty,
    1164             :                 "This command is deprecated, because it is not VRF-aware.\n");
    1165           0 :         vty_out(vty,
    1166             :                 "Please, use \"no ipv6 ospf6 area\" on an interface instead.\n");
    1167             : 
    1168             :         /* find/create ospf6 interface */
    1169           0 :         ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name);
    1170             : 
    1171           0 :         if (ifp == NULL) {
    1172           0 :                 vty_out(vty, "No such interface %s\n", argv[idx_ifname]->arg);
    1173           0 :                 return CMD_SUCCESS;
    1174             :         }
    1175             : 
    1176           0 :         oi = (struct ospf6_interface *)ifp->info;
    1177           0 :         if (oi == NULL) {
    1178           0 :                 vty_out(vty, "Interface %s not enabled\n", ifp->name);
    1179           0 :                 return CMD_SUCCESS;
    1180             :         }
    1181             : 
    1182             :         /* parse Area-ID */
    1183           0 :         if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1)
    1184           0 :                 area_id = htonl(strtoul(argv[idx_ipv4]->arg, NULL, 10));
    1185             : 
    1186             :         /* Verify Area */
    1187           0 :         if (oi->area == NULL) {
    1188           0 :                 vty_out(vty, "%pOI not attached to area %s\n",
    1189           0 :                         oi, argv[idx_ipv4]->arg);
    1190           0 :                 return CMD_SUCCESS;
    1191             :         }
    1192             : 
    1193           0 :         if (oi->area->area_id != area_id) {
    1194           0 :                 vty_out(vty, "Wrong Area-ID: %pOI is attached to area %s\n",
    1195           0 :                         oi, oi->area->name);
    1196           0 :                 return CMD_SUCCESS;
    1197             :         }
    1198             : 
    1199           0 :         ospf6_interface_disable(oi);
    1200             : 
    1201           0 :         oa = oi->area;
    1202           0 :         listnode_delete(oi->area->if_list, oi);
    1203           0 :         oi->area = (struct ospf6_area *)NULL;
    1204             : 
    1205             :         /* Withdraw inter-area routes from this area, if necessary */
    1206           0 :         if (oa->if_list->count == 0) {
    1207           0 :                 UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
    1208           0 :                 ospf6_abr_disable_area(oa);
    1209             :         }
    1210             : 
    1211           0 :         oi->area_id = 0;
    1212           0 :         oi->area_id_format = OSPF6_AREA_FMT_UNSET;
    1213             : 
    1214           0 :         return CMD_SUCCESS;
    1215             : }
    1216             : 
    1217           0 : DEFUN (ospf6_stub_router_admin,
    1218             :        ospf6_stub_router_admin_cmd,
    1219             :        "stub-router administrative",
    1220             :        "Make router a stub router\n"
    1221             :        "Administratively applied, for an indefinite period\n")
    1222             : {
    1223           0 :         struct listnode *node;
    1224           0 :         struct ospf6_area *oa;
    1225             : 
    1226           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
    1227             : 
    1228           0 :         if (!CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) {
    1229           0 :                 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
    1230           0 :                         OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_V6);
    1231           0 :                         OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_R);
    1232           0 :                         OSPF6_ROUTER_LSA_SCHEDULE(oa);
    1233             :                 }
    1234           0 :                 SET_FLAG(ospf6->flag, OSPF6_STUB_ROUTER);
    1235             :         }
    1236             : 
    1237             :         return CMD_SUCCESS;
    1238             : }
    1239             : 
    1240           0 : DEFUN (no_ospf6_stub_router_admin,
    1241             :        no_ospf6_stub_router_admin_cmd,
    1242             :        "no stub-router administrative",
    1243             :        NO_STR
    1244             :        "Make router a stub router\n"
    1245             :        "Administratively applied, for an indefinite period\n")
    1246             : {
    1247           0 :         struct listnode *node;
    1248           0 :         struct ospf6_area *oa;
    1249             : 
    1250           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
    1251           0 :         if (CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) {
    1252           0 :                 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
    1253           0 :                         OSPF6_OPT_SET(oa->options, OSPF6_OPT_V6);
    1254           0 :                         OSPF6_OPT_SET(oa->options, OSPF6_OPT_R);
    1255           0 :                         OSPF6_ROUTER_LSA_SCHEDULE(oa);
    1256             :                 }
    1257           0 :                 UNSET_FLAG(ospf6->flag, OSPF6_STUB_ROUTER);
    1258             :         }
    1259             : 
    1260             :         return CMD_SUCCESS;
    1261             : }
    1262             : 
    1263             : /* Restart OSPF SPF algorithm*/
    1264           0 : void ospf6_restart_spf(struct ospf6 *ospf6)
    1265             : {
    1266           0 :         ospf6_route_remove_all(ospf6->route_table);
    1267           0 :         ospf6_route_remove_all(ospf6->brouter_table);
    1268             : 
    1269             :         /* Trigger SPF */
    1270           0 :         ospf6_spf_schedule(ospf6, OSPF6_SPF_FLAGS_CONFIG_CHANGE);
    1271           0 : }
    1272             : 
    1273             : /* Set the max paths */
    1274           0 : static void ospf6_maxpath_set(struct ospf6 *ospf6, uint16_t paths)
    1275             : {
    1276           0 :         if (ospf6->max_multipath == paths)
    1277             :                 return;
    1278             : 
    1279           0 :         ospf6->max_multipath = paths;
    1280             : 
    1281             :         /* Send deletion to zebra to delete all
    1282             :          * ospf specific routes and reinitiate
    1283             :          * SPF to reflect the new max multipath.
    1284             :          */
    1285           0 :         ospf6_restart_spf(ospf6);
    1286             : }
    1287             : 
    1288             : /* Ospf Maximum-paths config support */
    1289           0 : DEFUN(ospf6_max_multipath,
    1290             :       ospf6_max_multipath_cmd,
    1291             :       "maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM),
    1292             :       "Max no of multiple paths for ECMP support\n"
    1293             :       "Number of paths\n")
    1294             : {
    1295           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
    1296           0 :         int idx_number = 1;
    1297           0 :         int maximum_paths = strtol(argv[idx_number]->arg, NULL, 10);
    1298             : 
    1299           0 :         ospf6_maxpath_set(ospf6, maximum_paths);
    1300             : 
    1301             :         return CMD_SUCCESS;
    1302             : }
    1303             : 
    1304           0 : DEFUN(no_ospf6_max_multipath,
    1305             :       no_ospf6_max_multipath_cmd,
    1306             :      "no maximum-paths [" CMD_RANGE_STR(1, MULTIPATH_NUM)"]",
    1307             :       NO_STR
    1308             :       "Max no of multiple paths for ECMP support\n"
    1309             :       "Number of paths\n")
    1310             : {
    1311           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
    1312             : 
    1313           0 :         ospf6_maxpath_set(ospf6, MULTIPATH_NUM);
    1314             : 
    1315             :         return CMD_SUCCESS;
    1316             : }
    1317             : 
    1318           0 : static void ospf6_show(struct vty *vty, struct ospf6 *o, json_object *json,
    1319             :                        bool use_json)
    1320             : {
    1321           0 :         struct listnode *n;
    1322           0 :         struct ospf6_area *oa;
    1323           0 :         char router_id[16], duration[32];
    1324           0 :         struct timeval now, running, result;
    1325           0 :         char buf[32], rbuf[32];
    1326           0 :         json_object *json_areas = NULL;
    1327           0 :         const char *adjacency;
    1328             : 
    1329           0 :         if (use_json) {
    1330           0 :                 json_areas = json_object_new_object();
    1331             : 
    1332             :                 /* process id, router id */
    1333           0 :                 inet_ntop(AF_INET, &o->router_id, router_id, sizeof(router_id));
    1334           0 :                 json_object_string_add(json, "routerId", router_id);
    1335             : 
    1336             :                 /* running time */
    1337           0 :                 monotime(&now);
    1338           0 :                 timersub(&now, &o->starttime, &running);
    1339           0 :                 timerstring(&running, duration, sizeof(duration));
    1340           0 :                 json_object_string_add(json, "running", duration);
    1341             : 
    1342             :                 /* Redistribute configuration */
    1343             :                 /* XXX */
    1344           0 :                 json_object_int_add(json, "lsaMinimumArrivalMsecs",
    1345           0 :                                     o->lsa_minarrival);
    1346             : 
    1347             :                 /* Show SPF parameters */
    1348           0 :                 json_object_int_add(json, "spfScheduleDelayMsecs",
    1349           0 :                                     o->spf_delay);
    1350           0 :                 json_object_int_add(json, "holdTimeMinMsecs", o->spf_holdtime);
    1351           0 :                 json_object_int_add(json, "holdTimeMaxMsecs",
    1352           0 :                                     o->spf_max_holdtime);
    1353           0 :                 json_object_int_add(json, "holdTimeMultiplier",
    1354           0 :                                     o->spf_hold_multiplier);
    1355             : 
    1356           0 :                 json_object_int_add(json, "maximumPaths", o->max_multipath);
    1357           0 :                 json_object_int_add(json, "preference",
    1358           0 :                                     o->distance_all
    1359             :                                             ? o->distance_all
    1360             :                                             : ZEBRA_OSPF6_DISTANCE_DEFAULT);
    1361             : 
    1362           0 :                 if (o->ts_spf.tv_sec || o->ts_spf.tv_usec) {
    1363           0 :                         timersub(&now, &o->ts_spf, &result);
    1364           0 :                         timerstring(&result, buf, sizeof(buf));
    1365           0 :                         ospf6_spf_reason_string(o->last_spf_reason, rbuf,
    1366             :                                                 sizeof(rbuf));
    1367           0 :                         json_object_boolean_true_add(json, "spfHasRun");
    1368           0 :                         json_object_string_add(json, "spfLastExecutedMsecs",
    1369             :                                                buf);
    1370           0 :                         json_object_string_add(json, "spfLastExecutedReason",
    1371             :                                                rbuf);
    1372             : 
    1373           0 :                         json_object_int_add(
    1374             :                                 json, "spfLastDurationSecs",
    1375           0 :                                 (long long)o->ts_spf_duration.tv_sec);
    1376             : 
    1377           0 :                         json_object_int_add(
    1378             :                                 json, "spfLastDurationMsecs",
    1379           0 :                                 (long long)o->ts_spf_duration.tv_usec);
    1380             :                 } else
    1381           0 :                         json_object_boolean_false_add(json, "spfHasRun");
    1382             : 
    1383           0 :                 if (thread_is_scheduled(o->t_spf_calc)) {
    1384           0 :                         long time_store;
    1385             : 
    1386           0 :                         json_object_boolean_true_add(json, "spfTimerActive");
    1387           0 :                         time_store =
    1388           0 :                                 monotime_until(&o->t_spf_calc->u.sands, NULL)
    1389             :                                 / 1000LL;
    1390           0 :                         json_object_int_add(json, "spfTimerDueInMsecs",
    1391             :                                             time_store);
    1392             :                 } else
    1393           0 :                         json_object_boolean_false_add(json, "spfTimerActive");
    1394             : 
    1395           0 :                 json_object_boolean_add(json, "routerIsStubRouter",
    1396           0 :                                         CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER));
    1397             : 
    1398             :                 /* LSAs */
    1399           0 :                 json_object_int_add(json, "numberOfAsScopedLsa",
    1400           0 :                                     o->lsdb->count);
    1401             :                 /* Areas */
    1402           0 :                 json_object_int_add(json, "numberOfAreaInRouter",
    1403           0 :                                     listcount(o->area_list));
    1404             : 
    1405           0 :                 json_object_int_add(json, "AuthTrailerHigherSeqNo",
    1406           0 :                                     o->seqnum_h);
    1407           0 :                 json_object_int_add(json, "AuthTrailerLowerSeqNo", o->seqnum_l);
    1408             : 
    1409           0 :                 if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
    1410           0 :                         if (CHECK_FLAG(o->config_flags,
    1411             :                                        OSPF6_LOG_ADJACENCY_DETAIL))
    1412             :                                 adjacency = "LoggedAll";
    1413             :                         else
    1414           0 :                                 adjacency = "Logged";
    1415             :                 } else
    1416             :                         adjacency = "NotLogged";
    1417           0 :                 json_object_string_add(json, "adjacencyChanges", adjacency);
    1418             : 
    1419           0 :                 for (ALL_LIST_ELEMENTS_RO(o->area_list, n, oa))
    1420           0 :                         ospf6_area_show(vty, oa, json_areas, use_json);
    1421             : 
    1422           0 :                 json_object_object_add(json, "areas", json_areas);
    1423             : 
    1424           0 :                 vty_out(vty, "%s\n",
    1425             :                         json_object_to_json_string_ext(
    1426             :                                 json, JSON_C_TO_STRING_PRETTY));
    1427             : 
    1428             :         } else {
    1429             :                 /* process id, router id */
    1430           0 :                 inet_ntop(AF_INET, &o->router_id, router_id, sizeof(router_id));
    1431           0 :                 vty_out(vty, " OSPFv3 Routing Process (0) with Router-ID %s\n",
    1432             :                         router_id);
    1433             : 
    1434             :                 /* running time */
    1435           0 :                 monotime(&now);
    1436           0 :                 timersub(&now, &o->starttime, &running);
    1437           0 :                 timerstring(&running, duration, sizeof(duration));
    1438           0 :                 vty_out(vty, " Running %s\n", duration);
    1439             : 
    1440             :                 /* Redistribute configuration */
    1441             :                 /* XXX */
    1442           0 :                 vty_out(vty, " LSA minimum arrival %d msecs\n",
    1443             :                         o->lsa_minarrival);
    1444             : 
    1445           0 :                 vty_out(vty, " Maximum-paths %u\n", o->max_multipath);
    1446           0 :                 vty_out(vty, " Administrative distance %u\n",
    1447           0 :                         o->distance_all ? o->distance_all
    1448             :                                         : ZEBRA_OSPF6_DISTANCE_DEFAULT);
    1449             : 
    1450             :                 /* Show SPF parameters */
    1451           0 :                 vty_out(vty,
    1452             :                         " Initial SPF scheduling delay %d millisec(s)\n"
    1453             :                         " Minimum hold time between consecutive SPFs %d millsecond(s)\n"
    1454             :                         " Maximum hold time between consecutive SPFs %d millsecond(s)\n"
    1455             :                         " Hold time multiplier is currently %d\n",
    1456             :                         o->spf_delay, o->spf_holdtime, o->spf_max_holdtime,
    1457             :                         o->spf_hold_multiplier);
    1458             : 
    1459             : 
    1460           0 :                 vty_out(vty, " SPF algorithm ");
    1461           0 :                 if (o->ts_spf.tv_sec || o->ts_spf.tv_usec) {
    1462           0 :                         timersub(&now, &o->ts_spf, &result);
    1463           0 :                         timerstring(&result, buf, sizeof(buf));
    1464           0 :                         ospf6_spf_reason_string(o->last_spf_reason, rbuf,
    1465             :                                                 sizeof(rbuf));
    1466           0 :                         vty_out(vty, "last executed %s ago, reason %s\n", buf,
    1467             :                                 rbuf);
    1468           0 :                         vty_out(vty, " Last SPF duration %lld sec %lld usec\n",
    1469           0 :                                 (long long)o->ts_spf_duration.tv_sec,
    1470           0 :                                 (long long)o->ts_spf_duration.tv_usec);
    1471             :                 } else
    1472           0 :                         vty_out(vty, "has not been run\n");
    1473             : 
    1474           0 :                 threadtimer_string(now, o->t_spf_calc, buf, sizeof(buf));
    1475           0 :                 vty_out(vty, " SPF timer %s%s\n",
    1476           0 :                         (thread_is_scheduled(o->t_spf_calc) ? "due in "
    1477             :                                                             : "is "),
    1478             :                         buf);
    1479             : 
    1480           0 :                 if (CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER))
    1481           0 :                         vty_out(vty, " Router Is Stub Router\n");
    1482             : 
    1483             :                 /* LSAs */
    1484           0 :                 vty_out(vty, " Number of AS scoped LSAs is %u\n",
    1485           0 :                         o->lsdb->count);
    1486             : 
    1487             :                 /* Areas */
    1488           0 :                 vty_out(vty, " Number of areas in this router is %u\n",
    1489           0 :                         listcount(o->area_list));
    1490             : 
    1491           0 :                 vty_out(vty, " Authentication Sequence number info\n");
    1492           0 :                 vty_out(vty, "  Higher sequence no %u, Lower sequence no %u\n",
    1493             :                         o->seqnum_h, o->seqnum_l);
    1494             : 
    1495           0 :                 if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
    1496           0 :                         if (CHECK_FLAG(o->config_flags,
    1497             :                                        OSPF6_LOG_ADJACENCY_DETAIL))
    1498           0 :                                 vty_out(vty,
    1499             :                                         " All adjacency changes are logged\n");
    1500             :                         else
    1501           0 :                                 vty_out(vty, " Adjacency changes are logged\n");
    1502             :                 }
    1503             : 
    1504             : 
    1505           0 :                 vty_out(vty, "\n");
    1506             : 
    1507           0 :                 for (ALL_LIST_ELEMENTS_RO(o->area_list, n, oa))
    1508           0 :                         ospf6_area_show(vty, oa, json_areas, use_json);
    1509             :         }
    1510           0 : }
    1511             : 
    1512           0 : DEFUN(show_ipv6_ospf6_vrfs, show_ipv6_ospf6_vrfs_cmd,
    1513             :       "show ipv6 ospf6 vrfs [json]",
    1514             :       SHOW_STR IP6_STR OSPF6_STR "Show OSPF6 VRFs \n" JSON_STR)
    1515             : {
    1516           0 :         bool uj = use_json(argc, argv);
    1517           0 :         json_object *json = NULL;
    1518           0 :         json_object *json_vrfs = NULL;
    1519           0 :         struct ospf6 *ospf6 = NULL;
    1520           0 :         struct listnode *node = NULL;
    1521           0 :         int count = 0;
    1522           0 :         char buf[PREFIX_STRLEN];
    1523           0 :         static const char header[] =
    1524             :                 "Name                       Id     RouterId  ";
    1525             : 
    1526           0 :         if (uj) {
    1527           0 :                 json = json_object_new_object();
    1528           0 :                 json_vrfs = json_object_new_object();
    1529             :         }
    1530             : 
    1531           0 :         for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
    1532           0 :                 json_object *json_vrf = NULL;
    1533           0 :                 const char *name = NULL;
    1534           0 :                 int64_t vrf_id_ui = 0;
    1535           0 :                 struct in_addr router_id;
    1536             : 
    1537           0 :                 router_id.s_addr = ospf6->router_id;
    1538           0 :                 count++;
    1539             : 
    1540           0 :                 if (!uj && count == 1)
    1541           0 :                         vty_out(vty, "%s\n", header);
    1542           0 :                 if (uj)
    1543           0 :                         json_vrf = json_object_new_object();
    1544             : 
    1545           0 :                 if (ospf6->vrf_id == VRF_DEFAULT)
    1546           0 :                         name = VRF_DEFAULT_NAME;
    1547             :                 else
    1548           0 :                         name = ospf6->name;
    1549             : 
    1550           0 :                 vrf_id_ui = (ospf6->vrf_id == VRF_UNKNOWN)
    1551             :                                     ? -1
    1552           0 :                                     : (int64_t)ospf6->vrf_id;
    1553             : 
    1554           0 :                 if (uj) {
    1555           0 :                         json_object_int_add(json_vrf, "vrfId", vrf_id_ui);
    1556           0 :                         json_object_string_addf(json_vrf, "routerId", "%pI4",
    1557             :                                                 &router_id);
    1558           0 :                         json_object_object_add(json_vrfs, name, json_vrf);
    1559             : 
    1560             :                 } else {
    1561           0 :                         vty_out(vty, "%-25s  %-5d  %-16s  \n", name,
    1562             :                                 ospf6->vrf_id,
    1563             :                                 inet_ntop(AF_INET, &router_id, buf,
    1564             :                                           sizeof(buf)));
    1565             :                 }
    1566             :         }
    1567             : 
    1568           0 :         if (uj) {
    1569           0 :                 json_object_object_add(json, "vrfs", json_vrfs);
    1570           0 :                 json_object_int_add(json, "totalVrfs", count);
    1571             : 
    1572           0 :                 vty_json(vty, json);
    1573             :         } else {
    1574           0 :                 if (count)
    1575           0 :                         vty_out(vty, "\nTotal number of OSPF VRFs: %d\n",
    1576             :                                 count);
    1577             :         }
    1578             : 
    1579           0 :         return CMD_SUCCESS;
    1580             : }
    1581             : 
    1582             : /* show top level structures */
    1583           0 : DEFUN(show_ipv6_ospf6, show_ipv6_ospf6_cmd,
    1584             :       "show ipv6 ospf6 [vrf <NAME|all>] [json]",
    1585             :       SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR "All VRFs\n" JSON_STR)
    1586             : {
    1587           0 :         struct ospf6 *ospf6;
    1588           0 :         struct listnode *node;
    1589           0 :         const char *vrf_name = NULL;
    1590           0 :         bool all_vrf = false;
    1591           0 :         int idx_vrf = 0;
    1592             : 
    1593           0 :         bool uj = use_json(argc, argv);
    1594           0 :         json_object *json = NULL;
    1595             : 
    1596           0 :         OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
    1597             : 
    1598           0 :         for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
    1599           0 :                 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
    1600           0 :                         if (uj)
    1601           0 :                                 json = json_object_new_object();
    1602           0 :                         ospf6_show(vty, ospf6, json, uj);
    1603             : 
    1604           0 :                         if (!all_vrf)
    1605             :                                 break;
    1606             :                 }
    1607             :         }
    1608             : 
    1609           0 :         if (uj)
    1610           0 :                 json_object_free(json);
    1611             : 
    1612           0 :         OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
    1613             : 
    1614             :         return CMD_SUCCESS;
    1615             : }
    1616             : 
    1617           0 : DEFUN(show_ipv6_ospf6_route, show_ipv6_ospf6_route_cmd,
    1618             :       "show ipv6 ospf6 [vrf <NAME|all>] route [<intra-area|inter-area|external-1|external-2|X:X::X:X|X:X::X:X/M|detail|summary>] [json]",
    1619             :       SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
    1620             :       "All VRFs\n" ROUTE_STR
    1621             :       "Display Intra-Area routes\n"
    1622             :       "Display Inter-Area routes\n"
    1623             :       "Display Type-1 External routes\n"
    1624             :       "Display Type-2 External routes\n"
    1625             :       "Specify IPv6 address\n"
    1626             :       "Specify IPv6 prefix\n"
    1627             :       "Detailed information\n"
    1628             :       "Summary of route table\n" JSON_STR)
    1629             : {
    1630           0 :         struct ospf6 *ospf6;
    1631           0 :         struct listnode *node;
    1632           0 :         const char *vrf_name = NULL;
    1633           0 :         bool all_vrf = false;
    1634           0 :         int idx_vrf = 0;
    1635           0 :         int idx_arg_start = 4;
    1636           0 :         bool uj = use_json(argc, argv);
    1637             : 
    1638           0 :         OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
    1639           0 :         if (idx_vrf > 0)
    1640           0 :                 idx_arg_start += 2;
    1641             : 
    1642           0 :         for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
    1643           0 :                 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
    1644           0 :                         ospf6_route_table_show(vty, idx_arg_start, argc, argv,
    1645             :                                                ospf6->route_table, uj);
    1646             : 
    1647           0 :                         if (!all_vrf)
    1648             :                                 break;
    1649             :                 }
    1650             :         }
    1651             : 
    1652           0 :         OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
    1653             : 
    1654             :         return CMD_SUCCESS;
    1655             : }
    1656             : 
    1657           0 : DEFUN(show_ipv6_ospf6_route_match, show_ipv6_ospf6_route_match_cmd,
    1658             :       "show ipv6 ospf6 [vrf <NAME|all>] route X:X::X:X/M <match|longer> [json]",
    1659             :       SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
    1660             :       "All VRFs\n" ROUTE_STR
    1661             :       "Specify IPv6 prefix\n"
    1662             :       "Display routes which match the specified route\n"
    1663             :       "Display routes longer than the specified route\n" JSON_STR)
    1664             : {
    1665           0 :         struct ospf6 *ospf6;
    1666           0 :         struct listnode *node;
    1667           0 :         const char *vrf_name = NULL;
    1668           0 :         bool all_vrf = false;
    1669           0 :         int idx_vrf = 0;
    1670           0 :         int idx_start_arg = 4;
    1671           0 :         bool uj = use_json(argc, argv);
    1672             : 
    1673           0 :         OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
    1674           0 :         if (idx_vrf > 0)
    1675           0 :                 idx_start_arg += 2;
    1676             : 
    1677           0 :         for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
    1678           0 :                 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
    1679           0 :                         ospf6_route_table_show(vty, idx_start_arg, argc, argv,
    1680             :                                                ospf6->route_table, uj);
    1681             : 
    1682           0 :                         if (!all_vrf)
    1683             :                                 break;
    1684             :                 }
    1685             :         }
    1686             : 
    1687           0 :         OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
    1688             : 
    1689             :         return CMD_SUCCESS;
    1690             : }
    1691             : 
    1692           0 : DEFUN(show_ipv6_ospf6_route_match_detail,
    1693             :       show_ipv6_ospf6_route_match_detail_cmd,
    1694             :       "show ipv6 ospf6 [vrf <NAME|all>] route X:X::X:X/M match detail [json]",
    1695             :       SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
    1696             :       "All VRFs\n" ROUTE_STR
    1697             :       "Specify IPv6 prefix\n"
    1698             :       "Display routes which match the specified route\n"
    1699             :       "Detailed information\n" JSON_STR)
    1700             : {
    1701           0 :         struct ospf6 *ospf6;
    1702           0 :         struct listnode *node;
    1703           0 :         const char *vrf_name = NULL;
    1704           0 :         bool all_vrf = false;
    1705           0 :         int idx_vrf = 0;
    1706           0 :         int idx_start_arg = 4;
    1707           0 :         bool uj = use_json(argc, argv);
    1708             : 
    1709           0 :         OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
    1710           0 :         if (idx_vrf > 0)
    1711           0 :                 idx_start_arg += 2;
    1712             : 
    1713           0 :         for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
    1714           0 :                 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
    1715           0 :                         ospf6_route_table_show(vty, idx_start_arg, argc, argv,
    1716             :                                                ospf6->route_table, uj);
    1717             : 
    1718           0 :                         if (!all_vrf)
    1719             :                                 break;
    1720             :                 }
    1721             :         }
    1722             : 
    1723           0 :         OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
    1724             : 
    1725             :         return CMD_SUCCESS;
    1726             : }
    1727             : 
    1728           0 : DEFUN(show_ipv6_ospf6_route_type_detail, show_ipv6_ospf6_route_type_detail_cmd,
    1729             :       "show ipv6 ospf6 [vrf <NAME|all>] route <intra-area|inter-area|external-1|external-2> detail [json]",
    1730             :       SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
    1731             :       "All VRFs\n" ROUTE_STR
    1732             :       "Display Intra-Area routes\n"
    1733             :       "Display Inter-Area routes\n"
    1734             :       "Display Type-1 External routes\n"
    1735             :       "Display Type-2 External routes\n"
    1736             :       "Detailed information\n" JSON_STR)
    1737             : {
    1738           0 :         struct ospf6 *ospf6;
    1739           0 :         struct listnode *node;
    1740           0 :         const char *vrf_name = NULL;
    1741           0 :         bool all_vrf = false;
    1742           0 :         int idx_vrf = 0;
    1743           0 :         int idx_start_arg = 4;
    1744           0 :         bool uj = use_json(argc, argv);
    1745             : 
    1746           0 :         OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
    1747           0 :         if (idx_vrf > 0)
    1748           0 :                 idx_start_arg += 2;
    1749             : 
    1750           0 :         for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
    1751           0 :                 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
    1752           0 :                         ospf6_route_table_show(vty, idx_start_arg, argc, argv,
    1753             :                                                ospf6->route_table, uj);
    1754             : 
    1755           0 :                         if (!all_vrf)
    1756             :                                 break;
    1757             :                 }
    1758             :         }
    1759             : 
    1760           0 :         OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
    1761             : 
    1762             :         return CMD_SUCCESS;
    1763             : }
    1764             : 
    1765           0 : bool ospf6_is_valid_summary_addr(struct vty *vty, struct prefix *p)
    1766             : {
    1767             :         /* Default prefix validation*/
    1768           0 :         if (is_default_prefix(p)) {
    1769           0 :                 vty_out(vty,
    1770             :                         "Default address should not be configured as summary address.\n");
    1771           0 :                 return false;
    1772             :         }
    1773             : 
    1774             :         /* Host route should not be configured as summary address */
    1775           0 :         if (p->prefixlen == IPV6_MAX_BITLEN) {
    1776           0 :                 vty_out(vty, "Host route should not be configured as summary address.\n");
    1777           0 :                 return false;
    1778             :         }
    1779             : 
    1780             :         return true;
    1781             : }
    1782             : 
    1783             : /* External Route Aggregation */
    1784           0 : DEFPY (ospf6_external_route_aggregation,
    1785             :        ospf6_external_route_aggregation_cmd,
    1786             :        "summary-address X:X::X:X/M$prefix [tag (1-4294967295)] [{metric (0-16777215) | metric-type (1-2)$mtype}]",
    1787             :        "External summary address\n"
    1788             :        "Specify IPv6 prefix\n"
    1789             :        "Router tag \n"
    1790             :        "Router tag value\n"
    1791             :        "Metric \n"
    1792             :        "Advertised metric for this route\n"
    1793             :        "OSPFv3 exterior metric type for summarised routes\n"
    1794             :        "Set OSPFv3 External Type 1/2 metrics\n")
    1795             : {
    1796           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
    1797             : 
    1798           0 :         struct prefix p;
    1799           0 :         int ret = CMD_SUCCESS;
    1800             : 
    1801           0 :         p.family = AF_INET6;
    1802           0 :         ret = str2prefix(prefix_str, &p);
    1803           0 :         if (ret == 0) {
    1804           0 :                 vty_out(vty, "Malformed prefix\n");
    1805           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1806             :         }
    1807             : 
    1808             :         /* Apply mask for given prefix. */
    1809           0 :         apply_mask(&p);
    1810             : 
    1811           0 :         if (!ospf6_is_valid_summary_addr(vty, &p))
    1812             :                 return CMD_WARNING_CONFIG_FAILED;
    1813             : 
    1814           0 :         if (!tag_str)
    1815           0 :                 tag = 0;
    1816             : 
    1817           0 :         if (!metric_str)
    1818           0 :                 metric = -1;
    1819             : 
    1820           0 :         if (!mtype_str)
    1821           0 :                 mtype = DEFAULT_METRIC_TYPE;
    1822             : 
    1823           0 :         ret = ospf6_external_aggr_config_set(ospf6, &p, tag, metric, mtype);
    1824           0 :         if (ret == OSPF6_FAILURE) {
    1825           0 :                 vty_out(vty, "Invalid configuration!!\n");
    1826           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1827             :         }
    1828             : 
    1829             :         return CMD_SUCCESS;
    1830             : }
    1831             : 
    1832           0 : DEFPY(no_ospf6_external_route_aggregation,
    1833             :       no_ospf6_external_route_aggregation_cmd,
    1834             :       "no summary-address X:X::X:X/M$prefix [tag (1-4294967295)] [{metric (0-16777215) | metric-type (1-2)}]",
    1835             :       NO_STR
    1836             :       "External summary address\n"
    1837             :       "Specify IPv6 prefix\n"
    1838             :       "Router tag\n"
    1839             :       "Router tag value\n"
    1840             :       "Metric \n"
    1841             :       "Advertised metric for this route\n"
    1842             :       "OSPFv3 exterior metric type for summarised routes\n"
    1843             :       "Set OSPFv3 External Type 1/2 metrics\n")
    1844             : {
    1845           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
    1846             : 
    1847           0 :         struct prefix p;
    1848           0 :         int ret = CMD_SUCCESS;
    1849             : 
    1850           0 :         ret = str2prefix(prefix_str, &p);
    1851           0 :         if (ret == 0) {
    1852           0 :                 vty_out(vty, "Malformed prefix\n");
    1853           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1854             :         }
    1855             : 
    1856             :         /* Apply mask for given prefix. */
    1857           0 :         apply_mask(&p);
    1858             : 
    1859           0 :         if (!ospf6_is_valid_summary_addr(vty, &p))
    1860             :                 return CMD_WARNING_CONFIG_FAILED;
    1861             : 
    1862           0 :         ret = ospf6_external_aggr_config_unset(ospf6, &p);
    1863           0 :         if (ret == OSPF6_INVALID)
    1864           0 :                 vty_out(vty, "Invalid configuration!!\n");
    1865             : 
    1866             :         return CMD_SUCCESS;
    1867             : }
    1868             : 
    1869           0 : DEFPY (ospf6_external_route_aggregation_no_advertise,
    1870             :        ospf6_external_route_aggregation_no_advertise_cmd,
    1871             :        "summary-address X:X::X:X/M$prefix no-advertise",
    1872             :        "External summary address\n"
    1873             :        "Specify IPv6 prefix\n"
    1874             :        "Don't advertise summary route \n")
    1875             : {
    1876           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
    1877             : 
    1878           0 :         struct prefix p;
    1879           0 :         int ret = CMD_SUCCESS;
    1880             : 
    1881           0 :         ret = str2prefix(prefix_str, &p);
    1882           0 :         if (ret == 0) {
    1883           0 :                 vty_out(vty, "Malformed prefix\n");
    1884           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1885             :         }
    1886             : 
    1887             :         /* Apply mask for given prefix. */
    1888           0 :         apply_mask(&p);
    1889             : 
    1890           0 :         if (!ospf6_is_valid_summary_addr(vty, &p))
    1891             :                 return CMD_WARNING_CONFIG_FAILED;
    1892             : 
    1893           0 :         ret = ospf6_asbr_external_rt_no_advertise(ospf6, &p);
    1894           0 :         if (ret == OSPF6_INVALID)
    1895           0 :                 vty_out(vty, "!!Invalid configuration\n");
    1896             : 
    1897             :         return CMD_SUCCESS;
    1898             : }
    1899             : 
    1900           0 : DEFPY (no_ospf6_external_route_aggregation_no_advertise,
    1901             :        no_ospf6_external_route_aggregation_no_advertise_cmd,
    1902             :        "no summary-address X:X::X:X/M$prefix no-advertise",
    1903             :        NO_STR
    1904             :        "External summary address\n"
    1905             :        "Specify IPv6 prefix\n"
    1906             :        "Adverise summary route to the AS \n")
    1907             : {
    1908           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
    1909             : 
    1910           0 :         struct prefix p;
    1911           0 :         int ret = CMD_SUCCESS;
    1912             : 
    1913           0 :         ret = str2prefix(prefix_str, &p);
    1914           0 :         if (ret == 0) {
    1915           0 :                 vty_out(vty, "Malformed prefix\n");
    1916           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1917             :         }
    1918             : 
    1919             :         /* Apply mask for given prefix. */
    1920           0 :         apply_mask(&p);
    1921             : 
    1922           0 :         if (!ospf6_is_valid_summary_addr(vty, &p))
    1923             :                 return CMD_WARNING_CONFIG_FAILED;
    1924             : 
    1925           0 :         ret = ospf6_asbr_external_rt_advertise(ospf6, &p);
    1926           0 :         if (ret == OSPF6_INVALID)
    1927           0 :                 vty_out(vty, "!!Invalid configuration\n");
    1928             : 
    1929             :         return CMD_SUCCESS;
    1930             : }
    1931             : 
    1932           0 : DEFPY (ospf6_route_aggregation_timer,
    1933             :        ospf6_route_aggregation_timer_cmd,
    1934             :        "aggregation timer (5-1800)",
    1935             :        "External route aggregation\n"
    1936             :        "Delay timer (in seconds)\n"
    1937             :        "Timer interval(in seconds)\n")
    1938             : {
    1939           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
    1940             : 
    1941           0 :         ospf6_external_aggr_delay_timer_set(ospf6, timer);
    1942             : 
    1943           0 :         return CMD_SUCCESS;
    1944             : }
    1945             : 
    1946           0 : DEFPY (no_ospf6_route_aggregation_timer,
    1947             :        no_ospf6_route_aggregation_timer_cmd,
    1948             :        "no aggregation timer [5-1800]",
    1949             :        NO_STR
    1950             :        "External route aggregation\n"
    1951             :        "Delay timer\n"
    1952             :        "Timer interval(in seconds)\n")
    1953             : {
    1954           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
    1955             : 
    1956           0 :         ospf6_external_aggr_delay_timer_set(ospf6,
    1957             :                         OSPF6_EXTL_AGGR_DEFAULT_DELAY);
    1958           0 :         return CMD_SUCCESS;
    1959             : }
    1960             : 
    1961             : static int
    1962           0 : ospf6_print_vty_external_routes_walkcb(struct hash_bucket *bucket, void *arg)
    1963             : {
    1964           0 :         struct ospf6_route *rt = bucket->data;
    1965           0 :         struct vty *vty = (struct vty *)arg;
    1966           0 :         static unsigned int count;
    1967             : 
    1968           0 :         vty_out(vty, "%pFX ", &rt->prefix);
    1969             : 
    1970           0 :         count++;
    1971             : 
    1972           0 :         if (count%5 == 0)
    1973           0 :                 vty_out(vty, "\n");
    1974             : 
    1975           0 :         if (OSPF6_EXTERNAL_RT_COUNT(rt->aggr_route) == count)
    1976           0 :                 count = 0;
    1977             : 
    1978           0 :         return HASHWALK_CONTINUE;
    1979             : }
    1980             : 
    1981             : static int
    1982           0 : ospf6_print_json_external_routes_walkcb(struct hash_bucket *bucket, void *arg)
    1983             : {
    1984           0 :         struct ospf6_route *rt = bucket->data;
    1985           0 :         struct json_object *json = (struct json_object *)arg;
    1986           0 :         char buf[PREFIX2STR_BUFFER];
    1987           0 :         char exnalbuf[20];
    1988           0 :         static unsigned int count;
    1989             : 
    1990           0 :         prefix2str(&rt->prefix, buf, sizeof(buf));
    1991             : 
    1992           0 :         snprintf(exnalbuf, sizeof(exnalbuf), "Exnl Addr-%d", count);
    1993             : 
    1994           0 :         json_object_string_add(json, exnalbuf, buf);
    1995             : 
    1996           0 :         count++;
    1997             : 
    1998           0 :         if (OSPF6_EXTERNAL_RT_COUNT(rt->aggr_route) == count)
    1999           0 :                 count = 0;
    2000             : 
    2001           0 :         return HASHWALK_CONTINUE;
    2002             : }
    2003             : 
    2004             : static void
    2005           0 : ospf6_show_vrf_name(struct vty *vty, struct ospf6 *ospf6,
    2006             :                     json_object *json)
    2007             : {
    2008           0 :         if (json) {
    2009           0 :                 if (ospf6->vrf_id == VRF_DEFAULT)
    2010           0 :                         json_object_string_add(json, "vrfName",
    2011             :                                                "default");
    2012             :                 else
    2013           0 :                         json_object_string_add(json, "vrfName",
    2014           0 :                                                ospf6->name);
    2015           0 :                 json_object_int_add(json, "vrfId", ospf6->vrf_id);
    2016             :         } else {
    2017           0 :                 if (ospf6->vrf_id == VRF_DEFAULT)
    2018           0 :                         vty_out(vty, "VRF Name: %s\n", "default");
    2019           0 :                 else if (ospf6->name)
    2020           0 :                         vty_out(vty, "VRF Name: %s\n", ospf6->name);
    2021             :         }
    2022           0 : }
    2023             : 
    2024             : static int
    2025           0 : ospf6_show_summary_address(struct vty *vty, struct ospf6 *ospf6,
    2026             :                         json_object *json,
    2027             :                         bool uj, const char *detail)
    2028             : {
    2029           0 :         struct route_node *rn;
    2030           0 :         static const char header[] = "Summary-address       Metric-type     Metric     Tag         External_Rt_count\n";
    2031           0 :         json_object *json_vrf = NULL;
    2032             : 
    2033           0 :         if (!uj) {
    2034           0 :                 ospf6_show_vrf_name(vty, ospf6, json_vrf);
    2035           0 :                 vty_out(vty, "aggregation delay interval :%u(in seconds)\n\n",
    2036           0 :                         ospf6->aggr_delay_interval);
    2037           0 :                 vty_out(vty, "%s\n", header);
    2038             :         } else {
    2039           0 :                 json_vrf = json_object_new_object();
    2040             : 
    2041           0 :                 ospf6_show_vrf_name(vty, ospf6, json_vrf);
    2042             : 
    2043           0 :                 json_object_int_add(json_vrf, "aggregationDelayInterval",
    2044           0 :                                     ospf6->aggr_delay_interval);
    2045             :         }
    2046             : 
    2047             : 
    2048           0 :         for (rn = route_top(ospf6->rt_aggr_tbl); rn; rn = route_next(rn)) {
    2049           0 :                 if (!rn->info)
    2050           0 :                         continue;
    2051             : 
    2052           0 :                 struct ospf6_external_aggr_rt *aggr = rn->info;
    2053           0 :                 json_object *json_aggr = NULL;
    2054           0 :                 char buf[PREFIX2STR_BUFFER];
    2055             : 
    2056           0 :                 prefix2str(&aggr->p, buf, sizeof(buf));
    2057             : 
    2058           0 :                 if (uj) {
    2059             : 
    2060           0 :                         json_aggr = json_object_new_object();
    2061             : 
    2062           0 :                         json_object_object_add(json_vrf,
    2063             :                                                 buf,
    2064             :                                                 json_aggr);
    2065             : 
    2066           0 :                         json_object_string_add(json_aggr, "summaryAddress",
    2067             :                                                buf);
    2068             : 
    2069           0 :                         json_object_string_add(
    2070             :                                 json_aggr, "metricType",
    2071           0 :                                 (aggr->mtype == DEFAULT_METRIC_TYPE) ? "E2"
    2072             :                                                                      : "E1");
    2073             : 
    2074           0 :                         json_object_int_add(json_aggr, "Metric",
    2075           0 :                                            (aggr->metric != -1)
    2076             :                                             ? aggr->metric
    2077             :                                             : DEFAULT_DEFAULT_METRIC);
    2078             : 
    2079           0 :                         json_object_int_add(json_aggr, "Tag",
    2080           0 :                                             aggr->tag);
    2081             : 
    2082           0 :                         json_object_int_add(json_aggr, "externalRouteCount",
    2083           0 :                                             OSPF6_EXTERNAL_RT_COUNT(aggr));
    2084             : 
    2085           0 :                         if (OSPF6_EXTERNAL_RT_COUNT(aggr) && detail) {
    2086           0 :                                 json_object_int_add(json_aggr, "ID",
    2087           0 :                                                     aggr->id);
    2088           0 :                                 json_object_int_add(json_aggr, "Flags",
    2089           0 :                                                     aggr->aggrflags);
    2090           0 :                                 hash_walk(aggr->match_extnl_hash,
    2091             :                                         ospf6_print_json_external_routes_walkcb,
    2092             :                                                         json_aggr);
    2093             :                         }
    2094             : 
    2095             :                 } else {
    2096           0 :                         vty_out(vty, "%-22s", buf);
    2097             : 
    2098           0 :                         (aggr->mtype == DEFAULT_METRIC_TYPE)
    2099           0 :                                 ? vty_out(vty, "%-16s", "E2")
    2100           0 :                                 : vty_out(vty, "%-16s", "E1");
    2101           0 :                         vty_out(vty, "%-11d", (aggr->metric != -1)
    2102             :                                         ? aggr->metric
    2103             :                                         : DEFAULT_DEFAULT_METRIC);
    2104             : 
    2105           0 :                         vty_out(vty, "%-12u", aggr->tag);
    2106             : 
    2107           0 :                         vty_out(vty, "%-5ld\n",
    2108           0 :                                 OSPF6_EXTERNAL_RT_COUNT(aggr));
    2109             : 
    2110           0 :                         if (OSPF6_EXTERNAL_RT_COUNT(aggr) && detail) {
    2111           0 :                                 vty_out(vty,
    2112             :                                         "Matched External routes:\n");
    2113           0 :                                 hash_walk(aggr->match_extnl_hash,
    2114             :                                 ospf6_print_vty_external_routes_walkcb,
    2115             :                                                         vty);
    2116           0 :                                 vty_out(vty, "\n");
    2117             :                         }
    2118             : 
    2119           0 :                         vty_out(vty, "\n");
    2120             :                 }
    2121             :         }
    2122             : 
    2123           0 :         if (uj)
    2124           0 :                 json_object_object_add(json, ospf6->name,
    2125             :                                         json_vrf);
    2126             : 
    2127           0 :         return CMD_SUCCESS;
    2128             : }
    2129             : 
    2130           0 : DEFPY (show_ipv6_ospf6_external_aggregator,
    2131             :        show_ipv6_ospf6_external_aggregator_cmd,
    2132             :        "show ipv6 ospf6 [vrf <NAME|all>] summary-address [detail$detail] [json]",
    2133             :        SHOW_STR
    2134             :        IP6_STR
    2135             :        OSPF6_STR
    2136             :        VRF_CMD_HELP_STR
    2137             :        "All VRFs\n"
    2138             :        "Show external summary addresses\n"
    2139             :        "detailed information\n"
    2140             :        JSON_STR)
    2141             : {
    2142           0 :         bool uj = use_json(argc, argv);
    2143           0 :         struct ospf6 *ospf6 = NULL;
    2144           0 :         json_object *json = NULL;
    2145           0 :         const char *vrf_name = NULL;
    2146           0 :         struct listnode *node;
    2147           0 :         bool all_vrf = false;
    2148           0 :         int idx_vrf = 0;
    2149             : 
    2150           0 :         if (uj)
    2151           0 :                 json = json_object_new_object();
    2152             : 
    2153           0 :         OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
    2154             : 
    2155           0 :         for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
    2156           0 :                 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
    2157             : 
    2158           0 :                         ospf6_show_summary_address(vty, ospf6, json, uj,
    2159             :                                                    detail);
    2160             : 
    2161           0 :                         if (!all_vrf)
    2162             :                                 break;
    2163             :                 }
    2164             :         }
    2165             : 
    2166           0 :         if (uj) {
    2167           0 :                 vty_json(vty, json);
    2168             :         }
    2169             : 
    2170           0 :         OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
    2171             : 
    2172             :         return CMD_SUCCESS;
    2173             : }
    2174             : 
    2175           0 : static void ospf6_stub_router_config_write(struct vty *vty, struct ospf6 *ospf6)
    2176             : {
    2177           0 :         if (CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER))
    2178           0 :                 vty_out(vty, " stub-router administrative\n");
    2179           0 :         return;
    2180             : }
    2181             : 
    2182           0 : static int ospf6_distance_config_write(struct vty *vty, struct ospf6 *ospf6)
    2183             : {
    2184           0 :         struct route_node *rn;
    2185           0 :         struct ospf6_distance *odistance;
    2186             : 
    2187           0 :         if (ospf6->distance_all)
    2188           0 :                 vty_out(vty, " distance %u\n", ospf6->distance_all);
    2189             : 
    2190           0 :         if (ospf6->distance_intra || ospf6->distance_inter
    2191           0 :             || ospf6->distance_external) {
    2192           0 :                 vty_out(vty, " distance ospf6");
    2193             : 
    2194           0 :                 if (ospf6->distance_intra)
    2195           0 :                         vty_out(vty, " intra-area %u", ospf6->distance_intra);
    2196           0 :                 if (ospf6->distance_inter)
    2197           0 :                         vty_out(vty, " inter-area %u", ospf6->distance_inter);
    2198           0 :                 if (ospf6->distance_external)
    2199           0 :                         vty_out(vty, " external %u", ospf6->distance_external);
    2200             : 
    2201           0 :                 vty_out(vty, "\n");
    2202             :         }
    2203             : 
    2204           0 :         for (rn = route_top(ospf6->distance_table); rn; rn = route_next(rn))
    2205           0 :                 if ((odistance = rn->info) != NULL)
    2206           0 :                         vty_out(vty, " distance %u %pFX %s\n",
    2207           0 :                                 odistance->distance, &rn->p,
    2208           0 :                                 odistance->access_list ? odistance->access_list
    2209             :                                                        : "");
    2210           0 :         return 0;
    2211             : }
    2212             : 
    2213           0 : static int ospf6_asbr_summary_config_write(struct vty *vty, struct ospf6 *ospf6)
    2214             : {
    2215           0 :         struct route_node *rn;
    2216           0 :         struct ospf6_external_aggr_rt *aggr;
    2217           0 :         char buf[PREFIX2STR_BUFFER];
    2218             : 
    2219           0 :         if (ospf6->aggr_delay_interval != OSPF6_EXTL_AGGR_DEFAULT_DELAY)
    2220           0 :                 vty_out(vty, " aggregation timer %u\n",
    2221             :                                 ospf6->aggr_delay_interval);
    2222             : 
    2223             :         /* print 'summary-address A:B::C:D/M' */
    2224           0 :         for (rn = route_top(ospf6->rt_aggr_tbl); rn; rn = route_next(rn)) {
    2225           0 :                 if (!rn->info)
    2226           0 :                         continue;
    2227             : 
    2228           0 :                 aggr = rn->info;
    2229             : 
    2230           0 :                 prefix2str(&aggr->p, buf, sizeof(buf));
    2231           0 :                 vty_out(vty, " summary-address %s", buf);
    2232           0 :                 if (aggr->tag)
    2233           0 :                         vty_out(vty, " tag %u", aggr->tag);
    2234             : 
    2235           0 :                 if (aggr->metric != -1)
    2236           0 :                         vty_out(vty, " metric %d", aggr->metric);
    2237             : 
    2238           0 :                 if (aggr->mtype != DEFAULT_METRIC_TYPE)
    2239           0 :                         vty_out(vty, " metric-type %d", aggr->mtype);
    2240             : 
    2241           0 :                 if (CHECK_FLAG(aggr->aggrflags,
    2242             :                                OSPF6_EXTERNAL_AGGRT_NO_ADVERTISE))
    2243           0 :                         vty_out(vty, " no-advertise");
    2244             : 
    2245           0 :                 vty_out(vty, "\n");
    2246             :         }
    2247             : 
    2248           0 :         return 0;
    2249             : }
    2250             : 
    2251             : /* OSPF configuration write function. */
    2252           0 : static int config_write_ospf6(struct vty *vty)
    2253             : {
    2254           0 :         struct ospf6 *ospf6;
    2255           0 :         struct listnode *node, *nnode;
    2256             : 
    2257             :         /* OSPFv3 configuration. */
    2258           0 :         if (om6 == NULL)
    2259             :                 return CMD_SUCCESS;
    2260             : 
    2261           0 :         for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
    2262           0 :                 if (ospf6->name && strcmp(ospf6->name, VRF_DEFAULT_NAME))
    2263           0 :                         vty_out(vty, "router ospf6 vrf %s\n", ospf6->name);
    2264             :                 else
    2265           0 :                         vty_out(vty, "router ospf6\n");
    2266             : 
    2267           0 :                 if (ospf6->router_id_static != 0)
    2268           0 :                         vty_out(vty, " ospf6 router-id %pI4\n",
    2269             :                                 &ospf6->router_id_static);
    2270             : 
    2271           0 :                 if (CHECK_FLAG(ospf6->config_flags,
    2272             :                                OSPF6_SEND_EXTRA_DATA_TO_ZEBRA))
    2273           0 :                         vty_out(vty, " ospf6 send-extra-data zebra\n");
    2274             : 
    2275             :                 /* log-adjacency-changes flag print. */
    2276           0 :                 if (CHECK_FLAG(ospf6->config_flags,
    2277             :                                OSPF6_LOG_ADJACENCY_CHANGES)) {
    2278           0 :                         if (CHECK_FLAG(ospf6->config_flags,
    2279             :                                        OSPF6_LOG_ADJACENCY_DETAIL))
    2280           0 :                                 vty_out(vty, " log-adjacency-changes detail\n");
    2281           0 :                         else if (!SAVE_OSPF6_LOG_ADJACENCY_CHANGES)
    2282           0 :                                 vty_out(vty, " log-adjacency-changes\n");
    2283           0 :                 } else if (SAVE_OSPF6_LOG_ADJACENCY_CHANGES) {
    2284           0 :                         vty_out(vty, " no log-adjacency-changes\n");
    2285             :                 }
    2286             : 
    2287           0 :                 if (ospf6->ref_bandwidth != OSPF6_REFERENCE_BANDWIDTH)
    2288           0 :                         vty_out(vty, " auto-cost reference-bandwidth %d\n",
    2289             :                                 ospf6->ref_bandwidth);
    2290             : 
    2291           0 :                 if (ospf6->write_oi_count
    2292             :                     != OSPF6_WRITE_INTERFACE_COUNT_DEFAULT)
    2293           0 :                         vty_out(vty, " write-multiplier %d\n",
    2294             :                                 ospf6->write_oi_count);
    2295             : 
    2296             :                 /* LSA timers print. */
    2297           0 :                 if (ospf6->lsa_minarrival != OSPF_MIN_LS_ARRIVAL)
    2298           0 :                         vty_out(vty, " timers lsa min-arrival %d\n",
    2299             :                                 ospf6->lsa_minarrival);
    2300             : 
    2301             :                 /* ECMP max path config */
    2302           0 :                 if (ospf6->max_multipath != MULTIPATH_NUM)
    2303           0 :                         vty_out(vty, " maximum-paths %d\n",
    2304             :                                 ospf6->max_multipath);
    2305             : 
    2306           0 :                 ospf6_stub_router_config_write(vty, ospf6);
    2307           0 :                 ospf6_redistribute_config_write(vty, ospf6);
    2308           0 :                 ospf6_area_config_write(vty, ospf6);
    2309           0 :                 ospf6_spf_config_write(vty, ospf6);
    2310           0 :                 ospf6_distance_config_write(vty, ospf6);
    2311           0 :                 ospf6_distribute_config_write(vty, ospf6);
    2312           0 :                 ospf6_asbr_summary_config_write(vty, ospf6);
    2313           0 :                 config_write_ospf6_gr(vty, ospf6);
    2314           0 :                 config_write_ospf6_gr_helper(vty, ospf6);
    2315             : 
    2316           0 :                 vty_out(vty, "exit\n");
    2317           0 :                 vty_out(vty, "!\n");
    2318             :         }
    2319             :         return 0;
    2320             : }
    2321             : 
    2322             : static int config_write_ospf6(struct vty *vty);
    2323             : /* OSPF6 node structure. */
    2324             : static struct cmd_node ospf6_node = {
    2325             :         .name = "ospf6",
    2326             :         .node = OSPF6_NODE,
    2327             :         .parent_node = CONFIG_NODE,
    2328             :         .prompt = "%s(config-ospf6)# ",
    2329             :         .config_write = config_write_ospf6,
    2330             : };
    2331             : 
    2332           4 : void install_element_ospf6_clear_process(void)
    2333             : {
    2334           4 :         install_element(ENABLE_NODE, &clear_router_ospf6_cmd);
    2335           4 : }
    2336             : 
    2337             : /* Install ospf related commands. */
    2338           4 : void ospf6_top_init(void)
    2339             : {
    2340             :         /* Install ospf6 top node. */
    2341           4 :         install_node(&ospf6_node);
    2342             : 
    2343           4 :         install_element(VIEW_NODE, &show_ipv6_ospf6_cmd);
    2344           4 :         install_element(VIEW_NODE, &show_ipv6_ospf6_vrfs_cmd);
    2345           4 :         install_element(CONFIG_NODE, &router_ospf6_cmd);
    2346           4 :         install_element(CONFIG_NODE, &no_router_ospf6_cmd);
    2347             : 
    2348           4 :         install_element(VIEW_NODE, &show_ipv6_ospf6_route_cmd);
    2349           4 :         install_element(VIEW_NODE, &show_ipv6_ospf6_route_match_cmd);
    2350           4 :         install_element(VIEW_NODE, &show_ipv6_ospf6_route_match_detail_cmd);
    2351           4 :         install_element(VIEW_NODE, &show_ipv6_ospf6_route_type_detail_cmd);
    2352             : 
    2353           4 :         install_default(OSPF6_NODE);
    2354           4 :         install_element(OSPF6_NODE, &ospf6_router_id_cmd);
    2355           4 :         install_element(OSPF6_NODE, &no_ospf6_router_id_cmd);
    2356           4 :         install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_cmd);
    2357           4 :         install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_detail_cmd);
    2358           4 :         install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_cmd);
    2359           4 :         install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_detail_cmd);
    2360           4 :         install_element(OSPF6_NODE, &ospf6_send_extra_data_cmd);
    2361             : 
    2362             :         /* LSA timers commands */
    2363           4 :         install_element(OSPF6_NODE, &ospf6_timers_lsa_cmd);
    2364           4 :         install_element(OSPF6_NODE, &no_ospf6_timers_lsa_cmd);
    2365             : 
    2366           4 :         install_element(OSPF6_NODE, &ospf6_interface_area_cmd);
    2367           4 :         install_element(OSPF6_NODE, &no_ospf6_interface_area_cmd);
    2368           4 :         install_element(OSPF6_NODE, &ospf6_stub_router_admin_cmd);
    2369           4 :         install_element(OSPF6_NODE, &no_ospf6_stub_router_admin_cmd);
    2370             : 
    2371             :         /* maximum-paths command */
    2372           4 :         install_element(OSPF6_NODE, &ospf6_max_multipath_cmd);
    2373           4 :         install_element(OSPF6_NODE, &no_ospf6_max_multipath_cmd);
    2374             : 
    2375             :         /* ASBR Summarisation */
    2376           4 :         install_element(OSPF6_NODE, &ospf6_external_route_aggregation_cmd);
    2377           4 :         install_element(OSPF6_NODE, &no_ospf6_external_route_aggregation_cmd);
    2378           4 :         install_element(OSPF6_NODE,
    2379             :                 &ospf6_external_route_aggregation_no_advertise_cmd);
    2380           4 :         install_element(OSPF6_NODE,
    2381             :                         &no_ospf6_external_route_aggregation_no_advertise_cmd);
    2382           4 :         install_element(OSPF6_NODE, &ospf6_route_aggregation_timer_cmd);
    2383           4 :         install_element(OSPF6_NODE, &no_ospf6_route_aggregation_timer_cmd);
    2384           4 :         install_element(VIEW_NODE, &show_ipv6_ospf6_external_aggregator_cmd);
    2385             : 
    2386           4 :         install_element(OSPF6_NODE, &ospf6_distance_cmd);
    2387           4 :         install_element(OSPF6_NODE, &no_ospf6_distance_cmd);
    2388           4 :         install_element(OSPF6_NODE, &ospf6_distance_ospf6_cmd);
    2389           4 :         install_element(OSPF6_NODE, &no_ospf6_distance_ospf6_cmd);
    2390           4 : }

Generated by: LCOV version v1.16-topotato