uint8_t tier_pending;
struct thread *tier_calculation_timer;
struct thread *tier_set_timer;
+
+ int csnp_delay;
+ bool always_send_csnp;
};
/* Code related to maintaining the neighbor lists */
static struct neighbor_entry *neighbor_entry_new(const uint8_t *id,
struct isis_adjacency *adj)
{
- struct neighbor_entry *rv = XMALLOC(MTYPE_FABRICD_NEIGHBOR, sizeof(*rv));
+ struct neighbor_entry *rv = XMALLOC(MTYPE_FABRICD_NEIGHBOR,
+ sizeof(*rv));
memcpy(rv->id, id, sizeof(rv->id));
rv->adj = adj;
static struct neighbor_entry *neighbor_entry_lookup_list(struct skiplist *list,
const uint8_t *id)
{
- struct neighbor_entry n = {{0}};
+ struct neighbor_entry n = { {0} };
memcpy(n.id, id, sizeof(n.id));
return rv;
}
-static void neighbor_lists_update(struct fabricd *f)
+static int fabricd_handle_adj_state_change(struct isis_adjacency *arg)
{
- neighbor_lists_clear(f);
+ struct fabricd *f = arg->circuit->area->fabricd;
+
+ if (!f)
+ return 0;
+
+ while (!skiplist_empty(f->neighbors))
+ skiplist_delete_first(f->neighbors);
struct listnode *node;
struct isis_circuit *circuit;
skiplist_insert(f->neighbors, n, n);
}
+ return 0;
+}
+
+static void neighbors_neighbors_update(struct fabricd *f)
+{
+ hash_clean(f->neighbors_neighbors, neighbor_entry_del_void);
+
+ struct listnode *node;
struct isis_vertex *v;
for (ALL_QUEUE_ELEMENTS_RO(&f->spftree->paths, node, v)) {
"Fabricd Neighbors");
rv->tier = rv->tier_config = ISIS_TIER_UNDEFINED;
+
+ rv->csnp_delay = FABRICD_DEFAULT_CSNP_DELAY;
return rv;
};
return;
isis_run_hopcount_spf(area, isis->sysid, f->spftree);
- neighbor_lists_update(f);
+ neighbors_neighbors_update(f);
fabricd_bump_tier_calculation_timer(f);
}
written++;
}
+ if (f->csnp_delay != FABRICD_DEFAULT_CSNP_DELAY
+ || f->always_send_csnp) {
+ vty_out(vty, " triggered-csnp-delay %d%s\n", f->csnp_delay,
+ f->always_send_csnp ? " always" : "");
+ }
+
return written;
}
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));
+ 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);
}
lsp->flooding_neighbors[type] = list_new();
- lsp->flooding_neighbors[type]->del = fabricd_free_lsp_flooding_info;
+ lsp->flooding_neighbors[type]->del =
+ fabricd_free_lsp_flooding_info;
}
if (circuit) {
void *cursor = NULL;
struct neighbor_entry *n;
- /* Mark all elements in NL as present and move T0s into DNR */
- while (!skiplist_next(f->neighbors, NULL, (void **)&n, &cursor)) {
+ /* Mark all elements in NL as present */
+ while (!skiplist_next(f->neighbors, NULL, (void **)&n, &cursor))
n->present = true;
- struct isis_lsp *node_lsp = lsp_for_neighbor(f, n);
- if (!node_lsp
- || !node_lsp->tlvs
- || !node_lsp->tlvs->spine_leaf
- || !node_lsp->tlvs->spine_leaf->has_tier
- || node_lsp->tlvs->spine_leaf->tier != 0) {
- continue;
- }
-
- if (isis->debugs & DEBUG_FLOODING) {
- zlog_debug("Moving %s to DNR because it's T0",
- rawlspid_print(node_lsp->hdr.lsp_id));
- }
-
- move_to_queue(lsp, n, TX_LSP_CIRCUIT_SCOPED, circuit);
- }
-
/* Mark all elements in NN as present */
hash_iterate(f->neighbors_neighbors, mark_neighbor_as_present, NULL);
- struct isis_vertex *originator = isis_find_vertex(&f->spftree->paths,
- lsp->hdr.lsp_id,
- VTYPE_NONPSEUDO_TE_IS);
+ struct isis_vertex *originator =
+ isis_find_vertex(&f->spftree->paths,
+ lsp->hdr.lsp_id,
+ VTYPE_NONPSEUDO_TE_IS);
/* Remove all IS from NL and NN in the shortest path
* to the IS that originated the LSP */
}
}
-void fabricd_trigger_csnp(struct isis_area *area)
+void fabricd_trigger_csnp(struct isis_area *area, bool circuit_scoped)
{
struct fabricd *f = area->fabricd;
if (!f)
return;
+ if (!circuit_scoped && !f->always_send_csnp)
+ return;
+
struct listnode *node;
struct isis_circuit *circuit;
thread_cancel(circuit->t_send_csnp[ISIS_LEVEL2 - 1]);
thread_add_timer_msec(master, send_l2_csnp, circuit,
- isis_jitter(500, CSNP_JITTER),
+ isis_jitter(f->csnp_delay, CSNP_JITTER),
&circuit->t_send_csnp[ISIS_LEVEL2 - 1]);
}
}
fabricd_lsp_reset_flooding_info(lsp, circuit);
lsp->flooding_circuit_scoped = true;
}
+
+void fabricd_configure_triggered_csnp(struct isis_area *area, int delay,
+ bool always_send_csnp)
+{
+ struct fabricd *f = area->fabricd;
+
+ if (!f)
+ return;
+
+ f->csnp_delay = delay;
+ f->always_send_csnp = always_send_csnp;
+}
+
+void fabricd_init(void)
+{
+ hook_register(isis_adj_state_change_hook,
+ fabricd_handle_adj_state_change);
+}