From: Kaushik Date: Mon, 13 Jul 2020 12:37:59 +0000 (-0700) Subject: isisd : Transformational changes to support different VRFs. X-Git-Tag: frr-7.5.1~143^2 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=eab88f3655ba7549211f6bcc6fbc8edc3d51ede1;p=mirror_frr.git isisd : Transformational changes to support different VRFs. 1. Created a structure "isis master". 2. All the changes are related to handle ISIS with different vrf. 3. A new variable added in structure "isis" to store the vrf name. 4. The display commands for isis is changed to support different VRFs. Signed-off-by: Kaushik --- diff --git a/isisd/fabricd.c b/isisd/fabricd.c index e9dfd4601..ebaf14461 100644 --- a/isisd/fabricd.c +++ b/isisd/fabricd.c @@ -475,7 +475,7 @@ void fabricd_run_spf(struct isis_area *area) if (!f) return; - isis_run_hopcount_spf(area, isis->sysid, f->spftree); + isis_run_hopcount_spf(area, area->isis->sysid, f->spftree); neighbors_neighbors_update(f); fabricd_bump_tier_calculation_timer(f); } diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index ab133cbfd..af5258846 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -50,8 +50,6 @@ #include "isisd/fabricd.h" #include "isisd/isis_nb.h" -extern struct isis *isis; - static struct isis_adjacency *adj_alloc(const uint8_t *id) { struct isis_adjacency *adj; diff --git a/isisd/isis_bfd.c b/isisd/isis_bfd.c index 5729994ba..f81dd6cf5 100644 --- a/isisd/isis_bfd.c +++ b/isisd/isis_bfd.c @@ -195,6 +195,14 @@ static int isis_bfd_nbr_replay(ZAPI_CALLBACK_ARGS) struct listnode *anode; struct isis_area *area; + struct isis *isis = NULL; + + isis = isis_lookup_by_vrfid(vrf_id); + + if (isis == NULL) { + zlog_warn(" %s : ISIS routing instance not found", __func__); + return -1; + } if (IS_DEBUG_BFD) zlog_debug("ISIS-BFD: Got neighbor replay request, resending neighbors."); diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 253ba2266..985e07820 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -224,10 +224,17 @@ struct isis_circuit *circuit_scan_by_ifp(struct interface *ifp) struct isis_area *area; struct listnode *node; struct isis_circuit *circuit; + struct isis *isis = NULL; if (ifp->info) return (struct isis_circuit *)ifp->info; + isis = isis_lookup_by_vrfid(ifp->vrf_id); + if (isis == NULL) { + zlog_warn(" %s : ISIS routing instance not found", __func__); + return NULL; + } + if (isis->area_list) { for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { circuit = @@ -618,7 +625,8 @@ int isis_circuit_up(struct isis_circuit *circuit) } if (circuit->circ_type == CIRCUIT_T_BROADCAST) { - circuit->circuit_id = isis_circuit_id_gen(isis, circuit->interface); + circuit->circuit_id = isis_circuit_id_gen(circuit->area->isis, + circuit->interface); if (!circuit->circuit_id) { flog_err( EC_ISIS_CONFIG, @@ -802,7 +810,8 @@ void isis_circuit_down(struct isis_circuit *circuit) circuit->lsp_regenerate_pending[0] = 0; circuit->lsp_regenerate_pending[1] = 0; - _ISIS_CLEAR_FLAG(isis->circuit_ids_used, circuit->circuit_id); + _ISIS_CLEAR_FLAG(circuit->area->isis->circuit_ids_used, + circuit->circuit_id); circuit->circuit_id = 0; } else if (circuit->circ_type == CIRCUIT_T_P2P) { isis_delete_adj(circuit->u.p2p.neighbor); @@ -1011,6 +1020,14 @@ static int isis_interface_config_write(struct vty *vty) struct isis_area *area; struct isis_circuit *circuit; int i; + struct isis *isis = NULL; + + isis = isis_lookup_by_vrfid(vrf->vrf_id); + + if (isis == NULL) { + vty_out(vty, "ISIS routing instance not found"); + return 0; + } FOR_ALL_INTERFACES (vrf, ifp) { /* IF name */ diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c index 4c2bcc774..4d0275800 100644 --- a/isisd/isis_cli.c +++ b/isisd/isis_cli.c @@ -62,7 +62,12 @@ DEFPY_YANG_NOSH(router_isis, router_isis_cmd, "router isis WORD$tag", * need to make sure to set it in the yang model so that it * is consistent with what FRR sees. */ - if (listcount(isis->area_list) == 0) + + if (!im) { + return CMD_SUCCESS; + } + + if (listcount(im->isis) == 0) nb_cli_enqueue_change(vty, "./is-type", NB_OP_MODIFY, "level-1-2"); ret = nb_cli_apply_changes(vty, base_xpath); @@ -90,7 +95,7 @@ DEFPY_YANG(no_router_isis, no_router_isis_cmd, "no router isis WORD$tag", } nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); - area = isis_area_lookup(tag); + area = isis_area_lookup(tag, VRF_DEFAULT); if (area && area->circuit_list && listcount(area->circuit_list)) { for (ALL_LIST_ELEMENTS(area->circuit_list, node, nnode, circuit)) { @@ -134,13 +139,20 @@ DEFPY_YANG(ip_router_isis, ip_router_isis_cmd, "ip router isis WORD$tag", { char temp_xpath[XPATH_MAXLEN]; const char *circ_type; - struct isis_area *area; + struct isis_area *area = NULL; struct interface *ifp; /* area will be created if it is not present. make sure the yang model * is synced with FRR and call the appropriate NB cb. */ - area = isis_area_lookup(tag); + + if (!im) { + return CMD_SUCCESS; + } + ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); + if (ifp) + area = isis_area_lookup(tag, ifp->vrf_id); + if (!area) { snprintf(temp_xpath, XPATH_MAXLEN, "/frr-isisd:isis/instance[area-tag='%s']", tag); @@ -148,9 +160,9 @@ DEFPY_YANG(ip_router_isis, ip_router_isis_cmd, "ip router isis WORD$tag", snprintf(temp_xpath, XPATH_MAXLEN, "/frr-isisd:isis/instance[area-tag='%s']/is-type", tag); - nb_cli_enqueue_change( - vty, temp_xpath, NB_OP_MODIFY, - listcount(isis->area_list) == 0 ? "level-1-2" : NULL); + nb_cli_enqueue_change(vty, temp_xpath, NB_OP_MODIFY, + listcount(im->isis) == 0 ? "level-1-2" + : NULL); nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE, NULL); nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag", @@ -159,8 +171,7 @@ DEFPY_YANG(ip_router_isis, ip_router_isis_cmd, "ip router isis WORD$tag", NB_OP_MODIFY, "true"); nb_cli_enqueue_change( vty, "./frr-isisd:isis/circuit-type", NB_OP_MODIFY, - listcount(isis->area_list) == 0 ? "level-1-2" - : "level-1"); + listcount(im->isis) == 0 ? "level-1-2" : "level-1"); } else { /* area exists, circuit type defaults to its area's is_type */ switch (area->is_type) { @@ -188,7 +199,6 @@ DEFPY_YANG(ip_router_isis, ip_router_isis_cmd, "ip router isis WORD$tag", } /* check if the interface is a loopback and if so set it as passive */ - ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); if (ifp && if_is_loopback(ifp)) nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive", NB_OP_MODIFY, "true"); @@ -204,13 +214,20 @@ DEFPY_YANG(ip6_router_isis, ip6_router_isis_cmd, "ipv6 router isis WORD$tag", { char temp_xpath[XPATH_MAXLEN]; const char *circ_type; - struct isis_area *area; + struct isis_area *area = NULL; struct interface *ifp; /* area will be created if it is not present. make sure the yang model * is synced with FRR and call the appropriate NB cb. */ - area = isis_area_lookup(tag); + + if (!im) + return CMD_SUCCESS; + + ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); + if (ifp) + area = isis_area_lookup(tag, ifp->vrf_id); + if (!area) { snprintf(temp_xpath, XPATH_MAXLEN, "/frr-isisd:isis/instance[area-tag='%s']", tag); @@ -218,9 +235,9 @@ DEFPY_YANG(ip6_router_isis, ip6_router_isis_cmd, "ipv6 router isis WORD$tag", snprintf(temp_xpath, XPATH_MAXLEN, "/frr-isisd:isis/instance[area-tag='%s']/is-type", tag); - nb_cli_enqueue_change( - vty, temp_xpath, NB_OP_MODIFY, - listcount(isis->area_list) == 0 ? "level-1-2" : NULL); + nb_cli_enqueue_change(vty, temp_xpath, NB_OP_MODIFY, + listcount(im->isis) == 0 ? "level-1-2" + : NULL); nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE, NULL); nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag", @@ -229,8 +246,7 @@ DEFPY_YANG(ip6_router_isis, ip6_router_isis_cmd, "ipv6 router isis WORD$tag", NB_OP_MODIFY, "true"); nb_cli_enqueue_change( vty, "./frr-isisd:isis/circuit-type", NB_OP_MODIFY, - listcount(isis->area_list) == 0 ? "level-1-2" - : "level-1"); + listcount(im->isis) == 0 ? "level-1-2" : "level-1"); } else { /* area exists, circuit type defaults to its area's is_type */ switch (area->is_type) { @@ -258,7 +274,6 @@ DEFPY_YANG(ip6_router_isis, ip6_router_isis_cmd, "ipv6 router isis WORD$tag", } /* check if the interface is a loopback and if so set it as passive */ - ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); if (ifp && if_is_loopback(ifp)) nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive", NB_OP_MODIFY, "true"); diff --git a/isisd/isis_csm.c b/isisd/isis_csm.c index 7aae326a4..929b4c26e 100644 --- a/isisd/isis_csm.c +++ b/isisd/isis_csm.c @@ -48,8 +48,6 @@ #include "isisd/isis_events.h" #include "isisd/isis_errors.h" -extern struct isis *isis; - static const char *const csm_statestr[] = {"C_STATE_NA", "C_STATE_INIT", "C_STATE_CONF", "C_STATE_UP"}; @@ -66,6 +64,7 @@ struct isis_circuit * isis_csm_state_change(int event, struct isis_circuit *circuit, void *arg) { int old_state; + struct isis *isis = NULL; old_state = circuit ? circuit->state : C_STATE_NA; if (IS_DEBUG_EVENTS) @@ -86,6 +85,13 @@ isis_csm_state_change(int event, struct isis_circuit *circuit, void *arg) case IF_UP_FROM_Z: circuit = isis_circuit_new(); isis_circuit_if_add(circuit, (struct interface *)arg); + isis = isis_lookup_by_vrfid(circuit->interface->vrf_id); + if (isis == NULL) { + zlog_warn( + " %s : ISIS routing instance not found", + __func__); + break; + } listnode_add(isis->init_circ_list, circuit); circuit->state = C_STATE_INIT; break; @@ -111,7 +117,8 @@ isis_csm_state_change(int event, struct isis_circuit *circuit, void *arg) circuit->state = C_STATE_UP; isis_event_circuit_state_change(circuit, circuit->area, 1); - listnode_delete(isis->init_circ_list, circuit); + listnode_delete(circuit->area->isis->init_circ_list, + circuit); break; case IF_UP_FROM_Z: assert(circuit); @@ -122,6 +129,14 @@ isis_csm_state_change(int event, struct isis_circuit *circuit, void *arg) break; case IF_DOWN_FROM_Z: isis_circuit_if_del(circuit, (struct interface *)arg); + isis = isis_lookup_by_vrfid(circuit->interface->vrf_id); + if (isis == NULL) { + zlog_warn( + "%s : ISIS routing instance not found", + __func__); + break; + } + listnode_delete(isis->init_circ_list, circuit); isis_circuit_del(circuit); circuit = NULL; @@ -174,6 +189,15 @@ isis_csm_state_change(int event, struct isis_circuit *circuit, void *arg) circuit->state = C_STATE_INIT; isis_event_circuit_state_change( circuit, (struct isis_area *)arg, 0); + + isis = isis_lookup_by_vrfid(circuit->interface->vrf_id); + if (isis == NULL) { + zlog_warn( + "%s : ISIS routing instance not found", + __func__); + break; + } + listnode_add(isis->init_circ_list, circuit); break; case IF_DOWN_FROM_Z: diff --git a/isisd/isis_dr.c b/isisd/isis_dr.c index 8df130486..318fb9fab 100644 --- a/isisd/isis_dr.c +++ b/isisd/isis_dr.c @@ -225,7 +225,7 @@ int isis_dr_resign(struct isis_circuit *circuit, int level) THREAD_TIMER_OFF(circuit->u.bc.t_refresh_pseudo_lsp[level - 1]); circuit->lsp_regenerate_pending[level - 1] = 0; - memcpy(id, isis->sysid, ISIS_SYS_ID_LEN); + memcpy(id, circuit->area->isis->sysid, ISIS_SYS_ID_LEN); LSP_PSEUDO_ID(id) = circuit->circuit_id; LSP_FRAGMENT(id) = 0; lsp_purge_pseudo(id, circuit, level); @@ -278,7 +278,8 @@ int isis_dr_commence(struct isis_circuit *circuit, int level) /* there was a dr elected, purge its LSPs from the db */ lsp_purge_pseudo(old_dr, circuit, level); } - memcpy(circuit->u.bc.l1_desig_is, isis->sysid, ISIS_SYS_ID_LEN); + memcpy(circuit->u.bc.l1_desig_is, circuit->area->isis->sysid, + ISIS_SYS_ID_LEN); *(circuit->u.bc.l1_desig_is + ISIS_SYS_ID_LEN) = circuit->circuit_id; @@ -299,7 +300,8 @@ int isis_dr_commence(struct isis_circuit *circuit, int level) /* there was a dr elected, purge its LSPs from the db */ lsp_purge_pseudo(old_dr, circuit, level); } - memcpy(circuit->u.bc.l2_desig_is, isis->sysid, ISIS_SYS_ID_LEN); + memcpy(circuit->u.bc.l2_desig_is, circuit->area->isis->sysid, + ISIS_SYS_ID_LEN); *(circuit->u.bc.l2_desig_is + ISIS_SYS_ID_LEN) = circuit->circuit_id; diff --git a/isisd/isis_dynhn.c b/isisd/isis_dynhn.c index 921e23d33..e34c59be1 100644 --- a/isisd/isis_dynhn.c +++ b/isisd/isis_dynhn.c @@ -45,11 +45,11 @@ extern struct host host; struct list *dyn_cache = NULL; static int dyn_cache_cleanup(struct thread *); -void dyn_cache_init(void) +void dyn_cache_init(struct isis *isis) { if (dyn_cache == NULL) dyn_cache = list_new(); - thread_add_timer(master, dyn_cache_cleanup, NULL, 120, + thread_add_timer(master, dyn_cache_cleanup, isis, 120, &isis->t_dync_clean); return; } @@ -59,19 +59,22 @@ static int dyn_cache_cleanup(struct thread *thread) struct listnode *node, *nnode; struct isis_dynhn *dyn; time_t now = time(NULL); + struct isis *isis = NULL; + + isis = THREAD_ARG(thread); isis->t_dync_clean = NULL; for (ALL_LIST_ELEMENTS(dyn_cache, node, nnode, dyn)) { if ((now - dyn->refresh) < MAX_LSP_LIFETIME) continue; - list_delete_node(dyn_cache, node); XFREE(MTYPE_ISIS_DYNHN, dyn); } - thread_add_timer(master, dyn_cache_cleanup, NULL, 120, - &isis->t_dync_clean); + thread_add_timer(master, dyn_cache_cleanup, isis, 120, + &isis->t_dync_clean); + return ISIS_OK; } @@ -132,11 +135,14 @@ void isis_dynhn_remove(const uint8_t *id) * 2 0000.0000.0002 bar-gw * * 0000.0000.0004 this-gw */ -void dynhn_print_all(struct vty *vty) +void dynhn_print_all(struct vty *vty, struct isis *isis) { struct listnode *node; struct isis_dynhn *dyn; + vty_out(vty, "vrf : %s\n", isis->name); + if (!isis->sysid_set) + return; vty_out(vty, "Level System ID Dynamic Hostname\n"); for (ALL_LIST_ELEMENTS_RO(dyn_cache, node, dyn)) { vty_out(vty, "%-7d", dyn->level); diff --git a/isisd/isis_dynhn.h b/isisd/isis_dynhn.h index 27133bd3f..2cfc43fc1 100644 --- a/isisd/isis_dynhn.h +++ b/isisd/isis_dynhn.h @@ -30,11 +30,11 @@ struct isis_dynhn { int level; }; -void dyn_cache_init(void); +void dyn_cache_init(struct isis *isis); void isis_dynhn_insert(const uint8_t *id, const char *hostname, int level); void isis_dynhn_remove(const uint8_t *id); struct isis_dynhn *dynhn_find_by_id(const uint8_t *id); struct isis_dynhn *dynhn_find_by_name(const char *hostname); -void dynhn_print_all(struct vty *vty); +void dynhn_print_all(struct vty *vty, struct isis *isis); #endif /* _ZEBRA_ISIS_DYNHN_H */ diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 646f106bb..90c7c0efb 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -338,13 +338,17 @@ void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno) static void lsp_purge_add_poi(struct isis_lsp *lsp, const uint8_t *sender) { + if (lsp->area == NULL) + return; + if (!lsp->area->purge_originator) return; /* add purge originator identification */ if (!lsp->tlvs) lsp->tlvs = isis_alloc_tlvs(); - isis_tlvs_set_purge_originator(lsp->tlvs, isis->sysid, sender); + isis_tlvs_set_purge_originator(lsp->tlvs, lsp->area->isis->sysid, + sender); isis_tlvs_set_dynamic_hostname(lsp->tlvs, cmd_hostname_get()); } @@ -591,7 +595,8 @@ static void lsp_set_time(struct isis_lsp *lsp) stream_putw_at(lsp->pdu, 10, lsp->hdr.rem_lifetime); } -void lspid_print(uint8_t *lsp_id, char *dest, char dynhost, char frag) +void lspid_print(uint8_t *lsp_id, char *dest, char dynhost, char frag, + struct isis *isis) { struct isis_dynhn *dyn = NULL; char id[SYSID_STRLEN]; @@ -607,6 +612,7 @@ void lspid_print(uint8_t *lsp_id, char *dest, char dynhost, char frag) snprintf(id, sizeof(id), "%.14s", cmd_hostname_get()); else memcpy(id, sysid_print(lsp_id), 15); + if (frag) sprintf(dest, "%s.%02x-%02x", id, LSP_PSEUDO_ID(lsp_id), LSP_FRAGMENT(lsp_id)); @@ -638,13 +644,14 @@ static const char *lsp_bits2string(uint8_t lsp_bits, char *buf, size_t buf_size) } /* this function prints the lsp on show isis database */ -void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost) +void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost, + struct isis *isis) { char LSPid[255]; char age_out[8]; char b[200]; - lspid_print(lsp->hdr.lsp_id, LSPid, dynhost, 1); + lspid_print(lsp->hdr.lsp_id, LSPid, dynhost, 1, isis); vty_out(vty, "%-21s%c ", LSPid, lsp->own_lsp ? '*' : ' '); vty_out(vty, "%5hu ", lsp->hdr.pdu_len); vty_out(vty, "0x%08x ", lsp->hdr.seqno); @@ -658,9 +665,10 @@ void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost) 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) +void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost, + struct isis *isis) { - lsp_print(lsp, vty, dynhost); + lsp_print(lsp, vty, dynhost, isis); if (lsp->tlvs) vty_multiline(vty, " ", "%s", isis_format_tlvs(lsp->tlvs)); vty_out(vty, "\n"); @@ -668,19 +676,19 @@ void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost) /* print all the lsps info in the local lspdb */ int lsp_print_all(struct vty *vty, struct lspdb_head *head, char detail, - char dynhost) + 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); + lsp_print(lsp, vty, dynhost, isis); lsp_count++; } } else if (detail == ISIS_UI_LEVEL_DETAIL) { frr_each (lspdb, head, lsp) { - lsp_print_detail(lsp, vty, dynhost); + lsp_print_detail(lsp, vty, dynhost, isis); lsp_count++; } } @@ -913,10 +921,10 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) } /* Add Router Capability TLV. */ - if (isis->router_id != 0) { + if (area->isis->router_id != 0) { struct isis_router_cap cap = {}; - cap.router_id.s_addr = isis->router_id; + cap.router_id.s_addr = area->isis->router_id; /* Add SR Sub-TLVs if SR is enabled. */ if (area->srdb.enabled) { @@ -954,8 +962,8 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) * into LSP. TE router ID will be the same if MPLS-TE * is not activate or MPLS-TE router-id not specified */ - if (isis->router_id != 0) { - struct in_addr id = {.s_addr = isis->router_id}; + if (area->isis->router_id != 0) { + struct in_addr id = {.s_addr = area->isis->router_id}; inet_ntop(AF_INET, &id, buf, sizeof(buf)); lsp_debug("ISIS (%s): Adding router ID %s as IPv4 tlv.", area->area_tag, buf); @@ -1210,7 +1218,8 @@ int lsp_generate(struct isis_area *area, int level) return ISIS_ERROR; memset(&lspid, 0, ISIS_SYS_ID_LEN + 2); - memcpy(&lspid, isis->sysid, ISIS_SYS_ID_LEN); + + memcpy(&lspid, area->isis->sysid, ISIS_SYS_ID_LEN); /* only builds the lsp if the area shares the level */ oldlsp = lsp_search(&area->lspdb[level - 1], lspid); @@ -1281,9 +1290,8 @@ static int lsp_regenerate(struct isis_area *area, int level) return ISIS_ERROR; head = &area->lspdb[level - 1]; - memset(lspid, 0, ISIS_SYS_ID_LEN + 2); - memcpy(lspid, isis->sysid, ISIS_SYS_ID_LEN); + memcpy(lspid, area->isis->sysid, ISIS_SYS_ID_LEN); lsp = lsp_search(head, lspid); @@ -1404,7 +1412,7 @@ int _lsp_regenerate_schedule(struct isis_area *area, int level, all_pseudo ? "" : "not ", func, file, line); - memcpy(id, isis->sysid, ISIS_SYS_ID_LEN); + memcpy(id, area->isis->sysid, ISIS_SYS_ID_LEN); LSP_PSEUDO_ID(id) = LSP_FRAGMENT(id) = 0; now = time(NULL); @@ -1525,7 +1533,7 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit, */ uint8_t ne_id[ISIS_SYS_ID_LEN + 1]; - memcpy(ne_id, isis->sysid, ISIS_SYS_ID_LEN); + memcpy(ne_id, area->isis->sysid, ISIS_SYS_ID_LEN); LSP_PSEUDO_ID(ne_id) = 0; if (circuit->area->oldmetric) { @@ -1603,7 +1611,7 @@ int lsp_generate_pseudo(struct isis_circuit *circuit, int level) || (circuit->u.bc.is_dr[level - 1] == 0)) return ISIS_ERROR; - memcpy(lsp_id, isis->sysid, ISIS_SYS_ID_LEN); + memcpy(lsp_id, circuit->area->isis->sysid, ISIS_SYS_ID_LEN); LSP_FRAGMENT(lsp_id) = 0; LSP_PSEUDO_ID(lsp_id) = circuit->circuit_id; @@ -1663,7 +1671,7 @@ static int lsp_regenerate_pseudo(struct isis_circuit *circuit, int level) || (circuit->u.bc.is_dr[level - 1] == 0)) return ISIS_ERROR; - memcpy(lsp_id, isis->sysid, ISIS_SYS_ID_LEN); + memcpy(lsp_id, circuit->area->isis->sysid, ISIS_SYS_ID_LEN); LSP_PSEUDO_ID(lsp_id) = circuit->circuit_id; LSP_FRAGMENT(lsp_id) = 0; @@ -1720,7 +1728,7 @@ static int lsp_l1_refresh_pseudo(struct thread *thread) if ((circuit->u.bc.is_dr[0] == 0) || (circuit->is_type & IS_LEVEL_1) == 0) { - memcpy(id, isis->sysid, ISIS_SYS_ID_LEN); + memcpy(id, circuit->area->isis->sysid, ISIS_SYS_ID_LEN); LSP_PSEUDO_ID(id) = circuit->circuit_id; LSP_FRAGMENT(id) = 0; lsp_purge_pseudo(id, circuit, IS_LEVEL_1); @@ -1742,7 +1750,7 @@ static int lsp_l2_refresh_pseudo(struct thread *thread) if ((circuit->u.bc.is_dr[1] == 0) || (circuit->is_type & IS_LEVEL_2) == 0) { - memcpy(id, isis->sysid, ISIS_SYS_ID_LEN); + memcpy(id, circuit->area->isis->sysid, ISIS_SYS_ID_LEN); LSP_PSEUDO_ID(id) = circuit->circuit_id; LSP_FRAGMENT(id) = 0; lsp_purge_pseudo(id, circuit, IS_LEVEL_2); @@ -1770,7 +1778,7 @@ int lsp_regenerate_schedule_pseudo(struct isis_circuit *circuit, int level) area->area_tag, circuit_t2string(level), circuit->interface->name); - memcpy(lsp_id, isis->sysid, ISIS_SYS_ID_LEN); + memcpy(lsp_id, area->isis->sysid, ISIS_SYS_ID_LEN); LSP_PSEUDO_ID(lsp_id) = circuit->circuit_id; LSP_FRAGMENT(lsp_id) = 0; now = time(NULL); diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h index 4cbca5d51..6cbea4749 100644 --- a/isisd/isis_lsp.h +++ b/isisd/isis_lsp.h @@ -29,6 +29,7 @@ PREDECL_RBTREE_UNIQ(lspdb) +struct isis; /* Structure for isis_lsp, this structure will only support the fixed * System ID (Currently 6) (atleast for now). In order to support more * We will have to split the header into two parts, and for readability @@ -115,11 +116,14 @@ void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr, struct isis_tlvs *tlvs, struct stream *stream, struct isis_area *area, int level, bool confusion); void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno); -void lspid_print(uint8_t *lsp_id, char *dest, char dynhost, char frag); -void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost); -void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost); +void lspid_print(uint8_t *lsp_id, char *dest, 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, + struct isis *isis); int lsp_print_all(struct vty *vty, struct lspdb_head *head, char detail, - char dynhost); + 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); diff --git a/isisd/isis_main.c b/isisd/isis_main.c index 2317b166c..ed4b20685 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -101,6 +101,7 @@ void sigusr1(void); static __attribute__((__noreturn__)) void terminate(int i) { + isis_terminate(); isis_sr_term(); isis_zebra_stop(); exit(i); @@ -233,7 +234,8 @@ int main(int argc, char **argv, char **envp) } /* thread master */ - master = frr_init(); + isis_master_init(frr_init()); + master = im->master; /* * initializations @@ -259,7 +261,7 @@ int main(int argc, char **argv, char **envp) mt_init(); /* create the global 'isis' instance */ - isis_new(1, VRF_DEFAULT); + isis_global_instance_create(); isis_zebra_init(master, instance); isis_bfd_init(); diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c index 86725173c..3aedd8ba1 100644 --- a/isisd/isis_misc.c +++ b/isisd/isis_misc.c @@ -437,15 +437,18 @@ struct in_addr newprefix2inaddr(uint8_t *prefix_start, uint8_t prefix_masklen) * Returns the dynamic hostname associated with the passed system ID. * If no dynamic hostname found then returns formatted system ID. */ -const char *print_sys_hostname(const uint8_t *sysid) +const char *print_sys_hostname(uint8_t *sysid) { struct isis_dynhn *dyn; + struct isis *isis = NULL; if (!sysid) return "nullsysid"; /* For our system ID return our host name */ - if (memcmp(sysid, isis->sysid, ISIS_SYS_ID_LEN) == 0) + isis = isis_lookup_by_sysid(sysid); + + if (isis != NULL) return cmd_hostname_get(); dyn = dynhn_find_by_id(sysid); diff --git a/isisd/isis_misc.h b/isisd/isis_misc.h index 5cdbbfb05..c6a5832f3 100644 --- a/isisd/isis_misc.h +++ b/isisd/isis_misc.h @@ -49,7 +49,7 @@ const char *time2string(uint32_t); const char *nlpid2str(uint8_t nlpid); /* typedef struct nlpids nlpids; */ char *nlpid2string(struct nlpids *); -const char *print_sys_hostname(const uint8_t *sysid); +const char *print_sys_hostname(uint8_t *sysid); void zlog_dump_data(void *data, int len); /* diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c index cfe96e6ed..ffc3d5b2e 100644 --- a/isisd/isis_nb_config.c +++ b/isisd/isis_nb_config.c @@ -58,11 +58,11 @@ int isis_instance_create(struct nb_cb_create_args *args) return NB_OK; area_tag = yang_dnode_get_string(args->dnode, "./area-tag"); - area = isis_area_lookup(area_tag); + area = isis_area_lookup(area_tag, VRF_DEFAULT); if (area) return NB_ERR_INCONSISTENCY; - area = isis_area_create(area_tag); + area = isis_area_create(area_tag, VRF_DEFAULT_NAME); /* save area in dnode to avoid looking it up all the time */ nb_running_set_entry(args->dnode, area); @@ -113,6 +113,10 @@ int isis_instance_area_address_create(struct nb_cb_create_args *args) switch (args->event) { case NB_EV_VALIDATE: + area = nb_running_get_entry(args->dnode, NULL, true); + if (area == NULL) + return NB_ERR_VALIDATION; + addr.addr_len = dotformat2buff(buff, net_title); memcpy(addr.area_addr, buff, addr.addr_len); if (addr.area_addr[addr.addr_len - 1] != 0) { @@ -121,9 +125,9 @@ int isis_instance_area_address_create(struct nb_cb_create_args *args) "nsel byte (last byte) in area address must be 0"); return NB_ERR_VALIDATION; } - if (isis->sysid_set) { + if (area->isis->sysid_set) { /* Check that the SystemID portions match */ - if (memcmp(isis->sysid, GETSYSID((&addr)), + if (memcmp(area->isis->sysid, GETSYSID((&addr)), ISIS_SYS_ID_LEN)) { snprintf( args->errmsg, args->errmsg_len, @@ -145,12 +149,13 @@ int isis_instance_area_address_create(struct nb_cb_create_args *args) area = nb_running_get_entry(args->dnode, NULL, true); addrr = args->resource->ptr; - if (isis->sysid_set == 0) { + if (area->isis->sysid_set == 0) { /* * First area address - get the SystemID for this router */ - memcpy(isis->sysid, GETSYSID(addrr), ISIS_SYS_ID_LEN); - isis->sysid_set = 1; + memcpy(area->isis->sysid, GETSYSID(addrr), + ISIS_SYS_ID_LEN); + area->isis->sysid_set = 1; } else { /* check that we don't already have this address */ for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node, @@ -200,6 +205,7 @@ int isis_instance_area_address_destroy(struct nb_cb_destroy_args *args) addr.addr_len = dotformat2buff(buff, net_title); memcpy(addr.area_addr, buff, (int)addr.addr_len); area = nb_running_get_entry(args->dnode, NULL, true); + for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node, addrp)) { if ((addrp->addr_len + ISIS_SYS_ID_LEN + 1) == addr.addr_len && !memcmp(addrp->area_addr, addr.area_addr, addr.addr_len)) @@ -214,8 +220,8 @@ int isis_instance_area_address_destroy(struct nb_cb_destroy_args *args) * Last area address - reset the SystemID for this router */ if (listcount(area->area_addrs) == 0) { - memset(isis->sysid, 0, ISIS_SYS_ID_LEN); - isis->sysid_set = 0; + memset(area->isis->sysid, 0, ISIS_SYS_ID_LEN); + area->isis->sysid_set = 0; if (IS_DEBUG_EVENTS) zlog_debug("Router has no SystemID"); } @@ -1822,7 +1828,7 @@ int isis_instance_segment_routing_prefix_sid_map_prefix_sid_last_hop_behavior_mo */ int lib_interface_isis_create(struct nb_cb_create_args *args) { - struct isis_area *area; + struct isis_area *area = NULL; struct interface *ifp; struct isis_circuit *circuit; const char *area_tag = yang_dnode_get_string(args->dnode, "./area-tag"); @@ -1842,7 +1848,7 @@ int lib_interface_isis_create(struct nb_cb_create_args *args) break; actual_mtu = if_is_broadcast(ifp) ? ifp->mtu - LLC_LEN : ifp->mtu; - area = isis_area_lookup(area_tag); + area = isis_area_lookup(area_tag, ifp->vrf_id); if (area) min_mtu = area->lsp_mtu; else @@ -1860,7 +1866,9 @@ int lib_interface_isis_create(struct nb_cb_create_args *args) } break; case NB_EV_APPLY: - area = isis_area_lookup(area_tag); + ifp = nb_running_get_entry(args->dnode, NULL, true); + if (ifp) + area = isis_area_lookup(area_tag, ifp->vrf_id); /* The area should have already be created. We are * setting the priority of the global isis area creation * slightly lower, so it should be executed first, but I @@ -1874,7 +1882,6 @@ int lib_interface_isis_create(struct nb_cb_create_args *args) abort(); } - ifp = nb_running_get_entry(args->dnode, NULL, true); circuit = isis_circuit_create(area, ifp); assert(circuit && (circuit->state == C_STATE_CONF @@ -1915,6 +1922,7 @@ int lib_interface_isis_area_tag_modify(struct nb_cb_modify_args *args) struct interface *ifp; struct vrf *vrf; const char *area_tag, *ifname, *vrfname; + struct isis *isis = NULL; if (args->event == NB_EV_VALIDATE) { /* libyang doesn't like relative paths across module boundaries @@ -1926,8 +1934,14 @@ int lib_interface_isis_area_tag_modify(struct nb_cb_modify_args *args) vrf = vrf_lookup_by_name(vrfname); assert(vrf); ifp = if_lookup_by_name(ifname, vrf->vrf_id); + if (!ifp) return NB_OK; + + isis = isis_lookup_by_vrfid(ifp->vrf_id); + if (isis == NULL) + return NB_ERR_VALIDATION; + circuit = circuit_lookup_by_ifp(ifp, isis->init_circ_list); area_tag = yang_dnode_get_string(args->dnode, NULL); if (circuit && circuit->area && circuit->area->area_tag @@ -1952,6 +1966,7 @@ int lib_interface_isis_circuit_type_modify(struct nb_cb_modify_args *args) struct interface *ifp; struct vrf *vrf; const char *ifname, *vrfname; + struct isis *isis = NULL; switch (args->event) { case NB_EV_VALIDATE: @@ -1966,6 +1981,11 @@ int lib_interface_isis_circuit_type_modify(struct nb_cb_modify_args *args) ifp = if_lookup_by_name(ifname, vrf->vrf_id); if (!ifp) break; + + isis = isis_lookup_by_vrfid(ifp->vrf_id); + if (isis == NULL) + return NB_ERR_VALIDATION; + circuit = circuit_lookup_by_ifp(ifp, isis->init_circ_list); if (circuit && circuit->state == C_STATE_UP && circuit->area->is_type != IS_LEVEL_1_AND_2 diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index 72548e042..43b9f6685 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -74,8 +74,10 @@ static int ack_lsp(struct isis_lsp_hdr *hdr, struct isis_circuit *circuit, fill_fixed_hdr(pdu_type, circuit->snd_stream); lenp = stream_get_endp(circuit->snd_stream); + stream_putw(circuit->snd_stream, 0); /* PDU length */ - stream_put(circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); + stream_put(circuit->snd_stream, circuit->area->isis->sysid, + ISIS_SYS_ID_LEN); stream_putc(circuit->snd_stream, circuit->idx); stream_putc(circuit->snd_stream, 9); /* code */ stream_putc(circuit->snd_stream, 16); /* len */ @@ -128,6 +130,7 @@ struct iih_info { static int process_p2p_hello(struct iih_info *iih) { struct isis_threeway_adj *tw_adj = iih->tlvs->threeway_adj; + if (tw_adj) { if (tw_adj->state > ISIS_THREEWAY_DOWN) { if (IS_DEBUG_ADJ_PACKETS) { @@ -140,8 +143,10 @@ static int process_p2p_hello(struct iih_info *iih) } if (tw_adj->neighbor_set - && (memcmp(tw_adj->neighbor_id, isis->sysid, ISIS_SYS_ID_LEN) - || tw_adj->neighbor_circuit_id != (uint32_t) iih->circuit->idx)) { + && (memcmp(tw_adj->neighbor_id, + iih->circuit->area->isis->sysid, ISIS_SYS_ID_LEN) + || tw_adj->neighbor_circuit_id + != (uint32_t)iih->circuit->idx)) { if (IS_DEBUG_ADJ_PACKETS) { zlog_debug("ISIS-Adj (%s): Rcvd P2P IIH from (%s) which lists IS/Circuit different from us as neighbor.", @@ -561,7 +566,6 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, ? "P2P IIH" : (level == ISIS_LEVEL1) ? "L1 LAN IIH" : "L2 LAN IIH"; - stream_get_from(raw_pdu, circuit->rcv_stream, pdu_start, pdu_end - pdu_start); if (IS_DEBUG_ADJ_PACKETS) { @@ -724,7 +728,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, goto out; } - if (!memcmp(iih.sys_id, isis->sysid, ISIS_SYS_ID_LEN)) { + if (!memcmp(iih.sys_id, circuit->area->isis->sysid, ISIS_SYS_ID_LEN)) { zlog_warn( "ISIS-Adj (%s): Received IIH with own sysid - discard", circuit->area->area_tag); @@ -1040,7 +1044,8 @@ dontcheckadj: ack_lsp(&hdr, circuit, level); goto out; /* FIXME: do we need a purge? */ } else { - if (memcmp(hdr.lsp_id, isis->sysid, ISIS_SYS_ID_LEN)) { + if (memcmp(hdr.lsp_id, circuit->area->isis->sysid, + ISIS_SYS_ID_LEN)) { /* LSP by some other system -> do 7.3.16.4 b) */ /* 7.3.16.4 b) 1) */ if (comp == LSP_NEWER) { @@ -1134,7 +1139,8 @@ dontcheckadj: } /* 7.3.15.1 c) - If this is our own lsp and we don't have it initiate a * purge */ - if (memcmp(hdr.lsp_id, isis->sysid, ISIS_SYS_ID_LEN) == 0) { + if (memcmp(hdr.lsp_id, circuit->area->isis->sysid, ISIS_SYS_ID_LEN) + == 0) { if (!lsp) { /* 7.3.16.4: initiate a purge */ lsp_purge_non_exist(level, &hdr, circuit->area); @@ -1370,6 +1376,7 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, struct isis_passwd *passwd = (level == IS_LEVEL_1) ? &circuit->area->area_passwd : &circuit->area->domain_passwd; + if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_RECV)) { int auth_code = isis_tlvs_auth_is_valid( tlvs, passwd, circuit->rcv_stream, false); @@ -1420,7 +1427,8 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, entry = entry->next) { struct isis_lsp *lsp = lsp_search(&circuit->area->lspdb[level - 1], entry->id); - bool own_lsp = !memcmp(entry->id, isis->sysid, ISIS_SYS_ID_LEN); + bool own_lsp = !memcmp(entry->id, circuit->area->isis->sysid, + ISIS_SYS_ID_LEN); if (lsp) { /* 7.3.15.2 b) 1) is this LSP newer */ int cmp = lsp_compare(circuit->area->area_tag, lsp, @@ -1459,8 +1467,9 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, * are not 0, * insert it and set SSN on it */ if (entry->rem_lifetime && entry->checksum - && entry->seqno && memcmp(entry->id, isis->sysid, - ISIS_SYS_ID_LEN)) { + && entry->seqno + && memcmp(entry->id, circuit->area->isis->sysid, + ISIS_SYS_ID_LEN)) { struct isis_lsp *lsp0 = NULL; if (LSP_FRAGMENT(entry->id)) { @@ -1667,13 +1676,14 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) } /* either 3 or 0 */ - if (pdu_type != FS_LINK_STATE /* FS PDU doesn't contain max area addr field */ + if (pdu_type != FS_LINK_STATE /* FS PDU doesn't contain max area addr + field */ && max_area_addrs != 0 - && max_area_addrs != isis->max_area_addrs) { + && max_area_addrs != circuit->area->isis->max_area_addrs) { flog_err( EC_ISIS_PACKET, "maximumAreaAddressesMismatch: maximumAreaAdresses in a received PDU %hhu while the parameter for this IS is %u", - max_area_addrs, isis->max_area_addrs); + max_area_addrs, circuit->area->isis->max_area_addrs); circuit->max_area_addr_mismatches++; #ifndef FABRICD /* send northbound notification */ @@ -2052,8 +2062,10 @@ int send_csnp(struct isis_circuit *circuit, int level) fill_fixed_hdr(pdu_type, circuit->snd_stream); size_t len_pointer = stream_get_endp(circuit->snd_stream); + stream_putw(circuit->snd_stream, 0); - stream_put(circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); + stream_put(circuit->snd_stream, circuit->area->isis->sysid, + ISIS_SYS_ID_LEN); /* with zero circuit id - ref 9.10, 9.11 */ stream_putc(circuit->snd_stream, 0); @@ -2230,7 +2242,8 @@ static int send_psnp(int level, struct isis_circuit *circuit) size_t len_pointer = stream_get_endp(circuit->snd_stream); stream_putw(circuit->snd_stream, 0); /* length is filled in later */ - stream_put(circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); + stream_put(circuit->snd_stream, circuit->area->isis->sysid, + ISIS_SYS_ID_LEN); stream_putc(circuit->snd_stream, circuit->idx); struct isis_passwd *passwd = (level == ISIS_LEVEL1) diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c index 45e79b46d..44422ff66 100644 --- a/isisd/isis_redist.c +++ b/isisd/isis_redist.c @@ -218,8 +218,9 @@ static void isis_redist_ensure_default(struct isis *isis, int family) } /* Handle notification about route being added */ -void isis_redist_add(int type, struct prefix *p, struct prefix_ipv6 *src_p, - uint8_t distance, uint32_t metric) +void isis_redist_add(struct isis *isis, int type, struct prefix *p, + struct prefix_ipv6 *src_p, uint8_t distance, + uint32_t metric) { int family = p->family; struct route_table *ei_table = get_ext_info(isis, family); @@ -270,7 +271,8 @@ void isis_redist_add(int type, struct prefix *p, struct prefix_ipv6 *src_p, } } -void isis_redist_delete(int type, struct prefix *p, struct prefix_ipv6 *src_p) +void isis_redist_delete(struct isis *isis, int type, struct prefix *p, + struct prefix_ipv6 *src_p) { int family = p->family; struct route_table *ei_table = get_ext_info(isis, family); @@ -292,8 +294,8 @@ void isis_redist_delete(int type, struct prefix *p, struct prefix_ipv6 *src_p) * by "default-information originate always". Areas without the * "always" setting will ignore routes with origin * DEFAULT_ROUTE. */ - isis_redist_add(DEFAULT_ROUTE, p, NULL, - 254, MAX_WIDE_PATH_METRIC); + isis_redist_add(isis, DEFAULT_ROUTE, p, NULL, 254, + MAX_WIDE_PATH_METRIC); return; } diff --git a/isisd/isis_redist.h b/isisd/isis_redist.h index 9c37c310e..0d2dc6a80 100644 --- a/isisd/isis_redist.h +++ b/isisd/isis_redist.h @@ -40,6 +40,7 @@ struct isis_redist { struct route_map *map; }; +struct isis; struct isis_area; struct prefix; struct prefix_ipv6; @@ -47,9 +48,11 @@ struct vty; struct route_table *get_ext_reach(struct isis_area *area, int family, int level); -void isis_redist_add(int type, struct prefix *p, struct prefix_ipv6 *src_p, - uint8_t distance, uint32_t metric); -void isis_redist_delete(int type, struct prefix *p, struct prefix_ipv6 *src_p); +void isis_redist_add(struct isis *isis, int type, struct prefix *p, + struct prefix_ipv6 *src_p, uint8_t distance, + uint32_t metric); +void isis_redist_delete(struct isis *isis, int type, struct prefix *p, + struct prefix_ipv6 *src_p); int isis_redist_config_write(struct vty *vty, struct isis_area *area, int family); void isis_redist_init(void); diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 668f234b9..ebce86bed 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -35,6 +35,7 @@ #include "table.h" #include "spf_backoff.h" #include "srcdest_table.h" +#include "vrf.h" #include "isis_constants.h" #include "isis_common.h" @@ -1083,7 +1084,8 @@ struct isis_spftree *isis_run_hopcount_spf(struct isis_area *area, init_spt(spftree, ISIS_MT_IPV4_UNICAST, ISIS_LEVEL2, AF_INET, SPFTREE_IPV4, true); - if (!memcmp(sysid, isis->sysid, ISIS_SYS_ID_LEN)) { + + if (!memcmp(sysid, area->isis->sysid, ISIS_SYS_ID_LEN)) { /* If we are running locally, initialize with information from adjacencies */ struct isis_vertex *root = isis_spf_add_root(spftree, sysid); isis_spf_preload_tent(spftree, sysid, root); @@ -1209,11 +1211,14 @@ static int isis_run_spf_cb(struct thread *thread) area->area_tag, level); if (area->ip_circuits) - retval = isis_run_spf(area, level, SPFTREE_IPV4, isis->sysid); + retval = isis_run_spf(area, level, SPFTREE_IPV4, + area->isis->sysid); if (area->ipv6_circuits) - retval = isis_run_spf(area, level, SPFTREE_IPV6, isis->sysid); + retval = isis_run_spf(area, level, SPFTREE_IPV6, + area->isis->sysid); if (area->ipv6_circuits && isis_area_ipv6_dstsrc_enabled(area)) - retval = isis_run_spf(area, level, SPFTREE_DSTSRC, isis->sysid); + retval = isis_run_spf(area, level, SPFTREE_DSTSRC, + area->isis->sysid); isis_area_verify_routes(area); @@ -1405,38 +1410,19 @@ static void isis_print_spftree(struct vty *vty, int level, vty_out(vty, "IS-IS paths to level-%d routers %s\n", level, tree_id_text); isis_print_paths(vty, &area->spftree[tree_id][level - 1]->paths, - isis->sysid); + area->isis->sysid); + vty_out(vty, "\n"); } -DEFUN (show_isis_topology, - show_isis_topology_cmd, - "show " PROTO_NAME " topology" -#ifndef FABRICD - " []" -#endif - , SHOW_STR - PROTO_HELP - "IS-IS paths to Intermediate Systems\n" -#ifndef FABRICD - "Paths to all level-1 routers in the area\n" - "Paths to all level-2 routers in the domain\n" -#endif - ) +static void show_isis_topology_common(struct vty *vty, int levels, + struct isis *isis) { - int levels; struct listnode *node; struct isis_area *area; - if (argc < 4) - levels = ISIS_LEVEL1 | ISIS_LEVEL2; - else if (strmatch(argv[3]->text, "level-1")) - levels = ISIS_LEVEL1; - else - levels = ISIS_LEVEL2; - if (!isis->area_list || isis->area_list->count == 0) - return CMD_SUCCESS; + return; for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { vty_out(vty, "Area %s:\n", @@ -1469,6 +1455,58 @@ DEFUN (show_isis_topology, vty_out(vty, "\n"); } +} + +DEFUN(show_isis_topology, show_isis_topology_cmd, + "show " PROTO_NAME + " [vrf ] topology" +#ifndef FABRICD + " []" +#endif + , + SHOW_STR PROTO_HELP VRF_CMD_HELP_STR + "All VRFs\n" + "IS-IS paths to Intermediate Systems\n" +#ifndef FABRICD + "Paths to all level-1 routers in the area\n" + "Paths to all level-2 routers in the domain\n" +#endif +) +{ + int levels = ISIS_LEVELS; + struct listnode *inode, *nnode; + struct isis *isis = NULL; + int idx = 0; + const char *vrf_name = VRF_DEFAULT_NAME; + bool all_vrf = false; + int idx_vrf = 0; + + if (argv_find(argv, argc, "topology", &idx)) { + if (argc < idx + 2) + levels = ISIS_LEVEL1 | ISIS_LEVEL2; + else if (strmatch(argv[idx + 1]->arg, "level-1")) + levels = ISIS_LEVEL1; + else + levels = ISIS_LEVEL2; + } + + if (!im) { + vty_out(vty, "IS-IS Routing Process not enabled\n"); + return CMD_SUCCESS; + } + ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + show_isis_topology_common(vty, levels, isis); + } + return 0; + } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) + show_isis_topology_common(vty, levels, isis); + } return CMD_SUCCESS; } diff --git a/isisd/isis_sr.c b/isisd/isis_sr.c index c69bf31d2..bdbdc30b4 100644 --- a/isisd/isis_sr.c +++ b/isisd/isis_sr.c @@ -1980,20 +1980,48 @@ static void show_prefix_sids(struct vty *vty, struct isis_area *area, int level) * Declaration of new show commands. */ DEFUN(show_sr_prefix_sids, show_sr_prefix_sids_cmd, - "show isis segment-routing prefix-sids", - SHOW_STR PROTO_HELP + "show isis [vrf ] segment-routing prefix-sids", + SHOW_STR PROTO_HELP VRF_CMD_HELP_STR + "All VRFs\n" "Segment-Routing\n" "Segment-Routing Prefix-SIDs\n") { - struct listnode *node; + struct listnode *node, *inode, *nnode; struct isis_area *area; - - for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { - vty_out(vty, "Area %s:\n", - area->area_tag ? area->area_tag : "null"); - - for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) - show_prefix_sids(vty, area, level); + struct isis *isis = NULL; + const char *vrf_name = VRF_DEFAULT_NAME; + bool all_vrf = false; + int idx_vrf = 0; + + ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, + area)) { + vty_out(vty, "Area %s:\n", + area->area_tag ? area->area_tag + : "null"); + for (int level = ISIS_LEVEL1; + level <= ISIS_LEVELS; level++) + show_prefix_sids(vty, area, + level); + } + } + return 0; + } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) { + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, + area)) { + vty_out(vty, "Area %s:\n", + area->area_tag ? area->area_tag + : "null"); + for (int level = ISIS_LEVEL1; + level <= ISIS_LEVELS; level++) + show_prefix_sids(vty, area, level); + } + } } return CMD_SUCCESS; @@ -2056,15 +2084,19 @@ DEFUN(show_sr_node, show_sr_node_cmd, "Segment-Routing\n" "Segment-Routing node\n") { - struct listnode *node; + struct listnode *node, *inode, *nnode; struct isis_area *area; + struct isis *isis = NULL; - for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { - vty_out(vty, "Area %s:\n", - area->area_tag ? area->area_tag : "null"); + for (ALL_LIST_ELEMENTS(im->isis, inode, nnode, isis)) { + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { + vty_out(vty, "Area %s:\n", + area->area_tag ? area->area_tag : "null"); - for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) - show_node(vty, area, level); + for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; + level++) + show_node(vty, area, level); + } } return CMD_SUCCESS; diff --git a/isisd/isis_te.c b/isisd/isis_te.c index a599909eb..016f811a7 100644 --- a/isisd/isis_te.c +++ b/isisd/isis_te.c @@ -302,34 +302,68 @@ int isis_mpls_te_update(struct interface *ifp) /* Followings are vty command functions */ #ifndef FABRICD -DEFUN (show_isis_mpls_te_router, - show_isis_mpls_te_router_cmd, - "show " PROTO_NAME " mpls-te router", - SHOW_STR - PROTO_HELP - MPLS_TE_STR - "Router information\n") +DEFUN(show_isis_mpls_te_router, + show_isis_mpls_te_router_cmd, + "show " PROTO_NAME " [vrf ] mpls-te router", + SHOW_STR + PROTO_HELP + VRF_CMD_HELP_STR "All VRFs\n" + MPLS_TE_STR "Router information\n") { - struct listnode *anode; + struct listnode *anode, *nnode, *inode; struct isis_area *area; + struct isis *isis = NULL; + const char *vrf_name = VRF_DEFAULT_NAME; + bool all_vrf = false; + int idx_vrf = 0; - if (!isis) { + if (!im) { vty_out(vty, "IS-IS Routing Process not enabled\n"); return CMD_SUCCESS; } - - for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { - - if (!IS_MPLS_TE(area->mta)) - continue; - - vty_out(vty, "Area %s:\n", area->area_tag); - if (ntohs(area->mta->router_id.s_addr) != 0) - vty_out(vty, " MPLS-TE Router-Address: %s\n", - inet_ntoa(area->mta->router_id)); - else - vty_out(vty, " N/A\n"); + ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + for (ALL_LIST_ELEMENTS_RO(isis->area_list, + anode, area)) { + if (!IS_MPLS_TE(area->mta)) + continue; + + vty_out(vty, "Area %s:\n", + area->area_tag); + if (ntohs(area->mta->router_id.s_addr) + != 0) + vty_out(vty, + " MPLS-TE Router-Address: %s\n", + inet_ntoa( + area->mta + ->router_id)); + else + vty_out(vty, " N/A\n"); + } + } + return 0; + } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) { + for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, + area)) { + + if (!IS_MPLS_TE(area->mta)) + continue; + + vty_out(vty, "Area %s:\n", area->area_tag); + if (ntohs(area->mta->router_id.s_addr) != 0) + vty_out(vty, + " MPLS-TE Router-Address: %s\n", + inet_ntoa( + area->mta->router_id)); + else + vty_out(vty, " N/A\n"); + } + } } return CMD_SUCCESS; @@ -449,30 +483,35 @@ DEFUN (show_isis_mpls_te_interface, "Interface information\n" "Interface name\n") { - struct listnode *anode, *cnode; + struct listnode *anode, *cnode, *nnode, *inode; struct isis_area *area; struct isis_circuit *circuit; struct interface *ifp; int idx_interface = 4; + struct isis *isis = NULL; - if (!isis) { + if (!im) { vty_out(vty, "IS-IS Routing Process not enabled\n"); return CMD_SUCCESS; } if (argc == idx_interface) { /* Show All Interfaces. */ - for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { + for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, + area)) { - if (!IS_MPLS_TE(area->mta)) - continue; + if (!IS_MPLS_TE(area->mta)) + continue; - vty_out(vty, "Area %s:\n", area->area_tag); + vty_out(vty, "Area %s:\n", area->area_tag); - for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, - circuit)) - show_ext_sub(vty, circuit->interface->name, - circuit->ext); + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, + cnode, circuit)) + show_ext_sub(vty, + circuit->interface->name, + circuit->ext); + } } } else { /* Interface name is specified. */ diff --git a/isisd/isis_vty_fabricd.c b/isisd/isis_vty_fabricd.c index a574c5bd3..d0a411a8d 100644 --- a/isisd/isis_vty_fabricd.c +++ b/isisd/isis_vty_fabricd.c @@ -112,12 +112,13 @@ DEFUN (no_triggered_csnp, return CMD_SUCCESS; } -static void lsp_print_flooding(struct vty *vty, struct isis_lsp *lsp) +static void lsp_print_flooding(struct vty *vty, struct isis_lsp *lsp, + struct isis *isis) { char lspid[255]; char buf[MONOTIME_STRLEN]; - lspid_print(lsp->hdr.lsp_id, lspid, true, true); + lspid_print(lsp->hdr.lsp_id, lspid, true, true, isis); vty_out(vty, "Flooding information for %s\n", lspid); if (!lsp->flooding_neighbors[TX_LSP_NORMAL]) { @@ -170,25 +171,29 @@ DEFUN (show_lsp_flooding, struct listnode *node; struct isis_area *area; + struct isis *isis = NULL; + + isis = isis_lookup_by_vrfid(VRF_DEFAULT); + + if (isis == NULL) { + vty_out(vty, "IS-IS Routing Process not enabled\n"); + return CMD_SUCCESS; + } for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { struct lspdb_head *head = &area->lspdb[ISIS_LEVEL2 - 1]; struct isis_lsp *lsp; - vty_out(vty, "Area %s:\n", area->area_tag ? - area->area_tag : "null"); - + vty_out(vty, "Area %s:\n", + area->area_tag ? area->area_tag : "null"); if (lspid) { - lsp = lsp_for_arg(head, lspid); - + lsp = lsp_for_arg(head, lspid, isis); if (lsp) - lsp_print_flooding(vty, lsp); - + lsp_print_flooding(vty, lsp, isis); continue; } - frr_each (lspdb, head, lsp) { - lsp_print_flooding(vty, lsp); + lsp_print_flooding(vty, lsp, isis); vty_out(vty, "\n"); } } @@ -222,9 +227,9 @@ DEFUN (ip_router_isis, } } - area = isis_area_lookup(area_tag); + area = isis_area_lookup(area_tag, VRF_DEFAULT); if (!area) - area = isis_area_create(area_tag); + area = isis_area_create(area_tag, VRF_DEFAULT_NAME); if (!circuit || !circuit->area) { circuit = isis_circuit_create(area, ifp); @@ -276,7 +281,7 @@ DEFUN (no_ip_router_isis, const char *af = argv[idx_afi]->arg; const char *area_tag = argv[idx_word]->arg; - area = isis_area_lookup(area_tag); + area = isis_area_lookup(area_tag, VRF_DEFAULT); if (!area) { vty_out(vty, "Can't find ISIS instance %s\n", area_tag); diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index a80a18d88..3aa21a9ae 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -62,6 +62,13 @@ static int isis_router_id_update_zebra(ZAPI_CALLBACK_ARGS) struct isis_area *area; struct listnode *node; struct prefix router_id; + struct isis *isis = NULL; + + isis = isis_lookup_by_vrfid(vrf_id); + + if (isis == NULL) { + return -1; + } zebra_router_id_update_read(zclient->ibuf, &router_id); if (isis->router_id == router_id.u.prefix4.s_addr) @@ -407,6 +414,12 @@ void isis_zebra_send_adjacency_sid(int cmd, const struct sr_adjacency *sra) static int isis_zebra_read(ZAPI_CALLBACK_ARGS) { struct zapi_route api; + struct isis *isis = NULL; + + isis = isis_lookup_by_vrfid(vrf_id); + + if (isis == NULL) + return -1; if (zapi_route_decode(zclient->ibuf, &api) < 0) return -1; @@ -428,10 +441,11 @@ static int isis_zebra_read(ZAPI_CALLBACK_ARGS) } if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) - isis_redist_add(api.type, &api.prefix, &api.src_prefix, + isis_redist_add(isis, api.type, &api.prefix, &api.src_prefix, api.distance, api.metric); else - isis_redist_delete(api.type, &api.prefix, &api.src_prefix); + isis_redist_delete(isis, api.type, &api.prefix, + &api.src_prefix); return 0; } diff --git a/isisd/isisd.c b/isisd/isisd.c index cc94444d4..0d39aba20 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -35,6 +35,7 @@ #include "prefix.h" #include "table.h" #include "qobj.h" +#include "vrf.h" #include "spf_backoff.h" #include "lib/northbound_cli.h" @@ -75,41 +76,142 @@ unsigned long debug_bfd; unsigned long debug_tx_queue; unsigned long debug_sr; -struct isis *isis = NULL; - DEFINE_QOBJ_TYPE(isis_area) +/* ISIS process wide configuration. */ +static struct isis_master isis_master; + +/* ISIS process wide configuration pointer to export. */ +struct isis_master *im; + /* * Prototypes. */ int isis_area_get(struct vty *, const char *); int area_net_title(struct vty *, const char *); int area_clear_net_title(struct vty *, const char *); -int show_isis_interface_common(struct vty *, const char *ifname, char); -int show_isis_neighbor_common(struct vty *, const char *id, char); -int clear_isis_neighbor_common(struct vty *, const char *id); +int show_isis_interface_common(struct vty *, const char *ifname, char, + const char *vrf_name, bool all_vrf); +int show_isis_neighbor_common(struct vty *, const char *id, char, + const char *vrf_name, bool all_vrf); +int clear_isis_neighbor_common(struct vty *, const char *id, const char *vrf_name, + bool all_vrf); + +static void isis_add(struct isis *isis) +{ + listnode_add(im->isis, isis); +} + +static void isis_delete(struct isis *isis) +{ + listnode_delete(im->isis, isis); +} + +/* Link ISIS instance to VRF. */ +void isis_vrf_link(struct isis *isis, struct vrf *vrf) +{ + isis->vrf_id = vrf->vrf_id; + if (vrf->info != (void *)isis) + vrf->info = (void *)isis; +} + +/* Unlink ISIS instance to VRF. */ +void isis_vrf_unlink(struct isis *isis, struct vrf *vrf) +{ + if (vrf->info == (void *)isis) + vrf->info = NULL; + isis->vrf_id = VRF_UNKNOWN; +} + +struct isis *isis_lookup_by_vrfid(vrf_id_t vrf_id) +{ + struct isis *isis = NULL; + struct listnode *node, *nnode; + for (ALL_LIST_ELEMENTS(im->isis, node, nnode, isis)) + if (isis->vrf_id == vrf_id) + return isis; + return NULL; +} + +struct isis *isis_lookup_by_vrfname(const char *vrfname) +{ + struct isis *isis = NULL; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(im->isis, node, nnode, isis)) + if (isis->name && vrfname && strcmp(isis->name, vrfname) == 0) + return isis; + return NULL; +} + +struct isis *isis_lookup_by_sysid(uint8_t *sysid) +{ + struct isis *isis = NULL; + struct listnode *node, *nnode; + for (ALL_LIST_ELEMENTS(im->isis, node, nnode, isis)) + if (!memcmp(isis->sysid, sysid, ISIS_SYS_ID_LEN)) + return isis; + return NULL; +} + +void isis_master_init(struct thread_master *master) +{ + memset(&isis_master, 0, sizeof(struct isis_master)); + im = &isis_master; + im->isis = list_new(); + im->master = master; +} -void isis_new(unsigned long process_id, vrf_id_t vrf_id) +void isis_global_instance_create() { + struct isis *isis = NULL; + + isis = isis_lookup_by_vrfid(VRF_DEFAULT); + if (isis == NULL) { + isis = isis_new(VRF_DEFAULT); + isis_add(isis); + } +} + +struct isis *isis_new(vrf_id_t vrf_id) +{ + struct vrf *vrf = NULL; + struct isis *isis = NULL; + isis = XCALLOC(MTYPE_ISIS, sizeof(struct isis)); + isis->vrf_id = vrf_id; + vrf = vrf_lookup_by_id(vrf_id); + + if (vrf) { + isis_vrf_link(isis, vrf); + isis->name = XSTRDUP(MTYPE_ISIS, vrf->name); + } + + if (IS_DEBUG_EVENTS) + zlog_debug( + "%s: Create new isis instance with vrf_name %s vrf_id %u", + __func__, isis->name, isis->vrf_id); + /* * Default values */ - isis->vrf_id = vrf_id; isis->max_area_addrs = 3; - isis->process_id = process_id; + isis->process_id = getpid(); isis->router_id = 0; isis->area_list = list_new(); isis->init_circ_list = list_new(); isis->uptime = time(NULL); - dyn_cache_init(); + dyn_cache_init(isis); + + return isis; } -struct isis_area *isis_area_create(const char *area_tag) +struct isis_area *isis_area_create(const char *area_tag, const char *vrf_name) { struct isis_area *area; - + struct isis *isis = NULL; + struct vrf *vrf = NULL; area = XCALLOC(MTYPE_ISIS_AREA, sizeof(struct isis_area)); /* @@ -190,6 +292,25 @@ struct isis_area *isis_area_create(const char *area_tag) area_mt_init(area); area->area_tag = strdup(area_tag); + + if (vrf_name) { + vrf = vrf_lookup_by_name(vrf_name); + if (vrf) { + isis = isis_lookup_by_vrfid(vrf->vrf_id); + if (isis == NULL) { + isis = isis_new(vrf->vrf_id); + isis_add(isis); + } + } else + return NULL; + } else { + isis = isis_lookup_by_vrfid(VRF_DEFAULT); + if (isis == NULL) { + isis = isis_new(VRF_DEFAULT); + isis_add(isis); + } + } + listnode_add(isis->area_list, area); area->isis = isis; @@ -210,10 +331,15 @@ struct isis_area *isis_area_create(const char *area_tag) return area; } -struct isis_area *isis_area_lookup(const char *area_tag) +struct isis_area *isis_area_lookup(const char *area_tag, vrf_id_t vrf_id) { struct isis_area *area; struct listnode *node; + struct isis *isis = NULL; + + isis = isis_lookup_by_vrfid(vrf_id); + if (isis == NULL) + return NULL; for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) if ((area->area_tag == NULL && area_tag == NULL) @@ -228,14 +354,14 @@ int isis_area_get(struct vty *vty, const char *area_tag) { struct isis_area *area; - area = isis_area_lookup(area_tag); + area = isis_area_lookup(area_tag, VRF_DEFAULT); if (area) { VTY_PUSH_CONTEXT(ROUTER_NODE, area); return CMD_SUCCESS; } - area = isis_area_create(area_tag); + area = isis_area_create(area_tag, VRF_DEFAULT_NAME); if (IS_DEBUG_EVENTS) zlog_debug("New IS-IS area instance %s", area->area_tag); @@ -302,18 +428,50 @@ void isis_area_destroy(struct isis_area *area) thread_cancel_event(master, area); - listnode_delete(isis->area_list, area); + listnode_delete(area->isis->area_list, area); free(area->area_tag); area_mt_finish(area); + if (listcount(area->isis->area_list) == 0) { + memset(area->isis->sysid, 0, ISIS_SYS_ID_LEN); + area->isis->sysid_set = 0; + } + XFREE(MTYPE_ISIS_AREA, area); - if (listcount(isis->area_list) == 0) { - memset(isis->sysid, 0, ISIS_SYS_ID_LEN); - isis->sysid_set = 0; +} + +void isis_finish(struct isis *isis) +{ + struct vrf *vrf = NULL; + + isis_delete(isis); + if (isis->name) { + vrf = vrf_lookup_by_name(isis->name); + if (vrf) + isis_vrf_unlink(isis, vrf); + XFREE(MTYPE_ISIS, isis->name); + } else { + vrf = vrf_lookup_by_id(VRF_DEFAULT); + if (vrf) + isis_vrf_unlink(isis, vrf); } + + XFREE(MTYPE_ISIS, isis); +} + +void isis_terminate() +{ + struct isis *isis = NULL; + struct listnode *node, *nnode; + + if (listcount(im->isis) == 0) + return; + + for (ALL_LIST_ELEMENTS(im->isis, node, nnode, isis)) + isis_finish(isis); } #ifdef FABRICD @@ -354,10 +512,10 @@ int area_net_title(struct vty *vty, const char *net_title) uint8_t buff[255]; /* We check that we are not over the maximal number of addresses */ - if (listcount(area->area_addrs) >= isis->max_area_addrs) { + if (listcount(area->area_addrs) >= area->isis->max_area_addrs) { vty_out(vty, "Maximum of area addresses (%d) already reached \n", - isis->max_area_addrs); + area->isis->max_area_addrs); return CMD_ERR_NOTHING_TODO; } @@ -383,20 +541,21 @@ int area_net_title(struct vty *vty, const char *net_title) return CMD_WARNING_CONFIG_FAILED; } - if (isis->sysid_set == 0) { + if (area->isis->sysid_set == 0) { /* * First area address - get the SystemID for this router */ - memcpy(isis->sysid, GETSYSID(addr), ISIS_SYS_ID_LEN); - isis->sysid_set = 1; + memcpy(area->isis->sysid, GETSYSID(addr), ISIS_SYS_ID_LEN); + area->isis->sysid_set = 1; if (IS_DEBUG_EVENTS) zlog_debug("Router has SystemID %s", - sysid_print(isis->sysid)); + sysid_print(area->isis->sysid)); } else { /* * Check that the SystemID portions match */ - if (memcmp(isis->sysid, GETSYSID(addr), ISIS_SYS_ID_LEN)) { + if (memcmp(area->isis->sysid, GETSYSID(addr), + ISIS_SYS_ID_LEN)) { vty_out(vty, "System ID must not change when defining additional area addresses\n"); XFREE(MTYPE_ISIS_AREA_ADDR, addr); @@ -468,8 +627,8 @@ int area_clear_net_title(struct vty *vty, const char *net_title) * Last area address - reset the SystemID for this router */ if (listcount(area->area_addrs) == 0) { - memset(isis->sysid, 0, ISIS_SYS_ID_LEN); - isis->sysid_set = 0; + memset(area->isis->sysid, 0, ISIS_SYS_ID_LEN); + area->isis->sysid_set = 0; if (IS_DEBUG_EVENTS) zlog_debug("Router has no SystemID"); } @@ -481,100 +640,144 @@ int area_clear_net_title(struct vty *vty, const char *net_title) * 'show isis interface' command */ -int show_isis_interface_common(struct vty *vty, const char *ifname, char detail) +int show_isis_interface_common(struct vty *vty, const char *ifname, char detail, + const char *vrf_name, bool all_vrf) { - struct listnode *anode, *cnode; + struct listnode *anode, *cnode, *mnode, *inode; struct isis_area *area; struct isis_circuit *circuit; + struct isis *isis = NULL; - if (!isis) { + if (!im) { vty_out(vty, "IS-IS Routing Process not enabled\n"); return CMD_SUCCESS; } + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS(im->isis, mnode, inode, isis)) { + for (ALL_LIST_ELEMENTS_RO(isis->area_list, + anode, area)) { + vty_out(vty, "Area %s:\n", + area->area_tag); + + if (detail == ISIS_UI_LEVEL_BRIEF) + vty_out(vty, + " Interface CircId State Type Level\n"); + + for (ALL_LIST_ELEMENTS_RO( + area->circuit_list, cnode, + circuit)) + if (!ifname) + isis_circuit_print_vty( + circuit, vty, + detail); + else if (strcmp(circuit->interface->name, ifname) == 0) + isis_circuit_print_vty( + circuit, vty, + detail); + } + } + return 0; + } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) { + for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, + area)) { + vty_out(vty, "Area %s:\n", area->area_tag); - for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { - vty_out(vty, "Area %s:\n", area->area_tag); - - if (detail == ISIS_UI_LEVEL_BRIEF) - vty_out(vty, - " Interface CircId State Type Level\n"); - - for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit)) - if (!ifname) - isis_circuit_print_vty(circuit, vty, detail); - else if (strcmp(circuit->interface->name, ifname) == 0) - isis_circuit_print_vty(circuit, vty, detail); + if (detail == ISIS_UI_LEVEL_BRIEF) + vty_out(vty, + " Interface CircId State Type Level\n"); + + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, + cnode, circuit)) + if (!ifname) + isis_circuit_print_vty( + circuit, vty, detail); + else if ( + strcmp(circuit->interface->name, + ifname) + == 0) + isis_circuit_print_vty( + circuit, vty, detail); + } + } } return CMD_SUCCESS; } -DEFUN (show_isis_interface, - show_isis_interface_cmd, - "show " PROTO_NAME " interface", - SHOW_STR - PROTO_HELP - "IS-IS interface\n") +DEFUN(show_isis_interface, + show_isis_interface_cmd, + "show " PROTO_NAME " [vrf ] interface", + SHOW_STR + PROTO_HELP + VRF_CMD_HELP_STR + "All VRFs\n" + "IS-IS interface\n") { - return show_isis_interface_common(vty, NULL, ISIS_UI_LEVEL_BRIEF); + const char *vrf_name = VRF_DEFAULT_NAME; + bool all_vrf = false; + int idx_vrf = 0; + + ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + return show_isis_interface_common(vty, NULL, ISIS_UI_LEVEL_BRIEF, + vrf_name, all_vrf); } -DEFUN (show_isis_interface_detail, - show_isis_interface_detail_cmd, - "show " PROTO_NAME " interface detail", - SHOW_STR - PROTO_HELP - "IS-IS interface\n" - "show detailed information\n") +DEFUN(show_isis_interface_detail, + show_isis_interface_detail_cmd, + "show " PROTO_NAME " [vrf ] interface detail", + SHOW_STR + PROTO_HELP + VRF_CMD_HELP_STR + "All VRFs\n" + "IS-IS interface\n" + "show detailed information\n") { - return show_isis_interface_common(vty, NULL, ISIS_UI_LEVEL_DETAIL); + const char *vrf_name = VRF_DEFAULT_NAME; + bool all_vrf = false; + int idx_vrf = 0; + + ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + return show_isis_interface_common(vty, NULL, ISIS_UI_LEVEL_DETAIL, + vrf_name, all_vrf); } -DEFUN (show_isis_interface_arg, - show_isis_interface_arg_cmd, - "show " PROTO_NAME " interface WORD", - SHOW_STR - PROTO_HELP - "IS-IS interface\n" - "IS-IS interface name\n") +DEFUN(show_isis_interface_arg, + show_isis_interface_arg_cmd, + "show " PROTO_NAME " [vrf ] interface WORD", + SHOW_STR + PROTO_HELP + VRF_CMD_HELP_STR + "All VRFs\n" + "IS-IS interface\n" + "IS-IS interface name\n") { - int idx_word = 3; - return show_isis_interface_common(vty, argv[idx_word]->arg, - ISIS_UI_LEVEL_DETAIL); -} + int idx_word = 0; + const char *vrf_name = VRF_DEFAULT_NAME; + bool all_vrf = false; + int idx_vrf = 0; -/* - * 'show isis neighbor' command - */ + ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + char *ifname = argv_find(argv, argc, "WORD", &idx_word) + ? argv[idx_word]->arg + : NULL; + return show_isis_interface_common(vty, ifname, ISIS_UI_LEVEL_DETAIL, + vrf_name, all_vrf); +} -int show_isis_neighbor_common(struct vty *vty, const char *id, char detail) +static void isis_neighbor_common(struct vty *vty, const char *id, char detail, + struct isis *isis, uint8_t *sysid) { struct listnode *anode, *cnode, *node; struct isis_area *area; struct isis_circuit *circuit; struct list *adjdb; struct isis_adjacency *adj; - struct isis_dynhn *dynhn; - uint8_t sysid[ISIS_SYS_ID_LEN]; int i; - if (!isis) { - vty_out(vty, "IS-IS Routing Process not enabled\n"); - return CMD_SUCCESS; - } - - memset(sysid, 0, ISIS_SYS_ID_LEN); - if (id) { - if (sysid2buff(sysid, id) == 0) { - dynhn = dynhn_find_by_name(id); - if (dynhn == NULL) { - vty_out(vty, "Invalid system id %s\n", id); - return CMD_SUCCESS; - } - memcpy(sysid, dynhn->id, ISIS_SYS_ID_LEN); - } - } - for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { vty_out(vty, "Area %s:\n", area->area_tag); @@ -590,9 +793,10 @@ int show_isis_neighbor_common(struct vty *vty, const char *id, char detail) for (ALL_LIST_ELEMENTS_RO( adjdb, node, adj)) if (!id - || !memcmp(adj->sysid, - sysid, - ISIS_SYS_ID_LEN)) + || !memcmp( + adj->sysid, + sysid, + ISIS_SYS_ID_LEN)) isis_adj_print_vty( adj, vty, @@ -610,24 +814,20 @@ int show_isis_neighbor_common(struct vty *vty, const char *id, char detail) } } - return CMD_SUCCESS; } - /* - * 'clear isis neighbor' command + * 'show isis neighbor' command */ -int clear_isis_neighbor_common(struct vty *vty, const char *id) + +int show_isis_neighbor_common(struct vty *vty, const char *id, char detail, + const char *vrf_name, bool all_vrf) { - struct listnode *anode, *cnode, *cnextnode, *node, *nnode; - struct isis_area *area; - struct isis_circuit *circuit; - struct list *adjdb; - struct isis_adjacency *adj; + struct listnode *nnode, *inode; struct isis_dynhn *dynhn; uint8_t sysid[ISIS_SYS_ID_LEN]; - int i; + struct isis *isis = NULL; - if (!isis) { + if (!im) { vty_out(vty, "IS-IS Routing Process not enabled\n"); return CMD_SUCCESS; } @@ -644,6 +844,32 @@ int clear_isis_neighbor_common(struct vty *vty, const char *id) } } + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + isis_neighbor_common(vty, id, detail, isis, + sysid); + } + return 0; + } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) + isis_neighbor_common(vty, id, detail, isis, sysid); + } + + return CMD_SUCCESS; +} + +static void isis_neighbor_common_clear(struct vty *vty, const char *id, + uint8_t *sysid, struct isis *isis) +{ + struct listnode *anode, *cnode, *cnextnode, *node, *nnode; + struct isis_area *area; + struct isis_circuit *circuit; + struct list *adjdb; + struct isis_adjacency *adj; + int i; + for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { for (ALL_LIST_ELEMENTS(area->circuit_list, cnode, cnextnode, circuit)) { @@ -655,9 +881,10 @@ int clear_isis_neighbor_common(struct vty *vty, const char *id) adjdb, node, nnode, adj)) if (!id - || !memcmp(adj->sysid, - sysid, - ISIS_SYS_ID_LEN)) + || !memcmp( + adj->sysid, + sysid, + ISIS_SYS_ID_LEN)) isis_adj_state_change( &adj, ISIS_ADJ_DOWN, @@ -676,64 +903,149 @@ int clear_isis_neighbor_common(struct vty *vty, const char *id) } } } - - return CMD_SUCCESS; } - -DEFUN (show_isis_neighbor, - show_isis_neighbor_cmd, - "show " PROTO_NAME " neighbor", - SHOW_STR - PROTO_HELP - "IS-IS neighbor adjacencies\n") +/* + * 'clear isis neighbor' command + */ +int clear_isis_neighbor_common(struct vty *vty, const char *id, const char *vrf_name, + bool all_vrf) { - return show_isis_neighbor_common(vty, NULL, ISIS_UI_LEVEL_BRIEF); -} + struct listnode *nnode, *inode; + struct isis_dynhn *dynhn; + uint8_t sysid[ISIS_SYS_ID_LEN]; + struct isis *isis = NULL; -DEFUN (show_isis_neighbor_detail, - show_isis_neighbor_detail_cmd, - "show " PROTO_NAME " neighbor detail", - SHOW_STR - PROTO_HELP - "IS-IS neighbor adjacencies\n" - "show detailed information\n") -{ - return show_isis_neighbor_common(vty, NULL, ISIS_UI_LEVEL_DETAIL); -} + if (!im) { + vty_out(vty, "IS-IS Routing Process not enabled\n"); + return CMD_SUCCESS; + } -DEFUN (show_isis_neighbor_arg, - show_isis_neighbor_arg_cmd, - "show " PROTO_NAME " neighbor WORD", - SHOW_STR - PROTO_HELP - "IS-IS neighbor adjacencies\n" - "System id\n") -{ - int idx_word = 3; - return show_isis_neighbor_common(vty, argv[idx_word]->arg, - ISIS_UI_LEVEL_DETAIL); -} + memset(sysid, 0, ISIS_SYS_ID_LEN); + if (id) { + if (sysid2buff(sysid, id) == 0) { + dynhn = dynhn_find_by_name(id); + if (dynhn == NULL) { + vty_out(vty, "Invalid system id %s\n", id); + return CMD_SUCCESS; + } + memcpy(sysid, dynhn->id, ISIS_SYS_ID_LEN); + } + } + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + isis_neighbor_common_clear(vty, id, sysid, + isis); + } + return 0; + } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) + isis_neighbor_common_clear(vty, id, sysid, isis); + } -DEFUN (clear_isis_neighbor, - clear_isis_neighbor_cmd, - "clear " PROTO_NAME " neighbor", - CLEAR_STR - PROTO_HELP - "IS-IS neighbor adjacencies\n") -{ - return clear_isis_neighbor_common(vty, NULL); + return CMD_SUCCESS; } -DEFUN (clear_isis_neighbor_arg, - clear_isis_neighbor_arg_cmd, - "clear " PROTO_NAME " neighbor WORD", - CLEAR_STR - PROTO_HELP - "IS-IS neighbor adjacencies\n" - "System id\n") -{ - int idx_word = 3; - return clear_isis_neighbor_common(vty, argv[idx_word]->arg); +DEFUN(show_isis_neighbor, + show_isis_neighbor_cmd, + "show " PROTO_NAME " [vrf ] neighbor", + SHOW_STR + PROTO_HELP + VRF_CMD_HELP_STR + "All vrfs\n" + "IS-IS neighbor adjacencies\n") +{ + const char *vrf_name = VRF_DEFAULT_NAME; + bool all_vrf = false; + int idx_vrf = 0; + + ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + return show_isis_neighbor_common(vty, NULL, ISIS_UI_LEVEL_BRIEF, + vrf_name, all_vrf); +} + +DEFUN(show_isis_neighbor_detail, + show_isis_neighbor_detail_cmd, + "show " PROTO_NAME " [vrf ] neighbor detail", + SHOW_STR + PROTO_HELP + VRF_CMD_HELP_STR + "all vrfs\n" + "IS-IS neighbor adjacencies\n" + "show detailed information\n") +{ + const char *vrf_name = VRF_DEFAULT_NAME; + bool all_vrf = false; + int idx_vrf = 0; + + ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + return show_isis_neighbor_common(vty, NULL, ISIS_UI_LEVEL_DETAIL, + vrf_name, all_vrf); +} + +DEFUN(show_isis_neighbor_arg, + show_isis_neighbor_arg_cmd, + "show " PROTO_NAME " [vrf ] neighbor WORD", + SHOW_STR + PROTO_HELP + VRF_CMD_HELP_STR + "All vrfs\n" + "IS-IS neighbor adjacencies\n" + "System id\n") +{ + int idx_word = 0; + const char *vrf_name = VRF_DEFAULT_NAME; + bool all_vrf = false; + int idx_vrf = 0; + + ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + char *id = argv_find(argv, argc, "WORD", &idx_word) + ? argv[idx_word]->arg + : NULL; + + return show_isis_neighbor_common(vty, id, ISIS_UI_LEVEL_DETAIL, + vrf_name, all_vrf); +} + +DEFUN(clear_isis_neighbor, + clear_isis_neighbor_cmd, + "clear " PROTO_NAME " [vrf ] neighbor", + CLEAR_STR + PROTO_HELP + VRF_CMD_HELP_STR + "All vrfs\n" + "IS-IS neighbor adjacencies\n") +{ + const char *vrf_name = VRF_DEFAULT_NAME; + bool all_vrf = false; + int idx_vrf = 0; + + ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + return clear_isis_neighbor_common(vty, NULL, vrf_name, all_vrf); +} + +DEFUN(clear_isis_neighbor_arg, + clear_isis_neighbor_arg_cmd, + "clear " PROTO_NAME " [vrf ] neighbor WORD", + CLEAR_STR + PROTO_HELP + VRF_CMD_HELP_STR + "All vrfs\n" + "IS-IS neighbor adjacencies\n" + "System id\n") +{ + int idx_word = 0; + const char *vrf_name = VRF_DEFAULT_NAME; + bool all_vrf = false; + int idx_vrf = 0; + + char *id = argv_find(argv, argc, "WORD", &idx_word) + ? argv[idx_word]->arg + : NULL; + ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + return clear_isis_neighbor_common(vty, id, vrf_name, all_vrf); } /* @@ -1236,34 +1548,41 @@ DEFUN (no_debug_isis_bfd, return CMD_SUCCESS; } -DEFUN (show_hostname, - show_hostname_cmd, - "show " PROTO_NAME " hostname", - SHOW_STR - PROTO_HELP - "IS-IS Dynamic hostname mapping\n") +DEFUN(show_hostname, show_hostname_cmd, + "show " PROTO_NAME " [vrf ] hostname", + SHOW_STR PROTO_HELP VRF_CMD_HELP_STR + "All VRFs\n" + "IS-IS Dynamic hostname mapping\n") { - dynhn_print_all(vty); + struct listnode *nnode, *inode; + const char *vrf_name = VRF_DEFAULT_NAME; + bool all_vrf = false; + int idx_vrf = 0; + struct isis *isis = NULL; + + ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + dynhn_print_all(vty, isis); + } + return 0; + } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) + dynhn_print_all(vty, isis); + } return CMD_SUCCESS; } -DEFUN (show_isis_spf_ietf, - show_isis_spf_ietf_cmd, - "show " PROTO_NAME " spf-delay-ietf", - SHOW_STR - PROTO_HELP - "SPF delay IETF information\n") +static void isis_spf_ietf_common(struct vty *vty, struct isis *isis) { - if (!isis) { - vty_out(vty, "ISIS is not running\n"); - return CMD_SUCCESS; - } - struct listnode *node; struct isis_area *area; - for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { + + vty_out(vty, "vrf : %s\n", isis->name); vty_out(vty, "Area %s:\n", area->area_tag ? area->area_tag : "null"); @@ -1294,23 +1613,49 @@ DEFUN (show_isis_spf_ietf, } } } +} + +DEFUN(show_isis_spf_ietf, show_isis_spf_ietf_cmd, + "show " PROTO_NAME " [vrf ] spf-delay-ietf", + SHOW_STR PROTO_HELP VRF_CMD_HELP_STR + "All VRFs\n" + "SPF delay IETF information\n") +{ + struct listnode *nnode, *inode; + struct isis *isis = NULL; + int idx_vrf = 0; + const char *vrf_name = VRF_DEFAULT_NAME; + bool all_vrf = false; + + ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf) + + if (!im) { + vty_out(vty, "ISIS is not running\n"); + return CMD_SUCCESS; + } + + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + isis_spf_ietf_common(vty, isis); + } + return 0; + } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) + isis_spf_ietf_common(vty, isis); + } + return CMD_SUCCESS; } -DEFUN (show_isis_summary, - show_isis_summary_cmd, - "show " PROTO_NAME " summary", - SHOW_STR PROTO_HELP "summary\n") +static void common_isis_summary(struct vty *vty, struct isis *isis) { struct listnode *node, *node2; struct isis_area *area; int level; - if (isis == NULL) { - vty_out(vty, PROTO_NAME " is not running\n"); - return CMD_SUCCESS; - } - + vty_out(vty, "vrf : %s\n", isis->name); vty_out(vty, "Process Id : %ld\n", isis->process_id); if (isis->sysid_set) vty_out(vty, "System Id : %s\n", @@ -1402,12 +1747,44 @@ DEFUN (show_isis_summary, } } } +} + +DEFUN(show_isis_summary, show_isis_summary_cmd, + "show " PROTO_NAME " [vrf ] summary", + SHOW_STR PROTO_HELP VRF_CMD_HELP_STR + "All VRFs\n" + "summary\n") +{ + struct listnode *inode, *nnode; + int idx_vrf = 0; + struct isis *isis = NULL; + const char *vrf_name = VRF_DEFAULT_NAME; + bool all_vrf = false; + + ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf) + if (!im) { + vty_out(vty, PROTO_NAME " is not running\n"); + return CMD_SUCCESS; + } + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + common_isis_summary(vty, isis); + } + return 0; + } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) + common_isis_summary(vty, isis); + } + vty_out(vty, "\n"); return CMD_SUCCESS; } -struct isis_lsp *lsp_for_arg(struct lspdb_head *head, const char *argv) +struct isis_lsp *lsp_for_arg(struct lspdb_head *head, const char *argv, + struct isis *isis) { char sysid[255] = {0}; uint8_t number[3]; @@ -1467,23 +1844,8 @@ struct isis_lsp *lsp_for_arg(struct lspdb_head *head, const char *argv) return lsp; } -/* - * This function supports following display options: - * [ show isis database [detail] ] - * [ show isis database [detail] ] - * [ show isis database [detail] ] - * [ show isis database . [detail] ] - * [ show isis database . [detail] ] - * [ show isis database .- [detail] ] - * [ show isis database .- [detail] ] - * [ show isis database detail ] - * [ show isis database detail ] - * [ show isis database detail . ] - * [ show isis database detail . ] - * [ show isis database detail .- ] - * [ show isis database detail .- ] - */ -static int show_isis_database(struct vty *vty, const char *argv, int ui_level) +static int show_isis_database_common(struct vty *vty, const char *argv, + int ui_level, struct isis *isis) { struct listnode *node; struct isis_area *area; @@ -1499,7 +1861,9 @@ static int show_isis_database(struct vty *vty, const char *argv, int ui_level) for (level = 0; level < ISIS_LEVELS; level++) { if (lspdb_count(&area->lspdb[level]) > 0) { - lsp = lsp_for_arg(&area->lspdb[level], argv); + lsp = NULL; + lsp = lsp_for_arg(&area->lspdb[level], argv, + isis); if (lsp != NULL || argv == NULL) { vty_out(vty, @@ -1515,14 +1879,17 @@ static int show_isis_database(struct vty *vty, const char *argv, int ui_level) if (ui_level == ISIS_UI_LEVEL_DETAIL) lsp_print_detail( lsp, vty, - area->dynhostname); + area->dynhostname, + isis); else lsp_print(lsp, vty, - area->dynhostname); + area->dynhostname, + isis); } else if (argv == NULL) { lsp_count = lsp_print_all( vty, &area->lspdb[level], - ui_level, area->dynhostname); + ui_level, area->dynhostname, + isis); vty_out(vty, " %u LSPs\n\n", lsp_count); @@ -1530,25 +1897,64 @@ static int show_isis_database(struct vty *vty, const char *argv, int ui_level) } } } + return CMD_SUCCESS; +} +/* + * This function supports following display options: + * [ show isis database [detail] ] + * [ show isis database [detail] ] + * [ show isis database [detail] ] + * [ show isis database . [detail] ] + * [ show isis database . [detail] ] + * [ show isis database .- [detail] ] + * [ show isis database .- [detail] ] + * [ show isis database detail ] + * [ show isis database detail ] + * [ show isis database detail . ] + * [ show isis database detail . ] + * [ show isis database detail .- ] + * [ show isis database detail .- ] + */ +static int show_isis_database(struct vty *vty, const char *argv, int ui_level, + const char *vrf_name, bool all_vrf) +{ + struct listnode *inode, *nnode; + struct isis *isis = NULL; + + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + show_isis_database_common(vty, argv, ui_level, + isis); + } + return 0; + } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) + show_isis_database_common(vty, argv, ui_level, isis); + } return CMD_SUCCESS; } -DEFUN (show_database, - show_database_cmd, - "show " PROTO_NAME " database [detail] [WORD]", - SHOW_STR - PROTO_HELP - "Link state database\n" - "Detailed information\n" - "LSP ID\n") +DEFUN(show_database, show_database_cmd, + "show " PROTO_NAME " [vrf ] database [detail] [WORD]", + SHOW_STR PROTO_HELP VRF_CMD_HELP_STR + "All VRFs\n" + "Link state database\n" + "Detailed information\n" + "LSP ID\n") { int idx = 0; + int idx_vrf = 0; + const char *vrf_name = VRF_DEFAULT_NAME; + bool all_vrf = false; int uilevel = argv_find(argv, argc, "detail", &idx) ? ISIS_UI_LEVEL_DETAIL : ISIS_UI_LEVEL_BRIEF; char *id = argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; - return show_isis_database(vty, id, uilevel); + ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + return show_isis_database(vty, id, uilevel, vrf_name, all_vrf); } #ifdef FABRICD @@ -1582,7 +1988,7 @@ DEFUN (no_router_openfabric, int idx_word = 3; area_tag = argv[idx_word]->arg; - area = isis_area_lookup(area_tag); + area = isis_area_lookup(area_tag, VRF_DEFAULT); if (area == NULL) { zlog_warn("%s: could not find area with area-tag %s", __func__, area_tag); @@ -1945,10 +2351,16 @@ DEFUN (no_log_adj_changes, static int isis_config_write(struct vty *vty) { int write = 0; + struct isis_area *area; + struct listnode *node, *node2, *inode, *nnode; + struct isis *isis = NULL; + + if (!im) { + vty_out(vty, "IS-IS Routing Process not enabled\n"); + return CMD_SUCCESS; + } - if (isis != NULL) { - struct isis_area *area; - struct listnode *node, *node2; + for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { /* ISIS - Area name */ diff --git a/isisd/isisd.h b/isisd/isisd.h index 724d5f8e5..41b69df2b 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -55,6 +55,12 @@ static const bool fabricd = false; extern void isis_cli_init(void); #endif +#define ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf) \ + if (argv_find(argv, argc, "vrf", &idx_vrf)) { \ + vrf_name = argv[idx_vrf + 1]->arg; \ + all_vrf = strmatch(vrf_name, "all"); \ + } + extern struct zebra_privs_t isisd_privs; /* uncomment if you are a developer in bug hunt */ @@ -62,8 +68,18 @@ extern struct zebra_privs_t isisd_privs; struct fabricd; +struct isis_master { + /* ISIS instance. */ + struct list *isis; + /* ISIS thread master. */ + struct thread_master *master; + /* Various OSPF global configuration. */ + uint8_t options; +}; + struct isis { vrf_id_t vrf_id; + char *name; unsigned long process_id; int sysid_set; uint8_t sysid[ISIS_SYS_ID_LEN]; /* SystemID for this IS */ @@ -79,7 +95,7 @@ struct isis { struct route_table *ext_info[REDIST_PROTOCOL_COUNT]; }; -extern struct isis *isis; +extern struct isis_master *im; enum spf_tree_id { SPFTREE_IPV4 = 0, @@ -191,14 +207,25 @@ struct isis_area { }; DECLARE_QOBJ_TYPE(isis_area) +void isis_terminate(void); +void isis_finish(struct isis *isis); +void isis_master_init(struct thread_master *master); +void isis_vrf_link(struct isis *isis, struct vrf *vrf); +void isis_vrf_unlink(struct isis *isis, struct vrf *vrf); +void isis_global_instance_create(void); +struct isis *isis_lookup_by_vrfid(vrf_id_t vrf_id); +struct isis *isis_lookup_by_vrfname(const char *vrfname); +struct isis *isis_lookup_by_sysid(uint8_t *sysid); + void isis_init(void); -void isis_new(unsigned long process_id, vrf_id_t vrf_id); -struct isis_area *isis_area_create(const char *); -struct isis_area *isis_area_lookup(const char *); +struct isis *isis_new(vrf_id_t vrf_id); +struct isis_area *isis_area_create(const char *, const char *); +struct isis_area *isis_area_lookup(const char *, vrf_id_t vrf_id); int isis_area_get(struct vty *vty, const char *area_tag); void isis_area_destroy(struct isis_area *area); void print_debug(struct vty *, int, int); -struct isis_lsp *lsp_for_arg(struct lspdb_head *head, const char *argv); +struct isis_lsp *lsp_for_arg(struct lspdb_head *head, const char *argv, + struct isis *isis); void isis_area_invalidate_routes(struct isis_area *area, int levels); void isis_area_verify_routes(struct isis_area *area); diff --git a/tests/isisd/test_isis_lspdb.c b/tests/isisd/test_isis_lspdb.c index f0baa482c..6a571eaa8 100644 --- a/tests/isisd/test_isis_lspdb.c +++ b/tests/isisd/test_isis_lspdb.c @@ -82,6 +82,7 @@ static void test_lsp_build_list_nonzero_ht(void) int main(int argc, char **argv) { + struct isis *isis = NULL; isis = calloc(sizeof(*isis), 1); test_lsp_build_list_nonzero_ht(); return 0;