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