diff options
Diffstat (limited to 'isisd/isis_lsp.c')
-rw-r--r-- | isisd/isis_lsp.c | 4950 |
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); + } + } } |