#include "isisd/isis_spf.h"
#include "isisd/isis_events.h"
#include "isisd/isis_mt.h"
+#include "isisd/isis_tlvs.h"
+#include "isisd/fabricd.h"
extern struct isis *isis;
-static struct isis_adjacency *adj_alloc(const u_char *id)
+static struct isis_adjacency *adj_alloc(const uint8_t *id)
{
struct isis_adjacency *adj;
return adj;
}
-struct isis_adjacency *isis_new_adj(const u_char *id, const u_char *snpa,
+struct isis_adjacency *isis_new_adj(const uint8_t *id, const uint8_t *snpa,
int level, struct isis_circuit *circuit)
{
struct isis_adjacency *adj;
adj->level = level;
adj->flaps = 0;
adj->last_flap = time(NULL);
+ adj->threeway_state = ISIS_THREEWAY_DOWN;
if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
listnode_add(circuit->u.bc.adjdb[level - 1], adj);
adj->dischanges[level - 1] = 0;
return adj;
}
-struct isis_adjacency *isis_adj_lookup(const u_char *sysid, struct list *adjdb)
+struct isis_adjacency *isis_adj_lookup(const uint8_t *sysid, struct list *adjdb)
{
struct isis_adjacency *adj;
struct listnode *node;
return NULL;
}
-struct isis_adjacency *isis_adj_lookup_snpa(const u_char *ssnpa,
+struct isis_adjacency *isis_adj_lookup_snpa(const uint8_t *ssnpa,
struct list *adjdb)
{
struct listnode *node;
return NULL; /* not reached */
}
+void isis_adj_process_threeway(struct isis_adjacency *adj,
+ struct isis_threeway_adj *tw_adj,
+ enum isis_adj_usage adj_usage)
+{
+ enum isis_threeway_state next_tw_state = ISIS_THREEWAY_DOWN;
+
+ if (tw_adj && !adj->circuit->disable_threeway_adj) {
+ if (tw_adj->state == ISIS_THREEWAY_DOWN) {
+ next_tw_state = ISIS_THREEWAY_INITIALIZING;
+ } else if (tw_adj->state == ISIS_THREEWAY_INITIALIZING) {
+ next_tw_state = ISIS_THREEWAY_UP;
+ } else if (tw_adj->state == ISIS_THREEWAY_UP) {
+ if (adj->threeway_state == ISIS_THREEWAY_DOWN)
+ next_tw_state = ISIS_THREEWAY_DOWN;
+ else
+ next_tw_state = ISIS_THREEWAY_UP;
+ }
+ } else {
+ next_tw_state = ISIS_THREEWAY_UP;
+ }
+
+ if (next_tw_state != adj->threeway_state) {
+ if (isis->debugs & DEBUG_ADJ_PACKETS) {
+ zlog_info("ISIS-Adj (%s): Threeway state change %s to %s",
+ adj->circuit->area->area_tag,
+ isis_threeway_state_name(adj->threeway_state),
+ isis_threeway_state_name(next_tw_state));
+ }
+ }
+
+ if (next_tw_state != ISIS_THREEWAY_DOWN)
+ fabricd_initial_sync_hello(adj->circuit);
+
+ if (next_tw_state == ISIS_THREEWAY_DOWN) {
+ isis_adj_state_change(adj, ISIS_ADJ_DOWN, "Neighbor restarted");
+ return;
+ }
+
+ if (next_tw_state == ISIS_THREEWAY_UP) {
+ if (adj->adj_state != ISIS_ADJ_UP) {
+ isis_adj_state_change(adj, ISIS_ADJ_UP, NULL);
+ adj->adj_usage = adj_usage;
+ }
+ }
+
+ adj->threeway_state = next_tw_state;
+}
+
void isis_adj_state_change(struct isis_adjacency *adj,
enum isis_adj_state new_state, const char *reason)
{
} else if (new_state == ISIS_ADJ_DOWN) {
listnode_delete(circuit->u.bc.adjdb[level - 1],
adj);
+
circuit->upadjcount[level - 1]--;
- if (circuit->upadjcount[level - 1] == 0) {
- /* Clean lsp_queue when no adj is up. */
- if (circuit->lsp_queue)
- list_delete_all_node(
- circuit->lsp_queue);
- }
+ if (circuit->upadjcount[level - 1] == 0)
+ isis_tx_queue_clean(circuit->tx_queue);
+
isis_event_adjacency_state_change(adj,
new_state);
del = true;
if (del)
isis_delete_adj(adj);
- adj = NULL;
} else if (circuit->circ_type == CIRCUIT_T_P2P) {
del = false;
for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) {
adj->last_flap = time(NULL);
adj->flaps++;
- /* 7.3.17 - going up on P2P -> send CSNP */
- /* FIXME: yup, I know its wrong... but i will do
- * it! (for now) */
- send_csnp(circuit, level);
+ if (level == IS_LEVEL_1) {
+ thread_add_timer(master, send_l1_csnp,
+ circuit, 0,
+ &circuit->t_send_csnp[0]);
+ } else {
+ thread_add_timer(master, send_l2_csnp,
+ circuit, 0,
+ &circuit->t_send_csnp[1]);
+ }
} else if (new_state == ISIS_ADJ_DOWN) {
if (adj->circuit->u.p2p.neighbor == adj)
adj->circuit->u.p2p.neighbor = NULL;
circuit->upadjcount[level - 1]--;
- if (circuit->upadjcount[level - 1] == 0) {
- /* Clean lsp_queue when no adj is up. */
- if (circuit->lsp_queue)
- list_delete_all_node(
- circuit->lsp_queue);
- }
+ if (circuit->upadjcount[level - 1] == 0)
+ isis_tx_queue_clean(circuit->tx_queue);
+
isis_event_adjacency_state_change(adj,
new_state);
del = true;
if (del)
isis_delete_adj(adj);
-
- adj = NULL;
}
return;
for (unsigned int i = 0; i < adj->area_address_count;
i++) {
vty_out(vty, " %s\n",
- isonet_print(adj->area_addresses[i]
- .area_addr,
- adj->area_addresses[i]
- .addr_len));
+ isonet_print(adj->area_addresses[i]
+ .area_addr,
+ adj->area_addresses[i]
+ .addr_len));
}
}
if (adj->ipv4_address_count) {
for (unsigned int i = 0; i < adj->ipv4_address_count;
i++)
vty_out(vty, " %s\n",
- inet_ntoa(adj->ipv4_addresses[i]));
+ inet_ntoa(adj->ipv4_addresses[i]));
}
if (adj->ipv6_address_count) {
vty_out(vty, " IPv6 Address(es):\n");