summaryrefslogtreecommitdiff
path: root/isisd
diff options
context:
space:
mode:
Diffstat (limited to 'isisd')
-rw-r--r--isisd/fabricd.c136
-rw-r--r--isisd/fabricd.h36
-rw-r--r--isisd/isis_adjacency.c17
-rw-r--r--isisd/isis_lsp.c16
-rw-r--r--isisd/isis_pdu.c28
-rw-r--r--isisd/isisd.c4
-rw-r--r--isisd/isisd.h4
-rw-r--r--isisd/subdir.am2
8 files changed, 233 insertions, 10 deletions
diff --git a/isisd/fabricd.c b/isisd/fabricd.c
new file mode 100644
index 0000000000..d37e6a71d8
--- /dev/null
+++ b/isisd/fabricd.c
@@ -0,0 +1,136 @@
+/*
+ * IS-IS Rout(e)ing protocol - OpenFabric extensions
+ *
+ * Copyright (C) 2018 Christian Franke
+ *
+ * This file is part of FreeRangeRouting (FRR)
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <zebra.h>
+#include "isisd/fabricd.h"
+#include "isisd/isisd.h"
+#include "isisd/isis_memory.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isis_misc.h"
+#include "isisd/isis_adjacency.h"
+
+DEFINE_MTYPE_STATIC(ISISD, FABRICD_STATE, "ISIS OpenFabric")
+
+/* Tracks initial synchronization as per section 2.4
+ *
+ * We declare the sync complete once we have seen at least one
+ * CSNP and there are no more LSPs with SSN or SRM set.
+ */
+enum fabricd_sync_state {
+ FABRICD_SYNC_PENDING,
+ FABRICD_SYNC_STARTED,
+ FABRICD_SYNC_COMPLETE
+};
+
+struct fabricd {
+ enum fabricd_sync_state initial_sync_state;
+ time_t initial_sync_start;
+ struct isis_circuit *initial_sync_circuit;
+ struct thread *initial_sync_timeout;
+};
+
+struct fabricd *fabricd_new(void)
+{
+ struct fabricd *rv = XCALLOC(MTYPE_FABRICD_STATE, sizeof(*rv));
+
+ rv->initial_sync_state = FABRICD_SYNC_PENDING;
+ return rv;
+};
+
+static int fabricd_initial_sync_timeout(struct thread *thread)
+{
+ struct fabricd *f = THREAD_ARG(thread);
+
+ zlog_info("OpenFabric: Initial synchronization on %s timed out!",
+ f->initial_sync_circuit->interface->name);
+ f->initial_sync_state = FABRICD_SYNC_PENDING;
+ f->initial_sync_circuit = NULL;
+ f->initial_sync_timeout = NULL;
+ return 0;
+}
+
+void fabricd_initial_sync_hello(struct isis_circuit *circuit)
+{
+ struct fabricd *f = circuit->area->fabricd;
+
+ if (!f)
+ return;
+
+ if (f->initial_sync_state > FABRICD_SYNC_PENDING)
+ return;
+
+ f->initial_sync_state = FABRICD_SYNC_STARTED;
+
+ long timeout = 2 * circuit->hello_interval[1] * circuit->hello_multiplier[1];
+
+ f->initial_sync_circuit = circuit;
+ if (f->initial_sync_timeout)
+ return;
+
+ thread_add_timer(master, fabricd_initial_sync_timeout, f,
+ timeout, &f->initial_sync_timeout);
+ f->initial_sync_start = monotime(NULL);
+
+ zlog_info("OpenFabric: Started initial synchronization with %s on %s",
+ sysid_print(circuit->u.p2p.neighbor->sysid),
+ circuit->interface->name);
+}
+
+bool fabricd_initial_sync_is_in_progress(struct isis_area *area)
+{
+ struct fabricd *f = area->fabricd;
+
+ if (!f)
+ return false;
+
+ if (f->initial_sync_state > FABRICD_SYNC_PENDING
+ && f->initial_sync_state < FABRICD_SYNC_COMPLETE)
+ return true;
+
+ return false;
+}
+
+struct isis_circuit *fabricd_initial_sync_circuit(struct isis_area *area)
+{
+ struct fabricd *f = area->fabricd;
+ if (!f)
+ return NULL;
+
+ return f->initial_sync_circuit;
+}
+
+void fabricd_initial_sync_finish(struct isis_area *area)
+{
+ struct fabricd *f = area->fabricd;
+
+ if (!f)
+ return;
+
+ if (monotime(NULL) - f->initial_sync_start < 5)
+ return;
+
+ zlog_info("OpenFabric: Initial synchronization on %s complete.",
+ f->initial_sync_circuit->interface->name);
+ f->initial_sync_state = FABRICD_SYNC_COMPLETE;
+ f->initial_sync_circuit = NULL;
+ thread_cancel(f->initial_sync_timeout);
+ f->initial_sync_timeout = NULL;
+}
diff --git a/isisd/fabricd.h b/isisd/fabricd.h
new file mode 100644
index 0000000000..35a5bb6a3b
--- /dev/null
+++ b/isisd/fabricd.h
@@ -0,0 +1,36 @@
+/*
+ * IS-IS Rout(e)ing protocol - OpenFabric extensions
+ *
+ * Copyright (C) 2018 Christian Franke
+ *
+ * This file is part of FreeRangeRouting (FRR)
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef FABRICD_H
+#define FABRICD_H
+
+struct fabricd;
+
+struct isis_circuit;
+struct isis_area;
+
+struct fabricd *fabricd_new(void);
+void fabricd_initial_sync_hello(struct isis_circuit *circuit);
+bool fabricd_initial_sync_is_in_progress(struct isis_area *area);
+struct isis_circuit *fabricd_initial_sync_circuit(struct isis_area *area);
+void fabricd_initial_sync_finish(struct isis_area *area);
+
+#endif
diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c
index 4b3d78421e..56dbc25829 100644
--- a/isisd/isis_adjacency.c
+++ b/isisd/isis_adjacency.c
@@ -48,6 +48,7 @@
#include "isisd/isis_events.h"
#include "isisd/isis_mt.h"
#include "isisd/isis_tlvs.h"
+#include "isisd/fabricd.h"
extern struct isis *isis;
@@ -193,6 +194,9 @@ void isis_adj_process_threeway(struct isis_adjacency *adj,
}
}
+ 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;
@@ -306,10 +310,15 @@ void isis_adj_state_change(struct isis_adjacency *adj,
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;
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index 66c97ae897..90bcece15d 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -56,6 +56,7 @@
#include "isisd/isis_te.h"
#include "isisd/isis_mt.h"
#include "isisd/isis_tlvs.h"
+#include "isisd/fabricd.h"
static int lsp_l1_refresh(struct thread *thread);
static int lsp_l2_refresh(struct thread *thread);
@@ -1813,6 +1814,7 @@ int lsp_tick(struct thread *thread)
int level;
uint16_t rem_lifetime;
time_t now = monotime(NULL);
+ bool fabricd_sync_incomplete = false;
lsp_list = list_new();
@@ -1821,6 +1823,8 @@ int lsp_tick(struct thread *thread)
area->t_tick = NULL;
thread_add_timer(master, lsp_tick, area, 1, &area->t_tick);
+ struct isis_circuit *fabricd_init_c = fabricd_initial_sync_circuit(area);
+
/*
* Build a list of LSPs with (any) SRMflag set
* and removed the ones that have aged out
@@ -1880,6 +1884,15 @@ int lsp_tick(struct thread *thread)
dnode);
} else if (flags_any_set(lsp->SRMflags))
listnode_add(lsp_list, lsp);
+
+ if (fabricd_init_c) {
+ fabricd_sync_incomplete |=
+ ISIS_CHECK_FLAG(lsp->SSNflags,
+ fabricd_init_c);
+ fabricd_sync_incomplete |=
+ ISIS_CHECK_FLAG(lsp->SRMflags,
+ fabricd_init_c);
+ }
}
/*
@@ -1915,6 +1928,9 @@ int lsp_tick(struct thread *thread)
}
}
+ if (fabricd_init_c && !fabricd_sync_incomplete)
+ fabricd_initial_sync_finish(area);
+
list_delete_and_null(&lsp_list);
return ISIS_OK;
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index 5c4e3a35bc..8a5db3c6f9 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -56,6 +56,7 @@
#include "isisd/isis_mt.h"
#include "isisd/isis_tlvs.h"
#include "isisd/isis_errors.h"
+#include "isisd/fabricd.h"
static int ack_lsp(struct isis_lsp_hdr *hdr, struct isis_circuit *circuit,
int level)
@@ -207,6 +208,12 @@ static int process_p2p_hello(struct iih_info *iih)
thread_add_timer(master, isis_adj_expire, adj, (long)adj->hold_time,
&adj->t_expire);
+ /* While fabricds initial sync is in progress, ignore hellos from other
+ * interfaces than the one we are performing the initial sync on. */
+ if (fabricd_initial_sync_is_in_progress(iih->circuit->area)
+ && fabricd_initial_sync_circuit(iih->circuit->area) != iih->circuit)
+ return ISIS_OK;
+
/* 8.2.5.2 a) a match was detected */
if (isis_tlvs_area_addresses_match(iih->tlvs,
iih->circuit->area->area_addrs)) {
@@ -1157,7 +1164,7 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
circuit->u.bc.adjdb[level - 1]))
return ISIS_OK; /* Silently discard */
} else {
- if (!circuit->u.p2p.neighbor) {
+ if (!fabricd && !circuit->u.p2p.neighbor) {
zlog_warn("no p2p neighbor on circuit %s",
circuit->interface->name);
return ISIS_OK; /* Silently discard */
@@ -1582,8 +1589,15 @@ int send_hello(struct isis_circuit *circuit, int level)
&& !circuit->disable_threeway_adj) {
uint32_t ext_circuit_id = circuit->idx;
if (circuit->u.p2p.neighbor) {
+ uint8_t threeway_state;
+
+ if (fabricd_initial_sync_is_in_progress(circuit->area)
+ && fabricd_initial_sync_circuit(circuit->area) != circuit)
+ threeway_state = ISIS_THREEWAY_DOWN;
+ else
+ threeway_state = circuit->u.p2p.neighbor->threeway_state;
isis_tlvs_add_threeway_adj(tlvs,
- circuit->u.p2p.neighbor->threeway_state,
+ threeway_state,
ext_circuit_id,
circuit->u.p2p.neighbor->sysid,
circuit->u.p2p.neighbor->ext_circuit_id);
@@ -1889,8 +1903,9 @@ int send_l1_csnp(struct thread *thread)
circuit->t_send_csnp[0] = NULL;
- if (circuit->circ_type == CIRCUIT_T_BROADCAST
- && circuit->u.bc.is_dr[0]) {
+ if ((circuit->circ_type == CIRCUIT_T_BROADCAST
+ && circuit->u.bc.is_dr[0])
+ || circuit->circ_type == CIRCUIT_T_P2P) {
send_csnp(circuit, 1);
}
/* set next timer thread */
@@ -1911,8 +1926,9 @@ int send_l2_csnp(struct thread *thread)
circuit->t_send_csnp[1] = NULL;
- if (circuit->circ_type == CIRCUIT_T_BROADCAST
- && circuit->u.bc.is_dr[1]) {
+ if ((circuit->circ_type == CIRCUIT_T_BROADCAST
+ && circuit->u.bc.is_dr[1])
+ || circuit->circ_type == CIRCUIT_T_P2P) {
send_csnp(circuit, 2);
}
/* set next timer thread */
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 609ca450df..e8efa391e0 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -56,6 +56,7 @@
#include "isisd/isis_events.h"
#include "isisd/isis_te.h"
#include "isisd/isis_mt.h"
+#include "isisd/fabricd.h"
struct isis *isis = NULL;
@@ -95,6 +96,7 @@ void isis_new(unsigned long process_id)
*/
/* isis->debugs = 0xFFFF; */
isisMplsTE.status = disable; /* Only support TE metric */
+
QOBJ_REG(isis, isis);
}
@@ -156,6 +158,8 @@ struct isis_area *isis_area_create(const char *area_tag)
listnode_add(isis->area_list, area);
area->isis = isis;
+ if (fabricd)
+ area->fabricd = fabricd_new();
QOBJ_REG(area, isis_area);
return area;
diff --git a/isisd/isisd.h b/isisd/isisd.h
index b76b0b7847..0e75b870a5 100644
--- a/isisd/isisd.h
+++ b/isisd/isisd.h
@@ -57,6 +57,8 @@ extern struct zebra_privs_t isisd_privs;
/* #define EXTREME_DEBUG */
/* #define EXTREME_DICT_DEBUG */
+struct fabricd;
+
struct isis {
unsigned long process_id;
int sysid_set;
@@ -111,6 +113,8 @@ struct isis_area {
*/
int lsp_regenerate_pending[ISIS_LEVELS];
+ struct fabricd *fabricd;
+
/*
* Configurables
*/
diff --git a/isisd/subdir.am b/isisd/subdir.am
index 5593f2a4ed..cd8bfdbddc 100644
--- a/isisd/subdir.am
+++ b/isisd/subdir.am
@@ -43,6 +43,7 @@ noinst_HEADERS += \
isisd/isis_zebra.h \
isisd/isisd.h \
isisd/iso_checksum.h \
+ isisd/fabricd.h \
# end
LIBISIS_SOURCES = \
@@ -71,6 +72,7 @@ LIBISIS_SOURCES = \
isisd/isis_zebra.c \
isisd/isisd.c \
isisd/iso_checksum.c \
+ isisd/fabricd.c \
# end
ISIS_SOURCES = \