diff options
| author | Christian Franke <chris@opensourcerouting.org> | 2018-11-23 03:13:56 +0100 | 
|---|---|---|
| committer | Rodny Molina <rmolina@linkedin.com> | 2018-12-07 19:45:14 +0000 | 
| commit | 1eb7c3a19568c8e460b8147c9dcd91cf0b9feb21 (patch) | |
| tree | c9215e4fdfeb83ea1e2264245aef29eb466ea088 | |
| parent | 0d6fb551c164c584f751325ccd53cccad7ecdb88 (diff) | |
fabricd: Add `show openfabric flooding` command
Add a command to show to what neighbors an LSP has been flooded.
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
| -rw-r--r-- | isisd/fabricd.c | 60 | ||||
| -rw-r--r-- | isisd/fabricd.h | 3 | ||||
| -rw-r--r-- | isisd/isis_lsp.c | 4 | ||||
| -rw-r--r-- | isisd/isis_lsp.h | 3 | ||||
| -rw-r--r-- | isisd/isis_vty_fabricd.c | 85 | 
5 files changed, 144 insertions, 11 deletions
diff --git a/isisd/fabricd.c b/isisd/fabricd.c index 5a9c424d66..3b6db67c2b 100644 --- a/isisd/fabricd.c +++ b/isisd/fabricd.c @@ -35,6 +35,7 @@  DEFINE_MTYPE_STATIC(ISISD, FABRICD_STATE, "ISIS OpenFabric")  DEFINE_MTYPE_STATIC(ISISD, FABRICD_NEIGHBOR, "ISIS OpenFabric Neighbor Entry") +DEFINE_MTYPE_STATIC(ISISD, FABRICD_FLOODING_INFO, "ISIS OpenFabric Flooding Log")  /* Tracks initial synchronization as per section 2.4   * @@ -509,10 +510,13 @@ int fabricd_write_settings(struct isis_area *area, struct vty *vty)  }  static void move_to_queue(struct isis_lsp *lsp, struct neighbor_entry *n, -			  enum isis_tx_type type) +			  enum isis_tx_type type, struct isis_circuit *circuit)  {  	n->present = false; +	if (n->adj && n->adj->circuit == circuit) +		return; +  	if (isis->debugs & DEBUG_FLOODING) {  		zlog_debug("OpenFabric: Adding %s to %s",  			   print_sys_hostname(n->id), @@ -521,6 +525,11 @@ static void move_to_queue(struct isis_lsp *lsp, struct neighbor_entry *n,  	if (n->adj)  		isis_tx_queue_add(n->adj->circuit->tx_queue, lsp, type); + +	uint8_t *neighbor_id = XMALLOC(MTYPE_FABRICD_FLOODING_INFO, sizeof(n->id)); + +	memcpy(neighbor_id, n->id, sizeof(n->id)); +	listnode_add(lsp->flooding_neighbors[type], neighbor_id);  }  static void mark_neighbor_as_present(struct hash_backet *backet, void *arg) @@ -571,11 +580,39 @@ static struct isis_lsp *lsp_for_neighbor(struct fabricd *f,  	return lsp_for_vertex(f->spftree, &vertex);  } -void fabricd_lsp_flood(struct isis_lsp *lsp) +static void fabricd_free_lsp_flooding_info(void *val) +{ +	XFREE(MTYPE_FABRICD_FLOODING_INFO, val); +} + +static void fabricd_lsp_reset_flooding_info(struct isis_lsp *lsp, +					    struct isis_circuit *circuit) +{ +	XFREE(MTYPE_FABRICD_FLOODING_INFO, lsp->flooding_interface); +	for (enum isis_tx_type type = TX_LSP_NORMAL; +	     type <= TX_LSP_CIRCUIT_SCOPED; type++) { +		if (lsp->flooding_neighbors[type]) { +			list_delete_all_node(lsp->flooding_neighbors[type]); +			continue; +		} + +		lsp->flooding_neighbors[type] = list_new(); +		lsp->flooding_neighbors[type]->del = fabricd_free_lsp_flooding_info; +	} + +	if (circuit) { +		lsp->flooding_interface = XSTRDUP(MTYPE_FABRICD_FLOODING_INFO, +						  circuit->interface->name); +	} +} + +void fabricd_lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit)  {  	struct fabricd *f = lsp->area->fabricd;  	assert(f); +	fabricd_lsp_reset_flooding_info(lsp, circuit); +  	void *cursor = NULL;  	struct neighbor_entry *n; @@ -597,7 +634,7 @@ void fabricd_lsp_flood(struct isis_lsp *lsp)  			           rawlspid_print(node_lsp->hdr.lsp_id));  		} -		move_to_queue(lsp, n, TX_LSP_CIRCUIT_SCOPED); +		move_to_queue(lsp, n, TX_LSP_CIRCUIT_SCOPED, circuit);  	}  	/* Mark all elements in NN as present */ @@ -625,7 +662,7 @@ void fabricd_lsp_flood(struct isis_lsp *lsp)  					   print_sys_hostname(n->id));  			} -			move_to_queue(lsp, n, TX_LSP_CIRCUIT_SCOPED); +			move_to_queue(lsp, n, TX_LSP_CIRCUIT_SCOPED, circuit);  			continue;  		} @@ -657,7 +694,8 @@ void fabricd_lsp_flood(struct isis_lsp *lsp)  		}  		move_to_queue(lsp, n, need_reflood ? -			      TX_LSP_NORMAL : TX_LSP_CIRCUIT_SCOPED); +			      TX_LSP_NORMAL : TX_LSP_CIRCUIT_SCOPED, +			      circuit);  	}  	if (isis->debugs & DEBUG_FLOODING) { @@ -709,3 +747,15 @@ struct list *fabricd_ip_addrs(struct isis_circuit *circuit)  	return NULL;  } + +void fabricd_lsp_free(struct isis_lsp *lsp) +{ +	XFREE(MTYPE_FABRICD_FLOODING_INFO, lsp->flooding_interface); +	for (enum isis_tx_type type = TX_LSP_NORMAL; +	     type <= TX_LSP_CIRCUIT_SCOPED; type++) { +		if (!lsp->flooding_neighbors[type]) +			continue; + +		list_delete(&lsp->flooding_neighbors[type]); +	} +} diff --git a/isisd/fabricd.h b/isisd/fabricd.h index 76c182f2d2..886fd3c628 100644 --- a/isisd/fabricd.h +++ b/isisd/fabricd.h @@ -42,8 +42,9 @@ struct isis_spftree *fabricd_spftree(struct isis_area *area);  void fabricd_configure_tier(struct isis_area *area, uint8_t tier);  uint8_t fabricd_tier(struct isis_area *area);  int fabricd_write_settings(struct isis_area *area, struct vty *vty); -void fabricd_lsp_flood(struct isis_lsp *lsp); +void fabricd_lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit);  void fabricd_trigger_csnp(struct isis_area *area);  struct list *fabricd_ip_addrs(struct isis_circuit *circuit); +void fabricd_lsp_free(struct isis_lsp *lsp);  #endif diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index b8640f34bf..86d433cff7 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -143,6 +143,8 @@ static void lsp_destroy(struct isis_lsp *lsp)  	if (lsp->pdu)  		stream_free(lsp->pdu); + +	fabricd_lsp_free(lsp);  	XFREE(MTYPE_ISIS_LSP, lsp);  } @@ -2011,7 +2013,7 @@ void _lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit,  	if (!fabricd)  		lsp_set_all_srmflags(lsp, true);  	else -		fabricd_lsp_flood(lsp); +		fabricd_lsp_flood(lsp, circuit);  	if (circuit)  		isis_tx_queue_del(circuit->tx_queue, lsp); diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h index 3013b8c214..7f088987be 100644 --- a/isisd/isis_lsp.h +++ b/isisd/isis_lsp.h @@ -47,6 +47,9 @@ struct isis_lsp {  	int age_out;  	struct isis_area *area;  	struct isis_tlvs *tlvs; + +	struct list *flooding_neighbors[TX_LSP_CIRCUIT_SCOPED + 1]; +	char *flooding_interface;  };  dict_t *lsp_db_init(void); diff --git a/isisd/isis_vty_fabricd.c b/isisd/isis_vty_fabricd.c index 5ef3af0f19..72ee2ac921 100644 --- a/isisd/isis_vty_fabricd.c +++ b/isisd/isis_vty_fabricd.c @@ -23,10 +23,12 @@  #include "command.h" -#include "isisd.h" -#include "isis_vty_common.h" -#include "fabricd.h" -#include "isis_tlvs.h" +#include "isisd/isisd.h" +#include "isisd/isis_vty_common.h" +#include "isisd/fabricd.h" +#include "isisd/isis_tlvs.h" +#include "isisd/isis_misc.h" +#include "isisd/isis_lsp.h"  DEFUN (fabric_tier,         fabric_tier_cmd, @@ -55,8 +57,83 @@ DEFUN (no_fabric_tier,  	return CMD_SUCCESS;  } +static void lsp_print_flooding(struct vty *vty, struct isis_lsp *lsp) +{ +	char lspid[255]; + +	lspid_print(lsp->hdr.lsp_id, lspid, true, true); +	vty_out(vty, "Flooding information for %s\n", lspid); + +	if (!lsp->flooding_neighbors[TX_LSP_NORMAL]) { +		vty_out(vty, "    Never flooded.\n"); +		return; +	} + +	vty_out(vty, "    Last received on: %s\n", +		lsp->flooding_interface ? +		lsp->flooding_interface : "(null)"); + +	for (enum isis_tx_type type = TX_LSP_NORMAL; +	     type <= TX_LSP_CIRCUIT_SCOPED; type++) { +		struct listnode *node; +		uint8_t *neighbor_id; + +		vty_out(vty, "    %s:\n", +			(type == TX_LSP_NORMAL) ? "RF" : "DNR"); +		for (ALL_LIST_ELEMENTS_RO(lsp->flooding_neighbors[type], +					  node, neighbor_id)) { +			vty_out(vty, "        %s\n", +				print_sys_hostname(neighbor_id)); +		} +	} +} + +DEFUN (show_lsp_flooding, +       show_lsp_flooding_cmd, +       "show openfabric flooding [WORD]", +       SHOW_STR +       PROTO_HELP +       "Flooding information\n" +       "LSP ID\n") +{ +	const char *lspid = NULL; + +	if (argc == 4) { +		lspid = argv[3]->arg; +	} + +	struct listnode *node; +	struct isis_area *area; + +	for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { +		dict_t *lspdb = area->lspdb[ISIS_LEVEL2 - 1]; + +		vty_out(vty, "Area %s:\n", area->area_tag ? +			area->area_tag : "null"); + +		if (lspid) { +			struct isis_lsp *lsp = lsp_for_arg(lspid, lspdb); + +			if (lsp) +				lsp_print_flooding(vty, lsp); + +			continue; +		} + +		for (dnode_t *dnode = dict_first(lspdb); dnode; +		     dnode = dict_next(lspdb, dnode)) { +			lsp_print_flooding(vty, dnode_get(dnode)); +			vty_out(vty, "\n"); +		} +	} + +	return CMD_SUCCESS; +} +  void isis_vty_daemon_init(void)  {  	install_element(ROUTER_NODE, &fabric_tier_cmd);  	install_element(ROUTER_NODE, &no_fabric_tier_cmd); + +	install_element(ENABLE_NODE, &show_lsp_flooding_cmd);  }  | 
