]> git.proxmox.com Git - mirror_frr.git/commitdiff
isisd : Transformational changes to support different VRFs.
authorKaushik <kaushik@niralnetworks.com>
Mon, 13 Jul 2020 12:37:59 +0000 (05:37 -0700)
committerKaushik <kaushik@niralnetworks.com>
Fri, 14 Aug 2020 20:46:22 +0000 (13:46 -0700)
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 <kaushik@niralnetworks.com>
26 files changed:
isisd/fabricd.c
isisd/isis_adjacency.c
isisd/isis_bfd.c
isisd/isis_circuit.c
isisd/isis_cli.c
isisd/isis_csm.c
isisd/isis_dr.c
isisd/isis_dynhn.c
isisd/isis_dynhn.h
isisd/isis_lsp.c
isisd/isis_lsp.h
isisd/isis_main.c
isisd/isis_misc.c
isisd/isis_misc.h
isisd/isis_nb_config.c
isisd/isis_pdu.c
isisd/isis_redist.c
isisd/isis_redist.h
isisd/isis_spf.c
isisd/isis_sr.c
isisd/isis_te.c
isisd/isis_vty_fabricd.c
isisd/isis_zebra.c
isisd/isisd.c
isisd/isisd.h
tests/isisd/test_isis_lspdb.c

index e9dfd4601027f3cec8c2694859eae26010778cab..ebaf14461eff89a71d973ab464c5d5790511055f 100644 (file)
@@ -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);
 }
index ab133cbfd3239e6ab85e5f8a46cb3bc809c62410..af5258846a9490d597459fe458aa395a2b9d206f 100644 (file)
@@ -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;
index 5729994baac15a1a96f058a2e620673b6dec3d68..f81dd6cf51c35f6eee8b21835dbdc82e6fb80a18 100644 (file)
@@ -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.");
index 253ba22667d494e6a2b36980e36b110c0c27162b..985e07820f5ee51dddc9f8ceeb94ba5f5ed10d61 100644 (file)
@@ -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 */
index 4c2bcc774e8d3735a32fab3bce3336646e9941c5..4d0275800342b8c3c0641a87fd61fe912aab4d62 100644 (file)
@@ -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");
index 7aae326a4f182de7eb59965551207d26ee2c4512..929b4c26e8dd9caf8e4730b6eaf8c4ac4b7b8814 100644 (file)
@@ -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:
index 8df13048664064c89c1e1c1b6379f1f3f3ad6352..318fb9fab8b43a2a6ecc2e203f7fc04c43c1ab64 100644 (file)
@@ -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;
 
index 921e23d33a31ac8b752af4739beebf51b4e29ba1..e34c59be11bb5527505f9bb128d5ffc957ba02fa 100644 (file)
@@ -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);
index 27133bd3fd7fdc25fd70f003e81494272dbe5936..2cfc43fc1770c5bcf1a53573f8175aee2e394397 100644 (file)
@@ -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 */
index 646f106bb0356a7e431943f3b69e08c2a027deb8..90c7c0efb514f9991b2c267689d595922709c477 100644 (file)
@@ -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);
index 4cbca5d517c32d07a8d38b012a3375dfdaa35276..6cbea4749624704e56583d16eba9bb8e9e42666d 100644 (file)
@@ -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);
 
