Showing ISIS information
========================
- .. clicmd:: show isis summary
+ .. clicmd:: show isis [vrf <NAME|all>] summary [json]
Show summary information about ISIS.
Show information about ISIS node.
- .. clicmd:: show isis interface [detail] [IFNAME]
+ .. clicmd:: show isis [vrf <NAME|all>] interface [detail] [IFNAME] [json]
Show state and configuration of ISIS specified interface, or all interfaces
if no interface is given with or without details.
- .. clicmd:: show isis neighbor [detail] [SYSTEMID]
+ .. clicmd:: show isis [vrf <NAME|all>] neighbor [detail] [SYSTEMID] [json]
Show state and information of ISIS specified neighbor, or all neighbors if
no system id is given with or without details.
- .. clicmd:: show isis database [detail] [LSPID]
+ .. clicmd:: show isis [vrf <NAME|all>] database [detail] [LSPID] [json]
Show the ISIS database globally, for a specific LSP id without or with
details.
may not exceed 65535. Optionally sets also the Segment Routing Local Block.
The negative command always unsets both.
-.. clicmd:: segment-routing local-block (16-1048575) (16-1048575)
-
- Set the Segment Routing Local Block i.e. the label range used by MPLS
- to store label in the MPLS FIB for Adjacency SID. Note that the block size
- may not exceed 65535. This command is deprecated in favor of the combined
- 'segment-routing global-block A B local-block C D' command.
-
.. clicmd:: segment-routing node-msd (1-16)
Set the Maximum Stack Depth supported by the router. The value depend of the
}
}
-int isis_adj_expire(struct thread *thread)
+void isis_adj_expire(struct thread *thread)
{
struct isis_adjacency *adj;
/* trigger the adj expire event */
isis_adj_state_change(&adj, ISIS_ADJ_DOWN, "holding time expired");
-
- return 0;
}
+ /*
+ * show isis neighbor [detail] json
+ */
+ void isis_adj_print_json(struct isis_adjacency *adj, struct json_object *json,
+ char detail)
+ {
+ json_object *iface_json, *ipv4_addr_json, *ipv6_link_json,
+ *ipv6_non_link_json, *topo_json, *dis_flaps_json,
+ *area_addr_json, *adj_sid_json;
+ time_t now;
+ struct isis_dynhn *dyn;
+ int level;
+ char buf[256];
+
+ json_object_string_add(json, "adj", isis_adj_name(adj));
+
+ if (detail == ISIS_UI_LEVEL_BRIEF) {
+ if (adj->circuit)
+ json_object_string_add(json, "interface",
+ adj->circuit->interface->name);
+ else
+ json_object_string_add(json, "interface",
+ "NULL circuit!");
+ json_object_int_add(json, "level", adj->level);
+ json_object_string_add(json, "state",
+ adj_state2string(adj->adj_state));
+ now = time(NULL);
+ if (adj->last_upd) {
+ if (adj->last_upd + adj->hold_time < now)
+ json_object_string_add(json, "last-upd",
+ "expiring");
+ else
+ json_object_string_add(
+ json, "expires-in",
+ time2string(adj->last_upd +
+ adj->hold_time - now));
+ }
+ json_object_string_add(json, "snpa", snpa_print(adj->snpa));
+ }
+
+ if (detail == ISIS_UI_LEVEL_DETAIL) {
+ struct sr_adjacency *sra;
+ struct listnode *anode;
+
+ level = adj->level;
+ iface_json = json_object_new_object();
+ json_object_object_add(json, "interface", iface_json);
+ if (adj->circuit)
+ json_object_string_add(iface_json, "name",
+ adj->circuit->interface->name);
+ else
+ json_object_string_add(iface_json, "name",
+ "null-circuit");
+ json_object_int_add(json, "level", adj->level);
+ json_object_string_add(iface_json, "state",
+ adj_state2string(adj->adj_state));
+ now = time(NULL);
+ if (adj->last_upd) {
+ if (adj->last_upd + adj->hold_time < now)
+ json_object_string_add(iface_json, "last-upd",
+ "expiring");
+ else
+ json_object_string_add(
+ json, "expires-in",
+ time2string(adj->last_upd +
+ adj->hold_time - now));
+ } else
+ json_object_string_add(json, "expires-in",
+ time2string(adj->hold_time));
+ json_object_int_add(iface_json, "adj-flaps", adj->flaps);
+ json_object_string_add(iface_json, "last-ago",
+ time2string(now - adj->last_flap));
+ json_object_string_add(iface_json, "circuit-type",
+ circuit_t2string(adj->circuit_t));
+ json_object_string_add(iface_json, "speaks",
+ nlpid2string(&adj->nlpids));
+ if (adj->mt_count != 1 ||
+ adj->mt_set[0] != ISIS_MT_IPV4_UNICAST) {
+ topo_json = json_object_new_object();
+ json_object_object_add(iface_json, "topologies",
+ topo_json);
+ for (unsigned int i = 0; i < adj->mt_count; i++) {
+ snprintfrr(buf, sizeof(buf), "topo-%d", i);
+ json_object_string_add(
+ topo_json, buf,
+ isis_mtid2str(adj->mt_set[i]));
+ }
+ }
+ json_object_string_add(iface_json, "snpa",
+ snpa_print(adj->snpa));
+ if (adj->circuit &&
+ (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) {
+ dyn = dynhn_find_by_id(adj->circuit->isis, adj->lanid);
+ if (dyn) {
+ snprintfrr(buf, sizeof(buf), "%s-%02x",
+ dyn->hostname,
+ adj->lanid[ISIS_SYS_ID_LEN]);
+ json_object_string_add(iface_json, "lan-id",
+ buf);
+ } else {
+ snprintfrr(buf, sizeof(buf), "%s-%02x",
+ sysid_print(adj->lanid),
+ adj->lanid[ISIS_SYS_ID_LEN]);
+ json_object_string_add(iface_json, "lan-id",
+ buf);
+ }
+
+ json_object_int_add(iface_json, "lan-prio",
+ adj->prio[adj->level - 1]);
+
+ dis_flaps_json = json_object_new_object();
+ json_object_object_add(iface_json, "dis-flaps",
+ dis_flaps_json);
+ json_object_string_add(
+ dis_flaps_json, "dis-record",
+ isis_disflag2string(
+ adj->dis_record[ISIS_LEVELS + level - 1]
+ .dis));
+ json_object_int_add(dis_flaps_json, "last",
+ adj->dischanges[level - 1]);
+ json_object_string_add(
+ dis_flaps_json, "ago",
+ time2string(now - (adj->dis_record[ISIS_LEVELS +
+ level - 1]
+ .last_dis_change)));
+ }
+
+ if (adj->area_address_count) {
+ area_addr_json = json_object_new_object();
+ json_object_object_add(iface_json, "area-address",
+ area_addr_json);
+ for (unsigned int i = 0; i < adj->area_address_count;
+ i++) {
+ json_object_string_add(
+ area_addr_json, "isonet",
+ isonet_print(adj->area_addresses[i]
+ .area_addr,
+ adj->area_addresses[i]
+ .addr_len));
+ }
+ }
+ if (adj->ipv4_address_count) {
+ ipv4_addr_json = json_object_new_object();
+ json_object_object_add(iface_json, "ipv4-address",
+ ipv4_addr_json);
+ for (unsigned int i = 0; i < adj->ipv4_address_count;
+ i++){
+ inet_ntop(AF_INET, &adj->ipv4_addresses[i], buf,
+ sizeof(buf));
+ json_object_string_add(ipv4_addr_json, "ipv4", buf);
+ }
+ }
+ if (adj->ll_ipv6_count) {
+ ipv6_link_json = json_object_new_object();
+ json_object_object_add(iface_json, "ipv6-link-local",
+ ipv6_link_json);
+ for (unsigned int i = 0; i < adj->ll_ipv6_count; i++) {
+ char buf[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, &adj->ll_ipv6_addrs[i], buf,
+ sizeof(buf));
+ json_object_string_add(ipv6_link_json, "ipv6",
+ buf);
+ }
+ }
+ if (adj->global_ipv6_count) {
+ ipv6_non_link_json = json_object_new_object();
+ json_object_object_add(iface_json, "ipv6-global",
+ ipv6_non_link_json);
+ for (unsigned int i = 0; i < adj->global_ipv6_count;
+ i++) {
+ char buf[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, &adj->global_ipv6_addrs[i],
+ buf, sizeof(buf));
+ json_object_string_add(ipv6_non_link_json,
+ "ipv6", buf);
+ }
+ }
+
+ adj_sid_json = json_object_new_object();
+ json_object_object_add(iface_json, "adj-sid", adj_sid_json);
+ for (ALL_LIST_ELEMENTS_RO(adj->adj_sids, anode, sra)) {
+ const char *adj_type;
+ const char *backup;
+ uint32_t sid;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ adj_type = "LAN Adjacency-SID";
+ sid = sra->u.ladj_sid->sid;
+ break;
+ case CIRCUIT_T_P2P:
+ adj_type = "Adjacency-SID";
+ sid = sra->u.adj_sid->sid;
+ break;
+ default:
+ continue;
+ }
+ backup = (sra->type == ISIS_SR_LAN_BACKUP) ? " (backup)"
+ : "";
+
+ json_object_string_add(adj_sid_json, "nexthop",
+ (sra->nexthop.family == AF_INET)
+ ? "IPv4"
+ : "IPv6");
+ json_object_string_add(adj_sid_json, "adj-type",
+ adj_type);
+ json_object_string_add(adj_sid_json, "is-backup",
+ backup);
+ json_object_int_add(adj_sid_json, "sid", sid);
+ }
+ }
+ return;
+ }
+
/*
* show isis neighbor [detail]
*/
enum isis_adj_state state, const char *reason);
void isis_adj_print(struct isis_adjacency *adj);
const char *isis_adj_yang_state(enum isis_adj_state state);
-int isis_adj_expire(struct thread *thread);
+void isis_adj_expire(struct thread *thread);
void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
char detail);
+ void isis_adj_print_json(struct isis_adjacency *adj, struct json_object *json,
+ char detail);
void isis_adj_build_neigh_list(struct list *adjdb, struct list *list);
void isis_adj_build_up_list(struct list *adjdb, struct list *list);
int isis_adj_usage2levels(enum isis_adj_usage usage);
-int isis_bfd_startup_timer(struct thread *thread);
+void isis_bfd_startup_timer(struct thread *thread);
const char *isis_adj_name(const struct isis_adjacency *adj);
#endif /* ISIS_ADJACENCY_H */
DEFINE_MTYPE_STATIC(ISISD, ISIS_LSP, "ISIS LSP");
-static int lsp_refresh(struct thread *thread);
-static int lsp_l1_refresh_pseudo(struct thread *thread);
-static int lsp_l2_refresh_pseudo(struct thread *thread);
+static void lsp_refresh(struct thread *thread);
+static void lsp_l1_refresh_pseudo(struct thread *thread);
+static void lsp_l2_refresh_pseudo(struct thread *thread);
static void lsp_destroy(struct isis_lsp *lsp);
}
/* this function prints the lsp on show isis database */
- void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost,
- struct isis *isis)
+ void lsp_print_common(struct isis_lsp *lsp, struct vty *vty, struct json_object *json,
+ char dynhost, struct isis *isis)
+ {
+ if (json) {
+ return lsp_print_json(lsp, json, dynhost, isis);
+ } else {
+ return lsp_print_vty(lsp, vty, dynhost, isis);
+ }
+ }
+
+ void lsp_print_json(struct isis_lsp *lsp, struct json_object *json,
+ char dynhost, struct isis *isis)
+ {
+ char LSPid[255];
+ char age_out[8];
+ char b[200];
+ json_object *own_json;
+ char buf[256];
+
+ lspid_print(lsp->hdr.lsp_id, LSPid, sizeof(LSPid), dynhost, 1, isis);
+ own_json = json_object_new_object();
+ json_object_object_add(json, "lsp", own_json);
+ json_object_string_add(own_json, "id", LSPid);
+ json_object_string_add(own_json, "own", lsp->own_lsp ? "*" : " ");
+ json_object_int_add(json, "pdu-len", lsp->hdr.pdu_len);
+ snprintfrr(buf, sizeof(buf), "0x%08x", lsp->hdr.seqno);
+ json_object_string_add(json, "seq-number", buf);
+ snprintfrr(buf, sizeof(buf), "0x%04hx", lsp->hdr.checksum);
+ json_object_string_add(json, "chksum", buf);
+ if (lsp->hdr.rem_lifetime == 0) {
+ snprintf(age_out, sizeof(age_out), "(%d)", lsp->age_out);
+ age_out[7] = '\0';
+ json_object_string_add(json, "holdtime", age_out);
+ } else {
+ json_object_int_add(json, "holdtime", lsp->hdr.rem_lifetime);
+ }
+ json_object_string_add(
+ json, "att-p-ol", lsp_bits2string(lsp->hdr.lsp_bits, b, sizeof(b)));
+ }
+
+ void lsp_print_vty(struct isis_lsp *lsp, struct vty *vty,
+ char dynhost, struct isis *isis)
{
char LSPid[255];
char age_out[8];
vty_out(vty, "%s\n", lsp_bits2string(lsp->hdr.lsp_bits, b, sizeof(b)));
}
- void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost,
- struct isis *isis)
+ void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty,
+ struct json_object *json, char dynhost,
+ struct isis *isis)
{
- lsp_print(lsp, vty, dynhost, isis);
- if (lsp->tlvs)
- vty_multiline(vty, " ", "%s", isis_format_tlvs(lsp->tlvs));
- vty_out(vty, "\n");
+ if (json) {
+ lsp_print_json(lsp, json, dynhost, isis);
+ if (lsp->tlvs) {
+ isis_format_tlvs(lsp->tlvs, json);
+ }
+ } else {
+ lsp_print_vty(lsp, vty, dynhost, isis);
+ if (lsp->tlvs)
+ vty_multiline(vty, " ", "%s",
+ isis_format_tlvs(lsp->tlvs, NULL));
+ vty_out(vty, "\n");
+ }
}
/* print all the lsps info in the local lspdb */
- int lsp_print_all(struct vty *vty, struct lspdb_head *head, char detail,
- char dynhost, struct isis *isis)
+ int lsp_print_all(struct vty *vty, struct json_object *json,
+ struct lspdb_head *head, char detail, char dynhost,
+ struct isis *isis)
{
struct isis_lsp *lsp;
int lsp_count = 0;
if (detail == ISIS_UI_LEVEL_BRIEF) {
frr_each (lspdb, head, lsp) {
- lsp_print(lsp, vty, dynhost, isis);
+ lsp_print_common(lsp, vty, json, dynhost, isis);
lsp_count++;
}
} else if (detail == ISIS_UI_LEVEL_DETAIL) {
frr_each (lspdb, head, lsp) {
- lsp_print_detail(lsp, vty, dynhost, isis);
+ lsp_print_detail(lsp, vty, json, dynhost, isis);
lsp_count++;
}
}
if (!fragments) {
zlog_warn("BUG: could not fragment own LSP:");
log_multiline(LOG_WARNING, " ", "%s",
- isis_format_tlvs(tlvs));
+ isis_format_tlvs(tlvs, NULL));
isis_free_tlvs(tlvs);
return;
}
/*
* Something has changed or periodic refresh -> regenerate LSP
*/
-static int lsp_refresh(struct thread *thread)
+static void lsp_refresh(struct thread *thread)
{
struct lsp_refresh_arg *arg = THREAD_ARG(thread);
area->lsp_regenerate_pending[level - 1] = 0;
if ((area->is_type & level) == 0)
- return ISIS_ERROR;
+ return;
/*
* Throttle regeneration of LSPs (but not when BFD signalled a 'down'
area->area_tag, level);
_lsp_regenerate_schedule(area, level, 0, false,
__func__, __FILE__, __LINE__);
- return 0;
+ return;
}
sched_debug(
"ISIS (%s): LSP L%d refresh timer expired. Refreshing LSP...",
area->area_tag, level);
- return lsp_regenerate(area, level);
+ lsp_regenerate(area, level);
}
int _lsp_regenerate_schedule(struct isis_area *area, int level,
/*
* Something has changed or periodic refresh -> regenerate pseudo LSP
*/
-static int lsp_l1_refresh_pseudo(struct thread *thread)
+static void lsp_l1_refresh_pseudo(struct thread *thread)
{
struct isis_circuit *circuit;
uint8_t id[ISIS_SYS_ID_LEN + 2];
LSP_PSEUDO_ID(id) = circuit->circuit_id;
LSP_FRAGMENT(id) = 0;
lsp_purge_pseudo(id, circuit, IS_LEVEL_1);
- return ISIS_ERROR;
+ return;
}
- return lsp_regenerate_pseudo(circuit, IS_LEVEL_1);
+ lsp_regenerate_pseudo(circuit, IS_LEVEL_1);
}
-static int lsp_l2_refresh_pseudo(struct thread *thread)
+static void lsp_l2_refresh_pseudo(struct thread *thread)
{
struct isis_circuit *circuit;
uint8_t id[ISIS_SYS_ID_LEN + 2];
LSP_PSEUDO_ID(id) = circuit->circuit_id;
LSP_FRAGMENT(id) = 0;
lsp_purge_pseudo(id, circuit, IS_LEVEL_2);
- return ISIS_ERROR;
+ return;
}
- return lsp_regenerate_pseudo(circuit, IS_LEVEL_2);
+ lsp_regenerate_pseudo(circuit, IS_LEVEL_2);
}
int lsp_regenerate_schedule_pseudo(struct isis_circuit *circuit, int level)
* Walk through LSPs for an area
* - set remaining lifetime
*/
-int lsp_tick(struct thread *thread)
+void lsp_tick(struct thread *thread)
{
struct isis_area *area;
struct isis_lsp *lsp;
&& !isis_tx_queue_len(fabricd_init_c->tx_queue)) {
fabricd_initial_sync_finish(area);
}
-
- return ISIS_OK;
}
void lsp_purge_pseudo(uint8_t *id, struct isis_circuit *circuit, int level)
void lsp_db_init(struct lspdb_head *head);
void lsp_db_fini(struct lspdb_head *head);
-int lsp_tick(struct thread *thread);
+void lsp_tick(struct thread *thread);
int lsp_generate(struct isis_area *area, int level);
#define lsp_regenerate_schedule(area, level, all_pseudo) \
void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno);
void lspid_print(uint8_t *lsp_id, char *dest, size_t dest_len, char dynhost,
char frag, struct isis *isis);
- void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost,
- struct isis *isis);
- void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost,
+ void lsp_print_common(struct isis_lsp *lsp, struct vty *vty,
+ struct json_object *json, char dynhost,
struct isis *isis);
- int lsp_print_all(struct vty *vty, struct lspdb_head *head, char detail,
- char dynhost, struct isis *isis);
+ void lsp_print_vty(struct isis_lsp *lsp, struct vty *vty, char dynhost,
+ struct isis *isis);
+ void lsp_print_json(struct isis_lsp *lsp, struct json_object *json,
+ char dynhost, struct isis *isis);
+ void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty,
+ struct json_object *json, char dynhost,
+ struct isis *isis);
+ int lsp_print_all(struct vty *vty, struct json_object *json,
+ struct lspdb_head *head, char detail, char dynhost,
+ struct isis *isis);
/* sets SRMflags for all active circuits of an lsp */
void lsp_set_all_srmflags(struct isis_lsp *lsp, bool set);
return retval;
}
-int isis_receive(struct thread *thread)
+void isis_receive(struct thread *thread)
{
struct isis_circuit *circuit;
uint8_t ssnpa[ETH_ALEN];
- int retval;
/*
* Get the circuit
isis_circuit_stream(circuit, &circuit->rcv_stream);
+#if ISIS_METHOD != ISIS_METHOD_BPF
+ int retval;
+
retval = circuit->rx(circuit, ssnpa);
-#if ISIS_METHOD != ISIS_METHOD_BPF
if (retval == ISIS_OK)
- retval = isis_handle_pdu(circuit, ssnpa);
-#endif //ISIS_METHOD != ISIS_METHOD_BPF
+ isis_handle_pdu(circuit, ssnpa);
+#else // ISIS_METHOD != ISIS_METHOD_BPF
+ circuit->rx(circuit, ssnpa);
+#endif
/*
* prepare for next packet.
*/
if (!circuit->is_passive)
isis_circuit_prepare(circuit);
-
- return retval;
}
/*
return retval;
}
-static int send_hello_cb(struct thread *thread)
+static void send_hello_cb(struct thread *thread)
{
struct isis_circuit_arg *arg = THREAD_ARG(thread);
assert(arg);
send_hello(circuit, 1);
send_hello_sched(circuit, ISIS_LEVEL1,
1000 * circuit->hello_interval[1]);
- return ISIS_OK;
+ return;
}
if (circuit->circ_type != CIRCUIT_T_BROADCAST) {
zlog_warn("ISIS-Hello (%s): Trying to send hello on unknown circuit type %d",
circuit->area->area_tag, circuit->circ_type);
- return ISIS_WARNING;
+ return;
}
circuit->u.bc.t_send_lan_hello[level - 1] = NULL;
if (!(circuit->is_type & level)) {
zlog_warn("ISIS-Hello (%s): Trying to send L%d IIH in L%d-only circuit",
circuit->area->area_tag, level, 3 - level);
- return ISIS_WARNING;
+ return;
}
if (circuit->u.bc.run_dr_elect[level - 1])
isis_dr_elect(circuit, level);
- int rv = send_hello(circuit, level);
+ send_hello(circuit, level);
/* set next timer thread */
send_hello_sched(circuit, level, 1000 * circuit->hello_interval[level - 1]);
- return rv;
}
static void _send_hello_sched(struct isis_circuit *circuit,
circuit->interface->name,
stream_get_endp(circuit->snd_stream));
log_multiline(LOG_DEBUG, " ", "%s",
- isis_format_tlvs(tlvs));
+ isis_format_tlvs(tlvs, NULL));
if (IS_DEBUG_PACKET_DUMP)
zlog_dump_data(
STREAM_DATA(circuit->snd_stream),
return ISIS_OK;
}
-int send_l1_csnp(struct thread *thread)
+void send_l1_csnp(struct thread *thread)
{
struct isis_circuit *circuit;
thread_add_timer(master, send_l1_csnp, circuit,
isis_jitter(circuit->csnp_interval[0], CSNP_JITTER),
&circuit->t_send_csnp[0]);
-
- return ISIS_OK;
}
-int send_l2_csnp(struct thread *thread)
+void send_l2_csnp(struct thread *thread)
{
struct isis_circuit *circuit;
thread_add_timer(master, send_l2_csnp, circuit,
isis_jitter(circuit->csnp_interval[1], CSNP_JITTER),
&circuit->t_send_csnp[1]);
-
- return ISIS_OK;
}
/*
circuit->interface->name,
stream_get_endp(circuit->snd_stream));
log_multiline(LOG_DEBUG, " ", "%s",
- isis_format_tlvs(tlvs));
+ isis_format_tlvs(tlvs, NULL));
if (IS_DEBUG_PACKET_DUMP)
zlog_dump_data(
STREAM_DATA(circuit->snd_stream),
return ISIS_OK;
}
-int send_l1_psnp(struct thread *thread)
+void send_l1_psnp(struct thread *thread)
{
struct isis_circuit *circuit;
thread_add_timer(master, send_l1_psnp, circuit,
isis_jitter(circuit->psnp_interval[0], PSNP_JITTER),
&circuit->t_send_psnp[0]);
-
- return ISIS_OK;
}
/*
* 7.3.15.4 action on expiration of partial SNP interval
* level 2
*/
-int send_l2_psnp(struct thread *thread)
+void send_l2_psnp(struct thread *thread)
{
struct isis_circuit *circuit;
thread_add_timer(master, send_l2_psnp, circuit,
isis_jitter(circuit->psnp_interval[1], PSNP_JITTER),
&circuit->t_send_psnp[1]);
-
- return ISIS_OK;
}
/*
tree->route_table_backup->cleanup = isis_route_node_cleanup;
}
-static int isis_run_spf_cb(struct thread *thread)
+static void isis_run_spf_cb(struct thread *thread)
{
struct isis_spf_run *run = THREAD_ARG(thread);
struct isis_area *area = run->area;
if (IS_DEBUG_SPF_EVENTS)
zlog_warn("ISIS-SPF (%s) area does not share level",
area->area_tag);
- return ISIS_WARNING;
+ return;
}
isis_area_delete_backup_adj_sids(area, level);
UNSET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
fabricd_run_spf(area);
-
- return 0;
}
static struct isis_spf_run *isis_run_spf_arg(struct isis_area *area, int level)
vty_out(vty, " run count : %u\n", spftree->runcount);
}
+ void isis_spf_print_json(struct isis_spftree *spftree, struct json_object *json)
+ {
+ char uptime[MONOTIME_STRLEN];
+ time_t cur;
+ cur = time(NULL);
+ cur -= spftree->last_run_timestamp;
+ frrtime_to_interval(cur, uptime, sizeof(uptime));
+ json_object_string_add(json, "last-run-elapsed", uptime);
+ json_object_int_add(json, "last-run-duration-usec",
+ spftree->last_run_duration);
+ json_object_int_add(json, "last-run-count", spftree->runcount);
+ }