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
*
}
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),
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)
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;
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 */
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;
}
}
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) {
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]);
+ }
+}
#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,
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);
}