frr/ospf6d/ospf6_top.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

2366 lines
60 KiB
C
Raw Normal View History

2002-12-13 21:15:29 +01:00
/*
* Copyright (C) 2003 Yasuhiro Ohara
2002-12-13 21:15:29 +01:00
*
* This file is part of GNU Zebra.
*
* GNU Zebra is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2002-12-13 21:15:29 +01:00
*/
#include <zebra.h>
#include "log.h"
#include "memory.h"
#include "vty.h"
#include "linklist.h"
#include "prefix.h"
#include "table.h"
#include "thread.h"
#include "command.h"
#include "defaults.h"
#include "lib/json.h"
#include "lib_errors.h"
2002-12-13 21:15:29 +01:00
#include "ospf6_proto.h"
#include "ospf6_message.h"
2002-12-13 21:15:29 +01:00
#include "ospf6_lsa.h"
#include "ospf6_lsdb.h"
#include "ospf6_route.h"
#include "ospf6_zebra.h"
#include "ospf6_top.h"
#include "ospf6_area.h"
#include "ospf6_interface.h"
#include "ospf6_neighbor.h"
#include "ospf6_network.h"
2002-12-13 21:15:29 +01:00
#include "ospf6_flood.h"
#include "ospf6_asbr.h"
#include "ospf6_abr.h"
#include "ospf6_intra.h"
#include "ospf6_spf.h"
#include "ospf6d.h"
#include "ospf6_gr.h"
#include "lib/json.h"
#include "ospf6_nssa.h"
2002-12-13 21:15:29 +01:00
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_TOP, "OSPF6 top");
DEFINE_QOBJ_TYPE(ospf6);
FRR_CFG_DEFAULT_BOOL(OSPF6_LOG_ADJACENCY_CHANGES,
{ .val_bool = true, .match_profile = "datacenter", },
{ .val_bool = false },
);
#ifndef VTYSH_EXTRACT_PL
#include "ospf6d/ospf6_top_clippy.c"
#endif
2002-12-13 21:15:29 +01:00
/* global ospf6d variable */
static struct ospf6_master ospf6_master;
struct ospf6_master *om6;
2002-12-13 21:15:29 +01:00
static void ospf6_disable(struct ospf6 *o);
static void ospf6_add(struct ospf6 *ospf6)
{
listnode_add(om6->ospf6, ospf6);
}
static void ospf6_del(struct ospf6 *ospf6)
{
listnode_delete(om6->ospf6, ospf6);
}
const char *ospf6_vrf_id_to_name(vrf_id_t vrf_id)
{
struct vrf *vrf = vrf_lookup_by_id(vrf_id);
return vrf ? vrf->name : "NIL";
}
/* Link OSPF instance to VRF. */
void ospf6_vrf_link(struct ospf6 *ospf6, struct vrf *vrf)
{
ospf6->vrf_id = vrf->vrf_id;
if (vrf->info != (void *)ospf6)
vrf->info = (void *)ospf6;
}
/* Unlink OSPF instance from VRF. */
void ospf6_vrf_unlink(struct ospf6 *ospf6, struct vrf *vrf)
{
if (vrf->info == (void *)ospf6)
vrf->info = NULL;
ospf6->vrf_id = VRF_UNKNOWN;
}
struct ospf6 *ospf6_lookup_by_vrf_id(vrf_id_t vrf_id)
{
struct vrf *vrf = NULL;
vrf = vrf_lookup_by_id(vrf_id);
if (!vrf)
return NULL;
return (vrf->info) ? (struct ospf6 *)vrf->info : NULL;
}
struct ospf6 *ospf6_lookup_by_vrf_name(const char *name)
{
struct ospf6 *o = NULL;
struct listnode *node, *nnode;
for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, o)) {
if (((o->name == NULL && name == NULL)
|| (o->name && name && strcmp(o->name, name) == 0)))
return o;
}
return NULL;
}
/* This is hook function for vrf create called as part of vrf_init */
static int ospf6_vrf_new(struct vrf *vrf)
{
return 0;
}
/* This is hook function for vrf delete call as part of vrf_init */
static int ospf6_vrf_delete(struct vrf *vrf)
{
return 0;
}
static void ospf6_set_redist_vrf_bitmaps(struct ospf6 *ospf6, bool set)
{
int type;
struct list *red_list;
for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
red_list = ospf6->redist[type];
if (!red_list)
continue;
if (IS_OSPF6_DEBUG_ZEBRA(RECV))
zlog_debug(
"%s: setting redist vrf %d bitmap for type %d",
__func__, ospf6->vrf_id, type);
if (set)
vrf_bitmap_set(zclient->redist[AFI_IP6][type],
ospf6->vrf_id);
else
vrf_bitmap_unset(zclient->redist[AFI_IP6][type],
ospf6->vrf_id);
}
red_list = ospf6->redist[DEFAULT_ROUTE];
if (red_list) {
if (set)
vrf_bitmap_set(zclient->default_information[AFI_IP6],
ospf6->vrf_id);
else
vrf_bitmap_unset(zclient->default_information[AFI_IP6],
ospf6->vrf_id);
}
}
/* Disable OSPF6 VRF instance */
static int ospf6_vrf_disable(struct vrf *vrf)
{
struct ospf6 *ospf6 = NULL;
if (vrf->vrf_id == VRF_DEFAULT)
return 0;
ospf6 = ospf6_lookup_by_vrf_name(vrf->name);
if (ospf6) {
ospf6_zebra_vrf_deregister(ospf6);
ospf6_set_redist_vrf_bitmaps(ospf6, false);
/* We have instance configured, unlink
* from VRF and make it "down".
*/
ospf6_vrf_unlink(ospf6, vrf);
thread_cancel(&ospf6->t_ospf6_receive);
close(ospf6->fd);
ospf6->fd = -1;
}
/* Note: This is a callback, the VRF will be deleted by the caller. */
return 0;
}
/* Enable OSPF6 VRF instance */
static int ospf6_vrf_enable(struct vrf *vrf)
{
struct ospf6 *ospf6 = NULL;
vrf_id_t old_vrf_id;
int ret = 0;
ospf6 = ospf6_lookup_by_vrf_name(vrf->name);
if (ospf6) {
old_vrf_id = ospf6->vrf_id;
/* We have instance configured, link to VRF and make it "up". */
ospf6_vrf_link(ospf6, vrf);
if (old_vrf_id != ospf6->vrf_id) {
ospf6_set_redist_vrf_bitmaps(ospf6, true);
/* start zebra redist to us for new vrf */
ospf6_zebra_vrf_register(ospf6);
ret = ospf6_serv_sock(ospf6);
if (ret < 0 || ospf6->fd <= 0)
return 0;
thread_add_read(master, ospf6_receive, ospf6, ospf6->fd,
&ospf6->t_ospf6_receive);
ospf6_router_id_update(ospf6, true);
}
}
return 0;
}
void ospf6_vrf_init(void)
{
vrf_init(ospf6_vrf_new, ospf6_vrf_enable, ospf6_vrf_disable,
*: rework renaming the default VRF Currently, it is possible to rename the default VRF either by passing `-o` option to zebra or by creating a file in `/var/run/netns` and binding it to `/proc/self/ns/net`. In both cases, only zebra knows about the rename and other daemons learn about it only after they connect to zebra. This is a problem, because daemons may read their config before they connect to zebra. To handle this rename after the config is read, we have some special code in every single daemon, which is not very bad but not desirable in my opinion. But things are getting worse when we need to handle this in northbound layer as we have to manually rewrite the config nodes. This approach is already hacky, but still works as every daemon handles its own NB structures. But it is completely incompatible with the central management daemon architecture we are aiming for, as mgmtd doesn't even have a connection with zebra to learn from it. And it shouldn't have it, because operational state changes should never affect configuration. To solve the problem and simplify the code, I propose to expand the `-o` option to all daemons. By using the startup option, we let daemons know about the rename before they read their configs so we don't need any special code to deal with it. There's an easy way to pass the option to all daemons by using `frr_global_options` variable. Unfortunately, the second way of renaming by creating a file in `/var/run/netns` is incompatible with the new mgmtd architecture. Theoretically, we could force daemons to read their configs only after they connect to zebra, but it means adding even more code to handle a very specific use-case. And anyway this won't work for mgmtd as it doesn't have a connection with zebra. So I had to remove this option. Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
2021-12-03 23:22:55 +01:00
ospf6_vrf_delete);
vrf_cmd_init(NULL);
}
static void ospf6_top_lsdb_hook_add(struct ospf6_lsa *lsa)
2002-12-13 21:15:29 +01:00
{
switch (ntohs(lsa->header->type)) {
case OSPF6_LSTYPE_AS_EXTERNAL:
ospf6_asbr_lsa_add(lsa);
break;
default:
break;
2002-12-13 21:15:29 +01:00
}
}
static void ospf6_top_lsdb_hook_remove(struct ospf6_lsa *lsa)
2002-12-13 21:15:29 +01:00
{
switch (ntohs(lsa->header->type)) {
case OSPF6_LSTYPE_AS_EXTERNAL:
ospf6_asbr_lsa_remove(lsa, NULL);
break;
default:
break;
2002-12-13 21:15:29 +01:00
}
}
static void ospf6_top_route_hook_add(struct ospf6_route *route)
{
struct ospf6 *ospf6 = NULL;
struct ospf6_area *oa = NULL;
if (route->table->scope_type == OSPF6_SCOPE_TYPE_GLOBAL)
ospf6 = route->table->scope;
else if (route->table->scope_type == OSPF6_SCOPE_TYPE_AREA) {
oa = (struct ospf6_area *)route->table->scope;
ospf6 = oa->ospf6;
} else {
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)
|| IS_OSPF6_DEBUG_BROUTER)
zlog_debug(
"%s: Route is not GLOBAL or scope is not of TYPE_AREA: %pFX",
__func__, &route->prefix);
return;
}
ospf6_abr_originate_summary(route, ospf6);
ospf6_zebra_route_update_add(route, ospf6);
}
static void ospf6_top_route_hook_remove(struct ospf6_route *route)
{
struct ospf6 *ospf6 = NULL;
struct ospf6_area *oa = NULL;
if (route->table->scope_type == OSPF6_SCOPE_TYPE_GLOBAL)
ospf6 = route->table->scope;
else if (route->table->scope_type == OSPF6_SCOPE_TYPE_AREA) {
oa = (struct ospf6_area *)route->table->scope;
ospf6 = oa->ospf6;
} else {
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)
|| IS_OSPF6_DEBUG_BROUTER)
zlog_debug(
"%s: Route is not GLOBAL or scope is not of TYPE_AREA: %pFX",
__func__, &route->prefix);
return;
}
route->flag |= OSPF6_ROUTE_REMOVE;
ospf6_abr_originate_summary(route, ospf6);
ospf6_zebra_route_update_remove(route, ospf6);
}
static void ospf6_top_brouter_hook_add(struct ospf6_route *route)
{
struct ospf6 *ospf6 = route->table->scope;
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL) ||
IS_OSPF6_DEBUG_BROUTER) {
uint32_t brouter_id;
char brouter_name[16];
brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
inet_ntop(AF_INET, &brouter_id, brouter_name,
sizeof(brouter_name));
zlog_debug("%s: brouter %s add with adv router %x nh count %u",
__func__, brouter_name,
route->path.origin.adv_router,
listcount(route->nh_list));
}
ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix), route,
ospf6);
ospf6_asbr_lsentry_add(route, ospf6);
ospf6_abr_originate_summary(route, ospf6);
}
static void ospf6_top_brouter_hook_remove(struct ospf6_route *route)
{
struct ospf6 *ospf6 = route->table->scope;
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL) ||
IS_OSPF6_DEBUG_BROUTER) {
uint32_t brouter_id;
char brouter_name[16];
brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
inet_ntop(AF_INET, &brouter_id, brouter_name,
sizeof(brouter_name));
zlog_debug("%s: brouter %p %s del with adv router %x nh %u",
__func__, (void *)route, brouter_name,
route->path.origin.adv_router,
listcount(route->nh_list));
}
route->flag |= OSPF6_ROUTE_REMOVE;
ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix), route,
ospf6);
ospf6_asbr_lsentry_remove(route, ospf6);
ospf6_abr_originate_summary(route, ospf6);
}
static struct ospf6 *ospf6_create(const char *name)
2002-12-13 21:15:29 +01:00
{
struct ospf6 *o;
struct vrf *vrf = NULL;
2002-12-13 21:15:29 +01:00
o = XCALLOC(MTYPE_OSPF6_TOP, sizeof(struct ospf6));
2002-12-13 21:15:29 +01:00
vrf = vrf_lookup_by_name(name);
if (vrf) {
o->vrf_id = vrf->vrf_id;
} else
o->vrf_id = VRF_UNKNOWN;
/* Freed in ospf6_delete */
o->name = XSTRDUP(MTYPE_OSPF6_TOP, name);
if (vrf)
ospf6_vrf_link(o, vrf);
ospf6_zebra_vrf_register(o);
/* initialize */
monotime(&o->starttime);
o->area_list = list_new();
o->area_list->cmp = ospf6_area_cmp;
o->lsdb = ospf6_lsdb_create(o);
o->lsdb_self = ospf6_lsdb_create(o);
o->lsdb->hook_add = ospf6_top_lsdb_hook_add;
o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove;
2002-12-13 21:15:29 +01:00
o->spf_delay = OSPF_SPF_DELAY_DEFAULT;
o->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
o->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
o->spf_hold_multiplier = 1;
o->default_originate = DEFAULT_ORIGINATE_NONE;
o->redistribute = 0;
/* LSA timers value init */
o->lsa_minarrival = OSPF_MIN_LS_ARRIVAL;
o->route_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, ROUTES);
o->route_table->scope = o;
o->route_table->hook_add = ospf6_top_route_hook_add;
o->route_table->hook_remove = ospf6_top_route_hook_remove;
2002-12-13 21:15:29 +01:00
o->brouter_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, BORDER_ROUTERS);
o->brouter_table->scope = o;
o->brouter_table->hook_add = ospf6_top_brouter_hook_add;
o->brouter_table->hook_remove = ospf6_top_brouter_hook_remove;
o->external_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, EXTERNAL_ROUTES);
o->external_table->scope = o;
/* Setting this to 1, so that the LS ID 0 can be considered as invalid
* for self originated external LSAs. This helps in differentiating if
* an LSA is originated for any route or not in the route data.
* rt->route_option->id is by default 0
* Consider a route having id as 0 and prefix as 1::1, an external LSA
* is originated with ID 0.0.0.0. Now consider another route 2::2
* and for this LSA was not originated because of some configuration
* but the ID field rt->route_option->id is still 0.Consider now this
* 2::2 is being deleted, it will search LSA with LS ID as 0 and it
* will find the LSA and hence delete it but the LSA belonged to prefix
* 1::1, this happened because of LS ID 0.
*/
o->external_id = OSPF6_EXT_INIT_LS_ID;
2002-12-13 21:15:29 +01:00
o->write_oi_count = OSPF6_WRITE_INTERFACE_COUNT_DEFAULT;
o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH;
o->distance_table = route_table_init();
o->rt_aggr_tbl = route_table_init();
o->aggr_delay_interval = OSPF6_EXTL_AGGR_DEFAULT_DELAY;
o->aggr_action = OSPF6_ROUTE_AGGR_NONE;
o->fd = -1;
o->max_multipath = MULTIPATH_NUM;
SET_FLAG(o->config_flags, OSPF6_SEND_EXTRA_DATA_TO_ZEBRA);
o->oi_write_q = list_new();
ospf6_gr_helper_init(o);
QOBJ_REG(o, ospf6);
/* Make ospf protocol socket. */
ospf6_serv_sock(o);
return o;
2002-12-13 21:15:29 +01:00
}
struct ospf6 *ospf6_instance_create(const char *name)
{
struct ospf6 *ospf6;
struct vrf *vrf;
struct interface *ifp;
ospf6 = ospf6_create(name);
if (DFLT_OSPF6_LOG_ADJACENCY_CHANGES)
SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
if (ospf6->router_id == 0)
ospf6_router_id_update(ospf6, true);
ospf6_add(ospf6);
if (ospf6->vrf_id != VRF_UNKNOWN) {
vrf = vrf_lookup_by_id(ospf6->vrf_id);
FOR_ALL_INTERFACES (vrf, ifp) {
if (ifp->info)
ospf6_interface_start(ifp->info);
}
}
if (ospf6->fd < 0)
return ospf6;
/*
* Read from non-volatile memory whether this instance is performing a
* graceful restart or not.
*/
ospf6_gr_nvm_read(ospf6);
thread_add_read(master, ospf6_receive, ospf6, ospf6->fd,
&ospf6->t_ospf6_receive);
return ospf6;
}
void ospf6_delete(struct ospf6 *o)
2002-12-13 21:15:29 +01:00
{
struct listnode *node, *nnode;
struct route_node *rn = NULL;
struct ospf6_area *oa;
struct vrf *vrf;
2002-12-13 21:15:29 +01:00
QOBJ_UNREG(o);
ospf6_gr_helper_deinit(o);
if (!o->gr_info.prepare_in_progress)
ospf6_flush_self_originated_lsas_now(o);
ospf6_disable(o);
ospf6_del(o);
ospf6_zebra_vrf_deregister(o);
ospf6_serv_close(&o->fd);
for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa))
ospf6_area_delete(oa);
list_delete(&o->area_list);
2002-12-13 21:15:29 +01:00
ospf6_lsdb_delete(o->lsdb);
ospf6_lsdb_delete(o->lsdb_self);
2002-12-13 21:15:29 +01:00
ospf6_route_table_delete(o->route_table);
ospf6_route_table_delete(o->brouter_table);
2002-12-13 21:15:29 +01:00
ospf6_route_table_delete(o->external_table);
2002-12-13 21:15:29 +01:00
ospf6_distance_reset(o);
route_table_finish(o->distance_table);
list_delete(&o->oi_write_q);
if (o->vrf_id != VRF_UNKNOWN) {
vrf = vrf_lookup_by_id(o->vrf_id);
if (vrf)
ospf6_vrf_unlink(o, vrf);
}
for (rn = route_top(o->rt_aggr_tbl); rn; rn = route_next(rn))
if (rn->info)
ospf6_external_aggregator_free(rn->info);
route_table_finish(o->rt_aggr_tbl);
XFREE(MTYPE_OSPF6_TOP, o->name);
XFREE(MTYPE_OSPF6_TOP, o);
}
2002-12-13 21:15:29 +01:00
static void ospf6_disable(struct ospf6 *o)
2002-12-13 21:15:29 +01:00
{
struct listnode *node, *nnode;
struct ospf6_area *oa;
if (!CHECK_FLAG(o->flag, OSPF6_DISABLED)) {
SET_FLAG(o->flag, OSPF6_DISABLED);
for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa))
ospf6_area_disable(oa);
/* XXX: This also changes persistent settings */
/* Unregister redistribution */
ospf6_asbr_redistribute_disable(o);
ospf6_lsdb_remove_all(o->lsdb);
ospf6_route_remove_all(o->route_table);
ospf6_route_remove_all(o->brouter_table);
THREAD_OFF(o->maxage_remover);
THREAD_OFF(o->t_spf_calc);
THREAD_OFF(o->t_ase_calc);
THREAD_OFF(o->t_distribute_update);
THREAD_OFF(o->t_ospf6_receive);
THREAD_OFF(o->t_external_aggr);
THREAD_OFF(o->gr_info.t_grace_period);
ospf6d: Prevent use after free I encountered a crash where the ospf6_write thread was already thought to be scheduled by ospf6d: (gdb) bt t_ptr=0x5624ee6bd260) at lib/thread.c:972 (gdb) When poking around it was noticed that the ospf6 pointer was crap: (gdb) p (struct ospf6 *)$7 $8 = (struct ospf6 *) 0x5624ee6c6b20 (gdb) p *$8 $9 = {vrf_id = 3998487040, name = 0x5624ee420010 "\a", router_id = 65892, router_id_static = 65892, router_id_zebra = 0, starttime = {tv_sec = 1654674, tv_usec = 678673}, area_list = 0x0, backbone = 0x5624ee6c6710, lsdb = 0x5624ee6c2370, lsdb_self = 0x5624ee6c5d80, route_table = 0x5624ee6c5c10, brouter_table = 0x5624ee6c4690, external_table = 0x5624ee6c4710, external_id_table = 0x5624ee6c4f10, external_id = 24, redist = {0x0 <repeats 32 times>}, nssa_default_import_check = {refcnt = 0, status = false}, flag = 1 '\001', redistribute = 0, config_flags = 0 '\000', default_originate = 0, lsa_minarrival = 1000, spf_delay = 0, spf_holdtime = 50, spf_max_holdtime = 5000, spf_hold_multiplier = 1, spf_reason = 554, ts_spf = {tv_sec = 1654712, tv_usec = 122041}, ts_spf_duration = {tv_sec = 0, tv_usec = 48}, last_spf_reason = 11, fd = -1, t_spf_calc = 0x0, t_ase_calc = 0x0, maxage_remover = 0x0, t_distribute_update = 0x0, t_ospf6_receive = 0x0, t_external_aggr = 0x0, t_write = 0x5624ee6cc930, write_oi_count = 20, ref_bandwidth = 100000, distance_all = 0 '\000', distance_intra = 0 '\000', distance_inter = 0 '\000', distance_external = 0 '\000', distance_table = 0x5624ee6c4f50, inst_shutdown = 1 '\001', max_multipath = 128, gr_info = {restart_support = false, restart_in_progress = false, prepare_in_progress = false, finishing_restart = false, grace_period = 0, t_grace_period = 0x0}, ospf6_helper_cfg = {supported_grace_time = 1800, is_helper_supported = false, strict_lsa_check = true, only_planned_restart = false, enable_rtr_list = 0x0, active_restarter_cnt = 0, last_exit_reason = 0}, anyNSSA = 0 '\000', t_abr_task = 0x0, oi_write_q = 0x0, redist_count = 0, aggr_action = 1, aggr_delay_interval = 6, rt_aggr_tbl = 0x5624ee6c51b0, qobj_node = {nid = 6163304287853836241, nodehash = {hi = {next = 0x0, hashval = 1613461457}}, type = 0x5624ed65e4e0 <qobj_t_ospf6>}} Upon code inspection there was no place where we disabled the t_write thread upon ospf6 deletion. If the code were to issue a `no router ospf6` and then recreate it. We could see this crash. Signed-off-by: Donald Sharp <sharpd@nvidia.com>
2021-11-18 00:46:06 +01:00
THREAD_OFF(o->t_write);
THREAD_OFF(o->t_abr_task);
}
}
2002-12-13 21:15:29 +01:00
void ospf6_master_init(struct thread_master *master)
{
memset(&ospf6_master, 0, sizeof(struct ospf6_master));
om6 = &ospf6_master;
om6->ospf6 = list_new();
om6->master = master;
}
static int ospf6_maxage_remover(struct thread *thread)
{
struct ospf6 *o = (struct ospf6 *)THREAD_ARG(thread);
struct ospf6_area *oa;
struct ospf6_interface *oi;
struct ospf6_neighbor *on;
struct listnode *i, *j, *k;
int reschedule = 0;
for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) {
for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) {
for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on)) {
if (on->state != OSPF6_NEIGHBOR_EXCHANGE
&& on->state != OSPF6_NEIGHBOR_LOADING)
continue;
ospf6_maxage_remove(o);
return 0;
2002-12-13 21:15:29 +01:00
}
}
}
for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) {
for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) {
if (ospf6_lsdb_maxage_remover(oi->lsdb)) {
reschedule = 1;
}
}
if (ospf6_lsdb_maxage_remover(oa->lsdb)) {
reschedule = 1;
}
}
if (ospf6_lsdb_maxage_remover(o->lsdb)) {
reschedule = 1;
}
if (reschedule) {
ospf6_maxage_remove(o);
}
return 0;
2002-12-13 21:15:29 +01:00
}
void ospf6_maxage_remove(struct ospf6 *o)
2002-12-13 21:15:29 +01:00
{
if (o)
thread_add_timer(master, ospf6_maxage_remover, o,
OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT,
&o->maxage_remover);
2002-12-13 21:15:29 +01:00
}
bool ospf6_router_id_update(struct ospf6 *ospf6, bool init)
{
in_addr_t new_router_id;
struct listnode *node;
struct ospf6_area *oa;
if (!ospf6)
return true;
if (ospf6->router_id_static != 0)
new_router_id = ospf6->router_id_static;
else
new_router_id = ospf6->router_id_zebra;
if (ospf6->router_id == new_router_id)
return true;
if (!init)
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
if (oa->full_nbrs) {
zlog_err(
"%s: cannot update router-id. Run the \"clear ipv6 ospf6 process\" command",
__func__);
return false;
}
}
ospf6->router_id = new_router_id;
return true;
}
/* start ospf6 */
DEFUN_NOSH(router_ospf6, router_ospf6_cmd, "router ospf6 [vrf NAME]",
ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR)
2002-12-13 21:15:29 +01:00
{
struct ospf6 *ospf6;
const char *vrf_name = VRF_DEFAULT_NAME;
int idx_vrf = 0;
if (argv_find(argv, argc, "vrf", &idx_vrf)) {
vrf_name = argv[idx_vrf + 1]->arg;
}
ospf6 = ospf6_lookup_by_vrf_name(vrf_name);
if (ospf6 == NULL)
ospf6 = ospf6_instance_create(vrf_name);
/* set current ospf point. */
VTY_PUSH_CONTEXT(OSPF6_NODE, ospf6);
return CMD_SUCCESS;
2002-12-13 21:15:29 +01:00
}
/* stop ospf6 */
DEFUN(no_router_ospf6, no_router_ospf6_cmd, "no router ospf6 [vrf NAME]",
NO_STR ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR)
2002-12-13 21:15:29 +01:00
{
struct ospf6 *ospf6;
const char *vrf_name = VRF_DEFAULT_NAME;
int idx_vrf = 0;
if (argv_find(argv, argc, "vrf", &idx_vrf)) {
vrf_name = argv[idx_vrf + 1]->arg;
}
ospf6 = ospf6_lookup_by_vrf_name(vrf_name);
if (ospf6 == NULL)
vty_out(vty, "OSPFv3 is not configured\n");
else {
ospf6_delete(ospf6);
ospf6 = NULL;
}
/* return to config node . */
VTY_PUSH_CONTEXT_NULL(CONFIG_NODE);
return CMD_SUCCESS;
2002-12-13 21:15:29 +01:00
}
static void ospf6_db_clear(struct ospf6 *ospf6)
{
struct ospf6_interface *oi;
struct interface *ifp;
struct vrf *vrf = vrf_lookup_by_id(ospf6->vrf_id);
struct listnode *node, *nnode;
struct ospf6_area *oa;
FOR_ALL_INTERFACES (vrf, ifp) {
if (if_is_operative(ifp) && ifp->info != NULL) {
oi = (struct ospf6_interface *)ifp->info;
ospf6_lsdb_remove_all(oi->lsdb);
ospf6_lsdb_remove_all(oi->lsdb_self);
ospf6_lsdb_remove_all(oi->lsupdate_list);
ospf6_lsdb_remove_all(oi->lsack_list);
}
}
for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
ospf6_lsdb_remove_all(oa->lsdb);
ospf6_lsdb_remove_all(oa->lsdb_self);
ospf6_spf_table_finish(oa->spf_table);
ospf6_route_remove_all(oa->route_table);
}
ospf6_lsdb_remove_all(ospf6->lsdb);
ospf6_lsdb_remove_all(ospf6->lsdb_self);
ospf6_route_remove_all(ospf6->route_table);
ospf6_route_remove_all(ospf6->brouter_table);
}
static void ospf6_process_reset(struct ospf6 *ospf6)
{
struct interface *ifp;
struct vrf *vrf = vrf_lookup_by_id(ospf6->vrf_id);
ospf6_unset_all_aggr_flag(ospf6);
ospf6_flush_self_originated_lsas_now(ospf6);
ospf6->inst_shutdown = 0;
ospf6_db_clear(ospf6);
ospf6_asbr_redistribute_reset(ospf6);
FOR_ALL_INTERFACES (vrf, ifp)
ospf6_interface_clear(ifp);
}
DEFPY (clear_router_ospf6,
clear_router_ospf6_cmd,
"clear ipv6 ospf6 process [vrf NAME$name]",
CLEAR_STR
IP6_STR
OSPF6_STR
"Reset OSPF Process\n"
VRF_CMD_HELP_STR)
{
struct ospf6 *ospf6;
const char *vrf_name = VRF_DEFAULT_NAME;
if (name != NULL)
vrf_name = name;
ospf6 = ospf6_lookup_by_vrf_name(vrf_name);
ospf6d: reset areas and redistribution at router-id modification The ospf6 router-id is provided by order of preference by: ospf6d itself if the "ospf6 router-id X.X.X.X" command is set. - zebra. If the "ip router-id X.X.X.X" zebra command is set, the configured IP is provided as the ID or alternatively the highest loopback IPv4 address or else the highest interface IPv4 address. The running ospf6 router-id is stored in ospf6->router-id. ospf6->router-id can change in the following conditions: - A configuration change provides a new router-id value according to the above rules. ospf6->router-id is updated to the new value if there is no adjacency in FULL state. Otherwise, the ospf6d process must be restarted to take the new router-id into account. - On startup of both zebra and ospf6d, if ospf6d has not yet received a valid router-id, ospf6d->router-id is set to 0 (i.e. 0.0.0.0). Then, zebra notifies ospf6d that the router-id is available. At ospf6->router-id, the current behavior of ospf6d is the following: - The self generated LSAs that refer to the previous router-id as the advertising router are kept. - Self generated LSAs are created with router-id value. - LSAs from the redistribution that refer to the previous router-id are kept and no new redistribution LSAs are created. As a consequence, the routers in the ospf6 areas will get incorrect LSAs and might not be able to install prefixes of those LSAs into their RIB. This fix solves this issue by resetting the areas and the redistribution when ospf6->router-id updated. Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
2021-06-10 11:30:05 +02:00
if (ospf6 == NULL) {
vty_out(vty, "OSPFv3 is not configured\n");
ospf6d: reset areas and redistribution at router-id modification The ospf6 router-id is provided by order of preference by: ospf6d itself if the "ospf6 router-id X.X.X.X" command is set. - zebra. If the "ip router-id X.X.X.X" zebra command is set, the configured IP is provided as the ID or alternatively the highest loopback IPv4 address or else the highest interface IPv4 address. The running ospf6 router-id is stored in ospf6->router-id. ospf6->router-id can change in the following conditions: - A configuration change provides a new router-id value according to the above rules. ospf6->router-id is updated to the new value if there is no adjacency in FULL state. Otherwise, the ospf6d process must be restarted to take the new router-id into account. - On startup of both zebra and ospf6d, if ospf6d has not yet received a valid router-id, ospf6d->router-id is set to 0 (i.e. 0.0.0.0). Then, zebra notifies ospf6d that the router-id is available. At ospf6->router-id, the current behavior of ospf6d is the following: - The self generated LSAs that refer to the previous router-id as the advertising router are kept. - Self generated LSAs are created with router-id value. - LSAs from the redistribution that refer to the previous router-id are kept and no new redistribution LSAs are created. As a consequence, the routers in the ospf6 areas will get incorrect LSAs and might not be able to install prefixes of those LSAs into their RIB. This fix solves this issue by resetting the areas and the redistribution when ospf6->router-id updated. Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
2021-06-10 11:30:05 +02:00
} else {
ospf6_router_id_update(ospf6, true);
ospf6_process_reset(ospf6);
ospf6d: reset areas and redistribution at router-id modification The ospf6 router-id is provided by order of preference by: ospf6d itself if the "ospf6 router-id X.X.X.X" command is set. - zebra. If the "ip router-id X.X.X.X" zebra command is set, the configured IP is provided as the ID or alternatively the highest loopback IPv4 address or else the highest interface IPv4 address. The running ospf6 router-id is stored in ospf6->router-id. ospf6->router-id can change in the following conditions: - A configuration change provides a new router-id value according to the above rules. ospf6->router-id is updated to the new value if there is no adjacency in FULL state. Otherwise, the ospf6d process must be restarted to take the new router-id into account. - On startup of both zebra and ospf6d, if ospf6d has not yet received a valid router-id, ospf6d->router-id is set to 0 (i.e. 0.0.0.0). Then, zebra notifies ospf6d that the router-id is available. At ospf6->router-id, the current behavior of ospf6d is the following: - The self generated LSAs that refer to the previous router-id as the advertising router are kept. - Self generated LSAs are created with router-id value. - LSAs from the redistribution that refer to the previous router-id are kept and no new redistribution LSAs are created. As a consequence, the routers in the ospf6 areas will get incorrect LSAs and might not be able to install prefixes of those LSAs into their RIB. This fix solves this issue by resetting the areas and the redistribution when ospf6->router-id updated. Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
2021-06-10 11:30:05 +02:00
}
return CMD_SUCCESS;
}
/* change Router_ID commands. */
DEFUN(ospf6_router_id,
ospf6_router_id_cmd,
"ospf6 router-id A.B.C.D",
OSPF6_STR
"Configure OSPF6 Router-ID\n"
V4NOTATION_STR)
2002-12-13 21:15:29 +01:00
{
VTY_DECLVAR_CONTEXT(ospf6, o);
int idx = 0;
int ret;
const char *router_id_str;
uint32_t router_id;
argv_find(argv, argc, "A.B.C.D", &idx);
router_id_str = argv[idx]->arg;
ret = inet_pton(AF_INET, router_id_str, &router_id);
if (ret == 0) {
vty_out(vty, "malformed OSPF Router-ID: %s\n", router_id_str);
return CMD_SUCCESS;
}
2004-10-11 19:02:40 +02:00
o->router_id_static = router_id;
ospf6d: reset areas and redistribution at router-id modification The ospf6 router-id is provided by order of preference by: ospf6d itself if the "ospf6 router-id X.X.X.X" command is set. - zebra. If the "ip router-id X.X.X.X" zebra command is set, the configured IP is provided as the ID or alternatively the highest loopback IPv4 address or else the highest interface IPv4 address. The running ospf6 router-id is stored in ospf6->router-id. ospf6->router-id can change in the following conditions: - A configuration change provides a new router-id value according to the above rules. ospf6->router-id is updated to the new value if there is no adjacency in FULL state. Otherwise, the ospf6d process must be restarted to take the new router-id into account. - On startup of both zebra and ospf6d, if ospf6d has not yet received a valid router-id, ospf6d->router-id is set to 0 (i.e. 0.0.0.0). Then, zebra notifies ospf6d that the router-id is available. At ospf6->router-id, the current behavior of ospf6d is the following: - The self generated LSAs that refer to the previous router-id as the advertising router are kept. - Self generated LSAs are created with router-id value. - LSAs from the redistribution that refer to the previous router-id are kept and no new redistribution LSAs are created. As a consequence, the routers in the ospf6 areas will get incorrect LSAs and might not be able to install prefixes of those LSAs into their RIB. This fix solves this issue by resetting the areas and the redistribution when ospf6->router-id updated. Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
2021-06-10 11:30:05 +02:00
if (ospf6_router_id_update(o, false))
ospf6_process_reset(o);
else
vty_out(vty,
"For this router-id change to take effect run the \"clear ipv6 ospf6 process\" command\n");
2004-10-11 19:02:40 +02:00
return CMD_SUCCESS;
2002-12-13 21:15:29 +01:00
}
DEFUN(no_ospf6_router_id,
no_ospf6_router_id_cmd,
"no ospf6 router-id [A.B.C.D]",
NO_STR OSPF6_STR
"Configure OSPF6 Router-ID\n"
V4NOTATION_STR)
{
VTY_DECLVAR_CONTEXT(ospf6, o);
o->router_id_static = 0;
ospf6d: reset areas and redistribution at router-id modification The ospf6 router-id is provided by order of preference by: ospf6d itself if the "ospf6 router-id X.X.X.X" command is set. - zebra. If the "ip router-id X.X.X.X" zebra command is set, the configured IP is provided as the ID or alternatively the highest loopback IPv4 address or else the highest interface IPv4 address. The running ospf6 router-id is stored in ospf6->router-id. ospf6->router-id can change in the following conditions: - A configuration change provides a new router-id value according to the above rules. ospf6->router-id is updated to the new value if there is no adjacency in FULL state. Otherwise, the ospf6d process must be restarted to take the new router-id into account. - On startup of both zebra and ospf6d, if ospf6d has not yet received a valid router-id, ospf6d->router-id is set to 0 (i.e. 0.0.0.0). Then, zebra notifies ospf6d that the router-id is available. At ospf6->router-id, the current behavior of ospf6d is the following: - The self generated LSAs that refer to the previous router-id as the advertising router are kept. - Self generated LSAs are created with router-id value. - LSAs from the redistribution that refer to the previous router-id are kept and no new redistribution LSAs are created. As a consequence, the routers in the ospf6 areas will get incorrect LSAs and might not be able to install prefixes of those LSAs into their RIB. This fix solves this issue by resetting the areas and the redistribution when ospf6->router-id updated. Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
2021-06-10 11:30:05 +02:00
if (ospf6_router_id_update(o, false))
ospf6_process_reset(o);
else
vty_out(vty,
"For this router-id change to take effect run the \"clear ipv6 ospf6 process\" command\n");
return CMD_SUCCESS;
}
DEFUN (ospf6_log_adjacency_changes,
ospf6_log_adjacency_changes_cmd,
"log-adjacency-changes",
"Log changes in adjacency state\n")
{
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
return CMD_SUCCESS;
}
DEFUN (ospf6_log_adjacency_changes_detail,
ospf6_log_adjacency_changes_detail_cmd,
"log-adjacency-changes detail",
"Log changes in adjacency state\n"
"Log all state changes\n")
{
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
return CMD_SUCCESS;
}
DEFUN (no_ospf6_log_adjacency_changes,
no_ospf6_log_adjacency_changes_cmd,
"no log-adjacency-changes",
NO_STR
"Log changes in adjacency state\n")
{
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
return CMD_SUCCESS;
}
DEFUN (no_ospf6_log_adjacency_changes_detail,
no_ospf6_log_adjacency_changes_detail_cmd,
"no log-adjacency-changes detail",
NO_STR
"Log changes in adjacency state\n"
"Log all state changes\n")
{
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
return CMD_SUCCESS;
}
static void ospf6_reinstall_routes(struct ospf6 *ospf6)
{
struct ospf6_route *route;
for (route = ospf6_route_head(ospf6->route_table); route;
route = ospf6_route_next(route))
ospf6_zebra_route_update_add(route, ospf6);
}
DEFPY (ospf6_send_extra_data,
ospf6_send_extra_data_cmd,
"[no] ospf6 send-extra-data zebra",
NO_STR
OSPF6_STR
"Extra data to Zebra for display/use\n"
"To zebra\n")
{
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
if (no
&& CHECK_FLAG(ospf6->config_flags,
OSPF6_SEND_EXTRA_DATA_TO_ZEBRA)) {
UNSET_FLAG(ospf6->config_flags, OSPF6_SEND_EXTRA_DATA_TO_ZEBRA);
ospf6_reinstall_routes(ospf6);
} else if (!CHECK_FLAG(ospf6->config_flags,
OSPF6_SEND_EXTRA_DATA_TO_ZEBRA)) {
SET_FLAG(ospf6->config_flags, OSPF6_SEND_EXTRA_DATA_TO_ZEBRA);
ospf6_reinstall_routes(ospf6);
}
return CMD_SUCCESS;
}
DEFUN (ospf6_timers_lsa,
ospf6_timers_lsa_cmd,
"timers lsa min-arrival (0-600000)",
"Adjust routing timers\n"
"OSPF6 LSA timers\n"
"Minimum delay in receiving new version of a LSA\n"
"Delay in milliseconds\n")
{
VTY_DECLVAR_CONTEXT(ospf6, ospf);
int idx_number = 3;
unsigned int minarrival;
minarrival = strtoul(argv[idx_number]->arg, NULL, 10);
ospf->lsa_minarrival = minarrival;
return CMD_SUCCESS;
}
DEFUN (no_ospf6_timers_lsa,
no_ospf6_timers_lsa_cmd,
"no timers lsa min-arrival [(0-600000)]",
NO_STR
"Adjust routing timers\n"
"OSPF6 LSA timers\n"
"Minimum delay in receiving new version of a LSA\n"
"Delay in milliseconds\n")
{
VTY_DECLVAR_CONTEXT(ospf6, ospf);
int idx_number = 4;
unsigned int minarrival;
if (argc == 5) {
minarrival = strtoul(argv[idx_number]->arg, NULL, 10);
if (ospf->lsa_minarrival != minarrival
|| minarrival == OSPF_MIN_LS_ARRIVAL)
return CMD_SUCCESS;
}
ospf->lsa_minarrival = OSPF_MIN_LS_ARRIVAL;
return CMD_SUCCESS;
}
DEFUN (ospf6_distance,
ospf6_distance_cmd,
"distance (1-255)",
"Administrative distance\n"
"OSPF6 Administrative distance\n")
{
VTY_DECLVAR_CONTEXT(ospf6, o);
ospf6d: restart spf when distance is updated if r1 has a route received from a neighbor and the same route configured as static, the administrative distance will determine which route to use r1(config)# ipv6 route 1:1::1/128 Null0 70 r1# sh ipv6 route Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3, I - IS-IS, B - BGP, N - NHRP, T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR, f - OpenFabric, > - selected route, * - FIB route, q - queued, r - rejected, b - backup t - trapped, o - offload failure S>* 1:1::1/128 [70/0] unreachable (blackhole), weight 1, 00:00:12 O 1:1::1/128 [110/20] via fe80::1833:c9ff:fe7b:3e43, r1-r2-eth0, weight 1, 00:00:49 The static route is selected. If we now change the administrative distance in ospf6, the OSPF route should be selected r1(config)# router ospf6 r1(config-ospf6)# distance 50 r1# sh ipv6 route Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3, I - IS-IS, B - BGP, N - NHRP, T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR, f - OpenFabric, > - selected route, * - FIB route, q - queued, r - rejected, b - backup t - trapped, o - offload failure S>* 1:1::1/128 [70/0] unreachable (blackhole), weight 1, 00:00:39 O 1:1::1/128 [110/20] via fe80::1833:c9ff:fe7b:3e43, r1-r2-eth0, weight 1, 00:01:16 However the distance is not applied as there are no changes in the routing table This commit will force the update of the routing table with the new configured distance r1# sh ipv6 route Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3, I - IS-IS, B - BGP, N - NHRP, T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR, f - OpenFabric, > - selected route, * - FIB route, q - queued, r - rejected, b - backup t - trapped, o - offload failure O>* 1:1::1/128 [50/20] via fe80::8cb7:e6ff:fef5:2344, r1-r2-eth0, weight 1, 00:00:03 S 1:1::1/128 [70/0] unreachable (blackhole), weight 1, 00:00:19 Signed-off-by: ckishimo <carles.kishimoto@gmail.com>
2022-01-26 22:41:36 +01:00
uint8_t distance;
ospf6d: restart spf when distance is updated if r1 has a route received from a neighbor and the same route configured as static, the administrative distance will determine which route to use r1(config)# ipv6 route 1:1::1/128 Null0 70 r1# sh ipv6 route Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3, I - IS-IS, B - BGP, N - NHRP, T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR, f - OpenFabric, > - selected route, * - FIB route, q - queued, r - rejected, b - backup t - trapped, o - offload failure S>* 1:1::1/128 [70/0] unreachable (blackhole), weight 1, 00:00:12 O 1:1::1/128 [110/20] via fe80::1833:c9ff:fe7b:3e43, r1-r2-eth0, weight 1, 00:00:49 The static route is selected. If we now change the administrative distance in ospf6, the OSPF route should be selected r1(config)# router ospf6 r1(config-ospf6)# distance 50 r1# sh ipv6 route Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3, I - IS-IS, B - BGP, N - NHRP, T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR, f - OpenFabric, > - selected route, * - FIB route, q - queued, r - rejected, b - backup t - trapped, o - offload failure S>* 1:1::1/128 [70/0] unreachable (blackhole), weight 1, 00:00:39 O 1:1::1/128 [110/20] via fe80::1833:c9ff:fe7b:3e43, r1-r2-eth0, weight 1, 00:01:16 However the distance is not applied as there are no changes in the routing table This commit will force the update of the routing table with the new configured distance r1# sh ipv6 route Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3, I - IS-IS, B - BGP, N - NHRP, T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR, f - OpenFabric, > - selected route, * - FIB route, q - queued, r - rejected, b - backup t - trapped, o - offload failure O>* 1:1::1/128 [50/20] via fe80::8cb7:e6ff:fef5:2344, r1-r2-eth0, weight 1, 00:00:03 S 1:1::1/128 [70/0] unreachable (blackhole), weight 1, 00:00:19 Signed-off-by: ckishimo <carles.kishimoto@gmail.com>
2022-01-26 22:41:36 +01:00
distance = atoi(argv[1]->arg);
if (o->distance_all != distance) {
o->distance_all = distance;
ospf6_restart_spf(o);
}
return CMD_SUCCESS;
}
DEFUN (no_ospf6_distance,
no_ospf6_distance_cmd,
"no distance (1-255)",
NO_STR
"Administrative distance\n"
"OSPF6 Administrative distance\n")
{
VTY_DECLVAR_CONTEXT(ospf6, o);
ospf6d: restart spf when distance is updated if r1 has a route received from a neighbor and the same route configured as static, the administrative distance will determine which route to use r1(config)# ipv6 route 1:1::1/128 Null0 70 r1# sh ipv6 route Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3, I - IS-IS, B - BGP, N - NHRP, T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR, f - OpenFabric, > - selected route, * - FIB route, q - queued, r - rejected, b - backup t - trapped, o - offload failure S>* 1:1::1/128 [70/0] unreachable (blackhole), weight 1, 00:00:12 O 1:1::1/128 [110/20] via fe80::1833:c9ff:fe7b:3e43, r1-r2-eth0, weight 1, 00:00:49 The static route is selected. If we now change the administrative distance in ospf6, the OSPF route should be selected r1(config)# router ospf6 r1(config-ospf6)# distance 50 r1# sh ipv6 route Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3, I - IS-IS, B - BGP, N - NHRP, T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR, f - OpenFabric, > - selected route, * - FIB route, q - queued, r - rejected, b - backup t - trapped, o - offload failure S>* 1:1::1/128 [70/0] unreachable (blackhole), weight 1, 00:00:39 O 1:1::1/128 [110/20] via fe80::1833:c9ff:fe7b:3e43, r1-r2-eth0, weight 1, 00:01:16 However the distance is not applied as there are no changes in the routing table This commit will force the update of the routing table with the new configured distance r1# sh ipv6 route Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3, I - IS-IS, B - BGP, N - NHRP, T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR, f - OpenFabric, > - selected route, * - FIB route, q - queued, r - rejected, b - backup t - trapped, o - offload failure O>* 1:1::1/128 [50/20] via fe80::8cb7:e6ff:fef5:2344, r1-r2-eth0, weight 1, 00:00:03 S 1:1::1/128 [70/0] unreachable (blackhole), weight 1, 00:00:19 Signed-off-by: ckishimo <carles.kishimoto@gmail.com>
2022-01-26 22:41:36 +01:00
if (o->distance_all) {
o->distance_all = 0;
ospf6_restart_spf(o);
}
return CMD_SUCCESS;
}
DEFUN (ospf6_distance_ospf6,
ospf6_distance_ospf6_cmd,
"distance ospf6 {intra-area (1-255)|inter-area (1-255)|external (1-255)}",
"Administrative distance\n"
"OSPF6 administrative distance\n"
"Intra-area routes\n"
"Distance for intra-area routes\n"
"Inter-area routes\n"
"Distance for inter-area routes\n"
"External routes\n"
"Distance for external routes\n")
{
VTY_DECLVAR_CONTEXT(ospf6, o);
int idx = 0;
o->distance_intra = 0;
o->distance_inter = 0;
o->distance_external = 0;
if (argv_find(argv, argc, "intra-area", &idx))
o->distance_intra = atoi(argv[idx + 1]->arg);
idx = 0;
if (argv_find(argv, argc, "inter-area", &idx))
o->distance_inter = atoi(argv[idx + 1]->arg);
idx = 0;
if (argv_find(argv, argc, "external", &idx))
o->distance_external = atoi(argv[idx + 1]->arg);
return CMD_SUCCESS;
}
DEFUN (no_ospf6_distance_ospf6,
no_ospf6_distance_ospf6_cmd,
"no distance ospf6 [{intra-area [(1-255)]|inter-area [(1-255)]|external [(1-255)]}]",
NO_STR
"Administrative distance\n"
"OSPF6 distance\n"
"Intra-area routes\n"
"Distance for intra-area routes\n"
"Inter-area routes\n"
"Distance for inter-area routes\n"
"External routes\n"
"Distance for external routes\n")
{
VTY_DECLVAR_CONTEXT(ospf6, o);
int idx = 0;
if (argv_find(argv, argc, "intra-area", &idx) || argc == 3)
idx = o->distance_intra = 0;
if (argv_find(argv, argc, "inter-area", &idx) || argc == 3)
idx = o->distance_inter = 0;
if (argv_find(argv, argc, "external", &idx) || argc == 3)
o->distance_external = 0;
return CMD_SUCCESS;
}
DEFUN_HIDDEN (ospf6_interface_area,
ospf6_interface_area_cmd,
"interface IFNAME area <A.B.C.D|(0-4294967295)>",
"Enable routing on an IPv6 interface\n"
IFNAME_STR
"Specify the OSPF6 area ID\n"
"OSPF6 area ID in IPv4 address notation\n"
"OSPF6 area ID in decimal notation\n"
)
2002-12-13 21:15:29 +01:00
{
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
int idx_ifname = 1;
int idx_ipv4 = 3;
struct ospf6_area *oa;
struct ospf6_interface *oi;
struct interface *ifp;
uint32_t area_id;
int format;
vty_out(vty,
"This command is deprecated, because it is not VRF-aware.\n");
vty_out(vty,
"Please, use \"ipv6 ospf6 area\" on an interface instead.\n");
/* find/create ospf6 interface */
ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name);
oi = (struct ospf6_interface *)ifp->info;
if (oi == NULL)
oi = ospf6_interface_create(ifp);
if (oi->area) {
vty_out(vty, "%s already attached to Area %s\n",
oi->interface->name, oi->area->name);
return CMD_SUCCESS;
}
if (str2area_id(argv[idx_ipv4]->arg, &area_id, &format)) {
vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
oi->area_id = area_id;
oi->area_id_format = format;
oa = ospf6_area_lookup(area_id, ospf6);
if (oa == NULL)
oa = ospf6_area_create(area_id, ospf6, format);
/* attach interface to area */
listnode_add(oa->if_list, oi); /* sort ?? */
oi->area = oa;
SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
/* ospf6 process is currently disabled, not much more to do */
if (CHECK_FLAG(ospf6->flag, OSPF6_DISABLED))
return CMD_SUCCESS;
/* start up */
ospf6_interface_enable(oi);
/* If the router is ABR, originate summary routes */
if (ospf6_check_and_set_router_abr(ospf6)) {
ospf6_abr_enable_area(oa);
ospf6_schedule_abr_task(oa->ospf6);
}
return CMD_SUCCESS;
2002-12-13 21:15:29 +01:00
}
DEFUN_HIDDEN (no_ospf6_interface_area,
no_ospf6_interface_area_cmd,
"no interface IFNAME area <A.B.C.D|(0-4294967295)>",
NO_STR
"Disable routing on an IPv6 interface\n"
IFNAME_STR
"Specify the OSPF6 area ID\n"
"OSPF6 area ID in IPv4 address notation\n"
"OSPF6 area ID in decimal notation\n"
)
2002-12-13 21:15:29 +01:00
{
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
int idx_ifname = 2;
int idx_ipv4 = 4;
struct ospf6_interface *oi;
struct ospf6_area *oa;
struct interface *ifp;
uint32_t area_id;
vty_out(vty,
"This command is deprecated, because it is not VRF-aware.\n");
vty_out(vty,
"Please, use \"no ipv6 ospf6 area\" on an interface instead.\n");
/* find/create ospf6 interface */
ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name);
if (ifp == NULL) {
vty_out(vty, "No such interface %s\n", argv[idx_ifname]->arg);
return CMD_SUCCESS;
}
oi = (struct ospf6_interface *)ifp->info;
if (oi == NULL) {
vty_out(vty, "Interface %s not enabled\n", ifp->name);
return CMD_SUCCESS;
}
/* parse Area-ID */
if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1)
area_id = htonl(strtoul(argv[idx_ipv4]->arg, NULL, 10));
/* Verify Area */
if (oi->area == NULL) {
vty_out(vty, "%s not attached to area %s\n",
oi->interface->name, argv[idx_ipv4]->arg);
return CMD_SUCCESS;
}
if (oi->area->area_id != area_id) {
vty_out(vty, "Wrong Area-ID: %s is attached to area %s\n",
oi->interface->name, oi->area->name);
return CMD_SUCCESS;
}
ospf6_interface_disable(oi);
oa = oi->area;
listnode_delete(oi->area->if_list, oi);
oi->area = (struct ospf6_area *)NULL;
/* Withdraw inter-area routes from this area, if necessary */
if (oa->if_list->count == 0) {
UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
ospf6_abr_disable_area(oa);
}
oi->area_id = 0;
oi->area_id_format = OSPF6_AREA_FMT_UNSET;
return CMD_SUCCESS;
2002-12-13 21:15:29 +01:00
}
DEFUN (ospf6_stub_router_admin,
ospf6_stub_router_admin_cmd,
"stub-router administrative",
"Make router a stub router\n"
"Administratively applied, for an indefinite period\n")
{
struct listnode *node;
struct ospf6_area *oa;
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
if (!CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) {
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_V6);
OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_R);
OSPF6_ROUTER_LSA_SCHEDULE(oa);
}
SET_FLAG(ospf6->flag, OSPF6_STUB_ROUTER);
}
return CMD_SUCCESS;
}
DEFUN (no_ospf6_stub_router_admin,
no_ospf6_stub_router_admin_cmd,
"no stub-router administrative",
NO_STR
"Make router a stub router\n"
"Administratively applied, for an indefinite period\n")
{
struct listnode *node;
struct ospf6_area *oa;
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
if (CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) {
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
OSPF6_OPT_SET(oa->options, OSPF6_OPT_V6);
OSPF6_OPT_SET(oa->options, OSPF6_OPT_R);
OSPF6_ROUTER_LSA_SCHEDULE(oa);
}
UNSET_FLAG(ospf6->flag, OSPF6_STUB_ROUTER);
}
return CMD_SUCCESS;
}
/* Restart OSPF SPF algorithm*/
ospf6d: restart spf when distance is updated if r1 has a route received from a neighbor and the same route configured as static, the administrative distance will determine which route to use r1(config)# ipv6 route 1:1::1/128 Null0 70 r1# sh ipv6 route Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3, I - IS-IS, B - BGP, N - NHRP, T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR, f - OpenFabric, > - selected route, * - FIB route, q - queued, r - rejected, b - backup t - trapped, o - offload failure S>* 1:1::1/128 [70/0] unreachable (blackhole), weight 1, 00:00:12 O 1:1::1/128 [110/20] via fe80::1833:c9ff:fe7b:3e43, r1-r2-eth0, weight 1, 00:00:49 The static route is selected. If we now change the administrative distance in ospf6, the OSPF route should be selected r1(config)# router ospf6 r1(config-ospf6)# distance 50 r1# sh ipv6 route Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3, I - IS-IS, B - BGP, N - NHRP, T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR, f - OpenFabric, > - selected route, * - FIB route, q - queued, r - rejected, b - backup t - trapped, o - offload failure S>* 1:1::1/128 [70/0] unreachable (blackhole), weight 1, 00:00:39 O 1:1::1/128 [110/20] via fe80::1833:c9ff:fe7b:3e43, r1-r2-eth0, weight 1, 00:01:16 However the distance is not applied as there are no changes in the routing table This commit will force the update of the routing table with the new configured distance r1# sh ipv6 route Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3, I - IS-IS, B - BGP, N - NHRP, T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR, f - OpenFabric, > - selected route, * - FIB route, q - queued, r - rejected, b - backup t - trapped, o - offload failure O>* 1:1::1/128 [50/20] via fe80::8cb7:e6ff:fef5:2344, r1-r2-eth0, weight 1, 00:00:03 S 1:1::1/128 [70/0] unreachable (blackhole), weight 1, 00:00:19 Signed-off-by: ckishimo <carles.kishimoto@gmail.com>
2022-01-26 22:41:36 +01:00
void ospf6_restart_spf(struct ospf6 *ospf6)
{
ospf6_route_remove_all(ospf6->route_table);
ospf6_route_remove_all(ospf6->brouter_table);
/* Trigger SPF */
ospf6_spf_schedule(ospf6, OSPF6_SPF_FLAGS_CONFIG_CHANGE);
}
/* Set the max paths */
static void ospf6_maxpath_set(struct ospf6 *ospf6, uint16_t paths)
{
if (ospf6->max_multipath == paths)
return;
ospf6->max_multipath = paths;
/* Send deletion to zebra to delete all
* ospf specific routes and reinitiate
* SPF to reflect the new max multipath.
*/
ospf6_restart_spf(ospf6);
}
/* Ospf Maximum-paths config support */
DEFUN(ospf6_max_multipath,
ospf6_max_multipath_cmd,
"maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM),
"Max no of multiple paths for ECMP support\n"
"Number of paths\n")
{
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
int idx_number = 1;
int maximum_paths = strtol(argv[idx_number]->arg, NULL, 10);
ospf6_maxpath_set(ospf6, maximum_paths);
return CMD_SUCCESS;
}
DEFUN(no_ospf6_max_multipath,
no_ospf6_max_multipath_cmd,
"no maximum-paths [" CMD_RANGE_STR(1, MULTIPATH_NUM)"]",
NO_STR
"Max no of multiple paths for ECMP support\n"
"Number of paths\n")
{
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
ospf6_maxpath_set(ospf6, MULTIPATH_NUM);
return CMD_SUCCESS;
}
static void ospf6_show(struct vty *vty, struct ospf6 *o, json_object *json,
bool use_json)
2002-12-13 21:15:29 +01:00
{
struct listnode *n;
struct ospf6_area *oa;
char router_id[16], duration[32];
struct timeval now, running, result;
char buf[32], rbuf[32];
json_object *json_areas = NULL;
const char *adjacency;
if (use_json) {
json_areas = json_object_new_object();
/* process id, router id */
inet_ntop(AF_INET, &o->router_id, router_id, sizeof(router_id));
json_object_string_add(json, "routerId", router_id);
/* running time */
monotime(&now);
timersub(&now, &o->starttime, &running);
timerstring(&running, duration, sizeof(duration));
json_object_string_add(json, "running", duration);
/* Redistribute configuration */
/* XXX */
json_object_int_add(json, "lsaMinimumArrivalMsecs",
o->lsa_minarrival);
/* Show SPF parameters */
json_object_int_add(json, "spfScheduleDelayMsecs",
o->spf_delay);
json_object_int_add(json, "holdTimeMinMsecs", o->spf_holdtime);
json_object_int_add(json, "holdTimeMaxMsecs",
o->spf_max_holdtime);
json_object_int_add(json, "holdTimeMultiplier",
o->spf_hold_multiplier);
json_object_int_add(json, "maximumPaths", o->max_multipath);
if (o->ts_spf.tv_sec || o->ts_spf.tv_usec) {
timersub(&now, &o->ts_spf, &result);
timerstring(&result, buf, sizeof(buf));
ospf6_spf_reason_string(o->last_spf_reason, rbuf,
sizeof(rbuf));
json_object_boolean_true_add(json, "spfHasRun");
json_object_string_add(json, "spfLastExecutedMsecs",
buf);
json_object_string_add(json, "spfLastExecutedReason",
rbuf);
json_object_int_add(
json, "spfLastDurationSecs",
(long long)o->ts_spf_duration.tv_sec);
json_object_int_add(
json, "spfLastDurationMsecs",
(long long)o->ts_spf_duration.tv_usec);
} else
json_object_boolean_false_add(json, "spfHasRun");
threadtimer_string(now, o->t_spf_calc, buf, sizeof(buf));
if (o->t_spf_calc) {
long time_store;
json_object_boolean_true_add(json, "spfTimerActive");
time_store =
monotime_until(&o->t_spf_calc->u.sands, NULL)
/ 1000LL;
json_object_int_add(json, "spfTimerDueInMsecs",
time_store);
} else
json_object_boolean_false_add(json, "spfTimerActive");
json_object_boolean_add(json, "routerIsStubRouter",
CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER));
/* LSAs */
json_object_int_add(json, "numberOfAsScopedLsa",
o->lsdb->count);
/* Areas */
json_object_int_add(json, "numberOfAreaInRouter",
listcount(o->area_list));
if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
if (CHECK_FLAG(o->config_flags,
OSPF6_LOG_ADJACENCY_DETAIL))
adjacency = "LoggedAll";
else
adjacency = "Logged";
} else
adjacency = "NotLogged";
json_object_string_add(json, "adjacencyChanges", adjacency);
for (ALL_LIST_ELEMENTS_RO(o->area_list, n, oa))
ospf6_area_show(vty, oa, json_areas, use_json);
json_object_object_add(json, "areas", json_areas);
vty_out(vty, "%s\n",
json_object_to_json_string_ext(
json, JSON_C_TO_STRING_PRETTY));
} else {
/* process id, router id */
inet_ntop(AF_INET, &o->router_id, router_id, sizeof(router_id));
vty_out(vty, " OSPFv3 Routing Process (0) with Router-ID %s\n",
router_id);
/* running time */
monotime(&now);
timersub(&now, &o->starttime, &running);
timerstring(&running, duration, sizeof(duration));
vty_out(vty, " Running %s\n", duration);
/* Redistribute configuration */
/* XXX */
vty_out(vty, " LSA minimum arrival %d msecs\n",
o->lsa_minarrival);
vty_out(vty, " Maximum-paths %u\n", o->max_multipath);
/* Show SPF parameters */
vty_out(vty,
" Initial SPF scheduling delay %d millisec(s)\n"
" Minimum hold time between consecutive SPFs %d millsecond(s)\n"
" Maximum hold time between consecutive SPFs %d millsecond(s)\n"
" Hold time multiplier is currently %d\n",
o->spf_delay, o->spf_holdtime, o->spf_max_holdtime,
o->spf_hold_multiplier);
vty_out(vty, " SPF algorithm ");
if (o->ts_spf.tv_sec || o->ts_spf.tv_usec) {
timersub(&now, &o->ts_spf, &result);
timerstring(&result, buf, sizeof(buf));
ospf6_spf_reason_string(o->last_spf_reason, rbuf,
sizeof(rbuf));
vty_out(vty, "last executed %s ago, reason %s\n", buf,
rbuf);
vty_out(vty, " Last SPF duration %lld sec %lld usec\n",
(long long)o->ts_spf_duration.tv_sec,
(long long)o->ts_spf_duration.tv_usec);
} else
vty_out(vty, "has not been run\n");
threadtimer_string(now, o->t_spf_calc, buf, sizeof(buf));
vty_out(vty, " SPF timer %s%s\n",
(o->t_spf_calc ? "due in " : "is "), buf);
if (CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER))
vty_out(vty, " Router Is Stub Router\n");
/* LSAs */
vty_out(vty, " Number of AS scoped LSAs is %u\n",
o->lsdb->count);
/* Areas */
vty_out(vty, " Number of areas in this router is %u\n",
listcount(o->area_list));
if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
if (CHECK_FLAG(o->config_flags,
OSPF6_LOG_ADJACENCY_DETAIL))
vty_out(vty,
" All adjacency changes are logged\n");
else
vty_out(vty, " Adjacency changes are logged\n");
}
vty_out(vty, "\n");
for (ALL_LIST_ELEMENTS_RO(o->area_list, n, oa))
ospf6_area_show(vty, oa, json_areas, use_json);
}
2002-12-13 21:15:29 +01:00
}
DEFUN(show_ipv6_ospf6_vrfs, show_ipv6_ospf6_vrfs_cmd,
"show ipv6 ospf6 vrfs [json]",
SHOW_STR IP6_STR OSPF6_STR "Show OSPF6 VRFs \n" JSON_STR)
{
bool uj = use_json(argc, argv);
json_object *json = NULL;
json_object *json_vrfs = NULL;
struct ospf6 *ospf6 = NULL;
struct listnode *node = NULL;
int count = 0;
char buf[PREFIX_STRLEN];
static const char header[] =
"Name Id RouterId ";
if (uj) {
json = json_object_new_object();
json_vrfs = json_object_new_object();
}
for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
json_object *json_vrf = NULL;
const char *name = NULL;
int64_t vrf_id_ui = 0;
struct in_addr router_id;
router_id.s_addr = ospf6->router_id;
count++;
if (!uj && count == 1)
vty_out(vty, "%s\n", header);
if (uj)
json_vrf = json_object_new_object();
if (ospf6->vrf_id == VRF_DEFAULT)
name = VRF_DEFAULT_NAME;
else
name = ospf6->name;
vrf_id_ui = (ospf6->vrf_id == VRF_UNKNOWN)
? -1
: (int64_t)ospf6->vrf_id;
if (uj) {
json_object_int_add(json_vrf, "vrfId", vrf_id_ui);
json_object_string_addf(json_vrf, "routerId", "%pI4",
&router_id);
json_object_object_add(json_vrfs, name, json_vrf);
} else {
vty_out(vty, "%-25s %-5d %-16s \n", name,
ospf6->vrf_id,
inet_ntop(AF_INET, &router_id, buf,
sizeof(buf)));
}
}
if (uj) {
json_object_object_add(json, "vrfs", json_vrfs);
json_object_int_add(json, "totalVrfs", count);
vty_json(vty, json);
} else {
if (count)
vty_out(vty, "\nTotal number of OSPF VRFs: %d\n",
count);
}
return CMD_SUCCESS;
}
/* show top level structures */
DEFUN(show_ipv6_ospf6, show_ipv6_ospf6_cmd,
"show ipv6 ospf6 [vrf <NAME|all>] [json]",
SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR "All VRFs\n" JSON_STR)
2002-12-13 21:15:29 +01:00
{
struct ospf6 *ospf6;
struct listnode *node;
const char *vrf_name = NULL;
bool all_vrf = false;
int idx_vrf = 0;
bool uj = use_json(argc, argv);
json_object *json = NULL;
OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
if (uj)
json = json_object_new_object();
ospf6_show(vty, ospf6, json, uj);
if (!all_vrf)
break;
}
}
if (uj)
json_object_free(json);
OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
return CMD_SUCCESS;
2002-12-13 21:15:29 +01:00
}
DEFUN(show_ipv6_ospf6_route, show_ipv6_ospf6_route_cmd,
"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]",
SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
"All VRFs\n" ROUTE_STR
"Display Intra-Area routes\n"
"Display Inter-Area routes\n"
"Display Type-1 External routes\n"
"Display Type-2 External routes\n"
"Specify IPv6 address\n"
"Specify IPv6 prefix\n"
"Detailed information\n"
"Summary of route table\n" JSON_STR)
2002-12-13 21:15:29 +01:00
{
struct ospf6 *ospf6;
struct listnode *node;
const char *vrf_name = NULL;
bool all_vrf = false;
int idx_vrf = 0;
int idx_arg_start = 4;
bool uj = use_json(argc, argv);
OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
if (idx_vrf > 0)
idx_arg_start += 2;
for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
ospf6_route_table_show(vty, idx_arg_start, argc, argv,
ospf6->route_table, uj);
if (!all_vrf)
break;
}
}
OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
return CMD_SUCCESS;
2002-12-13 21:15:29 +01:00
}
DEFUN(show_ipv6_ospf6_route_match, show_ipv6_ospf6_route_match_cmd,
"show ipv6 ospf6 [vrf <NAME|all>] route X:X::X:X/M <match|longer> [json]",
SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
"All VRFs\n" ROUTE_STR
"Specify IPv6 prefix\n"
"Display routes which match the specified route\n"
"Display routes longer than the specified route\n" JSON_STR)
2002-12-13 21:15:29 +01:00
{
struct ospf6 *ospf6;
struct listnode *node;
const char *vrf_name = NULL;
bool all_vrf = false;
int idx_vrf = 0;
int idx_start_arg = 4;
bool uj = use_json(argc, argv);
OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
if (idx_vrf > 0)
idx_start_arg += 2;
for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
ospf6_route_table_show(vty, idx_start_arg, argc, argv,
ospf6->route_table, uj);
if (!all_vrf)
break;
}
}
OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
return CMD_SUCCESS;
2002-12-13 21:15:29 +01:00
}
DEFUN(show_ipv6_ospf6_route_match_detail,
show_ipv6_ospf6_route_match_detail_cmd,
"show ipv6 ospf6 [vrf <NAME|all>] route X:X::X:X/M match detail [json]",
SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
"All VRFs\n" ROUTE_STR
"Specify IPv6 prefix\n"
"Display routes which match the specified route\n"
"Detailed information\n" JSON_STR)
{
struct ospf6 *ospf6;
struct listnode *node;
const char *vrf_name = NULL;
bool all_vrf = false;
int idx_vrf = 0;
int idx_start_arg = 4;
bool uj = use_json(argc, argv);
OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
if (idx_vrf > 0)
idx_start_arg += 2;
for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
ospf6_route_table_show(vty, idx_start_arg, argc, argv,
ospf6->route_table, uj);
if (!all_vrf)
break;
}
}
OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
return CMD_SUCCESS;
}
2002-12-13 21:15:29 +01:00
DEFUN(show_ipv6_ospf6_route_type_detail, show_ipv6_ospf6_route_type_detail_cmd,
"show ipv6 ospf6 [vrf <NAME|all>] route <intra-area|inter-area|external-1|external-2> detail [json]",
SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
"All VRFs\n" ROUTE_STR
"Display Intra-Area routes\n"
"Display Inter-Area routes\n"
"Display Type-1 External routes\n"
"Display Type-2 External routes\n"
"Detailed information\n" JSON_STR)
2004-09-03 08:04:00 +02:00
{
struct ospf6 *ospf6;
struct listnode *node;
const char *vrf_name = NULL;
bool all_vrf = false;
int idx_vrf = 0;
int idx_start_arg = 4;
bool uj = use_json(argc, argv);
OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
if (idx_vrf > 0)
idx_start_arg += 2;
for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
ospf6_route_table_show(vty, idx_start_arg, argc, argv,
ospf6->route_table, uj);
if (!all_vrf)
break;
}
}
OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
2004-09-03 08:04:00 +02:00
return CMD_SUCCESS;
}
2002-12-13 21:15:29 +01:00
bool ospf6_is_valid_summary_addr(struct vty *vty, struct prefix *p)
{
struct in6_addr addr_zero;
memset(&addr_zero, 0, sizeof(struct in6_addr));
/* Default prefix validation*/
if ((is_default_prefix((struct prefix *)p))
|| (!memcmp(&p->u.prefix6, &addr_zero, sizeof(struct in6_addr)))) {
vty_out(vty, "Default address should not be configured as summary address.\n");
return false;
}
/* Host route should not be configured as summary address */
if (p->prefixlen == IPV6_MAX_BITLEN) {
vty_out(vty, "Host route should not be configured as summary address.\n");
return false;
}
return true;
}
/* External Route Aggregation */
DEFPY (ospf6_external_route_aggregation,
ospf6_external_route_aggregation_cmd,
"summary-address X:X::X:X/M$prefix [tag (1-4294967295)] [{metric (0-16777215) | metric-type (1-2)$mtype}]",
"External summary address\n"
"Specify IPv6 prefix\n"
"Router tag \n"
"Router tag value\n"
"Metric \n"
"Advertised metric for this route\n"
"OSPFv3 exterior metric type for summarised routes\n"
"Set OSPFv3 External Type 1/2 metrics\n")
{
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
struct prefix p;
int ret = CMD_SUCCESS;
p.family = AF_INET6;
ret = str2prefix(prefix_str, &p);
if (ret == 0) {
vty_out(vty, "Malformed prefix\n");
return CMD_WARNING_CONFIG_FAILED;
}
/* Apply mask for given prefix. */
apply_mask((struct prefix *)&p);
if (!ospf6_is_valid_summary_addr(vty, &p))
return CMD_WARNING_CONFIG_FAILED;
if (!tag_str)
tag = 0;
if (!metric_str)
metric = -1;
if (!mtype_str)
mtype = DEFAULT_METRIC_TYPE;
ret = ospf6_external_aggr_config_set(ospf6, &p, tag, metric, mtype);
if (ret == OSPF6_FAILURE) {
vty_out(vty, "Invalid configuration!!\n");
return CMD_WARNING_CONFIG_FAILED;
}
return CMD_SUCCESS;
}
DEFPY(no_ospf6_external_route_aggregation,
no_ospf6_external_route_aggregation_cmd,
"no summary-address X:X::X:X/M$prefix [tag (1-4294967295)] [{metric (0-16777215) | metric-type (1-2)}]",
NO_STR
"External summary address\n"
"Specify IPv6 prefix\n"
"Router tag\n"
"Router tag value\n"
"Metric \n"
"Advertised metric for this route\n"
"OSPFv3 exterior metric type for summarised routes\n"
"Set OSPFv3 External Type 1/2 metrics\n")
{
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
struct prefix p;
int ret = CMD_SUCCESS;
ret = str2prefix(prefix_str, &p);
if (ret == 0) {
vty_out(vty, "Malformed prefix\n");
return CMD_WARNING_CONFIG_FAILED;
}
/* Apply mask for given prefix. */
apply_mask((struct prefix *)&p);
if (!ospf6_is_valid_summary_addr(vty, &p))
return CMD_WARNING_CONFIG_FAILED;
ret = ospf6_external_aggr_config_unset(ospf6, &p);
if (ret == OSPF6_INVALID)
vty_out(vty, "Invalid configuration!!\n");
return CMD_SUCCESS;
}
DEFPY (ospf6_external_route_aggregation_no_advertise,
ospf6_external_route_aggregation_no_advertise_cmd,
"summary-address X:X::X:X/M$prefix no-advertise",
"External summary address\n"
"Specify IPv6 prefix\n"
"Don't advertise summary route \n")
{
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
struct prefix p;
int ret = CMD_SUCCESS;
ret = str2prefix(prefix_str, &p);
if (ret == 0) {
vty_out(vty, "Malformed prefix\n");
return CMD_WARNING_CONFIG_FAILED;
}
/* Apply mask for given prefix. */
apply_mask((struct prefix *)&p);
if (!ospf6_is_valid_summary_addr(vty, &p))
return CMD_WARNING_CONFIG_FAILED;
ret = ospf6_asbr_external_rt_no_advertise(ospf6, &p);
if (ret == OSPF6_INVALID)
vty_out(vty, "!!Invalid configuration\n");
return CMD_SUCCESS;
}
DEFPY (no_ospf6_external_route_aggregation_no_advertise,
no_ospf6_external_route_aggregation_no_advertise_cmd,
"no summary-address X:X::X:X/M$prefix no-advertise",
NO_STR
"External summary address\n"
"Specify IPv6 prefix\n"
"Adverise summary route to the AS \n")
{
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
struct prefix p;
int ret = CMD_SUCCESS;
ret = str2prefix(prefix_str, &p);
if (ret == 0) {
vty_out(vty, "Malformed prefix\n");
return CMD_WARNING_CONFIG_FAILED;
}
/* Apply mask for given prefix. */
apply_mask((struct prefix *)&p);
if (!ospf6_is_valid_summary_addr(vty, &p))
return CMD_WARNING_CONFIG_FAILED;
ret = ospf6_asbr_external_rt_advertise(ospf6, &p);
if (ret == OSPF6_INVALID)
vty_out(vty, "!!Invalid configuration\n");
return CMD_SUCCESS;
}
DEFPY (ospf6_route_aggregation_timer,
ospf6_route_aggregation_timer_cmd,
"aggregation timer (5-1800)",
"External route aggregation\n"
"Delay timer (in seconds)\n"
"Timer interval(in seconds)\n")
{
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
ospf6_external_aggr_delay_timer_set(ospf6, timer);
return CMD_SUCCESS;
}
DEFPY (no_ospf6_route_aggregation_timer,
no_ospf6_route_aggregation_timer_cmd,
"no aggregation timer [5-1800]",
NO_STR
"External route aggregation\n"
"Delay timer\n"
"Timer interval(in seconds)\n")
{
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
ospf6_external_aggr_delay_timer_set(ospf6,
OSPF6_EXTL_AGGR_DEFAULT_DELAY);
return CMD_SUCCESS;
}
static int
ospf6_print_vty_external_routes_walkcb(struct hash_bucket *bucket, void *arg)
{
struct ospf6_route *rt = bucket->data;
struct vty *vty = (struct vty *)arg;
static unsigned int count;
vty_out(vty, "%pFX ", &rt->prefix);
count++;
if (count%5 == 0)
vty_out(vty, "\n");
if (OSPF6_EXTERNAL_RT_COUNT(rt->aggr_route) == count)
count = 0;
return HASHWALK_CONTINUE;
}
static int
ospf6_print_json_external_routes_walkcb(struct hash_bucket *bucket, void *arg)
{
struct ospf6_route *rt = bucket->data;
struct json_object *json = (struct json_object *)arg;
char buf[PREFIX2STR_BUFFER];
char exnalbuf[20];
static unsigned int count;
prefix2str(&rt->prefix, buf, sizeof(buf));
snprintf(exnalbuf, sizeof(exnalbuf), "Exnl Addr-%d", count);
json_object_string_add(json, exnalbuf, buf);
count++;
if (OSPF6_EXTERNAL_RT_COUNT(rt->aggr_route) == count)
count = 0;
return HASHWALK_CONTINUE;
}
static void
ospf6_show_vrf_name(struct vty *vty, struct ospf6 *ospf6,
json_object *json)
{
if (json) {
if (ospf6->vrf_id == VRF_DEFAULT)
json_object_string_add(json, "vrfName",
"default");
else
json_object_string_add(json, "vrfName",
ospf6->name);
json_object_int_add(json, "vrfId", ospf6->vrf_id);
} else {
if (ospf6->vrf_id == VRF_DEFAULT)
vty_out(vty, "VRF Name: %s\n", "default");
else if (ospf6->name)
vty_out(vty, "VRF Name: %s\n", ospf6->name);
}
}
static int
ospf6_show_summary_address(struct vty *vty, struct ospf6 *ospf6,
json_object *json,
bool uj, const char *detail)
{
struct route_node *rn;
static const char header[] = "Summary-address Metric-type Metric Tag External_Rt_count\n";
json_object *json_vrf = NULL;
if (!uj) {
ospf6_show_vrf_name(vty, ospf6, json_vrf);
vty_out(vty, "aggregation delay interval :%d(in seconds)\n\n",
ospf6->aggr_delay_interval);
vty_out(vty, "%s\n", header);
} else {
json_vrf = json_object_new_object();
ospf6_show_vrf_name(vty, ospf6, json_vrf);
json_object_int_add(json_vrf, "aggregation delay interval",
ospf6->aggr_delay_interval);
}
for (rn = route_top(ospf6->rt_aggr_tbl); rn; rn = route_next(rn)) {
if (!rn->info)
continue;
struct ospf6_external_aggr_rt *aggr = rn->info;
json_object *json_aggr = NULL;
char buf[PREFIX2STR_BUFFER];
prefix2str(&aggr->p, buf, sizeof(buf));
if (uj) {
json_aggr = json_object_new_object();
json_object_object_add(json_vrf,
buf,
json_aggr);
json_object_string_add(json_aggr,
"Summary address",
buf);
json_object_string_add(
json_aggr, "Metric-type",
(aggr->mtype == DEFAULT_METRIC_TYPE)
? "E2"
: "E1");
json_object_int_add(json_aggr, "Metric",
(aggr->metric != -1)
? aggr->metric
: DEFAULT_DEFAULT_METRIC);
json_object_int_add(json_aggr, "Tag",
aggr->tag);
json_object_int_add(json_aggr,
"External route count",
OSPF6_EXTERNAL_RT_COUNT(aggr));
if (OSPF6_EXTERNAL_RT_COUNT(aggr) && detail) {
json_object_int_add(json_aggr, "ID",
aggr->id);
json_object_int_add(json_aggr, "Flags",
aggr->aggrflags);
hash_walk(aggr->match_extnl_hash,
ospf6_print_json_external_routes_walkcb,
json_aggr);
}
} else {
vty_out(vty, "%-22s", buf);
(aggr->mtype == DEFAULT_METRIC_TYPE)
? vty_out(vty, "%-16s", "E2")
: vty_out(vty, "%-16s", "E1");
vty_out(vty, "%-11d", (aggr->metric != -1)
? aggr->metric
: DEFAULT_DEFAULT_METRIC);
vty_out(vty, "%-12u", aggr->tag);
vty_out(vty, "%-5ld\n",
OSPF6_EXTERNAL_RT_COUNT(aggr));
if (OSPF6_EXTERNAL_RT_COUNT(aggr) && detail) {
vty_out(vty,
"Matched External routes:\n");
hash_walk(aggr->match_extnl_hash,
ospf6_print_vty_external_routes_walkcb,
vty);
vty_out(vty, "\n");
}
vty_out(vty, "\n");
}
}
if (uj)
json_object_object_add(json, ospf6->name,
json_vrf);
return CMD_SUCCESS;
}
DEFPY (show_ipv6_ospf6_external_aggregator,
show_ipv6_ospf6_external_aggregator_cmd,
"show ipv6 ospf6 [vrf <NAME|all>] summary-address [detail$detail] [json]",
SHOW_STR
IP6_STR
OSPF6_STR
VRF_CMD_HELP_STR
"All VRFs\n"
"Show external summary addresses\n"
"detailed informtion\n"
JSON_STR)
{
bool uj = use_json(argc, argv);
struct ospf6 *ospf6 = NULL;
json_object *json = NULL;
const char *vrf_name = NULL;
struct listnode *node;
bool all_vrf = false;
int idx_vrf = 0;
if (uj)
json = json_object_new_object();
OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
ospf6_show_summary_address(vty, ospf6, json, uj,
detail);
if (!all_vrf)
break;
}
}
if (uj) {
vty_json(vty, json);
}
OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
return CMD_SUCCESS;
}
static void ospf6_stub_router_config_write(struct vty *vty, struct ospf6 *ospf6)
{
if (CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER))
vty_out(vty, " stub-router administrative\n");
return;
}
static int ospf6_distance_config_write(struct vty *vty, struct ospf6 *ospf6)
{
struct route_node *rn;
struct ospf6_distance *odistance;
if (ospf6->distance_all)
vty_out(vty, " distance %u\n", ospf6->distance_all);
if (ospf6->distance_intra || ospf6->distance_inter
|| ospf6->distance_external) {
vty_out(vty, " distance ospf6");
if (ospf6->distance_intra)
vty_out(vty, " intra-area %u", ospf6->distance_intra);
if (ospf6->distance_inter)
vty_out(vty, " inter-area %u", ospf6->distance_inter);
if (ospf6->distance_external)
vty_out(vty, " external %u", ospf6->distance_external);
vty_out(vty, "\n");
}
for (rn = route_top(ospf6->distance_table); rn; rn = route_next(rn))
if ((odistance = rn->info) != NULL)
vty_out(vty, " distance %u %pFX %s\n",
odistance->distance, &rn->p,
odistance->access_list ? odistance->access_list
: "");
return 0;
}
static int ospf6_asbr_summary_config_write(struct vty *vty, struct ospf6 *ospf6)
{
struct route_node *rn;
struct ospf6_external_aggr_rt *aggr;
char buf[PREFIX2STR_BUFFER];
if (ospf6->aggr_delay_interval != OSPF6_EXTL_AGGR_DEFAULT_DELAY)
vty_out(vty, " aggregation timer %u\n",
ospf6->aggr_delay_interval);
/* print 'summary-address A:B::C:D/M' */
for (rn = route_top(ospf6->rt_aggr_tbl); rn; rn = route_next(rn)) {
if (!rn->info)
continue;
aggr = rn->info;
prefix2str(&aggr->p, buf, sizeof(buf));
vty_out(vty, " summary-address %s", buf);
if (aggr->tag)
vty_out(vty, " tag %u", aggr->tag);
if (aggr->metric != -1)
vty_out(vty, " metric %d", aggr->metric);
if (aggr->mtype != DEFAULT_METRIC_TYPE)
vty_out(vty, " metric-type %d", aggr->mtype);
if (CHECK_FLAG(aggr->aggrflags,
OSPF6_EXTERNAL_AGGRT_NO_ADVERTISE))
vty_out(vty, " no-advertise");
vty_out(vty, "\n");
}
return 0;
}
/* OSPF configuration write function. */
static int config_write_ospf6(struct vty *vty)
{
struct ospf6 *ospf6;
struct listnode *node, *nnode;
/* OSPFv3 configuration. */
if (om6 == NULL)
return CMD_SUCCESS;
for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
if (ospf6->name && strcmp(ospf6->name, VRF_DEFAULT_NAME))
vty_out(vty, "router ospf6 vrf %s\n", ospf6->name);
else
vty_out(vty, "router ospf6\n");
if (ospf6->router_id_static != 0)
vty_out(vty, " ospf6 router-id %pI4\n",
&ospf6->router_id_static);
if (!CHECK_FLAG(ospf6->config_flags,
OSPF6_SEND_EXTRA_DATA_TO_ZEBRA))
vty_out(vty, " no ospf6 send-extra-data zebra\n");
/* log-adjacency-changes flag print. */
if (CHECK_FLAG(ospf6->config_flags,
OSPF6_LOG_ADJACENCY_CHANGES)) {
if (CHECK_FLAG(ospf6->config_flags,
OSPF6_LOG_ADJACENCY_DETAIL))
vty_out(vty, " log-adjacency-changes detail\n");
else if (!SAVE_OSPF6_LOG_ADJACENCY_CHANGES)
vty_out(vty, " log-adjacency-changes\n");
} else if (SAVE_OSPF6_LOG_ADJACENCY_CHANGES) {
vty_out(vty, " no log-adjacency-changes\n");
}
if (ospf6->ref_bandwidth != OSPF6_REFERENCE_BANDWIDTH)
vty_out(vty, " auto-cost reference-bandwidth %d\n",
ospf6->ref_bandwidth);
if (ospf6->write_oi_count
!= OSPF6_WRITE_INTERFACE_COUNT_DEFAULT)
vty_out(vty, " write-multiplier %d\n",
ospf6->write_oi_count);
/* LSA timers print. */
if (ospf6->lsa_minarrival != OSPF_MIN_LS_ARRIVAL)
vty_out(vty, " timers lsa min-arrival %d\n",
ospf6->lsa_minarrival);
/* ECMP max path config */
if (ospf6->max_multipath != MULTIPATH_NUM)
vty_out(vty, " maximum-paths %d\n",
ospf6->max_multipath);
ospf6_stub_router_config_write(vty, ospf6);
ospf6_redistribute_config_write(vty, ospf6);
ospf6_area_config_write(vty, ospf6);
ospf6_spf_config_write(vty, ospf6);
ospf6_distance_config_write(vty, ospf6);
ospf6_distribute_config_write(vty, ospf6);
ospf6_asbr_summary_config_write(vty, ospf6);
config_write_ospf6_gr(vty, ospf6);
config_write_ospf6_gr_helper(vty, ospf6);
vty_out(vty, "exit\n");
vty_out(vty, "!\n");
}
return 0;
}
static int config_write_ospf6(struct vty *vty);
/* OSPF6 node structure. */
static struct cmd_node ospf6_node = {
.name = "ospf6",
.node = OSPF6_NODE,
.parent_node = CONFIG_NODE,
.prompt = "%s(config-ospf6)# ",
.config_write = config_write_ospf6,
};
void install_element_ospf6_clear_process(void)
{
install_element(ENABLE_NODE, &clear_router_ospf6_cmd);
}
/* Install ospf related commands. */
void ospf6_top_init(void)
2002-12-13 21:15:29 +01:00
{
/* Install ospf6 top node. */
install_node(&ospf6_node);
install_element(VIEW_NODE, &show_ipv6_ospf6_cmd);
install_element(VIEW_NODE, &show_ipv6_ospf6_vrfs_cmd);
install_element(CONFIG_NODE, &router_ospf6_cmd);
install_element(CONFIG_NODE, &no_router_ospf6_cmd);
2002-12-13 21:15:29 +01:00
install_element(VIEW_NODE, &show_ipv6_ospf6_route_cmd);
install_element(VIEW_NODE, &show_ipv6_ospf6_route_match_cmd);
install_element(VIEW_NODE, &show_ipv6_ospf6_route_match_detail_cmd);
2004-09-03 08:04:00 +02:00
install_element(VIEW_NODE, &show_ipv6_ospf6_route_type_detail_cmd);
install_default(OSPF6_NODE);
install_element(OSPF6_NODE, &ospf6_router_id_cmd);
install_element(OSPF6_NODE, &no_ospf6_router_id_cmd);
install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_cmd);
install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_detail_cmd);
install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_cmd);
install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_detail_cmd);
install_element(OSPF6_NODE, &ospf6_send_extra_data_cmd);
/* LSA timers commands */
install_element(OSPF6_NODE, &ospf6_timers_lsa_cmd);
install_element(OSPF6_NODE, &no_ospf6_timers_lsa_cmd);
install_element(OSPF6_NODE, &ospf6_interface_area_cmd);
install_element(OSPF6_NODE, &no_ospf6_interface_area_cmd);
install_element(OSPF6_NODE, &ospf6_stub_router_admin_cmd);
install_element(OSPF6_NODE, &no_ospf6_stub_router_admin_cmd);
/* maximum-paths command */
install_element(OSPF6_NODE, &ospf6_max_multipath_cmd);
install_element(OSPF6_NODE, &no_ospf6_max_multipath_cmd);
/* ASBR Summarisation */
install_element(OSPF6_NODE, &ospf6_external_route_aggregation_cmd);
install_element(OSPF6_NODE, &no_ospf6_external_route_aggregation_cmd);
install_element(OSPF6_NODE,
&ospf6_external_route_aggregation_no_advertise_cmd);
install_element(OSPF6_NODE,
&no_ospf6_external_route_aggregation_no_advertise_cmd);
install_element(OSPF6_NODE, &ospf6_route_aggregation_timer_cmd);
install_element(OSPF6_NODE, &no_ospf6_route_aggregation_timer_cmd);
install_element(VIEW_NODE, &show_ipv6_ospf6_external_aggregator_cmd);
install_element(OSPF6_NODE, &ospf6_distance_cmd);
install_element(OSPF6_NODE, &no_ospf6_distance_cmd);
install_element(OSPF6_NODE, &ospf6_distance_ospf6_cmd);
install_element(OSPF6_NODE, &no_ospf6_distance_ospf6_cmd);
2002-12-13 21:15:29 +01:00
}