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>
This commit is contained in:
Christian Franke 2018-05-31 15:14:26 +02:00
parent 5f77d90188
commit 2c92bee499
8 changed files with 82 additions and 17 deletions

View File

@ -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

View File

@ -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]);

View File

@ -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),

View File

@ -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));
}
}

View File

@ -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

View File

@ -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);

View File

@ -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]

View File

@ -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]