summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Franke <chris@opensourcerouting.org>2018-05-31 15:14:26 +0200
committerChristian Franke <chris@opensourcerouting.org>2018-09-05 11:38:13 +0200
commit2c92bee49943b5703e183387ac0dd636a9c0e4c4 (patch)
treea6bb53b7ab93caae0b7713f1cdae0ed7681860da
parent5f77d90188278673764eb63d3210b38dc42924b0 (diff)
isisd: add purge originator identification support
Implement RFC 6232, optionally allowing to flood isisd's NET and hostname in purges it originates. Signed-off-by: Christian Franke <chris@opensourcerouting.org>
-rw-r--r--doc/user/isisd.rst8
-rw-r--r--isisd/isis_lsp.c48
-rw-r--r--isisd/isis_pdu.c3
-rw-r--r--isisd/isis_tlvs.c17
-rw-r--r--isisd/isis_tlvs.h4
-rw-r--r--isisd/isis_vty_common.c14
-rw-r--r--isisd/isisd.c4
-rw-r--r--isisd/isisd.h1
8 files changed, 82 insertions, 17 deletions
diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst
index 54f82f6832..ee681858d1 100644
--- a/doc/user/isisd.rst
+++ b/doc/user/isisd.rst
@@ -106,6 +106,14 @@ writing, *isisd* does not support multiple ISIS processes.
Set overload bit to avoid any transit traffic.
+.. index:: purge-originator
+.. clicmd:: purge-originator
+
+.. index:: no purge-originator
+.. clicmd:: no purge-originator
+
+ Enable or disable :rfc:`6232` purge originator identification.
+
.. _isis-timer:
ISIS Timer
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index dc38737923..e8777e9b53 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -353,7 +353,21 @@ void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno)
isis_spf_schedule(lsp->area, lsp->level);
}
-static void lsp_purge(struct isis_lsp *lsp, int level)
+static void lsp_purge_add_poi(struct isis_lsp *lsp,
+ const uint8_t *sender)
+{
+ if (!lsp->area->purge_originator)
+ return;
+
+ /* add purge originator identification */
+ if (!lsp->tlvs)
+ lsp->tlvs = isis_alloc_tlvs();
+ isis_tlvs_set_purge_originator(lsp->tlvs, isis->sysid, sender);
+ isis_tlvs_set_dynamic_hostname(lsp->tlvs, cmd_hostname_get());
+}
+
+static void lsp_purge(struct isis_lsp *lsp, int level,
+ const uint8_t *sender)
{
/* reset stream */
lsp_clear_data(lsp);
@@ -365,6 +379,8 @@ static void lsp_purge(struct isis_lsp *lsp, int level)
lsp->level = level;
lsp->age_out = lsp->area->max_lsp_lifetime[level - 1];
+ lsp_purge_add_poi(lsp, sender);
+
lsp_pack_pdu(lsp);
lsp_flood(lsp, NULL);
}
@@ -386,7 +402,7 @@ static void lsp_seqno_update(struct isis_lsp *lsp0)
if (lsp->tlvs)
lsp_inc_seqno(lsp, 0);
else
- lsp_purge(lsp, lsp0->level);
+ lsp_purge(lsp, lsp0->level, NULL);
}
return;
@@ -426,7 +442,8 @@ static void lsp_update_data(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr,
lsp->tlvs = tlvs;
- if (area->dynhostname && lsp->tlvs->hostname) {
+ if (area->dynhostname && lsp->tlvs->hostname
+ && lsp->hdr.rem_lifetime) {
isis_dynhn_insert(lsp->hdr.lsp_id, lsp->tlvs->hostname,
(lsp->hdr.lsp_bits & LSPBIT_IST)
== IS_LEVEL_1_AND_2
@@ -463,10 +480,10 @@ void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr,
lsp->own_lsp = 0;
}
- lsp_update_data(lsp, hdr, tlvs, stream, area, level);
if (confusion) {
- lsp->hdr.rem_lifetime = hdr->rem_lifetime = 0;
- put_lsp_hdr(lsp, NULL, true);
+ lsp_purge(lsp, level, NULL);
+ } else {
+ lsp_update_data(lsp, hdr, tlvs, stream, area, level);
}
if (LSP_FRAGMENT(lsp->hdr.lsp_id) && !lsp->lspu.zero_lsp) {
@@ -1865,17 +1882,14 @@ int lsp_tick(struct thread *thread)
*/
if (rem_lifetime == 1 && lsp->hdr.seqno != 0) {
/* 7.3.16.4 a) set SRM flags on all */
- lsp_flood(lsp, NULL);
- /* 7.3.16.4 b) retain only the header
- * FIXME */
+ /* 7.3.16.4 b) retain only the header */
+ if (lsp->area->purge_originator)
+ lsp_purge(lsp, lsp->level, NULL);
+ else
+ lsp_flood(lsp, NULL);
/* 7.3.16.4 c) record the time to purge
* FIXME */
- /* run/schedule spf */
- /* isis_spf_schedule is called inside
- * lsp_destroy() below;
- * so it is not needed here. */
- /* isis_spf_schedule (lsp->area,
- * lsp->level); */
+ isis_spf_schedule(lsp->area, lsp->level);
}
if (lsp->age_out == 0) {
@@ -1917,7 +1931,7 @@ void lsp_purge_pseudo(uint8_t *id, struct isis_circuit *circuit, int level)
if (!lsp)
return;
- lsp_purge(lsp, level);
+ lsp_purge(lsp, level, NULL);
}
/*
@@ -1941,6 +1955,8 @@ void lsp_purge_non_exist(int level, struct isis_lsp_hdr *hdr,
memcpy(&lsp->hdr, hdr, sizeof(lsp->hdr));
lsp->hdr.rem_lifetime = 0;
+ lsp_purge_add_poi(lsp, NULL);
+
lsp_pack_pdu(lsp);
lsp_insert(lsp, area->lspdb[lsp->level - 1]);
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index ce050a0c93..8649c5a0c8 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -900,7 +900,8 @@ dontcheckadj:
* but
* wrong checksum, initiate a purge. */
if (lsp && (lsp->hdr.seqno == hdr.seqno)
- && (lsp->hdr.checksum != hdr.checksum)) {
+ && (lsp->hdr.checksum != hdr.checksum)
+ && hdr.rem_lifetime) {
zlog_warn("ISIS-Upd (%s): LSP %s seq 0x%08" PRIx32
" with confused checksum received.",
circuit->area->area_tag, rawlspid_print(hdr.lsp_id),
diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c
index 0efe52d0c1..b22460a0b5 100644
--- a/isisd/isis_tlvs.c
+++ b/isisd/isis_tlvs.c
@@ -3697,3 +3697,20 @@ isis_tlvs_lookup_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid)
return NULL;
}
+
+void isis_tlvs_set_purge_originator(struct isis_tlvs *tlvs,
+ const uint8_t *generator,
+ const uint8_t *sender)
+{
+ assert(!tlvs->purge_originator);
+
+ tlvs->purge_originator = XCALLOC(MTYPE_ISIS_TLV,
+ sizeof(*tlvs->purge_originator));
+ memcpy(tlvs->purge_originator->generator, generator,
+ sizeof(tlvs->purge_originator->generator));
+ if (sender) {
+ tlvs->purge_originator->sender_set = true;
+ memcpy(tlvs->purge_originator->sender, sender,
+ sizeof(tlvs->purge_originator->sender));
+ }
+}
diff --git a/isisd/isis_tlvs.h b/isisd/isis_tlvs.h
index abdd03f02d..4144809fa3 100644
--- a/isisd/isis_tlvs.h
+++ b/isisd/isis_tlvs.h
@@ -383,4 +383,8 @@ void isis_tlvs_add_spine_leaf(struct isis_tlvs *tlvs, uint8_t tier,
struct isis_mt_router_info *
isis_tlvs_lookup_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid);
+
+void isis_tlvs_set_purge_originator(struct isis_tlvs *tlvs,
+ const uint8_t *generator,
+ const uint8_t *sender);
#endif
diff --git a/isisd/isis_vty_common.c b/isisd/isis_vty_common.c
index dbe5beca6e..2b98a88b34 100644
--- a/isisd/isis_vty_common.c
+++ b/isisd/isis_vty_common.c
@@ -568,6 +568,18 @@ DEFUN (no_area_lsp_mtu,
return isis_vty_lsp_mtu_set(vty, DEFAULT_LSP_MTU);
}
+DEFUN (area_purge_originator,
+ area_purge_originator_cmd,
+ "[no] purge-originator",
+ NO_STR
+ "Use the RFC 6232 purge-originator\n")
+{
+ VTY_DECLVAR_CONTEXT(isis_area, area);
+
+ area->purge_originator = !!strcmp(argv[0]->text, "no");
+ return CMD_SUCCESS;
+}
+
int isis_vty_lsp_gen_interval_set(struct vty *vty, int level, uint16_t interval)
{
VTY_DECLVAR_CONTEXT(isis_area, area);
@@ -924,6 +936,8 @@ void isis_vty_init(void)
install_element(ROUTER_NODE, &area_lsp_mtu_cmd);
install_element(ROUTER_NODE, &no_area_lsp_mtu_cmd);
+ install_element(ROUTER_NODE, &area_purge_originator_cmd);
+
install_element(ROUTER_NODE, &lsp_gen_interval_cmd);
install_element(ROUTER_NODE, &no_lsp_gen_interval_cmd);
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 640bd69ce4..e3ff3b8d93 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -2029,6 +2029,10 @@ int isis_config_write(struct vty *vty)
vty_out(vty, " lsp-mtu %u\n", area->lsp_mtu);
write++;
}
+ if (area->purge_originator) {
+ vty_out(vty, " purge-originator\n");
+ write++;
+ }
/* Minimum SPF interval. */
if (area->min_spf_interval[0]
diff --git a/isisd/isisd.h b/isisd/isisd.h
index cc5def8f56..864021428a 100644
--- a/isisd/isisd.h
+++ b/isisd/isisd.h
@@ -148,6 +148,7 @@ struct isis_area {
/* multi topology settings */
struct list *mt_settings;
int ipv6_circuits;
+ bool purge_originator;
/* Counters */
uint32_t circuit_state_changes;
struct isis_redist redist_settings[REDIST_PROTOCOL_COUNT]