mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-02 18:54:42 +00:00

Currently the ospf6d's commands with non-exist vrfs can't give the error informations to users. This commit adds a macro "OSPF6_CMD_CHECK_VRF" to give error information if with non-exist vrfs. As usual, skip the checking process in the case of json. So one command can call this macro to do the checking process in its end. At that time it need know json style or not, so add "json" parameter for several related functions. BTW, suppress the build warning of the macro `OSPF6_FIND_VRF_ARGS`: "Macros starting with if should be enclosed by a do - while loop to avoid possible if/else logic defects." Signed-off-by: anlan_cs <anlan_cs@tom.com>
1305 lines
38 KiB
C
1305 lines
38 KiB
C
/*
|
|
* Copyright (C) 2003 Yasuhiro Ohara
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
#include <zebra.h>
|
|
|
|
#include "log.h"
|
|
#include "memory.h"
|
|
#include "thread.h"
|
|
#include "linklist.h"
|
|
#include "vty.h"
|
|
#include "command.h"
|
|
#include "lib/bfd.h"
|
|
|
|
#include "ospf6_proto.h"
|
|
#include "ospf6_lsa.h"
|
|
#include "ospf6_lsdb.h"
|
|
#include "ospf6_message.h"
|
|
#include "ospf6_top.h"
|
|
#include "ospf6_area.h"
|
|
#include "ospf6_interface.h"
|
|
#include "ospf6_neighbor.h"
|
|
#include "ospf6_intra.h"
|
|
#include "ospf6_flood.h"
|
|
#include "ospf6d.h"
|
|
#include "ospf6_bfd.h"
|
|
#include "ospf6_abr.h"
|
|
#include "ospf6_asbr.h"
|
|
#include "ospf6_lsa.h"
|
|
#include "ospf6_spf.h"
|
|
#include "ospf6_zebra.h"
|
|
#include "ospf6_gr.h"
|
|
#include "lib/json.h"
|
|
|
|
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_NEIGHBOR, "OSPF6 neighbor");
|
|
|
|
DEFINE_HOOK(ospf6_neighbor_change,
|
|
(struct ospf6_neighbor * on, int state, int next_state),
|
|
(on, state, next_state));
|
|
|
|
unsigned char conf_debug_ospf6_neighbor = 0;
|
|
|
|
const char *const ospf6_neighbor_state_str[] = {
|
|
"None", "Down", "Attempt", "Init", "Twoway",
|
|
"ExStart", "ExChange", "Loading", "Full", NULL};
|
|
|
|
const char *const ospf6_neighbor_event_str[] = {
|
|
"NoEvent", "HelloReceived", "2-WayReceived", "NegotiationDone",
|
|
"ExchangeDone", "LoadingDone", "AdjOK?", "SeqNumberMismatch",
|
|
"BadLSReq", "1-WayReceived", "InactivityTimer",
|
|
};
|
|
|
|
int ospf6_neighbor_cmp(void *va, void *vb)
|
|
{
|
|
struct ospf6_neighbor *ona = (struct ospf6_neighbor *)va;
|
|
struct ospf6_neighbor *onb = (struct ospf6_neighbor *)vb;
|
|
|
|
if (ona->router_id == onb->router_id)
|
|
return 0;
|
|
|
|
return (ntohl(ona->router_id) < ntohl(onb->router_id)) ? -1 : 1;
|
|
}
|
|
|
|
struct ospf6_neighbor *ospf6_neighbor_lookup(uint32_t router_id,
|
|
struct ospf6_interface *oi)
|
|
{
|
|
struct listnode *n;
|
|
struct ospf6_neighbor *on;
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, n, on))
|
|
if (on->router_id == router_id)
|
|
return on;
|
|
|
|
return (struct ospf6_neighbor *)NULL;
|
|
}
|
|
|
|
struct ospf6_neighbor *ospf6_area_neighbor_lookup(struct ospf6_area *area,
|
|
uint32_t router_id)
|
|
{
|
|
struct ospf6_interface *oi;
|
|
struct ospf6_neighbor *nbr;
|
|
struct listnode *node;
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(area->if_list, node, oi)) {
|
|
nbr = ospf6_neighbor_lookup(router_id, oi);
|
|
if (nbr)
|
|
return nbr;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* create ospf6_neighbor */
|
|
struct ospf6_neighbor *ospf6_neighbor_create(uint32_t router_id,
|
|
struct ospf6_interface *oi)
|
|
{
|
|
struct ospf6_neighbor *on;
|
|
char buf[16];
|
|
|
|
on = XCALLOC(MTYPE_OSPF6_NEIGHBOR, sizeof(struct ospf6_neighbor));
|
|
inet_ntop(AF_INET, &router_id, buf, sizeof(buf));
|
|
snprintf(on->name, sizeof(on->name), "%s%%%s", buf,
|
|
oi->interface->name);
|
|
on->ospf6_if = oi;
|
|
on->state = OSPF6_NEIGHBOR_DOWN;
|
|
on->state_change = 0;
|
|
monotime(&on->last_changed);
|
|
on->router_id = router_id;
|
|
|
|
on->summary_list = ospf6_lsdb_create(on);
|
|
on->request_list = ospf6_lsdb_create(on);
|
|
on->retrans_list = ospf6_lsdb_create(on);
|
|
|
|
on->dbdesc_list = ospf6_lsdb_create(on);
|
|
on->lsupdate_list = ospf6_lsdb_create(on);
|
|
on->lsack_list = ospf6_lsdb_create(on);
|
|
|
|
listnode_add_sort(oi->neighbor_list, on);
|
|
|
|
ospf6_bfd_info_nbr_create(oi, on);
|
|
return on;
|
|
}
|
|
|
|
void ospf6_neighbor_delete(struct ospf6_neighbor *on)
|
|
{
|
|
struct ospf6_lsa *lsa, *lsanext;
|
|
|
|
ospf6_lsdb_remove_all(on->summary_list);
|
|
ospf6_lsdb_remove_all(on->request_list);
|
|
for (ALL_LSDB(on->retrans_list, lsa, lsanext)) {
|
|
ospf6_decrement_retrans_count(lsa);
|
|
ospf6_lsdb_remove(lsa, on->retrans_list);
|
|
}
|
|
|
|
ospf6_lsdb_remove_all(on->dbdesc_list);
|
|
ospf6_lsdb_remove_all(on->lsupdate_list);
|
|
ospf6_lsdb_remove_all(on->lsack_list);
|
|
|
|
ospf6_lsdb_delete(on->summary_list);
|
|
ospf6_lsdb_delete(on->request_list);
|
|
ospf6_lsdb_delete(on->retrans_list);
|
|
|
|
ospf6_lsdb_delete(on->dbdesc_list);
|
|
ospf6_lsdb_delete(on->lsupdate_list);
|
|
ospf6_lsdb_delete(on->lsack_list);
|
|
|
|
THREAD_OFF(on->inactivity_timer);
|
|
|
|
THREAD_OFF(on->last_dbdesc_release_timer);
|
|
|
|
THREAD_OFF(on->thread_send_dbdesc);
|
|
THREAD_OFF(on->thread_send_lsreq);
|
|
THREAD_OFF(on->thread_send_lsupdate);
|
|
THREAD_OFF(on->thread_send_lsack);
|
|
THREAD_OFF(on->thread_exchange_done);
|
|
THREAD_OFF(on->thread_adj_ok);
|
|
|
|
THREAD_OFF(on->gr_helper_info.t_grace_timer);
|
|
|
|
bfd_sess_free(&on->bfd_session);
|
|
XFREE(MTYPE_OSPF6_NEIGHBOR, on);
|
|
}
|
|
|
|
static void ospf6_neighbor_state_change(uint8_t next_state,
|
|
struct ospf6_neighbor *on, int event)
|
|
{
|
|
uint8_t prev_state;
|
|
|
|
prev_state = on->state;
|
|
on->state = next_state;
|
|
|
|
if (prev_state == next_state)
|
|
return;
|
|
|
|
on->state_change++;
|
|
monotime(&on->last_changed);
|
|
|
|
/* log */
|
|
if (IS_OSPF6_DEBUG_NEIGHBOR(STATE)) {
|
|
zlog_debug("Neighbor state change %s: [%s]->[%s] (%s)",
|
|
on->name, ospf6_neighbor_state_str[prev_state],
|
|
ospf6_neighbor_state_str[next_state],
|
|
ospf6_neighbor_event_string(event));
|
|
}
|
|
|
|
/* Optionally notify about adjacency changes */
|
|
if (CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags,
|
|
OSPF6_LOG_ADJACENCY_CHANGES)
|
|
&& (CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags,
|
|
OSPF6_LOG_ADJACENCY_DETAIL)
|
|
|| (next_state == OSPF6_NEIGHBOR_FULL)
|
|
|| (next_state < prev_state)))
|
|
zlog_notice("AdjChg: Nbr %s: %s -> %s (%s)", on->name,
|
|
ospf6_neighbor_state_str[prev_state],
|
|
ospf6_neighbor_state_str[next_state],
|
|
ospf6_neighbor_event_string(event));
|
|
|
|
if (prev_state == OSPF6_NEIGHBOR_FULL
|
|
|| next_state == OSPF6_NEIGHBOR_FULL) {
|
|
if (!OSPF6_GR_IS_ACTIVE_HELPER(on)) {
|
|
OSPF6_ROUTER_LSA_SCHEDULE(on->ospf6_if->area);
|
|
if (on->ospf6_if->state == OSPF6_INTERFACE_DR) {
|
|
OSPF6_NETWORK_LSA_SCHEDULE(on->ospf6_if);
|
|
OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(
|
|
on->ospf6_if);
|
|
}
|
|
}
|
|
if (next_state == OSPF6_NEIGHBOR_FULL)
|
|
on->ospf6_if->area->intra_prefix_originate = 1;
|
|
|
|
if (!OSPF6_GR_IS_ACTIVE_HELPER(on))
|
|
OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(
|
|
on->ospf6_if->area);
|
|
|
|
if ((prev_state == OSPF6_NEIGHBOR_LOADING
|
|
|| prev_state == OSPF6_NEIGHBOR_EXCHANGE)
|
|
&& next_state == OSPF6_NEIGHBOR_FULL) {
|
|
OSPF6_AS_EXTERN_LSA_SCHEDULE(on->ospf6_if);
|
|
on->ospf6_if->area->full_nbrs++;
|
|
}
|
|
|
|
if (prev_state == OSPF6_NEIGHBOR_FULL)
|
|
on->ospf6_if->area->full_nbrs--;
|
|
}
|
|
|
|
if ((prev_state == OSPF6_NEIGHBOR_EXCHANGE
|
|
|| prev_state == OSPF6_NEIGHBOR_LOADING)
|
|
&& (next_state != OSPF6_NEIGHBOR_EXCHANGE
|
|
&& next_state != OSPF6_NEIGHBOR_LOADING))
|
|
ospf6_maxage_remove(on->ospf6_if->area->ospf6);
|
|
|
|
hook_call(ospf6_neighbor_change, on, next_state, prev_state);
|
|
ospf6_bfd_trigger_event(on, prev_state, next_state);
|
|
}
|
|
|
|
/* RFC2328 section 10.4 */
|
|
static int need_adjacency(struct ospf6_neighbor *on)
|
|
{
|
|
if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT
|
|
|| on->ospf6_if->state == OSPF6_INTERFACE_DR
|
|
|| on->ospf6_if->state == OSPF6_INTERFACE_BDR)
|
|
return 1;
|
|
|
|
if (on->ospf6_if->drouter == on->router_id
|
|
|| on->ospf6_if->bdrouter == on->router_id)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int hello_received(struct thread *thread)
|
|
{
|
|
struct ospf6_neighbor *on;
|
|
|
|
on = (struct ospf6_neighbor *)THREAD_ARG(thread);
|
|
assert(on);
|
|
|
|
if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT))
|
|
zlog_debug("Neighbor Event %s: *HelloReceived*", on->name);
|
|
|
|
/* reset Inactivity Timer */
|
|
THREAD_OFF(on->inactivity_timer);
|
|
thread_add_timer(master, inactivity_timer, on,
|
|
on->ospf6_if->dead_interval, &on->inactivity_timer);
|
|
|
|
if (on->state <= OSPF6_NEIGHBOR_DOWN)
|
|
ospf6_neighbor_state_change(OSPF6_NEIGHBOR_INIT, on,
|
|
OSPF6_NEIGHBOR_EVENT_HELLO_RCVD);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int twoway_received(struct thread *thread)
|
|
{
|
|
struct ospf6_neighbor *on;
|
|
|
|
on = (struct ospf6_neighbor *)THREAD_ARG(thread);
|
|
assert(on);
|
|
|
|
if (on->state > OSPF6_NEIGHBOR_INIT)
|
|
return 0;
|
|
|
|
if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT))
|
|
zlog_debug("Neighbor Event %s: *2Way-Received*", on->name);
|
|
|
|
thread_add_event(master, neighbor_change, on->ospf6_if, 0, NULL);
|
|
|
|
if (!need_adjacency(on)) {
|
|
ospf6_neighbor_state_change(OSPF6_NEIGHBOR_TWOWAY, on,
|
|
OSPF6_NEIGHBOR_EVENT_TWOWAY_RCVD);
|
|
return 0;
|
|
}
|
|
|
|
ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXSTART, on,
|
|
OSPF6_NEIGHBOR_EVENT_TWOWAY_RCVD);
|
|
SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
|
|
SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT);
|
|
SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT);
|
|
|
|
THREAD_OFF(on->thread_send_dbdesc);
|
|
thread_add_event(master, ospf6_dbdesc_send, on, 0,
|
|
&on->thread_send_dbdesc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int negotiation_done(struct thread *thread)
|
|
{
|
|
struct ospf6_neighbor *on;
|
|
struct ospf6_lsa *lsa, *lsanext;
|
|
|
|
on = (struct ospf6_neighbor *)THREAD_ARG(thread);
|
|
assert(on);
|
|
|
|
if (on->state != OSPF6_NEIGHBOR_EXSTART)
|
|
return 0;
|
|
|
|
if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT))
|
|
zlog_debug("Neighbor Event %s: *NegotiationDone*", on->name);
|
|
|
|
/* clear ls-list */
|
|
ospf6_lsdb_remove_all(on->summary_list);
|
|
ospf6_lsdb_remove_all(on->request_list);
|
|
for (ALL_LSDB(on->retrans_list, lsa, lsanext)) {
|
|
ospf6_decrement_retrans_count(lsa);
|
|
ospf6_lsdb_remove(lsa, on->retrans_list);
|
|
}
|
|
|
|
/* Interface scoped LSAs */
|
|
for (ALL_LSDB(on->ospf6_if->lsdb, lsa, lsanext)) {
|
|
if (OSPF6_LSA_IS_MAXAGE(lsa)) {
|
|
ospf6_increment_retrans_count(lsa);
|
|
ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list);
|
|
} else
|
|
ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->summary_list);
|
|
}
|
|
|
|
/* Area scoped LSAs */
|
|
for (ALL_LSDB(on->ospf6_if->area->lsdb, lsa, lsanext)) {
|
|
if (OSPF6_LSA_IS_MAXAGE(lsa)) {
|
|
ospf6_increment_retrans_count(lsa);
|
|
ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list);
|
|
} else
|
|
ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->summary_list);
|
|
}
|
|
|
|
/* AS scoped LSAs */
|
|
for (ALL_LSDB(on->ospf6_if->area->ospf6->lsdb, lsa, lsanext)) {
|
|
if (OSPF6_LSA_IS_MAXAGE(lsa)) {
|
|
ospf6_increment_retrans_count(lsa);
|
|
ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list);
|
|
} else
|
|
ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->summary_list);
|
|
}
|
|
|
|
UNSET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT);
|
|
ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXCHANGE, on,
|
|
OSPF6_NEIGHBOR_EVENT_NEGOTIATION_DONE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int ospf6_neighbor_last_dbdesc_release(struct thread *thread)
|
|
{
|
|
struct ospf6_neighbor *on = THREAD_ARG(thread);
|
|
|
|
assert(on);
|
|
memset(&on->dbdesc_last, 0, sizeof(struct ospf6_dbdesc));
|
|
|
|
return 0;
|
|
}
|
|
|
|
int exchange_done(struct thread *thread)
|
|
{
|
|
struct ospf6_neighbor *on;
|
|
|
|
on = (struct ospf6_neighbor *)THREAD_ARG(thread);
|
|
assert(on);
|
|
|
|
if (on->state != OSPF6_NEIGHBOR_EXCHANGE)
|
|
return 0;
|
|
|
|
if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT))
|
|
zlog_debug("Neighbor Event %s: *ExchangeDone*", on->name);
|
|
|
|
THREAD_OFF(on->thread_send_dbdesc);
|
|
ospf6_lsdb_remove_all(on->dbdesc_list);
|
|
|
|
/* RFC 2328 (10.8): Release the last dbdesc after dead_interval */
|
|
if (!CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT)) {
|
|
THREAD_OFF(on->last_dbdesc_release_timer);
|
|
thread_add_timer(master, ospf6_neighbor_last_dbdesc_release, on,
|
|
on->ospf6_if->dead_interval,
|
|
&on->last_dbdesc_release_timer);
|
|
}
|
|
|
|
if (on->request_list->count == 0)
|
|
ospf6_neighbor_state_change(OSPF6_NEIGHBOR_FULL, on,
|
|
OSPF6_NEIGHBOR_EVENT_EXCHANGE_DONE);
|
|
else {
|
|
ospf6_neighbor_state_change(OSPF6_NEIGHBOR_LOADING, on,
|
|
OSPF6_NEIGHBOR_EVENT_EXCHANGE_DONE);
|
|
|
|
thread_add_event(master, ospf6_lsreq_send, on, 0,
|
|
&on->thread_send_lsreq);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Check loading state. */
|
|
void ospf6_check_nbr_loading(struct ospf6_neighbor *on)
|
|
{
|
|
|
|
/* RFC2328 Section 10.9: When the neighbor responds to these requests
|
|
with the proper Link State Update packet(s), the Link state request
|
|
list is truncated and a new Link State Request packet is sent.
|
|
*/
|
|
if ((on->state == OSPF6_NEIGHBOR_LOADING)
|
|
|| (on->state == OSPF6_NEIGHBOR_EXCHANGE)) {
|
|
if (on->request_list->count == 0)
|
|
thread_add_event(master, loading_done, on, 0, NULL);
|
|
else if (on->last_ls_req == NULL) {
|
|
if (on->thread_send_lsreq != NULL)
|
|
THREAD_OFF(on->thread_send_lsreq);
|
|
thread_add_event(master, ospf6_lsreq_send, on, 0,
|
|
&on->thread_send_lsreq);
|
|
}
|
|
}
|
|
}
|
|
|
|
int loading_done(struct thread *thread)
|
|
{
|
|
struct ospf6_neighbor *on;
|
|
|
|
on = (struct ospf6_neighbor *)THREAD_ARG(thread);
|
|
assert(on);
|
|
|
|
if (on->state != OSPF6_NEIGHBOR_LOADING)
|
|
return 0;
|
|
|
|
if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT))
|
|
zlog_debug("Neighbor Event %s: *LoadingDone*", on->name);
|
|
|
|
assert(on->request_list->count == 0);
|
|
|
|
ospf6_neighbor_state_change(OSPF6_NEIGHBOR_FULL, on,
|
|
OSPF6_NEIGHBOR_EVENT_LOADING_DONE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int adj_ok(struct thread *thread)
|
|
{
|
|
struct ospf6_neighbor *on;
|
|
struct ospf6_lsa *lsa, *lsanext;
|
|
|
|
on = (struct ospf6_neighbor *)THREAD_ARG(thread);
|
|
assert(on);
|
|
|
|
if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT))
|
|
zlog_debug("Neighbor Event %s: *AdjOK?*", on->name);
|
|
|
|
if (on->state == OSPF6_NEIGHBOR_TWOWAY && need_adjacency(on)) {
|
|
ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXSTART, on,
|
|
OSPF6_NEIGHBOR_EVENT_ADJ_OK);
|
|
SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
|
|
SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT);
|
|
SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT);
|
|
|
|
THREAD_OFF(on->thread_send_dbdesc);
|
|
on->thread_send_dbdesc = NULL;
|
|
thread_add_event(master, ospf6_dbdesc_send, on, 0,
|
|
&on->thread_send_dbdesc);
|
|
|
|
} else if (on->state >= OSPF6_NEIGHBOR_EXSTART && !need_adjacency(on)) {
|
|
ospf6_neighbor_state_change(OSPF6_NEIGHBOR_TWOWAY, on,
|
|
OSPF6_NEIGHBOR_EVENT_ADJ_OK);
|
|
ospf6_lsdb_remove_all(on->summary_list);
|
|
ospf6_lsdb_remove_all(on->request_list);
|
|
for (ALL_LSDB(on->retrans_list, lsa, lsanext)) {
|
|
ospf6_decrement_retrans_count(lsa);
|
|
ospf6_lsdb_remove(lsa, on->retrans_list);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int seqnumber_mismatch(struct thread *thread)
|
|
{
|
|
struct ospf6_neighbor *on;
|
|
struct ospf6_lsa *lsa, *lsanext;
|
|
|
|
on = (struct ospf6_neighbor *)THREAD_ARG(thread);
|
|
assert(on);
|
|
|
|
if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
|
|
return 0;
|
|
|
|
if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT))
|
|
zlog_debug("Neighbor Event %s: *SeqNumberMismatch*", on->name);
|
|
|
|
ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXSTART, on,
|
|
OSPF6_NEIGHBOR_EVENT_SEQNUMBER_MISMATCH);
|
|
SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
|
|
SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT);
|
|
SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT);
|
|
|
|
ospf6_lsdb_remove_all(on->summary_list);
|
|
ospf6_lsdb_remove_all(on->request_list);
|
|
for (ALL_LSDB(on->retrans_list, lsa, lsanext)) {
|
|
ospf6_decrement_retrans_count(lsa);
|
|
ospf6_lsdb_remove(lsa, on->retrans_list);
|
|
}
|
|
|
|
THREAD_OFF(on->thread_send_dbdesc);
|
|
on->dbdesc_seqnum++; /* Incr seqnum as per RFC2328, sec 10.3 */
|
|
|
|
on->thread_send_dbdesc = NULL;
|
|
thread_add_event(master, ospf6_dbdesc_send, on, 0,
|
|
&on->thread_send_dbdesc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int bad_lsreq(struct thread *thread)
|
|
{
|
|
struct ospf6_neighbor *on;
|
|
struct ospf6_lsa *lsa, *lsanext;
|
|
|
|
on = (struct ospf6_neighbor *)THREAD_ARG(thread);
|
|
assert(on);
|
|
|
|
if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
|
|
return 0;
|
|
|
|
if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT))
|
|
zlog_debug("Neighbor Event %s: *BadLSReq*", on->name);
|
|
|
|
ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXSTART, on,
|
|
OSPF6_NEIGHBOR_EVENT_BAD_LSREQ);
|
|
SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
|
|
SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT);
|
|
SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT);
|
|
|
|
ospf6_lsdb_remove_all(on->summary_list);
|
|
ospf6_lsdb_remove_all(on->request_list);
|
|
for (ALL_LSDB(on->retrans_list, lsa, lsanext)) {
|
|
ospf6_decrement_retrans_count(lsa);
|
|
ospf6_lsdb_remove(lsa, on->retrans_list);
|
|
}
|
|
|
|
THREAD_OFF(on->thread_send_dbdesc);
|
|
on->dbdesc_seqnum++; /* Incr seqnum as per RFC2328, sec 10.3 */
|
|
|
|
on->thread_send_dbdesc = NULL;
|
|
thread_add_event(master, ospf6_dbdesc_send, on, 0,
|
|
&on->thread_send_dbdesc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int oneway_received(struct thread *thread)
|
|
{
|
|
struct ospf6_neighbor *on;
|
|
struct ospf6_lsa *lsa, *lsanext;
|
|
|
|
on = (struct ospf6_neighbor *)THREAD_ARG(thread);
|
|
assert(on);
|
|
|
|
if (on->state < OSPF6_NEIGHBOR_TWOWAY)
|
|
return 0;
|
|
|
|
if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT))
|
|
zlog_debug("Neighbor Event %s: *1Way-Received*", on->name);
|
|
|
|
ospf6_neighbor_state_change(OSPF6_NEIGHBOR_INIT, on,
|
|
OSPF6_NEIGHBOR_EVENT_ONEWAY_RCVD);
|
|
thread_add_event(master, neighbor_change, on->ospf6_if, 0, NULL);
|
|
|
|
ospf6_lsdb_remove_all(on->summary_list);
|
|
ospf6_lsdb_remove_all(on->request_list);
|
|
for (ALL_LSDB(on->retrans_list, lsa, lsanext)) {
|
|
ospf6_decrement_retrans_count(lsa);
|
|
ospf6_lsdb_remove(lsa, on->retrans_list);
|
|
}
|
|
|
|
THREAD_OFF(on->thread_send_dbdesc);
|
|
THREAD_OFF(on->thread_send_lsreq);
|
|
THREAD_OFF(on->thread_send_lsupdate);
|
|
THREAD_OFF(on->thread_send_lsack);
|
|
THREAD_OFF(on->thread_exchange_done);
|
|
THREAD_OFF(on->thread_adj_ok);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int inactivity_timer(struct thread *thread)
|
|
{
|
|
struct ospf6_neighbor *on;
|
|
|
|
on = (struct ospf6_neighbor *)THREAD_ARG(thread);
|
|
assert(on);
|
|
|
|
if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT))
|
|
zlog_debug("Neighbor Event %s: *InactivityTimer*", on->name);
|
|
|
|
on->drouter = on->prev_drouter = 0;
|
|
on->bdrouter = on->prev_bdrouter = 0;
|
|
|
|
if (!OSPF6_GR_IS_ACTIVE_HELPER(on)) {
|
|
on->drouter = on->prev_drouter = 0;
|
|
on->bdrouter = on->prev_bdrouter = 0;
|
|
|
|
ospf6_neighbor_state_change(
|
|
OSPF6_NEIGHBOR_DOWN, on,
|
|
OSPF6_NEIGHBOR_EVENT_INACTIVITY_TIMER);
|
|
thread_add_event(master, neighbor_change, on->ospf6_if, 0,
|
|
NULL);
|
|
|
|
listnode_delete(on->ospf6_if->neighbor_list, on);
|
|
ospf6_neighbor_delete(on);
|
|
|
|
} else {
|
|
if (IS_DEBUG_OSPF6_GR)
|
|
zlog_debug(
|
|
"%s, Acting as HELPER for this neighbour, So restart the dead timer.",
|
|
__PRETTY_FUNCTION__);
|
|
|
|
thread_add_timer(master, inactivity_timer, on,
|
|
on->ospf6_if->dead_interval,
|
|
&on->inactivity_timer);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* vty functions */
|
|
/* show neighbor structure */
|
|
static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on,
|
|
json_object *json_array, bool use_json)
|
|
{
|
|
char router_id[16];
|
|
char duration[64];
|
|
struct timeval res;
|
|
char nstate[16];
|
|
char deadtime[64];
|
|
long h, m, s;
|
|
json_object *json_route;
|
|
|
|
/* Router-ID (Name) */
|
|
inet_ntop(AF_INET, &on->router_id, router_id, sizeof(router_id));
|
|
#ifdef HAVE_GETNAMEINFO
|
|
{
|
|
}
|
|
#endif /*HAVE_GETNAMEINFO*/
|
|
|
|
/* Dead time */
|
|
h = m = s = 0;
|
|
if (on->inactivity_timer) {
|
|
s = monotime_until(&on->inactivity_timer->u.sands, NULL)
|
|
/ 1000000LL;
|
|
h = s / 3600;
|
|
s -= h * 3600;
|
|
m = s / 60;
|
|
s -= m * 60;
|
|
}
|
|
snprintf(deadtime, sizeof(deadtime), "%02ld:%02ld:%02ld", h, m, s);
|
|
|
|
/* Neighbor State */
|
|
if (on->ospf6_if->type == OSPF_IFTYPE_POINTOPOINT)
|
|
snprintf(nstate, sizeof(nstate), "PointToPoint");
|
|
else {
|
|
if (on->router_id == on->drouter)
|
|
snprintf(nstate, sizeof(nstate), "DR");
|
|
else if (on->router_id == on->bdrouter)
|
|
snprintf(nstate, sizeof(nstate), "BDR");
|
|
else
|
|
snprintf(nstate, sizeof(nstate), "DROther");
|
|
}
|
|
|
|
/* Duration */
|
|
monotime_since(&on->last_changed, &res);
|
|
timerstring(&res, duration, sizeof(duration));
|
|
|
|
/*
|
|
vty_out (vty, "%-15s %3d %11s %6s/%-12s %11s %s[%s]\n",
|
|
"Neighbor ID", "Pri", "DeadTime", "State", "IfState",
|
|
"Duration", "I/F", "State");
|
|
*/
|
|
if (use_json) {
|
|
json_route = json_object_new_object();
|
|
|
|
json_object_string_add(json_route, "neighborId", router_id);
|
|
json_object_int_add(json_route, "priority", on->priority);
|
|
json_object_string_add(json_route, "deadTime", deadtime);
|
|
json_object_string_add(json_route, "state",
|
|
ospf6_neighbor_state_str[on->state]);
|
|
json_object_string_add(json_route, "ifState", nstate);
|
|
json_object_string_add(json_route, "duration", duration);
|
|
json_object_string_add(json_route, "interfaceName",
|
|
on->ospf6_if->interface->name);
|
|
json_object_string_add(
|
|
json_route, "interfaceState",
|
|
ospf6_interface_state_str[on->ospf6_if->state]);
|
|
|
|
json_object_array_add(json_array, json_route);
|
|
} else
|
|
vty_out(vty, "%-15s %3d %11s %8s/%-12s %11s %s[%s]\n",
|
|
router_id, on->priority, deadtime,
|
|
ospf6_neighbor_state_str[on->state], nstate, duration,
|
|
on->ospf6_if->interface->name,
|
|
ospf6_interface_state_str[on->ospf6_if->state]);
|
|
}
|
|
|
|
static void ospf6_neighbor_show_drchoice(struct vty *vty,
|
|
struct ospf6_neighbor *on,
|
|
json_object *json_array, bool use_json)
|
|
{
|
|
char router_id[16];
|
|
char drouter[16], bdrouter[16];
|
|
char duration[64];
|
|
struct timeval now, res;
|
|
json_object *json_route;
|
|
|
|
/*
|
|
vty_out (vty, "%-15s %6s/%-11s %-15s %-15s %s[%s]\n",
|
|
"RouterID", "State", "Duration", "DR", "BDR", "I/F",
|
|
"State");
|
|
*/
|
|
|
|
inet_ntop(AF_INET, &on->router_id, router_id, sizeof(router_id));
|
|
inet_ntop(AF_INET, &on->drouter, drouter, sizeof(drouter));
|
|
inet_ntop(AF_INET, &on->bdrouter, bdrouter, sizeof(bdrouter));
|
|
|
|
monotime(&now);
|
|
timersub(&now, &on->last_changed, &res);
|
|
timerstring(&res, duration, sizeof(duration));
|
|
|
|
if (use_json) {
|
|
json_route = json_object_new_object();
|
|
json_object_string_add(json_route, "routerId", router_id);
|
|
json_object_string_add(json_route, "state",
|
|
ospf6_neighbor_state_str[on->state]);
|
|
json_object_string_add(json_route, "duration", duration);
|
|
json_object_string_add(json_route, "dRouter", drouter);
|
|
json_object_string_add(json_route, "bdRouter", bdrouter);
|
|
json_object_string_add(json_route, "interfaceName",
|
|
on->ospf6_if->interface->name);
|
|
json_object_string_add(
|
|
json_route, "interfaceState",
|
|
ospf6_interface_state_str[on->ospf6_if->state]);
|
|
|
|
json_object_array_add(json_array, json_route);
|
|
} else
|
|
vty_out(vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]\n", router_id,
|
|
ospf6_neighbor_state_str[on->state], duration, drouter,
|
|
bdrouter, on->ospf6_if->interface->name,
|
|
ospf6_interface_state_str[on->ospf6_if->state]);
|
|
}
|
|
|
|
static void ospf6_neighbor_show_detail(struct vty *vty,
|
|
struct ospf6_neighbor *on,
|
|
json_object *json, bool use_json)
|
|
{
|
|
char drouter[16], bdrouter[16];
|
|
char linklocal_addr[64], duration[32];
|
|
struct timeval now, res;
|
|
struct ospf6_lsa *lsa, *lsanext;
|
|
json_object *json_neighbor;
|
|
json_object *json_array;
|
|
char db_desc_str[20];
|
|
|
|
inet_ntop(AF_INET6, &on->linklocal_addr, linklocal_addr,
|
|
sizeof(linklocal_addr));
|
|
inet_ntop(AF_INET, &on->drouter, drouter, sizeof(drouter));
|
|
inet_ntop(AF_INET, &on->bdrouter, bdrouter, sizeof(bdrouter));
|
|
|
|
monotime(&now);
|
|
timersub(&now, &on->last_changed, &res);
|
|
timerstring(&res, duration, sizeof(duration));
|
|
|
|
if (use_json) {
|
|
json_neighbor = json_object_new_object();
|
|
json_object_string_add(json_neighbor, "area",
|
|
on->ospf6_if->area->name);
|
|
json_object_string_add(json_neighbor, "interface",
|
|
on->ospf6_if->interface->name);
|
|
json_object_int_add(json_neighbor, "interfaceIndex",
|
|
on->ospf6_if->interface->ifindex);
|
|
json_object_int_add(json_neighbor, "neighborInterfaceIndex",
|
|
on->ifindex);
|
|
json_object_string_add(json_neighbor, "linkLocalAddress",
|
|
linklocal_addr);
|
|
json_object_string_add(json_neighbor, "neighborState",
|
|
ospf6_neighbor_state_str[on->state]);
|
|
json_object_string_add(json_neighbor, "neighborStateDuration",
|
|
duration);
|
|
json_object_string_add(json_neighbor, "neighborDRouter",
|
|
drouter);
|
|
json_object_string_add(json_neighbor, "neighborBdRouter",
|
|
bdrouter);
|
|
snprintf(db_desc_str, sizeof(db_desc_str), "%s%s%s",
|
|
(CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT)
|
|
? "Initial "
|
|
: ""),
|
|
(CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT)
|
|
? "More"
|
|
: ""),
|
|
(CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT)
|
|
? "Master"
|
|
: "Slave"));
|
|
json_object_string_add(json_neighbor, "dbDescStatus",
|
|
db_desc_str);
|
|
|
|
json_object_int_add(json_neighbor, "dbDescSeqNumber",
|
|
(unsigned long)ntohl(on->dbdesc_seqnum));
|
|
|
|
json_array = json_object_new_array();
|
|
json_object_int_add(json_neighbor, "summaryListCount",
|
|
on->summary_list->count);
|
|
for (ALL_LSDB(on->summary_list, lsa, lsanext))
|
|
json_object_array_add(
|
|
json_array, json_object_new_string(lsa->name));
|
|
json_object_object_add(json_neighbor, "summaryListLsa",
|
|
json_array);
|
|
|
|
json_array = json_object_new_array();
|
|
json_object_int_add(json_neighbor, "requestListCount",
|
|
on->request_list->count);
|
|
for (ALL_LSDB(on->request_list, lsa, lsanext))
|
|
json_object_array_add(
|
|
json_array, json_object_new_string(lsa->name));
|
|
json_object_object_add(json_neighbor, "requestListLsa",
|
|
json_array);
|
|
|
|
json_array = json_object_new_array();
|
|
json_object_int_add(json_neighbor, "reTransListCount",
|
|
on->retrans_list->count);
|
|
for (ALL_LSDB(on->retrans_list, lsa, lsanext))
|
|
json_object_array_add(
|
|
json_array, json_object_new_string(lsa->name));
|
|
json_object_object_add(json_neighbor, "reTransListLsa",
|
|
json_array);
|
|
|
|
|
|
timerclear(&res);
|
|
if (on->thread_send_dbdesc)
|
|
timersub(&on->thread_send_dbdesc->u.sands, &now, &res);
|
|
timerstring(&res, duration, sizeof(duration));
|
|
json_object_int_add(json_neighbor, "pendingLsaDbDescCount",
|
|
on->dbdesc_list->count);
|
|
json_object_string_add(json_neighbor, "pendingLsaDbDescTime",
|
|
duration);
|
|
json_object_string_add(json_neighbor, "dbDescSendThread",
|
|
(on->thread_send_dbdesc ? "on" : "off"));
|
|
json_array = json_object_new_array();
|
|
for (ALL_LSDB(on->dbdesc_list, lsa, lsanext))
|
|
json_object_array_add(
|
|
json_array, json_object_new_string(lsa->name));
|
|
json_object_object_add(json_neighbor, "pendingLsaDbDesc",
|
|
json_array);
|
|
|
|
timerclear(&res);
|
|
if (on->thread_send_lsreq)
|
|
timersub(&on->thread_send_lsreq->u.sands, &now, &res);
|
|
timerstring(&res, duration, sizeof(duration));
|
|
json_object_int_add(json_neighbor, "pendingLsaLsReqCount",
|
|
on->request_list->count);
|
|
json_object_string_add(json_neighbor, "pendingLsaLsReqTime",
|
|
duration);
|
|
json_object_string_add(json_neighbor, "lsReqSendThread",
|
|
(on->thread_send_lsreq ? "on" : "off"));
|
|
json_array = json_object_new_array();
|
|
for (ALL_LSDB(on->request_list, lsa, lsanext))
|
|
json_object_array_add(
|
|
json_array, json_object_new_string(lsa->name));
|
|
json_object_object_add(json_neighbor, "pendingLsaLsReq",
|
|
json_array);
|
|
|
|
|
|
timerclear(&res);
|
|
if (on->thread_send_lsupdate)
|
|
timersub(&on->thread_send_lsupdate->u.sands, &now,
|
|
&res);
|
|
timerstring(&res, duration, sizeof(duration));
|
|
json_object_int_add(json_neighbor, "pendingLsaLsUpdateCount",
|
|
on->lsupdate_list->count);
|
|
json_object_string_add(json_neighbor, "pendingLsaLsUpdateTime",
|
|
duration);
|
|
json_object_string_add(
|
|
json_neighbor, "lsUpdateSendThread",
|
|
(on->thread_send_lsupdate ? "on" : "off"));
|
|
json_array = json_object_new_array();
|
|
for (ALL_LSDB(on->lsupdate_list, lsa, lsanext))
|
|
json_object_array_add(
|
|
json_array, json_object_new_string(lsa->name));
|
|
json_object_object_add(json_neighbor, "pendingLsaLsUpdate",
|
|
json_array);
|
|
|
|
timerclear(&res);
|
|
if (on->thread_send_lsack)
|
|
timersub(&on->thread_send_lsack->u.sands, &now, &res);
|
|
timerstring(&res, duration, sizeof(duration));
|
|
json_object_int_add(json_neighbor, "pendingLsaLsAckCount",
|
|
on->lsack_list->count);
|
|
json_object_string_add(json_neighbor, "pendingLsaLsAckTime",
|
|
duration);
|
|
json_object_string_add(json_neighbor, "lsAckSendThread",
|
|
(on->thread_send_lsack ? "on" : "off"));
|
|
json_array = json_object_new_array();
|
|
for (ALL_LSDB(on->lsack_list, lsa, lsanext))
|
|
json_object_array_add(
|
|
json_array, json_object_new_string(lsa->name));
|
|
json_object_object_add(json_neighbor, "pendingLsaLsAck",
|
|
json_array);
|
|
|
|
bfd_sess_show(vty, json_neighbor, on->bfd_session);
|
|
|
|
json_object_object_add(json, on->name, json_neighbor);
|
|
|
|
|
|
} else {
|
|
vty_out(vty, " Neighbor %s\n", on->name);
|
|
vty_out(vty, " Area %s via interface %s (ifindex %d)\n",
|
|
on->ospf6_if->area->name, on->ospf6_if->interface->name,
|
|
on->ospf6_if->interface->ifindex);
|
|
vty_out(vty, " His IfIndex: %d Link-local address: %s\n",
|
|
on->ifindex, linklocal_addr);
|
|
vty_out(vty, " State %s for a duration of %s\n",
|
|
ospf6_neighbor_state_str[on->state], duration);
|
|
vty_out(vty, " His choice of DR/BDR %s/%s, Priority %d\n",
|
|
drouter, bdrouter, on->priority);
|
|
vty_out(vty, " DbDesc status: %s%s%s SeqNum: %#lx\n",
|
|
(CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT)
|
|
? "Initial "
|
|
: ""),
|
|
(CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT)
|
|
? "More "
|
|
: ""),
|
|
(CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT)
|
|
? "Master"
|
|
: "Slave"),
|
|
(unsigned long)ntohl(on->dbdesc_seqnum));
|
|
|
|
vty_out(vty, " Summary-List: %d LSAs\n",
|
|
on->summary_list->count);
|
|
for (ALL_LSDB(on->summary_list, lsa, lsanext))
|
|
vty_out(vty, " %s\n", lsa->name);
|
|
|
|
vty_out(vty, " Request-List: %d LSAs\n",
|
|
on->request_list->count);
|
|
for (ALL_LSDB(on->request_list, lsa, lsanext))
|
|
vty_out(vty, " %s\n", lsa->name);
|
|
|
|
vty_out(vty, " Retrans-List: %d LSAs\n",
|
|
on->retrans_list->count);
|
|
for (ALL_LSDB(on->retrans_list, lsa, lsanext))
|
|
vty_out(vty, " %s\n", lsa->name);
|
|
|
|
timerclear(&res);
|
|
if (on->thread_send_dbdesc)
|
|
timersub(&on->thread_send_dbdesc->u.sands, &now, &res);
|
|
timerstring(&res, duration, sizeof(duration));
|
|
vty_out(vty,
|
|
" %d Pending LSAs for DbDesc in Time %s [thread %s]\n",
|
|
on->dbdesc_list->count, duration,
|
|
(on->thread_send_dbdesc ? "on" : "off"));
|
|
for (ALL_LSDB(on->dbdesc_list, lsa, lsanext))
|
|
vty_out(vty, " %s\n", lsa->name);
|
|
|
|
timerclear(&res);
|
|
if (on->thread_send_lsreq)
|
|
timersub(&on->thread_send_lsreq->u.sands, &now, &res);
|
|
timerstring(&res, duration, sizeof(duration));
|
|
vty_out(vty,
|
|
" %d Pending LSAs for LSReq in Time %s [thread %s]\n",
|
|
on->request_list->count, duration,
|
|
(on->thread_send_lsreq ? "on" : "off"));
|
|
for (ALL_LSDB(on->request_list, lsa, lsanext))
|
|
vty_out(vty, " %s\n", lsa->name);
|
|
|
|
timerclear(&res);
|
|
if (on->thread_send_lsupdate)
|
|
timersub(&on->thread_send_lsupdate->u.sands, &now,
|
|
&res);
|
|
timerstring(&res, duration, sizeof(duration));
|
|
vty_out(vty,
|
|
" %d Pending LSAs for LSUpdate in Time %s [thread %s]\n",
|
|
on->lsupdate_list->count, duration,
|
|
(on->thread_send_lsupdate ? "on" : "off"));
|
|
for (ALL_LSDB(on->lsupdate_list, lsa, lsanext))
|
|
vty_out(vty, " %s\n", lsa->name);
|
|
|
|
timerclear(&res);
|
|
if (on->thread_send_lsack)
|
|
timersub(&on->thread_send_lsack->u.sands, &now, &res);
|
|
timerstring(&res, duration, sizeof(duration));
|
|
vty_out(vty,
|
|
" %d Pending LSAs for LSAck in Time %s [thread %s]\n",
|
|
on->lsack_list->count, duration,
|
|
(on->thread_send_lsack ? "on" : "off"));
|
|
for (ALL_LSDB(on->lsack_list, lsa, lsanext))
|
|
vty_out(vty, " %s\n", lsa->name);
|
|
|
|
bfd_sess_show(vty, NULL, on->bfd_session);
|
|
}
|
|
}
|
|
|
|
static void ospf6_neighbor_show_detail_common(struct vty *vty,
|
|
struct ospf6 *ospf6, bool uj,
|
|
bool detail, bool drchoice)
|
|
{
|
|
struct ospf6_neighbor *on;
|
|
struct ospf6_interface *oi;
|
|
struct ospf6_area *oa;
|
|
struct listnode *i, *j, *k;
|
|
json_object *json = NULL;
|
|
json_object *json_array = NULL;
|
|
void (*showfunc)(struct vty *, struct ospf6_neighbor *,
|
|
json_object *json, bool use_json);
|
|
|
|
if (detail)
|
|
showfunc = ospf6_neighbor_show_detail;
|
|
else if (drchoice)
|
|
showfunc = ospf6_neighbor_show_drchoice;
|
|
else
|
|
showfunc = ospf6_neighbor_show;
|
|
|
|
if (uj) {
|
|
json = json_object_new_object();
|
|
json_array = json_object_new_array();
|
|
} else {
|
|
if (showfunc == ospf6_neighbor_show)
|
|
vty_out(vty, "%-15s %3s %11s %8s/%-12s %11s %s[%s]\n",
|
|
"Neighbor ID", "Pri", "DeadTime", "State",
|
|
"IfState", "Duration", "I/F", "State");
|
|
else if (showfunc == ospf6_neighbor_show_drchoice)
|
|
vty_out(vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]\n",
|
|
"RouterID", "State", "Duration", "DR", "BDR",
|
|
"I/F", "State");
|
|
}
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(ospf6->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 (showfunc == ospf6_neighbor_show_detail)
|
|
(*showfunc)(vty, on, json, uj);
|
|
else
|
|
(*showfunc)(vty, on, json_array, uj);
|
|
}
|
|
|
|
if (uj) {
|
|
if (showfunc != ospf6_neighbor_show_detail)
|
|
json_object_object_add(json, "neighbors", json_array);
|
|
else
|
|
json_object_free(json_array);
|
|
vty_json(vty, json);
|
|
}
|
|
}
|
|
|
|
DEFUN(show_ipv6_ospf6_neighbor, show_ipv6_ospf6_neighbor_cmd,
|
|
"show ipv6 ospf6 [vrf <NAME|all>] neighbor [<detail|drchoice>] [json]",
|
|
SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
|
|
"All VRFs\n"
|
|
"Neighbor list\n"
|
|
"Display details\n"
|
|
"Display DR choices\n" JSON_STR)
|
|
{
|
|
struct ospf6 *ospf6;
|
|
struct listnode *node;
|
|
const char *vrf_name = NULL;
|
|
bool all_vrf = false;
|
|
int idx_vrf = 0;
|
|
int idx_type = 4;
|
|
bool uj = use_json(argc, argv);
|
|
bool detail = false;
|
|
bool drchoice = false;
|
|
|
|
OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
|
|
|
|
if (argv_find(argv, argc, "detail", &idx_type))
|
|
detail = true;
|
|
else if (argv_find(argv, argc, "drchoice", &idx_type))
|
|
drchoice = true;
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
|
|
if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
|
|
ospf6_neighbor_show_detail_common(vty, ospf6, uj,
|
|
detail, drchoice);
|
|
if (!all_vrf)
|
|
break;
|
|
}
|
|
}
|
|
|
|
OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
static int ospf6_neighbor_show_common(struct vty *vty, int argc,
|
|
struct cmd_token **argv,
|
|
struct ospf6 *ospf6, int idx_ipv4,
|
|
bool uj)
|
|
{
|
|
struct ospf6_neighbor *on;
|
|
struct ospf6_interface *oi;
|
|
struct ospf6_area *oa;
|
|
struct listnode *i, *j, *k;
|
|
void (*showfunc)(struct vty *, struct ospf6_neighbor *,
|
|
json_object *json, bool use_json);
|
|
uint32_t router_id;
|
|
json_object *json = NULL;
|
|
|
|
showfunc = ospf6_neighbor_show_detail;
|
|
if (uj)
|
|
json = json_object_new_object();
|
|
|
|
if ((inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id)) != 1) {
|
|
vty_out(vty, "Router-ID is not parsable: %s\n",
|
|
argv[idx_ipv4]->arg);
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(ospf6->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 (router_id == on->router_id)
|
|
(*showfunc)(vty, on, json, uj);
|
|
}
|
|
|
|
if (uj)
|
|
vty_json(vty, json);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(show_ipv6_ospf6_neighbor_one, show_ipv6_ospf6_neighbor_one_cmd,
|
|
"show ipv6 ospf6 [vrf <NAME|all>] neighbor A.B.C.D [json]",
|
|
SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
|
|
"All VRFs\n"
|
|
"Neighbor list\n"
|
|
"Specify Router-ID as IPv4 address notation\n" JSON_STR)
|
|
{
|
|
int idx_ipv4 = 4;
|
|
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);
|
|
|
|
OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
|
|
if (idx_vrf > 0)
|
|
idx_ipv4 += 2;
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
|
|
if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
|
|
ospf6_neighbor_show_common(vty, argc, argv, ospf6,
|
|
idx_ipv4, uj);
|
|
|
|
if (!all_vrf)
|
|
break;
|
|
}
|
|
}
|
|
|
|
OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
void ospf6_neighbor_init(void)
|
|
{
|
|
install_element(VIEW_NODE, &show_ipv6_ospf6_neighbor_cmd);
|
|
install_element(VIEW_NODE, &show_ipv6_ospf6_neighbor_one_cmd);
|
|
}
|
|
|
|
DEFUN (debug_ospf6_neighbor,
|
|
debug_ospf6_neighbor_cmd,
|
|
"debug ospf6 neighbor [<state|event>]",
|
|
DEBUG_STR
|
|
OSPF6_STR
|
|
"Debug OSPFv3 Neighbor\n"
|
|
"Debug OSPFv3 Neighbor State Change\n"
|
|
"Debug OSPFv3 Neighbor Event\n")
|
|
{
|
|
int idx_type = 3;
|
|
unsigned char level = 0;
|
|
|
|
if (argc == 4) {
|
|
if (!strncmp(argv[idx_type]->arg, "s", 1))
|
|
level = OSPF6_DEBUG_NEIGHBOR_STATE;
|
|
else if (!strncmp(argv[idx_type]->arg, "e", 1))
|
|
level = OSPF6_DEBUG_NEIGHBOR_EVENT;
|
|
} else
|
|
level = OSPF6_DEBUG_NEIGHBOR_STATE | OSPF6_DEBUG_NEIGHBOR_EVENT;
|
|
|
|
OSPF6_DEBUG_NEIGHBOR_ON(level);
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
|
|
DEFUN (no_debug_ospf6_neighbor,
|
|
no_debug_ospf6_neighbor_cmd,
|
|
"no debug ospf6 neighbor [<state|event>]",
|
|
NO_STR
|
|
DEBUG_STR
|
|
OSPF6_STR
|
|
"Debug OSPFv3 Neighbor\n"
|
|
"Debug OSPFv3 Neighbor State Change\n"
|
|
"Debug OSPFv3 Neighbor Event\n")
|
|
{
|
|
int idx_type = 4;
|
|
unsigned char level = 0;
|
|
|
|
if (argc == 5) {
|
|
if (!strncmp(argv[idx_type]->arg, "s", 1))
|
|
level = OSPF6_DEBUG_NEIGHBOR_STATE;
|
|
if (!strncmp(argv[idx_type]->arg, "e", 1))
|
|
level = OSPF6_DEBUG_NEIGHBOR_EVENT;
|
|
} else
|
|
level = OSPF6_DEBUG_NEIGHBOR_STATE | OSPF6_DEBUG_NEIGHBOR_EVENT;
|
|
|
|
OSPF6_DEBUG_NEIGHBOR_OFF(level);
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
|
|
DEFUN (no_debug_ospf6,
|
|
no_debug_ospf6_cmd,
|
|
"no debug ospf6",
|
|
NO_STR
|
|
DEBUG_STR
|
|
OSPF6_STR)
|
|
{
|
|
unsigned int i;
|
|
|
|
OSPF6_DEBUG_ABR_OFF();
|
|
OSPF6_DEBUG_ASBR_OFF();
|
|
OSPF6_DEBUG_BROUTER_OFF();
|
|
OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF();
|
|
OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF();
|
|
OSPF6_DEBUG_FLOODING_OFF();
|
|
OSPF6_DEBUG_INTERFACE_OFF();
|
|
|
|
ospf6_lsa_debug_set_all(false);
|
|
|
|
for (i = 0; i < 6; i++)
|
|
OSPF6_DEBUG_MESSAGE_OFF(i,
|
|
OSPF6_DEBUG_NEIGHBOR_STATE
|
|
| OSPF6_DEBUG_NEIGHBOR_EVENT);
|
|
|
|
OSPF6_DEBUG_NEIGHBOR_OFF(OSPF6_DEBUG_NEIGHBOR_STATE
|
|
| OSPF6_DEBUG_NEIGHBOR_EVENT);
|
|
OSPF6_DEBUG_ROUTE_OFF(OSPF6_DEBUG_ROUTE_TABLE);
|
|
OSPF6_DEBUG_ROUTE_OFF(OSPF6_DEBUG_ROUTE_INTRA);
|
|
OSPF6_DEBUG_ROUTE_OFF(OSPF6_DEBUG_ROUTE_INTER);
|
|
OSPF6_DEBUG_ROUTE_OFF(OSPF6_DEBUG_ROUTE_MEMORY);
|
|
OSPF6_DEBUG_SPF_OFF(OSPF6_DEBUG_SPF_PROCESS);
|
|
OSPF6_DEBUG_SPF_OFF(OSPF6_DEBUG_SPF_TIME);
|
|
OSPF6_DEBUG_SPF_OFF(OSPF6_DEBUG_SPF_DATABASE);
|
|
OSPF6_DEBUG_ZEBRA_OFF(OSPF6_DEBUG_ZEBRA_SEND | OSPF6_DEBUG_ZEBRA_RECV);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
int config_write_ospf6_debug_neighbor(struct vty *vty)
|
|
{
|
|
if (IS_OSPF6_DEBUG_NEIGHBOR(STATE) && IS_OSPF6_DEBUG_NEIGHBOR(EVENT))
|
|
vty_out(vty, "debug ospf6 neighbor\n");
|
|
else if (IS_OSPF6_DEBUG_NEIGHBOR(STATE))
|
|
vty_out(vty, "debug ospf6 neighbor state\n");
|
|
else if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT))
|
|
vty_out(vty, "debug ospf6 neighbor event\n");
|
|
return 0;
|
|
}
|
|
|
|
void install_element_ospf6_debug_neighbor(void)
|
|
{
|
|
install_element(ENABLE_NODE, &debug_ospf6_neighbor_cmd);
|
|
install_element(ENABLE_NODE, &no_debug_ospf6_neighbor_cmd);
|
|
install_element(ENABLE_NODE, &no_debug_ospf6_cmd);
|
|
install_element(CONFIG_NODE, &debug_ospf6_neighbor_cmd);
|
|
install_element(CONFIG_NODE, &no_debug_ospf6_neighbor_cmd);
|
|
install_element(CONFIG_NODE, &no_debug_ospf6_cmd);
|
|
}
|