index 2317b166c6e0344db8576525e27b5d5fda83bf95..ed4b206851f57c01119a4fb49ffeee6133f0f262 100644 (file)
@@ -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();
index 86725173c453b62f651307480971e484e2f48fda..3aedd8ba1f9b64b1086450a61442187e7cfdd758 100644 (file)
@@ -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);
index 5cdbbfb0581513af01c1d340526440cd56f3ee4e..c6a5832f33c967e705f3a624aee594b62127d9b8 100644 (file)
@@ -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);
 
 /*
index cfe96e6edf917f627fe44f2320db4139dbe45430..ffc3d5b2e00cb952cab3ff41d46591b16564f73b 100644 (file)
@@ -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
index 72548e0425239dbd4110341e215db4392b5cb3b8..43b9f6685e51b237d3733be27c2a879dce350197 100644 (file)
@@ -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)
index 45e79b46da08490776d9bd4d70bb7485a364907f..44422ff6641ae9c0b09c6fa21dc7437dd5164292 100644 (file)
@@ -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;
        }
 
index 9c37c310eae8e61dfa00c8a7fd9d0b639a590629..0d2dc6a80342d255352de5dfecf76fc33001d6e7 100644 (file)
@@ -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);
index 668f234b9ab929c65ef297b9f46b9252d500b822..ebce86bed9b9328eddf6e12be3f7d0a73466b15e 100644 (file)
@@ -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
-       " [<level-1|level-2>]"
-#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 <NAME|all>] topology"
+#ifndef FABRICD
+      " [<level-1|level-2>]"
+#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;
 }
index c69bf31d24ef51fc596a3371836ee79d7b492d18..bdbdc30b4a2f7cf0c8b510bf7aa85ec7157d6ded 100644 (file)
@@ -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 <NAME|all>] 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;
index a599909eb89c341a42d2215b09d67d7f11d5771e..016f811a728ae619dcfe975dadbe62cc5363e42a 100644 (file)
@@ -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 <NAME|all>] 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. */
index a574c5bd3fd54fe570c2234b6e30323bfa0b81e9..d0a411a8db5ac3024455c1a9279aeaab09a5c088 100644 (file)
@@ -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);
index a80a18d88760d2333b2c680023e09192a219e548..3aa21a9aed259753ca73b034d8fa4b496804a993 100644 (file)
@@ -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;
 }
index cc94444d479909edfed9a0402a31cec19a351681..0d39aba20b421138a9c0fad13e6e539753ed19f5 100644 (file)
@@ -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 <NAME|all>] 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 <NAME|all>] 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 <NAME|all>] 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 <NAME|all>] 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 <NAME|all>] 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 <NAME|all>] 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 <NAME|all>] 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 <NAME|all>] 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 <NAME|all>] 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 <NAME|all>] 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 <NAME|all>] 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 <sysid> [detail] ]
- * [ show isis database <hostname> [detail] ]
- * [ show isis database <sysid>.<pseudo-id> [detail] ]
- * [ show isis database <hostname>.<pseudo-id> [detail] ]
- * [ show isis database <sysid>.<pseudo-id>-<fragment-number> [detail] ]
- * [ show isis database <hostname>.<pseudo-id>-<fragment-number> [detail] ]
- * [ show isis database detail <sysid> ]
- * [ show isis database detail <hostname> ]
- * [ show isis database detail <sysid>.<pseudo-id> ]
- * [ show isis database detail <hostname>.<pseudo-id> ]
- * [ show isis database detail <sysid>.<pseudo-id>-<fragment-number> ]
- * [ show isis database detail <hostname>.<pseudo-id>-<fragment-number> ]
- */
-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 <sysid> [detail] ]
+ * [ show isis database <hostname> [detail] ]
+ * [ show isis database <sysid>.<pseudo-id> [detail] ]
+ * [ show isis database <hostname>.<pseudo-id> [detail] ]
+ * [ show isis database <sysid>.<pseudo-id>-<fragment-number> [detail] ]
+ * [ show isis database <hostname>.<pseudo-id>-<fragment-number> [detail] ]
+ * [ show isis database detail <sysid> ]
+ * [ show isis database detail <hostname> ]
+ * [ show isis database detail <sysid>.<pseudo-id> ]
+ * [ show isis database detail <hostname>.<pseudo-id> ]
+ * [ show isis database detail <sysid>.<pseudo-id>-<fragment-number> ]
+ * [ show isis database detail <hostname>.<pseudo-id>-<fragment-number> ]
+ */
+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 <NAME|all>] 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 */
index 724d5f8e542202217550f9600a0b468a3619b8d1..41b69df2bf3cf069fddb04ae67a2b6d94aa27e53 100644 (file)
@@ -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);
index f0baa482c78ae27489085968ce11f14220a81c0c..6a571eaa847a987da2cc481901a357999c57dd64 100644 (file)
@@ -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;