summaryrefslogtreecommitdiffstats
path: root/isisd/isis_lsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'isisd/isis_lsp.c')
-rw-r--r--isisd/isis_lsp.c4950
1 files changed, 2528 insertions, 2422 deletions
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index f7ed23aa3..3fb423a2c 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -3,22 +3,22 @@
* LSP processing
*
* Copyright (C) 2001,2002 Sampo Saaristo
- * Tampere University of Technology
+ * Tampere University of Technology
* Institute of Communications Engineering
* Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
*
- * This program 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 of the License, or (at your option)
+ * This program 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 of the License, or (at your option)
* any later version.
*
- * This program 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
+ * This program 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; if not, write to the Free Software Foundation, Inc.,
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
@@ -55,2063 +55,2138 @@
#include "isisd/isis_te.h"
/* staticly assigned vars for printing purposes */
-char lsp_bits_string[200]; /* FIXME: enough ? */
+char lsp_bits_string[200]; /* FIXME: enough ? */
-static int lsp_l1_refresh (struct thread *thread);
-static int lsp_l2_refresh (struct thread *thread);
-static int lsp_l1_refresh_pseudo (struct thread *thread);
-static int lsp_l2_refresh_pseudo (struct thread *thread);
+static int lsp_l1_refresh(struct thread *thread);
+static int lsp_l2_refresh(struct thread *thread);
+static int lsp_l1_refresh_pseudo(struct thread *thread);
+static int lsp_l2_refresh_pseudo(struct thread *thread);
-int
-lsp_id_cmp (u_char * id1, u_char * id2)
+int lsp_id_cmp(u_char *id1, u_char *id2)
{
- return memcmp (id1, id2, ISIS_SYS_ID_LEN + 2);
+ return memcmp(id1, id2, ISIS_SYS_ID_LEN + 2);
}
-dict_t *
-lsp_db_init (void)
+dict_t *lsp_db_init(void)
{
- dict_t *dict;
+ dict_t *dict;
- dict = dict_create (DICTCOUNT_T_MAX, (dict_comp_t) lsp_id_cmp);
+ dict = dict_create(DICTCOUNT_T_MAX, (dict_comp_t)lsp_id_cmp);
- return dict;
+ return dict;
}
-struct isis_lsp *
-lsp_search (u_char * id, dict_t * lspdb)
+struct isis_lsp *lsp_search(u_char *id, dict_t *lspdb)
{
- dnode_t *node;
+ dnode_t *node;
#ifdef EXTREME_DEBUG
- dnode_t *dn;
-
- zlog_debug ("searching db");
- for (dn = dict_first (lspdb); dn; dn = dict_next (lspdb, dn))
- {
- zlog_debug ("%s\t%pX", rawlspid_print ((u_char *) dnode_getkey (dn)),
- dnode_get (dn));
- }
+ dnode_t *dn;
+
+ zlog_debug("searching db");
+ for (dn = dict_first(lspdb); dn; dn = dict_next(lspdb, dn)) {
+ zlog_debug("%s\t%pX",
+ rawlspid_print((u_char *)dnode_getkey(dn)),
+ dnode_get(dn));
+ }
#endif /* EXTREME DEBUG */
- node = dict_lookup (lspdb, id);
+ node = dict_lookup(lspdb, id);
- if (node)
- return (struct isis_lsp *) dnode_get (node);
+ if (node)
+ return (struct isis_lsp *)dnode_get(node);
- return NULL;
+ return NULL;
}
-static void
-lsp_clear_data (struct isis_lsp *lsp)
+static void lsp_clear_data(struct isis_lsp *lsp)
{
- if (!lsp)
- return;
-
- if (lsp->tlv_data.hostname)
- isis_dynhn_remove (lsp->lsp_header->lsp_id);
-
- if (lsp->own_lsp)
- {
- if (lsp->tlv_data.nlpids)
- XFREE (MTYPE_ISIS_TLV, lsp->tlv_data.nlpids);
- if (lsp->tlv_data.hostname)
- XFREE (MTYPE_ISIS_TLV, lsp->tlv_data.hostname);
- if (lsp->tlv_data.router_id)
- XFREE (MTYPE_ISIS_TLV, lsp->tlv_data.router_id);
- }
-
- free_tlvs (&lsp->tlv_data);
+ if (!lsp)
+ return;
+
+ if (lsp->tlv_data.hostname)
+ isis_dynhn_remove(lsp->lsp_header->lsp_id);
+
+ if (lsp->own_lsp) {
+ if (lsp->tlv_data.nlpids)
+ XFREE(MTYPE_ISIS_TLV, lsp->tlv_data.nlpids);
+ if (lsp->tlv_data.hostname)
+ XFREE(MTYPE_ISIS_TLV, lsp->tlv_data.hostname);
+ if (lsp->tlv_data.router_id)
+ XFREE(MTYPE_ISIS_TLV, lsp->tlv_data.router_id);
+ }
+
+ free_tlvs(&lsp->tlv_data);
}
-static void
-lsp_destroy (struct isis_lsp *lsp)
+static void lsp_destroy(struct isis_lsp *lsp)
{
- struct listnode *cnode, *lnode, *lnnode;
- struct isis_lsp *lsp_in_list;
- struct isis_circuit *circuit;
-
- if (!lsp)
- return;
-
- if (lsp->area->circuit_list) {
- for (ALL_LIST_ELEMENTS_RO (lsp->area->circuit_list, cnode, circuit))
- {
- if (circuit->lsp_queue == NULL)
- continue;
- for (ALL_LIST_ELEMENTS (circuit->lsp_queue, lnode, lnnode, lsp_in_list))
- if (lsp_in_list == lsp)
- list_delete_node(circuit->lsp_queue, lnode);
- }
- }
- ISIS_FLAGS_CLEAR_ALL (lsp->SSNflags);
- ISIS_FLAGS_CLEAR_ALL (lsp->SRMflags);
-
- lsp_clear_data (lsp);
-
- if (LSP_FRAGMENT (lsp->lsp_header->lsp_id) == 0 && lsp->lspu.frags)
- {
- list_delete (lsp->lspu.frags);
- lsp->lspu.frags = NULL;
- }
-
- isis_spf_schedule (lsp->area, lsp->level);
-
- if (lsp->pdu)
- stream_free (lsp->pdu);
- XFREE (MTYPE_ISIS_LSP, lsp);
+ struct listnode *cnode, *lnode, *lnnode;
+ struct isis_lsp *lsp_in_list;
+ struct isis_circuit *circuit;
+
+ if (!lsp)
+ return;
+
+ if (lsp->area->circuit_list) {
+ for (ALL_LIST_ELEMENTS_RO(lsp->area->circuit_list, cnode,
+ circuit)) {
+ if (circuit->lsp_queue == NULL)
+ continue;
+ for (ALL_LIST_ELEMENTS(circuit->lsp_queue, lnode,
+ lnnode, lsp_in_list))
+ if (lsp_in_list == lsp)
+ list_delete_node(circuit->lsp_queue,
+ lnode);
+ }
+ }
+ ISIS_FLAGS_CLEAR_ALL(lsp->SSNflags);
+ ISIS_FLAGS_CLEAR_ALL(lsp->SRMflags);
+
+ lsp_clear_data(lsp);
+
+ if (LSP_FRAGMENT(lsp->lsp_header->lsp_id) == 0 && lsp->lspu.frags) {
+ list_delete(lsp->lspu.frags);
+ lsp->lspu.frags = NULL;
+ }
+
+ isis_spf_schedule(lsp->area, lsp->level);
+
+ if (lsp->pdu)
+ stream_free(lsp->pdu);
+ XFREE(MTYPE_ISIS_LSP, lsp);
}
-void
-lsp_db_destroy (dict_t * lspdb)
+void lsp_db_destroy(dict_t *lspdb)
{
- dnode_t *dnode, *next;
- struct isis_lsp *lsp;
-
- dnode = dict_first (lspdb);
- while (dnode)
- {
- next = dict_next (lspdb, dnode);
- lsp = dnode_get (dnode);
- lsp_destroy (lsp);
- dict_delete_free (lspdb, dnode);
- dnode = next;
- }
-
- dict_free (lspdb);
-
- return;
+ dnode_t *dnode, *next;
+ struct isis_lsp *lsp;
+
+ dnode = dict_first(lspdb);
+ while (dnode) {
+ next = dict_next(lspdb, dnode);
+ lsp = dnode_get(dnode);
+ lsp_destroy(lsp);
+ dict_delete_free(lspdb, dnode);
+ dnode = next;
+ }
+
+ dict_free(lspdb);
+
+ return;
}
/*
* Remove all the frags belonging to the given lsp
*/
-static void
-lsp_remove_frags (struct list *frags, dict_t * lspdb)
+static void lsp_remove_frags(struct list *frags, dict_t *lspdb)
{
- dnode_t *dnode;
- struct listnode *lnode, *lnnode;
- struct isis_lsp *lsp;
-
- for (ALL_LIST_ELEMENTS (frags, lnode, lnnode, lsp))
- {
- dnode = dict_lookup (lspdb, lsp->lsp_header->lsp_id);
- lsp_destroy (lsp);
- dnode_destroy (dict_delete (lspdb, dnode));
- }
+ dnode_t *dnode;
+ struct listnode *lnode, *lnnode;
+ struct isis_lsp *lsp;
+
+ for (ALL_LIST_ELEMENTS(frags, lnode, lnnode, lsp)) {
+ dnode = dict_lookup(lspdb, lsp->lsp_header->lsp_id);
+ lsp_destroy(lsp);
+ dnode_destroy(dict_delete(lspdb, dnode));
+ }
- list_delete_all_node (frags);
+ list_delete_all_node(frags);
- return;
+ return;
}
-void
-lsp_search_and_destroy (u_char * id, dict_t * lspdb)
+void lsp_search_and_destroy(u_char *id, dict_t *lspdb)
{
- dnode_t *node;
- struct isis_lsp *lsp;
-
- node = dict_lookup (lspdb, id);
- if (node)
- {
- node = dict_delete (lspdb, node);
- lsp = dnode_get (node);
- /*
- * If this is a zero lsp, remove all the frags now
- */
- if (LSP_FRAGMENT (lsp->lsp_header->lsp_id) == 0)
- {
- if (lsp->lspu.frags)
- lsp_remove_frags (lsp->lspu.frags, lspdb);
- }
- else
- {
- /*
- * else just remove this frag, from the zero lsps' frag list
- */
- if (lsp->lspu.zero_lsp && lsp->lspu.zero_lsp->lspu.frags)
- listnode_delete (lsp->lspu.zero_lsp->lspu.frags, lsp);
+ dnode_t *node;
+ struct isis_lsp *lsp;
+
+ node = dict_lookup(lspdb, id);
+ if (node) {
+ node = dict_delete(lspdb, node);
+ lsp = dnode_get(node);
+ /*
+ * If this is a zero lsp, remove all the frags now
+ */
+ if (LSP_FRAGMENT(lsp->lsp_header->lsp_id) == 0) {
+ if (lsp->lspu.frags)
+ lsp_remove_frags(lsp->lspu.frags, lspdb);
+ } else {
+ /*
+ * else just remove this frag, from the zero lsps' frag
+ * list
+ */
+ if (lsp->lspu.zero_lsp
+ && lsp->lspu.zero_lsp->lspu.frags)
+ listnode_delete(lsp->lspu.zero_lsp->lspu.frags,
+ lsp);
+ }
+ lsp_destroy(lsp);
+ dnode_destroy(node);
}
- lsp_destroy (lsp);
- dnode_destroy (node);
- }
}
/*
* Compares a LSP to given values
* Params are given in net order
*/
-int
-lsp_compare (char *areatag, struct isis_lsp *lsp, u_int32_t seq_num,
- u_int16_t checksum, u_int16_t rem_lifetime)
+int lsp_compare(char *areatag, struct isis_lsp *lsp, u_int32_t seq_num,
+ u_int16_t checksum, u_int16_t rem_lifetime)
{
- /* no point in double ntohl on seqnum */
- if (lsp->lsp_header->seq_num == seq_num &&
- lsp->lsp_header->checksum == checksum &&
- /*comparing with 0, no need to do ntohl */
- ((lsp->lsp_header->rem_lifetime == 0 && rem_lifetime == 0) ||
- (lsp->lsp_header->rem_lifetime != 0 && rem_lifetime != 0)))
- {
- if (isis->debugs & DEBUG_SNP_PACKETS)
- {
- zlog_debug ("ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04x,"
- " lifetime %us",
- areatag,
- rawlspid_print (lsp->lsp_header->lsp_id),
- ntohl (lsp->lsp_header->seq_num),
- ntohs (lsp->lsp_header->checksum),
- ntohs (lsp->lsp_header->rem_lifetime));
- zlog_debug ("ISIS-Snp (%s): is equal to ours seq 0x%08x,"
- " cksum 0x%04x, lifetime %us",
- areatag,
- ntohl (seq_num), ntohs (checksum), ntohs (rem_lifetime));
+ /* no point in double ntohl on seqnum */
+ if (lsp->lsp_header->seq_num == seq_num
+ && lsp->lsp_header->checksum == checksum &&
+ /*comparing with 0, no need to do ntohl */
+ ((lsp->lsp_header->rem_lifetime == 0 && rem_lifetime == 0)
+ || (lsp->lsp_header->rem_lifetime != 0 && rem_lifetime != 0))) {
+ if (isis->debugs & DEBUG_SNP_PACKETS) {
+ zlog_debug(
+ "ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04x,"
+ " lifetime %us",
+ areatag,
+ rawlspid_print(lsp->lsp_header->lsp_id),
+ ntohl(lsp->lsp_header->seq_num),
+ ntohs(lsp->lsp_header->checksum),
+ ntohs(lsp->lsp_header->rem_lifetime));
+ zlog_debug(
+ "ISIS-Snp (%s): is equal to ours seq 0x%08x,"
+ " cksum 0x%04x, lifetime %us",
+ areatag, ntohl(seq_num), ntohs(checksum),
+ ntohs(rem_lifetime));
+ }
+ return LSP_EQUAL;
+ }
+
+ /*
+ * LSPs with identical checksums should only be treated as newer if:
+ * a) The current LSP has a remaining lifetime != 0 and the other LSP
+ * has a
+ * remaining lifetime == 0. In this case, we should participate in
+ * the purge
+ * and should not treat the current LSP with remaining lifetime == 0
+ * as older.
+ * b) The LSP has an incorrect checksum. In this case, we need to react
+ * as given
+ * in 7.3.16.2.
+ */
+ if (ntohl(seq_num) > ntohl(lsp->lsp_header->seq_num)
+ || (ntohl(seq_num) == ntohl(lsp->lsp_header->seq_num)
+ && ((lsp->lsp_header->rem_lifetime != 0 && rem_lifetime == 0)
+ || lsp->lsp_header->checksum != checksum))) {
+ if (isis->debugs & DEBUG_SNP_PACKETS) {
+ zlog_debug(
+ "ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04x,"
+ " lifetime %us",
+ areatag,
+ rawlspid_print(lsp->lsp_header->lsp_id),
+ ntohl(seq_num), ntohs(checksum),
+ ntohs(rem_lifetime));
+ zlog_debug(
+ "ISIS-Snp (%s): is newer than ours seq 0x%08x, "
+ "cksum 0x%04x, lifetime %us",
+ areatag, ntohl(lsp->lsp_header->seq_num),
+ ntohs(lsp->lsp_header->checksum),
+ ntohs(lsp->lsp_header->rem_lifetime));
+ }
+ return LSP_NEWER;
}
- return LSP_EQUAL;
- }
-
- /*
- * LSPs with identical checksums should only be treated as newer if:
- * a) The current LSP has a remaining lifetime != 0 and the other LSP has a
- * remaining lifetime == 0. In this case, we should participate in the purge
- * and should not treat the current LSP with remaining lifetime == 0 as older.
- * b) The LSP has an incorrect checksum. In this case, we need to react as given
- * in 7.3.16.2.
- */
- if (ntohl (seq_num) > ntohl (lsp->lsp_header->seq_num)
- || (ntohl(seq_num) == ntohl(lsp->lsp_header->seq_num)
- && ( (lsp->lsp_header->rem_lifetime != 0
- && rem_lifetime == 0)
- || lsp->lsp_header->checksum != checksum)))
- {
- if (isis->debugs & DEBUG_SNP_PACKETS)
- {
- zlog_debug ("ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04x,"
- " lifetime %us",
- areatag,
- rawlspid_print (lsp->lsp_header->lsp_id),
- ntohl (seq_num), ntohs (checksum), ntohs (rem_lifetime));
- zlog_debug ("ISIS-Snp (%s): is newer than ours seq 0x%08x, "
- "cksum 0x%04x, lifetime %us",
- areatag,
- ntohl (lsp->lsp_header->seq_num),
- ntohs (lsp->lsp_header->checksum),
- ntohs (lsp->lsp_header->rem_lifetime));
+ if (isis->debugs & DEBUG_SNP_PACKETS) {
+ zlog_debug(
+ "ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04x, lifetime %us",
+ areatag, rawlspid_print(lsp->lsp_header->lsp_id),
+ ntohl(seq_num), ntohs(checksum), ntohs(rem_lifetime));
+ zlog_debug(
+ "ISIS-Snp (%s): is older than ours seq 0x%08x,"
+ " cksum 0x%04x, lifetime %us",
+ areatag, ntohl(lsp->lsp_header->seq_num),
+ ntohs(lsp->lsp_header->checksum),
+ ntohs(lsp->lsp_header->rem_lifetime));
}
- return LSP_NEWER;
- }
- if (isis->debugs & DEBUG_SNP_PACKETS)
- {
- zlog_debug
- ("ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04x, lifetime %us",
- areatag, rawlspid_print (lsp->lsp_header->lsp_id), ntohl (seq_num),
- ntohs (checksum), ntohs (rem_lifetime));
- zlog_debug ("ISIS-Snp (%s): is older than ours seq 0x%08x,"
- " cksum 0x%04x, lifetime %us", areatag,
- ntohl (lsp->lsp_header->seq_num),
- ntohs (lsp->lsp_header->checksum),
- ntohs (lsp->lsp_header->rem_lifetime));
- }
-
- return LSP_OLDER;
+
+ return LSP_OLDER;
}
-static void
-lsp_auth_add (struct isis_lsp *lsp)
+static void lsp_auth_add(struct isis_lsp *lsp)
{
- struct isis_passwd *passwd;
- unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE];
-
- /*
- * Add the authentication info if its present
- */
- (lsp->level == IS_LEVEL_1) ? (passwd = &lsp->area->area_passwd) :
- (passwd = &lsp->area->domain_passwd);
- switch (passwd->type)
- {
- /* Cleartext */
- case ISIS_PASSWD_TYPE_CLEARTXT:
- memcpy (&lsp->tlv_data.auth_info, passwd, sizeof (struct isis_passwd));
- tlv_add_authinfo (passwd->type, passwd->len, passwd->passwd, lsp->pdu);
- break;
-
- /* HMAC MD5 */
- case ISIS_PASSWD_TYPE_HMAC_MD5:
- /* Remember where TLV is written so we can later
- * overwrite the MD5 hash */
- lsp->auth_tlv_offset = stream_get_endp (lsp->pdu);
- memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE);
- lsp->tlv_data.auth_info.type = ISIS_PASSWD_TYPE_HMAC_MD5;
- lsp->tlv_data.auth_info.len = ISIS_AUTH_MD5_SIZE;
- memcpy (&lsp->tlv_data.auth_info.passwd, hmac_md5_hash,
- ISIS_AUTH_MD5_SIZE);
- tlv_add_authinfo (passwd->type, ISIS_AUTH_MD5_SIZE, hmac_md5_hash,
- lsp->pdu);
- break;
-
- default:
- break;
- }
+ struct isis_passwd *passwd;
+ unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE];
+
+ /*
+ * Add the authentication info if its present
+ */
+ (lsp->level == IS_LEVEL_1) ? (passwd = &lsp->area->area_passwd)
+ : (passwd = &lsp->area->domain_passwd);
+ switch (passwd->type) {
+ /* Cleartext */
+ case ISIS_PASSWD_TYPE_CLEARTXT:
+ memcpy(&lsp->tlv_data.auth_info, passwd,
+ sizeof(struct isis_passwd));
+ tlv_add_authinfo(passwd->type, passwd->len, passwd->passwd,
+ lsp->pdu);
+ break;
+
+ /* HMAC MD5 */
+ case ISIS_PASSWD_TYPE_HMAC_MD5:
+ /* Remember where TLV is written so we can later
+ * overwrite the MD5 hash */
+ lsp->auth_tlv_offset = stream_get_endp(lsp->pdu);
+ memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE);
+ lsp->tlv_data.auth_info.type = ISIS_PASSWD_TYPE_HMAC_MD5;
+ lsp->tlv_data.auth_info.len = ISIS_AUTH_MD5_SIZE;
+ memcpy(&lsp->tlv_data.auth_info.passwd, hmac_md5_hash,
+ ISIS_AUTH_MD5_SIZE);
+ tlv_add_authinfo(passwd->type, ISIS_AUTH_MD5_SIZE,
+ hmac_md5_hash, lsp->pdu);
+ break;
+
+ default:
+ break;
+ }
}
-static void
-lsp_auth_update (struct isis_lsp *lsp)
+static void lsp_auth_update(struct isis_lsp *lsp)
{
- struct isis_passwd *passwd;
- unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE];
- uint16_t checksum, rem_lifetime;
-
- /* For HMAC MD5 we need to recompute the md5 hash and store it */
- (lsp->level == IS_LEVEL_1) ? (passwd = &lsp->area->area_passwd) :
- (passwd = &lsp->area->domain_passwd);
- if (passwd->type != ISIS_PASSWD_TYPE_HMAC_MD5)
- return;
-
- /*
- * In transient conditions (when net is configured where authentication
- * config and lsp regenerate schedule is not yet run), there could be
- * an own_lsp with auth_tlv_offset set to 0. In such a case, simply
- * return, when lsp_regenerate is run, lsp will have auth tlv.
- */
- if (lsp->auth_tlv_offset == 0)
- return;
-
- /*
- * RFC 5304 set auth value, checksum and remaining lifetime to zero
- * before computation and reset to old values after computation.
- */
- checksum = lsp->lsp_header->checksum;
- rem_lifetime = lsp->lsp_header->rem_lifetime;
- lsp->lsp_header->checksum = 0;
- lsp->lsp_header->rem_lifetime = 0;
- /* Set the authentication value as well to zero */
- memset (STREAM_DATA (lsp->pdu) + lsp->auth_tlv_offset + 3,
- 0, ISIS_AUTH_MD5_SIZE);
- /* Compute autentication value */
- hmac_md5 (STREAM_DATA (lsp->pdu), stream_get_endp(lsp->pdu),
- (unsigned char *) &passwd->passwd, passwd->len,
- (unsigned char *) &hmac_md5_hash);
- /* Copy the hash into the stream */
- memcpy (STREAM_DATA (lsp->pdu) + lsp->auth_tlv_offset + 3,
- hmac_md5_hash, ISIS_AUTH_MD5_SIZE);
- memcpy (&lsp->tlv_data.auth_info.passwd, hmac_md5_hash,
- ISIS_AUTH_MD5_SIZE);
- /* Copy back the checksum and remaining lifetime */
- lsp->lsp_header->checksum = checksum;
- lsp->lsp_header->rem_lifetime = rem_lifetime;
+ struct isis_passwd *passwd;
+ unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE];
+ uint16_t checksum, rem_lifetime;
+
+ /* For HMAC MD5 we need to recompute the md5 hash and store it */
+ (lsp->level == IS_LEVEL_1) ? (passwd = &lsp->area->area_passwd)
+ : (passwd = &lsp->area->domain_passwd);
+ if (passwd->type != ISIS_PASSWD_TYPE_HMAC_MD5)
+ return;
+
+ /*
+ * In transient conditions (when net is configured where authentication
+ * config and lsp regenerate schedule is not yet run), there could be
+ * an own_lsp with auth_tlv_offset set to 0. In such a case, simply
+ * return, when lsp_regenerate is run, lsp will have auth tlv.
+ */
+ if (lsp->auth_tlv_offset == 0)
+ return;
+
+ /*
+ * RFC 5304 set auth value, checksum and remaining lifetime to zero
+ * before computation and reset to old values after computation.
+ */
+ checksum = lsp->lsp_header->checksum;
+ rem_lifetime = lsp->lsp_header->rem_lifetime;
+ lsp->lsp_header->checksum = 0;
+ lsp->lsp_header->rem_lifetime = 0;
+ /* Set the authentication value as well to zero */
+ memset(STREAM_DATA(lsp->pdu) + lsp->auth_tlv_offset + 3, 0,
+ ISIS_AUTH_MD5_SIZE);
+ /* Compute autentication value */
+ hmac_md5(STREAM_DATA(lsp->pdu), stream_get_endp(lsp->pdu),
+ (unsigned char *)&passwd->passwd, passwd->len,
+ (unsigned char *)&hmac_md5_hash);
+ /* Copy the hash into the stream */
+ memcpy(STREAM_DATA(lsp->pdu) + lsp->auth_tlv_offset + 3, hmac_md5_hash,
+ ISIS_AUTH_MD5_SIZE);
+ memcpy(&lsp->tlv_data.auth_info.passwd, hmac_md5_hash,
+ ISIS_AUTH_MD5_SIZE);
+ /* Copy back the checksum and remaining lifetime */
+ lsp->lsp_header->checksum = checksum;
+ lsp->lsp_header->rem_lifetime = rem_lifetime;
}
-void
-lsp_inc_seqnum (struct isis_lsp *lsp, u_int32_t seq_num)
+void lsp_inc_seqnum(struct isis_lsp *lsp, u_int32_t seq_num)
{
- u_int32_t newseq;
-
- if (seq_num == 0 || ntohl (lsp->lsp_header->seq_num) > seq_num)
- newseq = ntohl (lsp->lsp_header->seq_num) + 1;
- else
- newseq = seq_num + 1;
-
- lsp->lsp_header->seq_num = htonl (newseq);
-
- /* Recompute authentication and checksum information */
- lsp_auth_update (lsp);
- /* ISO 10589 - 7.3.11 Generation of the checksum
- * The checksum shall be computed over all fields in the LSP which appear
- * after the Remaining Lifetime field. This field (and those appearing
- * before it) are excluded so that the LSP may be aged by systems without
- * requiring recomputation.
- */
- fletcher_checksum(STREAM_DATA (lsp->pdu) + 12,
- ntohs (lsp->lsp_header->pdu_len) - 12, 12);
-
- isis_spf_schedule (lsp->area, lsp->level);
-
- return;
+ u_int32_t newseq;
+
+ if (seq_num == 0 || ntohl(lsp->lsp_header->seq_num) > seq_num)
+ newseq = ntohl(lsp->lsp_header->seq_num) + 1;
+ else
+ newseq = seq_num + 1;
+
+ lsp->lsp_header->seq_num = htonl(newseq);
+
+ /* Recompute authentication and checksum information */
+ lsp_auth_update(lsp);
+ /* ISO 10589 - 7.3.11 Generation of the checksum
+ * The checksum shall be computed over all fields in the LSP which
+ * appear
+ * after the Remaining Lifetime field. This field (and those appearing
+ * before it) are excluded so that the LSP may be aged by systems
+ * without
+ * requiring recomputation.
+ */
+ fletcher_checksum(STREAM_DATA(lsp->pdu) + 12,
+ ntohs(lsp->lsp_header->pdu_len) - 12, 12);
+
+ isis_spf_schedule(lsp->area, lsp->level);
+
+ return;
}
/*
* Genetates checksum for LSP and its frags
*/
-static void
-lsp_seqnum_update (struct isis_lsp *lsp0)
+static void lsp_seqnum_update(struct isis_lsp *lsp0)
{
- struct isis_lsp *lsp;
- struct listnode *node;
+ struct isis_lsp *lsp;
+ struct listnode *node;
- lsp_inc_seqnum (lsp0, 0);
+ lsp_inc_seqnum(lsp0, 0);
- if (!lsp0->lspu.frags)
- return;
+ if (!lsp0->lspu.frags)
+ return;
- for (ALL_LIST_ELEMENTS_RO (lsp0->lspu.frags, node, lsp))
- lsp_inc_seqnum (lsp, 0);
+ for (ALL_LIST_ELEMENTS_RO(lsp0->lspu.frags, node, lsp))
+ lsp_inc_seqnum(lsp, 0);
- return;
+ return;
}
-static u_int8_t
-lsp_bits_generate (int level, int overload_bit, int attached_bit)
+static u_int8_t lsp_bits_generate(int level, int overload_bit, int attached_bit)
{
- u_int8_t lsp_bits = 0;
- if (level == IS_LEVEL_1)
- lsp_bits = IS_LEVEL_1;
- else
- lsp_bits = IS_LEVEL_1_AND_2;
- if (overload_bit)
- lsp_bits |= overload_bit;
- if (attached_bit)
- lsp_bits |= attached_bit;
- return lsp_bits;
+ u_int8_t lsp_bits = 0;
+ if (level == IS_LEVEL_1)
+ lsp_bits = IS_LEVEL_1;
+ else
+ lsp_bits = IS_LEVEL_1_AND_2;
+ if (overload_bit)
+ lsp_bits |= overload_bit;
+ if (attached_bit)
+ lsp_bits |= attached_bit;
+ return lsp_bits;
}
-static void
-lsp_update_data (struct isis_lsp *lsp, struct stream *stream,
- struct isis_area *area, int level)
+static void lsp_update_data(struct isis_lsp *lsp, struct stream *stream,
+ struct isis_area *area, int level)
{
- uint32_t expected = 0, found;
- int retval;
-
- /* free the old lsp data */
- lsp_clear_data (lsp);
-
- /* copying only the relevant part of our stream */
- if (lsp->pdu != NULL)
- stream_free (lsp->pdu);
- lsp->pdu = stream_dup (stream);
-
- /* setting pointers to the correct place */
- lsp->isis_header = (struct isis_fixed_hdr *) (STREAM_DATA (lsp->pdu));
- lsp->lsp_header = (struct isis_link_state_hdr *) (STREAM_DATA (lsp->pdu) +
- ISIS_FIXED_HDR_LEN);
- lsp->area = area;
- lsp->level = level;
- lsp->age_out = ZERO_AGE_LIFETIME;
- lsp->installed = time (NULL);
- /*
- * Get LSP data i.e. TLVs
- */
- expected |= TLVFLAG_AUTH_INFO;
- expected |= TLVFLAG_AREA_ADDRS;
- expected |= TLVFLAG_IS_NEIGHS;
- expected |= TLVFLAG_NLPID;
- if (area->dynhostname)
- expected |= TLVFLAG_DYN_HOSTNAME;
- if (area->newmetric)
- {
- expected |= TLVFLAG_TE_IS_NEIGHS;
- expected |= TLVFLAG_TE_IPV4_REACHABILITY;
- expected |= TLVFLAG_TE_ROUTER_ID;
- }
- expected |= TLVFLAG_IPV4_ADDR;
- expected |= TLVFLAG_IPV4_INT_REACHABILITY;
- expected |= TLVFLAG_IPV4_EXT_REACHABILITY;
- expected |= TLVFLAG_IPV6_ADDR;
- expected |= TLVFLAG_IPV6_REACHABILITY;
-
- retval = parse_tlvs (area->area_tag, STREAM_DATA (lsp->pdu) +
- ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN,
- ntohs (lsp->lsp_header->pdu_len) -
- ISIS_FIXED_HDR_LEN - ISIS_LSP_HDR_LEN,
- &expected, &found, &lsp->tlv_data,
- NULL);
- if (retval != ISIS_OK)
- {
- zlog_warn ("Could not parse LSP");
- return;
- }
-
- if ((found & TLVFLAG_DYN_HOSTNAME) && (area->dynhostname))
- {
- isis_dynhn_insert (lsp->lsp_header->lsp_id, lsp->tlv_data.hostname,
- (lsp->lsp_header->lsp_bits & LSPBIT_IST) ==
- IS_LEVEL_1_AND_2 ? IS_LEVEL_2 : IS_LEVEL_1);
- }
-
- return;
+ uint32_t expected = 0, found;
+ int retval;
+
+ /* free the old lsp data */
+ lsp_clear_data(lsp);
+
+ /* copying only the relevant part of our stream */
+ if (lsp->pdu != NULL)
+ stream_free(lsp->pdu);
+ lsp->pdu = stream_dup(stream);
+
+ /* setting pointers to the correct place */
+ lsp->isis_header = (struct isis_fixed_hdr *)(STREAM_DATA(lsp->pdu));
+ lsp->lsp_header = (struct isis_link_state_hdr *)(STREAM_DATA(lsp->pdu)
+ + ISIS_FIXED_HDR_LEN);
+ lsp->area = area;
+ lsp->level = level;
+ lsp->age_out = ZERO_AGE_LIFETIME;
+ lsp->installed = time(NULL);
+ /*
+ * Get LSP data i.e. TLVs
+ */
+ expected |= TLVFLAG_AUTH_INFO;
+ expected |= TLVFLAG_AREA_ADDRS;
+ expected |= TLVFLAG_IS_NEIGHS;
+ expected |= TLVFLAG_NLPID;
+ if (area->dynhostname)
+ expected |= TLVFLAG_DYN_HOSTNAME;
+ if (area->newmetric) {
+ expected |= TLVFLAG_TE_IS_NEIGHS;
+ expected |= TLVFLAG_TE_IPV4_REACHABILITY;
+ expected |= TLVFLAG_TE_ROUTER_ID;
+ }
+ expected |= TLVFLAG_IPV4_ADDR;
+ expected |= TLVFLAG_IPV4_INT_REACHABILITY;
+ expected |= TLVFLAG_IPV4_EXT_REACHABILITY;
+ expected |= TLVFLAG_IPV6_ADDR;
+ expected |= TLVFLAG_IPV6_REACHABILITY;
+
+ retval = parse_tlvs(area->area_tag,
+ STREAM_DATA(lsp->pdu) + ISIS_FIXED_HDR_LEN
+ + ISIS_LSP_HDR_LEN,
+ ntohs(lsp->lsp_header->pdu_len) - ISIS_FIXED_HDR_LEN
+ - ISIS_LSP_HDR_LEN,
+ &expected, &found, &lsp->tlv_data, NULL);
+ if (retval != ISIS_OK) {
+ zlog_warn("Could not parse LSP");
+ return;
+ }
+
+ if ((found & TLVFLAG_DYN_HOSTNAME) && (area->dynhostname)) {
+ isis_dynhn_insert(lsp->lsp_header->lsp_id,
+ lsp->tlv_data.hostname,
+ (lsp->lsp_header->lsp_bits & LSPBIT_IST)
+ == IS_LEVEL_1_AND_2
+ ? IS_LEVEL_2
+ : IS_LEVEL_1);
+ }
+
+ return;
}
-void
-lsp_update (struct isis_lsp *lsp, struct stream *stream,
- struct isis_area *area, int level)
+void lsp_update(struct isis_lsp *lsp, struct stream *stream,
+ struct isis_area *area, int level)
{
- dnode_t *dnode = NULL;
-
- /* Remove old LSP from database. This is required since the
- * lsp_update_data will free the lsp->pdu (which has the key, lsp_id)
- * and will update it with the new data in the stream. */
- dnode = dict_lookup (area->lspdb[level - 1], lsp->lsp_header->lsp_id);
- if (dnode)
- dnode_destroy (dict_delete (area->lspdb[level - 1], dnode));
-
- if (lsp->own_lsp)
- {
- zlog_err("ISIS-Upd (%s): BUG updating LSP %s still marked as own LSP",
- area->area_tag, rawlspid_print(lsp->lsp_header->lsp_id));
- lsp_clear_data(lsp);
- lsp->own_lsp = 0;
- }
-
- /* rebuild the lsp data */
- lsp_update_data (lsp, stream, area, level);
-
- /* insert the lsp back into the database */
- lsp_insert (lsp, area->lspdb[level - 1]);
+ dnode_t *dnode = NULL;
+
+ /* Remove old LSP from database. This is required since the
+ * lsp_update_data will free the lsp->pdu (which has the key, lsp_id)
+ * and will update it with the new data in the stream. */
+ dnode = dict_lookup(area->lspdb[level - 1], lsp->lsp_header->lsp_id);
+ if (dnode)
+ dnode_destroy(dict_delete(area->lspdb[level - 1], dnode));
+
+ if (lsp->own_lsp) {
+ zlog_err(
+ "ISIS-Upd (%s): BUG updating LSP %s still marked as own LSP",
+ area->area_tag,
+ rawlspid_print(lsp->lsp_header->lsp_id));
+ lsp_clear_data(lsp);
+ lsp->own_lsp = 0;
+ }
+
+ /* rebuild the lsp data */
+ lsp_update_data(lsp, stream, area, level);
+
+ /* insert the lsp back into the database */
+ lsp_insert(lsp, area->lspdb[level - 1]);
}
/* creation of LSP directly from what we received */
-struct isis_lsp *
-lsp_new_from_stream_ptr (struct stream *stream,
- u_int16_t pdu_len, struct isis_lsp *lsp0,
- struct isis_area *area, int level)
+struct isis_lsp *lsp_new_from_stream_ptr(struct stream *stream,
+ u_int16_t pdu_len,
+ struct isis_lsp *lsp0,
+ struct isis_area *area, int level)
{
- struct isis_lsp *lsp;
-
- lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
- lsp_update_data (lsp, stream, area, level);
-
- if (lsp0 == NULL)
- {
- /*
- * zero lsp -> create the list for fragments
- */
- lsp->lspu.frags = list_new ();
- }
- else
- {
- /*
- * a fragment -> set the backpointer and add this to zero lsps frag list
- */
- lsp->lspu.zero_lsp = lsp0;
- listnode_add (lsp0->lspu.frags, lsp);
- }
-
- return lsp;
+ struct isis_lsp *lsp;
+
+ lsp = XCALLOC(MTYPE_ISIS_LSP, sizeof(struct isis_lsp));
+ lsp_update_data(lsp, stream, area, level);
+
+ if (lsp0 == NULL) {
+ /*
+ * zero lsp -> create the list for fragments
+ */
+ lsp->lspu.frags = list_new();
+ } else {
+ /*
+ * a fragment -> set the backpointer and add this to zero lsps
+ * frag list
+ */
+ lsp->lspu.zero_lsp = lsp0;
+ listnode_add(lsp0->lspu.frags, lsp);
+ }
+
+ return lsp;
}
-struct isis_lsp *
-lsp_new(struct isis_area *area, u_char * lsp_id,
- u_int16_t rem_lifetime, u_int32_t seq_num,
- u_int8_t lsp_bits, u_int16_t checksum, int level)
+struct isis_lsp *lsp_new(struct isis_area *area, u_char *lsp_id,
+ u_int16_t rem_lifetime, u_int32_t seq_num,
+ u_int8_t lsp_bits, u_int16_t checksum, int level)
{
- struct isis_lsp *lsp;
-
- lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
- lsp->area = area;
-
- lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu);
- if (LSP_FRAGMENT (lsp_id) == 0)
- lsp->lspu.frags = list_new ();
- lsp->isis_header = (struct isis_fixed_hdr *) (STREAM_DATA (lsp->pdu));
- lsp->lsp_header = (struct isis_link_state_hdr *)
- (STREAM_DATA (lsp->pdu) + ISIS_FIXED_HDR_LEN);
-
- /* at first we fill the FIXED HEADER */
- (level == IS_LEVEL_1) ? fill_fixed_hdr (lsp->isis_header, L1_LINK_STATE) :
- fill_fixed_hdr (lsp->isis_header, L2_LINK_STATE);
-
- /* now for the LSP HEADER */
- /* Minimal LSP PDU size */
- lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
- memcpy (lsp->lsp_header->lsp_id, lsp_id, ISIS_SYS_ID_LEN + 2);
- lsp->lsp_header->checksum = checksum; /* Provided in network order */
- lsp->lsp_header->seq_num = htonl (seq_num);
- lsp->lsp_header->rem_lifetime = htons (rem_lifetime);
- lsp->lsp_header->lsp_bits = lsp_bits;
- lsp->level = level;
- lsp->age_out = ZERO_AGE_LIFETIME;
-
- stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
-
- if (isis->debugs & DEBUG_EVENTS)
- zlog_debug ("New LSP with ID %s-%02x-%02x len %d seqnum %08x",
- sysid_print (lsp_id), LSP_PSEUDO_ID (lsp->lsp_header->lsp_id),
- LSP_FRAGMENT (lsp->lsp_header->lsp_id),
- ntohl (lsp->lsp_header->pdu_len),
- ntohl (lsp->lsp_header->seq_num));
-
- return lsp;
+ struct isis_lsp *lsp;
+
+ lsp = XCALLOC(MTYPE_ISIS_LSP, sizeof(struct isis_lsp));
+ lsp->area = area;
+
+ lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu);
+ if (LSP_FRAGMENT(lsp_id) == 0)
+ lsp->lspu.frags = list_new();
+ lsp->isis_header = (struct isis_fixed_hdr *)(STREAM_DATA(lsp->pdu));
+ lsp->lsp_header = (struct isis_link_state_hdr *)(STREAM_DATA(lsp->pdu)
+ + ISIS_FIXED_HDR_LEN);
+
+ /* at first we fill the FIXED HEADER */
+ (level == IS_LEVEL_1) ? fill_fixed_hdr(lsp->isis_header, L1_LINK_STATE)
+ : fill_fixed_hdr(lsp->isis_header, L2_LINK_STATE);
+
+ /* now for the LSP HEADER */
+ /* Minimal LSP PDU size */
+ lsp->lsp_header->pdu_len = htons(ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
+ memcpy(lsp->lsp_header->lsp_id, lsp_id, ISIS_SYS_ID_LEN + 2);
+ lsp->lsp_header->checksum = checksum; /* Provided in network order */
+ lsp->lsp_header->seq_num = htonl(seq_num);
+ lsp->lsp_header->rem_lifetime = htons(rem_lifetime);
+ lsp->lsp_header->lsp_bits = lsp_bits;
+ lsp->level = level;
+ lsp->age_out = ZERO_AGE_LIFETIME;
+
+ stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
+
+ if (isis->debugs & DEBUG_EVENTS)
+ zlog_debug("New LSP with ID %s-%02x-%02x len %d seqnum %08x",
+ sysid_print(lsp_id),
+ LSP_PSEUDO_ID(lsp->lsp_header->lsp_id),
+ LSP_FRAGMENT(lsp->lsp_header->lsp_id),
+ ntohl(lsp->lsp_header->pdu_len),
+ ntohl(lsp->lsp_header->seq_num));
+
+ return lsp;
}
-void
-lsp_insert (struct isis_lsp *lsp, dict_t * lspdb)
+void lsp_insert(struct isis_lsp *lsp, dict_t *lspdb)
{
- dict_alloc_insert (lspdb, lsp->lsp_header->lsp_id, lsp);
- if (lsp->lsp_header->seq_num != 0)
- {
- isis_spf_schedule (lsp->area, lsp->level);
- }
+ dict_alloc_insert(lspdb, lsp->lsp_header->lsp_id, lsp);
+ if (lsp->lsp_header->seq_num != 0) {
+ isis_spf_schedule(lsp->area, lsp->level);
+ }
}
/*
* Build a list of LSPs with non-zero ht bounded by start and stop ids
*/
-void
-lsp_build_list_nonzero_ht (u_char * start_id, u_char * stop_id,
- struct list *list, dict_t * lspdb)
+void lsp_build_list_nonzero_ht(u_char *start_id, u_char *stop_id,
+ struct list *list, dict_t *lspdb)
{
- dnode_t *first, *last, *curr;
+ dnode_t *first, *last, *curr;
- first = dict_lower_bound (lspdb, start_id);
- if (!first)
- return;
+ first = dict_lower_bound(lspdb, start_id);
+ if (!first)
+ return;
- last = dict_upper_bound (lspdb, stop_id);
+ last = dict_upper_bound(lspdb, stop_id);
- curr = first;
+ curr = first;
- if (((struct isis_lsp *) (curr->dict_data))->lsp_header->rem_lifetime)
- listnode_add (list, first->dict_data);
+ if (((struct isis_lsp *)(curr->dict_data))->lsp_header->rem_lifetime)
+ listnode_add(list, first->dict_data);
- while (curr)
- {
- curr = dict_next (lspdb, curr);
- if (curr &&
- ((struct isis_lsp *) (curr->dict_data))->lsp_header->rem_lifetime)
- listnode_add (list, curr->dict_data);
- if (curr == last)
- break;
- }
+ while (curr) {
+ curr = dict_next(lspdb, curr);
+ if (curr
+ && ((struct isis_lsp *)(curr->dict_data))
+ ->lsp_header->rem_lifetime)
+ listnode_add(list, curr->dict_data);
+ if (curr == last)
+ break;
+ }
- return;
+ return;
}
/*
* Build a list of num_lsps LSPs bounded by start_id and stop_id.
*/
-void
-lsp_build_list (u_char * start_id, u_char * stop_id, u_char num_lsps,
- struct list *list, dict_t * lspdb)
+void lsp_build_list(u_char *start_id, u_char *stop_id, u_char num_lsps,
+ struct list *list, dict_t *lspdb)
{
- u_char count;
- dnode_t *first, *last, *curr;
+ u_char count;
+ dnode_t *first, *last, *curr;
- first = dict_lower_bound (lspdb, start_id);
- if (!first)
- return;
+ first = dict_lower_bound(lspdb, start_id);
+ if (!first)
+ return;
- last = dict_upper_bound (lspdb, stop_id);
+ last = dict_upper_bound(lspdb, stop_id);
- curr = first;
+ curr = first;
- listnode_add (list, first->dict_data);
- count = 1;
+ listnode_add(list, first->dict_data);
+ count = 1;
- while (curr)
- {
- curr = dict_next (lspdb, curr);
- if (curr)
- {
- listnode_add (list, curr->dict_data);
- count++;
- }
- if (count == num_lsps || curr == last)
- break;
- }
+ while (curr) {
+ curr = dict_next(lspdb, curr);
+ if (curr) {
+ listnode_add(list, curr->dict_data);
+ count++;
+ }
+ if (count == num_lsps || curr == last)
+ break;
+ }
- return;
+ return;
}
/*
* Build a list of LSPs with SSN flag set for the given circuit
*/
-void
-lsp_build_list_ssn (struct isis_circuit *circuit, u_char num_lsps,
- struct list *list, dict_t * lspdb)
+void lsp_build_list_ssn(struct isis_circuit *circuit, u_char num_lsps,
+ struct list *list, dict_t *lspdb)
{
- dnode_t *dnode, *next;
- struct isis_lsp *lsp;
- u_char count = 0;
-
- dnode = dict_first (lspdb);
- while (dnode != NULL)
- {
- next = dict_next (lspdb, dnode);
- lsp = dnode_get (dnode);
- if (ISIS_CHECK_FLAG (lsp->SSNflags, circuit))
- {
- listnode_add (list, lsp);
- ++count;
- }
- if (count == num_lsps)
- break;
- dnode = next;
- }
-
- return;
+ dnode_t *dnode, *next;
+ struct isis_lsp *lsp;
+ u_char count = 0;
+
+ dnode = dict_first(lspdb);
+ while (dnode != NULL) {
+ next = dict_next(lspdb, dnode);
+ lsp = dnode_get(dnode);
+ if (ISIS_CHECK_FLAG(lsp->SSNflags, circuit)) {
+ listnode_add(list, lsp);
+ ++count;
+ }
+ if (count == num_lsps)
+ break;
+ dnode = next;
+ }
+
+ return;
}
-static void
-lsp_set_time (struct isis_lsp *lsp)
+static void lsp_set_time(struct isis_lsp *lsp)
{
- assert (lsp);
+ assert(lsp);
- if (lsp->lsp_header->rem_lifetime == 0)
- {
- if (lsp->age_out > 0)
- lsp->age_out--;
- return;
- }
+ if (lsp->lsp_header->rem_lifetime == 0) {
+ if (lsp->age_out > 0)
+ lsp->age_out--;
+ return;
+ }
- lsp->lsp_header->rem_lifetime =
- htons (ntohs (lsp->lsp_header->rem_lifetime) - 1);
+ lsp->lsp_header->rem_lifetime =
+ htons(ntohs(lsp->lsp_header->rem_lifetime) - 1);
}
-static void
-lspid_print (u_char * lsp_id, u_char * trg, char dynhost, char frag)
+static void lspid_print(u_char *lsp_id, u_char *trg, char dynhost, char frag)
{
- struct isis_dynhn *dyn = NULL;
- u_char id[SYSID_STRLEN];
-
- if (dynhost)
- dyn = dynhn_find_by_id (lsp_id);
- else
- dyn = NULL;
-
- if (dyn)
- sprintf ((char *)id, "%.14s", dyn->name.name);
- else if (!memcmp (isis->sysid, lsp_id, ISIS_SYS_ID_LEN) && dynhost)
- sprintf ((char *)id, "%.14s", unix_hostname ());
- else
- memcpy (id, sysid_print (lsp_id), 15);
- if (frag)
- sprintf ((char *)trg, "%s.%02x-%02x", id, LSP_PSEUDO_ID (lsp_id),
- LSP_FRAGMENT (lsp_id));
- else
- sprintf ((char *)trg, "%s.%02x", id, LSP_PSEUDO_ID (lsp_id));
+ struct isis_dynhn *dyn = NULL;
+ u_char id[SYSID_STRLEN];
+
+ if (dynhost)
+ dyn = dynhn_find_by_id(lsp_id);
+ else
+ dyn = NULL;
+
+ if (dyn)
+ sprintf((char *)id, "%.14s", dyn->name.name);
+ else if (!memcmp(isis->sysid, lsp_id, ISIS_SYS_ID_LEN) && dynhost)
+ sprintf((char *)id, "%.14s", unix_hostname());
+ else
+ memcpy(id, sysid_print(lsp_id), 15);
+ if (frag)
+ sprintf((char *)trg, "%s.%02x-%02x", id, LSP_PSEUDO_ID(lsp_id),
+ LSP_FRAGMENT(lsp_id));
+ else
+ sprintf((char *)trg, "%s.%02x", id, LSP_PSEUDO_ID(lsp_id));
}
/* Convert the lsp attribute bits to attribute string */
-const char *
-lsp_bits2string (u_char * lsp_bits)
+const char *lsp_bits2string(u_char *lsp_bits)
{
- char *pos = lsp_bits_string;
+ char *pos = lsp_bits_string;
- if (!*lsp_bits)
- return " none";
+ if (!*lsp_bits)
+ return " none";
- /* we only focus on the default metric */
- pos += sprintf (pos, "%d/",
- ISIS_MASK_LSP_ATT_DEFAULT_BIT (*lsp_bits) ? 1 : 0);
+ /* we only focus on the default metric */
+ pos += sprintf(pos, "%d/",
+ ISIS_MASK_LSP_ATT_DEFAULT_BIT(*lsp_bits) ? 1 : 0);
- pos += sprintf (pos, "%d/",
- ISIS_MASK_LSP_PARTITION_BIT (*lsp_bits) ? 1 : 0);
+ pos += sprintf(pos, "%d/",
+ ISIS_MASK_LSP_PARTITION_BIT(*lsp_bits) ? 1 : 0);
- pos += sprintf (pos, "%d", ISIS_MASK_LSP_OL_BIT (*lsp_bits) ? 1 : 0);
+ pos += sprintf(pos, "%d", ISIS_MASK_LSP_OL_BIT(*lsp_bits) ? 1 : 0);
- *(pos) = '\0';
+ *(pos) = '\0';
- return lsp_bits_string;
+ return lsp_bits_string;
}
/* this function prints the lsp on show isis database */
-void
-lsp_print (struct isis_lsp *lsp, struct vty *vty, char dynhost)
+void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost)
{
- u_char LSPid[255];
- char age_out[8];
-
- lspid_print (lsp->lsp_header->lsp_id, LSPid, dynhost, 1);
- vty_out (vty, "%-21s%c ", LSPid, lsp->own_lsp ? '*' : ' ');
- vty_out (vty, "%5u ", ntohs (lsp->lsp_header->pdu_len));
- vty_out (vty, "0x%08x ", ntohl (lsp->lsp_header->seq_num));
- vty_out (vty, "0x%04x ", ntohs (lsp->lsp_header->checksum));
- if (ntohs (lsp->lsp_header->rem_lifetime) == 0)
- {
- snprintf (age_out, 8, "(%u)", lsp->age_out);
- age_out[7] = '\0';
- vty_out (vty, "%7s ", age_out);
- }
- else
- vty_out (vty, " %5u ", ntohs (lsp->lsp_header->rem_lifetime));
- vty_out (vty, "%s%s",
- lsp_bits2string (&lsp->lsp_header->lsp_bits), VTY_NEWLINE);
+ u_char LSPid[255];
+ char age_out[8];
+
+ lspid_print(lsp->lsp_header->lsp_id, LSPid, dynhost, 1);
+ vty_out(vty, "%-21s%c ", LSPid, lsp->own_lsp ? '*' : ' ');
+ vty_out(vty, "%5u ", ntohs(lsp->lsp_header->pdu_len));
+ vty_out(vty, "0x%08x ", ntohl(lsp->lsp_header->seq_num));
+ vty_out(vty, "0x%04x ", ntohs(lsp->lsp_header->checksum));
+ if (ntohs(lsp->lsp_header->rem_lifetime) == 0) {
+ snprintf(age_out, 8, "(%u)", lsp->age_out);
+ age_out[7] = '\0';
+ vty_out(vty, "%7s ", age_out);
+ } else
+ vty_out(vty, " %5u ", ntohs(lsp->lsp_header->rem_lifetime));
+ vty_out(vty, "%s%s", lsp_bits2string(&lsp->lsp_header->lsp_bits),
+ VTY_NEWLINE);
}
-void
-lsp_print_detail (struct isis_lsp *lsp, struct vty *vty, char dynhost)
+void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost)
{
- struct area_addr *area_addr;
- int i;
- struct listnode *lnode;
- struct is_neigh *is_neigh;
- struct te_is_neigh *te_is_neigh;
- struct ipv4_reachability *ipv4_reach;
- struct in_addr *ipv4_addr;
- struct te_ipv4_reachability *te_ipv4_reach;
- struct ipv6_reachability *ipv6_reach;
- struct in6_addr in6;
- u_char buff[BUFSIZ];
- u_char LSPid[255];
- u_char hostname[255];
- u_char ipv4_reach_prefix[20];
- u_char ipv4_reach_mask[20];
- u_char ipv4_address[20];
-
- lspid_print (lsp->lsp_header->lsp_id, LSPid, dynhost, 1);
- lsp_print (lsp, vty, dynhost);
-
- /* for all area address */
- if (lsp->tlv_data.area_addrs)
- for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.area_addrs, lnode, area_addr))
- {
- vty_out (vty, " Area Address: %s%s",
- isonet_print (area_addr->area_addr, area_addr->addr_len),
- VTY_NEWLINE);
- }
-
- /* for the nlpid tlv */
- if (lsp->tlv_data.nlpids)
- {
- for (i = 0; i < lsp->tlv_data.nlpids->count; i++)
- {
- switch (lsp->tlv_data.nlpids->nlpids[i])
- {
- case NLPID_IP:
- case NLPID_IPV6:
- vty_out (vty, " NLPID : 0x%X%s",
- lsp->tlv_data.nlpids->nlpids[i], VTY_NEWLINE);
- break;
- default:
- vty_out (vty, " NLPID : %s%s", "unknown", VTY_NEWLINE);
- break;
- }
+ struct area_addr *area_addr;
+ int i;
+ struct listnode *lnode;
+ struct is_neigh *is_neigh;
+ struct te_is_neigh *te_is_neigh;
+ struct ipv4_reachability *ipv4_reach;
+ struct in_addr *ipv4_addr;
+ struct te_ipv4_reachability *te_ipv4_reach;
+ struct ipv6_reachability *ipv6_reach;
+ struct in6_addr in6;
+ u_char buff[BUFSIZ];
+ u_char LSPid[255];
+ u_char hostname[255];
+ u_char ipv4_reach_prefix[20];
+ u_char ipv4_reach_mask[20];
+ u_char ipv4_address[20];
+
+ lspid_print(lsp->lsp_header->lsp_id, LSPid, dynhost, 1);
+ lsp_print(lsp, vty, dynhost);
+
+ /* for all area address */
+ if (lsp->tlv_data.area_addrs)
+ for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.area_addrs, lnode,
+ area_addr)) {
+ vty_out(vty, " Area Address: %s%s",
+ isonet_print(area_addr->area_addr,
+ area_addr->addr_len),
+ VTY_NEWLINE);
+ }
+
+ /* for the nlpid tlv */
+ if (lsp->tlv_data.nlpids) {
+ for (i = 0; i < lsp->tlv_data.nlpids->count; i++) {
+ switch (lsp->tlv_data.nlpids->nlpids[i]) {
+ case NLPID_IP:
+ case NLPID_IPV6:
+ vty_out(vty, " NLPID : 0x%X%s",
+ lsp->tlv_data.nlpids->nlpids[i],
+ VTY_NEWLINE);
+ break;
+ default:
+ vty_out(vty, " NLPID : %s%s", "unknown",
+ VTY_NEWLINE);
+ break;
+ }
+ }
+ }
+
+ /* for the hostname tlv */
+ if (lsp->tlv_data.hostname) {
+ bzero(hostname, sizeof(hostname));
+ memcpy(hostname, lsp->tlv_data.hostname->name,
+ lsp->tlv_data.hostname->namelen);
+ vty_out(vty, " Hostname : %s%s", hostname, VTY_NEWLINE);
+ }
+
+ /* authentication tlv */
+ if (lsp->tlv_data.auth_info.type != ISIS_PASSWD_TYPE_UNUSED) {
+ if (lsp->tlv_data.auth_info.type == ISIS_PASSWD_TYPE_HMAC_MD5)
+ vty_out(vty, " Auth type : md5%s", VTY_NEWLINE);
+ else if (lsp->tlv_data.auth_info.type
+ == ISIS_PASSWD_TYPE_CLEARTXT)
+ vty_out(vty, " Auth type : clear text%s",
+ VTY_NEWLINE);
+ }
+
+ /* TE router id */
+ if (lsp->tlv_data.router_id) {
+ memcpy(ipv4_address, inet_ntoa(lsp->tlv_data.router_id->id),
+ sizeof(ipv4_address));
+ vty_out(vty, " Router ID : %s%s", ipv4_address, VTY_NEWLINE);
}
- }
-
- /* for the hostname tlv */
- if (lsp->tlv_data.hostname)
- {
- bzero (hostname, sizeof (hostname));
- memcpy (hostname, lsp->tlv_data.hostname->name,
- lsp->tlv_data.hostname->namelen);
- vty_out (vty, " Hostname : %s%s", hostname, VTY_NEWLINE);
- }
-
- /* authentication tlv */
- if (lsp->tlv_data.auth_info.type != ISIS_PASSWD_TYPE_UNUSED)
- {
- if (lsp->tlv_data.auth_info.type == ISIS_PASSWD_TYPE_HMAC_MD5)
- vty_out (vty, " Auth type : md5%s", VTY_NEWLINE);
- else if (lsp->tlv_data.auth_info.type == ISIS_PASSWD_TYPE_CLEARTXT)
- vty_out (vty, " Auth type : clear text%s", VTY_NEWLINE);
- }
-
- /* TE router id */
- if (lsp->tlv_data.router_id)
- {
- memcpy (ipv4_address, inet_ntoa (lsp->tlv_data.router_id->id),
- sizeof (ipv4_address));
- vty_out (vty, " Router ID : %s%s", ipv4_address, VTY_NEWLINE);
- }
-
- if (lsp->tlv_data.ipv4_addrs)
- for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_addrs, lnode, ipv4_addr))
- {
- memcpy (ipv4_address, inet_ntoa (*ipv4_addr), sizeof (ipv4_address));
- vty_out (vty, " IPv4 Address: %s%s", ipv4_address, VTY_NEWLINE);
- }
-
- /* for the IS neighbor tlv */
- if (lsp->tlv_data.is_neighs)
- for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, lnode, is_neigh))
- {
- lspid_print (is_neigh->neigh_id, LSPid, dynhost, 0);
- vty_out (vty, " Metric : %-8" PRIu8 " IS : %s%s",
- is_neigh->metrics.metric_default, LSPid, VTY_NEWLINE);
- }
-
- /* for the internal reachable tlv */
- if (lsp->tlv_data.ipv4_int_reachs)
- for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_int_reachs, lnode,
- ipv4_reach))
- {
- memcpy (ipv4_reach_prefix, inet_ntoa (ipv4_reach->prefix),
- sizeof (ipv4_reach_prefix));
- memcpy (ipv4_reach_mask, inet_ntoa (ipv4_reach->mask),
- sizeof (ipv4_reach_mask));
- vty_out (vty, " Metric : %-8" PRIu8 " IPv4-Internal : %s %s%s",
- ipv4_reach->metrics.metric_default, ipv4_reach_prefix,
- ipv4_reach_mask, VTY_NEWLINE);
- }
-
- /* for the external reachable tlv */
- if (lsp->tlv_data.ipv4_ext_reachs)
- for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_ext_reachs, lnode,
- ipv4_reach))
- {
- memcpy (ipv4_reach_prefix, inet_ntoa (ipv4_reach->prefix),
- sizeof (ipv4_reach_prefix));
- memcpy (ipv4_reach_mask, inet_ntoa (ipv4_reach->mask),
- sizeof (ipv4_reach_mask));
- vty_out (vty, " Metric : %-8" PRIu8 " IPv4-External : %s %s%s",
- ipv4_reach->metrics.metric_default, ipv4_reach_prefix,
- ipv4_reach_mask, VTY_NEWLINE);
- }
-
- /* IPv6 tlv */
- if (lsp->tlv_data.ipv6_reachs)
- for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv6_reachs, lnode, ipv6_reach))
- {
- memset (&in6, 0, sizeof (in6));
- memcpy (in6.s6_addr, ipv6_reach->prefix,
- PSIZE (ipv6_reach->prefix_len));
- inet_ntop (AF_INET6, &in6, (char *)buff, BUFSIZ);
- if ((ipv6_reach->control_info &
- CTRL_INFO_DISTRIBUTION) == DISTRIBUTION_INTERNAL)
- vty_out (vty, " Metric : %-8" PRIu32 " IPv6-Internal : %s/%d%s",
- ntohl (ipv6_reach->metric),
- buff, ipv6_reach->prefix_len, VTY_NEWLINE);
- else
- vty_out (vty, " Metric : %-8" PRIu32 " IPv6-External : %s/%d%s",
- ntohl (ipv6_reach->metric),
- buff, ipv6_reach->prefix_len, VTY_NEWLINE);
- }
-
- /* TE IS neighbor tlv */
- if (lsp->tlv_data.te_is_neighs)
- for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, lnode, te_is_neigh))
- {
- lspid_print (te_is_neigh->neigh_id, LSPid, dynhost, 0);
- vty_out (vty, " Metric : %-8u IS-Extended : %s%s",
- GET_TE_METRIC(te_is_neigh), LSPid, VTY_NEWLINE);
- if (IS_MPLS_TE(isisMplsTE))
- mpls_te_print_detail(vty, te_is_neigh);
- }
-
- /* TE IPv4 tlv */
- if (lsp->tlv_data.te_ipv4_reachs)
- for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_ipv4_reachs, lnode,
- te_ipv4_reach))
- {
- /* FIXME: There should be better way to output this stuff. */
- vty_out (vty, " Metric : %-8" PRIu32 " IPv4-Extended : %s/%d%s",
- ntohl (te_ipv4_reach->te_metric),
- inet_ntoa (newprefix2inaddr (&te_ipv4_reach->prefix_start,
- te_ipv4_reach->control)),
- te_ipv4_reach->control & 0x3F, VTY_NEWLINE);
- }
- vty_out (vty, "%s", VTY_NEWLINE);
-
- return;
+
+ if (lsp->tlv_data.ipv4_addrs)
+ for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.ipv4_addrs, lnode,
+ ipv4_addr)) {
+ memcpy(ipv4_address, inet_ntoa(*ipv4_addr),
+ sizeof(ipv4_address));
+ vty_out(vty, " IPv4 Address: %s%s", ipv4_address,
+ VTY_NEWLINE);
+ }
+
+ /* for the IS neighbor tlv */
+ if (lsp->tlv_data.is_neighs)
+ for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.is_neighs, lnode,
+ is_neigh)) {
+ lspid_print(is_neigh->neigh_id, LSPid, dynhost, 0);
+ vty_out(vty, " Metric : %-8" PRIu8
+ " IS : %s%s",
+ is_neigh->metrics.metric_default, LSPid,
+ VTY_NEWLINE);
+ }
+
+ /* for the internal reachable tlv */
+ if (lsp->tlv_data.ipv4_int_reachs)
+ for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.ipv4_int_reachs, lnode,
+ ipv4_reach)) {
+ memcpy(ipv4_reach_prefix, inet_ntoa(ipv4_reach->prefix),
+ sizeof(ipv4_reach_prefix));
+ memcpy(ipv4_reach_mask, inet_ntoa(ipv4_reach->mask),
+ sizeof(ipv4_reach_mask));
+ vty_out(vty, " Metric : %-8" PRIu8
+ " IPv4-Internal : %s %s%s",
+ ipv4_reach->metrics.metric_default,
+ ipv4_reach_prefix, ipv4_reach_mask,
+ VTY_NEWLINE);
+ }
+
+ /* for the external reachable tlv */
+ if (lsp->tlv_data.ipv4_ext_reachs)
+ for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.ipv4_ext_reachs, lnode,
+ ipv4_reach)) {
+ memcpy(ipv4_reach_prefix, inet_ntoa(ipv4_reach->prefix),
+ sizeof(ipv4_reach_prefix));
+ memcpy(ipv4_reach_mask, inet_ntoa(ipv4_reach->mask),
+ sizeof(ipv4_reach_mask));
+ vty_out(vty, " Metric : %-8" PRIu8
+ " IPv4-External : %s %s%s",
+ ipv4_reach->metrics.metric_default,
+ ipv4_reach_prefix, ipv4_reach_mask,
+ VTY_NEWLINE);
+ }
+
+ /* IPv6 tlv */
+ if (lsp->tlv_data.ipv6_reachs)
+ for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.ipv6_reachs, lnode,
+ ipv6_reach)) {
+ memset(&in6, 0, sizeof(in6));
+ memcpy(in6.s6_addr, ipv6_reach->prefix,
+ PSIZE(ipv6_reach->prefix_len));
+ inet_ntop(AF_INET6, &in6, (char *)buff, BUFSIZ);
+ if ((ipv6_reach->control_info & CTRL_INFO_DISTRIBUTION)
+ == DISTRIBUTION_INTERNAL)
+ vty_out(vty, " Metric : %-8" PRIu32
+ " IPv6-Internal : %s/%d%s",
+ ntohl(ipv6_reach->metric), buff,
+ ipv6_reach->prefix_len, VTY_NEWLINE);
+ else
+ vty_out(vty, " Metric : %-8" PRIu32
+ " IPv6-External : %s/%d%s",
+ ntohl(ipv6_reach->metric), buff,
+ ipv6_reach->prefix_len, VTY_NEWLINE);
+ }
+
+ /* TE IS neighbor tlv */
+ if (lsp->tlv_data.te_is_neighs)
+ for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.te_is_neighs, lnode,
+ te_is_neigh)) {
+ lspid_print(te_is_neigh->neigh_id, LSPid, dynhost, 0);
+ vty_out(vty,
+ " Metric : %-8u IS-Extended : %s%s",
+ GET_TE_METRIC(te_is_neigh), LSPid, VTY_NEWLINE);
+ if (IS_MPLS_TE(isisMplsTE))
+ mpls_te_print_detail(vty, te_is_neigh);
+ }
+
+ /* TE IPv4 tlv */
+ if (lsp->tlv_data.te_ipv4_reachs)
+ for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.te_ipv4_reachs, lnode,
+ te_ipv4_reach)) {
+ /* FIXME: There should be better way to output this
+ * stuff. */
+ vty_out(vty, " Metric : %-8" PRIu32
+ " IPv4-Extended : %s/%d%s",
+ ntohl(te_ipv4_reach->te_metric),
+ inet_ntoa(newprefix2inaddr(
+ &te_ipv4_reach->prefix_start,
+ te_ipv4_reach->control)),
+ te_ipv4_reach->control & 0x3F, VTY_NEWLINE);
+ }
+ vty_out(vty, "%s", VTY_NEWLINE);
+
+ return;
}
/* print all the lsps info in the local lspdb */
-int
-lsp_print_all (struct vty *vty, dict_t * lspdb, char detail, char dynhost)
+int lsp_print_all(struct vty *vty, dict_t *lspdb, char detail, char dynhost)
{
- dnode_t *node = dict_first (lspdb), *next;
- int lsp_count = 0;
-
- if (detail == ISIS_UI_LEVEL_BRIEF)
- {
- while (node != NULL)
- {
- /* I think it is unnecessary, so I comment it out */
- /* dict_contains (lspdb, node); */
- next = dict_next (lspdb, node);
- lsp_print (dnode_get (node), vty, dynhost);
- node = next;
- lsp_count++;
- }
- }
- else if (detail == ISIS_UI_LEVEL_DETAIL)
- {
- while (node != NULL)
- {
- next = dict_next (lspdb, node);
- lsp_print_detail (dnode_get (node), vty, dynhost);
- node = next;
- lsp_count++;
+ dnode_t *node = dict_first(lspdb), *next;
+ int lsp_count = 0;
+
+ if (detail == ISIS_UI_LEVEL_BRIEF) {
+ while (node != NULL) {
+ /* I think it is unnecessary, so I comment it out */
+ /* dict_contains (lspdb, node); */
+ next = dict_next(lspdb, node);
+ lsp_print(dnode_get(node), vty, dynhost);
+ node = next;
+ lsp_count++;
+ }
+ } else if (detail == ISIS_UI_LEVEL_DETAIL) {
+ while (node != NULL) {
+ next = dict_next(lspdb, node);
+ lsp_print_detail(dnode_get(node), vty, dynhost);
+ node = next;
+ lsp_count++;
+ }
}
- }
- return lsp_count;
+ return lsp_count;
}
-#define FRAG_THOLD(S,T) \
- ((STREAM_SIZE(S)*T)/100)
+#define FRAG_THOLD(S, T) ((STREAM_SIZE(S) * T) / 100)
/* stream*, area->lsp_frag_threshold, increment */
-#define FRAG_NEEDED(S,T,I) \
- (STREAM_SIZE(S)-STREAM_REMAIN(S)+(I) > FRAG_THOLD(S,T))
+#define FRAG_NEEDED(S, T, I) \
+ (STREAM_SIZE(S) - STREAM_REMAIN(S) + (I) > FRAG_THOLD(S, T))
/* FIXME: It shouldn't be necessary to pass tlvsize here, TLVs can have
* variable length (TE TLVs, sub TLVs). */
-static void
-lsp_tlv_fit (struct isis_lsp *lsp, struct list **from, struct list **to,
- int tlvsize, int frag_thold,
- int tlv_build_func (struct list *, struct stream *))
+static void lsp_tlv_fit(struct isis_lsp *lsp, struct list **from,
+ struct list **to, int tlvsize, int frag_thold,
+ int tlv_build_func(struct list *, struct stream *))
{
- int count, i;
-
- /* can we fit all ? */
- if (!FRAG_NEEDED (lsp->pdu, frag_thold, listcount (*from) * tlvsize + 2))
- {
- tlv_build_func (*from, lsp->pdu);
- if (listcount (*to) != 0)
- {
- struct listnode *node, *nextnode;
- void *elem;
-
- for (ALL_LIST_ELEMENTS (*from, node, nextnode, elem))
- {
- listnode_add (*to, elem);
- list_delete_node (*from, node);
- }
- }
- else
- {
- list_free (*to);
- *to = *from;
- *from = NULL;
- }
- }
- else if (!FRAG_NEEDED (lsp->pdu, frag_thold, tlvsize + 2))
- {
- /* fit all we can */
- count = FRAG_THOLD (lsp->pdu, frag_thold) - 2 -
- (STREAM_SIZE (lsp->pdu) - STREAM_REMAIN (lsp->pdu));
- count = count / tlvsize;
- if (count > (int)listcount (*from))
- count = listcount (*from);
- for (i = 0; i < count; i++)
- {
- listnode_add (*to, listgetdata (listhead (*from)));
- listnode_delete (*from, listgetdata (listhead (*from)));
+ int count, i;
+
+ /* can we fit all ? */
+ if (!FRAG_NEEDED(lsp->pdu, frag_thold,
+ listcount(*from) * tlvsize + 2)) {
+ tlv_build_func(*from, lsp->pdu);
+ if (listcount(*to) != 0) {
+ struct listnode *node, *nextnode;
+ void *elem;
+
+ for (ALL_LIST_ELEMENTS(*from, node, nextnode, elem)) {
+ listnode_add(*to, elem);
+ list_delete_node(*from, node);
+ }
+ } else {
+ list_free(*to);
+ *to = *from;
+ *from = NULL;
+ }
+ } else if (!FRAG_NEEDED(lsp->pdu, frag_thold, tlvsize + 2)) {
+ /* fit all we can */
+ count = FRAG_THOLD(lsp->pdu, frag_thold) - 2
+ - (STREAM_SIZE(lsp->pdu) - STREAM_REMAIN(lsp->pdu));
+ count = count / tlvsize;
+ if (count > (int)listcount(*from))
+ count = listcount(*from);
+ for (i = 0; i < count; i++) {
+ listnode_add(*to, listgetdata(listhead(*from)));
+ listnode_delete(*from, listgetdata(listhead(*from)));
+ }
+ tlv_build_func(*to, lsp->pdu);
}
- tlv_build_func (*to, lsp->pdu);
- }
- lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
- return;
+ lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu));
+ return;
}
/* Process IS_NEIGHBOURS TLV with TE subTLVs */
-void
-lsp_te_tlv_fit (struct isis_lsp *lsp, struct list **from, struct list **to, int frag_thold)
+void lsp_te_tlv_fit(struct isis_lsp *lsp, struct list **from, struct list **to,
+ int frag_thold)
{
- int count, size = 0;
- struct listnode *node, *nextnode;
- struct te_is_neigh *elem;
-
- /* Start computing real size of TLVs */
- for (ALL_LIST_ELEMENTS (*from, node, nextnode, elem))
- size = size + elem->sub_tlvs_length + IS_NEIGHBOURS_LEN;
-
- /* can we fit all ? */
- if (!FRAG_NEEDED (lsp->pdu, frag_thold, size))
- {
- tlv_add_te_is_neighs (*from, lsp->pdu);
- if (listcount (*to) != 0)
- {
- for (ALL_LIST_ELEMENTS (*from, node, nextnode, elem))
- {
- listnode_add (*to, elem);
- list_delete_node (*from, node);
- }
- }
- else
- {
- list_free (*to);
- *to = *from;
- *from = NULL;
- }
- }
- else
- {
- /* fit all we can */
- /* Compute remaining place in LSP PDU */
- count = FRAG_THOLD (lsp->pdu, frag_thold) - 2 -
- (STREAM_SIZE (lsp->pdu) - STREAM_REMAIN (lsp->pdu));
- /* Determine size of TE SubTLVs */
- elem = (struct te_is_neigh *)listgetdata ((struct listnode *)listhead (*from));
- count = count - elem->sub_tlvs_length - IS_NEIGHBOURS_LEN;
- if (count > 0)
- {
- while (count > 0)
- {
- listnode_add (*to, listgetdata ((struct listnode *)listhead (*from)));
- listnode_delete (*from, listgetdata ((struct listnode *)listhead (*from)));
-
- elem = (struct te_is_neigh *)listgetdata ((struct listnode *)listhead (*from));
- count = count - elem->sub_tlvs_length - IS_NEIGHBOURS_LEN;
- }
-
- tlv_add_te_is_neighs (*to, lsp->pdu);
- }
- }
- lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
- return;
+ int count, size = 0;
+ struct listnode *node, *nextnode;
+ struct te_is_neigh *elem;
+
+ /* Start computing real size of TLVs */
+ for (ALL_LIST_ELEMENTS(*from, node, nextnode, elem))
+ size = size + elem->sub_tlvs_length + IS_NEIGHBOURS_LEN;
+
+ /* can we fit all ? */
+ if (!FRAG_NEEDED(lsp->pdu, frag_thold, size)) {
+ tlv_add_te_is_neighs(*from, lsp->pdu);
+ if (listcount(*to) != 0) {
+ for (ALL_LIST_ELEMENTS(*from, node, nextnode, elem)) {
+ listnode_add(*to, elem);
+ list_delete_node(*from, node);
+ }
+ } else {
+ list_free(*to);
+ *to = *from;
+ *from = NULL;
+ }
+ } else {
+ /* fit all we can */
+ /* Compute remaining place in LSP PDU */
+ count = FRAG_THOLD(lsp->pdu, frag_thold) - 2
+ - (STREAM_SIZE(lsp->pdu) - STREAM_REMAIN(lsp->pdu));
+ /* Determine size of TE SubTLVs */
+ elem = (struct te_is_neigh *)listgetdata(
+ (struct listnode *)listhead(*from));
+ count = count - elem->sub_tlvs_length - IS_NEIGHBOURS_LEN;
+ if (count > 0) {
+ while (count > 0) {
+ listnode_add(
+ *to,
+ listgetdata((struct listnode *)listhead(
+ *from)));
+ listnode_delete(
+ *from,
+ listgetdata((struct listnode *)listhead(
+ *from)));
+
+ elem = (struct te_is_neigh *)listgetdata(
+ (struct listnode *)listhead(*from));
+ count = count - elem->sub_tlvs_length
+ - IS_NEIGHBOURS_LEN;
+ }
+
+ tlv_add_te_is_neighs(*to, lsp->pdu);
+ }
+ }
+ lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu));
+ return;
}
-static u_int16_t
-lsp_rem_lifetime (struct isis_area *area, int level)
+static u_int16_t lsp_rem_lifetime(struct isis_area *area, int level)
{
- u_int16_t rem_lifetime;
+ u_int16_t rem_lifetime;
- /* Add jitter to configured LSP lifetime */
- rem_lifetime = isis_jitter (area->max_lsp_lifetime[level - 1],
- MAX_AGE_JITTER);
+ /* Add jitter to configured LSP lifetime */
+ rem_lifetime =
+ isis_jitter(area->max_lsp_lifetime[level - 1], MAX_AGE_JITTER);
- /* No jitter if the max refresh will be less than configure gen interval */
- /* N.B. this calucation is acceptable since rem_lifetime is in [332,65535] at
- * this point */
- if (area->lsp_gen_interval[level - 1] > (rem_lifetime - 300))
- rem_lifetime = area->max_lsp_lifetime[level - 1];
+ /* No jitter if the max refresh will be less than configure gen interval
+ */
+ /* N.B. this calucation is acceptable since rem_lifetime is in
+ * [332,65535] at
+ * this point */
+ if (area->lsp_gen_interval[level - 1] > (rem_lifetime - 300))
+ rem_lifetime = area->max_lsp_lifetime[level - 1];
- return rem_lifetime;
+ return rem_lifetime;
}
-static u_int16_t
-lsp_refresh_time (struct isis_lsp *lsp, u_int16_t rem_lifetime)
+static u_int16_t lsp_refresh_time(struct isis_lsp *lsp, u_int16_t rem_lifetime)
{
- struct isis_area *area = lsp->area;
- int level = lsp->level;
- u_int16_t refresh_time;
+ struct isis_area *area = lsp->area;
+ int level = lsp->level;
+ u_int16_t refresh_time;
- /* Add jitter to LSP refresh time */
- refresh_time = isis_jitter (area->lsp_refresh[level - 1],
- MAX_LSP_GEN_JITTER);
+ /* Add jitter to LSP refresh time */
+ refresh_time =
+ isis_jitter(area->lsp_refresh[level - 1], MAX_LSP_GEN_JITTER);
- /* RFC 4444 : make sure the refresh time is at least less than 300
- * of the remaining lifetime and more than gen interval */
- if (refresh_time <= area->lsp_gen_interval[level - 1] ||
- refresh_time > (rem_lifetime - 300))
- refresh_time = rem_lifetime - 300;
+ /* RFC 4444 : make sure the refresh time is at least less than 300
+ * of the remaining lifetime and more than gen interval */
+ if (refresh_time <= area->lsp_gen_interval[level - 1]
+ || refresh_time > (rem_lifetime - 300))
+ refresh_time = rem_lifetime - 300;
- /* In cornercases, refresh_time might be <= lsp_gen_interval, however
- * we accept this violation to satisfy refresh_time <= rem_lifetime - 300 */
+ /* In cornercases, refresh_time might be <= lsp_gen_interval, however
+ * we accept this violation to satisfy refresh_time <= rem_lifetime -
+ * 300 */
- return refresh_time;
+ return refresh_time;
}
-static struct isis_lsp *
-lsp_next_frag (u_char frag_num, struct isis_lsp *lsp0, struct isis_area *area,
- int level)
+static struct isis_lsp *lsp_next_frag(u_char frag_num, struct isis_lsp *lsp0,
+ struct isis_area *area, int level)
{
- struct isis_lsp *lsp;
- u_char frag_id[ISIS_SYS_ID_LEN + 2];
-
- memcpy (frag_id, lsp0->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 1);
- LSP_FRAGMENT (frag_id) = frag_num;
- /* FIXME add authentication TLV for fragment LSPs */
- lsp = lsp_search (frag_id, area->lspdb[level - 1]);
- if (lsp)
- {
- /* Clear the TLVs */
- lsp_clear_data (lsp);
- return lsp;
- }
- lsp = lsp_new (area, frag_id, ntohs(lsp0->lsp_header->rem_lifetime), 0,
- lsp_bits_generate (level, area->overload_bit,
- area->attached_bit), 0, level);
- lsp->area = area;
- lsp->own_lsp = 1;
- lsp_insert (lsp, area->lspdb[level - 1]);
- listnode_add (lsp0->lspu.frags, lsp);
- lsp->lspu.zero_lsp = lsp0;
- return lsp;
+ struct isis_lsp *lsp;
+ u_char frag_id[ISIS_SYS_ID_LEN + 2];
+
+ memcpy(frag_id, lsp0->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 1);
+ LSP_FRAGMENT(frag_id) = frag_num;
+ /* FIXME add authentication TLV for fragment LSPs */
+ lsp = lsp_search(frag_id, area->lspdb[level - 1]);
+ if (lsp) {
+ /* Clear the TLVs */
+ lsp_clear_data(lsp);
+ return lsp;
+ }
+ lsp = lsp_new(area, frag_id, ntohs(lsp0->lsp_header->rem_lifetime), 0,
+ lsp_bits_generate(level, area->overload_bit,
+ area->attached_bit),
+ 0, level);
+ lsp->area = area;
+ lsp->own_lsp = 1;
+ lsp_insert(lsp, area->lspdb[level - 1]);
+ listnode_add(lsp0->lspu.frags, lsp);
+ lsp->lspu.zero_lsp = lsp0;
+ return lsp;
}
-static void
-lsp_build_ext_reach_ipv4(struct isis_lsp *lsp, struct isis_area *area,
- struct tlvs *tlv_data)
+static void lsp_build_ext_reach_ipv4(struct isis_lsp *lsp,
+ struct isis_area *area,
+ struct tlvs *tlv_data)
{
- struct route_table *er_table;
- struct route_node *rn;
- struct prefix_ipv4 *ipv4;
- struct isis_ext_info *info;
- struct ipv4_reachability *ipreach;
- struct te_ipv4_reachability *te_ipreach;
-
- er_table = get_ext_reach(area, AF_INET, lsp->level);
- if (!er_table)
- return;
-
- for (rn = route_top(er_table); rn; rn = route_next(rn))
- {
- if (!rn->info)
- continue;
-
- ipv4 = (struct prefix_ipv4*)&rn->p;
- info = rn->info;
- if (area->oldmetric)
- {
- if (tlv_data->ipv4_ext_reachs == NULL)
- {
- tlv_data->ipv4_ext_reachs = list_new();
- tlv_data->ipv4_ext_reachs->del = free_tlv;
- }
- ipreach = XMALLOC(MTYPE_ISIS_TLV, sizeof(*ipreach));
-
- ipreach->prefix.s_addr = ipv4->prefix.s_addr;
- masklen2ip(ipv4->prefixlen, &ipreach->mask);
- ipreach->prefix.s_addr &= ipreach->mask.s_addr;
-
- if ((info->metric & 0x3f) != info->metric)
- ipreach->metrics.metric_default = 0x3f;
- else
- ipreach->metrics.metric_default = info->metric;
- ipreach->metrics.metric_expense = METRICS_UNSUPPORTED;
- ipreach->metrics.metric_error = METRICS_UNSUPPORTED;
- ipreach->metrics.metric_delay = METRICS_UNSUPPORTED;
- listnode_add(tlv_data->ipv4_ext_reachs, ipreach);
- }
- if (area->newmetric)
- {
- if (tlv_data->te_ipv4_reachs == NULL)
- {
- tlv_data->te_ipv4_reachs = list_new();
- tlv_data->te_ipv4_reachs->del = free_tlv;
- }
- te_ipreach =
- XCALLOC(MTYPE_ISIS_TLV,
- sizeof(*te_ipreach) - 1 + PSIZE(ipv4->prefixlen));
- if (info->metric > MAX_WIDE_PATH_METRIC)
- te_ipreach->te_metric = htonl(MAX_WIDE_PATH_METRIC);
- else
- te_ipreach->te_metric = htonl(info->metric);
- te_ipreach->control = ipv4->prefixlen & 0x3f;
- memcpy(&te_ipreach->prefix_start, &ipv4->prefix.s_addr,
- PSIZE(ipv4->prefixlen));
- listnode_add(tlv_data->te_ipv4_reachs, te_ipreach);
- }
- }
+ struct route_table *er_table;
+ struct route_node *rn;
+ struct prefix_ipv4 *ipv4;
+ struct isis_ext_info *info;
+ struct ipv4_reachability *ipreach;
+ struct te_ipv4_reachability *te_ipreach;
+
+ er_table = get_ext_reach(area, AF_INET, lsp->level);
+ if (!er_table)
+ return;
+
+ for (rn = route_top(er_table); rn; rn = route_next(rn)) {
+ if (!rn->info)
+ continue;
+
+ ipv4 = (struct prefix_ipv4 *)&rn->p;
+ info = rn->info;
+ if (area->oldmetric) {
+ if (tlv_data->ipv4_ext_reachs == NULL) {
+ tlv_data->ipv4_ext_reachs = list_new();
+ tlv_data->ipv4_ext_reachs->del = free_tlv;
+ }
+ ipreach = XMALLOC(MTYPE_ISIS_TLV, sizeof(*ipreach));
+
+ ipreach->prefix.s_addr = ipv4->prefix.s_addr;
+ masklen2ip(ipv4->prefixlen, &ipreach->mask);
+ ipreach->prefix.s_addr &= ipreach->mask.s_addr;
+
+ if ((info->metric & 0x3f) != info->metric)
+ ipreach->metrics.metric_default = 0x3f;
+ else
+ ipreach->metrics.metric_default = info->metric;
+ ipreach->metrics.metric_expense = METRICS_UNSUPPORTED;
+ ipreach->metrics.metric_error = METRICS_UNSUPPORTED;
+ ipreach->metrics.metric_delay = METRICS_UNSUPPORTED;
+ listnode_add(tlv_data->ipv4_ext_reachs, ipreach);
+ }
+ if (area->newmetric) {
+ if (tlv_data->te_ipv4_reachs == NULL) {
+ tlv_data->te_ipv4_reachs = list_new();
+ tlv_data->te_ipv4_reachs->del = free_tlv;
+ }
+ te_ipreach = XCALLOC(MTYPE_ISIS_TLV,
+ sizeof(*te_ipreach) - 1
+ + PSIZE(ipv4->prefixlen));
+ if (info->metric > MAX_WIDE_PATH_METRIC)
+ te_ipreach->te_metric =
+ htonl(MAX_WIDE_PATH_METRIC);
+ else
+ te_ipreach->te_metric = htonl(info->metric);
+ te_ipreach->control = ipv4->prefixlen & 0x3f;
+ memcpy(&te_ipreach->prefix_start, &ipv4->prefix.s_addr,
+ PSIZE(ipv4->prefixlen));
+ listnode_add(tlv_data->te_ipv4_reachs, te_ipreach);
+ }
+ }
}
-static void
-lsp_build_ext_reach_ipv6(struct isis_lsp *lsp, struct isis_area *area,
- struct tlvs *tlv_data)
+static void lsp_build_ext_reach_ipv6(struct isis_lsp *lsp,
+ struct isis_area *area,
+ struct tlvs *tlv_data)
{
- struct route_table *er_table;
- struct route_node *rn;
- struct prefix_ipv6 *ipv6;
- struct isis_ext_info *info;
- struct ipv6_reachability *ip6reach;
-
- er_table = get_ext_reach(area, AF_INET6, lsp->level);
- if (!er_table)
- return;
-
- for (rn = route_top(er_table); rn; rn = route_next(rn))
- {
- if (!rn->info)
- continue;
-
- ipv6 = (struct prefix_ipv6*)&rn->p;
- info = rn->info;
-
- if (tlv_data->ipv6_reachs == NULL)
- {
- tlv_data->ipv6_reachs = list_new();
- tlv_data->ipv6_reachs->del = free_tlv;
- }
- ip6reach = XCALLOC(MTYPE_ISIS_TLV, sizeof(*ip6reach));
- if (info->metric > MAX_WIDE_PATH_METRIC)
- ip6reach->metric = htonl(MAX_WIDE_PATH_METRIC);
- else
- ip6reach->metric = htonl(info->metric);
- ip6reach->control_info = DISTRIBUTION_EXTERNAL;
- ip6reach->prefix_len = ipv6->prefixlen;
- memcpy(ip6reach->prefix, ipv6->prefix.s6_addr, sizeof(ip6reach->prefix));
- listnode_add(tlv_data->ipv6_reachs, ip6reach);
- }
+ struct route_table *er_table;
+ struct route_node *rn;
+ struct prefix_ipv6 *ipv6;
+ struct isis_ext_info *info;
+ struct ipv6_reachability *ip6reach;
+
+ er_table = get_ext_reach(area, AF_INET6, lsp->level);
+ if (!er_table)
+ return;
+
+ for (rn = route_top(er_table); rn; rn = route_next(rn)) {
+ if (!rn->info)
+ continue;
+
+ ipv6 = (struct prefix_ipv6 *)&rn->p;
+ info = rn->info;
+
+ if (tlv_data->ipv6_reachs == NULL) {
+ tlv_data->ipv6_reachs = list_new();
+ tlv_data->ipv6_reachs->del = free_tlv;
+ }
+ ip6reach = XCALLOC(MTYPE_ISIS_TLV, sizeof(*ip6reach));
+ if (info->metric > MAX_WIDE_PATH_METRIC)
+ ip6reach->metric = htonl(MAX_WIDE_PATH_METRIC);
+ else
+ ip6reach->metric = htonl(info->metric);
+ ip6reach->control_info = DISTRIBUTION_EXTERNAL;
+ ip6reach->prefix_len = ipv6->prefixlen;
+ memcpy(ip6reach->prefix, ipv6->prefix.s6_addr,
+ sizeof(ip6reach->prefix));
+ listnode_add(tlv_data->ipv6_reachs, ip6reach);
+ }
}
-static void
-lsp_build_ext_reach (struct isis_lsp *lsp, struct isis_area *area,
- struct tlvs *tlv_data)
+static void lsp_build_ext_reach(struct isis_lsp *lsp, struct isis_area *area,
+ struct tlvs *tlv_data)
{
- lsp_build_ext_reach_ipv4(lsp, area, tlv_data);
- lsp_build_ext_reach_ipv6(lsp, area, tlv_data);
+ lsp_build_ext_reach_ipv4(lsp, area, tlv_data);
+ lsp_build_ext_reach_ipv6(lsp, area, tlv_data);
}
/*
- * Builds the LSP data part. This func creates a new frag whenever
+ * Builds the LSP data part. This func creates a new frag whenever
* area->lsp_frag_threshold is exceeded.
*/
-static void
-lsp_build (struct isis_lsp *lsp, struct isis_area *area)
+static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
{
- struct is_neigh *is_neigh;
- struct te_is_neigh *te_is_neigh;
- struct listnode *node, *ipnode;
- int level = lsp->level;
- struct isis_circuit *circuit;
- struct prefix_ipv4 *ipv4;
- struct ipv4_reachability *ipreach;
- struct te_ipv4_reachability *te_ipreach;
- struct isis_adjacency *nei;
- struct prefix_ipv6 *ipv6, ip6prefix;
- struct ipv6_reachability *ip6reach;
- struct tlvs tlv_data;
- struct isis_lsp *lsp0 = lsp;
- struct in_addr *routerid;
- uint32_t expected = 0, found = 0;
- uint32_t metric;
- u_char zero_id[ISIS_SYS_ID_LEN + 1];
- int retval = ISIS_OK;
- char buf[BUFSIZ];
-
- lsp_debug("ISIS (%s): Constructing local system LSP for level %d", area->area_tag, level);
-
- /*
- * Building the zero lsp
- */
- memset (zero_id, 0, ISIS_SYS_ID_LEN + 1);
-
- /* Reset stream endp. Stream is always there and on every LSP refresh only
- * TLV part of it is overwritten. So we must seek past header we will not
- * touch. */
- stream_reset (lsp->pdu);
- stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
-
- /*
- * Add the authentication info if its present
- */
- lsp_auth_add (lsp);
-
- /*
- * First add the tlvs related to area
- */
-
- /* Area addresses */
- if (lsp->tlv_data.area_addrs == NULL)
- lsp->tlv_data.area_addrs = list_new ();
- list_add_list (lsp->tlv_data.area_addrs, area->area_addrs);
- if (listcount (lsp->tlv_data.area_addrs) > 0)
- tlv_add_area_addrs (lsp->tlv_data.area_addrs, lsp->pdu);
-
- /* Protocols Supported */
- if (area->ip_circuits > 0 || area->ipv6_circuits > 0)
- {
- lsp->tlv_data.nlpids = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct nlpids));
- lsp->tlv_data.nlpids->count = 0;
- if (area->ip_circuits > 0)
- {
- lsp_debug("ISIS (%s): Found IPv4 circuit, adding IPv4 to NLPIDs", area->area_tag);
- lsp->tlv_data.nlpids->count++;
- lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP;
- }
- if (area->ipv6_circuits > 0)
- {
- lsp_debug("ISIS (%s): Found IPv6 circuit, adding IPv6 to NLPIDs", area->area_tag);
- lsp->tlv_data.nlpids->count++;
- lsp->tlv_data.nlpids->nlpids[lsp->tlv_data.nlpids->count - 1] =
- NLPID_IPV6;
+ struct is_neigh *is_neigh;
+ struct te_is_neigh *te_is_neigh;
+ struct listnode *node, *ipnode;
+ int level = lsp->level;
+ struct isis_circuit *circuit;
+ struct prefix_ipv4 *ipv4;
+ struct ipv4_reachability *ipreach;
+ struct te_ipv4_reachability *te_ipreach;
+ struct isis_adjacency *nei;
+ struct prefix_ipv6 *ipv6, ip6prefix;
+ struct ipv6_reachability *ip6reach;
+ struct tlvs tlv_data;
+ struct isis_lsp *lsp0 = lsp;
+ struct in_addr *routerid;
+ uint32_t expected = 0, found = 0;
+ uint32_t metric;
+ u_char zero_id[ISIS_SYS_ID_LEN + 1];
+ int retval = ISIS_OK;
+ char buf[BUFSIZ];
+
+ lsp_debug("ISIS (%s): Constructing local system LSP for level %d",
+ area->area_tag, level);
+
+ /*
+ * Building the zero lsp
+ */
+ memset(zero_id, 0, ISIS_SYS_ID_LEN + 1);
+
+ /* Reset stream endp. Stream is always there and on every LSP refresh
+ * only
+ * TLV part of it is overwritten. So we must seek past header we will
+ * not
+ * touch. */
+ stream_reset(lsp->pdu);
+ stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
+
+ /*
+ * Add the authentication info if its present
+ */
+ lsp_auth_add(lsp);
+
+ /*
+ * First add the tlvs related to area
+ */
+
+ /* Area addresses */
+ if (lsp->tlv_data.area_addrs == NULL)
+ lsp->tlv_data.area_addrs = list_new();
+ list_add_list(lsp->tlv_data.area_addrs, area->area_addrs);
+ if (listcount(lsp->tlv_data.area_addrs) > 0)
+ tlv_add_area_addrs(lsp->tlv_data.area_addrs, lsp->pdu);
+
+ /* Protocols Supported */
+ if (area->ip_circuits > 0 || area->ipv6_circuits > 0) {
+ lsp->tlv_data.nlpids =
+ XCALLOC(MTYPE_ISIS_TLV, sizeof(struct nlpids));
+ lsp->tlv_data.nlpids->count = 0;
+ if (area->ip_circuits > 0) {
+ lsp_debug(
+ "ISIS (%s): Found IPv4 circuit, adding IPv4 to NLPIDs",
+ area->area_tag);
+ lsp->tlv_data.nlpids->count++;
+ lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP;
+ }
+ if (area->ipv6_circuits > 0) {
+ lsp_debug(
+ "ISIS (%s): Found IPv6 circuit, adding IPv6 to NLPIDs",
+ area->area_tag);
+ lsp->tlv_data.nlpids->count++;
+ lsp->tlv_data.nlpids
+ ->nlpids[lsp->tlv_data.nlpids->count - 1] =
+ NLPID_IPV6;
+ }
+ tlv_add_nlpid(lsp->tlv_data.nlpids, lsp->pdu);
}
- tlv_add_nlpid (lsp->tlv_data.nlpids, lsp->pdu);
- }
-
- /* Dynamic Hostname */
- if (area->dynhostname)
- {
- const char *hostname = unix_hostname();
- size_t hostname_len = strlen(hostname);
-
- lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV,
- sizeof (struct hostname));
-
- strncpy((char *)lsp->tlv_data.hostname->name, hostname,
- sizeof(lsp->tlv_data.hostname->name));
- if (hostname_len <= MAX_TLV_LEN)
- lsp->tlv_data.hostname->namelen = hostname_len;
- else
- lsp->tlv_data.hostname->namelen = MAX_TLV_LEN;
-
- lsp_debug("ISIS (%s): Adding dynamic hostname '%.*s'", area->area_tag,
- lsp->tlv_data.hostname->namelen, lsp->tlv_data.hostname->name);
- tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu);
- }
- else
- {
- lsp_debug("ISIS (%s): Not adding dynamic hostname (disabled)", area->area_tag);
- }
-
- /* IPv4 address and TE router ID TLVs. In case of the first one we don't
- * follow "C" vendor, but "J" vendor behavior - one IPv4 address is put into
- * LSP and this address is same as router id. */
- if (isis->router_id != 0)
- {
- inet_ntop(AF_INET, &isis->router_id, buf, sizeof(buf));
- lsp_debug("ISIS (%s): Adding router ID %s as IPv4 tlv.", area->area_tag, buf);
- if (lsp->tlv_data.ipv4_addrs == NULL)
- {
- lsp->tlv_data.ipv4_addrs = list_new ();
- lsp->tlv_data.ipv4_addrs->del = free_tlv;
+
+ /* Dynamic Hostname */
+ if (area->dynhostname) {
+ const char *hostname = unix_hostname();
+ size_t hostname_len = strlen(hostname);
+
+ lsp->tlv_data.hostname =
+ XMALLOC(MTYPE_ISIS_TLV, sizeof(struct hostname));
+
+ strncpy((char *)lsp->tlv_data.hostname->name, hostname,
+ sizeof(lsp->tlv_data.hostname->name));
+ if (hostname_len <= MAX_TLV_LEN)
+ lsp->tlv_data.hostname->namelen = hostname_len;
+ else
+ lsp->tlv_data.hostname->namelen = MAX_TLV_LEN;
+
+ lsp_debug("ISIS (%s): Adding dynamic hostname '%.*s'",
+ area->area_tag, lsp->tlv_data.hostname->namelen,
+ lsp->tlv_data.hostname->name);
+ tlv_add_dynamic_hostname(lsp->tlv_data.hostname, lsp->pdu);
+ } else {
+ lsp_debug("ISIS (%s): Not adding dynamic hostname (disabled)",
+ area->area_tag);
}
- routerid = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct in_addr));
- routerid->s_addr = isis->router_id;
- listnode_add (lsp->tlv_data.ipv4_addrs, routerid);
- tlv_add_in_addr (routerid, lsp->pdu, IPV4_ADDR);
-
- /* Exactly same data is put into TE router ID TLV, but only if new style
- * TLV's are in use. */
- if (area->newmetric)
- {
- lsp_debug("ISIS (%s): Adding router ID also as TE router ID tlv.", area->area_tag);
- lsp->tlv_data.router_id = XMALLOC (MTYPE_ISIS_TLV,
- sizeof (struct in_addr));
- lsp->tlv_data.router_id->id.s_addr = isis->router_id;
- tlv_add_in_addr (&lsp->tlv_data.router_id->id, lsp->pdu,
- TE_ROUTER_ID);
+ /* IPv4 address and TE router ID TLVs. In case of the first one we don't
+ * follow "C" vendor, but "J" vendor behavior - one IPv4 address is put
+ * into
+ * LSP and this address is same as router id. */
+ if (isis->router_id != 0) {
+ inet_ntop(AF_INET, &isis->router_id, buf, sizeof(buf));
+ lsp_debug("ISIS (%s): Adding router ID %s as IPv4 tlv.",
+ area->area_tag, buf);
+ if (lsp->tlv_data.ipv4_addrs == NULL) {
+ lsp->tlv_data.ipv4_addrs = list_new();
+ lsp->tlv_data.ipv4_addrs->del = free_tlv;
+ }
+
+ routerid = XMALLOC(MTYPE_ISIS_TLV, sizeof(struct in_addr));
+ routerid->s_addr = isis->router_id;
+ listnode_add(lsp->tlv_data.ipv4_addrs, routerid);
+ tlv_add_in_addr(routerid, lsp->pdu, IPV4_ADDR);
+
+ /* Exactly same data is put into TE router ID TLV, but only if
+ * new style
+ * TLV's are in use. */
+ if (area->newmetric) {
+ lsp_debug(
+ "ISIS (%s): Adding router ID also as TE router ID tlv.",
+ area->area_tag);
+ lsp->tlv_data.router_id =
+ XMALLOC(MTYPE_ISIS_TLV, sizeof(struct in_addr));
+ lsp->tlv_data.router_id->id.s_addr = isis->router_id;
+ tlv_add_in_addr(&lsp->tlv_data.router_id->id, lsp->pdu,
+ TE_ROUTER_ID);
+ }
+ } else {
+ lsp_debug("ISIS (%s): Router ID is unset. Not adding tlv.",
+ area->area_tag);
}
- }
- else
- {
- lsp_debug("ISIS (%s): Router ID is unset. Not adding tlv.", area->area_tag);
- }
-
- memset (&tlv_data, 0, sizeof (struct tlvs));
-
- lsp_debug("ISIS (%s): Adding circuit specific information.", area->area_tag);
-
- /*
- * Then build lists of tlvs related to circuits
- */
- for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit))
- {
- if (!circuit->interface)
- lsp_debug("ISIS (%s): Processing %s circuit %p with unknown interface",
- area->area_tag, circuit_type2string(circuit->circ_type), circuit);
- else
- lsp_debug("ISIS (%s): Processing %s circuit %s",
- area->area_tag, circuit_type2string(circuit->circ_type), circuit->interface->name);
-
- if (circuit->state != C_STATE_UP)
- {
- lsp_debug("ISIS (%s): Circuit is not up, ignoring.", area->area_tag);
- continue;
- }
-
- /*
- * Add IPv4 internal reachability of this circuit
- */
- if (circuit->ip_router && circuit->ip_addrs &&
- circuit->ip_addrs->count > 0)
- {
- lsp_debug("ISIS (%s): Circuit has IPv4 active, adding respective TLVs.", area->area_tag);
- if (area->oldmetric)
- {
- if (tlv_data.ipv4_int_reachs == NULL)
- {
- tlv_data.ipv4_int_reachs = list_new ();
- tlv_data.ipv4_int_reachs->del = free_tlv;
+
+ memset(&tlv_data, 0, sizeof(struct tlvs));
+
+ lsp_debug("ISIS (%s): Adding circuit specific information.",
+ area->area_tag);
+
+ /*
+ * Then build lists of tlvs related to circuits
+ */
+ for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
+ if (!circuit->interface)
+ lsp_debug(
+ "ISIS (%s): Processing %s circuit %p with unknown interface",
+ area->area_tag,
+ circuit_type2string(circuit->circ_type),
+ circuit);
+ else
+ lsp_debug("ISIS (%s): Processing %s circuit %s",
+ area->area_tag,
+ circuit_type2string(circuit->circ_type),
+ circuit->interface->name);
+
+ if (circuit->state != C_STATE_UP) {
+ lsp_debug("ISIS (%s): Circuit is not up, ignoring.",
+ area->area_tag);
+ continue;
}
- for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, ipnode, ipv4))
- {
- ipreach =
- XMALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv4_reachability));
- ipreach->metrics.metric_default = circuit->metric[level - 1];
- ipreach->metrics.metric_expense = METRICS_UNSUPPORTED;
- ipreach->metrics.metric_error = METRICS_UNSUPPORTED;
- ipreach->metrics.metric_delay = METRICS_UNSUPPORTED;
- masklen2ip (ipv4->prefixlen, &ipreach->mask);
- ipreach->prefix.s_addr = ((ipreach->mask.s_addr) &
- (ipv4->prefix.s_addr));
- inet_ntop(AF_INET, &ipreach->prefix.s_addr, buf, sizeof(buf));
- lsp_debug("ISIS (%s): Adding old-style IP reachability for %s/%d",
- area->area_tag, buf, ipv4->prefixlen);
- listnode_add (tlv_data.ipv4_int_reachs, ipreach);
+
+ /*
+ * Add IPv4 internal reachability of this circuit
+ */
+ if (circuit->ip_router && circuit->ip_addrs
+ && circuit->ip_addrs->count > 0) {
+ lsp_debug(
+ "ISIS (%s): Circuit has IPv4 active, adding respective TLVs.",
+ area->area_tag);
+ if (area->oldmetric) {
+ if (tlv_data.ipv4_int_reachs == NULL) {
+ tlv_data.ipv4_int_reachs = list_new();
+ tlv_data.ipv4_int_reachs->del =
+ free_tlv;
+ }
+ for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs,
+ ipnode, ipv4)) {
+ ipreach = XMALLOC(
+ MTYPE_ISIS_TLV,
+ sizeof(struct
+ ipv4_reachability));
+ ipreach->metrics.metric_default =
+ circuit->metric[level - 1];
+ ipreach->metrics.metric_expense =
+ METRICS_UNSUPPORTED;
+ ipreach->metrics.metric_error =
+ METRICS_UNSUPPORTED;
+ ipreach->metrics.metric_delay =
+ METRICS_UNSUPPORTED;
+ masklen2ip(ipv4->prefixlen,
+ &ipreach->mask);
+ ipreach->prefix.s_addr =
+ ((ipreach->mask.s_addr)
+ & (ipv4->prefix.s_addr));
+ inet_ntop(AF_INET,
+ &ipreach->prefix.s_addr, buf,
+ sizeof(buf));
+ lsp_debug(
+ "ISIS (%s): Adding old-style IP reachability for %s/%d",
+ area->area_tag, buf,
+ ipv4->prefixlen);
+ listnode_add(tlv_data.ipv4_int_reachs,
+ ipreach);
+ }
+ }
+ if (area->newmetric) {
+ if (tlv_data.te_ipv4_reachs == NULL) {
+ tlv_data.te_ipv4_reachs = list_new();
+ tlv_data.te_ipv4_reachs->del = free_tlv;
+ }
+ for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs,
+ ipnode, ipv4)) {
+ /* FIXME All this assumes that we have
+ * no sub TLVs. */
+ te_ipreach = XCALLOC(
+ MTYPE_ISIS_TLV,
+ sizeof(struct
+ te_ipv4_reachability)
+ + ((ipv4->prefixlen + 7)
+ / 8)
+ - 1);
+
+ if (area->oldmetric)
+ te_ipreach->te_metric = htonl(
+ circuit->metric[level
+ - 1]);
+ else
+ te_ipreach->te_metric = htonl(
+ circuit->te_metric
+ [level - 1]);
+
+ te_ipreach->control =
+ (ipv4->prefixlen & 0x3F);
+ memcpy(&te_ipreach->prefix_start,
+ &ipv4->prefix.s_addr,
+ (ipv4->prefixlen + 7) / 8);
+ inet_ntop(AF_INET, &ipv4->prefix.s_addr,
+ buf, sizeof(buf));
+ lsp_debug(
+ "ISIS (%s): Adding te-style IP reachability for %s/%d",
+ area->area_tag, buf,
+ ipv4->prefixlen);
+ listnode_add(tlv_data.te_ipv4_reachs,
+ te_ipreach);
+ }
+ }
}
- }
- if (area->newmetric)
- {
- if (tlv_data.te_ipv4_reachs == NULL)
- {
- tlv_data.te_ipv4_reachs = list_new ();
- tlv_data.te_ipv4_reachs->del = free_tlv;
+
+ /*
+ * Add IPv6 reachability of this circuit
+ */
+ if (circuit->ipv6_router && circuit->ipv6_non_link
+ && circuit->ipv6_non_link->count > 0) {
+
+ if (tlv_data.ipv6_reachs == NULL) {
+ tlv_data.ipv6_reachs = list_new();
+ tlv_data.ipv6_reachs->del = free_tlv;
+ }
+ for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link,
+ ipnode, ipv6)) {
+ ip6reach = XCALLOC(
+ MTYPE_ISIS_TLV,
+ sizeof(struct ipv6_reachability));
+
+ if (area->oldmetric)
+ ip6reach->metric = htonl(
+ circuit->metric[level - 1]);
+ else
+ ip6reach->metric = htonl(
+ circuit->te_metric[level - 1]);
+
+ ip6reach->control_info = 0;
+ ip6reach->prefix_len = ipv6->prefixlen;
+ memcpy(&ip6prefix, ipv6, sizeof(ip6prefix));
+ apply_mask_ipv6(&ip6prefix);
+
+ inet_ntop(AF_INET6, &ip6prefix.prefix.s6_addr,
+ buf, sizeof(buf));
+ lsp_debug(
+ "ISIS (%s): Adding IPv6 reachability for %s/%d",
+ area->area_tag, buf, ipv6->prefixlen);
+
+ memcpy(ip6reach->prefix,
+ ip6prefix.prefix.s6_addr,
+ sizeof(ip6reach->prefix));
+ listnode_add(tlv_data.ipv6_reachs, ip6reach);
+ }
}
- for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, ipnode, ipv4))
- {
- /* FIXME All this assumes that we have no sub TLVs. */
- te_ipreach = XCALLOC (MTYPE_ISIS_TLV,
- sizeof (struct te_ipv4_reachability) +
- ((ipv4->prefixlen + 7)/8) - 1);
-
- if (area->oldmetric)
- te_ipreach->te_metric = htonl (circuit->metric[level - 1]);
- else
- te_ipreach->te_metric = htonl (circuit->te_metric[level - 1]);
-
- te_ipreach->control = (ipv4->prefixlen & 0x3F);
- memcpy (&te_ipreach->prefix_start, &ipv4->prefix.s_addr,
- (ipv4->prefixlen + 7)/8);
- inet_ntop(AF_INET, &ipv4->prefix.s_addr, buf, sizeof(buf));
- lsp_debug("ISIS (%s): Adding te-style IP reachability for %s/%d",
- area->area_tag, buf, ipv4->prefixlen);
- listnode_add (tlv_data.te_ipv4_reachs, te_ipreach);
+
+ switch (circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ if (level & circuit->is_type) {
+ if (area->oldmetric) {
+ if (tlv_data.is_neighs == NULL) {
+ tlv_data.is_neighs = list_new();
+ tlv_data.is_neighs->del =
+ free_tlv;
+ }
+ is_neigh = XCALLOC(
+ MTYPE_ISIS_TLV,
+ sizeof(struct is_neigh));
+ if (level == IS_LEVEL_1)
+ memcpy(is_neigh->neigh_id,
+ circuit->u.bc
+ .l1_desig_is,
+ ISIS_SYS_ID_LEN + 1);
+ else
+ memcpy(is_neigh->neigh_id,
+ circuit->u.bc
+ .l2_desig_is,
+ ISIS_SYS_ID_LEN + 1);
+ is_neigh->metrics.metric_default =
+ circuit->metric[level - 1];
+ is_neigh->metrics.metric_expense =
+ METRICS_UNSUPPORTED;
+ is_neigh->metrics.metric_error =
+ METRICS_UNSUPPORTED;
+ is_neigh->metrics.metric_delay =
+ METRICS_UNSUPPORTED;
+ if (!memcmp(is_neigh->neigh_id, zero_id,
+ ISIS_SYS_ID_LEN + 1)) {
+ XFREE(MTYPE_ISIS_TLV, is_neigh);
+ lsp_debug(
+ "ISIS (%s): No DIS for circuit, not adding old-style IS neighbor.",
+ area->area_tag);
+ } else {
+ listnode_add(tlv_data.is_neighs,
+ is_neigh);
+ lsp_debug(
+ "ISIS (%s): Adding DIS %s.%02x as old-style neighbor",
+ area->area_tag,
+ sysid_print(
+ is_neigh->neigh_id),
+ LSP_PSEUDO_ID(
+ is_neigh->neigh_id));
+ }
+ }
+ if (area->newmetric) {
+ if (tlv_data.te_is_neighs == NULL) {
+ tlv_data.te_is_neighs =
+ list_new();
+ tlv_data.te_is_neighs->del =
+ free_tlv;
+ }
+ te_is_neigh = XCALLOC(
+ MTYPE_ISIS_TLV,
+ sizeof(struct te_is_neigh));
+ if (level == IS_LEVEL_1)
+ memcpy(te_is_neigh->neigh_id,
+ circuit->u.bc
+ .l1_desig_is,
+ ISIS_SYS_ID_LEN + 1);
+ else
+ memcpy(te_is_neigh->neigh_id,
+ circuit->u.bc
+ .l2_desig_is,
+ ISIS_SYS_ID_LEN + 1);
+ if (area->oldmetric)
+ metric = circuit->metric[level
+ - 1];
+ else
+ metric =
+ circuit->te_metric[level
+ - 1];
+ SET_TE_METRIC(te_is_neigh, metric);
+ if (!memcmp(te_is_neigh->neigh_id,
+ zero_id,
+ ISIS_SYS_ID_LEN + 1)) {
+ XFREE(MTYPE_ISIS_TLV,
+ te_is_neigh);
+ lsp_debug(
+ "ISIS (%s): No DIS for circuit, not adding te-style IS neighbor.",
+ area->area_tag);
+ } else {
+ /* Check if MPLS_TE is activate
+ */
+ if (IS_MPLS_TE(isisMplsTE)
+ && HAS_LINK_PARAMS(
+ circuit->interface))
+ /* Add SubTLVs & Adjust
+ * real size of SubTLVs
+ */
+ te_is_neigh
+ ->sub_tlvs_length = add_te_subtlvs(
+ te_is_neigh
+ ->sub_tlvs,
+ circuit->mtc);
+ else
+ /* Or keep only TE
+ * metric with no
+ * SubTLVs if MPLS_TE is
+ * off */
+ te_is_neigh
+ ->sub_tlvs_length =
+ 0;
+
+ listnode_add(
+ tlv_data.te_is_neighs,
+ te_is_neigh);
+ lsp_debug(
+ "ISIS (%s): Adding DIS %s.%02x as te-style neighbor",
+ area->area_tag,
+ sysid_print(
+ te_is_neigh
+ ->neigh_id),
+ LSP_PSEUDO_ID(
+ te_is_neigh
+ ->neigh_id));
+ }
+ }
+ } else {
+ lsp_debug(
+ "ISIS (%s): Circuit is not active for current level. Not adding IS neighbors",
+ area->area_tag);
+ }
+ break;
+ case CIRCUIT_T_P2P:
+ nei = circuit->u.p2p.neighbor;
+ if (nei && (level & nei->circuit_t)) {
+ if (area->oldmetric) {
+ if (tlv_data.is_neighs == NULL) {
+ tlv_data.is_neighs = list_new();
+ tlv_data.is_neighs->del =
+ free_tlv;
+ }
+ is_neigh = XCALLOC(
+ MTYPE_ISIS_TLV,
+ sizeof(struct is_neigh));
+ memcpy(is_neigh->neigh_id, nei->sysid,
+ ISIS_SYS_ID_LEN);
+ is_neigh->metrics.metric_default =
+ circuit->metric[level - 1];
+ is_neigh->metrics.metric_expense =
+ METRICS_UNSUPPORTED;
+ is_neigh->metrics.metric_error =
+ METRICS_UNSUPPORTED;
+ is_neigh->metrics.metric_delay =
+ METRICS_UNSUPPORTED;
+ listnode_add(tlv_data.is_neighs,
+ is_neigh);
+ lsp_debug(
+ "ISIS (%s): Adding old-style is reach for %s",
+ area->area_tag,
+ sysid_print(
+ is_neigh->neigh_id));
+ }
+ if (area->newmetric) {
+ uint32_t metric;
+
+ if (tlv_data.te_is_neighs == NULL) {
+ tlv_data.te_is_neighs =
+ list_new();
+ tlv_data.te_is_neighs->del =
+ free_tlv;
+ }
+ te_is_neigh = XCALLOC(
+ MTYPE_ISIS_TLV,
+ sizeof(struct te_is_neigh));
+ memcpy(te_is_neigh->neigh_id,
+ nei->sysid, ISIS_SYS_ID_LEN);
+ metric = circuit->te_metric[level - 1];
+ SET_TE_METRIC(te_is_neigh, metric);
+ /* Check if MPLS_TE is activate */
+ if (IS_MPLS_TE(isisMplsTE)
+ && HAS_LINK_PARAMS(
+ circuit->interface))
+ /* Update Local and Remote IP
+ * address for MPLS TE circuit
+ * parameters */
+ /* NOTE sure that it is the
+ * pertinent place for that
+ * updates */
+ /* Local IP address could be
+ * updated in isis_circuit.c -
+ * isis_circuit_add_addr() */
+ /* But, where update remote IP
+ * address ? in isis_pdu.c -
+ * process_p2p_hello() ? */
+
+ /* Add SubTLVs & Adjust real
+ * size of SubTLVs */
+ te_is_neigh->sub_tlvs_length =
+ add_te_subtlvs(
+ te_is_neigh
+ ->sub_tlvs,
+ circuit->mtc);
+ else
+ /* Or keep only TE metric with
+ * no SubTLVs if MPLS_TE is off
+ */
+ te_is_neigh->sub_tlvs_length =
+ 0;
+ listnode_add(tlv_data.te_is_neighs,
+ te_is_neigh);
+ lsp_debug(
+ "ISIS (%s): Adding te-style is reach for %s",
+ area->area_tag,
+ sysid_print(
+ te_is_neigh->neigh_id));
+ }
+ } else {
+ lsp_debug(
+ "ISIS (%s): No adjacency for given level on this circuit. Not adding IS neighbors",
+ area->area_tag);
+ }
+ break;
+ case CIRCUIT_T_LOOPBACK:
+ break;
+ default:
+ zlog_warn("lsp_area_create: unknown circuit type");
}
- }
}
- /*
- * Add IPv6 reachability of this circuit
- */
- if (circuit->ipv6_router && circuit->ipv6_non_link &&
- circuit->ipv6_non_link->count > 0)
- {
-
- if (tlv_data.ipv6_reachs == NULL)
- {
- tlv_data.ipv6_reachs = list_new ();
- tlv_data.ipv6_reachs->del = free_tlv;
- }
- for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, ipnode, ipv6))
- {
- ip6reach =
- XCALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv6_reachability));
-
- if (area->oldmetric)
- ip6reach->metric =
- htonl (circuit->metric[level - 1]);
- else
- ip6reach->metric = htonl (circuit->te_metric[level - 1]);
-
- ip6reach->control_info = 0;
- ip6reach->prefix_len = ipv6->prefixlen;
- memcpy(&ip6prefix, ipv6, sizeof(ip6prefix));
- apply_mask_ipv6(&ip6prefix);
-
- inet_ntop(AF_INET6, &ip6prefix.prefix.s6_addr, buf, sizeof(buf));
- lsp_debug("ISIS (%s): Adding IPv6 reachability for %s/%d",
- area->area_tag, buf, ipv6->prefixlen);
-
- memcpy (ip6reach->prefix, ip6prefix.prefix.s6_addr,
- sizeof (ip6reach->prefix));
- listnode_add (tlv_data.ipv6_reachs, ip6reach);
- }
+ lsp_build_ext_reach(lsp, area, &tlv_data);
+
+ lsp_debug("ISIS (%s): LSP construction is complete. Serializing...",
+ area->area_tag);
+
+ while (tlv_data.ipv4_int_reachs
+ && listcount(tlv_data.ipv4_int_reachs)) {
+ if (lsp->tlv_data.ipv4_int_reachs == NULL)
+ lsp->tlv_data.ipv4_int_reachs = list_new();
+ lsp_tlv_fit(lsp, &tlv_data.ipv4_int_reachs,
+ &lsp->tlv_data.ipv4_int_reachs, IPV4_REACH_LEN,
+ area->lsp_frag_threshold, tlv_add_ipv4_int_reachs);
+ if (tlv_data.ipv4_int_reachs
+ && listcount(tlv_data.ipv4_int_reachs))
+ lsp = lsp_next_frag(
+ LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0,
+ area, level);
}
- switch (circuit->circ_type)
- {
- case CIRCUIT_T_BROADCAST:
- if (level & circuit->is_type)
- {
- if (area->oldmetric)
- {
- if (tlv_data.is_neighs == NULL)
- {
- tlv_data.is_neighs = list_new ();
- tlv_data.is_neighs->del = free_tlv;
- }
- is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
- if (level == IS_LEVEL_1)
- memcpy (is_neigh->neigh_id,
- circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
- else
- memcpy (is_neigh->neigh_id,
- circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
- is_neigh->metrics.metric_default = circuit->metric[level - 1];
- is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
- is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
- is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
- if (!memcmp (is_neigh->neigh_id, zero_id,
- ISIS_SYS_ID_LEN + 1))
- {
- XFREE (MTYPE_ISIS_TLV, is_neigh);
- lsp_debug("ISIS (%s): No DIS for circuit, not adding old-style IS neighbor.",
- area->area_tag);
- }
- else
- {
- listnode_add (tlv_data.is_neighs, is_neigh);
- lsp_debug("ISIS (%s): Adding DIS %s.%02x as old-style neighbor",
- area->area_tag, sysid_print(is_neigh->neigh_id),
- LSP_PSEUDO_ID(is_neigh->neigh_id));
- }
- }
- if (area->newmetric)
- {
- if (tlv_data.te_is_neighs == NULL)
- {
- tlv_data.te_is_neighs = list_new ();
- tlv_data.te_is_neighs->del = free_tlv;
- }
- te_is_neigh = XCALLOC (MTYPE_ISIS_TLV,
- sizeof (struct te_is_neigh));
- if (level == IS_LEVEL_1)
- memcpy (te_is_neigh->neigh_id,
- circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
- else
- memcpy (te_is_neigh->neigh_id,
- circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
- if (area->oldmetric)
- metric = circuit->metric[level - 1];
- else
- metric = circuit->te_metric[level - 1];
- SET_TE_METRIC(te_is_neigh, metric);
- if (!memcmp (te_is_neigh->neigh_id, zero_id,
- ISIS_SYS_ID_LEN + 1))
- {
- XFREE (MTYPE_ISIS_TLV, te_is_neigh);
- lsp_debug("ISIS (%s): No DIS for circuit, not adding te-style IS neighbor.",
- area->area_tag);
- }
- else
- {
- /* Check if MPLS_TE is activate */
- if (IS_MPLS_TE(isisMplsTE) && HAS_LINK_PARAMS(circuit->interface))
- /* Add SubTLVs & Adjust real size of SubTLVs */
- te_is_neigh->sub_tlvs_length = add_te_subtlvs(te_is_neigh->sub_tlvs, circuit->mtc);
- else
- /* Or keep only TE metric with no SubTLVs if MPLS_TE is off */
- te_is_neigh->sub_tlvs_length = 0;
-
- listnode_add (tlv_data.te_is_neighs, te_is_neigh);
- lsp_debug("ISIS (%s): Adding DIS %s.%02x as te-style neighbor",
- area->area_tag, sysid_print(te_is_neigh->neigh_id),
- LSP_PSEUDO_ID(te_is_neigh->neigh_id));
- }
- }
- }
- else
- {
- lsp_debug("ISIS (%s): Circuit is not active for current level. Not adding IS neighbors",
- area->area_tag);
- }
- break;
- case CIRCUIT_T_P2P:
- nei = circuit->u.p2p.neighbor;
- if (nei && (level & nei->circuit_t))
- {
- if (area->oldmetric)
- {
- if (tlv_data.is_neighs == NULL)
- {
- tlv_data.is_neighs = list_new ();
- tlv_data.is_neighs->del = free_tlv;
- }
- is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
- memcpy (is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN);
- is_neigh->metrics.metric_default = circuit->metric[level - 1];
- is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
- is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
- is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
- listnode_add (tlv_data.is_neighs, is_neigh);
- lsp_debug("ISIS (%s): Adding old-style is reach for %s", area->area_tag,
- sysid_print(is_neigh->neigh_id));
- }
- if (area->newmetric)
- {
- uint32_t metric;
-
- if (tlv_data.te_is_neighs == NULL)
- {
- tlv_data.te_is_neighs = list_new ();
- tlv_data.te_is_neighs->del = free_tlv;
- }
- te_is_neigh = XCALLOC (MTYPE_ISIS_TLV,
- sizeof (struct te_is_neigh));
- memcpy (te_is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN);
- metric = circuit->te_metric[level - 1];
- SET_TE_METRIC(te_is_neigh, metric);
- /* Check if MPLS_TE is activate */
- if (IS_MPLS_TE(isisMplsTE) && HAS_LINK_PARAMS(circuit->interface))
- /* Update Local and Remote IP address for MPLS TE circuit parameters */
- /* NOTE sure that it is the pertinent place for that updates */
- /* Local IP address could be updated in isis_circuit.c - isis_circuit_add_addr() */
- /* But, where update remote IP address ? in isis_pdu.c - process_p2p_hello() ? */
-
- /* Add SubTLVs & Adjust real size of SubTLVs */
- te_is_neigh->sub_tlvs_length = add_te_subtlvs(te_is_neigh->sub_tlvs, circuit->mtc);
- else
- /* Or keep only TE metric with no SubTLVs if MPLS_TE is off */
- te_is_neigh->sub_tlvs_length = 0;
- listnode_add (tlv_data.te_is_neighs, te_is_neigh);
- lsp_debug("ISIS (%s): Adding te-style is reach for %s", area->area_tag,
- sysid_print(te_is_neigh->neigh_id));
- }
- }
- else
- {
- lsp_debug("ISIS (%s): No adjacency for given level on this circuit. Not adding IS neighbors",
- area->area_tag);
- }
- break;
- case CIRCUIT_T_LOOPBACK:
- break;
- default:
- zlog_warn ("lsp_area_create: unknown circuit type");
+ while (tlv_data.ipv4_ext_reachs
+ && listcount(tlv_data.ipv4_ext_reachs)) {
+ if (lsp->tlv_data.ipv4_ext_reachs == NULL)
+ lsp->tlv_data.ipv4_ext_reachs = list_new();
+ lsp_tlv_fit(lsp, &tlv_data.ipv4_ext_reachs,
+ &lsp->tlv_data.ipv4_ext_reachs, IPV4_REACH_LEN,
+ area->lsp_frag_threshold, tlv_add_ipv4_ext_reachs);
+ if (tlv_data.ipv4_ext_reachs
+ && listcount(tlv_data.ipv4_ext_reachs))
+ lsp = lsp_next_frag(
+ LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0,
+ area, level);
+ }
+
+ /* FIXME: We pass maximum te_ipv4_reachability length to the
+ * lsp_tlv_fit()
+ * for now. lsp_tlv_fit() needs to be fixed to deal with variable length
+ * TLVs (sub TLVs!). */
+ while (tlv_data.te_ipv4_reachs && listcount(tlv_data.te_ipv4_reachs)) {
+ if (lsp->tlv_data.te_ipv4_reachs == NULL)
+ lsp->tlv_data.te_ipv4_reachs = list_new();
+ lsp_tlv_fit(lsp, &tlv_data.te_ipv4_reachs,
+ &lsp->tlv_data.te_ipv4_reachs, TE_IPV4_REACH_LEN,
+ area->lsp_frag_threshold, tlv_add_te_ipv4_reachs);
+ if (tlv_data.te_ipv4_reachs
+ && listcount(tlv_data.te_ipv4_reachs))
+ lsp = lsp_next_frag(
+ LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0,
+ area, level);
+ }
+
+ while (tlv_data.ipv6_reachs && listcount(tlv_data.ipv6_reachs)) {
+ if (lsp->tlv_data.ipv6_reachs == NULL)
+ lsp->tlv_data.ipv6_reachs = list_new();
+ lsp_tlv_fit(lsp, &tlv_data.ipv6_reachs,
+ &lsp->tlv_data.ipv6_reachs, IPV6_REACH_LEN,
+ area->lsp_frag_threshold, tlv_add_ipv6_reachs);
+ if (tlv_data.ipv6_reachs && listcount(tlv_data.ipv6_reachs))
+ lsp = lsp_next_frag(
+ LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0,
+ area, level);
}
- }
-
- lsp_build_ext_reach(lsp, area, &tlv_data);
-
- lsp_debug("ISIS (%s): LSP construction is complete. Serializing...", area->area_tag);
-
- while (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs))
- {
- if (lsp->tlv_data.ipv4_int_reachs == NULL)
- lsp->tlv_data.ipv4_int_reachs = list_new ();
- lsp_tlv_fit (lsp, &tlv_data.ipv4_int_reachs,
- &lsp->tlv_data.ipv4_int_reachs,
- IPV4_REACH_LEN, area->lsp_frag_threshold,
- tlv_add_ipv4_int_reachs);
- if (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs))
- lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
- lsp0, area, level);
- }
-
- while (tlv_data.ipv4_ext_reachs && listcount (tlv_data.ipv4_ext_reachs))
- {
- if (lsp->tlv_data.ipv4_ext_reachs == NULL)
- lsp->tlv_data.ipv4_ext_reachs = list_new ();
- lsp_tlv_fit (lsp, &tlv_data.ipv4_ext_reachs,
- &lsp->tlv_data.ipv4_ext_reachs,
- IPV4_REACH_LEN, area->lsp_frag_threshold,
- tlv_add_ipv4_ext_reachs);
- if (tlv_data.ipv4_ext_reachs && listcount (tlv_data.ipv4_ext_reachs))
- lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
- lsp0, area, level);
- }
-
- /* FIXME: We pass maximum te_ipv4_reachability length to the lsp_tlv_fit()
- * for now. lsp_tlv_fit() needs to be fixed to deal with variable length
- * TLVs (sub TLVs!). */
- while (tlv_data.te_ipv4_reachs && listcount (tlv_data.te_ipv4_reachs))
- {
- if (lsp->tlv_data.te_ipv4_reachs == NULL)
- lsp->tlv_data.te_ipv4_reachs = list_new ();
- lsp_tlv_fit (lsp, &tlv_data.te_ipv4_reachs,
- &lsp->tlv_data.te_ipv4_reachs,
- TE_IPV4_REACH_LEN, area->lsp_frag_threshold,
- tlv_add_te_ipv4_reachs);
- if (tlv_data.te_ipv4_reachs && listcount (tlv_data.te_ipv4_reachs))
- lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
- lsp0, area, level);
- }
-
- while (tlv_data.ipv6_reachs && listcount (tlv_data.ipv6_reachs))
- {
- if (lsp->tlv_data.ipv6_reachs == NULL)
- lsp->tlv_data.ipv6_reachs = list_new ();
- lsp_tlv_fit (lsp, &tlv_data.ipv6_reachs,
- &lsp->tlv_data.ipv6_reachs,
- IPV6_REACH_LEN, area->lsp_frag_threshold,
- tlv_add_ipv6_reachs);
- if (tlv_data.ipv6_reachs && listcount (tlv_data.ipv6_reachs))
- lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
- lsp0, area, level);
- }
-
- while (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
- {
- if (lsp->tlv_data.is_neighs == NULL)
- lsp->tlv_data.is_neighs = list_new ();
- lsp_tlv_fit (lsp, &tlv_data.is_neighs,
- &lsp->tlv_data.is_neighs,
- IS_NEIGHBOURS_LEN, area->lsp_frag_threshold,
- tlv_add_is_neighs);
- if (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
- lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
- lsp0, area, level);
- }
-
- while (tlv_data.te_is_neighs && listcount (tlv_data.te_is_neighs))
- {
- if (lsp->tlv_data.te_is_neighs == NULL)
- lsp->tlv_data.te_is_neighs = list_new ();
- lsp_tlv_fit (lsp, &tlv_data.te_is_neighs, &lsp->tlv_data.te_is_neighs,
- IS_NEIGHBOURS_LEN, area->lsp_frag_threshold,
- tlv_add_te_is_neighs);
- if (tlv_data.te_is_neighs && listcount (tlv_data.te_is_neighs))
- lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
- lsp0, area, level);
- }
- lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
-
- free_tlvs (&tlv_data);
-
- /* Validate the LSP */
- retval = parse_tlvs (area->area_tag, STREAM_DATA (lsp->pdu) +
- ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN,
- stream_get_endp (lsp->pdu) -
- ISIS_FIXED_HDR_LEN - ISIS_LSP_HDR_LEN,
- &expected, &found, &tlv_data, NULL);
- assert (retval == ISIS_OK);
-
- return;
+
+ while (tlv_data.is_neighs && listcount(tlv_data.is_neighs)) {
+ if (lsp->tlv_data.is_neighs == NULL)
+ lsp->tlv_data.is_neighs = list_new();
+ lsp_tlv_fit(lsp, &tlv_data.is_neighs, &lsp->tlv_data.is_neighs,
+ IS_NEIGHBOURS_LEN, area->lsp_frag_threshold,
+ tlv_add_is_neighs);
+ if (tlv_data.is_neighs && listcount(tlv_data.is_neighs))
+ lsp = lsp_next_frag(
+ LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0,
+ area, level);
+ }
+
+ while (tlv_data.te_is_neighs && listcount(tlv_data.te_is_neighs)) {
+ if (lsp->tlv_data.te_is_neighs == NULL)
+ lsp->tlv_data.te_is_neighs = list_new();
+ lsp_tlv_fit(lsp, &tlv_data.te_is_neighs,
+ &lsp->tlv_data.te_is_neighs, IS_NEIGHBOURS_LEN,
+ area->lsp_frag_threshold, tlv_add_te_is_neighs);
+ if (tlv_data.te_is_neighs && listcount(tlv_data.te_is_neighs))
+ lsp = lsp_next_frag(
+ LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0,
+ area, level);
+ }
+ lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu));
+
+ free_tlvs(&tlv_data);
+
+ /* Validate the LSP */
+ retval = parse_tlvs(area->area_tag,
+ STREAM_DATA(lsp->pdu) + ISIS_FIXED_HDR_LEN
+ + ISIS_LSP_HDR_LEN,
+ stream_get_endp(lsp->pdu) - ISIS_FIXED_HDR_LEN
+ - ISIS_LSP_HDR_LEN,
+ &expected, &found, &tlv_data, NULL);
+ assert(retval == ISIS_OK);
+
+ return;
}
/*
* 7.3.7 and 7.3.9 Generation on non-pseudonode LSPs
*/
-int
-lsp_generate (struct isis_area *area, int level)
+int lsp_generate(struct isis_area *area, int level)
{
- struct isis_lsp *oldlsp, *newlsp;
- u_int32_t seq_num = 0;
- u_char lspid[ISIS_SYS_ID_LEN + 2];
- u_int16_t rem_lifetime, refresh_time;
-
- if ((area == NULL) || (area->is_type & level) != level)
- return ISIS_ERROR;
-
- memset (&lspid, 0, ISIS_SYS_ID_LEN + 2);
- memcpy (&lspid, isis->sysid, ISIS_SYS_ID_LEN);
-
- /* only builds the lsp if the area shares the level */
- oldlsp = lsp_search (lspid, area->lspdb[level - 1]);
- if (oldlsp)
- {
- /* FIXME: we should actually initiate a purge */
- seq_num = ntohl (oldlsp->lsp_header->seq_num);
- lsp_search_and_destroy (oldlsp->lsp_header->lsp_id,
- area->lspdb[level - 1]);
- }
- rem_lifetime = lsp_rem_lifetime (area, level);
- newlsp = lsp_new (area, lspid, rem_lifetime, seq_num,
- area->is_type | area->overload_bit | area->attached_bit,
- 0, level);
- newlsp->area = area;
- newlsp->own_lsp = 1;
-
- lsp_insert (newlsp, area->lspdb[level - 1]);
- /* build_lsp_data (newlsp, area); */
- lsp_build (newlsp, area);
- /* time to calculate our checksum */
- lsp_seqnum_update (newlsp);
- newlsp->last_generated = time(NULL);
- lsp_set_all_srmflags (newlsp);
-
- refresh_time = lsp_refresh_time (newlsp, rem_lifetime);
-
- THREAD_TIMER_OFF (area->t_lsp_refresh[level - 1]);
- area->lsp_regenerate_pending[level - 1] = 0;
- if (level == IS_LEVEL_1)
- THREAD_TIMER_ON (master, area->t_lsp_refresh[level - 1],
- lsp_l1_refresh, area, refresh_time);
- else if (level == IS_LEVEL_2)
- THREAD_TIMER_ON (master, area->t_lsp_refresh[level - 1],
- lsp_l2_refresh, area, refresh_time);
-
- if (isis->debugs & DEBUG_UPDATE_PACKETS)
- {
- zlog_debug ("ISIS-Upd (%s): Building L%d LSP %s, len %d, "
- "seq 0x%08x, cksum 0x%04x, lifetime %us refresh %us",
- area->area_tag, level,
- rawlspid_print (newlsp->lsp_header->lsp_id),
- ntohl (newlsp->lsp_header->pdu_len),
- ntohl (newlsp->lsp_header->seq_num),
- ntohs (newlsp->lsp_header->checksum),
- ntohs (newlsp->lsp_header->rem_lifetime),
- refresh_time);
- }
- sched_debug("ISIS (%s): Built L%d LSP. Set triggered regenerate to non-pending.",
- area->area_tag, level);
-
- return ISIS_OK;
+ struct isis_lsp *oldlsp, *newlsp;
+ u_int32_t seq_num = 0;
+ u_char lspid[ISIS_SYS_ID_LEN + 2];
+ u_int16_t rem_lifetime, refresh_time;
+
+ if ((area == NULL) || (area->is_type & level) != level)
+ return ISIS_ERROR;
+
+ memset(&lspid, 0, ISIS_SYS_ID_LEN + 2);
+ memcpy(&lspid, isis->sysid, ISIS_SYS_ID_LEN);
+
+ /* only builds the lsp if the area shares the level */
+ oldlsp = lsp_search(lspid, area->lspdb[level - 1]);
+ if (oldlsp) {
+ /* FIXME: we should actually initiate a purge */
+ seq_num = ntohl(oldlsp->lsp_header->seq_num);
+ lsp_search_and_destroy(oldlsp->lsp_header->lsp_id,
+ area->lspdb[level - 1]);
+ }
+ rem_lifetime = lsp_rem_lifetime(area, level);
+ newlsp =
+ lsp_new(area, lspid, rem_lifetime, seq_num,
+ area->is_type | area->overload_bit | area->attached_bit,
+ 0, level);
+ newlsp->area = area;
+ newlsp->own_lsp = 1;
+
+ lsp_insert(newlsp, area->lspdb[level - 1]);
+ /* build_lsp_data (newlsp, area); */
+ lsp_build(newlsp, area);
+ /* time to calculate our checksum */
+ lsp_seqnum_update(newlsp);
+ newlsp->last_generated = time(NULL);
+ lsp_set_all_srmflags(newlsp);
+
+ refresh_time = lsp_refresh_time(newlsp, rem_lifetime);
+
+ THREAD_TIMER_OFF(area->t_lsp_refresh[level - 1]);
+ area->lsp_regenerate_pending[level - 1] = 0;
+ if (level == IS_LEVEL_1)
+ THREAD_TIMER_ON(master, area->t_lsp_refresh[level - 1],
+ lsp_l1_refresh, area, refresh_time);
+ else if (level == IS_LEVEL_2)
+ THREAD_TIMER_ON(master, area->t_lsp_refresh[level - 1],
+ lsp_l2_refresh, area, refresh_time);
+
+ if (isis->debugs & DEBUG_UPDATE_PACKETS) {
+ zlog_debug(
+ "ISIS-Upd (%s): Building L%d LSP %s, len %d, "
+ "seq 0x%08x, cksum 0x%04x, lifetime %us refresh %us",
+ area->area_tag, level,
+ rawlspid_print(newlsp->lsp_header->lsp_id),
+ ntohl(newlsp->lsp_header->pdu_len),
+ ntohl(newlsp->lsp_header->seq_num),
+ ntohs(newlsp->lsp_header->checksum),
+ ntohs(newlsp->lsp_header->rem_lifetime), refresh_time);
+ }
+ sched_debug(
+ "ISIS (%s): Built L%d LSP. Set triggered regenerate to non-pending.",
+ area->area_tag, level);
+
+ return ISIS_OK;
}
/*
* Search own LSPs, update holding time and set SRM
*/
-static int
-lsp_regenerate (struct isis_area *area, int level)
+static int lsp_regenerate(struct isis_area *area, int level)
{
- dict_t *lspdb;
- struct isis_lsp *lsp, *frag;
- struct listnode *node;
- u_char lspid[ISIS_SYS_ID_LEN + 2];
- u_int16_t rem_lifetime, refresh_time;
-
- if ((area == NULL) || (area->is_type & level) != level)
- return ISIS_ERROR;
-
- lspdb = area->lspdb[level - 1];
-
- memset (lspid, 0, ISIS_SYS_ID_LEN + 2);
- memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN);
-
- lsp = lsp_search (lspid, lspdb);
-
- if (!lsp)
- {
- zlog_err ("ISIS-Upd (%s): lsp_regenerate: no L%d LSP found!",
- area->area_tag, level);
- return ISIS_ERROR;
- }
-
- lsp_clear_data (lsp);
- lsp_build (lsp, area);
- lsp->lsp_header->lsp_bits = lsp_bits_generate (level, area->overload_bit,
- area->attached_bit);
- rem_lifetime = lsp_rem_lifetime (area, level);
- lsp->lsp_header->rem_lifetime = htons (rem_lifetime);
- lsp_seqnum_update (lsp);
-
- lsp->last_generated = time (NULL);
- lsp_set_all_srmflags (lsp);
- for (ALL_LIST_ELEMENTS_RO (lsp->lspu.frags, node, frag))
- {
- frag->lsp_header->lsp_bits = lsp_bits_generate (level,
- area->overload_bit,
- area->attached_bit);
- /* Set the lifetime values of all the fragments to the same value,
- * so that no fragment expires before the lsp is refreshed.
- */
- frag->lsp_header->rem_lifetime = htons (rem_lifetime);
- lsp_set_all_srmflags (frag);
- }
-
- refresh_time = lsp_refresh_time (lsp, rem_lifetime);
- if (level == IS_LEVEL_1)
- THREAD_TIMER_ON (master, area->t_lsp_refresh[level - 1],
- lsp_l1_refresh, area, refresh_time);
- else if (level == IS_LEVEL_2)
- THREAD_TIMER_ON (master, area->t_lsp_refresh[level - 1],
- lsp_l2_refresh, area, refresh_time);
- area->lsp_regenerate_pending[level - 1] = 0;
-
- if (isis->debugs & DEBUG_UPDATE_PACKETS)
- {
- zlog_debug ("ISIS-Upd (%s): Refreshing our L%d LSP %s, len %d, "
- "seq 0x%08x, cksum 0x%04x, lifetime %us refresh %us",
- area->area_tag, level,
- rawlspid_print (lsp->lsp_header->lsp_id),
- ntohl (lsp->lsp_header->pdu_len),
- ntohl (lsp->lsp_header->seq_num),
- ntohs (lsp->lsp_header->checksum),
- ntohs (lsp->lsp_header->rem_lifetime),
- refresh_time);
- }
- sched_debug("ISIS (%s): Rebuilt L%d LSP. Set triggered regenerate to non-pending.",
- area->area_tag, level);
-
- return ISIS_OK;
+ dict_t *lspdb;
+ struct isis_lsp *lsp, *frag;
+ struct listnode *node;
+ u_char lspid[ISIS_SYS_ID_LEN + 2];
+ u_int16_t rem_lifetime, refresh_time;
+
+ if ((area == NULL) || (area->is_type & level) != level)
+ return ISIS_ERROR;
+
+ lspdb = area->lspdb[level - 1];
+
+ memset(lspid, 0, ISIS_SYS_ID_LEN + 2);
+ memcpy(lspid, isis->sysid, ISIS_SYS_ID_LEN);
+
+ lsp = lsp_search(lspid, lspdb);
+
+ if (!lsp) {
+ zlog_err("ISIS-Upd (%s): lsp_regenerate: no L%d LSP found!",
+ area->area_tag, level);
+ return ISIS_ERROR;
+ }
+
+ lsp_clear_data(lsp);
+ lsp_build(lsp, area);
+ lsp->lsp_header->lsp_bits = lsp_bits_generate(level, area->overload_bit,
+ area->attached_bit);
+ rem_lifetime = lsp_rem_lifetime(area, level);
+ lsp->lsp_header->rem_lifetime = htons(rem_lifetime);
+ lsp_seqnum_update(lsp);
+
+ lsp->last_generated = time(NULL);
+ lsp_set_all_srmflags(lsp);
+ for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) {
+ frag->lsp_header->lsp_bits = lsp_bits_generate(
+ level, area->overload_bit, area->attached_bit);
+ /* Set the lifetime values of all the fragments to the same
+ * value,
+ * so that no fragment expires before the lsp is refreshed.
+ */
+ frag->lsp_header->rem_lifetime = htons(rem_lifetime);
+ lsp_set_all_srmflags(frag);
+ }
+
+ refresh_time = lsp_refresh_time(lsp, rem_lifetime);
+ if (level == IS_LEVEL_1)
+ THREAD_TIMER_ON(master, area->t_lsp_refresh[level - 1],
+ lsp_l1_refresh, area, refresh_time);
+ else if (level == IS_LEVEL_2)
+ THREAD_TIMER_ON(master, area->t_lsp_refresh[level - 1],
+ lsp_l2_refresh, area, refresh_time);
+ area->lsp_regenerate_pending[level - 1] = 0;
+
+ if (isis->debugs & DEBUG_UPDATE_PACKETS) {
+ zlog_debug(
+ "ISIS-Upd (%s): Refreshing our L%d LSP %s, len %d, "
+ "seq 0x%08x, cksum 0x%04x, lifetime %us refresh %us",
+ area->area_tag, level,
+ rawlspid_print(lsp->lsp_header->lsp_id),
+ ntohl(lsp->lsp_header->pdu_len),
+ ntohl(lsp->lsp_header->seq_num),
+ ntohs(lsp->lsp_header->checksum),
+ ntohs(lsp->lsp_header->rem_lifetime), refresh_time);
+ }
+ sched_debug(
+ "ISIS (%s): Rebuilt L%d LSP. Set triggered regenerate to non-pending.",
+ area->area_tag, level);
+
+ return ISIS_OK;
}
/*
* Something has changed or periodic refresh -> regenerate LSP
*/
-static int
-lsp_l1_refresh (struct thread *thread)
+static int lsp_l1_refresh(struct thread *thread)
{
- struct isis_area *area;
+ struct isis_area *area;
- area = THREAD_ARG (thread);
- assert (area);
+ area = THREAD_ARG(thread);
+ assert(area);
- area->t_lsp_refresh[0] = NULL;
- area->lsp_regenerate_pending[0] = 0;
+ area->t_lsp_refresh[0] = NULL;
+ area->lsp_regenerate_pending[0] = 0;
- if ((area->is_type & IS_LEVEL_1) == 0)
- return ISIS_ERROR;
+ if ((area->is_type & IS_LEVEL_1) == 0)
+ return ISIS_ERROR;
- sched_debug("ISIS (%s): LSP L1 refresh timer expired. Refreshing LSP...", area->area_tag);
- return lsp_regenerate (area, IS_LEVEL_1);
+ sched_debug(
+ "ISIS (%s): LSP L1 refresh timer expired. Refreshing LSP...",
+ area->area_tag);
+ return lsp_regenerate(area, IS_LEVEL_1);
}
-static int
-lsp_l2_refresh (struct thread *thread)
+static int lsp_l2_refresh(struct thread *thread)
{
- struct isis_area *area;
+ struct isis_area *area;
- area = THREAD_ARG (thread);
- assert (area);
+ area = THREAD_ARG(thread);
+ assert(area);
- area->t_lsp_refresh[1] = NULL;
- area->lsp_regenerate_pending[1] = 0;
+ area->t_lsp_refresh[1] = NULL;
+ area->lsp_regenerate_pending[1] = 0;
- if ((area->is_type & IS_LEVEL_2) == 0)
- return ISIS_ERROR;
+ if ((area->is_type & IS_LEVEL_2) == 0)
+ return ISIS_ERROR;
- sched_debug("ISIS (%s): LSP L2 refresh timer expired. Refreshing LSP...", area->area_tag);
- return lsp_regenerate (area, IS_LEVEL_2);
+ sched_debug(
+ "ISIS (%s): LSP L2 refresh timer expired. Refreshing LSP...",
+ area->area_tag);
+ return lsp_regenerate(area, IS_LEVEL_2);
}
-int
-lsp_regenerate_schedule (struct isis_area *area, int level, int all_pseudo)
+int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo)
{
- struct isis_lsp *lsp;
- u_char id[ISIS_SYS_ID_LEN + 2];
- time_t now, diff;
- long timeout;
- struct listnode *cnode;
- struct isis_circuit *circuit;
- int lvl;
-
- if (area == NULL)
- return ISIS_ERROR;
-
- sched_debug("ISIS (%s): Scheduling regeneration of %s LSPs, %sincluding PSNs",
- area->area_tag, circuit_t2string(level), all_pseudo ? "" : "not ");
-
- memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
- LSP_PSEUDO_ID (id) = LSP_FRAGMENT (id) = 0;
- now = time (NULL);
-
- for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++)
- {
- if (!((level & lvl) && (area->is_type & lvl)))
- continue;
-
- sched_debug("ISIS (%s): Checking whether L%d needs to be scheduled",
- area->area_tag, lvl);
-
- if (area->lsp_regenerate_pending[lvl - 1])
- {
- struct timeval remain = thread_timer_remain(area->t_lsp_refresh[lvl - 1]);
- sched_debug("ISIS (%s): Regeneration is already pending, nothing todo."
- " (Due in %lld.%03lld seconds)", area->area_tag,
- (long long)remain.tv_sec, (long long)remain.tv_usec / 1000);
- continue;
- }
-
- lsp = lsp_search (id, area->lspdb[lvl - 1]);
- if (!lsp)
- {
- sched_debug("ISIS (%s): We do not have any LSPs to regenerate, nothing todo.",
- area->area_tag);
- continue;
- }
-
- /*
- * Throttle avoidance
- */
- sched_debug("ISIS (%s): Will schedule regen timer. Last run was: %lld, Now is: %lld",
- area->area_tag, (long long)lsp->last_generated, (long long)now);
- THREAD_TIMER_OFF (area->t_lsp_refresh[lvl - 1]);
- diff = now - lsp->last_generated;
- if (diff < area->lsp_gen_interval[lvl - 1])
- {
- timeout = 1000 * (area->lsp_gen_interval[lvl - 1] - diff);
- sched_debug("ISIS (%s): Scheduling in %ld ms to match configured lsp_gen_interval",
- area->area_tag, timeout);
- }
- else
- {
- /*
- * lsps are not regenerated if lsp_regenerate function is called
- * directly. However if the lsp_regenerate call is queued for
- * later execution it works.
- */
- timeout = 100;
- sched_debug("ISIS (%s): Last generation was more than lsp_gen_interval ago."
- " Scheduling for execution in %ld ms.", area->area_tag, timeout);
- }
-
- area->lsp_regenerate_pending[lvl - 1] = 1;
- if (lvl == IS_LEVEL_1)
- {
- THREAD_TIMER_MSEC_ON(master, area->t_lsp_refresh[lvl - 1],
- lsp_l1_refresh, area, timeout);
- }
- else if (lvl == IS_LEVEL_2)
- {
- THREAD_TIMER_MSEC_ON(master, area->t_lsp_refresh[lvl - 1],
- lsp_l2_refresh, area, timeout);
- }
- }
-
- if (all_pseudo)
- {
- for (ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit))
- lsp_regenerate_schedule_pseudo (circuit, level);
- }
-
- return ISIS_OK;
+ struct isis_lsp *lsp;
+ u_char id[ISIS_SYS_ID_LEN + 2];
+ time_t now, diff;
+ long timeout;
+ struct listnode *cnode;
+ struct isis_circuit *circuit;
+ int lvl;
+
+ if (area == NULL)
+ return ISIS_ERROR;
+
+ sched_debug(
+ "ISIS (%s): Scheduling regeneration of %s LSPs, %sincluding PSNs",
+ area->area_tag, circuit_t2string(level),
+ all_pseudo ? "" : "not ");
+
+ memcpy(id, isis->sysid, ISIS_SYS_ID_LEN);
+ LSP_PSEUDO_ID(id) = LSP_FRAGMENT(id) = 0;
+ now = time(NULL);
+
+ for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) {
+ if (!((level & lvl) && (area->is_type & lvl)))
+ continue;
+
+ sched_debug(
+ "ISIS (%s): Checking whether L%d needs to be scheduled",
+ area->area_tag, lvl);
+
+ if (area->lsp_regenerate_pending[lvl - 1]) {
+ struct timeval remain = thread_timer_remain(
+ area->t_lsp_refresh[lvl - 1]);
+ sched_debug(
+ "ISIS (%s): Regeneration is already pending, nothing todo."
+ " (Due in %lld.%03lld seconds)",
+ area->area_tag, (long long)remain.tv_sec,
+ (long long)remain.tv_usec / 1000);
+ continue;
+ }
+
+ lsp = lsp_search(id, area->lspdb[lvl - 1]);
+ if (!lsp) {
+ sched_debug(
+ "ISIS (%s): We do not have any LSPs to regenerate, nothing todo.",
+ area->area_tag);
+ continue;
+ }
+
+ /*
+ * Throttle avoidance
+ */
+ sched_debug(
+ "ISIS (%s): Will schedule regen timer. Last run was: %lld, Now is: %lld",
+ area->area_tag, (long long)lsp->last_generated,
+ (long long)now);
+ THREAD_TIMER_OFF(area->t_lsp_refresh[lvl - 1]);
+ diff = now - lsp->last_generated;
+ if (diff < area->lsp_gen_interval[lvl - 1]) {
+ timeout =
+ 1000 * (area->lsp_gen_interval[lvl - 1] - diff);
+ sched_debug(
+ "ISIS (%s): Scheduling in %ld ms to match configured lsp_gen_interval",
+ area->area_tag, timeout);
+ } else {
+ /*
+ * lsps are not regenerated if lsp_regenerate function
+ * is called
+ * directly. However if the lsp_regenerate call is
+ * queued for
+ * later execution it works.
+ */
+ timeout = 100;
+ sched_debug(
+ "ISIS (%s): Last generation was more than lsp_gen_interval ago."
+ " Scheduling for execution in %ld ms.",
+ area->area_tag, timeout);
+ }
+
+ area->lsp_regenerate_pending[lvl - 1] = 1;
+ if (lvl == IS_LEVEL_1) {
+ THREAD_TIMER_MSEC_ON(master,
+ area->t_lsp_refresh[lvl - 1],
+ lsp_l1_refresh, area, timeout);
+ } else if (lvl == IS_LEVEL_2) {
+ THREAD_TIMER_MSEC_ON(master,
+ area->t_lsp_refresh[lvl - 1],
+ lsp_l2_refresh, area, timeout);
+ }
+ }
+
+ if (all_pseudo) {
+ for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit))
+ lsp_regenerate_schedule_pseudo(circuit, level);
+ }
+
+ return ISIS_OK;
}
/*
@@ -2119,430 +2194,444 @@ lsp_regenerate_schedule (struct isis_area *area, int level, int all_pseudo)
*/
/*
- * 7.3.8 and 7.3.10 Generation of level 1 and 2 pseudonode LSPs
+ * 7.3.8 and 7.3.10 Generation of level 1 and 2 pseudonode LSPs
*/
-static void
-lsp_build_pseudo (struct isis_lsp *lsp, struct isis_circuit *circuit,
- int level)
+static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit,
+ int level)
{
- struct isis_adjacency *adj;
- struct is_neigh *is_neigh;
- struct te_is_neigh *te_is_neigh;
- struct es_neigh *es_neigh;
- struct list *adj_list;
- struct listnode *node;
- struct isis_area *area = circuit->area;
-
- lsp_debug("ISIS (%s): Constructing pseudo LSP %s for interface %s level %d",
- area->area_tag, rawlspid_print(lsp->lsp_header->lsp_id),
- circuit->interface->name, level);
-
- lsp->level = level;
- /* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */
- lsp->lsp_header->lsp_bits = lsp_bits_generate (level, 0,
- circuit->area->attached_bit);
-
- /*
- * add self to IS neighbours
- */
- if (circuit->area->oldmetric)
- {
- if (lsp->tlv_data.is_neighs == NULL)
- {
- lsp->tlv_data.is_neighs = list_new ();
- lsp->tlv_data.is_neighs->del = free_tlv;
- }
- is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
-
- memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
- listnode_add (lsp->tlv_data.is_neighs, is_neigh);
- lsp_debug("ISIS (%s): Adding %s.%02x as old-style neighbor (self)",
- area->area_tag, sysid_print(is_neigh->neigh_id),
- LSP_PSEUDO_ID(is_neigh->neigh_id));
- }
- if (circuit->area->newmetric)
- {
- if (lsp->tlv_data.te_is_neighs == NULL)
- {
- lsp->tlv_data.te_is_neighs = list_new ();
- lsp->tlv_data.te_is_neighs->del = free_tlv;
- }
- te_is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct te_is_neigh));
-
- memcpy (&te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
- listnode_add (lsp->tlv_data.te_is_neighs, te_is_neigh);
- lsp_debug("ISIS (%s): Adding %s.%02x as te-style neighbor (self)",
- area->area_tag, sysid_print(te_is_neigh->neigh_id),
- LSP_PSEUDO_ID(te_is_neigh->neigh_id));
- }
-
- adj_list = list_new ();
- isis_adj_build_up_list (circuit->u.bc.adjdb[level - 1], adj_list);
-
- for (ALL_LIST_ELEMENTS_RO (adj_list, node, adj))
- {
- if (adj->level & level)
- {
- if ((level == IS_LEVEL_1 && adj->sys_type == ISIS_SYSTYPE_L1_IS) ||
- (level == IS_LEVEL_1 && adj->sys_type == ISIS_SYSTYPE_L2_IS &&
- adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
- (level == IS_LEVEL_2 && adj->sys_type == ISIS_SYSTYPE_L2_IS))
- {
- /* an IS neighbour -> add it */
- if (circuit->area->oldmetric)
- {
- is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
-
- memcpy (&is_neigh->neigh_id, adj->sysid, ISIS_SYS_ID_LEN);
- listnode_add (lsp->tlv_data.is_neighs, is_neigh);
- lsp_debug("ISIS (%s): Adding %s.%02x as old-style neighbor (peer)",
- area->area_tag, sysid_print(is_neigh->neigh_id),
- LSP_PSEUDO_ID(is_neigh->neigh_id));
- }
- if (circuit->area->newmetric)
- {
- te_is_neigh = XCALLOC (MTYPE_ISIS_TLV,
- sizeof (struct te_is_neigh));
- memcpy (&te_is_neigh->neigh_id, adj->sysid, ISIS_SYS_ID_LEN);
- listnode_add (lsp->tlv_data.te_is_neighs, te_is_neigh);
- lsp_debug("ISIS (%s): Adding %s.%02x as te-style neighbor (peer)",
- area->area_tag, sysid_print(te_is_neigh->neigh_id),
- LSP_PSEUDO_ID(te_is_neigh->neigh_id));
+ struct isis_adjacency *adj;
+ struct is_neigh *is_neigh;
+ struct te_is_neigh *te_is_neigh;
+ struct es_neigh *es_neigh;
+ struct list *adj_list;
+ struct listnode *node;
+ struct isis_area *area = circuit->area;
+
+ lsp_debug(
+ "ISIS (%s): Constructing pseudo LSP %s for interface %s level %d",
+ area->area_tag, rawlspid_print(lsp->lsp_header->lsp_id),
+ circuit->interface->name, level);
+
+ lsp->level = level;
+ /* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */
+ lsp->lsp_header->lsp_bits =
+ lsp_bits_generate(level, 0, circuit->area->attached_bit);
+
+ /*
+ * add self to IS neighbours
+ */
+ if (circuit->area->oldmetric) {
+ if (lsp->tlv_data.is_neighs == NULL) {
+ lsp->tlv_data.is_neighs = list_new();
+ lsp->tlv_data.is_neighs->del = free_tlv;
}
- }
- else if (level == IS_LEVEL_1 && adj->sys_type == ISIS_SYSTYPE_ES)
- {
- /* an ES neigbour add it, if we are building level 1 LSP */
- /* FIXME: the tlv-format is hard to use here */
- if (lsp->tlv_data.es_neighs == NULL)
- {
- lsp->tlv_data.es_neighs = list_new ();
- lsp->tlv_data.es_neighs->del = free_tlv;
+ is_neigh = XCALLOC(MTYPE_ISIS_TLV, sizeof(struct is_neigh));
+
+ memcpy(&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
+ listnode_add(lsp->tlv_data.is_neighs, is_neigh);
+ lsp_debug(
+ "ISIS (%s): Adding %s.%02x as old-style neighbor (self)",
+ area->area_tag, sysid_print(is_neigh->neigh_id),
+ LSP_PSEUDO_ID(is_neigh->neigh_id));
+ }
+ if (circuit->area->newmetric) {
+ if (lsp->tlv_data.te_is_neighs == NULL) {
+ lsp->tlv_data.te_is_neighs = list_new();
+ lsp->tlv_data.te_is_neighs->del = free_tlv;
}
- es_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct es_neigh));
-
- memcpy (&es_neigh->first_es_neigh, adj->sysid, ISIS_SYS_ID_LEN);
- listnode_add (lsp->tlv_data.es_neighs, es_neigh);
- lsp_debug("ISIS (%s): Adding %s as ES neighbor (peer)",
- area->area_tag, sysid_print(es_neigh->first_es_neigh));
- }
- else
- {
- lsp_debug("ISIS (%s): Ignoring neighbor %s, level does not match",
- area->area_tag, sysid_print(adj->sysid));
- }
+ te_is_neigh =
+ XCALLOC(MTYPE_ISIS_TLV, sizeof(struct te_is_neigh));
+
+ memcpy(&te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
+ listnode_add(lsp->tlv_data.te_is_neighs, te_is_neigh);
+ lsp_debug(
+ "ISIS (%s): Adding %s.%02x as te-style neighbor (self)",
+ area->area_tag, sysid_print(te_is_neigh->neigh_id),
+ LSP_PSEUDO_ID(te_is_neigh->neigh_id));
}
- else
- {
- lsp_debug("ISIS (%s): Ignoring neighbor %s, level does not intersect",
- area->area_tag, sysid_print(adj->sysid));
+
+ adj_list = list_new();
+ isis_adj_build_up_list(circuit->u.bc.adjdb[level - 1], adj_list);
+
+ for (ALL_LIST_ELEMENTS_RO(adj_list, node, adj)) {
+ if (adj->level & level) {
+ if ((level == IS_LEVEL_1
+ && adj->sys_type == ISIS_SYSTYPE_L1_IS)
+ || (level == IS_LEVEL_1
+ && adj->sys_type == ISIS_SYSTYPE_L2_IS
+ && adj->adj_usage == ISIS_ADJ_LEVEL1AND2)
+ || (level == IS_LEVEL_2
+ && adj->sys_type == ISIS_SYSTYPE_L2_IS)) {
+ /* an IS neighbour -> add it */
+ if (circuit->area->oldmetric) {
+ is_neigh = XCALLOC(
+ MTYPE_ISIS_TLV,
+ sizeof(struct is_neigh));
+
+ memcpy(&is_neigh->neigh_id, adj->sysid,
+ ISIS_SYS_ID_LEN);
+ listnode_add(lsp->tlv_data.is_neighs,
+ is_neigh);
+ lsp_debug(
+ "ISIS (%s): Adding %s.%02x as old-style neighbor (peer)",
+ area->area_tag,
+ sysid_print(is_neigh->neigh_id),
+ LSP_PSEUDO_ID(
+ is_neigh->neigh_id));
+ }
+ if (circuit->area->newmetric) {
+ te_is_neigh = XCALLOC(
+ MTYPE_ISIS_TLV,
+ sizeof(struct te_is_neigh));
+ memcpy(&te_is_neigh->neigh_id,
+ adj->sysid, ISIS_SYS_ID_LEN);
+ listnode_add(lsp->tlv_data.te_is_neighs,
+ te_is_neigh);
+ lsp_debug(
+ "ISIS (%s): Adding %s.%02x as te-style neighbor (peer)",
+ area->area_tag,
+ sysid_print(
+ te_is_neigh->neigh_id),
+ LSP_PSEUDO_ID(
+ te_is_neigh->neigh_id));
+ }
+ } else if (level == IS_LEVEL_1
+ && adj->sys_type == ISIS_SYSTYPE_ES) {
+ /* an ES neigbour add it, if we are building
+ * level 1 LSP */
+ /* FIXME: the tlv-format is hard to use here */
+ if (lsp->tlv_data.es_neighs == NULL) {
+ lsp->tlv_data.es_neighs = list_new();
+ lsp->tlv_data.es_neighs->del = free_tlv;
+ }
+ es_neigh = XCALLOC(MTYPE_ISIS_TLV,
+ sizeof(struct es_neigh));
+
+ memcpy(&es_neigh->first_es_neigh, adj->sysid,
+ ISIS_SYS_ID_LEN);
+ listnode_add(lsp->tlv_data.es_neighs, es_neigh);
+ lsp_debug(
+ "ISIS (%s): Adding %s as ES neighbor (peer)",
+ area->area_tag,
+ sysid_print(es_neigh->first_es_neigh));
+ } else {
+ lsp_debug(
+ "ISIS (%s): Ignoring neighbor %s, level does not match",
+ area->area_tag,
+ sysid_print(adj->sysid));
+ }
+ } else {
+ lsp_debug(
+ "ISIS (%s): Ignoring neighbor %s, level does not intersect",
+ area->area_tag, sysid_print(adj->sysid));
+ }
}
- }
- list_delete (adj_list);
+ list_delete(adj_list);
- lsp_debug("ISIS (%s): Pseudo LSP construction is complete.", area->area_tag);
+ lsp_debug("ISIS (%s): Pseudo LSP construction is complete.",
+ area->area_tag);
- /* Reset endp of stream to overwrite only TLV part of it. */
- stream_reset (lsp->pdu);
- stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
+ /* Reset endp of stream to overwrite only TLV part of it. */
+ stream_reset(lsp->pdu);
+ stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
- /*
- * Add the authentication info if it's present
- */
- lsp_auth_add (lsp);
+ /*
+ * Add the authentication info if it's present
+ */
+ lsp_auth_add(lsp);
- if (lsp->tlv_data.is_neighs && listcount (lsp->tlv_data.is_neighs) > 0)
- tlv_add_is_neighs (lsp->tlv_data.is_neighs, lsp->pdu);
+ if (lsp->tlv_data.is_neighs && listcount(lsp->tlv_data.is_neighs) > 0)
+ tlv_add_is_neighs(lsp->tlv_data.is_neighs, lsp->pdu);
- if (lsp->tlv_data.te_is_neighs && listcount (lsp->tlv_data.te_is_neighs) > 0)
- tlv_add_te_is_neighs (lsp->tlv_data.te_is_neighs, lsp->pdu);
+ if (lsp->tlv_data.te_is_neighs
+ && listcount(lsp->tlv_data.te_is_neighs) > 0)
+ tlv_add_te_is_neighs(lsp->tlv_data.te_is_neighs, lsp->pdu);
- if (lsp->tlv_data.es_neighs && listcount (lsp->tlv_data.es_neighs) > 0)
- tlv_add_is_neighs (lsp->tlv_data.es_neighs, lsp->pdu);
+ if (lsp->tlv_data.es_neighs && listcount(lsp->tlv_data.es_neighs) > 0)
+ tlv_add_is_neighs(lsp->tlv_data.es_neighs, lsp->pdu);
- lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
+ lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu));
- /* Recompute authentication and checksum information */
- lsp_auth_update (lsp);
- fletcher_checksum(STREAM_DATA (lsp->pdu) + 12,
- ntohs (lsp->lsp_header->pdu_len) - 12, 12);
+ /* Recompute authentication and checksum information */
+ lsp_auth_update(lsp);
+ fletcher_checksum(STREAM_DATA(lsp->pdu) + 12,
+ ntohs(lsp->lsp_header->pdu_len) - 12, 12);
- return;
+ return;
}
-int
-lsp_generate_pseudo (struct isis_circuit *circuit, int level)
+int lsp_generate_pseudo(struct isis_circuit *circuit, int level)
{
- dict_t *lspdb = circuit->area->lspdb[level - 1];
- struct isis_lsp *lsp;
- u_char lsp_id[ISIS_SYS_ID_LEN + 2];
- u_int16_t rem_lifetime, refresh_time;
-
- if ((circuit->is_type & level) != level ||
- (circuit->state != C_STATE_UP) ||
- (circuit->circ_type != CIRCUIT_T_BROADCAST) ||
- (circuit->u.bc.is_dr[level - 1] == 0))
- return ISIS_ERROR;
-
- memcpy (lsp_id, isis->sysid, ISIS_SYS_ID_LEN);
- LSP_FRAGMENT (lsp_id) = 0;
- LSP_PSEUDO_ID (lsp_id) = circuit->circuit_id;
-
- /*
- * If for some reason have a pseudo LSP in the db already -> regenerate
- */
- if (lsp_search (lsp_id, lspdb))
- return lsp_regenerate_schedule_pseudo (circuit, level);
-
- rem_lifetime = lsp_rem_lifetime (circuit->area, level);
- /* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */
- lsp = lsp_new (circuit->area, lsp_id, rem_lifetime, 1,
- circuit->area->is_type | circuit->area->attached_bit,
- 0, level);
- lsp->area = circuit->area;
-
- lsp_build_pseudo (lsp, circuit, level);
-
- lsp->own_lsp = 1;
- lsp_insert (lsp, lspdb);
- lsp_set_all_srmflags (lsp);
-
- refresh_time = lsp_refresh_time (lsp, rem_lifetime);
- THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[level - 1]);
- circuit->lsp_regenerate_pending[level - 1] = 0;
- if (level == IS_LEVEL_1)
- THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[level - 1],
- lsp_l1_refresh_pseudo, circuit, refresh_time);
- else if (level == IS_LEVEL_2)
- THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[level - 1],
- lsp_l2_refresh_pseudo, circuit, refresh_time);
-
- if (isis->debugs & DEBUG_UPDATE_PACKETS)
- {
- zlog_debug ("ISIS-Upd (%s): Building L%d Pseudo LSP %s, len %d, "
- "seq 0x%08x, cksum 0x%04x, lifetime %us, refresh %us",
- circuit->area->area_tag, level,
- rawlspid_print (lsp->lsp_header->lsp_id),
- ntohl (lsp->lsp_header->pdu_len),
- ntohl (lsp->lsp_header->seq_num),
- ntohs (lsp->lsp_header->checksum),
- ntohs (lsp->lsp_header->rem_lifetime),
- refresh_time);
- }
-
- return ISIS_OK;
+ dict_t *lspdb = circuit->area->lspdb[level - 1];
+ struct isis_lsp *lsp;
+ u_char lsp_id[ISIS_SYS_ID_LEN + 2];
+ u_int16_t rem_lifetime, refresh_time;
+
+ if ((circuit->is_type & level) != level
+ || (circuit->state != C_STATE_UP)
+ || (circuit->circ_type != CIRCUIT_T_BROADCAST)
+ || (circuit->u.bc.is_dr[level - 1] == 0))
+ return ISIS_ERROR;
+
+ memcpy(lsp_id, isis->sysid, ISIS_SYS_ID_LEN);
+ LSP_FRAGMENT(lsp_id) = 0;
+ LSP_PSEUDO_ID(lsp_id) = circuit->circuit_id;
+
+ /*
+ * If for some reason have a pseudo LSP in the db already -> regenerate
+ */
+ if (lsp_search(lsp_id, lspdb))
+ return lsp_regenerate_schedule_pseudo(circuit, level);
+
+ rem_lifetime = lsp_rem_lifetime(circuit->area, level);
+ /* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */
+ lsp = lsp_new(circuit->area, lsp_id, rem_lifetime, 1,
+ circuit->area->is_type | circuit->area->attached_bit, 0,
+ level);
+ lsp->area = circuit->area;
+
+ lsp_build_pseudo(lsp, circuit, level);
+
+ lsp->own_lsp = 1;
+ lsp_insert(lsp, lspdb);
+ lsp_set_all_srmflags(lsp);
+
+ refresh_time = lsp_refresh_time(lsp, rem_lifetime);
+ THREAD_TIMER_OFF(circuit->u.bc.t_refresh_pseudo_lsp[level - 1]);
+ circuit->lsp_regenerate_pending[level - 1] = 0;
+ if (level == IS_LEVEL_1)
+ THREAD_TIMER_ON(master,
+ circuit->u.bc.t_refresh_pseudo_lsp[level - 1],
+ lsp_l1_refresh_pseudo, circuit, refresh_time);
+ else if (level == IS_LEVEL_2)
+ THREAD_TIMER_ON(master,
+ circuit->u.bc.t_refresh_pseudo_lsp[level - 1],
+ lsp_l2_refresh_pseudo, circuit, refresh_time);
+
+ if (isis->debugs & DEBUG_UPDATE_PACKETS) {
+ zlog_debug(
+ "ISIS-Upd (%s): Building L%d Pseudo LSP %s, len %d, "
+ "seq 0x%08x, cksum 0x%04x, lifetime %us, refresh %us",
+ circuit->area->area_tag, level,
+ rawlspid_print(lsp->lsp_header->lsp_id),
+ ntohl(lsp->lsp_header->pdu_len),
+ ntohl(lsp->lsp_header->seq_num),
+ ntohs(lsp->lsp_header->checksum),
+ ntohs(lsp->lsp_header->rem_lifetime), refresh_time);
+ }
+
+ return ISIS_OK;
}
-static int
-lsp_regenerate_pseudo (struct isis_circuit *circuit, int level)
+static int lsp_regenerate_pseudo(struct isis_circuit *circuit, int level)
{
- dict_t *lspdb = circuit->area->lspdb[level - 1];
- struct isis_lsp *lsp;
- u_char lsp_id[ISIS_SYS_ID_LEN + 2];
- u_int16_t rem_lifetime, refresh_time;
-
- if ((circuit->is_type & level) != level ||
- (circuit->state != C_STATE_UP) ||
- (circuit->circ_type != CIRCUIT_T_BROADCAST) ||
- (circuit->u.bc.is_dr[level - 1] == 0))
- return ISIS_ERROR;
-
- memcpy (lsp_id, isis->sysid, ISIS_SYS_ID_LEN);
- LSP_PSEUDO_ID (lsp_id) = circuit->circuit_id;
- LSP_FRAGMENT (lsp_id) = 0;
-
- lsp = lsp_search (lsp_id, lspdb);
-
- if (!lsp)
- {
- zlog_err ("lsp_regenerate_pseudo: no l%d LSP %s found!",
- level, rawlspid_print (lsp_id));
- return ISIS_ERROR;
- }
- lsp_clear_data (lsp);
-
- lsp_build_pseudo (lsp, circuit, level);
-
- /* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */
- lsp->lsp_header->lsp_bits = lsp_bits_generate (level, 0,
- circuit->area->attached_bit);
- rem_lifetime = lsp_rem_lifetime (circuit->area, level);
- lsp->lsp_header->rem_lifetime = htons (rem_lifetime);
- lsp_inc_seqnum (lsp, 0);
- lsp->last_generated = time (NULL);
- lsp_set_all_srmflags (lsp);
-
- refresh_time = lsp_refresh_time (lsp, rem_lifetime);
- if (level == IS_LEVEL_1)
- THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[level - 1],
- lsp_l1_refresh_pseudo, circuit, refresh_time);
- else if (level == IS_LEVEL_2)
- THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[level - 1],
- lsp_l2_refresh_pseudo, circuit, refresh_time);
-
- if (isis->debugs & DEBUG_UPDATE_PACKETS)
- {
- zlog_debug ("ISIS-Upd (%s): Refreshing L%d Pseudo LSP %s, len %d, "
- "seq 0x%08x, cksum 0x%04x, lifetime %us, refresh %us",
- circuit->area->area_tag, level,
- rawlspid_print (lsp->lsp_header->lsp_id),
- ntohl (lsp->lsp_header->pdu_len),
- ntohl (lsp->lsp_header->seq_num),
- ntohs (lsp->lsp_header->checksum),
- ntohs (lsp->lsp_header->rem_lifetime),
- refresh_time);
- }
-
- return ISIS_OK;
+ dict_t *lspdb = circuit->area->lspdb[level - 1];
+ struct isis_lsp *lsp;
+ u_char lsp_id[ISIS_SYS_ID_LEN + 2];
+ u_int16_t rem_lifetime, refresh_time;
+
+ if ((circuit->is_type & level) != level
+ || (circuit->state != C_STATE_UP)
+ || (circuit->circ_type != CIRCUIT_T_BROADCAST)
+ || (circuit->u.bc.is_dr[level - 1] == 0))
+ return ISIS_ERROR;
+
+ memcpy(lsp_id, isis->sysid, ISIS_SYS_ID_LEN);
+ LSP_PSEUDO_ID(lsp_id) = circuit->circuit_id;
+ LSP_FRAGMENT(lsp_id) = 0;
+
+ lsp = lsp_search(lsp_id, lspdb);
+
+ if (!lsp) {
+ zlog_err("lsp_regenerate_pseudo: no l%d LSP %s found!", level,
+ rawlspid_print(lsp_id));
+ return ISIS_ERROR;
+ }
+ lsp_clear_data(lsp);
+
+ lsp_build_pseudo(lsp, circuit, level);
+
+ /* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */
+ lsp->lsp_header->lsp_bits =
+ lsp_bits_generate(level, 0, circuit->area->attached_bit);
+ rem_lifetime = lsp_rem_lifetime(circuit->area, level);
+ lsp->lsp_header->rem_lifetime = htons(rem_lifetime);
+ lsp_inc_seqnum(lsp, 0);
+ lsp->last_generated = time(NULL);
+ lsp_set_all_srmflags(lsp);
+
+ refresh_time = lsp_refresh_time(lsp, rem_lifetime);
+ if (level == IS_LEVEL_1)
+ THREAD_TIMER_ON(master,
+ circuit->u.bc.t_refresh_pseudo_lsp[level - 1],
+ lsp_l1_refresh_pseudo, circuit, refresh_time);
+ else if (level == IS_LEVEL_2)
+ THREAD_TIMER_ON(master,
+ circuit->u.bc.t_refresh_pseudo_lsp[level - 1],
+ lsp_l2_refresh_pseudo, circuit, refresh_time);
+
+ if (isis->debugs & DEBUG_UPDATE_PACKETS) {
+ zlog_debug(
+ "ISIS-Upd (%s): Refreshing L%d Pseudo LSP %s, len %d, "
+ "seq 0x%08x, cksum 0x%04x, lifetime %us, refresh %us",
+ circuit->area->area_tag, level,
+ rawlspid_print(lsp->lsp_header->lsp_id),
+ ntohl(lsp->lsp_header->pdu_len),
+ ntohl(lsp->lsp_header->seq_num),
+ ntohs(lsp->lsp_header->checksum),
+ ntohs(lsp->lsp_header->rem_lifetime), refresh_time);
+ }
+
+ return ISIS_OK;
}
/*
* Something has changed or periodic refresh -> regenerate pseudo LSP
*/
-static int
-lsp_l1_refresh_pseudo (struct thread *thread)
+static int lsp_l1_refresh_pseudo(struct thread *thread)
{
- struct isis_circuit *circuit;
- u_char id[ISIS_SYS_ID_LEN + 2];
+ struct isis_circuit *circuit;
+ u_char id[ISIS_SYS_ID_LEN + 2];
- circuit = THREAD_ARG (thread);
+ circuit = THREAD_ARG(thread);
- circuit->u.bc.t_refresh_pseudo_lsp[0] = NULL;
- circuit->lsp_regenerate_pending[0] = 0;
+ circuit->u.bc.t_refresh_pseudo_lsp[0] = NULL;
+ circuit->lsp_regenerate_pending[0] = 0;
- if ((circuit->u.bc.is_dr[0] == 0) ||
- (circuit->is_type & IS_LEVEL_1) == 0)
- {
- memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
- LSP_PSEUDO_ID (id) = circuit->circuit_id;
- LSP_FRAGMENT (id) = 0;
- lsp_purge_pseudo (id, circuit, IS_LEVEL_1);
- return ISIS_ERROR;
- }
+ if ((circuit->u.bc.is_dr[0] == 0)
+ || (circuit->is_type & IS_LEVEL_1) == 0) {
+ memcpy(id, isis->sysid, ISIS_SYS_ID_LEN);
+ LSP_PSEUDO_ID(id) = circuit->circuit_id;
+ LSP_FRAGMENT(id) = 0;
+ lsp_purge_pseudo(id, circuit, IS_LEVEL_1);
+ return ISIS_ERROR;
+ }
- return lsp_regenerate_pseudo (circuit, IS_LEVEL_1);
+ return lsp_regenerate_pseudo(circuit, IS_LEVEL_1);
}
-static int
-lsp_l2_refresh_pseudo (struct thread *thread)
+static int lsp_l2_refresh_pseudo(struct thread *thread)
{
- struct isis_circuit *circuit;
- u_char id[ISIS_SYS_ID_LEN + 2];
+ struct isis_circuit *circuit;
+ u_char id[ISIS_SYS_ID_LEN + 2];
- circuit = THREAD_ARG (thread);
+ circuit = THREAD_ARG(thread);
- circuit->u.bc.t_refresh_pseudo_lsp[1] = NULL;
- circuit->lsp_regenerate_pending[1] = 0;
+ circuit->u.bc.t_refresh_pseudo_lsp[1] = NULL;
+ circuit->lsp_regenerate_pending[1] = 0;
- if ((circuit->u.bc.is_dr[1] == 0) ||
- (circuit->is_type & IS_LEVEL_2) == 0)
- {
- memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
- LSP_PSEUDO_ID (id) = circuit->circuit_id;
- LSP_FRAGMENT (id) = 0;
- lsp_purge_pseudo (id, circuit, IS_LEVEL_2);
- return ISIS_ERROR;
- }
+ if ((circuit->u.bc.is_dr[1] == 0)
+ || (circuit->is_type & IS_LEVEL_2) == 0) {
+ memcpy(id, isis->sysid, ISIS_SYS_ID_LEN);
+ LSP_PSEUDO_ID(id) = circuit->circuit_id;
+ LSP_FRAGMENT(id) = 0;
+ lsp_purge_pseudo(id, circuit, IS_LEVEL_2);
+ return ISIS_ERROR;
+ }
- return lsp_regenerate_pseudo (circuit, IS_LEVEL_2);
+ return lsp_regenerate_pseudo(circuit, IS_LEVEL_2);
}
-int
-lsp_regenerate_schedule_pseudo (struct isis_circuit *circuit, int level)
+int lsp_regenerate_schedule_pseudo(struct isis_circuit *circuit, int level)
{
- struct isis_lsp *lsp;
- u_char lsp_id[ISIS_SYS_ID_LEN + 2];
- time_t now, diff;
- long timeout;
- int lvl;
- struct isis_area *area = circuit->area;
-
- if (circuit->circ_type != CIRCUIT_T_BROADCAST ||
- circuit->state != C_STATE_UP)
- return ISIS_OK;
-
- sched_debug("ISIS (%s): Scheduling regeneration of %s pseudo LSP for interface %s",
- area->area_tag, circuit_t2string(level), circuit->interface->name);
-
- memcpy (lsp_id, isis->sysid, ISIS_SYS_ID_LEN);
- LSP_PSEUDO_ID (lsp_id) = circuit->circuit_id;
- LSP_FRAGMENT (lsp_id) = 0;
- now = time (NULL);
-
- for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++)
- {
- sched_debug("ISIS (%s): Checking whether L%d pseudo LSP needs to be scheduled",
- area->area_tag, lvl);
-
- if (!((level & lvl) && (circuit->is_type & lvl)))
- {
- sched_debug("ISIS (%s): Level is not active on circuit",
- area->area_tag);
- continue;
- }
-
- if (circuit->u.bc.is_dr[lvl - 1] == 0)
- {
- sched_debug("ISIS (%s): This IS is not DR, nothing to do.",
- area->area_tag);
- continue;
- }
-
- if (circuit->lsp_regenerate_pending[lvl - 1])
- {
- struct timeval remain =
- thread_timer_remain(circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1]);
- sched_debug("ISIS (%s): Regenerate is already pending, nothing todo."
- " (Due in %lld.%03lld seconds)", area->area_tag,
- (long long)remain.tv_sec, (long long)remain.tv_usec/1000);
- continue;
- }
-
- lsp = lsp_search (lsp_id, circuit->area->lspdb[lvl - 1]);
- if (!lsp)
- {
- sched_debug("ISIS (%s): Pseudonode LSP does not exist yet, nothing to regenerate.",
- area->area_tag);
- continue;
- }
-
- /*
- * Throttle avoidance
- */
- sched_debug("ISIS (%s): Will schedule PSN regen timer. Last run was: %lld, Now is: %lld",
- area->area_tag, (long long)lsp->last_generated, (long long) now);
- THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1]);
- diff = now - lsp->last_generated;
- if (diff < circuit->area->lsp_gen_interval[lvl - 1])
- {
- timeout = 1000 * (circuit->area->lsp_gen_interval[lvl - 1] - diff);
- sched_debug("ISIS (%s): Sechduling in %ld ms to match configured lsp_gen_interval",
- area->area_tag, timeout);
- }
- else
- {
- timeout = 100;
- sched_debug("ISIS (%s): Last generation was more than lsp_gen_interval ago."
- " Scheduling for execution in %ld ms.", area->area_tag, timeout);
- }
-
- circuit->lsp_regenerate_pending[lvl - 1] = 1;
-
- if (lvl == IS_LEVEL_1)
- {
- THREAD_TIMER_MSEC_ON(master,
- circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1],
- lsp_l1_refresh_pseudo, circuit, timeout);
- }
- else if (lvl == IS_LEVEL_2)
- {
- THREAD_TIMER_MSEC_ON(master,
- circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1],
- lsp_l2_refresh_pseudo, circuit, timeout);
- }
- }
-
- return ISIS_OK;
+ struct isis_lsp *lsp;
+ u_char lsp_id[ISIS_SYS_ID_LEN + 2];
+ time_t now, diff;
+ long timeout;
+ int lvl;
+ struct isis_area *area = circuit->area;
+
+ if (circuit->circ_type != CIRCUIT_T_BROADCAST
+ || circuit->state != C_STATE_UP)
+ return ISIS_OK;
+
+ sched_debug(
+ "ISIS (%s): Scheduling regeneration of %s pseudo LSP for interface %s",
+ area->area_tag, circuit_t2string(level),
+ circuit->interface->name);
+
+ memcpy(lsp_id, isis->sysid, ISIS_SYS_ID_LEN);
+ LSP_PSEUDO_ID(lsp_id) = circuit->circuit_id;
+ LSP_FRAGMENT(lsp_id) = 0;
+ now = time(NULL);
+
+ for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) {
+ sched_debug(
+ "ISIS (%s): Checking whether L%d pseudo LSP needs to be scheduled",
+ area->area_tag, lvl);
+
+ if (!((level & lvl) && (circuit->is_type & lvl))) {
+ sched_debug("ISIS (%s): Level is not active on circuit",
+ area->area_tag);
+ continue;
+ }
+
+ if (circuit->u.bc.is_dr[lvl - 1] == 0) {
+ sched_debug(
+ "ISIS (%s): This IS is not DR, nothing to do.",
+ area->area_tag);
+ continue;
+ }
+
+ if (circuit->lsp_regenerate_pending[lvl - 1]) {
+ struct timeval remain = thread_timer_remain(
+ circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1]);
+ sched_debug(
+ "ISIS (%s): Regenerate is already pending, nothing todo."
+ " (Due in %lld.%03lld seconds)",
+ area->area_tag, (long long)remain.tv_sec,
+ (long long)remain.tv_usec / 1000);
+ continue;
+ }
+
+ lsp = lsp_search(lsp_id, circuit->area->lspdb[lvl - 1]);
+ if (!lsp) {
+ sched_debug(
+ "ISIS (%s): Pseudonode LSP does not exist yet, nothing to regenerate.",
+ area->area_tag);
+ continue;
+ }
+
+ /*
+ * Throttle avoidance
+ */
+ sched_debug(
+ "ISIS (%s): Will schedule PSN regen timer. Last run was: %lld, Now is: %lld",
+ area->area_tag, (long long)lsp->last_generated,
+ (long long)now);
+ THREAD_TIMER_OFF(circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1]);
+ diff = now - lsp->last_generated;
+ if (diff < circuit->area->lsp_gen_interval[lvl - 1]) {
+ timeout =
+ 1000 * (circuit->area->lsp_gen_interval[lvl - 1]
+ - diff);
+ sched_debug(
+ "ISIS (%s): Sechduling in %ld ms to match configured lsp_gen_interval",
+ area->area_tag, timeout);
+ } else {
+ timeout = 100;
+ sched_debug(
+ "ISIS (%s): Last generation was more than lsp_gen_interval ago."
+ " Scheduling for execution in %ld ms.",
+ area->area_tag, timeout);
+ }
+
+ circuit->lsp_regenerate_pending[lvl - 1] = 1;
+
+ if (lvl == IS_LEVEL_1) {
+ THREAD_TIMER_MSEC_ON(
+ master,
+ circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1],
+ lsp_l1_refresh_pseudo, circuit, timeout);
+ } else if (lvl == IS_LEVEL_2) {
+ THREAD_TIMER_MSEC_ON(
+ master,
+ circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1],
+ lsp_l2_refresh_pseudo, circuit, timeout);
+ }
+ }
+
+ return ISIS_OK;
}
/*
@@ -2550,230 +2639,247 @@ lsp_regenerate_schedule_pseudo (struct isis_circuit *circuit, int level)
* - set remaining lifetime
* - set LSPs with SRMflag set for sending
*/
-int
-lsp_tick (struct thread *thread)
+int lsp_tick(struct thread *thread)
{
- struct isis_area *area;
- struct isis_circuit *circuit;
- struct isis_lsp *lsp;
- struct list *lsp_list;
- struct listnode *lspnode, *cnode;
- dnode_t *dnode, *dnode_next;
- int level;
- u_int16_t rem_lifetime;
-
- lsp_list = list_new ();
-
- area = THREAD_ARG (thread);
- assert (area);
- area->t_tick = NULL;
- THREAD_TIMER_ON (master, area->t_tick, lsp_tick, area, 1);
-
- /*
- * Build a list of LSPs with (any) SRMflag set
- * and removed the ones that have aged out
- */
- for (level = 0; level < ISIS_LEVELS; level++)
- {
- if (area->lspdb[level] && dict_count (area->lspdb[level]) > 0)
- {
- for (dnode = dict_first (area->lspdb[level]);
- dnode != NULL; dnode = dnode_next)
- {
- dnode_next = dict_next (area->lspdb[level], dnode);
- lsp = dnode_get (dnode);
-
- /*
- * The lsp rem_lifetime is kept at 0 for MaxAge or
- * ZeroAgeLifetime depending on explicit purge or
- * natural age out. So schedule spf only once when
- * the first time rem_lifetime becomes 0.
- */
- rem_lifetime = ntohs(lsp->lsp_header->rem_lifetime);
- lsp_set_time (lsp);
-
- /*
- * Schedule may run spf which should be done only after
- * the lsp rem_lifetime becomes 0 for the first time.
- * ISO 10589 - 7.3.16.4 first paragraph.
- */
- if (rem_lifetime == 1 && lsp->lsp_header->seq_num != 0)
- {
- /* 7.3.16.4 a) set SRM flags on all */
- lsp_set_all_srmflags (lsp);
- /* 7.3.16.4 b) retain only the header FIXME */
- /* 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); */
- }
-
- if (lsp->age_out == 0)
- {
- zlog_debug ("ISIS-Upd (%s): L%u LSP %s seq 0x%08x aged out",
- area->area_tag,
- lsp->level,
- rawlspid_print (lsp->lsp_header->lsp_id),
- ntohl (lsp->lsp_header->seq_num));
- lsp_destroy (lsp);
- lsp = NULL;
- dict_delete_free (area->lspdb[level], dnode);
- }
- else if (flags_any_set (lsp->SRMflags))
- listnode_add (lsp_list, lsp);
- }
-
- /*
- * Send LSPs on circuits indicated by the SRMflags
- */
- if (listcount (lsp_list) > 0)
- {
- for (ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit))
- {
- int diff = time (NULL) - circuit->lsp_queue_last_cleared;
- if (circuit->lsp_queue == NULL ||
- diff < MIN_LSP_TRANS_INTERVAL)
- continue;
- for (ALL_LIST_ELEMENTS_RO (lsp_list, lspnode, lsp))
- {
- if (circuit->upadjcount[lsp->level - 1] &&
- ISIS_CHECK_FLAG (lsp->SRMflags, circuit))
- {
- /* Add the lsp only if it is not already in lsp
- * queue */
- if (! listnode_lookup (circuit->lsp_queue, lsp))
- {
- listnode_add (circuit->lsp_queue, lsp);
- thread_add_event (master, send_lsp, circuit, 0);
- }
- }
- }
- }
- list_delete_all_node (lsp_list);
- }
- }
- }
-
- list_delete (lsp_list);
-
- return ISIS_OK;
+ struct isis_area *area;
+ struct isis_circuit *circuit;
+ struct isis_lsp *lsp;
+ struct list *lsp_list;
+ struct listnode *lspnode, *cnode;
+ dnode_t *dnode, *dnode_next;
+ int level;
+ u_int16_t rem_lifetime;
+
+ lsp_list = list_new();
+
+ area = THREAD_ARG(thread);
+ assert(area);
+ area->t_tick = NULL;
+ THREAD_TIMER_ON(master, area->t_tick, lsp_tick, area, 1);
+
+ /*
+ * Build a list of LSPs with (any) SRMflag set
+ * and removed the ones that have aged out
+ */
+ for (level = 0; level < ISIS_LEVELS; level++) {
+ if (area->lspdb[level] && dict_count(area->lspdb[level]) > 0) {
+ for (dnode = dict_first(area->lspdb[level]);
+ dnode != NULL; dnode = dnode_next) {
+ dnode_next =
+ dict_next(area->lspdb[level], dnode);
+ lsp = dnode_get(dnode);
+
+ /*
+ * The lsp rem_lifetime is kept at 0 for MaxAge
+ * or
+ * ZeroAgeLifetime depending on explicit purge
+ * or
+ * natural age out. So schedule spf only once
+ * when
+ * the first time rem_lifetime becomes 0.
+ */
+ rem_lifetime =
+ ntohs(lsp->lsp_header->rem_lifetime);
+ lsp_set_time(lsp);
+
+ /*
+ * Schedule may run spf which should be done
+ * only after
+ * the lsp rem_lifetime becomes 0 for the first
+ * time.
+ * ISO 10589 - 7.3.16.4 first paragraph.
+ */
+ if (rem_lifetime == 1
+ && lsp->lsp_header->seq_num != 0) {
+ /* 7.3.16.4 a) set SRM flags on all */
+ lsp_set_all_srmflags(lsp);
+ /* 7.3.16.4 b) retain only the header
+ * FIXME */
+ /* 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); */
+ }
+
+ if (lsp->age_out == 0) {
+ zlog_debug(
+ "ISIS-Upd (%s): L%u LSP %s seq 0x%08x aged out",
+ area->area_tag, lsp->level,
+ rawlspid_print(
+ lsp->lsp_header
+ ->lsp_id),
+ ntohl(lsp->lsp_header
+ ->seq_num));
+ lsp_destroy(lsp);
+ lsp = NULL;
+ dict_delete_free(area->lspdb[level],
+ dnode);
+ } else if (flags_any_set(lsp->SRMflags))
+ listnode_add(lsp_list, lsp);
+ }
+
+ /*
+ * Send LSPs on circuits indicated by the SRMflags
+ */
+ if (listcount(lsp_list) > 0) {
+ for (ALL_LIST_ELEMENTS_RO(area->circuit_list,
+ cnode, circuit)) {
+ int diff =
+ time(NULL)
+ - circuit->lsp_queue_last_cleared;
+ if (circuit->lsp_queue == NULL
+ || diff < MIN_LSP_TRANS_INTERVAL)
+ continue;
+ for (ALL_LIST_ELEMENTS_RO(
+ lsp_list, lspnode, lsp)) {
+ if (circuit->upadjcount
+ [lsp->level - 1]
+ && ISIS_CHECK_FLAG(
+ lsp->SRMflags,
+ circuit)) {
+ /* Add the lsp only if
+ * it is not already in
+ * lsp
+ * queue */
+ if (!listnode_lookup(
+ circuit->lsp_queue,
+ lsp)) {
+ listnode_add(
+ circuit->lsp_queue,
+ lsp);
+ thread_add_event(
+ master,
+ send_lsp,
+ circuit,
+ 0);
+ }
+ }
+ }
+ }
+ list_delete_all_node(lsp_list);
+ }
+ }
+ }
+
+ list_delete(lsp_list);
+
+ return ISIS_OK;
}
-void
-lsp_purge_pseudo (u_char * id, struct isis_circuit *circuit, int level)
+void lsp_purge_pseudo(u_char *id, struct isis_circuit *circuit, int level)
{
- struct isis_lsp *lsp;
- u_int16_t seq_num;
- u_int8_t lsp_bits;
-
- lsp = lsp_search (id, circuit->area->lspdb[level - 1]);
- if (!lsp)
- return;
-
- /* store old values */
- seq_num = lsp->lsp_header->seq_num;
- lsp_bits = lsp->lsp_header->lsp_bits;
-
- /* reset stream */
- lsp_clear_data (lsp);
- stream_reset (lsp->pdu);
-
- /* update header */
- lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
- memcpy (lsp->lsp_header->lsp_id, id, ISIS_SYS_ID_LEN + 2);
- lsp->lsp_header->checksum = 0;
- lsp->lsp_header->seq_num = seq_num;
- lsp->lsp_header->rem_lifetime = 0;
- lsp->lsp_header->lsp_bits = lsp_bits;
- lsp->level = level;
- lsp->age_out = lsp->area->max_lsp_lifetime[level-1];
- stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
-
- /*
- * Add and update the authentication info if its present
- */
- lsp_auth_add (lsp);
- lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
- lsp_auth_update (lsp);
- fletcher_checksum(STREAM_DATA (lsp->pdu) + 12,
- ntohs (lsp->lsp_header->pdu_len) - 12, 12);
-
- lsp_set_all_srmflags (lsp);
-
- return;
+ struct isis_lsp *lsp;
+ u_int16_t seq_num;
+ u_int8_t lsp_bits;
+
+ lsp = lsp_search(id, circuit->area->lspdb[level - 1]);
+ if (!lsp)
+ return;
+
+ /* store old values */
+ seq_num = lsp->lsp_header->seq_num;
+ lsp_bits = lsp->lsp_header->lsp_bits;
+
+ /* reset stream */
+ lsp_clear_data(lsp);
+ stream_reset(lsp->pdu);
+
+ /* update header */
+ lsp->lsp_header->pdu_len = htons(ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
+ memcpy(lsp->lsp_header->lsp_id, id, ISIS_SYS_ID_LEN + 2);
+ lsp->lsp_header->checksum = 0;
+ lsp->lsp_header->seq_num = seq_num;
+ lsp->lsp_header->rem_lifetime = 0;
+ lsp->lsp_header->lsp_bits = lsp_bits;
+ lsp->level = level;
+ lsp->age_out = lsp->area->max_lsp_lifetime[level - 1];
+ stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
+
+ /*
+ * Add and update the authentication info if its present
+ */
+ lsp_auth_add(lsp);
+ lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu));
+ lsp_auth_update(lsp);
+ fletcher_checksum(STREAM_DATA(lsp->pdu) + 12,
+ ntohs(lsp->lsp_header->pdu_len) - 12, 12);
+
+ lsp_set_all_srmflags(lsp);
+
+ return;
}
/*
- * Purge own LSP that is received and we don't have.
+ * Purge own LSP that is received and we don't have.
* -> Do as in 7.3.16.4
*/
-void
-lsp_purge_non_exist (int level,
- struct isis_link_state_hdr *lsp_hdr,
- struct isis_area *area)
+void lsp_purge_non_exist(int level, struct isis_link_state_hdr *lsp_hdr,
+ struct isis_area *area)
{
- struct isis_lsp *lsp;
-
- /*
- * We need to create the LSP to be purged
- */
- lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
- lsp->area = area;
- lsp->level = level;
- lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu);
- lsp->isis_header = (struct isis_fixed_hdr *) STREAM_DATA (lsp->pdu);
- fill_fixed_hdr (lsp->isis_header, (lsp->level == IS_LEVEL_1) ? L1_LINK_STATE
- : L2_LINK_STATE);
- lsp->lsp_header = (struct isis_link_state_hdr *) (STREAM_DATA (lsp->pdu) +
- ISIS_FIXED_HDR_LEN);
- memcpy (lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN);
- stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
-
- /*
- * Set the remaining lifetime to 0
- */
- lsp->lsp_header->rem_lifetime = 0;
-
- /*
- * Add and update the authentication info if its present
- */
- lsp_auth_add (lsp);
- lsp_auth_update (lsp);
-
- /*
- * Update the PDU length to header plus any authentication TLV.
- */
- lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
-
- /*
- * Put the lsp into LSPdb
- */
- lsp_insert (lsp, area->lspdb[lsp->level - 1]);
-
- /*
- * Send in to whole area
- */
- lsp_set_all_srmflags (lsp);
-
- return;
+ struct isis_lsp *lsp;
+
+ /*
+ * We need to create the LSP to be purged
+ */
+ lsp = XCALLOC(MTYPE_ISIS_LSP, sizeof(struct isis_lsp));
+ lsp->area = area;
+ lsp->level = level;
+ lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu);
+ lsp->isis_header = (struct isis_fixed_hdr *)STREAM_DATA(lsp->pdu);
+ fill_fixed_hdr(lsp->isis_header,
+ (lsp->level == IS_LEVEL_1) ? L1_LINK_STATE
+ : L2_LINK_STATE);
+ lsp->lsp_header = (struct isis_link_state_hdr *)(STREAM_DATA(lsp->pdu)
+ + ISIS_FIXED_HDR_LEN);
+ memcpy(lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN);
+ stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
+
+ /*
+ * Set the remaining lifetime to 0
+ */
+ lsp->lsp_header->rem_lifetime = 0;
+
+ /*
+ * Add and update the authentication info if its present
+ */
+ lsp_auth_add(lsp);
+ lsp_auth_update(lsp);
+
+ /*
+ * Update the PDU length to header plus any authentication TLV.
+ */
+ lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu));
+
+ /*
+ * Put the lsp into LSPdb
+ */
+ lsp_insert(lsp, area->lspdb[lsp->level - 1]);
+
+ /*
+ * Send in to whole area
+ */
+ lsp_set_all_srmflags(lsp);
+
+ return;
}
-void lsp_set_all_srmflags (struct isis_lsp *lsp)
+void lsp_set_all_srmflags(struct isis_lsp *lsp)
{
- struct listnode *node;
- struct isis_circuit *circuit;
+ struct listnode *node;
+ struct isis_circuit *circuit;
- assert (lsp);
+ assert(lsp);
- ISIS_FLAGS_CLEAR_ALL(lsp->SRMflags);
+ ISIS_FLAGS_CLEAR_ALL(lsp->SRMflags);
- if (lsp->area)
- {
- struct list *circuit_list = lsp->area->circuit_list;
- for (ALL_LIST_ELEMENTS_RO (circuit_list, node, circuit))
- {
- ISIS_SET_FLAG(lsp->SRMflags, circuit);
- }
- }
+ if (lsp->area) {
+ struct list *circuit_list = lsp->area->circuit_list;
+ for (ALL_LIST_ELEMENTS_RO(circuit_list, node, circuit)) {
+ ISIS_SET_FLAG(lsp->SRMflags, circuit);
+ }
+ }
}