diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst index 1e8c66ab2e..b69c4d4dc5 100644 --- a/doc/user/ospf6d.rst +++ b/doc/user/ospf6d.rst @@ -77,6 +77,13 @@ OSPF6 router of packets to process before returning. The default value of this parameter is 20. +.. clicmd:: clear ipv6 ospf6 process [vrf NAME] + + This command clears up the database and routing tables and resets the + neighborship by restarting the interface state machine. This will be + helpful when there is a change in router-id and if user wants the router-id + change to take effect, user can use this cli instead of restarting the + ospf6d daemon. .. _ospf6-area: diff --git a/lib/routemap.h b/lib/routemap.h index 4d76ae1536..4a40ec08b9 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -194,6 +194,11 @@ struct route_map_index { }; DECLARE_QOBJ_TYPE(route_map_index); +/* route map maximum length. Not strictly the maximum xpath length but cannot be + * greater + */ +#define RMAP_NAME_MAXLEN XPATH_MAXLEN + /* Route map list structure. */ struct route_map { /* Name of route map. */ diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index ba355a347e..d7307fe375 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -2478,7 +2478,7 @@ void ospf6_asbr_init(void) install_element(OSPF6_NODE, &no_ospf6_redistribute_cmd); } -void ospf6_asbr_redistribute_reset(struct ospf6 *ospf6) +void ospf6_asbr_redistribute_disable(struct ospf6 *ospf6) { int type; struct ospf6_redist *red; @@ -2500,6 +2500,35 @@ void ospf6_asbr_redistribute_reset(struct ospf6 *ospf6) } } +void ospf6_asbr_redistribute_reset(struct ospf6 *ospf6) +{ + int type; + struct ospf6_redist *red; + char buf[RMAP_NAME_MAXLEN]; + + for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { + buf[0] = '\0'; + if (type == ZEBRA_ROUTE_OSPF6) + continue; + red = ospf6_redist_lookup(ospf6, type, 0); + if (!red) + continue; + + if (type == DEFAULT_ROUTE) { + ospf6_redistribute_default_set( + ospf6, ospf6->default_originate); + continue; + } + if (ROUTEMAP_NAME(red)) + strlcpy(buf, ROUTEMAP_NAME(red), sizeof(buf)); + + ospf6_asbr_redistribute_unset(ospf6, red, type); + if (buf[0]) + ospf6_asbr_routemap_set(red, buf); + ospf6_asbr_redistribute_set(ospf6, type); + } +} + void ospf6_asbr_terminate(void) { /* Cleanup route maps */ diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h index 418c157f36..8f2135ef30 100644 --- a/ospf6d/ospf6_asbr.h +++ b/ospf6d/ospf6_asbr.h @@ -93,6 +93,7 @@ extern int ospf6_redistribute_config_write(struct vty *vty, struct ospf6 *ospf6); extern void ospf6_asbr_init(void); +extern void ospf6_asbr_redistribute_disable(struct ospf6 *ospf6); extern void ospf6_asbr_redistribute_reset(struct ospf6 *ospf6); extern void ospf6_asbr_terminate(void); extern void ospf6_asbr_send_externals_to_area(struct ospf6_area *); diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 553967e2e3..1e75fc60f6 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -2695,7 +2695,7 @@ void ospf6_interface_init(void) } /* Clear the specified interface structure */ -static void ospf6_interface_clear(struct vty *vty, struct interface *ifp) +void ospf6_interface_clear(struct interface *ifp) { struct ospf6_interface *oi; @@ -2733,7 +2733,7 @@ DEFUN (clear_ipv6_ospf6_interface, if (argc == 4) /* Clear all the ospfv3 interfaces. */ { FOR_ALL_INTERFACES (vrf, ifp) - ospf6_interface_clear(vty, ifp); + ospf6_interface_clear(ifp); } else /* Interface name is specified. */ { if ((ifp = if_lookup_by_name(argv[idx_ifname]->arg, @@ -2743,7 +2743,7 @@ DEFUN (clear_ipv6_ospf6_interface, argv[idx_ifname]->arg); return CMD_WARNING; } - ospf6_interface_clear(vty, ifp); + ospf6_interface_clear(ifp); } return CMD_SUCCESS; diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h index 530efc3bd2..c9cd74b691 100644 --- a/ospf6d/ospf6_interface.h +++ b/ospf6d/ospf6_interface.h @@ -213,6 +213,7 @@ extern int backup_seen(struct thread *); extern int neighbor_change(struct thread *); extern void ospf6_interface_init(void); +extern void ospf6_interface_clear(struct interface *ifp); extern void install_element_ospf6_clear_interface(void); diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 6cea5032bd..057f89797a 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -63,6 +63,10 @@ FRR_CFG_DEFAULT_BOOL(OSPF6_LOG_ADJACENCY_CHANGES, { .val_bool = false }, ); +#ifndef VTYSH_EXTRACT_PL +#include "ospf6d/ospf6_top_clippy.c" +#endif + /* global ospf6d variable */ static struct ospf6_master ospf6_master; struct ospf6_master *om6; @@ -512,7 +516,7 @@ static void ospf6_disable(struct ospf6 *o) /* XXX: This also changes persistent settings */ /* Unregister redistribution */ - ospf6_asbr_redistribute_reset(o); + ospf6_asbr_redistribute_disable(o); ospf6_lsdb_remove_all(o->lsdb); ospf6_route_remove_all(o->route_table); @@ -649,6 +653,78 @@ DEFUN(no_router_ospf6, no_router_ospf6_cmd, "no router ospf6 [vrf NAME]", return CMD_SUCCESS; } +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_flush_self_originated_lsas_now(ospf6); + ospf6->inst_shutdown = 0; + ospf6_db_clear(ospf6); + + ospf6_router_id_update(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); + if (ospf6 == NULL) + vty_out(vty, "OSPFv3 is not configured\n"); + else + ospf6_process_reset(ospf6); + + return CMD_SUCCESS; +} + /* change Router_ID commands. */ DEFUN(ospf6_router_id, ospf6_router_id_cmd, @@ -679,7 +755,7 @@ DEFUN(ospf6_router_id, for (ALL_LIST_ELEMENTS_RO(o->area_list, node, oa)) { if (oa->full_nbrs) { vty_out(vty, - "For this router-id change to take effect, save config and restart ospf6d\n"); + "For this router-id change to take effect, run the \"clear ipv6 ospf6 process\" command\n"); return CMD_SUCCESS; } } @@ -705,7 +781,7 @@ DEFUN(no_ospf6_router_id, for (ALL_LIST_ELEMENTS_RO(o->area_list, node, oa)) { if (oa->full_nbrs) { vty_out(vty, - "For this router-id change to take effect, save config and restart ospf6d\n"); + "For this router-id change to take effect, run the \"clear ipv6 ospf6 process\" command\n"); return CMD_SUCCESS; } } @@ -1708,6 +1784,11 @@ static struct cmd_node ospf6_node = { .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) { diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h index 5b739ac76b..51df4b6b8e 100644 --- a/ospf6d/ospf6_top.h +++ b/ospf6d/ospf6_top.h @@ -173,6 +173,7 @@ extern struct ospf6_master *om6; /* prototypes */ extern void ospf6_master_init(struct thread_master *master); +extern void install_element_ospf6_clear_process(void); extern void ospf6_top_init(void); extern void ospf6_delete(struct ospf6 *o); extern void ospf6_router_id_update(struct ospf6 *ospf6); diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c index 65f0aa664e..fb6ac4402a 100644 --- a/ospf6d/ospf6d.c +++ b/ospf6d/ospf6d.c @@ -1425,6 +1425,7 @@ void ospf6_init(struct thread_master *master) install_element_ospf6_debug_flood(); install_element_ospf6_debug_nssa(); + install_element_ospf6_clear_process(); install_element_ospf6_clear_interface(); install_element(ENABLE_NODE, &show_debugging_ospf6_cmd); diff --git a/ospf6d/subdir.am b/ospf6d/subdir.am index 2e1891be71..2b7bce5392 100644 --- a/ospf6d/subdir.am +++ b/ospf6d/subdir.am @@ -88,6 +88,7 @@ ospf6d_ospf6d_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic ospf6d_ospf6d_snmp_la_LIBADD = lib/libfrrsnmp.la clippy_scan += \ + ospf6d/ospf6_top.c \ ospf6d/ospf6_asbr.c \ # end