From 2c92bee49943b5703e183387ac0dd636a9c0e4c4 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Thu, 31 May 2018 15:14:26 +0200 Subject: [PATCH] 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 --- doc/user/isisd.rst | 8 +++++++ isisd/isis_lsp.c | 48 +++++++++++++++++++++++++++-------------- isisd/isis_pdu.c | 3 ++- isisd/isis_tlvs.c | 17 +++++++++++++++ isisd/isis_tlvs.h | 4 ++++ isisd/isis_vty_common.c | 14 ++++++++++++ isisd/isisd.c | 4 ++++ isisd/isisd.h | 1 + 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] -- 2.39.5