2003-12-23 09:09:43 +01:00
|
|
|
/*
|
|
|
|
* IS-IS Rout(e)ing protocol - isis_lsp.c
|
|
|
|
* LSP processing
|
|
|
|
*
|
|
|
|
* Copyright (C) 2001,2002 Sampo Saaristo
|
|
|
|
* Tampere University of Technology
|
|
|
|
* Institute of Communications Engineering
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public Licenseas 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
|
|
|
|
* 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.,
|
|
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
2005-05-03 11:27:23 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
#include <zebra.h>
|
|
|
|
|
|
|
|
#include "linklist.h"
|
|
|
|
#include "thread.h"
|
|
|
|
#include "vty.h"
|
|
|
|
#include "stream.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "prefix.h"
|
|
|
|
#include "command.h"
|
|
|
|
#include "hash.h"
|
|
|
|
#include "if.h"
|
2008-08-13 20:09:10 +02:00
|
|
|
#include "checksum.h"
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
#include "isisd/dict.h"
|
|
|
|
#include "isisd/isis_constants.h"
|
|
|
|
#include "isisd/isis_common.h"
|
|
|
|
#include "isisd/isis_circuit.h"
|
|
|
|
#include "isisd/isisd.h"
|
|
|
|
#include "isisd/isis_tlv.h"
|
|
|
|
#include "isisd/isis_lsp.h"
|
|
|
|
#include "isisd/isis_pdu.h"
|
|
|
|
#include "isisd/isis_dynhn.h"
|
|
|
|
#include "isisd/isis_misc.h"
|
|
|
|
#include "isisd/isis_flags.h"
|
|
|
|
#include "isisd/isis_csm.h"
|
|
|
|
#include "isisd/isis_adjacency.h"
|
|
|
|
#include "isisd/isis_spf.h"
|
|
|
|
|
|
|
|
#ifdef TOPOLOGY_GENERATE
|
|
|
|
#include "spgrid.h"
|
|
|
|
#endif
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
#define LSP_MEMORY_PREASSIGN
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
extern struct isis *isis;
|
|
|
|
extern struct thread_master *master;
|
2004-10-03 20:18:34 +02:00
|
|
|
extern struct in_addr router_id_zebra;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2004-09-24 12:45:28 +02:00
|
|
|
/* staticly assigned vars for printing purposes */
|
|
|
|
char lsp_bits_string[200]; /* FIXME: enough ? */
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
int
|
|
|
|
lsp_id_cmp (u_char * id1, u_char * id2)
|
|
|
|
{
|
2003-12-23 09:09:43 +01:00
|
|
|
return memcmp (id1, id2, ISIS_SYS_ID_LEN + 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
dict_t *
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_db_init (void)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
dict_t *dict;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
|
|
|
dict = dict_create (DICTCOUNT_T_MAX, (dict_comp_t) lsp_id_cmp);
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return dict;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct isis_lsp *
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_search (u_char * id, dict_t * lspdb)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
dnode_t *node;
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
#ifdef EXTREME_DEBUG
|
2003-12-23 09:09:43 +01:00
|
|
|
dnode_t *dn;
|
|
|
|
|
2004-12-24 01:14:50 +01:00
|
|
|
zlog_debug ("searching db");
|
2004-09-10 22:48:21 +02:00
|
|
|
for (dn = dict_first (lspdb); dn; dn = dict_next (lspdb, dn))
|
|
|
|
{
|
2004-12-24 01:14:50 +01:00
|
|
|
zlog_debug ("%s\t%pX", rawlspid_print ((char *) dnode_getkey (dn)),
|
|
|
|
dnode_get (dn));
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
#endif /* EXTREME DEBUG */
|
|
|
|
|
|
|
|
node = dict_lookup (lspdb, id);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
if (node)
|
2004-09-10 22:48:21 +02:00
|
|
|
return (struct isis_lsp *) dnode_get (node);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_clear_data (struct isis_lsp *lsp)
|
|
|
|
{
|
|
|
|
if (!lsp)
|
|
|
|
return;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
if (lsp->tlv_data.is_neighs)
|
|
|
|
list_delete (lsp->tlv_data.is_neighs);
|
2005-09-26 19:39:48 +02:00
|
|
|
if (lsp->tlv_data.te_is_neighs)
|
|
|
|
list_delete (lsp->tlv_data.te_is_neighs);
|
2003-12-23 09:09:43 +01:00
|
|
|
if (lsp->tlv_data.area_addrs)
|
|
|
|
list_delete (lsp->tlv_data.area_addrs);
|
|
|
|
if (lsp->tlv_data.es_neighs)
|
|
|
|
list_delete (lsp->tlv_data.es_neighs);
|
|
|
|
if (lsp->tlv_data.ipv4_addrs)
|
|
|
|
list_delete (lsp->tlv_data.ipv4_addrs);
|
|
|
|
if (lsp->tlv_data.ipv4_int_reachs)
|
|
|
|
list_delete (lsp->tlv_data.ipv4_int_reachs);
|
|
|
|
if (lsp->tlv_data.ipv4_ext_reachs)
|
|
|
|
list_delete (lsp->tlv_data.ipv4_ext_reachs);
|
2005-09-26 19:39:48 +02:00
|
|
|
if (lsp->tlv_data.te_ipv4_reachs)
|
|
|
|
list_delete (lsp->tlv_data.te_ipv4_reachs);
|
2003-12-23 09:09:43 +01:00
|
|
|
#ifdef HAVE_IPV6
|
|
|
|
if (lsp->tlv_data.ipv6_addrs)
|
|
|
|
list_delete (lsp->tlv_data.ipv6_addrs);
|
|
|
|
if (lsp->tlv_data.ipv6_reachs)
|
|
|
|
list_delete (lsp->tlv_data.ipv6_reachs);
|
|
|
|
#endif /* HAVE_IPV6 */
|
|
|
|
|
|
|
|
memset (&lsp->tlv_data, 0, sizeof (struct tlvs));
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_destroy (struct isis_lsp *lsp)
|
|
|
|
{
|
|
|
|
if (!lsp)
|
|
|
|
return;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_clear_data (lsp);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
|
|
|
if (LSP_FRAGMENT (lsp->lsp_header->lsp_id) == 0 && lsp->lspu.frags)
|
|
|
|
{
|
2003-12-23 09:09:43 +01:00
|
|
|
list_delete (lsp->lspu.frags);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
if (lsp->pdu)
|
|
|
|
stream_free (lsp->pdu);
|
|
|
|
XFREE (MTYPE_ISIS_LSP, lsp);
|
|
|
|
}
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
void
|
|
|
|
lsp_db_destroy (dict_t * lspdb)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
dnode_t *dnode, *next;
|
|
|
|
struct isis_lsp *lsp;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
dnode = dict_first (lspdb);
|
2004-09-10 22:48:21 +02:00
|
|
|
while (dnode)
|
|
|
|
{
|
|
|
|
next = dict_next (lspdb, dnode);
|
|
|
|
lsp = dnode_get (dnode);
|
|
|
|
lsp_destroy (lsp);
|
|
|
|
dict_delete_free (lspdb, dnode);
|
|
|
|
dnode = next;
|
|
|
|
}
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
dict_free (lspdb);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove all the frags belonging to the given lsp
|
|
|
|
*/
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_remove_frags (struct list *frags, dict_t * lspdb)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
dnode_t *dnode;
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
struct listnode *lnode, *lnnode;
|
2003-12-23 09:09:43 +01:00
|
|
|
struct isis_lsp *lsp;
|
|
|
|
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
for (ALL_LIST_ELEMENTS (frags, lnode, lnnode, lsp))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
dnode = dict_lookup (lspdb, lsp->lsp_header->lsp_id);
|
|
|
|
lsp_destroy (lsp);
|
|
|
|
dnode_destroy (dict_delete (lspdb, dnode));
|
|
|
|
}
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
list_delete_all_node (frags);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_search_and_destroy (u_char * id, dict_t * lspdb)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
dnode_t *node;
|
|
|
|
struct isis_lsp *lsp;
|
|
|
|
|
|
|
|
node = dict_lookup (lspdb, id);
|
2004-09-10 22:48:21 +02:00
|
|
|
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);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Compares a LSP to given values
|
|
|
|
* Params are given in net order
|
|
|
|
*/
|
2004-09-10 22:48:21 +02:00
|
|
|
int
|
|
|
|
lsp_compare (char *areatag, struct isis_lsp *lsp, u_int32_t seq_num,
|
2003-12-23 09:09:43 +01:00
|
|
|
u_int16_t checksum, u_int16_t rem_lifetime)
|
|
|
|
{
|
2004-09-10 22:48:21 +02:00
|
|
|
/* no point in double ntohl on seqnum */
|
|
|
|
if (lsp->lsp_header->seq_num == seq_num &&
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp->lsp_header->checksum == checksum &&
|
|
|
|
/*comparing with 0, no need to do ntohl */
|
|
|
|
((lsp->lsp_header->rem_lifetime == 0 && rem_lifetime == 0) ||
|
2004-09-10 22:48:21 +02:00
|
|
|
(lsp->lsp_header->rem_lifetime != 0 && rem_lifetime != 0)))
|
|
|
|
{
|
|
|
|
if (isis->debugs & DEBUG_SNP_PACKETS)
|
|
|
|
{
|
2004-12-24 01:14:50 +01:00
|
|
|
zlog_debug ("ISIS-Snp (%s): 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));
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
return LSP_EQUAL;
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
if (ntohl (seq_num) >= ntohl (lsp->lsp_header->seq_num))
|
|
|
|
{
|
|
|
|
if (isis->debugs & DEBUG_SNP_PACKETS)
|
|
|
|
{
|
2004-12-24 01:14:50 +01:00
|
|
|
zlog_debug ("ISIS-Snp (%s): 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));
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
return LSP_NEWER;
|
|
|
|
}
|
|
|
|
if (isis->debugs & DEBUG_SNP_PACKETS)
|
|
|
|
{
|
2004-12-24 01:14:50 +01:00
|
|
|
zlog_debug
|
2004-09-10 22:48:21 +02:00
|
|
|
("ISIS-Snp (%s): 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));
|
2004-12-24 01:14:50 +01:00
|
|
|
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));
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
return LSP_OLDER;
|
|
|
|
}
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
void
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_inc_seqnum (struct isis_lsp *lsp, u_int32_t seq_num)
|
|
|
|
{
|
|
|
|
u_int32_t newseq;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
if (seq_num == 0 || ntohl (lsp->lsp_header->seq_num) > seq_num)
|
|
|
|
newseq = ntohl (lsp->lsp_header->seq_num) + 1;
|
|
|
|
else
|
2004-09-10 22:48:21 +02:00
|
|
|
newseq = seq_num++;
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp->lsp_header->seq_num = htonl (newseq);
|
2008-08-13 20:09:10 +02:00
|
|
|
fletcher_checksum (STREAM_DATA (lsp->pdu) + 12,
|
2004-09-10 22:48:21 +02:00
|
|
|
ntohs (lsp->lsp_header->pdu_len) - 12, 12);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Genetates checksum for LSP and its frags
|
|
|
|
*/
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_seqnum_update (struct isis_lsp *lsp0)
|
|
|
|
{
|
|
|
|
struct isis_lsp *lsp;
|
2005-09-28 20:45:54 +02:00
|
|
|
struct listnode *node;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_inc_seqnum (lsp0, 0);
|
|
|
|
|
|
|
|
if (!lsp0->lspu.frags)
|
|
|
|
return;
|
|
|
|
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (lsp0->lspu.frags, node, lsp))
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
lsp_inc_seqnum (lsp, 0);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
int
|
2003-12-23 09:09:43 +01:00
|
|
|
isis_lsp_authinfo_check (struct stream *stream, struct isis_area *area,
|
2004-09-10 22:48:21 +02:00
|
|
|
int pdulen, struct isis_passwd *passwd)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
uint32_t expected = 0, found;
|
|
|
|
struct tlvs tlvs;
|
|
|
|
int retval = 0;
|
|
|
|
|
|
|
|
expected |= TLVFLAG_AUTH_INFO;
|
|
|
|
retval = parse_tlvs (area->area_tag, stream->data +
|
2004-09-10 22:48:21 +02:00
|
|
|
ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN,
|
|
|
|
pdulen - ISIS_FIXED_HDR_LEN
|
|
|
|
- ISIS_LSP_HDR_LEN, &expected, &found, &tlvs);
|
2003-12-23 09:09:43 +01:00
|
|
|
if (retval || !(found & TLVFLAG_AUTH_INFO))
|
2004-09-10 22:48:21 +02:00
|
|
|
return 1; /* Auth fail (parsing failed or no auth-tlv) */
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
return authentication_check (passwd, &tlvs.auth_info);
|
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_update_data (struct isis_lsp *lsp, struct stream *stream,
|
|
|
|
struct isis_area *area)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2004-09-10 22:48:21 +02:00
|
|
|
uint32_t expected = 0, found;
|
2003-12-23 09:09:43 +01:00
|
|
|
int retval;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/* copying only the relevant part of our stream */
|
2005-05-03 11:27:23 +02:00
|
|
|
lsp->pdu = stream_dup (stream);
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/* setting pointers to the correct place */
|
2004-09-10 22:48:21 +02:00
|
|
|
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);
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp->age_out = ZERO_AGE_LIFETIME;
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp->installed = time (NULL);
|
2003-12-23 09:09:43 +01:00
|
|
|
/*
|
|
|
|
* Get LSP data i.e. TLVs
|
|
|
|
*/
|
|
|
|
expected |= TLVFLAG_AUTH_INFO;
|
|
|
|
expected |= TLVFLAG_AREA_ADDRS;
|
|
|
|
expected |= TLVFLAG_IS_NEIGHS;
|
2004-09-10 22:48:21 +02:00
|
|
|
if ((lsp->lsp_header->lsp_bits & 3) == 3) /* a level 2 LSP */
|
2003-12-23 09:09:43 +01:00
|
|
|
expected |= TLVFLAG_PARTITION_DESIG_LEVEL2_IS;
|
|
|
|
expected |= TLVFLAG_NLPID;
|
|
|
|
if (area->dynhostname)
|
|
|
|
expected |= TLVFLAG_DYN_HOSTNAME;
|
2004-09-10 22:48:21 +02:00
|
|
|
if (area->newmetric)
|
|
|
|
{
|
|
|
|
expected |= TLVFLAG_TE_IS_NEIGHS;
|
|
|
|
expected |= TLVFLAG_TE_IPV4_REACHABILITY;
|
|
|
|
expected |= TLVFLAG_TE_ROUTER_ID;
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
expected |= TLVFLAG_IPV4_ADDR;
|
|
|
|
expected |= TLVFLAG_IPV4_INT_REACHABILITY;
|
|
|
|
expected |= TLVFLAG_IPV4_EXT_REACHABILITY;
|
|
|
|
#ifdef HAVE_IPV6
|
|
|
|
expected |= TLVFLAG_IPV6_ADDR;
|
|
|
|
expected |= TLVFLAG_IPV6_REACHABILITY;
|
|
|
|
#endif /* HAVE_IPV6 */
|
|
|
|
|
|
|
|
retval = parse_tlvs (area->area_tag, lsp->pdu->data +
|
2004-09-10 22:48:21 +02:00
|
|
|
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);
|
|
|
|
|
|
|
|
if (found & TLVFLAG_DYN_HOSTNAME)
|
|
|
|
{
|
|
|
|
if (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 :
|
|
|
|
(lsp->lsp_header->lsp_bits & LSPBIT_IST));
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
lsp_update (struct isis_lsp *lsp, struct isis_link_state_hdr *lsp_hdr,
|
2005-09-16 16:44:23 +02:00
|
|
|
struct stream *stream, struct isis_area *area, int level)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2005-09-18 19:51:02 +02:00
|
|
|
dnode_t *dnode = NULL;
|
2005-09-16 16:44:23 +02:00
|
|
|
|
|
|
|
/* Remove old LSP from LSP database. */
|
2005-09-18 19:51:02 +02:00
|
|
|
dnode = dict_lookup (area->lspdb[level - 1], lsp->lsp_header->lsp_id);
|
|
|
|
if (dnode)
|
|
|
|
dnode_destroy (dict_delete (area->lspdb[level - 1], dnode));
|
2005-09-16 16:44:23 +02:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
/* free the old lsp data */
|
2003-12-23 09:09:43 +01:00
|
|
|
XFREE (MTYPE_STREAM_DATA, lsp->pdu);
|
|
|
|
lsp_clear_data (lsp);
|
|
|
|
|
|
|
|
/* rebuild the lsp data */
|
|
|
|
lsp_update_data (lsp, stream, area);
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
/* set the new values for lsp header */
|
2003-12-23 09:09:43 +01:00
|
|
|
memcpy (lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN);
|
2005-09-16 16:44:23 +02:00
|
|
|
|
2005-09-18 19:51:02 +02:00
|
|
|
if (dnode)
|
|
|
|
lsp_insert (lsp, area->lspdb[level - 1]);
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* creation of LSP directly from what we received */
|
|
|
|
struct isis_lsp *
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_new_from_stream_ptr (struct stream *stream,
|
|
|
|
u_int16_t pdu_len, struct isis_lsp *lsp0,
|
|
|
|
struct isis_area *area)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_lsp *lsp;
|
|
|
|
|
2005-09-01 19:52:33 +02:00
|
|
|
lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_update_data (lsp, stream, area);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return lsp;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct isis_lsp *
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_new (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)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_lsp *lsp;
|
|
|
|
|
2005-09-01 19:52:33 +02:00
|
|
|
lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
|
2004-09-10 22:48:21 +02:00
|
|
|
if (!lsp)
|
|
|
|
{
|
|
|
|
/* FIXME: set lspdbol bit */
|
|
|
|
zlog_warn ("lsp_new(): out of memory");
|
|
|
|
return NULL;
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
#ifdef LSP_MEMORY_PREASSIGN
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp->pdu = stream_new (1514); /*Should be minimal mtu? yup... */
|
2003-12-23 09:09:43 +01:00
|
|
|
#else
|
2004-09-10 22:48:21 +02:00
|
|
|
/* We need to do realloc on TLVs additions */
|
|
|
|
lsp->pdu = malloc (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
|
2003-12-23 09:09:43 +01:00
|
|
|
#endif /* LSP_MEMORY_PREASSIGN */
|
|
|
|
if (LSP_FRAGMENT (lsp_id) == 0)
|
|
|
|
lsp->lspu.frags = list_new ();
|
2004-09-10 22:48:21 +02:00
|
|
|
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);
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/* at first we fill the FIXED HEADER */
|
2004-09-10 22:48:21 +02:00
|
|
|
(level == 1) ? fill_fixed_hdr (lsp->isis_header, L1_LINK_STATE) :
|
|
|
|
fill_fixed_hdr (lsp->isis_header, L2_LINK_STATE);
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/* now for the LSP HEADER */
|
|
|
|
/* Minimal LSP PDU size */
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
|
2003-12-23 09:09:43 +01:00
|
|
|
memcpy (lsp->lsp_header->lsp_id, lsp_id, ISIS_SYS_ID_LEN + 2);
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp->lsp_header->checksum = checksum; /* Provided in network order */
|
2003-12-23 09:09:43 +01:00
|
|
|
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;
|
|
|
|
|
2005-02-09 16:51:56 +01:00
|
|
|
stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2005-09-04 23:36:36 +02:00
|
|
|
if (isis->debugs & DEBUG_EVENTS)
|
|
|
|
zlog_debug ("New LSP with ID %s-%02x-%02x 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->seq_num));
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
return lsp;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_insert (struct isis_lsp *lsp, dict_t * lspdb)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
dict_alloc_insert (lspdb, lsp->lsp_header->lsp_id, lsp);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Build a list of LSPs with non-zero ht bounded by start and stop ids
|
|
|
|
*/
|
2004-09-10 22:48:21 +02:00
|
|
|
void
|
|
|
|
lsp_build_list_nonzero_ht (u_char * start_id, u_char * stop_id,
|
|
|
|
struct list *list, dict_t * lspdb)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
dnode_t *first, *last, *curr;
|
|
|
|
|
|
|
|
first = dict_lower_bound (lspdb, start_id);
|
|
|
|
if (!first)
|
|
|
|
return;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
last = dict_upper_bound (lspdb, stop_id);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
curr = first;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
|
|
|
if (((struct isis_lsp *) (curr->dict_data))->lsp_header->rem_lifetime)
|
2003-12-23 09:09:43 +01:00
|
|
|
listnode_add (list, first->dict_data);
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Build a list of all LSPs bounded by start and stop ids
|
|
|
|
*/
|
2004-09-10 22:48:21 +02:00
|
|
|
void
|
|
|
|
lsp_build_list (u_char * start_id, u_char * stop_id,
|
|
|
|
struct list *list, dict_t * lspdb)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
dnode_t *first, *last, *curr;
|
|
|
|
|
|
|
|
first = dict_lower_bound (lspdb, start_id);
|
|
|
|
if (!first)
|
|
|
|
return;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
last = dict_upper_bound (lspdb, stop_id);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
curr = first;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
listnode_add (list, first->dict_data);
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
while (curr)
|
|
|
|
{
|
|
|
|
curr = dict_next (lspdb, curr);
|
|
|
|
if (curr)
|
|
|
|
listnode_add (list, curr->dict_data);
|
|
|
|
if (curr == last)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Build a list of LSPs with SSN flag set for the given circuit
|
|
|
|
*/
|
|
|
|
void
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_build_list_ssn (struct isis_circuit *circuit, struct list *list,
|
|
|
|
dict_t * lspdb)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
dnode_t *dnode, *next;
|
|
|
|
struct isis_lsp *lsp;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
dnode = dict_first (lspdb);
|
2004-09-10 22:48:21 +02:00
|
|
|
while (dnode != NULL)
|
|
|
|
{
|
|
|
|
next = dict_next (lspdb, dnode);
|
|
|
|
lsp = dnode_get (dnode);
|
|
|
|
if (ISIS_CHECK_FLAG (lsp->SSNflags, circuit))
|
|
|
|
listnode_add (list, lsp);
|
|
|
|
dnode = next;
|
|
|
|
}
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_set_time (struct isis_lsp *lsp)
|
|
|
|
{
|
|
|
|
assert (lsp);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
|
|
|
if (lsp->lsp_header->rem_lifetime == 0)
|
|
|
|
{
|
|
|
|
if (lsp->age_out != 0)
|
|
|
|
lsp->age_out--;
|
|
|
|
return;
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
/* If we are turning 0 */
|
|
|
|
/* ISO 10589 - 7.3.16.4 first paragraph */
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
if (ntohs (lsp->lsp_header->rem_lifetime) == 1)
|
|
|
|
{
|
|
|
|
/* 7.3.16.4 a) set SRM flags on all */
|
|
|
|
ISIS_FLAGS_SET_ALL (lsp->SRMflags);
|
|
|
|
/* 7.3.16.4 b) retain only the header FIXME */
|
|
|
|
/* 7.3.16.4 c) record the time to purge FIXME (other way to do it) */
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp->lsp_header->rem_lifetime =
|
2003-12-23 09:09:43 +01:00
|
|
|
htons (ntohs (lsp->lsp_header->rem_lifetime) - 1);
|
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2004-09-10 22:48:21 +02:00
|
|
|
lspid_print (u_char * lsp_id, u_char * trg, char dynhost, char frag)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_dynhn *dyn = NULL;
|
2004-09-10 22:48:21 +02:00
|
|
|
u_char id[SYSID_STRLEN];
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
if (dynhost)
|
|
|
|
dyn = dynhn_find_by_id (lsp_id);
|
|
|
|
else
|
|
|
|
dyn = NULL;
|
|
|
|
|
|
|
|
if (dyn)
|
2004-09-26 18:24:14 +02:00
|
|
|
sprintf ((char *)id, "%.14s", dyn->name.name);
|
2003-12-23 09:09:43 +01:00
|
|
|
else if (!memcmp (isis->sysid, lsp_id, ISIS_SYS_ID_LEN) & dynhost)
|
2004-09-26 18:24:14 +02:00
|
|
|
sprintf ((char *)id, "%.14s", unix_hostname ());
|
2004-09-10 22:48:21 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy (id, sysid_print (lsp_id), 15);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
if (frag)
|
2004-09-26 18:24:14 +02:00
|
|
|
sprintf ((char *)trg, "%s.%02x-%02x", id, LSP_PSEUDO_ID (lsp_id),
|
2004-09-10 22:48:21 +02:00
|
|
|
LSP_FRAGMENT (lsp_id));
|
2003-12-23 09:09:43 +01:00
|
|
|
else
|
2004-09-26 18:24:14 +02:00
|
|
|
sprintf ((char *)trg, "%s.%02x", id, LSP_PSEUDO_ID (lsp_id));
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
/* Convert the lsp attribute bits to attribute string */
|
2004-10-07 22:07:40 +02:00
|
|
|
const char *
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_bits2string (u_char * lsp_bits)
|
|
|
|
{
|
|
|
|
char *pos = lsp_bits_string;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
if (!*lsp_bits)
|
2003-12-23 09:09:43 +01:00
|
|
|
return " none";
|
|
|
|
|
|
|
|
/* we only focus on the default metric */
|
|
|
|
pos += sprintf (pos, "%d/",
|
2004-09-10 22:48:21 +02:00
|
|
|
ISIS_MASK_LSP_ATT_DEFAULT_BIT (*lsp_bits) ? 1 : 0);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
pos += sprintf (pos, "%d/",
|
2004-09-10 22:48:21 +02:00
|
|
|
ISIS_MASK_LSP_PARTITION_BIT (*lsp_bits) ? 1 : 0);
|
|
|
|
|
|
|
|
pos += sprintf (pos, "%d", ISIS_MASK_LSP_OL_BIT (*lsp_bits) ? 1 : 0);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
*(pos) = '\0';
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
return lsp_bits_string;
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* this function prints the lsp on show isis database */
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_print (dnode_t * node, struct vty *vty, char dynhost)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2004-09-10 22:48:21 +02:00
|
|
|
struct isis_lsp *lsp = dnode_get (node);
|
2003-12-23 09:09:43 +01:00
|
|
|
u_char LSPid[255];
|
|
|
|
|
|
|
|
lspid_print (lsp->lsp_header->lsp_id, LSPid, dynhost, 1);
|
2004-09-10 22:48:21 +02:00
|
|
|
vty_out (vty, "%-21s%c ", LSPid, lsp->own_lsp ? '*' : ' ');
|
|
|
|
vty_out (vty, "0x%08x ", ntohl (lsp->lsp_header->seq_num));
|
|
|
|
vty_out (vty, "0x%04x ", ntohs (lsp->lsp_header->checksum));
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
if (ntohs (lsp->lsp_header->rem_lifetime) == 0)
|
|
|
|
vty_out (vty, " (%2u)", lsp->age_out);
|
2003-12-23 09:09:43 +01:00
|
|
|
else
|
2004-09-10 22:48:21 +02:00
|
|
|
vty_out (vty, "%5u", ntohs (lsp->lsp_header->rem_lifetime));
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
vty_out (vty, " %s%s",
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_bits2string (&lsp->lsp_header->lsp_bits), VTY_NEWLINE);
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_print_detail (dnode_t * node, struct vty *vty, char dynhost)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_lsp *lsp = dnode_get (node);
|
|
|
|
struct area_addr *area_addr;
|
2004-09-10 22:48:21 +02:00
|
|
|
int i;
|
2005-09-28 20:45:54 +02:00
|
|
|
struct listnode *lnode;
|
2003-12-23 09:09:43 +01:00
|
|
|
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;
|
|
|
|
#ifdef HAVE_IPV6
|
|
|
|
struct ipv6_reachability *ipv6_reach;
|
|
|
|
struct in6_addr in6;
|
2006-12-08 02:09:50 +01:00
|
|
|
u_char buff[BUFSIZ];
|
2003-12-23 09:09:43 +01:00
|
|
|
#endif
|
|
|
|
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);
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_print (node, vty, dynhost);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
/* for all area address */
|
2004-09-10 22:48:21 +02:00
|
|
|
if (lsp->tlv_data.area_addrs)
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.area_addrs, lnode, area_addr))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2004-10-07 22:07:40 +02:00
|
|
|
vty_out (vty, " Area Address: %s%s",
|
2004-09-10 22:48:21 +02:00
|
|
|
isonet_print (area_addr->area_addr, area_addr->addr_len),
|
|
|
|
VTY_NEWLINE);
|
|
|
|
}
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/* for the nlpid tlv */
|
2004-09-10 22:48:21 +02:00
|
|
|
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:
|
2004-10-07 22:07:40 +02:00
|
|
|
vty_out (vty, " NLPID: 0x%X%s",
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp->tlv_data.nlpids->nlpids[i], VTY_NEWLINE);
|
|
|
|
break;
|
|
|
|
default:
|
2004-10-07 22:07:40 +02:00
|
|
|
vty_out (vty, " NLPID: %s%s", "unknown", VTY_NEWLINE);
|
2004-09-10 22:48:21 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
/* for the hostname tlv */
|
2004-09-10 22:48:21 +02:00
|
|
|
if (lsp->tlv_data.hostname)
|
|
|
|
{
|
2009-01-22 02:51:57 +01:00
|
|
|
memset (hostname, 0, sizeof (hostname));
|
2004-09-10 22:48:21 +02:00
|
|
|
memcpy (hostname, lsp->tlv_data.hostname->name,
|
|
|
|
lsp->tlv_data.hostname->namelen);
|
|
|
|
vty_out (vty, " Hostname: %s%s", hostname, VTY_NEWLINE);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
if (lsp->tlv_data.ipv4_addrs)
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_addrs, lnode, ipv4_addr))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
memcpy (ipv4_address, inet_ntoa (*ipv4_addr), sizeof (ipv4_address));
|
|
|
|
vty_out (vty, " IP: %s%s", ipv4_address, VTY_NEWLINE);
|
|
|
|
}
|
|
|
|
|
2004-10-07 22:07:40 +02:00
|
|
|
/* 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 IS neighbor tlv */
|
|
|
|
if (lsp->tlv_data.is_neighs)
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, lnode, is_neigh))
|
2004-10-07 22:07:40 +02:00
|
|
|
{
|
|
|
|
lspid_print (is_neigh->neigh_id, LSPid, dynhost, 0);
|
2005-09-19 08:35:47 +02:00
|
|
|
vty_out (vty, " Metric: %-10d IS %s%s",
|
2004-10-07 22:07:40 +02:00
|
|
|
is_neigh->metrics.metric_default, LSPid, VTY_NEWLINE);
|
|
|
|
}
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/* for the internal reachable tlv */
|
|
|
|
if (lsp->tlv_data.ipv4_int_reachs)
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_int_reachs, lnode,
|
|
|
|
ipv4_reach))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
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));
|
2005-09-19 08:35:47 +02:00
|
|
|
vty_out (vty, " Metric: %-10d IP-Internal %s %s%s",
|
2004-09-10 22:48:21 +02:00
|
|
|
ipv4_reach->metrics.metric_default, ipv4_reach_prefix,
|
|
|
|
ipv4_reach_mask, VTY_NEWLINE);
|
|
|
|
}
|
2003-12-23 12:51:08 +01:00
|
|
|
|
|
|
|
/* for the external reachable tlv */
|
|
|
|
if (lsp->tlv_data.ipv4_ext_reachs)
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_ext_reachs, lnode,
|
|
|
|
ipv4_reach))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
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));
|
2005-09-19 08:35:47 +02:00
|
|
|
vty_out (vty, " Metric: %-10d IP-External %s %s%s",
|
2004-09-10 22:48:21 +02:00
|
|
|
ipv4_reach->metrics.metric_default, ipv4_reach_prefix,
|
|
|
|
ipv4_reach_mask, VTY_NEWLINE);
|
|
|
|
}
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
|
2003-12-23 12:51:08 +01:00
|
|
|
/* IPv6 tlv */
|
|
|
|
#ifdef HAVE_IPV6
|
|
|
|
if (lsp->tlv_data.ipv6_reachs)
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv6_reachs, lnode, ipv6_reach))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
memset (&in6, 0, sizeof (in6));
|
|
|
|
memcpy (in6.s6_addr, ipv6_reach->prefix,
|
|
|
|
PSIZE (ipv6_reach->prefix_len));
|
2004-09-26 18:24:14 +02:00
|
|
|
inet_ntop (AF_INET6, &in6, (char *)buff, BUFSIZ);
|
2003-12-23 12:51:08 +01:00
|
|
|
if ((ipv6_reach->control_info &&
|
2004-09-10 22:48:21 +02:00
|
|
|
CTRL_INFO_DISTRIBUTION) == DISTRIBUTION_INTERNAL)
|
2005-09-19 08:35:47 +02:00
|
|
|
vty_out (vty, " Metric: %-10d IPv6-Internal %s/%d%s",
|
2004-09-10 22:48:21 +02:00
|
|
|
ntohl (ipv6_reach->metric),
|
|
|
|
buff, ipv6_reach->prefix_len, VTY_NEWLINE);
|
2003-12-23 12:51:08 +01:00
|
|
|
else
|
2005-09-19 08:35:47 +02:00
|
|
|
vty_out (vty, " Metric: %-10d IPv6-External %s/%d%s",
|
2004-09-10 22:48:21 +02:00
|
|
|
ntohl (ipv6_reach->metric),
|
|
|
|
buff, ipv6_reach->prefix_len, VTY_NEWLINE);
|
2003-12-23 12:51:08 +01:00
|
|
|
}
|
|
|
|
#endif
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
|
2004-10-07 22:07:40 +02:00
|
|
|
/* TE IS neighbor tlv */
|
2003-12-23 09:09:43 +01:00
|
|
|
if (lsp->tlv_data.te_is_neighs)
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, lnode, te_is_neigh))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2005-09-19 08:35:47 +02:00
|
|
|
uint32_t metric;
|
|
|
|
memcpy (&metric, te_is_neigh->te_metric, 3);
|
2004-09-10 22:48:21 +02:00
|
|
|
lspid_print (te_is_neigh->neigh_id, LSPid, dynhost, 0);
|
2005-09-19 08:35:47 +02:00
|
|
|
vty_out (vty, " Metric: %-10d IS-Extended %s%s",
|
|
|
|
ntohl (metric << 8), LSPid, VTY_NEWLINE);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2004-10-07 22:07:40 +02:00
|
|
|
/* TE IPv4 tlv */
|
2003-12-23 09:09:43 +01:00
|
|
|
if (lsp->tlv_data.te_ipv4_reachs)
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_ipv4_reachs, lnode,
|
|
|
|
te_ipv4_reach))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2004-10-07 22:07:40 +02:00
|
|
|
/* FIXME: There should be better way to output this stuff. */
|
2005-09-19 08:35:47 +02:00
|
|
|
vty_out (vty, " Metric: %-10d IP-Extended %s/%d%s",
|
2004-10-07 22:07:40 +02:00
|
|
|
ntohl (te_ipv4_reach->te_metric),
|
2004-09-10 22:48:21 +02:00
|
|
|
inet_ntoa (newprefix2inaddr (&te_ipv4_reach->prefix_start,
|
|
|
|
te_ipv4_reach->control)),
|
2004-10-07 22:07:40 +02:00
|
|
|
te_ipv4_reach->control & 0x3F, VTY_NEWLINE);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
return;
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* print all the lsps info in the local lspdb */
|
2004-09-10 22:48:21 +02:00
|
|
|
int
|
|
|
|
lsp_print_all (struct vty *vty, dict_t * lspdb, char detail, char dynhost)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
dnode_t *node = dict_first (lspdb), *next;
|
2003-12-23 09:09:43 +01:00
|
|
|
int lsp_count = 0;
|
|
|
|
|
|
|
|
/* print the title, for both modes */
|
|
|
|
vty_out (vty, "LSP ID LSP Seq Num LSP Checksum "
|
2004-09-10 22:48:21 +02:00
|
|
|
"LSP Holdtime ATT/P/OL%s", VTY_NEWLINE);
|
|
|
|
|
|
|
|
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 (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 (node, vty, dynhost);
|
|
|
|
node = next;
|
|
|
|
lsp_count++;
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return lsp_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
#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))
|
|
|
|
|
2005-09-26 19:39:48 +02:00
|
|
|
/* FIXME: It shouldn't be necessary to pass tlvsize here, TLVs can have
|
|
|
|
* variable length (TE TLVs, sub TLVs). */
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_tlv_fit (struct isis_lsp *lsp, struct list **from, struct list **to,
|
2004-09-10 22:48:21 +02:00
|
|
|
int tlvsize, int frag_thold,
|
|
|
|
int tlv_build_func (struct list *, struct stream *))
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
int count, i;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/* can we fit all ? */
|
2004-09-10 22:48:21 +02:00
|
|
|
if (!FRAG_NEEDED (lsp->pdu, frag_thold, listcount (*from) * tlvsize + 2))
|
|
|
|
{
|
|
|
|
tlv_build_func (*from, lsp->pdu);
|
|
|
|
*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));
|
|
|
|
if (count)
|
|
|
|
count = count / tlvsize;
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
listnode_add (*to, listgetdata (listhead (*from)));
|
|
|
|
listnode_delete (*from, listgetdata (listhead (*from)));
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
tlv_build_func (*to, lsp->pdu);
|
|
|
|
}
|
2005-02-09 16:51:56 +01:00
|
|
|
lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static struct isis_lsp *
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_next_frag (u_char frag_num, struct isis_lsp *lsp0, struct isis_area *area,
|
|
|
|
int level)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_lsp *lsp;
|
2004-09-10 22:48:21 +02:00
|
|
|
u_char frag_id[ISIS_SYS_ID_LEN + 2];
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
memcpy (frag_id, lsp0->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 1);
|
|
|
|
LSP_FRAGMENT (frag_id) = frag_num;
|
|
|
|
lsp = lsp_search (frag_id, area->lspdb[level - 1]);
|
2004-09-10 22:48:21 +02:00
|
|
|
if (lsp)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Clear the TLVs, but inherit the authinfo
|
|
|
|
*/
|
|
|
|
lsp_clear_data (lsp);
|
|
|
|
if (lsp0->tlv_data.auth_info.type)
|
|
|
|
{
|
|
|
|
memcpy (&lsp->tlv_data.auth_info, &lsp->tlv_data.auth_info,
|
|
|
|
sizeof (struct isis_passwd));
|
|
|
|
tlv_add_authinfo (lsp->tlv_data.auth_info.type,
|
|
|
|
lsp->tlv_data.auth_info.len,
|
|
|
|
lsp->tlv_data.auth_info.passwd, lsp->pdu);
|
|
|
|
}
|
|
|
|
return lsp;
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
lsp = lsp_new (frag_id, area->max_lsp_lifetime[level - 1], 0, area->is_type,
|
2004-09-10 22:48:21 +02:00
|
|
|
0, level);
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp->own_lsp = 1;
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_insert (lsp, area->lspdb[level - 1]);
|
2003-12-23 09:09:43 +01:00
|
|
|
listnode_add (lsp0->lspu.frags, lsp);
|
|
|
|
lsp->lspu.zero_lsp = lsp0;
|
|
|
|
/*
|
|
|
|
* Copy the authinfo from zero LSP
|
|
|
|
*/
|
2004-09-10 22:48:21 +02:00
|
|
|
if (lsp0->tlv_data.auth_info.type)
|
|
|
|
{
|
|
|
|
memcpy (&lsp->tlv_data.auth_info, &lsp->tlv_data.auth_info,
|
|
|
|
sizeof (struct isis_passwd));
|
|
|
|
tlv_add_authinfo (lsp->tlv_data.auth_info.type,
|
|
|
|
lsp->tlv_data.auth_info.len,
|
|
|
|
lsp->tlv_data.auth_info.passwd, lsp->pdu);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
return lsp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Builds the LSP data part. This func creates a new frag whenever
|
|
|
|
* area->lsp_frag_threshold is exceeded.
|
|
|
|
*/
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_build_nonpseudo (struct isis_lsp *lsp, struct isis_area *area)
|
|
|
|
{
|
|
|
|
struct is_neigh *is_neigh;
|
2005-09-26 19:39:48 +02:00
|
|
|
struct te_is_neigh *te_is_neigh;
|
2005-09-28 20:45:54 +02:00
|
|
|
struct listnode *node, *ipnode;
|
2003-12-23 09:09:43 +01:00
|
|
|
int level = lsp->level;
|
|
|
|
struct isis_circuit *circuit;
|
|
|
|
struct prefix_ipv4 *ipv4;
|
|
|
|
struct ipv4_reachability *ipreach;
|
2005-09-26 19:39:48 +02:00
|
|
|
struct te_ipv4_reachability *te_ipreach;
|
2003-12-23 09:09:43 +01:00
|
|
|
struct isis_adjacency *nei;
|
|
|
|
#ifdef HAVE_IPV6
|
2004-09-21 16:17:04 +02:00
|
|
|
struct prefix_ipv6 *ipv6, *ip6prefix;
|
2003-12-23 09:09:43 +01:00
|
|
|
struct ipv6_reachability *ip6reach;
|
|
|
|
#endif /* HAVE_IPV6 */
|
|
|
|
struct tlvs tlv_data;
|
|
|
|
struct isis_lsp *lsp0 = lsp;
|
|
|
|
struct isis_passwd *passwd;
|
2004-10-03 20:18:34 +02:00
|
|
|
struct in_addr *routerid;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* First add the tlvs related to area
|
|
|
|
*/
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/* 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);
|
|
|
|
/* Protocols Supported */
|
2004-09-10 22:48:21 +02:00
|
|
|
if (area->ip_circuits > 0
|
2003-12-23 09:09:43 +01:00
|
|
|
#ifdef HAVE_IPV6
|
|
|
|
|| area->ipv6_circuits > 0
|
|
|
|
#endif /* HAVE_IPV6 */
|
2004-09-10 22:48:21 +02:00
|
|
|
)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2005-09-01 19:52:33 +02:00
|
|
|
lsp->tlv_data.nlpids = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct nlpids));
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp->tlv_data.nlpids->count = 0;
|
2004-09-10 22:48:21 +02:00
|
|
|
if (area->ip_circuits > 0)
|
|
|
|
{
|
|
|
|
lsp->tlv_data.nlpids->count++;
|
|
|
|
lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP;
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
#ifdef HAVE_IPV6
|
2004-09-10 22:48:21 +02:00
|
|
|
if (area->ipv6_circuits > 0)
|
|
|
|
{
|
|
|
|
lsp->tlv_data.nlpids->count++;
|
|
|
|
lsp->tlv_data.nlpids->nlpids[lsp->tlv_data.nlpids->count - 1] =
|
|
|
|
NLPID_IPV6;
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
#endif /* HAVE_IPV6 */
|
|
|
|
}
|
|
|
|
/* Dynamic Hostname */
|
2004-09-10 22:48:21 +02:00
|
|
|
if (area->dynhostname)
|
|
|
|
{
|
|
|
|
lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV,
|
|
|
|
sizeof (struct hostname));
|
2003-12-23 09:56:18 +01:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
memcpy (lsp->tlv_data.hostname->name, unix_hostname (),
|
|
|
|
strlen (unix_hostname ()));
|
|
|
|
lsp->tlv_data.hostname->namelen = strlen (unix_hostname ());
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Building the zero lsp
|
|
|
|
*/
|
2005-09-01 19:52:33 +02:00
|
|
|
|
|
|
|
/* 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. */
|
2005-09-04 23:36:36 +02:00
|
|
|
stream_reset (lsp->pdu);
|
2005-09-01 19:52:33 +02:00
|
|
|
stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/*
|
|
|
|
* Add the authentication info if its present
|
|
|
|
*/
|
2004-09-10 22:48:21 +02:00
|
|
|
(level == 1) ? (passwd = &area->area_passwd) :
|
|
|
|
(passwd = &area->domain_passwd);
|
|
|
|
if (passwd->type)
|
|
|
|
{
|
|
|
|
memcpy (&lsp->tlv_data.auth_info, passwd, sizeof (struct isis_passwd));
|
|
|
|
tlv_add_authinfo (passwd->type, passwd->len, passwd->passwd, lsp->pdu);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
if (lsp->tlv_data.nlpids)
|
|
|
|
tlv_add_nlpid (lsp->tlv_data.nlpids, lsp->pdu);
|
|
|
|
if (lsp->tlv_data.hostname)
|
|
|
|
tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu);
|
2004-09-10 22:48:21 +02:00
|
|
|
if (lsp->tlv_data.area_addrs && listcount (lsp->tlv_data.area_addrs) > 0)
|
2003-12-23 09:09:43 +01:00
|
|
|
tlv_add_area_addrs (lsp->tlv_data.area_addrs, lsp->pdu);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2005-09-26 19:58:24 +02:00
|
|
|
/* 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. */
|
2004-10-03 20:18:34 +02:00
|
|
|
if (router_id_zebra.s_addr != 0)
|
|
|
|
{
|
|
|
|
if (lsp->tlv_data.ipv4_addrs == NULL)
|
2005-09-02 03:38:16 +02:00
|
|
|
{
|
|
|
|
lsp->tlv_data.ipv4_addrs = list_new ();
|
|
|
|
lsp->tlv_data.ipv4_addrs->del = free_tlv;
|
|
|
|
}
|
2004-10-03 20:18:34 +02:00
|
|
|
|
|
|
|
routerid = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct in_addr));
|
|
|
|
routerid->s_addr = router_id_zebra.s_addr;
|
|
|
|
listnode_add (lsp->tlv_data.ipv4_addrs, routerid);
|
2005-09-26 19:58:24 +02:00
|
|
|
tlv_add_in_addr (routerid, lsp->pdu, IPV4_ADDR);
|
2004-10-03 20:18:34 +02:00
|
|
|
|
2005-09-26 19:58:24 +02:00
|
|
|
/* Exactly same data is put into TE router ID TLV, but only if new style
|
|
|
|
* TLV's are in use. */
|
|
|
|
if (area->newmetric)
|
|
|
|
{
|
|
|
|
lsp->tlv_data.router_id = XMALLOC (MTYPE_ISIS_TLV,
|
|
|
|
sizeof (struct in_addr));
|
|
|
|
lsp->tlv_data.router_id->id.s_addr = router_id_zebra.s_addr;
|
|
|
|
tlv_add_in_addr (&lsp->tlv_data.router_id->id, lsp->pdu, TE_ROUTER_ID);
|
|
|
|
}
|
2004-10-03 20:18:34 +02:00
|
|
|
}
|
2005-09-19 06:23:34 +02:00
|
|
|
|
2005-09-26 19:58:24 +02:00
|
|
|
memset (&tlv_data, 0, sizeof (struct tlvs));
|
|
|
|
|
2005-09-19 06:23:34 +02:00
|
|
|
#ifdef TOPOLOGY_GENERATE
|
|
|
|
/* If topology exists (and we create topology for level 1 only), create
|
|
|
|
* (hardcoded) link to topology. */
|
|
|
|
if (area->topology && level == 1)
|
|
|
|
{
|
|
|
|
if (tlv_data.is_neighs == NULL)
|
2005-09-26 19:39:48 +02:00
|
|
|
{
|
|
|
|
tlv_data.is_neighs = list_new ();
|
|
|
|
tlv_data.is_neighs->del = free_tlv;
|
|
|
|
}
|
2005-09-28 20:45:54 +02:00
|
|
|
is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
|
2005-09-19 06:23:34 +02:00
|
|
|
|
|
|
|
memcpy (&is_neigh->neigh_id, area->topology_baseis, ISIS_SYS_ID_LEN);
|
|
|
|
is_neigh->neigh_id[ISIS_SYS_ID_LEN - 1] = (1 & 0xFF);
|
|
|
|
is_neigh->neigh_id[ISIS_SYS_ID_LEN - 2] = ((1 >> 8) & 0xFF);
|
|
|
|
is_neigh->metrics.metric_default = 0x01;
|
|
|
|
is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
|
|
|
|
is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
|
|
|
|
is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
|
|
|
|
listnode_add (tlv_data.is_neighs, is_neigh);
|
|
|
|
}
|
|
|
|
#endif /* TOPOLOGY_GENERATE */
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/*
|
|
|
|
* Then build lists of tlvs related to circuits
|
|
|
|
*/
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
if (circuit->state != C_STATE_UP)
|
|
|
|
continue;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
/*
|
|
|
|
* Add IPv4 internal reachability of this circuit
|
|
|
|
*/
|
|
|
|
if (circuit->ip_router && circuit->ip_addrs &&
|
|
|
|
circuit->ip_addrs->count > 0)
|
|
|
|
{
|
2005-09-26 19:39:48 +02:00
|
|
|
if (area->oldmetric)
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2005-09-26 19:39:48 +02:00
|
|
|
if (tlv_data.ipv4_int_reachs == NULL)
|
|
|
|
{
|
|
|
|
tlv_data.ipv4_int_reachs = list_new ();
|
|
|
|
tlv_data.ipv4_int_reachs->del = free_tlv;
|
|
|
|
}
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, ipnode, ipv4))
|
2005-09-26 19:39:48 +02:00
|
|
|
{
|
|
|
|
ipreach =
|
|
|
|
XMALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv4_reachability));
|
|
|
|
ipreach->metrics = circuit->metrics[level - 1];
|
|
|
|
masklen2ip (ipv4->prefixlen, &ipreach->mask);
|
|
|
|
ipreach->prefix.s_addr = ((ipreach->mask.s_addr) &
|
|
|
|
(ipv4->prefix.s_addr));
|
|
|
|
listnode_add (tlv_data.ipv4_int_reachs, ipreach);
|
|
|
|
}
|
2005-09-02 03:38:16 +02:00
|
|
|
tlv_data.ipv4_int_reachs->del = free_tlv;
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2005-09-26 19:39:48 +02:00
|
|
|
if (area->newmetric)
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2005-09-26 19:39:48 +02:00
|
|
|
if (tlv_data.te_ipv4_reachs == NULL)
|
|
|
|
{
|
|
|
|
tlv_data.te_ipv4_reachs = list_new ();
|
|
|
|
tlv_data.te_ipv4_reachs->del = free_tlv;
|
|
|
|
}
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, ipnode, ipv4))
|
2005-09-26 19:39:48 +02:00
|
|
|
{
|
|
|
|
/* 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);
|
2005-09-26 20:06:47 +02:00
|
|
|
|
|
|
|
if (area->oldmetric)
|
|
|
|
te_ipreach->te_metric = htonl (circuit->metrics[level - 1].metric_default);
|
|
|
|
else
|
|
|
|
te_ipreach->te_metric = htonl (circuit->te_metric[level - 1]);
|
|
|
|
|
2005-09-26 19:39:48 +02:00
|
|
|
te_ipreach->control = (ipv4->prefixlen & 0x3F);
|
|
|
|
memcpy (&te_ipreach->prefix_start, &ipv4->prefix.s_addr,
|
|
|
|
(ipv4->prefixlen + 7)/8);
|
|
|
|
listnode_add (tlv_data.te_ipv4_reachs, te_ipreach);
|
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
#ifdef HAVE_IPV6
|
2004-09-10 22:48:21 +02:00
|
|
|
/*
|
|
|
|
* 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 ();
|
2005-09-02 03:38:16 +02:00
|
|
|
tlv_data.ipv6_reachs->del = free_tlv;
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, ipnode, ipv6))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
ip6reach =
|
2005-09-01 19:52:33 +02:00
|
|
|
XCALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv6_reachability));
|
2005-09-26 20:06:47 +02:00
|
|
|
|
|
|
|
if (area->oldmetric)
|
|
|
|
ip6reach->metric =
|
|
|
|
htonl (circuit->metrics[level - 1].metric_default);
|
|
|
|
else
|
|
|
|
ip6reach->metric = htonl (circuit->te_metric[level - 1]);
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
ip6reach->control_info = 0;
|
|
|
|
ip6reach->prefix_len = ipv6->prefixlen;
|
2004-09-21 16:17:04 +02:00
|
|
|
memcpy (&ip6prefix, &ipv6, sizeof(ip6prefix));
|
|
|
|
apply_mask_ipv6 (ip6prefix);
|
|
|
|
memcpy (ip6reach->prefix, ip6prefix->prefix.s6_addr,
|
|
|
|
sizeof (ip6reach->prefix));
|
2004-09-10 22:48:21 +02:00
|
|
|
listnode_add (tlv_data.ipv6_reachs, ip6reach);
|
|
|
|
}
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
#endif /* HAVE_IPV6 */
|
2004-09-10 22:48:21 +02:00
|
|
|
|
|
|
|
switch (circuit->circ_type)
|
|
|
|
{
|
|
|
|
case CIRCUIT_T_BROADCAST:
|
|
|
|
if (level & circuit->circuit_is_type)
|
|
|
|
{
|
2005-09-26 19:39:48 +02:00
|
|
|
if (area->oldmetric)
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2005-09-26 19:39:48 +02:00
|
|
|
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 == 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 = circuit->metrics[level - 1];
|
|
|
|
listnode_add (tlv_data.is_neighs, is_neigh);
|
2005-09-02 03:38:16 +02:00
|
|
|
tlv_data.is_neighs->del = free_tlv;
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2005-09-26 19:39:48 +02:00
|
|
|
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));
|
|
|
|
if (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);
|
2005-09-26 20:06:47 +02:00
|
|
|
if (area->oldmetric)
|
|
|
|
metric =
|
|
|
|
((htonl(circuit->metrics[level - 1].metric_default) >> 8)
|
|
|
|
& 0xffffff);
|
|
|
|
else
|
|
|
|
metric = ((htonl(*circuit->te_metric) >> 8) & 0xffffff);
|
|
|
|
|
2005-09-26 19:39:48 +02:00
|
|
|
memcpy (te_is_neigh->te_metric, &metric, 3);
|
|
|
|
listnode_add (tlv_data.te_is_neighs, te_is_neigh);
|
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CIRCUIT_T_P2P:
|
|
|
|
nei = circuit->u.p2p.neighbor;
|
|
|
|
if (nei && (level & nei->circuit_t))
|
|
|
|
{
|
2005-09-26 19:39:48 +02:00
|
|
|
if (area->oldmetric)
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2005-09-26 19:39:48 +02:00
|
|
|
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 = circuit->metrics[level - 1];
|
|
|
|
listnode_add (tlv_data.is_neighs, is_neigh);
|
|
|
|
}
|
|
|
|
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 = ((htonl(*circuit->te_metric) >> 8) & 0xffffff);
|
|
|
|
memcpy (te_is_neigh->te_metric, &metric, 3);
|
|
|
|
listnode_add (tlv_data.te_is_neighs, te_is_neigh);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CIRCUIT_T_STATIC_IN:
|
|
|
|
zlog_warn ("lsp_area_create: unsupported circuit type");
|
|
|
|
break;
|
|
|
|
case CIRCUIT_T_STATIC_OUT:
|
|
|
|
zlog_warn ("lsp_area_create: unsupported circuit type");
|
|
|
|
break;
|
|
|
|
case CIRCUIT_T_DA:
|
|
|
|
zlog_warn ("lsp_area_create: unsupported circuit type");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
zlog_warn ("lsp_area_create: unknown circuit type");
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
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_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);
|
|
|
|
}
|
2005-09-26 19:39:48 +02:00
|
|
|
/* 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,
|
|
|
|
9, 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);
|
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
|
|
|
|
#ifdef HAVE_IPV6
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
#endif /* HAVE_IPV6 */
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2005-09-26 19:39:48 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
free_tlvs (&tlv_data);
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 7.3.7 Generation on non-pseudonode LSPs
|
|
|
|
*/
|
2005-01-18 14:53:33 +01:00
|
|
|
static int
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_generate_non_pseudo (struct isis_area *area, int level)
|
|
|
|
{
|
2003-12-23 09:09:43 +01:00
|
|
|
struct isis_lsp *oldlsp, *newlsp;
|
|
|
|
u_int32_t seq_num = 0;
|
|
|
|
u_char lspid[ISIS_SYS_ID_LEN + 2];
|
|
|
|
|
|
|
|
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 */
|
2004-09-10 22:48:21 +02:00
|
|
|
if ((area->is_type & level) == level)
|
|
|
|
{
|
|
|
|
oldlsp = lsp_search (lspid, area->lspdb[level - 1]);
|
|
|
|
if (oldlsp)
|
|
|
|
{
|
|
|
|
seq_num = ntohl (oldlsp->lsp_header->seq_num);
|
|
|
|
lsp_search_and_destroy (oldlsp->lsp_header->lsp_id,
|
|
|
|
area->lspdb[level - 1]);
|
|
|
|
/* FIXME: we should actually initiate a purge */
|
|
|
|
}
|
|
|
|
newlsp = lsp_new (lspid, area->max_lsp_lifetime[level - 1], seq_num,
|
|
|
|
area->is_type, 0, level);
|
|
|
|
newlsp->own_lsp = 1;
|
|
|
|
|
|
|
|
lsp_insert (newlsp, area->lspdb[level - 1]);
|
|
|
|
/* build_lsp_data (newlsp, area); */
|
|
|
|
lsp_build_nonpseudo (newlsp, area);
|
|
|
|
/* time to calculate our checksum */
|
|
|
|
lsp_seqnum_update (newlsp);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
/* DEBUG_ADJ_PACKETS */
|
2004-09-10 22:48:21 +02:00
|
|
|
if (isis->debugs & DEBUG_ADJ_PACKETS)
|
|
|
|
{
|
|
|
|
/* FIXME: is this place right? fix missing info */
|
2004-12-24 01:14:50 +01:00
|
|
|
zlog_debug ("ISIS-Upd (%s): Building L%d LSP", area->area_tag, level);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
return ISIS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 7.3.9 Generation of level 1 LSPs (non-pseudonode)
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lsp_l1_generate (struct isis_area *area)
|
|
|
|
{
|
2004-09-10 22:48:21 +02:00
|
|
|
THREAD_TIMER_ON (master, area->t_lsp_refresh[0], lsp_refresh_l1, area,
|
|
|
|
MAX_LSP_GEN_INTERVAL);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
return lsp_generate_non_pseudo (area, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 7.3.9 Generation of level 2 LSPs (non-pseudonode)
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lsp_l2_generate (struct isis_area *area)
|
|
|
|
{
|
2004-09-10 22:48:21 +02:00
|
|
|
THREAD_TIMER_ON (master, area->t_lsp_refresh[1], lsp_refresh_l2, area,
|
|
|
|
MAX_LSP_GEN_INTERVAL);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
return lsp_generate_non_pseudo (area, 2);
|
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static int
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_non_pseudo_regenerate (struct isis_area *area, int level)
|
|
|
|
{
|
|
|
|
dict_t *lspdb = area->lspdb[level - 1];
|
|
|
|
struct isis_lsp *lsp, *frag;
|
|
|
|
struct listnode *node;
|
|
|
|
u_char lspid[ISIS_SYS_ID_LEN + 2];
|
|
|
|
|
|
|
|
memset (lspid, 0, ISIS_SYS_ID_LEN + 2);
|
|
|
|
memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp = lsp_search (lspid, lspdb);
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
if (!lsp)
|
|
|
|
{
|
|
|
|
zlog_err
|
|
|
|
("ISIS-Upd (%s): lsp_non_pseudo_regenerate(): no L%d LSP found!",
|
|
|
|
area->area_tag, level);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
return ISIS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
lsp_clear_data (lsp);
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_build_nonpseudo (lsp, area);
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp->lsp_header->rem_lifetime = htons (isis_jitter
|
|
|
|
(area->max_lsp_lifetime[level - 1],
|
|
|
|
MAX_AGE_JITTER));
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_seqnum_update (lsp);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
|
|
|
if (isis->debugs & DEBUG_UPDATE_PACKETS)
|
|
|
|
{
|
2004-12-24 01:14:50 +01:00
|
|
|
zlog_debug ("ISIS-Upd (%s): refreshing our L%d LSP %s, "
|
|
|
|
"seq 0x%08x, cksum 0x%04x lifetime %us",
|
|
|
|
area->area_tag,
|
|
|
|
level,
|
|
|
|
rawlspid_print (lsp->lsp_header->lsp_id),
|
|
|
|
ntohl (lsp->lsp_header->seq_num),
|
|
|
|
ntohs (lsp->lsp_header->checksum),
|
|
|
|
ntohs (lsp->lsp_header->rem_lifetime));
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
lsp->last_generated = time (NULL);
|
|
|
|
area->lsp_regenerate_pending[level - 1] = 0;
|
|
|
|
ISIS_FLAGS_SET_ALL (lsp->SRMflags);
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (lsp->lspu.frags, node, frag))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
frag->lsp_header->rem_lifetime = htons (isis_jitter
|
|
|
|
(area->
|
|
|
|
max_lsp_lifetime[level - 1],
|
|
|
|
MAX_AGE_JITTER));
|
|
|
|
ISIS_FLAGS_SET_ALL (frag->SRMflags);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
if (area->ip_circuits)
|
|
|
|
isis_spf_schedule (area, level);
|
|
|
|
#ifdef HAVE_IPV6
|
|
|
|
if (area->ipv6_circuits)
|
|
|
|
isis_spf_schedule6 (area, level);
|
|
|
|
#endif
|
|
|
|
return ISIS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Done at least every MAX_LSP_GEN_INTERVAL. Search own LSPs, update holding
|
|
|
|
* time and set SRM
|
|
|
|
*/
|
2004-09-10 22:48:21 +02:00
|
|
|
int
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_refresh_l1 (struct thread *thread)
|
|
|
|
{
|
|
|
|
struct isis_area *area;
|
|
|
|
unsigned long ref_time;
|
|
|
|
|
|
|
|
area = THREAD_ARG (thread);
|
|
|
|
assert (area);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
area->t_lsp_refresh[0] = NULL;
|
2004-09-10 22:48:21 +02:00
|
|
|
if (area->is_type & IS_LEVEL_1)
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_non_pseudo_regenerate (area, 1);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
|
|
|
ref_time = area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
|
2003-12-23 09:09:43 +01:00
|
|
|
MAX_LSP_GEN_INTERVAL : area->lsp_refresh[0];
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
THREAD_TIMER_ON (master, area->t_lsp_refresh[0], lsp_refresh_l1, area,
|
|
|
|
isis_jitter (ref_time, MAX_AGE_JITTER));
|
2004-02-11 21:26:31 +01:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return ISIS_OK;
|
|
|
|
}
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
int
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_refresh_l2 (struct thread *thread)
|
|
|
|
{
|
|
|
|
struct isis_area *area;
|
|
|
|
unsigned long ref_time;
|
|
|
|
|
|
|
|
area = THREAD_ARG (thread);
|
|
|
|
assert (area);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
area->t_lsp_refresh[1] = NULL;
|
2004-09-10 22:48:21 +02:00
|
|
|
if (area->is_type & IS_LEVEL_2)
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_non_pseudo_regenerate (area, 2);
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
ref_time = area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ?
|
2003-12-23 09:09:43 +01:00
|
|
|
MAX_LSP_GEN_INTERVAL : area->lsp_refresh[1];
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
THREAD_TIMER_ON (master, area->t_lsp_refresh[1], lsp_refresh_l2, area,
|
|
|
|
isis_jitter (ref_time, MAX_AGE_JITTER));
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
return ISIS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Something has changed -> regenerate LSP
|
|
|
|
*/
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static int
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_l1_regenerate (struct thread *thread)
|
|
|
|
{
|
|
|
|
struct isis_area *area;
|
|
|
|
|
|
|
|
area = THREAD_ARG (thread);
|
|
|
|
area->lsp_regenerate_pending[0] = 0;
|
|
|
|
|
|
|
|
return lsp_non_pseudo_regenerate (area, 1);
|
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static int
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_l2_regenerate (struct thread *thread)
|
|
|
|
{
|
|
|
|
struct isis_area *area;
|
|
|
|
|
|
|
|
area = THREAD_ARG (thread);
|
|
|
|
area->lsp_regenerate_pending[1] = 0;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return lsp_non_pseudo_regenerate (area, 2);
|
|
|
|
}
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
int
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_regenerate_schedule (struct isis_area *area)
|
|
|
|
{
|
|
|
|
struct isis_lsp *lsp;
|
|
|
|
u_char id[ISIS_SYS_ID_LEN + 2];
|
|
|
|
time_t now, diff;
|
2004-09-10 22:48:21 +02:00
|
|
|
memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
|
|
|
|
LSP_PSEUDO_ID (id) = LSP_FRAGMENT (id) = 0;
|
2003-12-23 09:09:43 +01:00
|
|
|
now = time (NULL);
|
|
|
|
/*
|
|
|
|
* First level 1
|
|
|
|
*/
|
2004-09-10 22:48:21 +02:00
|
|
|
if (area->is_type & IS_LEVEL_1)
|
|
|
|
{
|
|
|
|
lsp = lsp_search (id, area->lspdb[0]);
|
|
|
|
if (!lsp || area->lsp_regenerate_pending[0])
|
|
|
|
goto L2;
|
|
|
|
/*
|
|
|
|
* Throttle avoidance
|
|
|
|
*/
|
|
|
|
diff = now - lsp->last_generated;
|
|
|
|
if (diff < MIN_LSP_GEN_INTERVAL)
|
|
|
|
{
|
|
|
|
area->lsp_regenerate_pending[0] = 1;
|
|
|
|
thread_add_timer (master, lsp_l1_regenerate, area,
|
|
|
|
MIN_LSP_GEN_INTERVAL - diff);
|
2004-09-19 21:39:26 +02:00
|
|
|
goto L2;
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
lsp_non_pseudo_regenerate (area, 1);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
/*
|
|
|
|
* then 2
|
|
|
|
*/
|
2004-09-10 22:48:21 +02:00
|
|
|
L2:
|
|
|
|
if (area->is_type & IS_LEVEL_2)
|
|
|
|
{
|
|
|
|
lsp = lsp_search (id, area->lspdb[1]);
|
|
|
|
if (!lsp || area->lsp_regenerate_pending[1])
|
|
|
|
return ISIS_OK;
|
|
|
|
/*
|
|
|
|
* Throttle avoidance
|
|
|
|
*/
|
|
|
|
diff = now - lsp->last_generated;
|
|
|
|
if (diff < MIN_LSP_GEN_INTERVAL)
|
|
|
|
{
|
|
|
|
area->lsp_regenerate_pending[1] = 1;
|
|
|
|
thread_add_timer (master, lsp_l2_regenerate, area,
|
|
|
|
MIN_LSP_GEN_INTERVAL - diff);
|
|
|
|
return ISIS_OK;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
lsp_non_pseudo_regenerate (area, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ISIS_OK;
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Funcs for pseudonode LSPs
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 7.3.8 and 7.3.10 Generation of level 1 and 2 pseudonode LSPs
|
|
|
|
*/
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_build_pseudo (struct isis_lsp *lsp, struct isis_circuit *circuit,
|
|
|
|
int level)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_adjacency *adj;
|
|
|
|
struct is_neigh *is_neigh;
|
2005-09-26 19:39:48 +02:00
|
|
|
struct te_is_neigh *te_is_neigh;
|
2003-12-23 09:09:43 +01:00
|
|
|
struct es_neigh *es_neigh;
|
|
|
|
struct list *adj_list;
|
2005-09-28 20:45:54 +02:00
|
|
|
struct listnode *node;
|
2003-12-23 09:09:43 +01:00
|
|
|
struct isis_passwd *passwd;
|
|
|
|
|
|
|
|
assert (circuit);
|
|
|
|
assert (circuit->circ_type == CIRCUIT_T_BROADCAST);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
if (!circuit->u.bc.is_dr[level - 1])
|
2004-09-10 22:48:21 +02:00
|
|
|
return; /* we are not DIS on this circuit */
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp->level = level;
|
|
|
|
if (level == 1)
|
|
|
|
lsp->lsp_header->lsp_bits |= IS_LEVEL_1;
|
|
|
|
else
|
|
|
|
lsp->lsp_header->lsp_bits |= IS_LEVEL_2;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* add self to IS neighbours
|
|
|
|
*/
|
2005-09-26 19:39:48 +02:00
|
|
|
if (circuit->area->oldmetric)
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2005-09-26 19:39:48 +02:00
|
|
|
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);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2005-09-26 19:39:48 +02:00
|
|
|
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));
|
2005-05-03 11:27:23 +02:00
|
|
|
|
2005-09-26 19:39:48 +02:00
|
|
|
memcpy (&te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
|
|
|
|
listnode_add (lsp->tlv_data.te_is_neighs, te_is_neigh);
|
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
|
|
|
|
adj_list = list_new ();
|
|
|
|
isis_adj_build_up_list (circuit->u.bc.adjdb[level - 1], adj_list);
|
|
|
|
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (adj_list, node, adj))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
if (adj->circuit_t & level)
|
|
|
|
{
|
|
|
|
if ((level == 1 && adj->sys_type == ISIS_SYSTYPE_L1_IS) ||
|
|
|
|
(level == 1 && adj->sys_type == ISIS_SYSTYPE_L2_IS &&
|
2005-09-26 19:39:48 +02:00
|
|
|
adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
|
2004-09-10 22:48:21 +02:00
|
|
|
(level == 2 && adj->sys_type == ISIS_SYSTYPE_L2_IS))
|
|
|
|
{
|
|
|
|
/* an IS neighbour -> add it */
|
2005-09-26 19:39:48 +02:00
|
|
|
if (circuit->area->oldmetric)
|
|
|
|
{
|
|
|
|
is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
|
2005-05-03 11:27:23 +02:00
|
|
|
|
2005-09-26 19:39:48 +02:00
|
|
|
memcpy (&is_neigh->neigh_id, adj->sysid, ISIS_SYS_ID_LEN);
|
|
|
|
listnode_add (lsp->tlv_data.is_neighs, is_neigh);
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
else if (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;
|
|
|
|
}
|
2005-05-03 11:27:23 +02:00
|
|
|
es_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct es_neigh));
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
memcpy (&es_neigh->first_es_neigh, adj->sysid, ISIS_SYS_ID_LEN);
|
2005-09-01 19:52:33 +02:00
|
|
|
listnode_add (lsp->tlv_data.es_neighs, es_neigh);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2005-09-03 18:29:40 +02:00
|
|
|
/* Reset endp of stream to overwrite only TLV part of it. */
|
2005-09-04 23:36:36 +02:00
|
|
|
stream_reset (lsp->pdu);
|
2005-09-03 18:29:40 +02:00
|
|
|
stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/*
|
|
|
|
* Add the authentication info if it's present
|
|
|
|
*/
|
2004-09-10 22:48:21 +02:00
|
|
|
(level == 1) ? (passwd = &circuit->area->area_passwd) :
|
|
|
|
(passwd = &circuit->area->domain_passwd);
|
|
|
|
if (passwd->type)
|
|
|
|
{
|
|
|
|
memcpy (&lsp->tlv_data.auth_info, passwd, sizeof (struct isis_passwd));
|
|
|
|
tlv_add_authinfo (passwd->type, passwd->len, passwd->passwd, lsp->pdu);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
if (lsp->tlv_data.is_neighs && listcount (lsp->tlv_data.is_neighs) > 0)
|
|
|
|
tlv_add_is_neighs (lsp->tlv_data.is_neighs, lsp->pdu);
|
|
|
|
|
2005-09-26 19:39:48 +02:00
|
|
|
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);
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
if (lsp->tlv_data.es_neighs && listcount (lsp->tlv_data.es_neighs) > 0)
|
|
|
|
tlv_add_is_neighs (lsp->tlv_data.es_neighs, lsp->pdu);
|
|
|
|
|
2005-02-09 16:51:56 +01:00
|
|
|
lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
|
2008-08-13 20:09:10 +02:00
|
|
|
fletcher_checksum (STREAM_DATA (lsp->pdu) + 12,
|
2004-09-10 22:48:21 +02:00
|
|
|
ntohs (lsp->lsp_header->pdu_len) - 12, 12);
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
list_delete (adj_list);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static int
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_pseudo_regenerate (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];
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
memcpy (lsp_id, isis->sysid, ISIS_SYS_ID_LEN);
|
2004-09-10 22:48:21 +02:00
|
|
|
LSP_PSEUDO_ID (lsp_id) = circuit->circuit_id;
|
|
|
|
LSP_FRAGMENT (lsp_id) = 0;
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp = lsp_search (lsp_id, lspdb);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
|
|
|
if (!lsp)
|
|
|
|
{
|
|
|
|
zlog_err ("lsp_pseudo_regenerate(): no l%d LSP %s found!", level,
|
|
|
|
rawlspid_print (lsp_id));
|
|
|
|
return ISIS_ERROR;
|
|
|
|
}
|
|
|
|
lsp_clear_data (lsp);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
lsp_build_pseudo (lsp, circuit, level);
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp->lsp_header->rem_lifetime =
|
2003-12-23 09:09:43 +01:00
|
|
|
htons (isis_jitter (circuit->area->max_lsp_lifetime[level - 1],
|
2004-09-10 22:48:21 +02:00
|
|
|
MAX_AGE_JITTER));
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
lsp_inc_seqnum (lsp, 0);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
|
|
|
if (isis->debugs & DEBUG_UPDATE_PACKETS)
|
|
|
|
{
|
2004-12-24 01:14:50 +01:00
|
|
|
zlog_debug ("ISIS-Upd (%s): refreshing pseudo LSP L%d %s",
|
|
|
|
circuit->area->area_tag, level,
|
|
|
|
rawlspid_print (lsp->lsp_header->lsp_id));
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
lsp->last_generated = time (NULL);
|
|
|
|
ISIS_FLAGS_SET_ALL (lsp->SRMflags);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return ISIS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
lsp_l1_refresh_pseudo (struct thread *thread)
|
|
|
|
{
|
|
|
|
struct isis_circuit *circuit;
|
|
|
|
int retval;
|
|
|
|
unsigned long ref_time;
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
circuit = THREAD_ARG (thread);
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
if (!circuit->u.bc.is_dr[0])
|
2004-09-10 22:48:21 +02:00
|
|
|
return ISIS_ERROR; /* FIXME: purge and such */
|
|
|
|
|
2004-09-10 23:19:13 +02:00
|
|
|
circuit->u.bc.t_refresh_pseudo_lsp[0] = NULL;
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
retval = lsp_pseudo_regenerate (circuit, 1);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
|
|
|
ref_time = circuit->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
|
2003-12-23 09:09:43 +01:00
|
|
|
MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[0];
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[0],
|
|
|
|
lsp_l1_refresh_pseudo, circuit,
|
|
|
|
isis_jitter (ref_time, MAX_AGE_JITTER));
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
int
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_l1_pseudo_generate (struct isis_circuit *circuit)
|
|
|
|
{
|
|
|
|
struct isis_lsp *lsp;
|
|
|
|
u_char id[ISIS_SYS_ID_LEN + 2];
|
|
|
|
unsigned long ref_time;
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
|
|
|
|
LSP_FRAGMENT (id) = 0;
|
|
|
|
LSP_PSEUDO_ID (id) = circuit->circuit_id;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If for some reason have a pseudo LSP in the db already -> regenerate
|
|
|
|
*/
|
|
|
|
if (lsp_search (id, circuit->area->lspdb[0]))
|
|
|
|
return lsp_pseudo_regenerate (circuit, 1);
|
|
|
|
lsp = lsp_new (id, circuit->area->max_lsp_lifetime[0],
|
2004-09-10 22:48:21 +02:00
|
|
|
1, circuit->area->is_type, 0, 1);
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_build_pseudo (lsp, circuit, 1);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp->own_lsp = 1;
|
|
|
|
lsp_insert (lsp, circuit->area->lspdb[0]);
|
|
|
|
ISIS_FLAGS_SET_ALL (lsp->SRMflags);
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
ref_time = circuit->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
|
2003-12-23 09:09:43 +01:00
|
|
|
MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[0];
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[0],
|
|
|
|
lsp_l1_refresh_pseudo, circuit,
|
|
|
|
isis_jitter (ref_time, MAX_AGE_JITTER));
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
return lsp_regenerate_schedule (circuit->area);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
lsp_l2_refresh_pseudo (struct thread *thread)
|
|
|
|
{
|
|
|
|
struct isis_circuit *circuit;
|
|
|
|
int retval;
|
|
|
|
unsigned long ref_time;
|
2004-09-10 22:48:21 +02:00
|
|
|
circuit = THREAD_ARG (thread);
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
if (!circuit->u.bc.is_dr[1])
|
2004-09-10 22:48:21 +02:00
|
|
|
return ISIS_ERROR; /* FIXME: purge and such */
|
|
|
|
|
2004-09-10 23:19:13 +02:00
|
|
|
circuit->u.bc.t_refresh_pseudo_lsp[1] = NULL;
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
retval = lsp_pseudo_regenerate (circuit, 2);
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
ref_time = circuit->area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ?
|
2003-12-23 09:09:43 +01:00
|
|
|
MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[1];
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[1],
|
|
|
|
lsp_l2_refresh_pseudo, circuit,
|
|
|
|
isis_jitter (ref_time, MAX_AGE_JITTER));
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
int
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_l2_pseudo_generate (struct isis_circuit *circuit)
|
|
|
|
{
|
|
|
|
struct isis_lsp *lsp;
|
|
|
|
u_char id[ISIS_SYS_ID_LEN + 2];
|
|
|
|
unsigned long ref_time;
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
|
|
|
|
LSP_FRAGMENT (id) = 0;
|
|
|
|
LSP_PSEUDO_ID (id) = circuit->circuit_id;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
if (lsp_search (id, circuit->area->lspdb[1]))
|
|
|
|
return lsp_pseudo_regenerate (circuit, 2);
|
|
|
|
|
|
|
|
lsp = lsp_new (id, circuit->area->max_lsp_lifetime[1],
|
2004-09-10 22:48:21 +02:00
|
|
|
1, circuit->area->is_type, 0, 2);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
lsp_build_pseudo (lsp, circuit, 2);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
|
|
|
ref_time = circuit->area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ?
|
2003-12-23 09:09:43 +01:00
|
|
|
MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[1];
|
|
|
|
|
|
|
|
|
|
|
|
lsp->own_lsp = 1;
|
|
|
|
lsp_insert (lsp, circuit->area->lspdb[1]);
|
|
|
|
ISIS_FLAGS_SET_ALL (lsp->SRMflags);
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[1],
|
|
|
|
lsp_l2_refresh_pseudo, circuit,
|
|
|
|
isis_jitter (ref_time, MAX_AGE_JITTER));
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
return lsp_regenerate_schedule (circuit->area);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Walk through LSPs for an area
|
|
|
|
* - set remaining lifetime
|
|
|
|
* - set LSPs with SRMflag set for sending
|
|
|
|
*/
|
2004-09-10 22:48:21 +02:00
|
|
|
int
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp_tick (struct thread *thread)
|
|
|
|
{
|
|
|
|
struct isis_area *area;
|
|
|
|
struct isis_circuit *circuit;
|
|
|
|
struct isis_lsp *lsp;
|
|
|
|
struct list *lsp_list;
|
2005-09-28 20:45:54 +02:00
|
|
|
struct listnode *lspnode, *cnode;
|
2003-12-23 09:09:43 +01:00
|
|
|
dnode_t *dnode, *dnode_next;
|
|
|
|
int level;
|
|
|
|
|
|
|
|
lsp_list = list_new ();
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
area = THREAD_ARG (thread);
|
|
|
|
assert (area);
|
2004-09-10 23:19:13 +02:00
|
|
|
area->t_tick = NULL;
|
2004-09-10 22:48:21 +02:00
|
|
|
THREAD_TIMER_ON (master, area->t_tick, lsp_tick, area, 1);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Build a list of LSPs with (any) SRMflag set
|
|
|
|
* and removed the ones that have aged out
|
|
|
|
*/
|
2004-09-10 22:48:21 +02:00
|
|
|
for (level = 0; level < ISIS_LEVELS; level++)
|
|
|
|
{
|
|
|
|
if (area->lspdb[level] && dict_count (area->lspdb[level]) > 0)
|
|
|
|
{
|
|
|
|
dnode = dict_first (area->lspdb[level]);
|
|
|
|
while (dnode != NULL)
|
|
|
|
{
|
|
|
|
dnode_next = dict_next (area->lspdb[level], dnode);
|
|
|
|
lsp = dnode_get (dnode);
|
|
|
|
lsp_set_time (lsp);
|
|
|
|
if (lsp->age_out == 0)
|
|
|
|
{
|
|
|
|
|
2004-12-24 01:14:50 +01:00
|
|
|
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));
|
2005-09-19 06:23:34 +02:00
|
|
|
#ifdef TOPOLOGY_GENERATE
|
|
|
|
if (lsp->from_topology)
|
|
|
|
THREAD_TIMER_OFF (lsp->t_lsp_top_ref);
|
|
|
|
#endif /* TOPOLOGY_GENERATE */
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_destroy (lsp);
|
|
|
|
dict_delete (area->lspdb[level], dnode);
|
|
|
|
}
|
|
|
|
else if (flags_any_set (lsp->SRMflags))
|
|
|
|
listnode_add (lsp_list, lsp);
|
|
|
|
dnode = dnode_next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send LSPs on circuits indicated by the SRMflags
|
|
|
|
*/
|
|
|
|
if (listcount (lsp_list) > 0)
|
|
|
|
{
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (lsp_list, lspnode, lsp))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
if (ISIS_CHECK_FLAG (lsp->SRMflags, circuit))
|
|
|
|
{
|
|
|
|
/* FIXME: if same or elder lsp is already in lsp
|
|
|
|
* queue */
|
|
|
|
listnode_add (circuit->lsp_queue, lsp);
|
|
|
|
thread_add_event (master, send_lsp, circuit, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
list_delete_all_node (lsp_list);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
list_delete (lsp_list);
|
|
|
|
|
|
|
|
return ISIS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_purge_dr (u_char * id, struct isis_circuit *circuit, int level)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_lsp *lsp;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp = lsp_search (id, circuit->area->lspdb[level - 1]);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
|
|
|
if (lsp && lsp->purged == 0)
|
|
|
|
{
|
|
|
|
lsp->lsp_header->rem_lifetime = htons (0);
|
|
|
|
lsp->lsp_header->pdu_len =
|
|
|
|
htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
|
|
|
|
lsp->purged = 0;
|
2008-08-13 20:09:10 +02:00
|
|
|
fletcher_checksum (STREAM_DATA (lsp->pdu) + 12,
|
2004-09-10 22:48:21 +02:00
|
|
|
ntohs (lsp->lsp_header->pdu_len) - 12, 12);
|
|
|
|
ISIS_FLAGS_SET_ALL (lsp->SRMflags);
|
|
|
|
}
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Purge own LSP that is received and we don't have.
|
|
|
|
* -> Do as in 7.3.16.4
|
|
|
|
*/
|
|
|
|
void
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_purge_non_exist (struct isis_link_state_hdr *lsp_hdr,
|
|
|
|
struct isis_area *area)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_lsp *lsp;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We need to create the LSP to be purged
|
|
|
|
*/
|
2004-12-24 01:14:50 +01:00
|
|
|
zlog_debug ("LSP PURGE NON EXIST");
|
2005-09-01 19:52:33 +02:00
|
|
|
lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
|
2004-09-10 22:48:21 +02:00
|
|
|
/*FIXME: BUG BUG BUG! the lsp doesn't exist here! */
|
|
|
|
/*did smt here, maybe good probably not */
|
2003-12-23 09:09:43 +01:00
|
|
|
lsp->level = ((lsp_hdr->lsp_bits & LSPBIT_IST) == IS_LEVEL_1) ? 1 : 2;
|
|
|
|
lsp->pdu = stream_new (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp->isis_header = (struct isis_fixed_hdr *) STREAM_DATA (lsp->pdu);
|
2003-12-23 09:09:43 +01:00
|
|
|
fill_fixed_hdr (lsp->isis_header, (lsp->level == 1) ? L1_LINK_STATE
|
2004-09-10 22:48:21 +02:00
|
|
|
: L2_LINK_STATE);
|
|
|
|
lsp->lsp_header = (struct isis_link_state_hdr *) (STREAM_DATA (lsp->pdu) +
|
|
|
|
ISIS_FIXED_HDR_LEN);
|
2003-12-23 09:09:43 +01:00
|
|
|
memcpy (lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/*
|
|
|
|
* Retain only LSP header
|
|
|
|
*/
|
|
|
|
lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
|
|
|
|
/*
|
|
|
|
* Set the remaining lifetime to 0
|
|
|
|
*/
|
|
|
|
lsp->lsp_header->rem_lifetime = 0;
|
|
|
|
/*
|
|
|
|
* Put the lsp into LSPdb
|
|
|
|
*/
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp_insert (lsp, area->lspdb[lsp->level - 1]);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Send in to whole area
|
|
|
|
*/
|
|
|
|
ISIS_FLAGS_SET_ALL (lsp->SRMflags);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef TOPOLOGY_GENERATE
|
2005-01-18 14:53:33 +01:00
|
|
|
static int
|
2003-12-23 09:09:43 +01:00
|
|
|
top_lsp_refresh (struct thread *thread)
|
|
|
|
{
|
2004-09-10 22:48:21 +02:00
|
|
|
struct isis_lsp *lsp;
|
2005-09-19 06:23:34 +02:00
|
|
|
unsigned long ref_time;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
lsp = THREAD_ARG (thread);
|
|
|
|
assert (lsp);
|
|
|
|
|
|
|
|
lsp->t_lsp_top_ref = NULL;
|
|
|
|
|
2005-09-19 06:23:34 +02:00
|
|
|
lsp_seqnum_update (lsp);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
ISIS_FLAGS_SET_ALL (lsp->SRMflags);
|
2004-09-10 22:48:21 +02:00
|
|
|
if (isis->debugs & DEBUG_UPDATE_PACKETS)
|
|
|
|
{
|
2004-12-24 01:14:50 +01:00
|
|
|
zlog_debug ("ISIS-Upd (): refreshing Topology L1 %s",
|
|
|
|
rawlspid_print (lsp->lsp_header->lsp_id));
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2005-09-28 20:30:51 +02:00
|
|
|
/* Refresh dynamic hostname in the cache. */
|
|
|
|
isis_dynhn_insert (lsp->lsp_header->lsp_id, lsp->tlv_data.hostname,
|
|
|
|
IS_LEVEL_1);
|
|
|
|
|
2005-09-19 06:23:34 +02:00
|
|
|
lsp->lsp_header->rem_lifetime =
|
|
|
|
htons (isis_jitter (lsp->area->max_lsp_lifetime[0], MAX_AGE_JITTER));
|
|
|
|
|
|
|
|
ref_time = lsp->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
|
|
|
|
MAX_LSP_GEN_INTERVAL : lsp->area->lsp_refresh[0];
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
THREAD_TIMER_ON (master, lsp->t_lsp_top_ref, top_lsp_refresh, lsp,
|
2005-09-19 06:23:34 +02:00
|
|
|
isis_jitter (ref_time, MAX_LSP_GEN_JITTER));
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
return ISIS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
generate_topology_lsps (struct isis_area *area)
|
|
|
|
{
|
|
|
|
struct listnode *node;
|
|
|
|
int i, max = 0;
|
|
|
|
struct arc *arc;
|
|
|
|
u_char lspid[ISIS_SYS_ID_LEN + 2];
|
|
|
|
struct isis_lsp *lsp;
|
2005-09-19 06:23:34 +02:00
|
|
|
unsigned long ref_time;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
/* first we find the maximal node */
|
2005-04-10 17:58:10 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (area->topology, node, arc))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
if (arc->from_node > max)
|
|
|
|
max = arc->from_node;
|
|
|
|
if (arc->to_node > max)
|
|
|
|
max = arc->to_node;
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
for (i = 1; i < (max + 1); i++)
|
|
|
|
{
|
|
|
|
memcpy (lspid, area->topology_baseis, ISIS_SYS_ID_LEN);
|
|
|
|
LSP_PSEUDO_ID (lspid) = 0x00;
|
|
|
|
LSP_FRAGMENT (lspid) = 0x00;
|
|
|
|
lspid[ISIS_SYS_ID_LEN - 1] = (i & 0xFF);
|
|
|
|
lspid[ISIS_SYS_ID_LEN - 2] = ((i >> 8) & 0xFF);
|
|
|
|
|
|
|
|
lsp = lsp_new (lspid, isis_jitter (area->max_lsp_lifetime[0],
|
2005-09-19 06:23:34 +02:00
|
|
|
MAX_AGE_JITTER), 1, IS_LEVEL_1, 0, 1);
|
|
|
|
if (!lsp)
|
|
|
|
return;
|
2004-09-10 22:48:21 +02:00
|
|
|
lsp->from_topology = 1;
|
2005-09-19 06:23:34 +02:00
|
|
|
lsp->area = area;
|
|
|
|
|
|
|
|
/* Creating LSP data based on topology info. */
|
2004-09-10 22:48:21 +02:00
|
|
|
build_topology_lsp_data (lsp, area, i);
|
2005-09-19 06:23:34 +02:00
|
|
|
/* Checksum is also calculated here. */
|
|
|
|
lsp_seqnum_update (lsp);
|
2005-09-28 20:26:25 +02:00
|
|
|
/* Take care of inserting dynamic hostname into cache. */
|
|
|
|
isis_dynhn_insert (lspid, lsp->tlv_data.hostname, IS_LEVEL_1);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2005-09-19 06:23:34 +02:00
|
|
|
ref_time = area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
|
|
|
|
MAX_LSP_GEN_INTERVAL : area->lsp_refresh[0];
|
|
|
|
|
|
|
|
THREAD_TIMER_ON (master, lsp->t_lsp_top_ref, top_lsp_refresh, lsp,
|
|
|
|
isis_jitter (ref_time, MAX_LSP_GEN_JITTER));
|
2004-09-10 22:48:21 +02:00
|
|
|
ISIS_FLAGS_SET_ALL (lsp->SRMflags);
|
|
|
|
lsp_insert (lsp, area->lspdb[0]);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
remove_topology_lsps (struct isis_area *area)
|
|
|
|
{
|
|
|
|
struct isis_lsp *lsp;
|
|
|
|
dnode_t *dnode, *dnode_next;
|
|
|
|
|
|
|
|
dnode = dict_first (area->lspdb[0]);
|
2004-09-10 22:48:21 +02:00
|
|
|
while (dnode != NULL)
|
|
|
|
{
|
|
|
|
dnode_next = dict_next (area->lspdb[0], dnode);
|
|
|
|
lsp = dnode_get (dnode);
|
|
|
|
if (lsp->from_topology)
|
|
|
|
{
|
|
|
|
THREAD_TIMER_OFF (lsp->t_lsp_top_ref);
|
|
|
|
lsp_destroy (lsp);
|
|
|
|
dict_delete (area->lspdb[0], dnode);
|
|
|
|
}
|
|
|
|
dnode = dnode_next;
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2004-09-10 22:48:21 +02:00
|
|
|
build_topology_lsp_data (struct isis_lsp *lsp, struct isis_area *area,
|
2003-12-23 09:09:43 +01:00
|
|
|
int lsp_top_num)
|
|
|
|
{
|
2005-09-28 20:45:54 +02:00
|
|
|
struct listnode *node;
|
2003-12-23 09:09:43 +01:00
|
|
|
struct arc *arc;
|
|
|
|
struct is_neigh *is_neigh;
|
2005-09-28 20:26:25 +02:00
|
|
|
struct te_is_neigh *te_is_neigh;
|
2003-12-23 09:09:43 +01:00
|
|
|
char buff[200];
|
2005-09-19 06:23:34 +02:00
|
|
|
struct tlvs tlv_data;
|
|
|
|
struct isis_lsp *lsp0 = lsp;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2005-09-19 06:23:34 +02:00
|
|
|
/* Add area addresses. FIXME: Is it needed at all? */
|
|
|
|
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);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2005-09-19 06:23:34 +02:00
|
|
|
if (lsp->tlv_data.nlpids == NULL)
|
|
|
|
lsp->tlv_data.nlpids = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct nlpids));
|
|
|
|
lsp->tlv_data.nlpids->count = 1;
|
|
|
|
lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP;
|
|
|
|
|
|
|
|
if (area->dynhostname)
|
|
|
|
{
|
|
|
|
lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV,
|
|
|
|
sizeof (struct hostname));
|
|
|
|
memset (buff, 0x00, 200);
|
|
|
|
sprintf (buff, "%s%d", area->topology_basedynh ? area->topology_basedynh :
|
|
|
|
"feedme", lsp_top_num);
|
|
|
|
memcpy (lsp->tlv_data.hostname->name, buff, strlen (buff));
|
|
|
|
lsp->tlv_data.hostname->namelen = strlen (buff);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2005-09-19 06:23:34 +02:00
|
|
|
if (lsp->tlv_data.nlpids)
|
|
|
|
tlv_add_nlpid (lsp->tlv_data.nlpids, lsp->pdu);
|
|
|
|
if (lsp->tlv_data.hostname)
|
|
|
|
tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu);
|
|
|
|
if (lsp->tlv_data.area_addrs && listcount (lsp->tlv_data.area_addrs) > 0)
|
|
|
|
tlv_add_area_addrs (lsp->tlv_data.area_addrs, lsp->pdu);
|
|
|
|
|
|
|
|
memset (&tlv_data, 0, sizeof (struct tlvs));
|
|
|
|
if (tlv_data.is_neighs == NULL)
|
2005-09-28 20:26:25 +02:00
|
|
|
{
|
|
|
|
tlv_data.is_neighs = list_new ();
|
|
|
|
tlv_data.is_neighs->del = free_tlv;
|
|
|
|
}
|
2005-09-19 06:23:34 +02:00
|
|
|
|
|
|
|
/* Add reachability for this IS for simulated 1. */
|
2004-09-10 22:48:21 +02:00
|
|
|
if (lsp_top_num == 1)
|
|
|
|
{
|
2005-09-28 20:45:54 +02:00
|
|
|
is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
|
2005-09-19 06:23:34 +02:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
|
2003-12-23 09:09:43 +01:00
|
|
|
LSP_PSEUDO_ID (is_neigh->neigh_id) = 0x00;
|
2005-09-19 06:23:34 +02:00
|
|
|
/* Metric MUST NOT be 0, unless it's not alias TLV. */
|
|
|
|
is_neigh->metrics.metric_default = 0x01;
|
2003-12-23 09:09:43 +01:00
|
|
|
is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
|
|
|
|
is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
|
|
|
|
is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
|
2005-09-19 06:23:34 +02:00
|
|
|
listnode_add (tlv_data.is_neighs, is_neigh);
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2005-09-19 06:23:34 +02:00
|
|
|
/* Add IS reachabilities. */
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (area->topology, node, arc))
|
2005-09-19 06:23:34 +02:00
|
|
|
{
|
|
|
|
int to_lsp = 0;
|
|
|
|
|
|
|
|
if ((lsp_top_num != arc->from_node) && (lsp_top_num != arc->to_node))
|
|
|
|
continue;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2005-09-19 06:23:34 +02:00
|
|
|
if (lsp_top_num == arc->from_node)
|
|
|
|
to_lsp = arc->to_node;
|
|
|
|
else
|
|
|
|
to_lsp = arc->from_node;
|
|
|
|
|
2005-09-28 20:26:25 +02:00
|
|
|
if (area->oldmetric)
|
|
|
|
{
|
|
|
|
is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
|
|
|
|
|
|
|
|
memcpy (&is_neigh->neigh_id, area->topology_baseis, ISIS_SYS_ID_LEN);
|
|
|
|
is_neigh->neigh_id[ISIS_SYS_ID_LEN - 1] = (to_lsp & 0xFF);
|
|
|
|
is_neigh->neigh_id[ISIS_SYS_ID_LEN - 2] = ((to_lsp >> 8) & 0xFF);
|
|
|
|
is_neigh->metrics.metric_default = arc->distance;
|
|
|
|
is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
|
|
|
|
is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
|
|
|
|
is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
|
|
|
|
listnode_add (tlv_data.is_neighs, is_neigh);
|
|
|
|
}
|
2005-09-19 06:23:34 +02:00
|
|
|
|
2005-09-28 20:26:25 +02:00
|
|
|
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, area->topology_baseis,
|
|
|
|
ISIS_SYS_ID_LEN);
|
|
|
|
te_is_neigh->neigh_id[ISIS_SYS_ID_LEN - 1] = (to_lsp & 0xFF);
|
|
|
|
te_is_neigh->neigh_id[ISIS_SYS_ID_LEN - 2] = ((to_lsp >> 8) & 0xFF);
|
|
|
|
metric = ((htonl(arc->distance) >> 8) & 0xffffff);
|
|
|
|
memcpy (te_is_neigh->te_metric, &metric, 3);
|
|
|
|
listnode_add (tlv_data.te_is_neighs, te_is_neigh);
|
|
|
|
}
|
2005-09-19 06:23:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
while (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2005-09-19 06:23:34 +02:00
|
|
|
if (lsp->tlv_data.is_neighs == NULL)
|
|
|
|
lsp->tlv_data.is_neighs = list_new ();
|
2005-09-28 20:26:25 +02:00
|
|
|
lsp_tlv_fit (lsp, &tlv_data.is_neighs, &lsp->tlv_data.is_neighs,
|
2005-09-19 06:23:34 +02:00
|
|
|
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, IS_LEVEL_1);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2005-09-19 06:23:34 +02:00
|
|
|
|
2005-09-28 20:26:25 +02:00
|
|
|
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, IS_LEVEL_1);
|
|
|
|
}
|
|
|
|
|
2005-09-19 06:23:34 +02:00
|
|
|
free_tlvs (&tlv_data);
|
|
|
|
return;
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
#endif /* TOPOLOGY_GENERATE */
|