blob: d02f383365c2f09da6295879d083b1085c2a295e [file] [log] [blame]
jardineb5d44e2003-12-23 08:09:43 +00001/*
2 * IS-IS Rout(e)ing protocol - isis_lsp.c
3 * LSP processing
4 *
5 * Copyright (C) 2001,2002 Sampo Saaristo
6 * Tampere University of Technology
7 * Institute of Communications Engineering
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public Licenseas published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
paul15935e92005-05-03 09:27:23 +000023
jardineb5d44e2003-12-23 08:09:43 +000024#include <stdlib.h>
25#include <stdio.h>
26#include <zebra.h>
jardineb5d44e2003-12-23 08:09:43 +000027
28#include "linklist.h"
29#include "thread.h"
30#include "vty.h"
31#include "stream.h"
32#include "memory.h"
33#include "log.h"
34#include "prefix.h"
35#include "command.h"
36#include "hash.h"
37#include "if.h"
38
39#include "isisd/dict.h"
40#include "isisd/isis_constants.h"
41#include "isisd/isis_common.h"
42#include "isisd/isis_circuit.h"
43#include "isisd/isisd.h"
44#include "isisd/isis_tlv.h"
45#include "isisd/isis_lsp.h"
46#include "isisd/isis_pdu.h"
47#include "isisd/isis_dynhn.h"
48#include "isisd/isis_misc.h"
49#include "isisd/isis_flags.h"
50#include "isisd/iso_checksum.h"
51#include "isisd/isis_csm.h"
52#include "isisd/isis_adjacency.h"
53#include "isisd/isis_spf.h"
54
55#ifdef TOPOLOGY_GENERATE
56#include "spgrid.h"
57#endif
58
hassof390d2c2004-09-10 20:48:21 +000059#define LSP_MEMORY_PREASSIGN
jardineb5d44e2003-12-23 08:09:43 +000060
61extern struct isis *isis;
62extern struct thread_master *master;
hasso18a6dce2004-10-03 18:18:34 +000063extern struct in_addr router_id_zebra;
jardineb5d44e2003-12-23 08:09:43 +000064
hasso73d1aea2004-09-24 10:45:28 +000065/* staticly assigned vars for printing purposes */
66char lsp_bits_string[200]; /* FIXME: enough ? */
67
hassof390d2c2004-09-10 20:48:21 +000068int
69lsp_id_cmp (u_char * id1, u_char * id2)
70{
jardineb5d44e2003-12-23 08:09:43 +000071 return memcmp (id1, id2, ISIS_SYS_ID_LEN + 2);
72}
73
74dict_t *
hassof390d2c2004-09-10 20:48:21 +000075lsp_db_init (void)
jardineb5d44e2003-12-23 08:09:43 +000076{
77 dict_t *dict;
hassof390d2c2004-09-10 20:48:21 +000078
79 dict = dict_create (DICTCOUNT_T_MAX, (dict_comp_t) lsp_id_cmp);
80
jardineb5d44e2003-12-23 08:09:43 +000081 return dict;
82}
83
84struct isis_lsp *
hassof390d2c2004-09-10 20:48:21 +000085lsp_search (u_char * id, dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +000086{
87 dnode_t *node;
88
hassof390d2c2004-09-10 20:48:21 +000089#ifdef EXTREME_DEBUG
jardineb5d44e2003-12-23 08:09:43 +000090 dnode_t *dn;
91
hasso529d65b2004-12-24 00:14:50 +000092 zlog_debug ("searching db");
hassof390d2c2004-09-10 20:48:21 +000093 for (dn = dict_first (lspdb); dn; dn = dict_next (lspdb, dn))
94 {
hasso529d65b2004-12-24 00:14:50 +000095 zlog_debug ("%s\t%pX", rawlspid_print ((char *) dnode_getkey (dn)),
96 dnode_get (dn));
hassof390d2c2004-09-10 20:48:21 +000097 }
jardineb5d44e2003-12-23 08:09:43 +000098#endif /* EXTREME DEBUG */
99
100 node = dict_lookup (lspdb, id);
hassof390d2c2004-09-10 20:48:21 +0000101
jardineb5d44e2003-12-23 08:09:43 +0000102 if (node)
hassof390d2c2004-09-10 20:48:21 +0000103 return (struct isis_lsp *) dnode_get (node);
jardineb5d44e2003-12-23 08:09:43 +0000104
105 return NULL;
106}
107
hasso92365882005-01-18 13:53:33 +0000108static void
jardineb5d44e2003-12-23 08:09:43 +0000109lsp_clear_data (struct isis_lsp *lsp)
110{
111 if (!lsp)
112 return;
hassof390d2c2004-09-10 20:48:21 +0000113
114 if (lsp->own_lsp)
115 {
116 if (lsp->tlv_data.nlpids)
117 XFREE (MTYPE_ISIS_TLV, lsp->tlv_data.nlpids);
118 if (lsp->tlv_data.hostname)
119 XFREE (MTYPE_ISIS_TLV, lsp->tlv_data.hostname);
120 }
jardineb5d44e2003-12-23 08:09:43 +0000121 if (lsp->tlv_data.is_neighs)
122 list_delete (lsp->tlv_data.is_neighs);
123 if (lsp->tlv_data.area_addrs)
124 list_delete (lsp->tlv_data.area_addrs);
125 if (lsp->tlv_data.es_neighs)
126 list_delete (lsp->tlv_data.es_neighs);
127 if (lsp->tlv_data.ipv4_addrs)
128 list_delete (lsp->tlv_data.ipv4_addrs);
129 if (lsp->tlv_data.ipv4_int_reachs)
130 list_delete (lsp->tlv_data.ipv4_int_reachs);
131 if (lsp->tlv_data.ipv4_ext_reachs)
132 list_delete (lsp->tlv_data.ipv4_ext_reachs);
133#ifdef HAVE_IPV6
134 if (lsp->tlv_data.ipv6_addrs)
135 list_delete (lsp->tlv_data.ipv6_addrs);
136 if (lsp->tlv_data.ipv6_reachs)
137 list_delete (lsp->tlv_data.ipv6_reachs);
138#endif /* HAVE_IPV6 */
139
140 memset (&lsp->tlv_data, 0, sizeof (struct tlvs));
141
142 return;
143}
144
hasso92365882005-01-18 13:53:33 +0000145static void
jardineb5d44e2003-12-23 08:09:43 +0000146lsp_destroy (struct isis_lsp *lsp)
147{
148 if (!lsp)
149 return;
hassof390d2c2004-09-10 20:48:21 +0000150
jardineb5d44e2003-12-23 08:09:43 +0000151 lsp_clear_data (lsp);
hassof390d2c2004-09-10 20:48:21 +0000152
153 if (LSP_FRAGMENT (lsp->lsp_header->lsp_id) == 0 && lsp->lspu.frags)
154 {
jardineb5d44e2003-12-23 08:09:43 +0000155 list_delete (lsp->lspu.frags);
hassof390d2c2004-09-10 20:48:21 +0000156 }
157
jardineb5d44e2003-12-23 08:09:43 +0000158 if (lsp->pdu)
159 stream_free (lsp->pdu);
160 XFREE (MTYPE_ISIS_LSP, lsp);
161}
162
hassof390d2c2004-09-10 20:48:21 +0000163void
164lsp_db_destroy (dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +0000165{
166 dnode_t *dnode, *next;
167 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +0000168
jardineb5d44e2003-12-23 08:09:43 +0000169 dnode = dict_first (lspdb);
hassof390d2c2004-09-10 20:48:21 +0000170 while (dnode)
171 {
172 next = dict_next (lspdb, dnode);
173 lsp = dnode_get (dnode);
174 lsp_destroy (lsp);
175 dict_delete_free (lspdb, dnode);
176 dnode = next;
177 }
178
jardineb5d44e2003-12-23 08:09:43 +0000179 dict_free (lspdb);
hassof390d2c2004-09-10 20:48:21 +0000180
jardineb5d44e2003-12-23 08:09:43 +0000181 return;
182}
183
184/*
185 * Remove all the frags belonging to the given lsp
186 */
hasso92365882005-01-18 13:53:33 +0000187static void
hassof390d2c2004-09-10 20:48:21 +0000188lsp_remove_frags (struct list *frags, dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +0000189{
190 dnode_t *dnode;
paul1eb8ef22005-04-07 07:30:20 +0000191 struct listnode *lnode, *lnnode;
jardineb5d44e2003-12-23 08:09:43 +0000192 struct isis_lsp *lsp;
193
paul1eb8ef22005-04-07 07:30:20 +0000194 for (ALL_LIST_ELEMENTS (frags, lnode, lnnode, lsp))
hassof390d2c2004-09-10 20:48:21 +0000195 {
hassof390d2c2004-09-10 20:48:21 +0000196 dnode = dict_lookup (lspdb, lsp->lsp_header->lsp_id);
197 lsp_destroy (lsp);
198 dnode_destroy (dict_delete (lspdb, dnode));
199 }
200
jardineb5d44e2003-12-23 08:09:43 +0000201 list_delete_all_node (frags);
hassof390d2c2004-09-10 20:48:21 +0000202
jardineb5d44e2003-12-23 08:09:43 +0000203 return;
204}
205
206void
hassof390d2c2004-09-10 20:48:21 +0000207lsp_search_and_destroy (u_char * id, dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +0000208{
209 dnode_t *node;
210 struct isis_lsp *lsp;
211
212 node = dict_lookup (lspdb, id);
hassof390d2c2004-09-10 20:48:21 +0000213 if (node)
214 {
215 node = dict_delete (lspdb, node);
216 lsp = dnode_get (node);
217 /*
218 * If this is a zero lsp, remove all the frags now
219 */
220 if (LSP_FRAGMENT (lsp->lsp_header->lsp_id) == 0)
221 {
222 if (lsp->lspu.frags)
223 lsp_remove_frags (lsp->lspu.frags, lspdb);
224 }
225 else
226 {
227 /*
228 * else just remove this frag, from the zero lsps' frag list
229 */
230 if (lsp->lspu.zero_lsp && lsp->lspu.zero_lsp->lspu.frags)
231 listnode_delete (lsp->lspu.zero_lsp->lspu.frags, lsp);
232 }
233 lsp_destroy (lsp);
234 dnode_destroy (node);
jardineb5d44e2003-12-23 08:09:43 +0000235 }
jardineb5d44e2003-12-23 08:09:43 +0000236}
237
238/*
239 * Compares a LSP to given values
240 * Params are given in net order
241 */
hassof390d2c2004-09-10 20:48:21 +0000242int
243lsp_compare (char *areatag, struct isis_lsp *lsp, u_int32_t seq_num,
jardineb5d44e2003-12-23 08:09:43 +0000244 u_int16_t checksum, u_int16_t rem_lifetime)
245{
hassof390d2c2004-09-10 20:48:21 +0000246 /* no point in double ntohl on seqnum */
247 if (lsp->lsp_header->seq_num == seq_num &&
jardineb5d44e2003-12-23 08:09:43 +0000248 lsp->lsp_header->checksum == checksum &&
249 /*comparing with 0, no need to do ntohl */
250 ((lsp->lsp_header->rem_lifetime == 0 && rem_lifetime == 0) ||
hassof390d2c2004-09-10 20:48:21 +0000251 (lsp->lsp_header->rem_lifetime != 0 && rem_lifetime != 0)))
252 {
253 if (isis->debugs & DEBUG_SNP_PACKETS)
254 {
hasso529d65b2004-12-24 00:14:50 +0000255 zlog_debug ("ISIS-Snp (%s): LSP %s seq 0x%08x, cksum 0x%04x,"
256 " lifetime %us",
257 areatag,
258 rawlspid_print (lsp->lsp_header->lsp_id),
259 ntohl (lsp->lsp_header->seq_num),
260 ntohs (lsp->lsp_header->checksum),
261 ntohs (lsp->lsp_header->rem_lifetime));
262 zlog_debug ("ISIS-Snp (%s): is equal to ours seq 0x%08x,"
263 " cksum 0x%04x, lifetime %us",
264 areatag,
265 ntohl (seq_num), ntohs (checksum), ntohs (rem_lifetime));
hassof390d2c2004-09-10 20:48:21 +0000266 }
267 return LSP_EQUAL;
jardineb5d44e2003-12-23 08:09:43 +0000268 }
jardineb5d44e2003-12-23 08:09:43 +0000269
hassof390d2c2004-09-10 20:48:21 +0000270 if (ntohl (seq_num) >= ntohl (lsp->lsp_header->seq_num))
271 {
272 if (isis->debugs & DEBUG_SNP_PACKETS)
273 {
hasso529d65b2004-12-24 00:14:50 +0000274 zlog_debug ("ISIS-Snp (%s): LSP %s seq 0x%08x, cksum 0x%04x,"
275 " lifetime %us",
276 areatag,
277 rawlspid_print (lsp->lsp_header->lsp_id),
278 ntohl (seq_num), ntohs (checksum), ntohs (rem_lifetime));
279 zlog_debug ("ISIS-Snp (%s): is newer than ours seq 0x%08x, "
280 "cksum 0x%04x, lifetime %us",
281 areatag,
282 ntohl (lsp->lsp_header->seq_num),
283 ntohs (lsp->lsp_header->checksum),
284 ntohs (lsp->lsp_header->rem_lifetime));
hassof390d2c2004-09-10 20:48:21 +0000285 }
286 return LSP_NEWER;
jardineb5d44e2003-12-23 08:09:43 +0000287 }
hassof390d2c2004-09-10 20:48:21 +0000288 if (isis->debugs & DEBUG_SNP_PACKETS)
289 {
hasso529d65b2004-12-24 00:14:50 +0000290 zlog_debug
hassof390d2c2004-09-10 20:48:21 +0000291 ("ISIS-Snp (%s): LSP %s seq 0x%08x, cksum 0x%04x, lifetime %us",
292 areatag, rawlspid_print (lsp->lsp_header->lsp_id), ntohl (seq_num),
293 ntohs (checksum), ntohs (rem_lifetime));
hasso529d65b2004-12-24 00:14:50 +0000294 zlog_debug ("ISIS-Snp (%s): is older than ours seq 0x%08x,"
295 " cksum 0x%04x, lifetime %us", areatag,
296 ntohl (lsp->lsp_header->seq_num),
297 ntohs (lsp->lsp_header->checksum),
298 ntohs (lsp->lsp_header->rem_lifetime));
hassof390d2c2004-09-10 20:48:21 +0000299 }
jardineb5d44e2003-12-23 08:09:43 +0000300
301 return LSP_OLDER;
302}
303
hassof390d2c2004-09-10 20:48:21 +0000304void
jardineb5d44e2003-12-23 08:09:43 +0000305lsp_inc_seqnum (struct isis_lsp *lsp, u_int32_t seq_num)
306{
307 u_int32_t newseq;
hassof390d2c2004-09-10 20:48:21 +0000308
jardineb5d44e2003-12-23 08:09:43 +0000309 if (seq_num == 0 || ntohl (lsp->lsp_header->seq_num) > seq_num)
310 newseq = ntohl (lsp->lsp_header->seq_num) + 1;
311 else
hassof390d2c2004-09-10 20:48:21 +0000312 newseq = seq_num++;
313
jardineb5d44e2003-12-23 08:09:43 +0000314 lsp->lsp_header->seq_num = htonl (newseq);
hassof390d2c2004-09-10 20:48:21 +0000315 iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
316 ntohs (lsp->lsp_header->pdu_len) - 12, 12);
jardineb5d44e2003-12-23 08:09:43 +0000317
318 return;
319}
320
321/*
322 * Genetates checksum for LSP and its frags
323 */
hasso92365882005-01-18 13:53:33 +0000324static void
jardineb5d44e2003-12-23 08:09:43 +0000325lsp_seqnum_update (struct isis_lsp *lsp0)
326{
327 struct isis_lsp *lsp;
paul1eb8ef22005-04-07 07:30:20 +0000328 struct listnode *node, *nnode;
hassof390d2c2004-09-10 20:48:21 +0000329
jardineb5d44e2003-12-23 08:09:43 +0000330 lsp_inc_seqnum (lsp0, 0);
331
332 if (!lsp0->lspu.frags)
333 return;
334
paul1eb8ef22005-04-07 07:30:20 +0000335 for (ALL_LIST_ELEMENTS (lsp0->lspu.frags, node, nnode, lsp))
336 lsp_inc_seqnum (lsp, 0);
hassof390d2c2004-09-10 20:48:21 +0000337
jardineb5d44e2003-12-23 08:09:43 +0000338 return;
339}
340
hassof390d2c2004-09-10 20:48:21 +0000341int
jardineb5d44e2003-12-23 08:09:43 +0000342isis_lsp_authinfo_check (struct stream *stream, struct isis_area *area,
hassof390d2c2004-09-10 20:48:21 +0000343 int pdulen, struct isis_passwd *passwd)
jardineb5d44e2003-12-23 08:09:43 +0000344{
345 uint32_t expected = 0, found;
346 struct tlvs tlvs;
347 int retval = 0;
348
349 expected |= TLVFLAG_AUTH_INFO;
350 retval = parse_tlvs (area->area_tag, stream->data +
hassof390d2c2004-09-10 20:48:21 +0000351 ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN,
352 pdulen - ISIS_FIXED_HDR_LEN
353 - ISIS_LSP_HDR_LEN, &expected, &found, &tlvs);
jardineb5d44e2003-12-23 08:09:43 +0000354 if (retval || !(found & TLVFLAG_AUTH_INFO))
hassof390d2c2004-09-10 20:48:21 +0000355 return 1; /* Auth fail (parsing failed or no auth-tlv) */
jardineb5d44e2003-12-23 08:09:43 +0000356
357 return authentication_check (passwd, &tlvs.auth_info);
358}
359
hasso92365882005-01-18 13:53:33 +0000360static void
hassof390d2c2004-09-10 20:48:21 +0000361lsp_update_data (struct isis_lsp *lsp, struct stream *stream,
362 struct isis_area *area)
jardineb5d44e2003-12-23 08:09:43 +0000363{
hassof390d2c2004-09-10 20:48:21 +0000364 uint32_t expected = 0, found;
jardineb5d44e2003-12-23 08:09:43 +0000365 int retval;
hassof390d2c2004-09-10 20:48:21 +0000366
jardineb5d44e2003-12-23 08:09:43 +0000367 /* copying only the relevant part of our stream */
paul15935e92005-05-03 09:27:23 +0000368 lsp->pdu = stream_dup (stream);
369
jardineb5d44e2003-12-23 08:09:43 +0000370 /* setting pointers to the correct place */
hassof390d2c2004-09-10 20:48:21 +0000371 lsp->isis_header = (struct isis_fixed_hdr *) (STREAM_DATA (lsp->pdu));
372 lsp->lsp_header = (struct isis_link_state_hdr *) (STREAM_DATA (lsp->pdu) +
373 ISIS_FIXED_HDR_LEN);
jardineb5d44e2003-12-23 08:09:43 +0000374 lsp->age_out = ZERO_AGE_LIFETIME;
hassof390d2c2004-09-10 20:48:21 +0000375 lsp->installed = time (NULL);
jardineb5d44e2003-12-23 08:09:43 +0000376 /*
377 * Get LSP data i.e. TLVs
378 */
379 expected |= TLVFLAG_AUTH_INFO;
380 expected |= TLVFLAG_AREA_ADDRS;
381 expected |= TLVFLAG_IS_NEIGHS;
hassof390d2c2004-09-10 20:48:21 +0000382 if ((lsp->lsp_header->lsp_bits & 3) == 3) /* a level 2 LSP */
jardineb5d44e2003-12-23 08:09:43 +0000383 expected |= TLVFLAG_PARTITION_DESIG_LEVEL2_IS;
384 expected |= TLVFLAG_NLPID;
385 if (area->dynhostname)
386 expected |= TLVFLAG_DYN_HOSTNAME;
hassof390d2c2004-09-10 20:48:21 +0000387 if (area->newmetric)
388 {
389 expected |= TLVFLAG_TE_IS_NEIGHS;
390 expected |= TLVFLAG_TE_IPV4_REACHABILITY;
391 expected |= TLVFLAG_TE_ROUTER_ID;
392 }
jardineb5d44e2003-12-23 08:09:43 +0000393 expected |= TLVFLAG_IPV4_ADDR;
394 expected |= TLVFLAG_IPV4_INT_REACHABILITY;
395 expected |= TLVFLAG_IPV4_EXT_REACHABILITY;
396#ifdef HAVE_IPV6
397 expected |= TLVFLAG_IPV6_ADDR;
398 expected |= TLVFLAG_IPV6_REACHABILITY;
399#endif /* HAVE_IPV6 */
400
401 retval = parse_tlvs (area->area_tag, lsp->pdu->data +
hassof390d2c2004-09-10 20:48:21 +0000402 ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN,
403 ntohs (lsp->lsp_header->pdu_len) - ISIS_FIXED_HDR_LEN
404 - ISIS_LSP_HDR_LEN, &expected, &found, &lsp->tlv_data);
jardineb5d44e2003-12-23 08:09:43 +0000405
hassof390d2c2004-09-10 20:48:21 +0000406 if (found & TLVFLAG_DYN_HOSTNAME)
407 {
408 if (area->dynhostname)
409 isis_dynhn_insert (lsp->lsp_header->lsp_id, lsp->tlv_data.hostname,
410 (lsp->lsp_header->lsp_bits & LSPBIT_IST) ==
411 IS_LEVEL_1_AND_2 ? IS_LEVEL_2 :
412 (lsp->lsp_header->lsp_bits & LSPBIT_IST));
413 }
jardineb5d44e2003-12-23 08:09:43 +0000414
415}
416
417void
418lsp_update (struct isis_lsp *lsp, struct isis_link_state_hdr *lsp_hdr,
hassoa96d8d12005-09-16 14:44:23 +0000419 struct stream *stream, struct isis_area *area, int level)
jardineb5d44e2003-12-23 08:09:43 +0000420{
hasso4eda93a2005-09-18 17:51:02 +0000421 dnode_t *dnode = NULL;
hassoa96d8d12005-09-16 14:44:23 +0000422
423 /* Remove old LSP from LSP database. */
hasso4eda93a2005-09-18 17:51:02 +0000424 dnode = dict_lookup (area->lspdb[level - 1], lsp->lsp_header->lsp_id);
425 if (dnode)
426 dnode_destroy (dict_delete (area->lspdb[level - 1], dnode));
hassoa96d8d12005-09-16 14:44:23 +0000427
hassof390d2c2004-09-10 20:48:21 +0000428 /* free the old lsp data */
jardineb5d44e2003-12-23 08:09:43 +0000429 XFREE (MTYPE_STREAM_DATA, lsp->pdu);
430 lsp_clear_data (lsp);
431
432 /* rebuild the lsp data */
433 lsp_update_data (lsp, stream, area);
434
hassof390d2c2004-09-10 20:48:21 +0000435 /* set the new values for lsp header */
jardineb5d44e2003-12-23 08:09:43 +0000436 memcpy (lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN);
hassoa96d8d12005-09-16 14:44:23 +0000437
hasso4eda93a2005-09-18 17:51:02 +0000438 if (dnode)
439 lsp_insert (lsp, area->lspdb[level - 1]);
jardineb5d44e2003-12-23 08:09:43 +0000440}
441
jardineb5d44e2003-12-23 08:09:43 +0000442/* creation of LSP directly from what we received */
443struct isis_lsp *
hassof390d2c2004-09-10 20:48:21 +0000444lsp_new_from_stream_ptr (struct stream *stream,
445 u_int16_t pdu_len, struct isis_lsp *lsp0,
446 struct isis_area *area)
jardineb5d44e2003-12-23 08:09:43 +0000447{
448 struct isis_lsp *lsp;
449
hassoaac372f2005-09-01 17:52:33 +0000450 lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
jardineb5d44e2003-12-23 08:09:43 +0000451 lsp_update_data (lsp, stream, area);
hassof390d2c2004-09-10 20:48:21 +0000452
453 if (lsp0 == NULL)
454 {
455 /*
456 * zero lsp -> create the list for fragments
457 */
458 lsp->lspu.frags = list_new ();
459 }
460 else
461 {
462 /*
463 * a fragment -> set the backpointer and add this to zero lsps frag list
464 */
465 lsp->lspu.zero_lsp = lsp0;
466 listnode_add (lsp0->lspu.frags, lsp);
467 }
468
jardineb5d44e2003-12-23 08:09:43 +0000469 return lsp;
470}
471
472struct isis_lsp *
hassof390d2c2004-09-10 20:48:21 +0000473lsp_new (u_char * lsp_id, u_int16_t rem_lifetime, u_int32_t seq_num,
474 u_int8_t lsp_bits, u_int16_t checksum, int level)
jardineb5d44e2003-12-23 08:09:43 +0000475{
476 struct isis_lsp *lsp;
477
hassoaac372f2005-09-01 17:52:33 +0000478 lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
hassof390d2c2004-09-10 20:48:21 +0000479 if (!lsp)
480 {
481 /* FIXME: set lspdbol bit */
482 zlog_warn ("lsp_new(): out of memory");
483 return NULL;
484 }
jardineb5d44e2003-12-23 08:09:43 +0000485#ifdef LSP_MEMORY_PREASSIGN
hassof390d2c2004-09-10 20:48:21 +0000486 lsp->pdu = stream_new (1514); /*Should be minimal mtu? yup... */
jardineb5d44e2003-12-23 08:09:43 +0000487#else
hassof390d2c2004-09-10 20:48:21 +0000488 /* We need to do realloc on TLVs additions */
489 lsp->pdu = malloc (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
jardineb5d44e2003-12-23 08:09:43 +0000490#endif /* LSP_MEMORY_PREASSIGN */
491 if (LSP_FRAGMENT (lsp_id) == 0)
492 lsp->lspu.frags = list_new ();
hassof390d2c2004-09-10 20:48:21 +0000493 lsp->isis_header = (struct isis_fixed_hdr *) (STREAM_DATA (lsp->pdu));
494 lsp->lsp_header = (struct isis_link_state_hdr *)
495 (STREAM_DATA (lsp->pdu) + ISIS_FIXED_HDR_LEN);
496
jardineb5d44e2003-12-23 08:09:43 +0000497 /* at first we fill the FIXED HEADER */
hassof390d2c2004-09-10 20:48:21 +0000498 (level == 1) ? fill_fixed_hdr (lsp->isis_header, L1_LINK_STATE) :
499 fill_fixed_hdr (lsp->isis_header, L2_LINK_STATE);
500
jardineb5d44e2003-12-23 08:09:43 +0000501 /* now for the LSP HEADER */
502 /* Minimal LSP PDU size */
hassof390d2c2004-09-10 20:48:21 +0000503 lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
jardineb5d44e2003-12-23 08:09:43 +0000504 memcpy (lsp->lsp_header->lsp_id, lsp_id, ISIS_SYS_ID_LEN + 2);
hassof390d2c2004-09-10 20:48:21 +0000505 lsp->lsp_header->checksum = checksum; /* Provided in network order */
jardineb5d44e2003-12-23 08:09:43 +0000506 lsp->lsp_header->seq_num = htonl (seq_num);
507 lsp->lsp_header->rem_lifetime = htons (rem_lifetime);
508 lsp->lsp_header->lsp_bits = lsp_bits;
509 lsp->level = level;
510 lsp->age_out = ZERO_AGE_LIFETIME;
511
paul9985f832005-02-09 15:51:56 +0000512 stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
jardineb5d44e2003-12-23 08:09:43 +0000513
hassoc89c05d2005-09-04 21:36:36 +0000514 if (isis->debugs & DEBUG_EVENTS)
515 zlog_debug ("New LSP with ID %s-%02x-%02x seqnum %08x",
516 sysid_print (lsp_id), LSP_PSEUDO_ID (lsp->lsp_header->lsp_id),
517 LSP_FRAGMENT (lsp->lsp_header->lsp_id),
518 ntohl (lsp->lsp_header->seq_num));
jardineb5d44e2003-12-23 08:09:43 +0000519
520 return lsp;
521}
522
523void
hassof390d2c2004-09-10 20:48:21 +0000524lsp_insert (struct isis_lsp *lsp, dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +0000525{
526 dict_alloc_insert (lspdb, lsp->lsp_header->lsp_id, lsp);
527}
528
529/*
530 * Build a list of LSPs with non-zero ht bounded by start and stop ids
531 */
hassof390d2c2004-09-10 20:48:21 +0000532void
533lsp_build_list_nonzero_ht (u_char * start_id, u_char * stop_id,
534 struct list *list, dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +0000535{
536 dnode_t *first, *last, *curr;
537
538 first = dict_lower_bound (lspdb, start_id);
539 if (!first)
540 return;
hassof390d2c2004-09-10 20:48:21 +0000541
jardineb5d44e2003-12-23 08:09:43 +0000542 last = dict_upper_bound (lspdb, stop_id);
hassof390d2c2004-09-10 20:48:21 +0000543
jardineb5d44e2003-12-23 08:09:43 +0000544 curr = first;
hassof390d2c2004-09-10 20:48:21 +0000545
546 if (((struct isis_lsp *) (curr->dict_data))->lsp_header->rem_lifetime)
jardineb5d44e2003-12-23 08:09:43 +0000547 listnode_add (list, first->dict_data);
548
hassof390d2c2004-09-10 20:48:21 +0000549 while (curr)
550 {
551 curr = dict_next (lspdb, curr);
552 if (curr &&
553 ((struct isis_lsp *) (curr->dict_data))->lsp_header->rem_lifetime)
554 listnode_add (list, curr->dict_data);
555 if (curr == last)
556 break;
557 }
558
jardineb5d44e2003-12-23 08:09:43 +0000559 return;
560}
561
562/*
563 * Build a list of all LSPs bounded by start and stop ids
564 */
hassof390d2c2004-09-10 20:48:21 +0000565void
566lsp_build_list (u_char * start_id, u_char * stop_id,
567 struct list *list, dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +0000568{
569 dnode_t *first, *last, *curr;
570
571 first = dict_lower_bound (lspdb, start_id);
572 if (!first)
573 return;
hassof390d2c2004-09-10 20:48:21 +0000574
jardineb5d44e2003-12-23 08:09:43 +0000575 last = dict_upper_bound (lspdb, stop_id);
hassof390d2c2004-09-10 20:48:21 +0000576
jardineb5d44e2003-12-23 08:09:43 +0000577 curr = first;
hassof390d2c2004-09-10 20:48:21 +0000578
jardineb5d44e2003-12-23 08:09:43 +0000579 listnode_add (list, first->dict_data);
580
hassof390d2c2004-09-10 20:48:21 +0000581 while (curr)
582 {
583 curr = dict_next (lspdb, curr);
584 if (curr)
585 listnode_add (list, curr->dict_data);
586 if (curr == last)
587 break;
588 }
589
jardineb5d44e2003-12-23 08:09:43 +0000590 return;
591}
592
593/*
594 * Build a list of LSPs with SSN flag set for the given circuit
595 */
596void
hassof390d2c2004-09-10 20:48:21 +0000597lsp_build_list_ssn (struct isis_circuit *circuit, struct list *list,
598 dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +0000599{
600 dnode_t *dnode, *next;
601 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +0000602
jardineb5d44e2003-12-23 08:09:43 +0000603 dnode = dict_first (lspdb);
hassof390d2c2004-09-10 20:48:21 +0000604 while (dnode != NULL)
605 {
606 next = dict_next (lspdb, dnode);
607 lsp = dnode_get (dnode);
608 if (ISIS_CHECK_FLAG (lsp->SSNflags, circuit))
609 listnode_add (list, lsp);
610 dnode = next;
611 }
612
jardineb5d44e2003-12-23 08:09:43 +0000613 return;
614}
615
hasso92365882005-01-18 13:53:33 +0000616static void
jardineb5d44e2003-12-23 08:09:43 +0000617lsp_set_time (struct isis_lsp *lsp)
618{
619 assert (lsp);
hassof390d2c2004-09-10 20:48:21 +0000620
621 if (lsp->lsp_header->rem_lifetime == 0)
622 {
623 if (lsp->age_out != 0)
624 lsp->age_out--;
625 return;
626 }
jardineb5d44e2003-12-23 08:09:43 +0000627
628 /* If we are turning 0 */
629 /* ISO 10589 - 7.3.16.4 first paragraph */
630
hassof390d2c2004-09-10 20:48:21 +0000631 if (ntohs (lsp->lsp_header->rem_lifetime) == 1)
632 {
633 /* 7.3.16.4 a) set SRM flags on all */
634 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
635 /* 7.3.16.4 b) retain only the header FIXME */
636 /* 7.3.16.4 c) record the time to purge FIXME (other way to do it) */
637 }
jardineb5d44e2003-12-23 08:09:43 +0000638
hassof390d2c2004-09-10 20:48:21 +0000639 lsp->lsp_header->rem_lifetime =
jardineb5d44e2003-12-23 08:09:43 +0000640 htons (ntohs (lsp->lsp_header->rem_lifetime) - 1);
641}
642
hasso92365882005-01-18 13:53:33 +0000643static void
hassof390d2c2004-09-10 20:48:21 +0000644lspid_print (u_char * lsp_id, u_char * trg, char dynhost, char frag)
jardineb5d44e2003-12-23 08:09:43 +0000645{
646 struct isis_dynhn *dyn = NULL;
hassof390d2c2004-09-10 20:48:21 +0000647 u_char id[SYSID_STRLEN];
jardineb5d44e2003-12-23 08:09:43 +0000648
649 if (dynhost)
650 dyn = dynhn_find_by_id (lsp_id);
651 else
652 dyn = NULL;
653
654 if (dyn)
hassof7c43dc2004-09-26 16:24:14 +0000655 sprintf ((char *)id, "%.14s", dyn->name.name);
jardineb5d44e2003-12-23 08:09:43 +0000656 else if (!memcmp (isis->sysid, lsp_id, ISIS_SYS_ID_LEN) & dynhost)
hassof7c43dc2004-09-26 16:24:14 +0000657 sprintf ((char *)id, "%.14s", unix_hostname ());
jardineb5d44e2003-12-23 08:09:43 +0000658 else
hassof390d2c2004-09-10 20:48:21 +0000659 {
660 memcpy (id, sysid_print (lsp_id), 15);
661 }
662 if (frag)
hassof7c43dc2004-09-26 16:24:14 +0000663 sprintf ((char *)trg, "%s.%02x-%02x", id, LSP_PSEUDO_ID (lsp_id),
hassof390d2c2004-09-10 20:48:21 +0000664 LSP_FRAGMENT (lsp_id));
665 else
hassof7c43dc2004-09-26 16:24:14 +0000666 sprintf ((char *)trg, "%s.%02x", id, LSP_PSEUDO_ID (lsp_id));
jardineb5d44e2003-12-23 08:09:43 +0000667}
668
hassof390d2c2004-09-10 20:48:21 +0000669/* Convert the lsp attribute bits to attribute string */
hasso1cd80842004-10-07 20:07:40 +0000670const char *
hassof390d2c2004-09-10 20:48:21 +0000671lsp_bits2string (u_char * lsp_bits)
672{
673 char *pos = lsp_bits_string;
jardineb5d44e2003-12-23 08:09:43 +0000674
hassof390d2c2004-09-10 20:48:21 +0000675 if (!*lsp_bits)
jardineb5d44e2003-12-23 08:09:43 +0000676 return " none";
677
678 /* we only focus on the default metric */
679 pos += sprintf (pos, "%d/",
hassof390d2c2004-09-10 20:48:21 +0000680 ISIS_MASK_LSP_ATT_DEFAULT_BIT (*lsp_bits) ? 1 : 0);
jardineb5d44e2003-12-23 08:09:43 +0000681
682 pos += sprintf (pos, "%d/",
hassof390d2c2004-09-10 20:48:21 +0000683 ISIS_MASK_LSP_PARTITION_BIT (*lsp_bits) ? 1 : 0);
jardineb5d44e2003-12-23 08:09:43 +0000684
hassof390d2c2004-09-10 20:48:21 +0000685 pos += sprintf (pos, "%d", ISIS_MASK_LSP_OL_BIT (*lsp_bits) ? 1 : 0);
686
jardineb5d44e2003-12-23 08:09:43 +0000687 *(pos) = '\0';
jardineb5d44e2003-12-23 08:09:43 +0000688
hassof390d2c2004-09-10 20:48:21 +0000689 return lsp_bits_string;
jardineb5d44e2003-12-23 08:09:43 +0000690}
691
692/* this function prints the lsp on show isis database */
hasso92365882005-01-18 13:53:33 +0000693static void
hassof390d2c2004-09-10 20:48:21 +0000694lsp_print (dnode_t * node, struct vty *vty, char dynhost)
jardineb5d44e2003-12-23 08:09:43 +0000695{
hassof390d2c2004-09-10 20:48:21 +0000696 struct isis_lsp *lsp = dnode_get (node);
jardineb5d44e2003-12-23 08:09:43 +0000697 u_char LSPid[255];
698
699 lspid_print (lsp->lsp_header->lsp_id, LSPid, dynhost, 1);
hassof390d2c2004-09-10 20:48:21 +0000700 vty_out (vty, "%-21s%c ", LSPid, lsp->own_lsp ? '*' : ' ');
701 vty_out (vty, "0x%08x ", ntohl (lsp->lsp_header->seq_num));
702 vty_out (vty, "0x%04x ", ntohs (lsp->lsp_header->checksum));
jardineb5d44e2003-12-23 08:09:43 +0000703
hassof390d2c2004-09-10 20:48:21 +0000704 if (ntohs (lsp->lsp_header->rem_lifetime) == 0)
705 vty_out (vty, " (%2u)", lsp->age_out);
jardineb5d44e2003-12-23 08:09:43 +0000706 else
hassof390d2c2004-09-10 20:48:21 +0000707 vty_out (vty, "%5u", ntohs (lsp->lsp_header->rem_lifetime));
jardineb5d44e2003-12-23 08:09:43 +0000708
709 vty_out (vty, " %s%s",
hassof390d2c2004-09-10 20:48:21 +0000710 lsp_bits2string (&lsp->lsp_header->lsp_bits), VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +0000711}
712
hasso92365882005-01-18 13:53:33 +0000713static void
hassof390d2c2004-09-10 20:48:21 +0000714lsp_print_detail (dnode_t * node, struct vty *vty, char dynhost)
jardineb5d44e2003-12-23 08:09:43 +0000715{
716 struct isis_lsp *lsp = dnode_get (node);
717 struct area_addr *area_addr;
hassof390d2c2004-09-10 20:48:21 +0000718 int i;
paul1eb8ef22005-04-07 07:30:20 +0000719 struct listnode *lnode, *lnnode;
jardineb5d44e2003-12-23 08:09:43 +0000720 struct is_neigh *is_neigh;
721 struct te_is_neigh *te_is_neigh;
722 struct ipv4_reachability *ipv4_reach;
723 struct in_addr *ipv4_addr;
724 struct te_ipv4_reachability *te_ipv4_reach;
725#ifdef HAVE_IPV6
726 struct ipv6_reachability *ipv6_reach;
727 struct in6_addr in6;
728#endif
729 u_char LSPid[255];
730 u_char hostname[255];
731 u_char buff[BUFSIZ];
jardineb5d44e2003-12-23 08:09:43 +0000732 u_char ipv4_reach_prefix[20];
733 u_char ipv4_reach_mask[20];
734 u_char ipv4_address[20];
735
736 lspid_print (lsp->lsp_header->lsp_id, LSPid, dynhost, 1);
hassof390d2c2004-09-10 20:48:21 +0000737 lsp_print (node, vty, dynhost);
jardineb5d44e2003-12-23 08:09:43 +0000738
739 /* for all area address */
hassof390d2c2004-09-10 20:48:21 +0000740 if (lsp->tlv_data.area_addrs)
paul1eb8ef22005-04-07 07:30:20 +0000741 for (ALL_LIST_ELEMENTS (lsp->tlv_data.area_addrs, lnode,
742 lnnode, area_addr))
hassof390d2c2004-09-10 20:48:21 +0000743 {
hasso1cd80842004-10-07 20:07:40 +0000744 vty_out (vty, " Area Address: %s%s",
hassof390d2c2004-09-10 20:48:21 +0000745 isonet_print (area_addr->area_addr, area_addr->addr_len),
746 VTY_NEWLINE);
747 }
paul1eb8ef22005-04-07 07:30:20 +0000748
jardineb5d44e2003-12-23 08:09:43 +0000749 /* for the nlpid tlv */
hassof390d2c2004-09-10 20:48:21 +0000750 if (lsp->tlv_data.nlpids)
751 {
752 for (i = 0; i < lsp->tlv_data.nlpids->count; i++)
753 {
754 switch (lsp->tlv_data.nlpids->nlpids[i])
755 {
756 case NLPID_IP:
757 case NLPID_IPV6:
hasso1cd80842004-10-07 20:07:40 +0000758 vty_out (vty, " NLPID: 0x%X%s",
hassof390d2c2004-09-10 20:48:21 +0000759 lsp->tlv_data.nlpids->nlpids[i], VTY_NEWLINE);
760 break;
761 default:
hasso1cd80842004-10-07 20:07:40 +0000762 vty_out (vty, " NLPID: %s%s", "unknown", VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +0000763 break;
764 }
765 }
766 }
jardineb5d44e2003-12-23 08:09:43 +0000767
768 /* for the hostname tlv */
hassof390d2c2004-09-10 20:48:21 +0000769 if (lsp->tlv_data.hostname)
770 {
771 bzero (hostname, sizeof (hostname));
772 memcpy (hostname, lsp->tlv_data.hostname->name,
773 lsp->tlv_data.hostname->namelen);
774 vty_out (vty, " Hostname: %s%s", hostname, VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +0000775 }
hassof390d2c2004-09-10 20:48:21 +0000776
777 if (lsp->tlv_data.ipv4_addrs)
paul1eb8ef22005-04-07 07:30:20 +0000778 for (ALL_LIST_ELEMENTS (lsp->tlv_data.ipv4_addrs, lnode,
779 lnnode, ipv4_addr))
hassof390d2c2004-09-10 20:48:21 +0000780 {
781 memcpy (ipv4_address, inet_ntoa (*ipv4_addr), sizeof (ipv4_address));
782 vty_out (vty, " IP: %s%s", ipv4_address, VTY_NEWLINE);
783 }
hassof390d2c2004-09-10 20:48:21 +0000784
hasso1cd80842004-10-07 20:07:40 +0000785 /* TE router id */
786 if (lsp->tlv_data.router_id)
787 {
788 memcpy (ipv4_address, inet_ntoa (lsp->tlv_data.router_id->id),
789 sizeof (ipv4_address));
790 vty_out (vty, " Router ID: %s%s", ipv4_address, VTY_NEWLINE);
791 }
792
793 /* for the IS neighbor tlv */
794 if (lsp->tlv_data.is_neighs)
paul1eb8ef22005-04-07 07:30:20 +0000795 for (ALL_LIST_ELEMENTS (lsp->tlv_data.is_neighs, lnode, lnnode, is_neigh))
hasso1cd80842004-10-07 20:07:40 +0000796 {
797 lspid_print (is_neigh->neigh_id, LSPid, dynhost, 0);
hasso96e30382005-09-19 06:35:47 +0000798 vty_out (vty, " Metric: %-10d IS %s%s",
hasso1cd80842004-10-07 20:07:40 +0000799 is_neigh->metrics.metric_default, LSPid, VTY_NEWLINE);
800 }
hasso1cd80842004-10-07 20:07:40 +0000801
jardineb5d44e2003-12-23 08:09:43 +0000802 /* for the internal reachable tlv */
803 if (lsp->tlv_data.ipv4_int_reachs)
paul1eb8ef22005-04-07 07:30:20 +0000804 for (ALL_LIST_ELEMENTS (lsp->tlv_data.ipv4_int_reachs, lnode,
805 lnnode, ipv4_reach))
hassof390d2c2004-09-10 20:48:21 +0000806 {
807 memcpy (ipv4_reach_prefix, inet_ntoa (ipv4_reach->prefix),
808 sizeof (ipv4_reach_prefix));
809 memcpy (ipv4_reach_mask, inet_ntoa (ipv4_reach->mask),
810 sizeof (ipv4_reach_mask));
hasso96e30382005-09-19 06:35:47 +0000811 vty_out (vty, " Metric: %-10d IP-Internal %s %s%s",
hassof390d2c2004-09-10 20:48:21 +0000812 ipv4_reach->metrics.metric_default, ipv4_reach_prefix,
813 ipv4_reach_mask, VTY_NEWLINE);
814 }
hasso2097cd82003-12-23 11:51:08 +0000815
816 /* for the external reachable tlv */
817 if (lsp->tlv_data.ipv4_ext_reachs)
paul1eb8ef22005-04-07 07:30:20 +0000818 for (ALL_LIST_ELEMENTS (lsp->tlv_data.ipv4_ext_reachs, lnode,
819 lnnode, ipv4_reach))
hassof390d2c2004-09-10 20:48:21 +0000820 {
821 memcpy (ipv4_reach_prefix, inet_ntoa (ipv4_reach->prefix),
822 sizeof (ipv4_reach_prefix));
823 memcpy (ipv4_reach_mask, inet_ntoa (ipv4_reach->mask),
824 sizeof (ipv4_reach_mask));
hasso96e30382005-09-19 06:35:47 +0000825 vty_out (vty, " Metric: %-10d IP-External %s %s%s",
hassof390d2c2004-09-10 20:48:21 +0000826 ipv4_reach->metrics.metric_default, ipv4_reach_prefix,
827 ipv4_reach_mask, VTY_NEWLINE);
828 }
paul1eb8ef22005-04-07 07:30:20 +0000829
hasso2097cd82003-12-23 11:51:08 +0000830 /* IPv6 tlv */
831#ifdef HAVE_IPV6
832 if (lsp->tlv_data.ipv6_reachs)
paul1eb8ef22005-04-07 07:30:20 +0000833 for (ALL_LIST_ELEMENTS (lsp->tlv_data.ipv6_reachs, lnode,
834 lnnode, ipv6_reach))
hassof390d2c2004-09-10 20:48:21 +0000835 {
836 memset (&in6, 0, sizeof (in6));
837 memcpy (in6.s6_addr, ipv6_reach->prefix,
838 PSIZE (ipv6_reach->prefix_len));
hassof7c43dc2004-09-26 16:24:14 +0000839 inet_ntop (AF_INET6, &in6, (char *)buff, BUFSIZ);
hasso2097cd82003-12-23 11:51:08 +0000840 if ((ipv6_reach->control_info &&
hassof390d2c2004-09-10 20:48:21 +0000841 CTRL_INFO_DISTRIBUTION) == DISTRIBUTION_INTERNAL)
hasso96e30382005-09-19 06:35:47 +0000842 vty_out (vty, " Metric: %-10d IPv6-Internal %s/%d%s",
hassof390d2c2004-09-10 20:48:21 +0000843 ntohl (ipv6_reach->metric),
844 buff, ipv6_reach->prefix_len, VTY_NEWLINE);
hasso2097cd82003-12-23 11:51:08 +0000845 else
hasso96e30382005-09-19 06:35:47 +0000846 vty_out (vty, " Metric: %-10d IPv6-External %s/%d%s",
hassof390d2c2004-09-10 20:48:21 +0000847 ntohl (ipv6_reach->metric),
848 buff, ipv6_reach->prefix_len, VTY_NEWLINE);
hasso2097cd82003-12-23 11:51:08 +0000849 }
850#endif
paul1eb8ef22005-04-07 07:30:20 +0000851
hasso1cd80842004-10-07 20:07:40 +0000852 /* TE IS neighbor tlv */
jardineb5d44e2003-12-23 08:09:43 +0000853 if (lsp->tlv_data.te_is_neighs)
paul1eb8ef22005-04-07 07:30:20 +0000854 for (ALL_LIST_ELEMENTS (lsp->tlv_data.te_is_neighs, lnode,
855 lnnode, te_is_neigh))
hassof390d2c2004-09-10 20:48:21 +0000856 {
hasso96e30382005-09-19 06:35:47 +0000857 uint32_t metric;
858 memcpy (&metric, te_is_neigh->te_metric, 3);
hassof390d2c2004-09-10 20:48:21 +0000859 lspid_print (te_is_neigh->neigh_id, LSPid, dynhost, 0);
hasso96e30382005-09-19 06:35:47 +0000860 vty_out (vty, " Metric: %-10d IS-Extended %s%s",
861 ntohl (metric << 8), LSPid, VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +0000862 }
jardineb5d44e2003-12-23 08:09:43 +0000863
hasso1cd80842004-10-07 20:07:40 +0000864 /* TE IPv4 tlv */
jardineb5d44e2003-12-23 08:09:43 +0000865 if (lsp->tlv_data.te_ipv4_reachs)
paul1eb8ef22005-04-07 07:30:20 +0000866 for (ALL_LIST_ELEMENTS (lsp->tlv_data.te_ipv4_reachs, lnode,
867 lnnode, te_ipv4_reach))
hassof390d2c2004-09-10 20:48:21 +0000868 {
hasso1cd80842004-10-07 20:07:40 +0000869 /* FIXME: There should be better way to output this stuff. */
hasso96e30382005-09-19 06:35:47 +0000870 vty_out (vty, " Metric: %-10d IP-Extended %s/%d%s",
hasso1cd80842004-10-07 20:07:40 +0000871 ntohl (te_ipv4_reach->te_metric),
hassof390d2c2004-09-10 20:48:21 +0000872 inet_ntoa (newprefix2inaddr (&te_ipv4_reach->prefix_start,
873 te_ipv4_reach->control)),
hasso1cd80842004-10-07 20:07:40 +0000874 te_ipv4_reach->control & 0x3F, VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +0000875 }
jardineb5d44e2003-12-23 08:09:43 +0000876
hassof390d2c2004-09-10 20:48:21 +0000877 return;
jardineb5d44e2003-12-23 08:09:43 +0000878}
879
880/* print all the lsps info in the local lspdb */
hassof390d2c2004-09-10 20:48:21 +0000881int
882lsp_print_all (struct vty *vty, dict_t * lspdb, char detail, char dynhost)
jardineb5d44e2003-12-23 08:09:43 +0000883{
884
hassof390d2c2004-09-10 20:48:21 +0000885 dnode_t *node = dict_first (lspdb), *next;
jardineb5d44e2003-12-23 08:09:43 +0000886 int lsp_count = 0;
887
888 /* print the title, for both modes */
889 vty_out (vty, "LSP ID LSP Seq Num LSP Checksum "
hassof390d2c2004-09-10 20:48:21 +0000890 "LSP Holdtime ATT/P/OL%s", VTY_NEWLINE);
891
892 if (detail == ISIS_UI_LEVEL_BRIEF)
893 {
894 while (node != NULL)
895 {
896 /* I think it is unnecessary, so I comment it out */
897 /* dict_contains (lspdb, node); */
898 next = dict_next (lspdb, node);
899 lsp_print (node, vty, dynhost);
900 node = next;
901 lsp_count++;
902 }
jardineb5d44e2003-12-23 08:09:43 +0000903 }
hassof390d2c2004-09-10 20:48:21 +0000904 else if (detail == ISIS_UI_LEVEL_DETAIL)
905 {
906 while (node != NULL)
907 {
908 next = dict_next (lspdb, node);
909 lsp_print_detail (node, vty, dynhost);
910 node = next;
911 lsp_count++;
912 }
jardineb5d44e2003-12-23 08:09:43 +0000913 }
jardineb5d44e2003-12-23 08:09:43 +0000914
915 return lsp_count;
916}
917
hassof1082d12005-09-19 04:23:34 +0000918#if 0
jardineb5d44e2003-12-23 08:09:43 +0000919/* this function reallocate memory to an lsp pdu, with an additional
920 * size of memory, it scans the lsp and moves all pointers the
921 * way they should */
hasso92365882005-01-18 13:53:33 +0000922static u_char *
hassof390d2c2004-09-10 20:48:21 +0000923lsppdu_realloc (struct isis_lsp * lsp, int memorytype, int size)
jardineb5d44e2003-12-23 08:09:43 +0000924{
925 u_char *retval;
hassof390d2c2004-09-10 20:48:21 +0000926
927 retval = STREAM_DATA (lsp->pdu) + ntohs (lsp->lsp_header->pdu_len);
jardineb5d44e2003-12-23 08:09:43 +0000928#ifdef LSP_MEMORY_PREASSIGN
hassof390d2c2004-09-10 20:48:21 +0000929 lsp->lsp_header->pdu_len = htons (ntohs (lsp->lsp_header->pdu_len) + size);
jardineb5d44e2003-12-23 08:09:43 +0000930 return retval;
hassof390d2c2004-09-10 20:48:21 +0000931#else /* otherwise we have to move all pointers */
jardineb5d44e2003-12-23 08:09:43 +0000932 u_char *newpdu;
933 newpdu = stream_new (ntohs (lsp->lsp_header->pdu_len) + size);
hassoaac372f2005-09-01 17:52:33 +0000934 stream_put (newpdu, STREAM_DATA(lsp->pdu), ntohs (lsp->lsp_header->pdu_len));
jardineb5d44e2003-12-23 08:09:43 +0000935 XFREE (memorytype, lsp->pdu);
936 lsp->pdu = newpdu;
hassof390d2c2004-09-10 20:48:21 +0000937 lsp->isis_header = (struct isis_fixed_hdr *) STREAM_DATA (lsp->pdu);
938 lsp->lsp_header = (struct isis_link_state_hdr *)
939 (STREAM_DATA (lsp->pdu) + ISIS_FIXED_HDR_LEN);
jardineb5d44e2003-12-23 08:09:43 +0000940 htons (ntohs (lsp->lsp_header->pdu_len) += size);
hassof390d2c2004-09-10 20:48:21 +0000941 return STREAM_DATA (lsp->pdu) + (lsp->lsp_header->pdu_len - size);
jardineb5d44e2003-12-23 08:09:43 +0000942#endif /* LSP_MEMORY_PREASSIGN */
943}
hassof1082d12005-09-19 04:23:34 +0000944#endif
jardineb5d44e2003-12-23 08:09:43 +0000945
hassof390d2c2004-09-10 20:48:21 +0000946#if 0 /* Saving the old one just in case :) */
jardineb5d44e2003-12-23 08:09:43 +0000947/*
948 * Builds the lsp->tlv_data
949 * and writes the tlvs into lsp->pdu
950 */
951void
952lsp_build_nonpseudo (struct isis_lsp *lsp, struct isis_area *area)
953{
954 struct is_neigh *is_neigh;
paul1eb8ef22005-04-07 07:30:20 +0000955 struct listnode *node, *nnode, *ipnode, *ipnnode;
jardineb5d44e2003-12-23 08:09:43 +0000956 int level = lsp->level;
957 struct isis_circuit *circuit;
958 struct prefix_ipv4 *ipv4;
959 struct ipv4_reachability *ipreach;
960 struct isis_adjacency *nei;
961#ifdef HAVE_IPV6
962 struct prefix_ipv6 *ipv6;
963 struct ipv6_reachability *ip6reach;
964#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000965
jardineb5d44e2003-12-23 08:09:43 +0000966 /*
967 * First add the tlvs related to area
968 */
hassof390d2c2004-09-10 20:48:21 +0000969
jardineb5d44e2003-12-23 08:09:43 +0000970 /* Area addresses */
971 if (lsp->tlv_data.area_addrs == NULL)
972 lsp->tlv_data.area_addrs = list_new ();
973 list_add_list (lsp->tlv_data.area_addrs, area->area_addrs);
974 /* Protocols Supported */
hassof390d2c2004-09-10 20:48:21 +0000975 if (area->ip_circuits > 0
jardineb5d44e2003-12-23 08:09:43 +0000976#ifdef HAVE_IPV6
977 || area->ipv6_circuits > 0
978#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000979 )
jardineb5d44e2003-12-23 08:09:43 +0000980 {
981 lsp->tlv_data.nlpids = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct nlpids));
982 lsp->tlv_data.nlpids->count = 0;
hassof390d2c2004-09-10 20:48:21 +0000983 if (area->ip_circuits > 0)
984 {
985 lsp->tlv_data.nlpids->count++;
986 lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP;
987 }
jardineb5d44e2003-12-23 08:09:43 +0000988#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000989 if (area->ipv6_circuits > 0)
990 {
991 lsp->tlv_data.nlpids->count++;
992 lsp->tlv_data.nlpids->nlpids[lsp->tlv_data.nlpids->count - 1] =
993 NLPID_IPV6;
994 }
jardineb5d44e2003-12-23 08:09:43 +0000995#endif /* HAVE_IPV6 */
996 }
997 /* Dynamic Hostname */
hassof390d2c2004-09-10 20:48:21 +0000998 if (area->dynhostname)
999 {
1000 lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV,
1001 sizeof (struct hostname));
1002 memcpy (&lsp->tlv_data.hostname->name, unix_hostname (),
1003 strlen (unix_hostname ()));
1004 lsp->tlv_data.hostname->namelen = strlen (unix_hostname ());
1005 }
jardineb5d44e2003-12-23 08:09:43 +00001006#ifdef TOPOLOGY_GENERATE
1007 /*
1008 * If we have a topology in this area, we need to connect this lsp to
1009 * the first topology lsp
1010 */
hassof390d2c2004-09-10 20:48:21 +00001011 if ((area->topology) && (level == 1))
1012 {
1013 if (lsp->tlv_data.is_neighs == NULL)
1014 lsp->tlv_data.is_neighs = list_new ();
hassoaac372f2005-09-01 17:52:33 +00001015 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
hassof390d2c2004-09-10 20:48:21 +00001016 memcpy (&is_neigh->neigh_id, area->topology_baseis, ISIS_SYS_ID_LEN);
1017 /* connected to the first */
1018 is_neigh->neigh_id[ISIS_SYS_ID_LEN - 1] = (0x01);
1019 /* this is actually the same system, why mess the SPT */
1020 is_neigh->metrics.metric_default = 0;
1021 is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
1022 is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
1023 is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
1024 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
jardineb5d44e2003-12-23 08:09:43 +00001025
hassof390d2c2004-09-10 20:48:21 +00001026 }
jardineb5d44e2003-12-23 08:09:43 +00001027#endif
1028
1029 /*
1030 * Then add tlvs related to circuits
1031 */
paul1eb8ef22005-04-07 07:30:20 +00001032 for (ALL_LIST_ELEMENTS (area->circuit_list, node, nnode, circuit))
hassof390d2c2004-09-10 20:48:21 +00001033 {
hassof390d2c2004-09-10 20:48:21 +00001034 if (circuit->state != C_STATE_UP)
1035 continue;
1036
1037 /*
1038 * Add IPv4 internal reachability of this circuit
1039 */
1040 if (circuit->ip_router && circuit->ip_addrs &&
1041 circuit->ip_addrs->count > 0)
1042 {
1043 if (lsp->tlv_data.ipv4_int_reachs == NULL)
1044 {
1045 lsp->tlv_data.ipv4_int_reachs = list_new ();
1046 lsp->tlv_data.ipv4_int_reachs->del = free_tlv;
1047 }
paul1eb8ef22005-04-07 07:30:20 +00001048 for (ALL_LIST_ELEMENTS (circuit->ip_addrs, ipnode, ipnnode, ipv4))
hassof390d2c2004-09-10 20:48:21 +00001049 {
hassof390d2c2004-09-10 20:48:21 +00001050 ipreach =
hassoaac372f2005-09-01 17:52:33 +00001051 XCALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv4_reachability));
hassof390d2c2004-09-10 20:48:21 +00001052 ipreach->metrics = circuit->metrics[level - 1];
1053 ipreach->prefix = ipv4->prefix;
1054 masklen2ip (ipv4->prefixlen, &ipreach->mask);
1055 listnode_add (lsp->tlv_data.ipv4_int_reachs, ipreach);
1056 }
1057 }
jardineb5d44e2003-12-23 08:09:43 +00001058#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001059 /*
1060 * Add IPv6 reachability of this circuit
1061 */
1062 if (circuit->ipv6_router && circuit->ipv6_non_link &&
1063 circuit->ipv6_non_link->count > 0)
1064 {
1065 if (lsp->tlv_data.ipv6_reachs == NULL)
1066 {
1067 lsp->tlv_data.ipv6_reachs = list_new ();
1068 lsp->tlv_data.ipv6_reachs->del = free_tlv;
1069 }
paul1eb8ef22005-04-07 07:30:20 +00001070 for (ALL_LIST_ELEMENTS (circuit->ipv6_non_link, ipnode,
1071 ipnnode, ipv6))
hassof390d2c2004-09-10 20:48:21 +00001072 {
hassof390d2c2004-09-10 20:48:21 +00001073 ip6reach =
hassoaac372f2005-09-01 17:52:33 +00001074 XCALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv6_reachability));
hassof390d2c2004-09-10 20:48:21 +00001075 ip6reach->metric =
1076 htonl (circuit->metrics[level - 1].metric_default);
1077 ip6reach->control_info = 0;
1078 ip6reach->prefix_len = ipv6->prefixlen;
1079 memcpy (&ip6reach->prefix, ipv6->prefix.s6_addr,
1080 (ipv6->prefixlen + 7) / 8);
1081 listnode_add (lsp->tlv_data.ipv6_reachs, ip6reach);
1082 }
1083 }
jardineb5d44e2003-12-23 08:09:43 +00001084#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +00001085
1086 switch (circuit->circ_type)
1087 {
1088 case CIRCUIT_T_BROADCAST:
1089 if (level & circuit->circuit_is_type)
1090 {
1091 if (lsp->tlv_data.is_neighs == NULL)
1092 {
1093 lsp->tlv_data.is_neighs = list_new ();
1094 lsp->tlv_data.is_neighs->del = free_tlv;
1095 }
hassoaac372f2005-09-01 17:52:33 +00001096 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
hassof390d2c2004-09-10 20:48:21 +00001097 if (level == 1)
1098 memcpy (&is_neigh->neigh_id,
1099 circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
1100 else
1101 memcpy (&is_neigh->neigh_id,
1102 circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
1103 is_neigh->metrics = circuit->metrics[level - 1];
1104 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
1105 }
1106 break;
1107 case CIRCUIT_T_P2P:
1108 nei = circuit->u.p2p.neighbor;
1109 if (nei && (level & nei->circuit_t))
1110 {
1111 if (lsp->tlv_data.is_neighs == NULL)
1112 {
1113 lsp->tlv_data.is_neighs = list_new ();
1114 lsp->tlv_data.is_neighs->del = free_tlv;
1115 }
hassoaac372f2005-09-01 17:52:33 +00001116 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
hassof390d2c2004-09-10 20:48:21 +00001117 memcpy (&is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN);
1118 is_neigh->metrics = circuit->metrics[level - 1];
1119 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
1120 }
1121 break;
1122 case CIRCUIT_T_STATIC_IN:
1123 zlog_warn ("lsp_area_create: unsupported circuit type");
1124 break;
1125 case CIRCUIT_T_STATIC_OUT:
1126 zlog_warn ("lsp_area_create: unsupported circuit type");
1127 break;
1128 case CIRCUIT_T_DA:
1129 zlog_warn ("lsp_area_create: unsupported circuit type");
1130 break;
1131 default:
1132 zlog_warn ("lsp_area_create: unknown circuit type");
1133 }
jardineb5d44e2003-12-23 08:09:43 +00001134 }
hassof390d2c2004-09-10 20:48:21 +00001135
jardineb5d44e2003-12-23 08:09:43 +00001136 if (lsp->tlv_data.nlpids)
1137 tlv_add_nlpid (lsp->tlv_data.nlpids, lsp->pdu);
1138 if (lsp->tlv_data.hostname)
1139 tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu);
hassof390d2c2004-09-10 20:48:21 +00001140 if (lsp->tlv_data.area_addrs && listcount (lsp->tlv_data.area_addrs) > 0)
jardineb5d44e2003-12-23 08:09:43 +00001141 tlv_add_area_addrs (lsp->tlv_data.area_addrs, lsp->pdu);
1142 if (lsp->tlv_data.is_neighs && listcount (lsp->tlv_data.is_neighs) > 0)
1143 tlv_add_is_neighs (lsp->tlv_data.is_neighs, lsp->pdu);
hassof390d2c2004-09-10 20:48:21 +00001144 if (lsp->tlv_data.ipv4_int_reachs &&
jardineb5d44e2003-12-23 08:09:43 +00001145 listcount (lsp->tlv_data.ipv4_int_reachs) > 0)
1146 tlv_add_ipv4_reachs (lsp->tlv_data.ipv4_int_reachs, lsp->pdu);
hassof390d2c2004-09-10 20:48:21 +00001147#ifdef HAVE_IPV6
1148 if (lsp->tlv_data.ipv6_reachs && listcount (lsp->tlv_data.ipv6_reachs) > 0)
jardineb5d44e2003-12-23 08:09:43 +00001149 tlv_add_ipv6_reachs (lsp->tlv_data.ipv6_reachs, lsp->pdu);
1150#endif /* HAVE_IPV6 */
1151
paul9985f832005-02-09 15:51:56 +00001152 lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
jardineb5d44e2003-12-23 08:09:43 +00001153
1154 return;
1155}
1156#endif
1157
1158#define FRAG_THOLD(S,T) \
1159((STREAM_SIZE(S)*T)/100)
1160
1161/* stream*, area->lsp_frag_threshold, increment */
1162#define FRAG_NEEDED(S,T,I) \
1163 (STREAM_SIZE(S)-STREAM_REMAIN(S)+(I) > FRAG_THOLD(S,T))
1164
hasso92365882005-01-18 13:53:33 +00001165static void
jardineb5d44e2003-12-23 08:09:43 +00001166lsp_tlv_fit (struct isis_lsp *lsp, struct list **from, struct list **to,
hassof390d2c2004-09-10 20:48:21 +00001167 int tlvsize, int frag_thold,
1168 int tlv_build_func (struct list *, struct stream *))
jardineb5d44e2003-12-23 08:09:43 +00001169{
1170 int count, i;
hassof390d2c2004-09-10 20:48:21 +00001171
jardineb5d44e2003-12-23 08:09:43 +00001172 /* can we fit all ? */
hassof390d2c2004-09-10 20:48:21 +00001173 if (!FRAG_NEEDED (lsp->pdu, frag_thold, listcount (*from) * tlvsize + 2))
1174 {
1175 tlv_build_func (*from, lsp->pdu);
1176 *to = *from;
1177 *from = NULL;
jardineb5d44e2003-12-23 08:09:43 +00001178 }
hassof390d2c2004-09-10 20:48:21 +00001179 else if (!FRAG_NEEDED (lsp->pdu, frag_thold, tlvsize + 2))
1180 {
1181 /* fit all we can */
1182 count = FRAG_THOLD (lsp->pdu, frag_thold) - 2 -
1183 (STREAM_SIZE (lsp->pdu) - STREAM_REMAIN (lsp->pdu));
1184 if (count)
1185 count = count / tlvsize;
1186 for (i = 0; i < count; i++)
1187 {
paul1eb8ef22005-04-07 07:30:20 +00001188 listnode_add (*to, listgetdata (listhead (*from)));
1189 listnode_delete (*from, listgetdata (listhead (*from)));
hassof390d2c2004-09-10 20:48:21 +00001190 }
1191 tlv_build_func (*to, lsp->pdu);
1192 }
paul9985f832005-02-09 15:51:56 +00001193 lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
jardineb5d44e2003-12-23 08:09:43 +00001194 return;
1195}
1196
hasso92365882005-01-18 13:53:33 +00001197static struct isis_lsp *
hassof390d2c2004-09-10 20:48:21 +00001198lsp_next_frag (u_char frag_num, struct isis_lsp *lsp0, struct isis_area *area,
1199 int level)
jardineb5d44e2003-12-23 08:09:43 +00001200{
1201 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +00001202 u_char frag_id[ISIS_SYS_ID_LEN + 2];
1203
jardineb5d44e2003-12-23 08:09:43 +00001204 memcpy (frag_id, lsp0->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 1);
1205 LSP_FRAGMENT (frag_id) = frag_num;
1206 lsp = lsp_search (frag_id, area->lspdb[level - 1]);
hassof390d2c2004-09-10 20:48:21 +00001207 if (lsp)
1208 {
1209 /*
1210 * Clear the TLVs, but inherit the authinfo
1211 */
1212 lsp_clear_data (lsp);
1213 if (lsp0->tlv_data.auth_info.type)
1214 {
1215 memcpy (&lsp->tlv_data.auth_info, &lsp->tlv_data.auth_info,
1216 sizeof (struct isis_passwd));
1217 tlv_add_authinfo (lsp->tlv_data.auth_info.type,
1218 lsp->tlv_data.auth_info.len,
1219 lsp->tlv_data.auth_info.passwd, lsp->pdu);
1220 }
1221 return lsp;
jardineb5d44e2003-12-23 08:09:43 +00001222 }
jardineb5d44e2003-12-23 08:09:43 +00001223 lsp = lsp_new (frag_id, area->max_lsp_lifetime[level - 1], 0, area->is_type,
hassof390d2c2004-09-10 20:48:21 +00001224 0, level);
jardineb5d44e2003-12-23 08:09:43 +00001225 lsp->own_lsp = 1;
hassof390d2c2004-09-10 20:48:21 +00001226 lsp_insert (lsp, area->lspdb[level - 1]);
jardineb5d44e2003-12-23 08:09:43 +00001227 listnode_add (lsp0->lspu.frags, lsp);
1228 lsp->lspu.zero_lsp = lsp0;
1229 /*
1230 * Copy the authinfo from zero LSP
1231 */
hassof390d2c2004-09-10 20:48:21 +00001232 if (lsp0->tlv_data.auth_info.type)
1233 {
1234 memcpy (&lsp->tlv_data.auth_info, &lsp->tlv_data.auth_info,
1235 sizeof (struct isis_passwd));
1236 tlv_add_authinfo (lsp->tlv_data.auth_info.type,
1237 lsp->tlv_data.auth_info.len,
1238 lsp->tlv_data.auth_info.passwd, lsp->pdu);
1239 }
jardineb5d44e2003-12-23 08:09:43 +00001240 return lsp;
1241}
1242
1243/*
1244 * Builds the LSP data part. This func creates a new frag whenever
1245 * area->lsp_frag_threshold is exceeded.
1246 */
1247#if 1
hasso92365882005-01-18 13:53:33 +00001248static void
jardineb5d44e2003-12-23 08:09:43 +00001249lsp_build_nonpseudo (struct isis_lsp *lsp, struct isis_area *area)
1250{
1251 struct is_neigh *is_neigh;
paul1eb8ef22005-04-07 07:30:20 +00001252 struct listnode *node, *nnode, *ipnode, *ipnnode;
jardineb5d44e2003-12-23 08:09:43 +00001253 int level = lsp->level;
1254 struct isis_circuit *circuit;
1255 struct prefix_ipv4 *ipv4;
1256 struct ipv4_reachability *ipreach;
1257 struct isis_adjacency *nei;
1258#ifdef HAVE_IPV6
hasso67851572004-09-21 14:17:04 +00001259 struct prefix_ipv6 *ipv6, *ip6prefix;
jardineb5d44e2003-12-23 08:09:43 +00001260 struct ipv6_reachability *ip6reach;
1261#endif /* HAVE_IPV6 */
1262 struct tlvs tlv_data;
1263 struct isis_lsp *lsp0 = lsp;
1264 struct isis_passwd *passwd;
hasso18a6dce2004-10-03 18:18:34 +00001265 struct in_addr *routerid;
jardineb5d44e2003-12-23 08:09:43 +00001266
1267 /*
1268 * First add the tlvs related to area
1269 */
hassof390d2c2004-09-10 20:48:21 +00001270
jardineb5d44e2003-12-23 08:09:43 +00001271 /* Area addresses */
1272 if (lsp->tlv_data.area_addrs == NULL)
1273 lsp->tlv_data.area_addrs = list_new ();
1274 list_add_list (lsp->tlv_data.area_addrs, area->area_addrs);
1275 /* Protocols Supported */
hassof390d2c2004-09-10 20:48:21 +00001276 if (area->ip_circuits > 0
jardineb5d44e2003-12-23 08:09:43 +00001277#ifdef HAVE_IPV6
1278 || area->ipv6_circuits > 0
1279#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +00001280 )
jardineb5d44e2003-12-23 08:09:43 +00001281 {
hassoaac372f2005-09-01 17:52:33 +00001282 lsp->tlv_data.nlpids = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct nlpids));
jardineb5d44e2003-12-23 08:09:43 +00001283 lsp->tlv_data.nlpids->count = 0;
hassof390d2c2004-09-10 20:48:21 +00001284 if (area->ip_circuits > 0)
1285 {
1286 lsp->tlv_data.nlpids->count++;
1287 lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP;
1288 }
jardineb5d44e2003-12-23 08:09:43 +00001289#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001290 if (area->ipv6_circuits > 0)
1291 {
1292 lsp->tlv_data.nlpids->count++;
1293 lsp->tlv_data.nlpids->nlpids[lsp->tlv_data.nlpids->count - 1] =
1294 NLPID_IPV6;
1295 }
jardineb5d44e2003-12-23 08:09:43 +00001296#endif /* HAVE_IPV6 */
1297 }
1298 /* Dynamic Hostname */
hassof390d2c2004-09-10 20:48:21 +00001299 if (area->dynhostname)
1300 {
1301 lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV,
1302 sizeof (struct hostname));
jardin9e867fe2003-12-23 08:56:18 +00001303
hassof390d2c2004-09-10 20:48:21 +00001304 memcpy (lsp->tlv_data.hostname->name, unix_hostname (),
1305 strlen (unix_hostname ()));
1306 lsp->tlv_data.hostname->namelen = strlen (unix_hostname ());
1307 }
jardineb5d44e2003-12-23 08:09:43 +00001308
1309 /*
1310 * Building the zero lsp
1311 */
hassoaac372f2005-09-01 17:52:33 +00001312
1313 /* Reset stream endp. Stream is always there and on every LSP refresh only
1314 * TLV part of it is overwritten. So we must seek past header we will not
1315 * touch. */
hassoc89c05d2005-09-04 21:36:36 +00001316 stream_reset (lsp->pdu);
hassoaac372f2005-09-01 17:52:33 +00001317 stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
1318
jardineb5d44e2003-12-23 08:09:43 +00001319 /*
1320 * Add the authentication info if its present
1321 */
hassof390d2c2004-09-10 20:48:21 +00001322 (level == 1) ? (passwd = &area->area_passwd) :
1323 (passwd = &area->domain_passwd);
1324 if (passwd->type)
1325 {
1326 memcpy (&lsp->tlv_data.auth_info, passwd, sizeof (struct isis_passwd));
1327 tlv_add_authinfo (passwd->type, passwd->len, passwd->passwd, lsp->pdu);
1328 }
jardineb5d44e2003-12-23 08:09:43 +00001329 if (lsp->tlv_data.nlpids)
1330 tlv_add_nlpid (lsp->tlv_data.nlpids, lsp->pdu);
1331 if (lsp->tlv_data.hostname)
1332 tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu);
hassof390d2c2004-09-10 20:48:21 +00001333 if (lsp->tlv_data.area_addrs && listcount (lsp->tlv_data.area_addrs) > 0)
jardineb5d44e2003-12-23 08:09:43 +00001334 tlv_add_area_addrs (lsp->tlv_data.area_addrs, lsp->pdu);
hassof390d2c2004-09-10 20:48:21 +00001335
jardineb5d44e2003-12-23 08:09:43 +00001336 memset (&tlv_data, 0, sizeof (struct tlvs));
1337 /*
hasso18a6dce2004-10-03 18:18:34 +00001338 * IPv4 address TLV. We don't follow "C" vendor, but "J" vendor behavior -
1339 * one IPv4 address is put into LSP and this address is same as router id.
1340 */
1341 if (router_id_zebra.s_addr != 0)
1342 {
hasso18a6dce2004-10-03 18:18:34 +00001343 if (lsp->tlv_data.ipv4_addrs == NULL)
hassobe7d65d2005-09-02 01:38:16 +00001344 {
1345 lsp->tlv_data.ipv4_addrs = list_new ();
1346 lsp->tlv_data.ipv4_addrs->del = free_tlv;
1347 }
hasso18a6dce2004-10-03 18:18:34 +00001348
1349 routerid = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct in_addr));
1350 routerid->s_addr = router_id_zebra.s_addr;
1351
1352 listnode_add (lsp->tlv_data.ipv4_addrs, routerid);
1353
1354 /*
1355 * FIXME: Using add_tlv() directly is hack, but tlv_add_ip_addrs()
1356 * expects list of prefix_ipv4 structures, but we have list of
1357 * in_addr structures.
1358 */
1359 add_tlv (IPV4_ADDR, IPV4_MAX_BYTELEN, (u_char *) &routerid->s_addr,
1360 lsp->pdu);
1361 }
hassof1082d12005-09-19 04:23:34 +00001362
1363#ifdef TOPOLOGY_GENERATE
1364 /* If topology exists (and we create topology for level 1 only), create
1365 * (hardcoded) link to topology. */
1366 if (area->topology && level == 1)
1367 {
1368 if (tlv_data.is_neighs == NULL)
1369 tlv_data.is_neighs = list_new ();
1370 is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1371 memset (is_neigh, 0, sizeof (struct is_neigh));
1372
1373 memcpy (&is_neigh->neigh_id, area->topology_baseis, ISIS_SYS_ID_LEN);
1374 is_neigh->neigh_id[ISIS_SYS_ID_LEN - 1] = (1 & 0xFF);
1375 is_neigh->neigh_id[ISIS_SYS_ID_LEN - 2] = ((1 >> 8) & 0xFF);
1376 is_neigh->metrics.metric_default = 0x01;
1377 is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
1378 is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
1379 is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
1380 listnode_add (tlv_data.is_neighs, is_neigh);
1381 }
1382#endif /* TOPOLOGY_GENERATE */
1383
hasso18a6dce2004-10-03 18:18:34 +00001384 /*
jardineb5d44e2003-12-23 08:09:43 +00001385 * Then build lists of tlvs related to circuits
1386 */
paul1eb8ef22005-04-07 07:30:20 +00001387 for (ALL_LIST_ELEMENTS (area->circuit_list, node, nnode, circuit))
hassof390d2c2004-09-10 20:48:21 +00001388 {
hassof390d2c2004-09-10 20:48:21 +00001389 if (circuit->state != C_STATE_UP)
1390 continue;
jardineb5d44e2003-12-23 08:09:43 +00001391
hassof390d2c2004-09-10 20:48:21 +00001392 /*
1393 * Add IPv4 internal reachability of this circuit
1394 */
1395 if (circuit->ip_router && circuit->ip_addrs &&
1396 circuit->ip_addrs->count > 0)
1397 {
1398 if (tlv_data.ipv4_int_reachs == NULL)
1399 {
1400 tlv_data.ipv4_int_reachs = list_new ();
hassobe7d65d2005-09-02 01:38:16 +00001401 tlv_data.ipv4_int_reachs->del = free_tlv;
hassof390d2c2004-09-10 20:48:21 +00001402 }
paul1eb8ef22005-04-07 07:30:20 +00001403 for (ALL_LIST_ELEMENTS (circuit->ip_addrs, ipnode, ipnnode, ipv4))
hassof390d2c2004-09-10 20:48:21 +00001404 {
hassof390d2c2004-09-10 20:48:21 +00001405 ipreach =
hassoaac372f2005-09-01 17:52:33 +00001406 XCALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv4_reachability));
hassof390d2c2004-09-10 20:48:21 +00001407 ipreach->metrics = circuit->metrics[level - 1];
hassof390d2c2004-09-10 20:48:21 +00001408 masklen2ip (ipv4->prefixlen, &ipreach->mask);
hasso67851572004-09-21 14:17:04 +00001409 ipreach->prefix.s_addr = ((ipreach->mask.s_addr) &
1410 (ipv4->prefix.s_addr));
hassof390d2c2004-09-10 20:48:21 +00001411 listnode_add (tlv_data.ipv4_int_reachs, ipreach);
1412 }
1413
1414 }
jardineb5d44e2003-12-23 08:09:43 +00001415#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001416 /*
1417 * Add IPv6 reachability of this circuit
1418 */
1419 if (circuit->ipv6_router && circuit->ipv6_non_link &&
1420 circuit->ipv6_non_link->count > 0)
1421 {
1422
1423 if (tlv_data.ipv6_reachs == NULL)
1424 {
1425 tlv_data.ipv6_reachs = list_new ();
hassobe7d65d2005-09-02 01:38:16 +00001426 tlv_data.ipv6_reachs->del = free_tlv;
hassof390d2c2004-09-10 20:48:21 +00001427 }
paul1eb8ef22005-04-07 07:30:20 +00001428 for (ALL_LIST_ELEMENTS (circuit->ipv6_non_link, ipnode, ipnnode,
1429 ipv6))
hassof390d2c2004-09-10 20:48:21 +00001430 {
hassof390d2c2004-09-10 20:48:21 +00001431 ip6reach =
hassoaac372f2005-09-01 17:52:33 +00001432 XCALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv6_reachability));
hassof390d2c2004-09-10 20:48:21 +00001433 ip6reach->metric =
1434 htonl (circuit->metrics[level - 1].metric_default);
1435 ip6reach->control_info = 0;
1436 ip6reach->prefix_len = ipv6->prefixlen;
hasso67851572004-09-21 14:17:04 +00001437 memcpy (&ip6prefix, &ipv6, sizeof(ip6prefix));
1438 apply_mask_ipv6 (ip6prefix);
1439 memcpy (ip6reach->prefix, ip6prefix->prefix.s6_addr,
1440 sizeof (ip6reach->prefix));
hassof390d2c2004-09-10 20:48:21 +00001441 listnode_add (tlv_data.ipv6_reachs, ip6reach);
1442 }
1443 }
1444#endif /* HAVE_IPV6 */
1445
1446 switch (circuit->circ_type)
1447 {
1448 case CIRCUIT_T_BROADCAST:
1449 if (level & circuit->circuit_is_type)
1450 {
1451 if (tlv_data.is_neighs == NULL)
1452 {
1453 tlv_data.is_neighs = list_new ();
hassobe7d65d2005-09-02 01:38:16 +00001454 tlv_data.is_neighs->del = free_tlv;
hassof390d2c2004-09-10 20:48:21 +00001455 }
hassoaac372f2005-09-01 17:52:33 +00001456 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
hassof390d2c2004-09-10 20:48:21 +00001457 if (level == 1)
1458 memcpy (is_neigh->neigh_id,
1459 circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
1460 else
1461 memcpy (is_neigh->neigh_id,
1462 circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
1463 is_neigh->metrics = circuit->metrics[level - 1];
1464 listnode_add (tlv_data.is_neighs, is_neigh);
1465 }
1466 break;
1467 case CIRCUIT_T_P2P:
1468 nei = circuit->u.p2p.neighbor;
1469 if (nei && (level & nei->circuit_t))
1470 {
1471 if (tlv_data.is_neighs == NULL)
1472 {
1473 tlv_data.is_neighs = list_new ();
1474 tlv_data.is_neighs->del = free_tlv;
1475 }
hassoaac372f2005-09-01 17:52:33 +00001476 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
hassof390d2c2004-09-10 20:48:21 +00001477 memcpy (is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN);
1478 is_neigh->metrics = circuit->metrics[level - 1];
1479 listnode_add (tlv_data.is_neighs, is_neigh);
1480 }
1481 break;
1482 case CIRCUIT_T_STATIC_IN:
1483 zlog_warn ("lsp_area_create: unsupported circuit type");
1484 break;
1485 case CIRCUIT_T_STATIC_OUT:
1486 zlog_warn ("lsp_area_create: unsupported circuit type");
1487 break;
1488 case CIRCUIT_T_DA:
1489 zlog_warn ("lsp_area_create: unsupported circuit type");
1490 break;
1491 default:
1492 zlog_warn ("lsp_area_create: unknown circuit type");
1493 }
1494 }
1495
1496 while (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs))
1497 {
1498 if (lsp->tlv_data.ipv4_int_reachs == NULL)
1499 lsp->tlv_data.ipv4_int_reachs = list_new ();
1500 lsp_tlv_fit (lsp, &tlv_data.ipv4_int_reachs,
1501 &lsp->tlv_data.ipv4_int_reachs,
1502 IPV4_REACH_LEN, area->lsp_frag_threshold,
1503 tlv_add_ipv4_reachs);
1504 if (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs))
1505 lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
1506 lsp0, area, level);
1507 }
1508
1509#ifdef HAVE_IPV6
1510 while (tlv_data.ipv6_reachs && listcount (tlv_data.ipv6_reachs))
1511 {
1512 if (lsp->tlv_data.ipv6_reachs == NULL)
1513 lsp->tlv_data.ipv6_reachs = list_new ();
1514 lsp_tlv_fit (lsp, &tlv_data.ipv6_reachs,
1515 &lsp->tlv_data.ipv6_reachs,
1516 IPV6_REACH_LEN, area->lsp_frag_threshold,
1517 tlv_add_ipv6_reachs);
1518 if (tlv_data.ipv6_reachs && listcount (tlv_data.ipv6_reachs))
1519 lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
1520 lsp0, area, level);
jardineb5d44e2003-12-23 08:09:43 +00001521 }
1522#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +00001523
1524 while (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
1525 {
1526 if (lsp->tlv_data.is_neighs == NULL)
1527 lsp->tlv_data.is_neighs = list_new ();
1528 lsp_tlv_fit (lsp, &tlv_data.is_neighs,
1529 &lsp->tlv_data.is_neighs,
1530 IS_NEIGHBOURS_LEN, area->lsp_frag_threshold,
1531 tlv_add_is_neighs);
1532 if (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
1533 lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
1534 lsp0, area, level);
jardineb5d44e2003-12-23 08:09:43 +00001535 }
jardineb5d44e2003-12-23 08:09:43 +00001536
jardineb5d44e2003-12-23 08:09:43 +00001537 return;
1538}
1539#endif
1540
hasso92365882005-01-18 13:53:33 +00001541#if 0 /* Old code? */
1542static void
jardineb5d44e2003-12-23 08:09:43 +00001543build_lsp_data (struct isis_lsp *lsp, struct isis_area *area)
1544{
1545 struct list *circuit_list = area->circuit_list;
1546 struct isis_circuit *circuit;
1547 u_char *tlv_ptr;
1548 struct is_neigh *is_neigh;
1549
hassof390d2c2004-09-10 20:48:21 +00001550
jardineb5d44e2003-12-23 08:09:43 +00001551 /* add our nlpids */
hassof390d2c2004-09-10 20:48:21 +00001552 /* the 2 is for the TL plus 1 for the nlpid */
1553 tlv_ptr = lsppdu_realloc (lsp, MTYPE_ISIS_TLV, 3);
1554 *tlv_ptr = PROTOCOLS_SUPPORTED; /* Type */
1555 *(tlv_ptr + 1) = 1; /* one protocol */
1556#ifdef HAVE_IPV6 /*dunno if its right */
1557 *(tlv_ptr + 2) = NLPID_IPV6;
jardineb5d44e2003-12-23 08:09:43 +00001558#else
hassof390d2c2004-09-10 20:48:21 +00001559 *(tlv_ptr + 2) = NLPID_IP;
jardineb5d44e2003-12-23 08:09:43 +00001560#endif /* HAVE_IPV6 */
1561
1562 /* we should add our areas here
1563 * FIXME: we need to figure out which should be added? Adj? All? First? */
1564
1565 /* first, lets add ourselves to the IS neighbours info */
hassof390d2c2004-09-10 20:48:21 +00001566 /* the 2 is for the TL plus 1 for the virtual field */
1567 tlv_ptr = lsppdu_realloc (lsp, MTYPE_ISIS_TLV, 3);
1568 *tlv_ptr = IS_NEIGHBOURS; /* Type */
1569 *(tlv_ptr + 2) = 0; /* virtual is zero */
1570 lsp->tlv_data.is_neighs = list_new (); /* new list of is_neighbours */
jardineb5d44e2003-12-23 08:09:43 +00001571 /* assign space for the is_neigh at the pdu end */
hassof390d2c2004-09-10 20:48:21 +00001572 is_neigh = (struct is_neigh *) lsppdu_realloc (lsp, MTYPE_ISIS_TLV,
1573 sizeof (struct is_neigh));
jardineb5d44e2003-12-23 08:09:43 +00001574 /* add this node to our list */
hassof390d2c2004-09-10 20:48:21 +00001575 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
jardineb5d44e2003-12-23 08:09:43 +00001576 /* FIXME: Do we need our designated address here? */
hassof390d2c2004-09-10 20:48:21 +00001577 memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN + 1);
jardineb5d44e2003-12-23 08:09:43 +00001578 /* FIXME: Where should we really get our own LSPs metrics from? */
hassof390d2c2004-09-10 20:48:21 +00001579 circuit = (struct isis_circuit *) listhead (circuit_list);
1580 /* is_neigh->metrics = circuit->metrics[lsp->level -1]; */
jardineb5d44e2003-12-23 08:09:43 +00001581 /* Length */
hassof390d2c2004-09-10 20:48:21 +00001582 *(tlv_ptr + 1) =
1583 (lsp->tlv_data.is_neighs->count * sizeof (struct is_neigh) + 1);
jardineb5d44e2003-12-23 08:09:43 +00001584
1585 /* FIXME: scan for adjencecies and add them */
1586
1587 /* FIXME: add reachability info */
1588
hassof390d2c2004-09-10 20:48:21 +00001589 /* adding dynamic hostname if needed */
1590 if (area->dynhostname)
1591 {
1592 tlv_ptr = lsppdu_realloc (lsp, MTYPE_ISIS_TLV, 2); /* the 2 is for the TL */
1593 *tlv_ptr = DYNAMIC_HOSTNAME; /* Type */
1594 *(tlv_ptr + 1) = strlen (unix_hostname ()); /* Length */
1595 lsp->tlv_data.hostname = (struct hostname *)
1596 (lsppdu_realloc (lsp, MTYPE_ISIS_TLV,
1597 /* the -1 is to fit the length in the struct */
1598 strlen (unix_hostname ())) - 1);
1599 memcpy (lsp->tlv_data.hostname->name, unix_hostname (),
1600 strlen (unix_hostname ()));
1601 }
jardineb5d44e2003-12-23 08:09:43 +00001602
1603}
hasso92365882005-01-18 13:53:33 +00001604#endif /* 0 */
jardineb5d44e2003-12-23 08:09:43 +00001605
1606/*
1607 * 7.3.7 Generation on non-pseudonode LSPs
1608 */
hasso92365882005-01-18 13:53:33 +00001609static int
hassof390d2c2004-09-10 20:48:21 +00001610lsp_generate_non_pseudo (struct isis_area *area, int level)
1611{
jardineb5d44e2003-12-23 08:09:43 +00001612 struct isis_lsp *oldlsp, *newlsp;
1613 u_int32_t seq_num = 0;
1614 u_char lspid[ISIS_SYS_ID_LEN + 2];
1615
1616 memset (&lspid, 0, ISIS_SYS_ID_LEN + 2);
1617 memcpy (&lspid, isis->sysid, ISIS_SYS_ID_LEN);
1618
1619 /* only builds the lsp if the area shares the level */
hassof390d2c2004-09-10 20:48:21 +00001620 if ((area->is_type & level) == level)
1621 {
1622 oldlsp = lsp_search (lspid, area->lspdb[level - 1]);
1623 if (oldlsp)
1624 {
1625 seq_num = ntohl (oldlsp->lsp_header->seq_num);
1626 lsp_search_and_destroy (oldlsp->lsp_header->lsp_id,
1627 area->lspdb[level - 1]);
1628 /* FIXME: we should actually initiate a purge */
1629 }
1630 newlsp = lsp_new (lspid, area->max_lsp_lifetime[level - 1], seq_num,
1631 area->is_type, 0, level);
1632 newlsp->own_lsp = 1;
jardineb5d44e2003-12-23 08:09:43 +00001633
hassof390d2c2004-09-10 20:48:21 +00001634 lsp_insert (newlsp, area->lspdb[level - 1]);
1635 /* build_lsp_data (newlsp, area); */
1636 lsp_build_nonpseudo (newlsp, area);
1637 /* time to calculate our checksum */
1638 lsp_seqnum_update (newlsp);
1639 }
jardineb5d44e2003-12-23 08:09:43 +00001640
1641 /* DEBUG_ADJ_PACKETS */
hassof390d2c2004-09-10 20:48:21 +00001642 if (isis->debugs & DEBUG_ADJ_PACKETS)
1643 {
1644 /* FIXME: is this place right? fix missing info */
hasso529d65b2004-12-24 00:14:50 +00001645 zlog_debug ("ISIS-Upd (%s): Building L%d LSP", area->area_tag, level);
hassof390d2c2004-09-10 20:48:21 +00001646 }
jardineb5d44e2003-12-23 08:09:43 +00001647
1648 return ISIS_OK;
1649}
1650
1651/*
1652 * 7.3.9 Generation of level 1 LSPs (non-pseudonode)
1653 */
1654int
1655lsp_l1_generate (struct isis_area *area)
1656{
hassof390d2c2004-09-10 20:48:21 +00001657 THREAD_TIMER_ON (master, area->t_lsp_refresh[0], lsp_refresh_l1, area,
1658 MAX_LSP_GEN_INTERVAL);
jardineb5d44e2003-12-23 08:09:43 +00001659
1660 return lsp_generate_non_pseudo (area, 1);
1661}
1662
jardineb5d44e2003-12-23 08:09:43 +00001663/*
1664 * 7.3.9 Generation of level 2 LSPs (non-pseudonode)
1665 */
1666int
1667lsp_l2_generate (struct isis_area *area)
1668{
hassof390d2c2004-09-10 20:48:21 +00001669 THREAD_TIMER_ON (master, area->t_lsp_refresh[1], lsp_refresh_l2, area,
1670 MAX_LSP_GEN_INTERVAL);
jardineb5d44e2003-12-23 08:09:43 +00001671
1672 return lsp_generate_non_pseudo (area, 2);
1673}
1674
hasso92365882005-01-18 13:53:33 +00001675static int
jardineb5d44e2003-12-23 08:09:43 +00001676lsp_non_pseudo_regenerate (struct isis_area *area, int level)
1677{
1678 dict_t *lspdb = area->lspdb[level - 1];
1679 struct isis_lsp *lsp, *frag;
1680 struct listnode *node;
1681 u_char lspid[ISIS_SYS_ID_LEN + 2];
1682
1683 memset (lspid, 0, ISIS_SYS_ID_LEN + 2);
1684 memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN);
hassof390d2c2004-09-10 20:48:21 +00001685
jardineb5d44e2003-12-23 08:09:43 +00001686 lsp = lsp_search (lspid, lspdb);
jardineb5d44e2003-12-23 08:09:43 +00001687
hassof390d2c2004-09-10 20:48:21 +00001688 if (!lsp)
1689 {
1690 zlog_err
1691 ("ISIS-Upd (%s): lsp_non_pseudo_regenerate(): no L%d LSP found!",
1692 area->area_tag, level);
jardineb5d44e2003-12-23 08:09:43 +00001693
hassof390d2c2004-09-10 20:48:21 +00001694 return ISIS_ERROR;
1695 }
1696
1697 lsp_clear_data (lsp);
jardineb5d44e2003-12-23 08:09:43 +00001698 lsp_build_nonpseudo (lsp, area);
hassof390d2c2004-09-10 20:48:21 +00001699 lsp->lsp_header->rem_lifetime = htons (isis_jitter
1700 (area->max_lsp_lifetime[level - 1],
1701 MAX_AGE_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00001702 lsp_seqnum_update (lsp);
hassof390d2c2004-09-10 20:48:21 +00001703
1704 if (isis->debugs & DEBUG_UPDATE_PACKETS)
1705 {
hasso529d65b2004-12-24 00:14:50 +00001706 zlog_debug ("ISIS-Upd (%s): refreshing our L%d LSP %s, "
1707 "seq 0x%08x, cksum 0x%04x lifetime %us",
1708 area->area_tag,
1709 level,
1710 rawlspid_print (lsp->lsp_header->lsp_id),
1711 ntohl (lsp->lsp_header->seq_num),
1712 ntohs (lsp->lsp_header->checksum),
1713 ntohs (lsp->lsp_header->rem_lifetime));
hassof390d2c2004-09-10 20:48:21 +00001714 }
jardineb5d44e2003-12-23 08:09:43 +00001715
1716 lsp->last_generated = time (NULL);
1717 area->lsp_regenerate_pending[level - 1] = 0;
1718 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
paul1eb8ef22005-04-07 07:30:20 +00001719 for (ALL_LIST_ELEMENTS_RO (lsp->lspu.frags, node, frag))
hassof390d2c2004-09-10 20:48:21 +00001720 {
hassof390d2c2004-09-10 20:48:21 +00001721 frag->lsp_header->rem_lifetime = htons (isis_jitter
1722 (area->
1723 max_lsp_lifetime[level - 1],
1724 MAX_AGE_JITTER));
1725 ISIS_FLAGS_SET_ALL (frag->SRMflags);
1726 }
jardineb5d44e2003-12-23 08:09:43 +00001727
1728 if (area->ip_circuits)
1729 isis_spf_schedule (area, level);
1730#ifdef HAVE_IPV6
1731 if (area->ipv6_circuits)
1732 isis_spf_schedule6 (area, level);
1733#endif
1734 return ISIS_OK;
1735}
1736
jardineb5d44e2003-12-23 08:09:43 +00001737/*
1738 * Done at least every MAX_LSP_GEN_INTERVAL. Search own LSPs, update holding
1739 * time and set SRM
1740 */
hassof390d2c2004-09-10 20:48:21 +00001741int
jardineb5d44e2003-12-23 08:09:43 +00001742lsp_refresh_l1 (struct thread *thread)
1743{
1744 struct isis_area *area;
1745 unsigned long ref_time;
1746
1747 area = THREAD_ARG (thread);
1748 assert (area);
hassof390d2c2004-09-10 20:48:21 +00001749
jardineb5d44e2003-12-23 08:09:43 +00001750 area->t_lsp_refresh[0] = NULL;
hassof390d2c2004-09-10 20:48:21 +00001751 if (area->is_type & IS_LEVEL_1)
jardineb5d44e2003-12-23 08:09:43 +00001752 lsp_non_pseudo_regenerate (area, 1);
hassof390d2c2004-09-10 20:48:21 +00001753
1754 ref_time = area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
jardineb5d44e2003-12-23 08:09:43 +00001755 MAX_LSP_GEN_INTERVAL : area->lsp_refresh[0];
1756
hassof390d2c2004-09-10 20:48:21 +00001757 THREAD_TIMER_ON (master, area->t_lsp_refresh[0], lsp_refresh_l1, area,
1758 isis_jitter (ref_time, MAX_AGE_JITTER));
hassod70f99e2004-02-11 20:26:31 +00001759
jardineb5d44e2003-12-23 08:09:43 +00001760 return ISIS_OK;
1761}
1762
hassof390d2c2004-09-10 20:48:21 +00001763int
jardineb5d44e2003-12-23 08:09:43 +00001764lsp_refresh_l2 (struct thread *thread)
1765{
1766 struct isis_area *area;
1767 unsigned long ref_time;
1768
1769 area = THREAD_ARG (thread);
1770 assert (area);
hassof390d2c2004-09-10 20:48:21 +00001771
jardineb5d44e2003-12-23 08:09:43 +00001772 area->t_lsp_refresh[1] = NULL;
hassof390d2c2004-09-10 20:48:21 +00001773 if (area->is_type & IS_LEVEL_2)
jardineb5d44e2003-12-23 08:09:43 +00001774 lsp_non_pseudo_regenerate (area, 2);
1775
hassof390d2c2004-09-10 20:48:21 +00001776 ref_time = area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ?
jardineb5d44e2003-12-23 08:09:43 +00001777 MAX_LSP_GEN_INTERVAL : area->lsp_refresh[1];
1778
hassof390d2c2004-09-10 20:48:21 +00001779 THREAD_TIMER_ON (master, area->t_lsp_refresh[1], lsp_refresh_l2, area,
1780 isis_jitter (ref_time, MAX_AGE_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00001781
jardineb5d44e2003-12-23 08:09:43 +00001782 return ISIS_OK;
1783}
1784
jardineb5d44e2003-12-23 08:09:43 +00001785/*
1786 * Something has changed -> regenerate LSP
1787 */
1788
hasso92365882005-01-18 13:53:33 +00001789static int
jardineb5d44e2003-12-23 08:09:43 +00001790lsp_l1_regenerate (struct thread *thread)
1791{
1792 struct isis_area *area;
1793
1794 area = THREAD_ARG (thread);
1795 area->lsp_regenerate_pending[0] = 0;
1796
1797 return lsp_non_pseudo_regenerate (area, 1);
1798}
1799
hasso92365882005-01-18 13:53:33 +00001800static int
jardineb5d44e2003-12-23 08:09:43 +00001801lsp_l2_regenerate (struct thread *thread)
1802{
1803 struct isis_area *area;
1804
1805 area = THREAD_ARG (thread);
1806 area->lsp_regenerate_pending[1] = 0;
hassof390d2c2004-09-10 20:48:21 +00001807
jardineb5d44e2003-12-23 08:09:43 +00001808 return lsp_non_pseudo_regenerate (area, 2);
1809}
1810
hassof390d2c2004-09-10 20:48:21 +00001811int
jardineb5d44e2003-12-23 08:09:43 +00001812lsp_regenerate_schedule (struct isis_area *area)
1813{
1814 struct isis_lsp *lsp;
1815 u_char id[ISIS_SYS_ID_LEN + 2];
1816 time_t now, diff;
hassof390d2c2004-09-10 20:48:21 +00001817 memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
1818 LSP_PSEUDO_ID (id) = LSP_FRAGMENT (id) = 0;
jardineb5d44e2003-12-23 08:09:43 +00001819 now = time (NULL);
1820 /*
1821 * First level 1
1822 */
hassof390d2c2004-09-10 20:48:21 +00001823 if (area->is_type & IS_LEVEL_1)
1824 {
1825 lsp = lsp_search (id, area->lspdb[0]);
1826 if (!lsp || area->lsp_regenerate_pending[0])
1827 goto L2;
1828 /*
1829 * Throttle avoidance
1830 */
1831 diff = now - lsp->last_generated;
1832 if (diff < MIN_LSP_GEN_INTERVAL)
1833 {
1834 area->lsp_regenerate_pending[0] = 1;
1835 thread_add_timer (master, lsp_l1_regenerate, area,
1836 MIN_LSP_GEN_INTERVAL - diff);
hasso12a5cae2004-09-19 19:39:26 +00001837 goto L2;
hassof390d2c2004-09-10 20:48:21 +00001838 }
1839 else
1840 lsp_non_pseudo_regenerate (area, 1);
1841 }
jardineb5d44e2003-12-23 08:09:43 +00001842 /*
1843 * then 2
1844 */
hassof390d2c2004-09-10 20:48:21 +00001845L2:
1846 if (area->is_type & IS_LEVEL_2)
1847 {
1848 lsp = lsp_search (id, area->lspdb[1]);
1849 if (!lsp || area->lsp_regenerate_pending[1])
1850 return ISIS_OK;
1851 /*
1852 * Throttle avoidance
1853 */
1854 diff = now - lsp->last_generated;
1855 if (diff < MIN_LSP_GEN_INTERVAL)
1856 {
1857 area->lsp_regenerate_pending[1] = 1;
1858 thread_add_timer (master, lsp_l2_regenerate, area,
1859 MIN_LSP_GEN_INTERVAL - diff);
1860 return ISIS_OK;
1861 }
1862 else
1863 lsp_non_pseudo_regenerate (area, 2);
1864 }
1865
1866 return ISIS_OK;
jardineb5d44e2003-12-23 08:09:43 +00001867}
1868
1869/*
1870 * Funcs for pseudonode LSPs
1871 */
1872
1873/*
1874 * 7.3.8 and 7.3.10 Generation of level 1 and 2 pseudonode LSPs
1875 */
hasso92365882005-01-18 13:53:33 +00001876static void
hassof390d2c2004-09-10 20:48:21 +00001877lsp_build_pseudo (struct isis_lsp *lsp, struct isis_circuit *circuit,
1878 int level)
jardineb5d44e2003-12-23 08:09:43 +00001879{
1880 struct isis_adjacency *adj;
1881 struct is_neigh *is_neigh;
1882 struct es_neigh *es_neigh;
1883 struct list *adj_list;
paul1eb8ef22005-04-07 07:30:20 +00001884 struct listnode *node, *nnode;
jardineb5d44e2003-12-23 08:09:43 +00001885 struct isis_passwd *passwd;
1886
1887 assert (circuit);
1888 assert (circuit->circ_type == CIRCUIT_T_BROADCAST);
hassof390d2c2004-09-10 20:48:21 +00001889
jardineb5d44e2003-12-23 08:09:43 +00001890 if (!circuit->u.bc.is_dr[level - 1])
hassof390d2c2004-09-10 20:48:21 +00001891 return; /* we are not DIS on this circuit */
1892
jardineb5d44e2003-12-23 08:09:43 +00001893 lsp->level = level;
1894 if (level == 1)
1895 lsp->lsp_header->lsp_bits |= IS_LEVEL_1;
1896 else
1897 lsp->lsp_header->lsp_bits |= IS_LEVEL_2;
1898
1899 /*
1900 * add self to IS neighbours
1901 */
hassof390d2c2004-09-10 20:48:21 +00001902 if (lsp->tlv_data.is_neighs == NULL)
1903 {
1904 lsp->tlv_data.is_neighs = list_new ();
1905 lsp->tlv_data.is_neighs->del = free_tlv;
1906 }
paul15935e92005-05-03 09:27:23 +00001907 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1908
jardineb5d44e2003-12-23 08:09:43 +00001909 memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
1910 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
hassof390d2c2004-09-10 20:48:21 +00001911
1912 adj_list = list_new ();
1913 isis_adj_build_up_list (circuit->u.bc.adjdb[level - 1], adj_list);
1914
paul1eb8ef22005-04-07 07:30:20 +00001915 for (ALL_LIST_ELEMENTS (adj_list, node, nnode, adj))
hassof390d2c2004-09-10 20:48:21 +00001916 {
hassof390d2c2004-09-10 20:48:21 +00001917 if (adj->circuit_t & level)
1918 {
1919 if ((level == 1 && adj->sys_type == ISIS_SYSTYPE_L1_IS) ||
1920 (level == 1 && adj->sys_type == ISIS_SYSTYPE_L2_IS &&
1921 adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
1922 (level == 2 && adj->sys_type == ISIS_SYSTYPE_L2_IS))
1923 {
1924 /* an IS neighbour -> add it */
paul15935e92005-05-03 09:27:23 +00001925 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1926
hassof390d2c2004-09-10 20:48:21 +00001927 memcpy (&is_neigh->neigh_id, adj->sysid, ISIS_SYS_ID_LEN);
1928 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
1929 }
1930 else if (level == 1 && adj->sys_type == ISIS_SYSTYPE_ES)
1931 {
1932 /* an ES neigbour add it, if we are building level 1 LSP */
1933 /* FIXME: the tlv-format is hard to use here */
1934 if (lsp->tlv_data.es_neighs == NULL)
1935 {
1936 lsp->tlv_data.es_neighs = list_new ();
1937 lsp->tlv_data.es_neighs->del = free_tlv;
1938 }
paul15935e92005-05-03 09:27:23 +00001939 es_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct es_neigh));
1940
hassof390d2c2004-09-10 20:48:21 +00001941 memcpy (&es_neigh->first_es_neigh, adj->sysid, ISIS_SYS_ID_LEN);
hassoaac372f2005-09-01 17:52:33 +00001942 listnode_add (lsp->tlv_data.es_neighs, es_neigh);
hassof390d2c2004-09-10 20:48:21 +00001943 }
1944 }
jardineb5d44e2003-12-23 08:09:43 +00001945 }
hassof390d2c2004-09-10 20:48:21 +00001946
hassoc0fb2a52005-09-03 16:29:40 +00001947 /* Reset endp of stream to overwrite only TLV part of it. */
hassoc89c05d2005-09-04 21:36:36 +00001948 stream_reset (lsp->pdu);
hassoc0fb2a52005-09-03 16:29:40 +00001949 stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
1950
jardineb5d44e2003-12-23 08:09:43 +00001951 /*
1952 * Add the authentication info if it's present
1953 */
hassof390d2c2004-09-10 20:48:21 +00001954 (level == 1) ? (passwd = &circuit->area->area_passwd) :
1955 (passwd = &circuit->area->domain_passwd);
1956 if (passwd->type)
1957 {
1958 memcpy (&lsp->tlv_data.auth_info, passwd, sizeof (struct isis_passwd));
1959 tlv_add_authinfo (passwd->type, passwd->len, passwd->passwd, lsp->pdu);
1960 }
jardineb5d44e2003-12-23 08:09:43 +00001961
1962 if (lsp->tlv_data.is_neighs && listcount (lsp->tlv_data.is_neighs) > 0)
1963 tlv_add_is_neighs (lsp->tlv_data.is_neighs, lsp->pdu);
1964
1965 if (lsp->tlv_data.es_neighs && listcount (lsp->tlv_data.es_neighs) > 0)
1966 tlv_add_is_neighs (lsp->tlv_data.es_neighs, lsp->pdu);
1967
paul9985f832005-02-09 15:51:56 +00001968 lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
hassof390d2c2004-09-10 20:48:21 +00001969 iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
1970 ntohs (lsp->lsp_header->pdu_len) - 12, 12);
1971
jardineb5d44e2003-12-23 08:09:43 +00001972 list_delete (adj_list);
1973
1974 return;
1975}
1976
hasso92365882005-01-18 13:53:33 +00001977static int
jardineb5d44e2003-12-23 08:09:43 +00001978lsp_pseudo_regenerate (struct isis_circuit *circuit, int level)
1979{
1980 dict_t *lspdb = circuit->area->lspdb[level - 1];
1981 struct isis_lsp *lsp;
1982 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
hassof390d2c2004-09-10 20:48:21 +00001983
jardineb5d44e2003-12-23 08:09:43 +00001984 memcpy (lsp_id, isis->sysid, ISIS_SYS_ID_LEN);
hassof390d2c2004-09-10 20:48:21 +00001985 LSP_PSEUDO_ID (lsp_id) = circuit->circuit_id;
1986 LSP_FRAGMENT (lsp_id) = 0;
1987
jardineb5d44e2003-12-23 08:09:43 +00001988 lsp = lsp_search (lsp_id, lspdb);
hassof390d2c2004-09-10 20:48:21 +00001989
1990 if (!lsp)
1991 {
1992 zlog_err ("lsp_pseudo_regenerate(): no l%d LSP %s found!", level,
1993 rawlspid_print (lsp_id));
1994 return ISIS_ERROR;
1995 }
1996 lsp_clear_data (lsp);
jardineb5d44e2003-12-23 08:09:43 +00001997
1998 lsp_build_pseudo (lsp, circuit, level);
1999
hassof390d2c2004-09-10 20:48:21 +00002000 lsp->lsp_header->rem_lifetime =
jardineb5d44e2003-12-23 08:09:43 +00002001 htons (isis_jitter (circuit->area->max_lsp_lifetime[level - 1],
hassof390d2c2004-09-10 20:48:21 +00002002 MAX_AGE_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00002003
2004 lsp_inc_seqnum (lsp, 0);
hassof390d2c2004-09-10 20:48:21 +00002005
2006 if (isis->debugs & DEBUG_UPDATE_PACKETS)
2007 {
hasso529d65b2004-12-24 00:14:50 +00002008 zlog_debug ("ISIS-Upd (%s): refreshing pseudo LSP L%d %s",
2009 circuit->area->area_tag, level,
2010 rawlspid_print (lsp->lsp_header->lsp_id));
hassof390d2c2004-09-10 20:48:21 +00002011 }
jardineb5d44e2003-12-23 08:09:43 +00002012
2013 lsp->last_generated = time (NULL);
2014 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
hassof390d2c2004-09-10 20:48:21 +00002015
jardineb5d44e2003-12-23 08:09:43 +00002016 return ISIS_OK;
2017}
2018
jardineb5d44e2003-12-23 08:09:43 +00002019int
2020lsp_l1_refresh_pseudo (struct thread *thread)
2021{
2022 struct isis_circuit *circuit;
2023 int retval;
2024 unsigned long ref_time;
2025
hassof390d2c2004-09-10 20:48:21 +00002026 circuit = THREAD_ARG (thread);
2027
jardineb5d44e2003-12-23 08:09:43 +00002028 if (!circuit->u.bc.is_dr[0])
hassof390d2c2004-09-10 20:48:21 +00002029 return ISIS_ERROR; /* FIXME: purge and such */
2030
hasso13c48f72004-09-10 21:19:13 +00002031 circuit->u.bc.t_refresh_pseudo_lsp[0] = NULL;
2032
jardineb5d44e2003-12-23 08:09:43 +00002033 retval = lsp_pseudo_regenerate (circuit, 1);
hassof390d2c2004-09-10 20:48:21 +00002034
2035 ref_time = circuit->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
jardineb5d44e2003-12-23 08:09:43 +00002036 MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[0];
2037
hassof390d2c2004-09-10 20:48:21 +00002038 THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[0],
2039 lsp_l1_refresh_pseudo, circuit,
2040 isis_jitter (ref_time, MAX_AGE_JITTER));
2041
jardineb5d44e2003-12-23 08:09:43 +00002042 return retval;
2043}
2044
hassof390d2c2004-09-10 20:48:21 +00002045int
jardineb5d44e2003-12-23 08:09:43 +00002046lsp_l1_pseudo_generate (struct isis_circuit *circuit)
2047{
2048 struct isis_lsp *lsp;
2049 u_char id[ISIS_SYS_ID_LEN + 2];
2050 unsigned long ref_time;
2051
hassof390d2c2004-09-10 20:48:21 +00002052 memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
2053 LSP_FRAGMENT (id) = 0;
2054 LSP_PSEUDO_ID (id) = circuit->circuit_id;
jardineb5d44e2003-12-23 08:09:43 +00002055
2056 /*
2057 * If for some reason have a pseudo LSP in the db already -> regenerate
2058 */
2059 if (lsp_search (id, circuit->area->lspdb[0]))
2060 return lsp_pseudo_regenerate (circuit, 1);
2061 lsp = lsp_new (id, circuit->area->max_lsp_lifetime[0],
hassof390d2c2004-09-10 20:48:21 +00002062 1, circuit->area->is_type, 0, 1);
2063
jardineb5d44e2003-12-23 08:09:43 +00002064 lsp_build_pseudo (lsp, circuit, 1);
hassof390d2c2004-09-10 20:48:21 +00002065
jardineb5d44e2003-12-23 08:09:43 +00002066 lsp->own_lsp = 1;
2067 lsp_insert (lsp, circuit->area->lspdb[0]);
2068 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
2069
hassof390d2c2004-09-10 20:48:21 +00002070 ref_time = circuit->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
jardineb5d44e2003-12-23 08:09:43 +00002071 MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[0];
2072
hassof390d2c2004-09-10 20:48:21 +00002073 THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[0],
2074 lsp_l1_refresh_pseudo, circuit,
2075 isis_jitter (ref_time, MAX_AGE_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00002076
2077 return lsp_regenerate_schedule (circuit->area);
2078}
2079
2080int
2081lsp_l2_refresh_pseudo (struct thread *thread)
2082{
2083 struct isis_circuit *circuit;
2084 int retval;
2085 unsigned long ref_time;
hassof390d2c2004-09-10 20:48:21 +00002086 circuit = THREAD_ARG (thread);
2087
jardineb5d44e2003-12-23 08:09:43 +00002088 if (!circuit->u.bc.is_dr[1])
hassof390d2c2004-09-10 20:48:21 +00002089 return ISIS_ERROR; /* FIXME: purge and such */
2090
hasso13c48f72004-09-10 21:19:13 +00002091 circuit->u.bc.t_refresh_pseudo_lsp[1] = NULL;
2092
jardineb5d44e2003-12-23 08:09:43 +00002093 retval = lsp_pseudo_regenerate (circuit, 2);
2094
hassof390d2c2004-09-10 20:48:21 +00002095 ref_time = circuit->area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ?
jardineb5d44e2003-12-23 08:09:43 +00002096 MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[1];
2097
hassof390d2c2004-09-10 20:48:21 +00002098 THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[1],
2099 lsp_l2_refresh_pseudo, circuit,
2100 isis_jitter (ref_time, MAX_AGE_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00002101
jardineb5d44e2003-12-23 08:09:43 +00002102 return retval;
2103}
2104
hassof390d2c2004-09-10 20:48:21 +00002105int
jardineb5d44e2003-12-23 08:09:43 +00002106lsp_l2_pseudo_generate (struct isis_circuit *circuit)
2107{
2108 struct isis_lsp *lsp;
2109 u_char id[ISIS_SYS_ID_LEN + 2];
2110 unsigned long ref_time;
2111
hassof390d2c2004-09-10 20:48:21 +00002112 memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
2113 LSP_FRAGMENT (id) = 0;
2114 LSP_PSEUDO_ID (id) = circuit->circuit_id;
jardineb5d44e2003-12-23 08:09:43 +00002115
2116 if (lsp_search (id, circuit->area->lspdb[1]))
2117 return lsp_pseudo_regenerate (circuit, 2);
2118
2119 lsp = lsp_new (id, circuit->area->max_lsp_lifetime[1],
hassof390d2c2004-09-10 20:48:21 +00002120 1, circuit->area->is_type, 0, 2);
jardineb5d44e2003-12-23 08:09:43 +00002121
2122 lsp_build_pseudo (lsp, circuit, 2);
hassof390d2c2004-09-10 20:48:21 +00002123
2124 ref_time = circuit->area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ?
jardineb5d44e2003-12-23 08:09:43 +00002125 MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[1];
2126
2127
2128 lsp->own_lsp = 1;
2129 lsp_insert (lsp, circuit->area->lspdb[1]);
2130 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
hassof390d2c2004-09-10 20:48:21 +00002131
2132 THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[1],
2133 lsp_l2_refresh_pseudo, circuit,
2134 isis_jitter (ref_time, MAX_AGE_JITTER));
2135
jardineb5d44e2003-12-23 08:09:43 +00002136 return lsp_regenerate_schedule (circuit->area);
2137}
2138
jardineb5d44e2003-12-23 08:09:43 +00002139/*
2140 * Walk through LSPs for an area
2141 * - set remaining lifetime
2142 * - set LSPs with SRMflag set for sending
2143 */
hassof390d2c2004-09-10 20:48:21 +00002144int
jardineb5d44e2003-12-23 08:09:43 +00002145lsp_tick (struct thread *thread)
2146{
2147 struct isis_area *area;
2148 struct isis_circuit *circuit;
2149 struct isis_lsp *lsp;
2150 struct list *lsp_list;
paul1eb8ef22005-04-07 07:30:20 +00002151 struct listnode *lspnode, *lspnnode, *cnode;
jardineb5d44e2003-12-23 08:09:43 +00002152 dnode_t *dnode, *dnode_next;
2153 int level;
2154
2155 lsp_list = list_new ();
hassof390d2c2004-09-10 20:48:21 +00002156
jardineb5d44e2003-12-23 08:09:43 +00002157 area = THREAD_ARG (thread);
2158 assert (area);
hasso13c48f72004-09-10 21:19:13 +00002159 area->t_tick = NULL;
hassof390d2c2004-09-10 20:48:21 +00002160 THREAD_TIMER_ON (master, area->t_tick, lsp_tick, area, 1);
jardineb5d44e2003-12-23 08:09:43 +00002161
2162 /*
2163 * Build a list of LSPs with (any) SRMflag set
2164 * and removed the ones that have aged out
2165 */
hassof390d2c2004-09-10 20:48:21 +00002166 for (level = 0; level < ISIS_LEVELS; level++)
2167 {
2168 if (area->lspdb[level] && dict_count (area->lspdb[level]) > 0)
2169 {
2170 dnode = dict_first (area->lspdb[level]);
2171 while (dnode != NULL)
2172 {
2173 dnode_next = dict_next (area->lspdb[level], dnode);
2174 lsp = dnode_get (dnode);
2175 lsp_set_time (lsp);
2176 if (lsp->age_out == 0)
2177 {
jardineb5d44e2003-12-23 08:09:43 +00002178
hasso529d65b2004-12-24 00:14:50 +00002179 zlog_debug ("ISIS-Upd (%s): L%u LSP %s seq 0x%08x aged out",
2180 area->area_tag,
2181 lsp->level,
2182 rawlspid_print (lsp->lsp_header->lsp_id),
2183 ntohl (lsp->lsp_header->seq_num));
hassof1082d12005-09-19 04:23:34 +00002184#ifdef TOPOLOGY_GENERATE
2185 if (lsp->from_topology)
2186 THREAD_TIMER_OFF (lsp->t_lsp_top_ref);
2187#endif /* TOPOLOGY_GENERATE */
hassof390d2c2004-09-10 20:48:21 +00002188 lsp_destroy (lsp);
2189 dict_delete (area->lspdb[level], dnode);
2190 }
2191 else if (flags_any_set (lsp->SRMflags))
2192 listnode_add (lsp_list, lsp);
2193 dnode = dnode_next;
2194 }
jardineb5d44e2003-12-23 08:09:43 +00002195
hassof390d2c2004-09-10 20:48:21 +00002196 /*
2197 * Send LSPs on circuits indicated by the SRMflags
2198 */
2199 if (listcount (lsp_list) > 0)
2200 {
paul1eb8ef22005-04-07 07:30:20 +00002201 for (ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit))
hassof390d2c2004-09-10 20:48:21 +00002202 {
paul1eb8ef22005-04-07 07:30:20 +00002203 for (ALL_LIST_ELEMENTS (lsp_list, lspnode, lspnnode, lsp))
hassof390d2c2004-09-10 20:48:21 +00002204 {
hassof390d2c2004-09-10 20:48:21 +00002205 if (ISIS_CHECK_FLAG (lsp->SRMflags, circuit))
2206 {
2207 /* FIXME: if same or elder lsp is already in lsp
2208 * queue */
2209 listnode_add (circuit->lsp_queue, lsp);
2210 thread_add_event (master, send_lsp, circuit, 0);
2211 }
2212 }
2213 }
2214 }
2215 list_delete_all_node (lsp_list);
2216 }
jardineb5d44e2003-12-23 08:09:43 +00002217 }
jardineb5d44e2003-12-23 08:09:43 +00002218
2219 list_delete (lsp_list);
2220
2221 return ISIS_OK;
2222}
2223
jardineb5d44e2003-12-23 08:09:43 +00002224void
hassof390d2c2004-09-10 20:48:21 +00002225lsp_purge_dr (u_char * id, struct isis_circuit *circuit, int level)
jardineb5d44e2003-12-23 08:09:43 +00002226{
2227 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +00002228
jardineb5d44e2003-12-23 08:09:43 +00002229 lsp = lsp_search (id, circuit->area->lspdb[level - 1]);
hassof390d2c2004-09-10 20:48:21 +00002230
2231 if (lsp && lsp->purged == 0)
2232 {
2233 lsp->lsp_header->rem_lifetime = htons (0);
2234 lsp->lsp_header->pdu_len =
2235 htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
2236 lsp->purged = 0;
2237 iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
2238 ntohs (lsp->lsp_header->pdu_len) - 12, 12);
2239 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
2240 }
2241
jardineb5d44e2003-12-23 08:09:43 +00002242 return;
2243}
2244
2245/*
2246 * Purge own LSP that is received and we don't have.
2247 * -> Do as in 7.3.16.4
2248 */
2249void
hassof390d2c2004-09-10 20:48:21 +00002250lsp_purge_non_exist (struct isis_link_state_hdr *lsp_hdr,
2251 struct isis_area *area)
jardineb5d44e2003-12-23 08:09:43 +00002252{
2253 struct isis_lsp *lsp;
2254
2255 /*
2256 * We need to create the LSP to be purged
2257 */
hasso529d65b2004-12-24 00:14:50 +00002258 zlog_debug ("LSP PURGE NON EXIST");
hassoaac372f2005-09-01 17:52:33 +00002259 lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
hassof390d2c2004-09-10 20:48:21 +00002260 /*FIXME: BUG BUG BUG! the lsp doesn't exist here! */
2261 /*did smt here, maybe good probably not */
jardineb5d44e2003-12-23 08:09:43 +00002262 lsp->level = ((lsp_hdr->lsp_bits & LSPBIT_IST) == IS_LEVEL_1) ? 1 : 2;
2263 lsp->pdu = stream_new (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
hassof390d2c2004-09-10 20:48:21 +00002264 lsp->isis_header = (struct isis_fixed_hdr *) STREAM_DATA (lsp->pdu);
jardineb5d44e2003-12-23 08:09:43 +00002265 fill_fixed_hdr (lsp->isis_header, (lsp->level == 1) ? L1_LINK_STATE
hassof390d2c2004-09-10 20:48:21 +00002266 : L2_LINK_STATE);
2267 lsp->lsp_header = (struct isis_link_state_hdr *) (STREAM_DATA (lsp->pdu) +
2268 ISIS_FIXED_HDR_LEN);
jardineb5d44e2003-12-23 08:09:43 +00002269 memcpy (lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN);
hassof390d2c2004-09-10 20:48:21 +00002270
jardineb5d44e2003-12-23 08:09:43 +00002271 /*
2272 * Retain only LSP header
2273 */
2274 lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
2275 /*
2276 * Set the remaining lifetime to 0
2277 */
2278 lsp->lsp_header->rem_lifetime = 0;
2279 /*
2280 * Put the lsp into LSPdb
2281 */
hassof390d2c2004-09-10 20:48:21 +00002282 lsp_insert (lsp, area->lspdb[lsp->level - 1]);
jardineb5d44e2003-12-23 08:09:43 +00002283
2284 /*
2285 * Send in to whole area
2286 */
2287 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
hassof390d2c2004-09-10 20:48:21 +00002288
jardineb5d44e2003-12-23 08:09:43 +00002289 return;
2290}
2291
2292#ifdef TOPOLOGY_GENERATE
hasso92365882005-01-18 13:53:33 +00002293static int
jardineb5d44e2003-12-23 08:09:43 +00002294top_lsp_refresh (struct thread *thread)
2295{
hassof390d2c2004-09-10 20:48:21 +00002296 struct isis_lsp *lsp;
hassof1082d12005-09-19 04:23:34 +00002297 unsigned long ref_time;
jardineb5d44e2003-12-23 08:09:43 +00002298
2299 lsp = THREAD_ARG (thread);
2300 assert (lsp);
2301
2302 lsp->t_lsp_top_ref = NULL;
2303
hassof1082d12005-09-19 04:23:34 +00002304 lsp_seqnum_update (lsp);
jardineb5d44e2003-12-23 08:09:43 +00002305
2306 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
hassof390d2c2004-09-10 20:48:21 +00002307 if (isis->debugs & DEBUG_UPDATE_PACKETS)
2308 {
hasso529d65b2004-12-24 00:14:50 +00002309 zlog_debug ("ISIS-Upd (): refreshing Topology L1 %s",
2310 rawlspid_print (lsp->lsp_header->lsp_id));
hassof390d2c2004-09-10 20:48:21 +00002311 }
hassof1082d12005-09-19 04:23:34 +00002312 lsp->lsp_header->rem_lifetime =
2313 htons (isis_jitter (lsp->area->max_lsp_lifetime[0], MAX_AGE_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00002314
hassof1082d12005-09-19 04:23:34 +00002315 ref_time = lsp->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
2316 MAX_LSP_GEN_INTERVAL : lsp->area->lsp_refresh[0];
2317
hassof390d2c2004-09-10 20:48:21 +00002318 THREAD_TIMER_ON (master, lsp->t_lsp_top_ref, top_lsp_refresh, lsp,
hassof1082d12005-09-19 04:23:34 +00002319 isis_jitter (ref_time, MAX_LSP_GEN_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00002320
2321 return ISIS_OK;
2322}
2323
2324void
2325generate_topology_lsps (struct isis_area *area)
2326{
2327 struct listnode *node;
2328 int i, max = 0;
2329 struct arc *arc;
2330 u_char lspid[ISIS_SYS_ID_LEN + 2];
2331 struct isis_lsp *lsp;
hassof1082d12005-09-19 04:23:34 +00002332 unsigned long ref_time;
jardineb5d44e2003-12-23 08:09:43 +00002333
2334 /* first we find the maximal node */
paula8f03df2005-04-10 15:58:10 +00002335 for (ALL_LIST_ELEMENTS_RO (area->topology, node, arc))
hassof390d2c2004-09-10 20:48:21 +00002336 {
2337 if (arc->from_node > max)
2338 max = arc->from_node;
2339 if (arc->to_node > max)
2340 max = arc->to_node;
jardineb5d44e2003-12-23 08:09:43 +00002341 }
2342
hassof390d2c2004-09-10 20:48:21 +00002343 for (i = 1; i < (max + 1); i++)
2344 {
2345 memcpy (lspid, area->topology_baseis, ISIS_SYS_ID_LEN);
2346 LSP_PSEUDO_ID (lspid) = 0x00;
2347 LSP_FRAGMENT (lspid) = 0x00;
2348 lspid[ISIS_SYS_ID_LEN - 1] = (i & 0xFF);
2349 lspid[ISIS_SYS_ID_LEN - 2] = ((i >> 8) & 0xFF);
jardineb5d44e2003-12-23 08:09:43 +00002350
hassof390d2c2004-09-10 20:48:21 +00002351 lsp = lsp_new (lspid, isis_jitter (area->max_lsp_lifetime[0],
hassof1082d12005-09-19 04:23:34 +00002352 MAX_AGE_JITTER), 1, IS_LEVEL_1, 0, 1);
2353 if (!lsp)
2354 return;
hassof390d2c2004-09-10 20:48:21 +00002355 lsp->from_topology = 1;
hassof1082d12005-09-19 04:23:34 +00002356 lsp->area = area;
jardineb5d44e2003-12-23 08:09:43 +00002357
hassof1082d12005-09-19 04:23:34 +00002358 /* Creating LSP data based on topology info. */
2359 build_topology_lsp_data (lsp, area, i);
2360 /* Checksum is also calculated here. */
2361 lsp_seqnum_update (lsp);
2362
2363 ref_time = area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
2364 MAX_LSP_GEN_INTERVAL : area->lsp_refresh[0];
2365
2366 THREAD_TIMER_ON (master, lsp->t_lsp_top_ref, top_lsp_refresh, lsp,
2367 isis_jitter (ref_time, MAX_LSP_GEN_JITTER));
hassof390d2c2004-09-10 20:48:21 +00002368 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
2369 lsp_insert (lsp, area->lspdb[0]);
hassof390d2c2004-09-10 20:48:21 +00002370 }
jardineb5d44e2003-12-23 08:09:43 +00002371}
2372
2373void
2374remove_topology_lsps (struct isis_area *area)
2375{
2376 struct isis_lsp *lsp;
2377 dnode_t *dnode, *dnode_next;
2378
2379 dnode = dict_first (area->lspdb[0]);
hassof390d2c2004-09-10 20:48:21 +00002380 while (dnode != NULL)
2381 {
2382 dnode_next = dict_next (area->lspdb[0], dnode);
2383 lsp = dnode_get (dnode);
2384 if (lsp->from_topology)
2385 {
2386 THREAD_TIMER_OFF (lsp->t_lsp_top_ref);
2387 lsp_destroy (lsp);
2388 dict_delete (area->lspdb[0], dnode);
2389 }
2390 dnode = dnode_next;
jardineb5d44e2003-12-23 08:09:43 +00002391 }
jardineb5d44e2003-12-23 08:09:43 +00002392}
2393
2394void
hassof390d2c2004-09-10 20:48:21 +00002395build_topology_lsp_data (struct isis_lsp *lsp, struct isis_area *area,
jardineb5d44e2003-12-23 08:09:43 +00002396 int lsp_top_num)
2397{
paula8f03df2005-04-10 15:58:10 +00002398 struct listnode *node, *nnode;
jardineb5d44e2003-12-23 08:09:43 +00002399 struct arc *arc;
jardineb5d44e2003-12-23 08:09:43 +00002400 struct is_neigh *is_neigh;
jardineb5d44e2003-12-23 08:09:43 +00002401 char buff[200];
hassof1082d12005-09-19 04:23:34 +00002402 struct tlvs tlv_data;
2403 struct isis_lsp *lsp0 = lsp;
jardineb5d44e2003-12-23 08:09:43 +00002404
hassof1082d12005-09-19 04:23:34 +00002405 /* Add area addresses. FIXME: Is it needed at all? */
2406 if (lsp->tlv_data.area_addrs == NULL)
2407 lsp->tlv_data.area_addrs = list_new ();
2408 list_add_list (lsp->tlv_data.area_addrs, area->area_addrs);
jardineb5d44e2003-12-23 08:09:43 +00002409
hassof1082d12005-09-19 04:23:34 +00002410 if (lsp->tlv_data.nlpids == NULL)
2411 lsp->tlv_data.nlpids = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct nlpids));
2412 lsp->tlv_data.nlpids->count = 1;
2413 lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP;
jardineb5d44e2003-12-23 08:09:43 +00002414
hassof1082d12005-09-19 04:23:34 +00002415 if (area->dynhostname)
2416 {
2417 lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV,
2418 sizeof (struct hostname));
2419 memset (buff, 0x00, 200);
2420 sprintf (buff, "%s%d", area->topology_basedynh ? area->topology_basedynh :
2421 "feedme", lsp_top_num);
2422 memcpy (lsp->tlv_data.hostname->name, buff, strlen (buff));
2423 lsp->tlv_data.hostname->namelen = strlen (buff);
2424 }
2425
2426 if (lsp->tlv_data.nlpids)
2427 tlv_add_nlpid (lsp->tlv_data.nlpids, lsp->pdu);
2428 if (lsp->tlv_data.hostname)
2429 tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu);
2430 if (lsp->tlv_data.area_addrs && listcount (lsp->tlv_data.area_addrs) > 0)
2431 tlv_add_area_addrs (lsp->tlv_data.area_addrs, lsp->pdu);
2432
2433 memset (&tlv_data, 0, sizeof (struct tlvs));
2434 if (tlv_data.is_neighs == NULL)
2435 tlv_data.is_neighs = list_new ();
2436
2437 /* Add reachability for this IS for simulated 1. */
hassof390d2c2004-09-10 20:48:21 +00002438 if (lsp_top_num == 1)
2439 {
hassof1082d12005-09-19 04:23:34 +00002440 is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
2441 memset (is_neigh, 0, sizeof (struct is_neigh));
2442
hassof390d2c2004-09-10 20:48:21 +00002443 memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
jardineb5d44e2003-12-23 08:09:43 +00002444 LSP_PSEUDO_ID (is_neigh->neigh_id) = 0x00;
hassof1082d12005-09-19 04:23:34 +00002445 /* Metric MUST NOT be 0, unless it's not alias TLV. */
2446 is_neigh->metrics.metric_default = 0x01;
jardineb5d44e2003-12-23 08:09:43 +00002447 is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
2448 is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
2449 is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
hassof1082d12005-09-19 04:23:34 +00002450 listnode_add (tlv_data.is_neighs, is_neigh);
jardineb5d44e2003-12-23 08:09:43 +00002451 }
hassof390d2c2004-09-10 20:48:21 +00002452
hassof1082d12005-09-19 04:23:34 +00002453 /* Add IS reachabilities. */
paula8f03df2005-04-10 15:58:10 +00002454 for (ALL_LIST_ELEMENTS (area->topology, node, nnode, arc))
hassof390d2c2004-09-10 20:48:21 +00002455 {
hassof1082d12005-09-19 04:23:34 +00002456 int to_lsp = 0;
2457
2458 if ((lsp_top_num != arc->from_node) && (lsp_top_num != arc->to_node))
2459 continue;
2460
2461 if (lsp_top_num == arc->from_node)
2462 to_lsp = arc->to_node;
2463 else
2464 to_lsp = arc->from_node;
2465
2466 is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
2467 memset (is_neigh, 0, sizeof (struct is_neigh));
2468
2469 memcpy (&is_neigh->neigh_id, area->topology_baseis, ISIS_SYS_ID_LEN);
2470 is_neigh->neigh_id[ISIS_SYS_ID_LEN - 1] = (to_lsp & 0xFF);
2471 is_neigh->neigh_id[ISIS_SYS_ID_LEN - 2] = ((to_lsp >> 8) & 0xFF);
2472 is_neigh->metrics.metric_default = arc->distance;
2473 is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
2474 is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
2475 is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
2476 listnode_add (tlv_data.is_neighs, is_neigh);
hassof390d2c2004-09-10 20:48:21 +00002477 }
hassof1082d12005-09-19 04:23:34 +00002478
2479 while (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
2480 {
2481 if (lsp->tlv_data.is_neighs == NULL)
2482 lsp->tlv_data.is_neighs = list_new ();
2483 lsp_tlv_fit (lsp, &tlv_data.is_neighs,
2484 &lsp->tlv_data.is_neighs,
2485 IS_NEIGHBOURS_LEN, area->lsp_frag_threshold,
2486 tlv_add_is_neighs);
2487 if (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
2488 lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
2489 lsp0, area, IS_LEVEL_1);
2490 }
2491
2492 free_tlvs (&tlv_data);
2493 return;
jardineb5d44e2003-12-23 08:09:43 +00002494}
2495#endif /* TOPOLOGY_GENERATE */