blob: 0860b1505e2ec6307663955d550205a1c212435b [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,
hassof390d2c2004-09-10 20:48:21 +0000419 struct stream *stream, struct isis_area *area)
jardineb5d44e2003-12-23 08:09:43 +0000420{
hassof390d2c2004-09-10 20:48:21 +0000421 /* free the old lsp data */
jardineb5d44e2003-12-23 08:09:43 +0000422 XFREE (MTYPE_STREAM_DATA, lsp->pdu);
423 lsp_clear_data (lsp);
424
425 /* rebuild the lsp data */
426 lsp_update_data (lsp, stream, area);
427
hassof390d2c2004-09-10 20:48:21 +0000428 /* set the new values for lsp header */
jardineb5d44e2003-12-23 08:09:43 +0000429 memcpy (lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN);
jardineb5d44e2003-12-23 08:09:43 +0000430}
431
jardineb5d44e2003-12-23 08:09:43 +0000432/* creation of LSP directly from what we received */
433struct isis_lsp *
hassof390d2c2004-09-10 20:48:21 +0000434lsp_new_from_stream_ptr (struct stream *stream,
435 u_int16_t pdu_len, struct isis_lsp *lsp0,
436 struct isis_area *area)
jardineb5d44e2003-12-23 08:09:43 +0000437{
438 struct isis_lsp *lsp;
439
440 lsp = XMALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
441 memset (lsp, 0, sizeof (struct isis_lsp));
hassof390d2c2004-09-10 20:48:21 +0000442
jardineb5d44e2003-12-23 08:09:43 +0000443 lsp_update_data (lsp, stream, area);
hassof390d2c2004-09-10 20:48:21 +0000444
445 if (lsp0 == NULL)
446 {
447 /*
448 * zero lsp -> create the list for fragments
449 */
450 lsp->lspu.frags = list_new ();
451 }
452 else
453 {
454 /*
455 * a fragment -> set the backpointer and add this to zero lsps frag list
456 */
457 lsp->lspu.zero_lsp = lsp0;
458 listnode_add (lsp0->lspu.frags, lsp);
459 }
460
jardineb5d44e2003-12-23 08:09:43 +0000461 return lsp;
462}
463
464struct isis_lsp *
hassof390d2c2004-09-10 20:48:21 +0000465lsp_new (u_char * lsp_id, u_int16_t rem_lifetime, u_int32_t seq_num,
466 u_int8_t lsp_bits, u_int16_t checksum, int level)
jardineb5d44e2003-12-23 08:09:43 +0000467{
468 struct isis_lsp *lsp;
469
470 lsp = XMALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
hassof390d2c2004-09-10 20:48:21 +0000471 if (!lsp)
472 {
473 /* FIXME: set lspdbol bit */
474 zlog_warn ("lsp_new(): out of memory");
475 return NULL;
476 }
jardineb5d44e2003-12-23 08:09:43 +0000477 memset (lsp, 0, sizeof (struct isis_lsp));
478#ifdef LSP_MEMORY_PREASSIGN
hassof390d2c2004-09-10 20:48:21 +0000479 lsp->pdu = stream_new (1514); /*Should be minimal mtu? yup... */
jardineb5d44e2003-12-23 08:09:43 +0000480#else
hassof390d2c2004-09-10 20:48:21 +0000481 /* We need to do realloc on TLVs additions */
482 lsp->pdu = malloc (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
jardineb5d44e2003-12-23 08:09:43 +0000483#endif /* LSP_MEMORY_PREASSIGN */
484 if (LSP_FRAGMENT (lsp_id) == 0)
485 lsp->lspu.frags = list_new ();
hassof390d2c2004-09-10 20:48:21 +0000486 lsp->isis_header = (struct isis_fixed_hdr *) (STREAM_DATA (lsp->pdu));
487 lsp->lsp_header = (struct isis_link_state_hdr *)
488 (STREAM_DATA (lsp->pdu) + ISIS_FIXED_HDR_LEN);
489
jardineb5d44e2003-12-23 08:09:43 +0000490 /* at first we fill the FIXED HEADER */
hassof390d2c2004-09-10 20:48:21 +0000491 (level == 1) ? fill_fixed_hdr (lsp->isis_header, L1_LINK_STATE) :
492 fill_fixed_hdr (lsp->isis_header, L2_LINK_STATE);
493
jardineb5d44e2003-12-23 08:09:43 +0000494 /* now for the LSP HEADER */
495 /* Minimal LSP PDU size */
hassof390d2c2004-09-10 20:48:21 +0000496 lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
jardineb5d44e2003-12-23 08:09:43 +0000497 memcpy (lsp->lsp_header->lsp_id, lsp_id, ISIS_SYS_ID_LEN + 2);
hassof390d2c2004-09-10 20:48:21 +0000498 lsp->lsp_header->checksum = checksum; /* Provided in network order */
jardineb5d44e2003-12-23 08:09:43 +0000499 lsp->lsp_header->seq_num = htonl (seq_num);
500 lsp->lsp_header->rem_lifetime = htons (rem_lifetime);
501 lsp->lsp_header->lsp_bits = lsp_bits;
502 lsp->level = level;
503 lsp->age_out = ZERO_AGE_LIFETIME;
504
paul9985f832005-02-09 15:51:56 +0000505 stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
jardineb5d44e2003-12-23 08:09:43 +0000506
507 /* #ifdef EXTREME_DEBUG */
508 /* logging */
hasso529d65b2004-12-24 00:14:50 +0000509 zlog_debug ("New LSP with ID %s-%02x-%02x seqnum %08x", sysid_print (lsp_id),
510 LSP_PSEUDO_ID (lsp->lsp_header->lsp_id),
511 LSP_FRAGMENT (lsp->lsp_header->lsp_id),
512 ntohl (lsp->lsp_header->seq_num));
jardineb5d44e2003-12-23 08:09:43 +0000513 /* #endif EXTREME DEBUG */
514
515 return lsp;
516}
517
518void
hassof390d2c2004-09-10 20:48:21 +0000519lsp_insert (struct isis_lsp *lsp, dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +0000520{
521 dict_alloc_insert (lspdb, lsp->lsp_header->lsp_id, lsp);
522}
523
524/*
525 * Build a list of LSPs with non-zero ht bounded by start and stop ids
526 */
hassof390d2c2004-09-10 20:48:21 +0000527void
528lsp_build_list_nonzero_ht (u_char * start_id, u_char * stop_id,
529 struct list *list, dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +0000530{
531 dnode_t *first, *last, *curr;
532
533 first = dict_lower_bound (lspdb, start_id);
534 if (!first)
535 return;
hassof390d2c2004-09-10 20:48:21 +0000536
jardineb5d44e2003-12-23 08:09:43 +0000537 last = dict_upper_bound (lspdb, stop_id);
hassof390d2c2004-09-10 20:48:21 +0000538
jardineb5d44e2003-12-23 08:09:43 +0000539 curr = first;
hassof390d2c2004-09-10 20:48:21 +0000540
541 if (((struct isis_lsp *) (curr->dict_data))->lsp_header->rem_lifetime)
jardineb5d44e2003-12-23 08:09:43 +0000542 listnode_add (list, first->dict_data);
543
hassof390d2c2004-09-10 20:48:21 +0000544 while (curr)
545 {
546 curr = dict_next (lspdb, curr);
547 if (curr &&
548 ((struct isis_lsp *) (curr->dict_data))->lsp_header->rem_lifetime)
549 listnode_add (list, curr->dict_data);
550 if (curr == last)
551 break;
552 }
553
jardineb5d44e2003-12-23 08:09:43 +0000554 return;
555}
556
557/*
558 * Build a list of all LSPs bounded by start and stop ids
559 */
hassof390d2c2004-09-10 20:48:21 +0000560void
561lsp_build_list (u_char * start_id, u_char * stop_id,
562 struct list *list, dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +0000563{
564 dnode_t *first, *last, *curr;
565
566 first = dict_lower_bound (lspdb, start_id);
567 if (!first)
568 return;
hassof390d2c2004-09-10 20:48:21 +0000569
jardineb5d44e2003-12-23 08:09:43 +0000570 last = dict_upper_bound (lspdb, stop_id);
hassof390d2c2004-09-10 20:48:21 +0000571
jardineb5d44e2003-12-23 08:09:43 +0000572 curr = first;
hassof390d2c2004-09-10 20:48:21 +0000573
jardineb5d44e2003-12-23 08:09:43 +0000574 listnode_add (list, first->dict_data);
575
hassof390d2c2004-09-10 20:48:21 +0000576 while (curr)
577 {
578 curr = dict_next (lspdb, curr);
579 if (curr)
580 listnode_add (list, curr->dict_data);
581 if (curr == last)
582 break;
583 }
584
jardineb5d44e2003-12-23 08:09:43 +0000585 return;
586}
587
588/*
589 * Build a list of LSPs with SSN flag set for the given circuit
590 */
591void
hassof390d2c2004-09-10 20:48:21 +0000592lsp_build_list_ssn (struct isis_circuit *circuit, struct list *list,
593 dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +0000594{
595 dnode_t *dnode, *next;
596 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +0000597
jardineb5d44e2003-12-23 08:09:43 +0000598 dnode = dict_first (lspdb);
hassof390d2c2004-09-10 20:48:21 +0000599 while (dnode != NULL)
600 {
601 next = dict_next (lspdb, dnode);
602 lsp = dnode_get (dnode);
603 if (ISIS_CHECK_FLAG (lsp->SSNflags, circuit))
604 listnode_add (list, lsp);
605 dnode = next;
606 }
607
jardineb5d44e2003-12-23 08:09:43 +0000608 return;
609}
610
hasso92365882005-01-18 13:53:33 +0000611static void
jardineb5d44e2003-12-23 08:09:43 +0000612lsp_set_time (struct isis_lsp *lsp)
613{
614 assert (lsp);
hassof390d2c2004-09-10 20:48:21 +0000615
616 if (lsp->lsp_header->rem_lifetime == 0)
617 {
618 if (lsp->age_out != 0)
619 lsp->age_out--;
620 return;
621 }
jardineb5d44e2003-12-23 08:09:43 +0000622
623 /* If we are turning 0 */
624 /* ISO 10589 - 7.3.16.4 first paragraph */
625
hassof390d2c2004-09-10 20:48:21 +0000626 if (ntohs (lsp->lsp_header->rem_lifetime) == 1)
627 {
628 /* 7.3.16.4 a) set SRM flags on all */
629 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
630 /* 7.3.16.4 b) retain only the header FIXME */
631 /* 7.3.16.4 c) record the time to purge FIXME (other way to do it) */
632 }
jardineb5d44e2003-12-23 08:09:43 +0000633
hassof390d2c2004-09-10 20:48:21 +0000634 lsp->lsp_header->rem_lifetime =
jardineb5d44e2003-12-23 08:09:43 +0000635 htons (ntohs (lsp->lsp_header->rem_lifetime) - 1);
636}
637
hasso92365882005-01-18 13:53:33 +0000638static void
hassof390d2c2004-09-10 20:48:21 +0000639lspid_print (u_char * lsp_id, u_char * trg, char dynhost, char frag)
jardineb5d44e2003-12-23 08:09:43 +0000640{
641 struct isis_dynhn *dyn = NULL;
hassof390d2c2004-09-10 20:48:21 +0000642 u_char id[SYSID_STRLEN];
jardineb5d44e2003-12-23 08:09:43 +0000643
644 if (dynhost)
645 dyn = dynhn_find_by_id (lsp_id);
646 else
647 dyn = NULL;
648
649 if (dyn)
hassof7c43dc2004-09-26 16:24:14 +0000650 sprintf ((char *)id, "%.14s", dyn->name.name);
jardineb5d44e2003-12-23 08:09:43 +0000651 else if (!memcmp (isis->sysid, lsp_id, ISIS_SYS_ID_LEN) & dynhost)
hassof7c43dc2004-09-26 16:24:14 +0000652 sprintf ((char *)id, "%.14s", unix_hostname ());
jardineb5d44e2003-12-23 08:09:43 +0000653 else
hassof390d2c2004-09-10 20:48:21 +0000654 {
655 memcpy (id, sysid_print (lsp_id), 15);
656 }
657 if (frag)
hassof7c43dc2004-09-26 16:24:14 +0000658 sprintf ((char *)trg, "%s.%02x-%02x", id, LSP_PSEUDO_ID (lsp_id),
hassof390d2c2004-09-10 20:48:21 +0000659 LSP_FRAGMENT (lsp_id));
660 else
hassof7c43dc2004-09-26 16:24:14 +0000661 sprintf ((char *)trg, "%s.%02x", id, LSP_PSEUDO_ID (lsp_id));
jardineb5d44e2003-12-23 08:09:43 +0000662}
663
hassof390d2c2004-09-10 20:48:21 +0000664/* Convert the lsp attribute bits to attribute string */
hasso1cd80842004-10-07 20:07:40 +0000665const char *
hassof390d2c2004-09-10 20:48:21 +0000666lsp_bits2string (u_char * lsp_bits)
667{
668 char *pos = lsp_bits_string;
jardineb5d44e2003-12-23 08:09:43 +0000669
hassof390d2c2004-09-10 20:48:21 +0000670 if (!*lsp_bits)
jardineb5d44e2003-12-23 08:09:43 +0000671 return " none";
672
673 /* we only focus on the default metric */
674 pos += sprintf (pos, "%d/",
hassof390d2c2004-09-10 20:48:21 +0000675 ISIS_MASK_LSP_ATT_DEFAULT_BIT (*lsp_bits) ? 1 : 0);
jardineb5d44e2003-12-23 08:09:43 +0000676
677 pos += sprintf (pos, "%d/",
hassof390d2c2004-09-10 20:48:21 +0000678 ISIS_MASK_LSP_PARTITION_BIT (*lsp_bits) ? 1 : 0);
jardineb5d44e2003-12-23 08:09:43 +0000679
hassof390d2c2004-09-10 20:48:21 +0000680 pos += sprintf (pos, "%d", ISIS_MASK_LSP_OL_BIT (*lsp_bits) ? 1 : 0);
681
jardineb5d44e2003-12-23 08:09:43 +0000682 *(pos) = '\0';
jardineb5d44e2003-12-23 08:09:43 +0000683
hassof390d2c2004-09-10 20:48:21 +0000684 return lsp_bits_string;
jardineb5d44e2003-12-23 08:09:43 +0000685}
686
687/* this function prints the lsp on show isis database */
hasso92365882005-01-18 13:53:33 +0000688static void
hassof390d2c2004-09-10 20:48:21 +0000689lsp_print (dnode_t * node, struct vty *vty, char dynhost)
jardineb5d44e2003-12-23 08:09:43 +0000690{
hassof390d2c2004-09-10 20:48:21 +0000691 struct isis_lsp *lsp = dnode_get (node);
jardineb5d44e2003-12-23 08:09:43 +0000692 u_char LSPid[255];
693
694 lspid_print (lsp->lsp_header->lsp_id, LSPid, dynhost, 1);
hassof390d2c2004-09-10 20:48:21 +0000695 vty_out (vty, "%-21s%c ", LSPid, lsp->own_lsp ? '*' : ' ');
696 vty_out (vty, "0x%08x ", ntohl (lsp->lsp_header->seq_num));
697 vty_out (vty, "0x%04x ", ntohs (lsp->lsp_header->checksum));
jardineb5d44e2003-12-23 08:09:43 +0000698
hassof390d2c2004-09-10 20:48:21 +0000699 if (ntohs (lsp->lsp_header->rem_lifetime) == 0)
700 vty_out (vty, " (%2u)", lsp->age_out);
jardineb5d44e2003-12-23 08:09:43 +0000701 else
hassof390d2c2004-09-10 20:48:21 +0000702 vty_out (vty, "%5u", ntohs (lsp->lsp_header->rem_lifetime));
jardineb5d44e2003-12-23 08:09:43 +0000703
704 vty_out (vty, " %s%s",
hassof390d2c2004-09-10 20:48:21 +0000705 lsp_bits2string (&lsp->lsp_header->lsp_bits), VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +0000706}
707
hasso92365882005-01-18 13:53:33 +0000708static void
hassof390d2c2004-09-10 20:48:21 +0000709lsp_print_detail (dnode_t * node, struct vty *vty, char dynhost)
jardineb5d44e2003-12-23 08:09:43 +0000710{
711 struct isis_lsp *lsp = dnode_get (node);
712 struct area_addr *area_addr;
hassof390d2c2004-09-10 20:48:21 +0000713 int i;
paul1eb8ef22005-04-07 07:30:20 +0000714 struct listnode *lnode, *lnnode;
jardineb5d44e2003-12-23 08:09:43 +0000715 struct is_neigh *is_neigh;
716 struct te_is_neigh *te_is_neigh;
717 struct ipv4_reachability *ipv4_reach;
718 struct in_addr *ipv4_addr;
719 struct te_ipv4_reachability *te_ipv4_reach;
720#ifdef HAVE_IPV6
721 struct ipv6_reachability *ipv6_reach;
722 struct in6_addr in6;
723#endif
724 u_char LSPid[255];
725 u_char hostname[255];
726 u_char buff[BUFSIZ];
jardineb5d44e2003-12-23 08:09:43 +0000727 u_char ipv4_reach_prefix[20];
728 u_char ipv4_reach_mask[20];
729 u_char ipv4_address[20];
730
731 lspid_print (lsp->lsp_header->lsp_id, LSPid, dynhost, 1);
hassof390d2c2004-09-10 20:48:21 +0000732 lsp_print (node, vty, dynhost);
jardineb5d44e2003-12-23 08:09:43 +0000733
734 /* for all area address */
hassof390d2c2004-09-10 20:48:21 +0000735 if (lsp->tlv_data.area_addrs)
paul1eb8ef22005-04-07 07:30:20 +0000736 for (ALL_LIST_ELEMENTS (lsp->tlv_data.area_addrs, lnode,
737 lnnode, area_addr))
hassof390d2c2004-09-10 20:48:21 +0000738 {
hasso1cd80842004-10-07 20:07:40 +0000739 vty_out (vty, " Area Address: %s%s",
hassof390d2c2004-09-10 20:48:21 +0000740 isonet_print (area_addr->area_addr, area_addr->addr_len),
741 VTY_NEWLINE);
742 }
paul1eb8ef22005-04-07 07:30:20 +0000743
jardineb5d44e2003-12-23 08:09:43 +0000744 /* for the nlpid tlv */
hassof390d2c2004-09-10 20:48:21 +0000745 if (lsp->tlv_data.nlpids)
746 {
747 for (i = 0; i < lsp->tlv_data.nlpids->count; i++)
748 {
749 switch (lsp->tlv_data.nlpids->nlpids[i])
750 {
751 case NLPID_IP:
752 case NLPID_IPV6:
hasso1cd80842004-10-07 20:07:40 +0000753 vty_out (vty, " NLPID: 0x%X%s",
hassof390d2c2004-09-10 20:48:21 +0000754 lsp->tlv_data.nlpids->nlpids[i], VTY_NEWLINE);
755 break;
756 default:
hasso1cd80842004-10-07 20:07:40 +0000757 vty_out (vty, " NLPID: %s%s", "unknown", VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +0000758 break;
759 }
760 }
761 }
jardineb5d44e2003-12-23 08:09:43 +0000762
763 /* for the hostname tlv */
hassof390d2c2004-09-10 20:48:21 +0000764 if (lsp->tlv_data.hostname)
765 {
766 bzero (hostname, sizeof (hostname));
767 memcpy (hostname, lsp->tlv_data.hostname->name,
768 lsp->tlv_data.hostname->namelen);
769 vty_out (vty, " Hostname: %s%s", hostname, VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +0000770 }
hassof390d2c2004-09-10 20:48:21 +0000771
772 if (lsp->tlv_data.ipv4_addrs)
paul1eb8ef22005-04-07 07:30:20 +0000773 for (ALL_LIST_ELEMENTS (lsp->tlv_data.ipv4_addrs, lnode,
774 lnnode, ipv4_addr))
hassof390d2c2004-09-10 20:48:21 +0000775 {
776 memcpy (ipv4_address, inet_ntoa (*ipv4_addr), sizeof (ipv4_address));
777 vty_out (vty, " IP: %s%s", ipv4_address, VTY_NEWLINE);
778 }
hassof390d2c2004-09-10 20:48:21 +0000779
hasso1cd80842004-10-07 20:07:40 +0000780 /* TE router id */
781 if (lsp->tlv_data.router_id)
782 {
783 memcpy (ipv4_address, inet_ntoa (lsp->tlv_data.router_id->id),
784 sizeof (ipv4_address));
785 vty_out (vty, " Router ID: %s%s", ipv4_address, VTY_NEWLINE);
786 }
787
788 /* for the IS neighbor tlv */
789 if (lsp->tlv_data.is_neighs)
paul1eb8ef22005-04-07 07:30:20 +0000790 for (ALL_LIST_ELEMENTS (lsp->tlv_data.is_neighs, lnode, lnnode, is_neigh))
hasso1cd80842004-10-07 20:07:40 +0000791 {
792 lspid_print (is_neigh->neigh_id, LSPid, dynhost, 0);
793 vty_out (vty, " Metric: %d IS %s%s",
794 is_neigh->metrics.metric_default, LSPid, VTY_NEWLINE);
795 }
hasso1cd80842004-10-07 20:07:40 +0000796
jardineb5d44e2003-12-23 08:09:43 +0000797 /* for the internal reachable tlv */
798 if (lsp->tlv_data.ipv4_int_reachs)
paul1eb8ef22005-04-07 07:30:20 +0000799 for (ALL_LIST_ELEMENTS (lsp->tlv_data.ipv4_int_reachs, lnode,
800 lnnode, ipv4_reach))
hassof390d2c2004-09-10 20:48:21 +0000801 {
802 memcpy (ipv4_reach_prefix, inet_ntoa (ipv4_reach->prefix),
803 sizeof (ipv4_reach_prefix));
804 memcpy (ipv4_reach_mask, inet_ntoa (ipv4_reach->mask),
805 sizeof (ipv4_reach_mask));
hasso2097cd82003-12-23 11:51:08 +0000806 vty_out (vty, " Metric: %d IP %s %s%s",
hassof390d2c2004-09-10 20:48:21 +0000807 ipv4_reach->metrics.metric_default, ipv4_reach_prefix,
808 ipv4_reach_mask, VTY_NEWLINE);
809 }
hasso2097cd82003-12-23 11:51:08 +0000810
811 /* for the external reachable tlv */
812 if (lsp->tlv_data.ipv4_ext_reachs)
paul1eb8ef22005-04-07 07:30:20 +0000813 for (ALL_LIST_ELEMENTS (lsp->tlv_data.ipv4_ext_reachs, lnode,
814 lnnode, ipv4_reach))
hassof390d2c2004-09-10 20:48:21 +0000815 {
816 memcpy (ipv4_reach_prefix, inet_ntoa (ipv4_reach->prefix),
817 sizeof (ipv4_reach_prefix));
818 memcpy (ipv4_reach_mask, inet_ntoa (ipv4_reach->mask),
819 sizeof (ipv4_reach_mask));
hasso2097cd82003-12-23 11:51:08 +0000820 vty_out (vty, " Metric: %d IP-External %s %s%s",
hassof390d2c2004-09-10 20:48:21 +0000821 ipv4_reach->metrics.metric_default, ipv4_reach_prefix,
822 ipv4_reach_mask, VTY_NEWLINE);
823 }
paul1eb8ef22005-04-07 07:30:20 +0000824
hasso2097cd82003-12-23 11:51:08 +0000825 /* IPv6 tlv */
826#ifdef HAVE_IPV6
827 if (lsp->tlv_data.ipv6_reachs)
paul1eb8ef22005-04-07 07:30:20 +0000828 for (ALL_LIST_ELEMENTS (lsp->tlv_data.ipv6_reachs, lnode,
829 lnnode, ipv6_reach))
hassof390d2c2004-09-10 20:48:21 +0000830 {
831 memset (&in6, 0, sizeof (in6));
832 memcpy (in6.s6_addr, ipv6_reach->prefix,
833 PSIZE (ipv6_reach->prefix_len));
hassof7c43dc2004-09-26 16:24:14 +0000834 inet_ntop (AF_INET6, &in6, (char *)buff, BUFSIZ);
hasso2097cd82003-12-23 11:51:08 +0000835 if ((ipv6_reach->control_info &&
hassof390d2c2004-09-10 20:48:21 +0000836 CTRL_INFO_DISTRIBUTION) == DISTRIBUTION_INTERNAL)
837 vty_out (vty, " Metric: %d IPv6-Intern %s/%d%s",
838 ntohl (ipv6_reach->metric),
839 buff, ipv6_reach->prefix_len, VTY_NEWLINE);
hasso2097cd82003-12-23 11:51:08 +0000840 else
hassof390d2c2004-09-10 20:48:21 +0000841 vty_out (vty, " Metric: %d IPv6-Extern %s/%d%s",
842 ntohl (ipv6_reach->metric),
843 buff, ipv6_reach->prefix_len, VTY_NEWLINE);
hasso2097cd82003-12-23 11:51:08 +0000844 }
845#endif
paul1eb8ef22005-04-07 07:30:20 +0000846
hasso1cd80842004-10-07 20:07:40 +0000847 /* TE IS neighbor tlv */
jardineb5d44e2003-12-23 08:09:43 +0000848 if (lsp->tlv_data.te_is_neighs)
paul1eb8ef22005-04-07 07:30:20 +0000849 for (ALL_LIST_ELEMENTS (lsp->tlv_data.te_is_neighs, lnode,
850 lnnode, te_is_neigh))
hassof390d2c2004-09-10 20:48:21 +0000851 {
hasso1cd80842004-10-07 20:07:40 +0000852 /* FIXME: metric display is wrong. */
hassof390d2c2004-09-10 20:48:21 +0000853 lspid_print (te_is_neigh->neigh_id, LSPid, dynhost, 0);
hasso1cd80842004-10-07 20:07:40 +0000854 vty_out (vty, " Metric: %d extd-IS %s%s",
855 te_is_neigh->te_metric[0], LSPid, VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +0000856 }
jardineb5d44e2003-12-23 08:09:43 +0000857
hasso1cd80842004-10-07 20:07:40 +0000858 /* TE IPv4 tlv */
jardineb5d44e2003-12-23 08:09:43 +0000859 if (lsp->tlv_data.te_ipv4_reachs)
paul1eb8ef22005-04-07 07:30:20 +0000860 for (ALL_LIST_ELEMENTS (lsp->tlv_data.te_ipv4_reachs, lnode,
861 lnnode, te_ipv4_reach))
hassof390d2c2004-09-10 20:48:21 +0000862 {
hasso1cd80842004-10-07 20:07:40 +0000863 /* FIXME: There should be better way to output this stuff. */
hasso2e864cf2004-10-08 06:40:24 +0000864 vty_out (vty, " Metric: %d extd-IP %s/%d%s",
hasso1cd80842004-10-07 20:07:40 +0000865 ntohl (te_ipv4_reach->te_metric),
hassof390d2c2004-09-10 20:48:21 +0000866 inet_ntoa (newprefix2inaddr (&te_ipv4_reach->prefix_start,
867 te_ipv4_reach->control)),
hasso1cd80842004-10-07 20:07:40 +0000868 te_ipv4_reach->control & 0x3F, VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +0000869 }
jardineb5d44e2003-12-23 08:09:43 +0000870
hassof390d2c2004-09-10 20:48:21 +0000871 return;
jardineb5d44e2003-12-23 08:09:43 +0000872}
873
874/* print all the lsps info in the local lspdb */
hassof390d2c2004-09-10 20:48:21 +0000875int
876lsp_print_all (struct vty *vty, dict_t * lspdb, char detail, char dynhost)
jardineb5d44e2003-12-23 08:09:43 +0000877{
878
hassof390d2c2004-09-10 20:48:21 +0000879 dnode_t *node = dict_first (lspdb), *next;
jardineb5d44e2003-12-23 08:09:43 +0000880 int lsp_count = 0;
881
882 /* print the title, for both modes */
883 vty_out (vty, "LSP ID LSP Seq Num LSP Checksum "
hassof390d2c2004-09-10 20:48:21 +0000884 "LSP Holdtime ATT/P/OL%s", VTY_NEWLINE);
885
886 if (detail == ISIS_UI_LEVEL_BRIEF)
887 {
888 while (node != NULL)
889 {
890 /* I think it is unnecessary, so I comment it out */
891 /* dict_contains (lspdb, node); */
892 next = dict_next (lspdb, node);
893 lsp_print (node, vty, dynhost);
894 node = next;
895 lsp_count++;
896 }
jardineb5d44e2003-12-23 08:09:43 +0000897 }
hassof390d2c2004-09-10 20:48:21 +0000898 else if (detail == ISIS_UI_LEVEL_DETAIL)
899 {
900 while (node != NULL)
901 {
902 next = dict_next (lspdb, node);
903 lsp_print_detail (node, vty, dynhost);
904 node = next;
905 lsp_count++;
906 }
jardineb5d44e2003-12-23 08:09:43 +0000907 }
jardineb5d44e2003-12-23 08:09:43 +0000908
909 return lsp_count;
910}
911
912/* this function reallocate memory to an lsp pdu, with an additional
913 * size of memory, it scans the lsp and moves all pointers the
914 * way they should */
hasso92365882005-01-18 13:53:33 +0000915static u_char *
hassof390d2c2004-09-10 20:48:21 +0000916lsppdu_realloc (struct isis_lsp * lsp, int memorytype, int size)
jardineb5d44e2003-12-23 08:09:43 +0000917{
918 u_char *retval;
hassof390d2c2004-09-10 20:48:21 +0000919
920 retval = STREAM_DATA (lsp->pdu) + ntohs (lsp->lsp_header->pdu_len);
jardineb5d44e2003-12-23 08:09:43 +0000921#ifdef LSP_MEMORY_PREASSIGN
hassof390d2c2004-09-10 20:48:21 +0000922 lsp->lsp_header->pdu_len = htons (ntohs (lsp->lsp_header->pdu_len) + size);
jardineb5d44e2003-12-23 08:09:43 +0000923 return retval;
hassof390d2c2004-09-10 20:48:21 +0000924#else /* otherwise we have to move all pointers */
jardineb5d44e2003-12-23 08:09:43 +0000925 u_char *newpdu;
926 newpdu = stream_new (ntohs (lsp->lsp_header->pdu_len) + size);
paul15935e92005-05-03 09:27:23 +0000927 stream_put (newpdu, STREAM_DATA(lsp->pdu), ntohs (lsp->lsp_header->pdu_len);
jardineb5d44e2003-12-23 08:09:43 +0000928 XFREE (memorytype, lsp->pdu);
929 lsp->pdu = newpdu;
hassof390d2c2004-09-10 20:48:21 +0000930 lsp->isis_header = (struct isis_fixed_hdr *) STREAM_DATA (lsp->pdu);
931 lsp->lsp_header = (struct isis_link_state_hdr *)
932 (STREAM_DATA (lsp->pdu) + ISIS_FIXED_HDR_LEN);
jardineb5d44e2003-12-23 08:09:43 +0000933 htons (ntohs (lsp->lsp_header->pdu_len) += size);
hassof390d2c2004-09-10 20:48:21 +0000934 return STREAM_DATA (lsp->pdu) + (lsp->lsp_header->pdu_len - size);
jardineb5d44e2003-12-23 08:09:43 +0000935#endif /* LSP_MEMORY_PREASSIGN */
936}
937
hassof390d2c2004-09-10 20:48:21 +0000938#if 0 /* Saving the old one just in case :) */
jardineb5d44e2003-12-23 08:09:43 +0000939/*
940 * Builds the lsp->tlv_data
941 * and writes the tlvs into lsp->pdu
942 */
943void
944lsp_build_nonpseudo (struct isis_lsp *lsp, struct isis_area *area)
945{
946 struct is_neigh *is_neigh;
paul1eb8ef22005-04-07 07:30:20 +0000947 struct listnode *node, *nnode, *ipnode, *ipnnode;
jardineb5d44e2003-12-23 08:09:43 +0000948 int level = lsp->level;
949 struct isis_circuit *circuit;
950 struct prefix_ipv4 *ipv4;
951 struct ipv4_reachability *ipreach;
952 struct isis_adjacency *nei;
953#ifdef HAVE_IPV6
954 struct prefix_ipv6 *ipv6;
955 struct ipv6_reachability *ip6reach;
956#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000957
jardineb5d44e2003-12-23 08:09:43 +0000958 /*
959 * First add the tlvs related to area
960 */
hassof390d2c2004-09-10 20:48:21 +0000961
jardineb5d44e2003-12-23 08:09:43 +0000962 /* Area addresses */
963 if (lsp->tlv_data.area_addrs == NULL)
964 lsp->tlv_data.area_addrs = list_new ();
965 list_add_list (lsp->tlv_data.area_addrs, area->area_addrs);
966 /* Protocols Supported */
hassof390d2c2004-09-10 20:48:21 +0000967 if (area->ip_circuits > 0
jardineb5d44e2003-12-23 08:09:43 +0000968#ifdef HAVE_IPV6
969 || area->ipv6_circuits > 0
970#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000971 )
jardineb5d44e2003-12-23 08:09:43 +0000972 {
973 lsp->tlv_data.nlpids = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct nlpids));
974 lsp->tlv_data.nlpids->count = 0;
hassof390d2c2004-09-10 20:48:21 +0000975 if (area->ip_circuits > 0)
976 {
977 lsp->tlv_data.nlpids->count++;
978 lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP;
979 }
jardineb5d44e2003-12-23 08:09:43 +0000980#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000981 if (area->ipv6_circuits > 0)
982 {
983 lsp->tlv_data.nlpids->count++;
984 lsp->tlv_data.nlpids->nlpids[lsp->tlv_data.nlpids->count - 1] =
985 NLPID_IPV6;
986 }
jardineb5d44e2003-12-23 08:09:43 +0000987#endif /* HAVE_IPV6 */
988 }
989 /* Dynamic Hostname */
hassof390d2c2004-09-10 20:48:21 +0000990 if (area->dynhostname)
991 {
992 lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV,
993 sizeof (struct hostname));
994 memcpy (&lsp->tlv_data.hostname->name, unix_hostname (),
995 strlen (unix_hostname ()));
996 lsp->tlv_data.hostname->namelen = strlen (unix_hostname ());
997 }
jardineb5d44e2003-12-23 08:09:43 +0000998#ifdef TOPOLOGY_GENERATE
999 /*
1000 * If we have a topology in this area, we need to connect this lsp to
1001 * the first topology lsp
1002 */
hassof390d2c2004-09-10 20:48:21 +00001003 if ((area->topology) && (level == 1))
1004 {
1005 if (lsp->tlv_data.is_neighs == NULL)
1006 lsp->tlv_data.is_neighs = list_new ();
1007 is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1008 memset (is_neigh, 0, sizeof (struct is_neigh));
1009 memcpy (&is_neigh->neigh_id, area->topology_baseis, ISIS_SYS_ID_LEN);
1010 /* connected to the first */
1011 is_neigh->neigh_id[ISIS_SYS_ID_LEN - 1] = (0x01);
1012 /* this is actually the same system, why mess the SPT */
1013 is_neigh->metrics.metric_default = 0;
1014 is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
1015 is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
1016 is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
1017 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
jardineb5d44e2003-12-23 08:09:43 +00001018
hassof390d2c2004-09-10 20:48:21 +00001019 }
jardineb5d44e2003-12-23 08:09:43 +00001020#endif
1021
1022 /*
1023 * Then add tlvs related to circuits
1024 */
paul1eb8ef22005-04-07 07:30:20 +00001025 for (ALL_LIST_ELEMENTS (area->circuit_list, node, nnode, circuit))
hassof390d2c2004-09-10 20:48:21 +00001026 {
hassof390d2c2004-09-10 20:48:21 +00001027 if (circuit->state != C_STATE_UP)
1028 continue;
1029
1030 /*
1031 * Add IPv4 internal reachability of this circuit
1032 */
1033 if (circuit->ip_router && circuit->ip_addrs &&
1034 circuit->ip_addrs->count > 0)
1035 {
1036 if (lsp->tlv_data.ipv4_int_reachs == NULL)
1037 {
1038 lsp->tlv_data.ipv4_int_reachs = list_new ();
1039 lsp->tlv_data.ipv4_int_reachs->del = free_tlv;
1040 }
paul1eb8ef22005-04-07 07:30:20 +00001041 for (ALL_LIST_ELEMENTS (circuit->ip_addrs, ipnode, ipnnode, ipv4))
hassof390d2c2004-09-10 20:48:21 +00001042 {
hassof390d2c2004-09-10 20:48:21 +00001043 ipreach =
1044 XMALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv4_reachability));
1045 ipreach->metrics = circuit->metrics[level - 1];
1046 ipreach->prefix = ipv4->prefix;
1047 masklen2ip (ipv4->prefixlen, &ipreach->mask);
1048 listnode_add (lsp->tlv_data.ipv4_int_reachs, ipreach);
1049 }
1050 }
jardineb5d44e2003-12-23 08:09:43 +00001051#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001052 /*
1053 * Add IPv6 reachability of this circuit
1054 */
1055 if (circuit->ipv6_router && circuit->ipv6_non_link &&
1056 circuit->ipv6_non_link->count > 0)
1057 {
1058 if (lsp->tlv_data.ipv6_reachs == NULL)
1059 {
1060 lsp->tlv_data.ipv6_reachs = list_new ();
1061 lsp->tlv_data.ipv6_reachs->del = free_tlv;
1062 }
paul1eb8ef22005-04-07 07:30:20 +00001063 for (ALL_LIST_ELEMENTS (circuit->ipv6_non_link, ipnode,
1064 ipnnode, ipv6))
hassof390d2c2004-09-10 20:48:21 +00001065 {
hassof390d2c2004-09-10 20:48:21 +00001066 ip6reach =
1067 XMALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv6_reachability));
1068 memset (ip6reach, 0, sizeof (struct ipv6_reachability));
1069 ip6reach->metric =
1070 htonl (circuit->metrics[level - 1].metric_default);
1071 ip6reach->control_info = 0;
1072 ip6reach->prefix_len = ipv6->prefixlen;
1073 memcpy (&ip6reach->prefix, ipv6->prefix.s6_addr,
1074 (ipv6->prefixlen + 7) / 8);
1075 listnode_add (lsp->tlv_data.ipv6_reachs, ip6reach);
1076 }
1077 }
jardineb5d44e2003-12-23 08:09:43 +00001078#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +00001079
1080 switch (circuit->circ_type)
1081 {
1082 case CIRCUIT_T_BROADCAST:
1083 if (level & circuit->circuit_is_type)
1084 {
1085 if (lsp->tlv_data.is_neighs == NULL)
1086 {
1087 lsp->tlv_data.is_neighs = list_new ();
1088 lsp->tlv_data.is_neighs->del = free_tlv;
1089 }
1090 is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1091 memset (is_neigh, 0, sizeof (struct is_neigh));
1092 if (level == 1)
1093 memcpy (&is_neigh->neigh_id,
1094 circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
1095 else
1096 memcpy (&is_neigh->neigh_id,
1097 circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
1098 is_neigh->metrics = circuit->metrics[level - 1];
1099 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
1100 }
1101 break;
1102 case CIRCUIT_T_P2P:
1103 nei = circuit->u.p2p.neighbor;
1104 if (nei && (level & nei->circuit_t))
1105 {
1106 if (lsp->tlv_data.is_neighs == NULL)
1107 {
1108 lsp->tlv_data.is_neighs = list_new ();
1109 lsp->tlv_data.is_neighs->del = free_tlv;
1110 }
1111 is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1112 memset (is_neigh, 0, sizeof (struct is_neigh));
1113 memcpy (&is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN);
1114 is_neigh->metrics = circuit->metrics[level - 1];
1115 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
1116 }
1117 break;
1118 case CIRCUIT_T_STATIC_IN:
1119 zlog_warn ("lsp_area_create: unsupported circuit type");
1120 break;
1121 case CIRCUIT_T_STATIC_OUT:
1122 zlog_warn ("lsp_area_create: unsupported circuit type");
1123 break;
1124 case CIRCUIT_T_DA:
1125 zlog_warn ("lsp_area_create: unsupported circuit type");
1126 break;
1127 default:
1128 zlog_warn ("lsp_area_create: unknown circuit type");
1129 }
jardineb5d44e2003-12-23 08:09:43 +00001130 }
hassof390d2c2004-09-10 20:48:21 +00001131
jardineb5d44e2003-12-23 08:09:43 +00001132 if (lsp->tlv_data.nlpids)
1133 tlv_add_nlpid (lsp->tlv_data.nlpids, lsp->pdu);
1134 if (lsp->tlv_data.hostname)
1135 tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu);
hassof390d2c2004-09-10 20:48:21 +00001136 if (lsp->tlv_data.area_addrs && listcount (lsp->tlv_data.area_addrs) > 0)
jardineb5d44e2003-12-23 08:09:43 +00001137 tlv_add_area_addrs (lsp->tlv_data.area_addrs, lsp->pdu);
1138 if (lsp->tlv_data.is_neighs && listcount (lsp->tlv_data.is_neighs) > 0)
1139 tlv_add_is_neighs (lsp->tlv_data.is_neighs, lsp->pdu);
hassof390d2c2004-09-10 20:48:21 +00001140 if (lsp->tlv_data.ipv4_int_reachs &&
jardineb5d44e2003-12-23 08:09:43 +00001141 listcount (lsp->tlv_data.ipv4_int_reachs) > 0)
1142 tlv_add_ipv4_reachs (lsp->tlv_data.ipv4_int_reachs, lsp->pdu);
hassof390d2c2004-09-10 20:48:21 +00001143#ifdef HAVE_IPV6
1144 if (lsp->tlv_data.ipv6_reachs && listcount (lsp->tlv_data.ipv6_reachs) > 0)
jardineb5d44e2003-12-23 08:09:43 +00001145 tlv_add_ipv6_reachs (lsp->tlv_data.ipv6_reachs, lsp->pdu);
1146#endif /* HAVE_IPV6 */
1147
paul9985f832005-02-09 15:51:56 +00001148 lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
jardineb5d44e2003-12-23 08:09:43 +00001149
1150 return;
1151}
1152#endif
1153
1154#define FRAG_THOLD(S,T) \
1155((STREAM_SIZE(S)*T)/100)
1156
1157/* stream*, area->lsp_frag_threshold, increment */
1158#define FRAG_NEEDED(S,T,I) \
1159 (STREAM_SIZE(S)-STREAM_REMAIN(S)+(I) > FRAG_THOLD(S,T))
1160
hasso92365882005-01-18 13:53:33 +00001161static void
jardineb5d44e2003-12-23 08:09:43 +00001162lsp_tlv_fit (struct isis_lsp *lsp, struct list **from, struct list **to,
hassof390d2c2004-09-10 20:48:21 +00001163 int tlvsize, int frag_thold,
1164 int tlv_build_func (struct list *, struct stream *))
jardineb5d44e2003-12-23 08:09:43 +00001165{
1166 int count, i;
hassof390d2c2004-09-10 20:48:21 +00001167
jardineb5d44e2003-12-23 08:09:43 +00001168 /* can we fit all ? */
hassof390d2c2004-09-10 20:48:21 +00001169 if (!FRAG_NEEDED (lsp->pdu, frag_thold, listcount (*from) * tlvsize + 2))
1170 {
1171 tlv_build_func (*from, lsp->pdu);
1172 *to = *from;
1173 *from = NULL;
jardineb5d44e2003-12-23 08:09:43 +00001174 }
hassof390d2c2004-09-10 20:48:21 +00001175 else if (!FRAG_NEEDED (lsp->pdu, frag_thold, tlvsize + 2))
1176 {
1177 /* fit all we can */
1178 count = FRAG_THOLD (lsp->pdu, frag_thold) - 2 -
1179 (STREAM_SIZE (lsp->pdu) - STREAM_REMAIN (lsp->pdu));
1180 if (count)
1181 count = count / tlvsize;
1182 for (i = 0; i < count; i++)
1183 {
paul1eb8ef22005-04-07 07:30:20 +00001184 listnode_add (*to, listgetdata (listhead (*from)));
1185 listnode_delete (*from, listgetdata (listhead (*from)));
hassof390d2c2004-09-10 20:48:21 +00001186 }
1187 tlv_build_func (*to, lsp->pdu);
1188 }
paul9985f832005-02-09 15:51:56 +00001189 lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
jardineb5d44e2003-12-23 08:09:43 +00001190 return;
1191}
1192
hasso92365882005-01-18 13:53:33 +00001193static struct isis_lsp *
hassof390d2c2004-09-10 20:48:21 +00001194lsp_next_frag (u_char frag_num, struct isis_lsp *lsp0, struct isis_area *area,
1195 int level)
jardineb5d44e2003-12-23 08:09:43 +00001196{
1197 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +00001198 u_char frag_id[ISIS_SYS_ID_LEN + 2];
1199
jardineb5d44e2003-12-23 08:09:43 +00001200 memcpy (frag_id, lsp0->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 1);
1201 LSP_FRAGMENT (frag_id) = frag_num;
1202 lsp = lsp_search (frag_id, area->lspdb[level - 1]);
hassof390d2c2004-09-10 20:48:21 +00001203 if (lsp)
1204 {
1205 /*
1206 * Clear the TLVs, but inherit the authinfo
1207 */
1208 lsp_clear_data (lsp);
1209 if (lsp0->tlv_data.auth_info.type)
1210 {
1211 memcpy (&lsp->tlv_data.auth_info, &lsp->tlv_data.auth_info,
1212 sizeof (struct isis_passwd));
1213 tlv_add_authinfo (lsp->tlv_data.auth_info.type,
1214 lsp->tlv_data.auth_info.len,
1215 lsp->tlv_data.auth_info.passwd, lsp->pdu);
1216 }
1217 return lsp;
jardineb5d44e2003-12-23 08:09:43 +00001218 }
jardineb5d44e2003-12-23 08:09:43 +00001219 lsp = lsp_new (frag_id, area->max_lsp_lifetime[level - 1], 0, area->is_type,
hassof390d2c2004-09-10 20:48:21 +00001220 0, level);
jardineb5d44e2003-12-23 08:09:43 +00001221 lsp->own_lsp = 1;
hassof390d2c2004-09-10 20:48:21 +00001222 lsp_insert (lsp, area->lspdb[level - 1]);
jardineb5d44e2003-12-23 08:09:43 +00001223 listnode_add (lsp0->lspu.frags, lsp);
1224 lsp->lspu.zero_lsp = lsp0;
1225 /*
1226 * Copy the authinfo from zero LSP
1227 */
hassof390d2c2004-09-10 20:48:21 +00001228 if (lsp0->tlv_data.auth_info.type)
1229 {
1230 memcpy (&lsp->tlv_data.auth_info, &lsp->tlv_data.auth_info,
1231 sizeof (struct isis_passwd));
1232 tlv_add_authinfo (lsp->tlv_data.auth_info.type,
1233 lsp->tlv_data.auth_info.len,
1234 lsp->tlv_data.auth_info.passwd, lsp->pdu);
1235 }
jardineb5d44e2003-12-23 08:09:43 +00001236 return lsp;
1237}
1238
1239/*
1240 * Builds the LSP data part. This func creates a new frag whenever
1241 * area->lsp_frag_threshold is exceeded.
1242 */
1243#if 1
hasso92365882005-01-18 13:53:33 +00001244static void
jardineb5d44e2003-12-23 08:09:43 +00001245lsp_build_nonpseudo (struct isis_lsp *lsp, struct isis_area *area)
1246{
1247 struct is_neigh *is_neigh;
paul1eb8ef22005-04-07 07:30:20 +00001248 struct listnode *node, *nnode, *ipnode, *ipnnode;
jardineb5d44e2003-12-23 08:09:43 +00001249 int level = lsp->level;
1250 struct isis_circuit *circuit;
1251 struct prefix_ipv4 *ipv4;
1252 struct ipv4_reachability *ipreach;
1253 struct isis_adjacency *nei;
1254#ifdef HAVE_IPV6
hasso67851572004-09-21 14:17:04 +00001255 struct prefix_ipv6 *ipv6, *ip6prefix;
jardineb5d44e2003-12-23 08:09:43 +00001256 struct ipv6_reachability *ip6reach;
1257#endif /* HAVE_IPV6 */
1258 struct tlvs tlv_data;
1259 struct isis_lsp *lsp0 = lsp;
1260 struct isis_passwd *passwd;
hasso18a6dce2004-10-03 18:18:34 +00001261 struct in_addr *routerid;
jardineb5d44e2003-12-23 08:09:43 +00001262
1263 /*
1264 * First add the tlvs related to area
1265 */
hassof390d2c2004-09-10 20:48:21 +00001266
jardineb5d44e2003-12-23 08:09:43 +00001267 /* Area addresses */
1268 if (lsp->tlv_data.area_addrs == NULL)
1269 lsp->tlv_data.area_addrs = list_new ();
1270 list_add_list (lsp->tlv_data.area_addrs, area->area_addrs);
1271 /* Protocols Supported */
hassof390d2c2004-09-10 20:48:21 +00001272 if (area->ip_circuits > 0
jardineb5d44e2003-12-23 08:09:43 +00001273#ifdef HAVE_IPV6
1274 || area->ipv6_circuits > 0
1275#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +00001276 )
jardineb5d44e2003-12-23 08:09:43 +00001277 {
1278 lsp->tlv_data.nlpids = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct nlpids));
1279 lsp->tlv_data.nlpids->count = 0;
hassof390d2c2004-09-10 20:48:21 +00001280 if (area->ip_circuits > 0)
1281 {
1282 lsp->tlv_data.nlpids->count++;
1283 lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP;
1284 }
jardineb5d44e2003-12-23 08:09:43 +00001285#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001286 if (area->ipv6_circuits > 0)
1287 {
1288 lsp->tlv_data.nlpids->count++;
1289 lsp->tlv_data.nlpids->nlpids[lsp->tlv_data.nlpids->count - 1] =
1290 NLPID_IPV6;
1291 }
jardineb5d44e2003-12-23 08:09:43 +00001292#endif /* HAVE_IPV6 */
1293 }
1294 /* Dynamic Hostname */
hassof390d2c2004-09-10 20:48:21 +00001295 if (area->dynhostname)
1296 {
1297 lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV,
1298 sizeof (struct hostname));
jardin9e867fe2003-12-23 08:56:18 +00001299
hassof390d2c2004-09-10 20:48:21 +00001300 memcpy (lsp->tlv_data.hostname->name, unix_hostname (),
1301 strlen (unix_hostname ()));
1302 lsp->tlv_data.hostname->namelen = strlen (unix_hostname ());
1303 }
jardineb5d44e2003-12-23 08:09:43 +00001304
1305 /*
1306 * Building the zero lsp
1307 */
jardineb5d44e2003-12-23 08:09:43 +00001308 /*
1309 * Add the authentication info if its present
1310 */
hassof390d2c2004-09-10 20:48:21 +00001311 (level == 1) ? (passwd = &area->area_passwd) :
1312 (passwd = &area->domain_passwd);
1313 if (passwd->type)
1314 {
1315 memcpy (&lsp->tlv_data.auth_info, passwd, sizeof (struct isis_passwd));
1316 tlv_add_authinfo (passwd->type, passwd->len, passwd->passwd, lsp->pdu);
1317 }
jardineb5d44e2003-12-23 08:09:43 +00001318 if (lsp->tlv_data.nlpids)
1319 tlv_add_nlpid (lsp->tlv_data.nlpids, lsp->pdu);
1320 if (lsp->tlv_data.hostname)
1321 tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu);
hassof390d2c2004-09-10 20:48:21 +00001322 if (lsp->tlv_data.area_addrs && listcount (lsp->tlv_data.area_addrs) > 0)
jardineb5d44e2003-12-23 08:09:43 +00001323 tlv_add_area_addrs (lsp->tlv_data.area_addrs, lsp->pdu);
hassof390d2c2004-09-10 20:48:21 +00001324
jardineb5d44e2003-12-23 08:09:43 +00001325 memset (&tlv_data, 0, sizeof (struct tlvs));
1326 /*
hasso18a6dce2004-10-03 18:18:34 +00001327 * IPv4 address TLV. We don't follow "C" vendor, but "J" vendor behavior -
1328 * one IPv4 address is put into LSP and this address is same as router id.
1329 */
1330 if (router_id_zebra.s_addr != 0)
1331 {
hasso18a6dce2004-10-03 18:18:34 +00001332 if (lsp->tlv_data.ipv4_addrs == NULL)
1333 lsp->tlv_data.ipv4_addrs = list_new ();
1334
1335 routerid = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct in_addr));
1336 routerid->s_addr = router_id_zebra.s_addr;
1337
1338 listnode_add (lsp->tlv_data.ipv4_addrs, routerid);
1339
1340 /*
1341 * FIXME: Using add_tlv() directly is hack, but tlv_add_ip_addrs()
1342 * expects list of prefix_ipv4 structures, but we have list of
1343 * in_addr structures.
1344 */
1345 add_tlv (IPV4_ADDR, IPV4_MAX_BYTELEN, (u_char *) &routerid->s_addr,
1346 lsp->pdu);
1347 }
1348 /*
jardineb5d44e2003-12-23 08:09:43 +00001349 * Then build lists of tlvs related to circuits
1350 */
paul1eb8ef22005-04-07 07:30:20 +00001351 for (ALL_LIST_ELEMENTS (area->circuit_list, node, nnode, circuit))
hassof390d2c2004-09-10 20:48:21 +00001352 {
hassof390d2c2004-09-10 20:48:21 +00001353 if (circuit->state != C_STATE_UP)
1354 continue;
jardineb5d44e2003-12-23 08:09:43 +00001355
hassof390d2c2004-09-10 20:48:21 +00001356 /*
1357 * Add IPv4 internal reachability of this circuit
1358 */
1359 if (circuit->ip_router && circuit->ip_addrs &&
1360 circuit->ip_addrs->count > 0)
1361 {
1362 if (tlv_data.ipv4_int_reachs == NULL)
1363 {
1364 tlv_data.ipv4_int_reachs = list_new ();
1365 }
paul1eb8ef22005-04-07 07:30:20 +00001366 for (ALL_LIST_ELEMENTS (circuit->ip_addrs, ipnode, ipnnode, ipv4))
hassof390d2c2004-09-10 20:48:21 +00001367 {
hassof390d2c2004-09-10 20:48:21 +00001368 ipreach =
1369 XMALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv4_reachability));
1370 ipreach->metrics = circuit->metrics[level - 1];
hassof390d2c2004-09-10 20:48:21 +00001371 masklen2ip (ipv4->prefixlen, &ipreach->mask);
hasso67851572004-09-21 14:17:04 +00001372 ipreach->prefix.s_addr = ((ipreach->mask.s_addr) &
1373 (ipv4->prefix.s_addr));
hassof390d2c2004-09-10 20:48:21 +00001374 listnode_add (tlv_data.ipv4_int_reachs, ipreach);
1375 }
1376
1377 }
jardineb5d44e2003-12-23 08:09:43 +00001378#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001379 /*
1380 * Add IPv6 reachability of this circuit
1381 */
1382 if (circuit->ipv6_router && circuit->ipv6_non_link &&
1383 circuit->ipv6_non_link->count > 0)
1384 {
1385
1386 if (tlv_data.ipv6_reachs == NULL)
1387 {
1388 tlv_data.ipv6_reachs = list_new ();
1389 }
paul1eb8ef22005-04-07 07:30:20 +00001390 for (ALL_LIST_ELEMENTS (circuit->ipv6_non_link, ipnode, ipnnode,
1391 ipv6))
hassof390d2c2004-09-10 20:48:21 +00001392 {
hassof390d2c2004-09-10 20:48:21 +00001393 ip6reach =
1394 XMALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv6_reachability));
1395 memset (ip6reach, 0, sizeof (struct ipv6_reachability));
1396 ip6reach->metric =
1397 htonl (circuit->metrics[level - 1].metric_default);
1398 ip6reach->control_info = 0;
1399 ip6reach->prefix_len = ipv6->prefixlen;
hasso67851572004-09-21 14:17:04 +00001400 memcpy (&ip6prefix, &ipv6, sizeof(ip6prefix));
1401 apply_mask_ipv6 (ip6prefix);
1402 memcpy (ip6reach->prefix, ip6prefix->prefix.s6_addr,
1403 sizeof (ip6reach->prefix));
hassof390d2c2004-09-10 20:48:21 +00001404 listnode_add (tlv_data.ipv6_reachs, ip6reach);
1405 }
1406 }
1407#endif /* HAVE_IPV6 */
1408
1409 switch (circuit->circ_type)
1410 {
1411 case CIRCUIT_T_BROADCAST:
1412 if (level & circuit->circuit_is_type)
1413 {
1414 if (tlv_data.is_neighs == NULL)
1415 {
1416 tlv_data.is_neighs = list_new ();
1417 }
1418 is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1419 memset (is_neigh, 0, sizeof (struct is_neigh));
1420 if (level == 1)
1421 memcpy (is_neigh->neigh_id,
1422 circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
1423 else
1424 memcpy (is_neigh->neigh_id,
1425 circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
1426 is_neigh->metrics = circuit->metrics[level - 1];
1427 listnode_add (tlv_data.is_neighs, is_neigh);
1428 }
1429 break;
1430 case CIRCUIT_T_P2P:
1431 nei = circuit->u.p2p.neighbor;
1432 if (nei && (level & nei->circuit_t))
1433 {
1434 if (tlv_data.is_neighs == NULL)
1435 {
1436 tlv_data.is_neighs = list_new ();
1437 tlv_data.is_neighs->del = free_tlv;
1438 }
1439 is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1440 memset (is_neigh, 0, sizeof (struct is_neigh));
1441 memcpy (is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN);
1442 is_neigh->metrics = circuit->metrics[level - 1];
1443 listnode_add (tlv_data.is_neighs, is_neigh);
1444 }
1445 break;
1446 case CIRCUIT_T_STATIC_IN:
1447 zlog_warn ("lsp_area_create: unsupported circuit type");
1448 break;
1449 case CIRCUIT_T_STATIC_OUT:
1450 zlog_warn ("lsp_area_create: unsupported circuit type");
1451 break;
1452 case CIRCUIT_T_DA:
1453 zlog_warn ("lsp_area_create: unsupported circuit type");
1454 break;
1455 default:
1456 zlog_warn ("lsp_area_create: unknown circuit type");
1457 }
1458 }
1459
1460 while (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs))
1461 {
1462 if (lsp->tlv_data.ipv4_int_reachs == NULL)
1463 lsp->tlv_data.ipv4_int_reachs = list_new ();
1464 lsp_tlv_fit (lsp, &tlv_data.ipv4_int_reachs,
1465 &lsp->tlv_data.ipv4_int_reachs,
1466 IPV4_REACH_LEN, area->lsp_frag_threshold,
1467 tlv_add_ipv4_reachs);
1468 if (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs))
1469 lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
1470 lsp0, area, level);
1471 }
1472
1473#ifdef HAVE_IPV6
1474 while (tlv_data.ipv6_reachs && listcount (tlv_data.ipv6_reachs))
1475 {
1476 if (lsp->tlv_data.ipv6_reachs == NULL)
1477 lsp->tlv_data.ipv6_reachs = list_new ();
1478 lsp_tlv_fit (lsp, &tlv_data.ipv6_reachs,
1479 &lsp->tlv_data.ipv6_reachs,
1480 IPV6_REACH_LEN, area->lsp_frag_threshold,
1481 tlv_add_ipv6_reachs);
1482 if (tlv_data.ipv6_reachs && listcount (tlv_data.ipv6_reachs))
1483 lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
1484 lsp0, area, level);
jardineb5d44e2003-12-23 08:09:43 +00001485 }
1486#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +00001487
1488 while (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
1489 {
1490 if (lsp->tlv_data.is_neighs == NULL)
1491 lsp->tlv_data.is_neighs = list_new ();
1492 lsp_tlv_fit (lsp, &tlv_data.is_neighs,
1493 &lsp->tlv_data.is_neighs,
1494 IS_NEIGHBOURS_LEN, area->lsp_frag_threshold,
1495 tlv_add_is_neighs);
1496 if (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
1497 lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
1498 lsp0, area, level);
jardineb5d44e2003-12-23 08:09:43 +00001499 }
jardineb5d44e2003-12-23 08:09:43 +00001500
jardineb5d44e2003-12-23 08:09:43 +00001501 return;
1502}
1503#endif
1504
hasso92365882005-01-18 13:53:33 +00001505#if 0 /* Old code? */
1506static void
jardineb5d44e2003-12-23 08:09:43 +00001507build_lsp_data (struct isis_lsp *lsp, struct isis_area *area)
1508{
1509 struct list *circuit_list = area->circuit_list;
1510 struct isis_circuit *circuit;
1511 u_char *tlv_ptr;
1512 struct is_neigh *is_neigh;
1513
hassof390d2c2004-09-10 20:48:21 +00001514
jardineb5d44e2003-12-23 08:09:43 +00001515 /* add our nlpids */
hassof390d2c2004-09-10 20:48:21 +00001516 /* the 2 is for the TL plus 1 for the nlpid */
1517 tlv_ptr = lsppdu_realloc (lsp, MTYPE_ISIS_TLV, 3);
1518 *tlv_ptr = PROTOCOLS_SUPPORTED; /* Type */
1519 *(tlv_ptr + 1) = 1; /* one protocol */
1520#ifdef HAVE_IPV6 /*dunno if its right */
1521 *(tlv_ptr + 2) = NLPID_IPV6;
jardineb5d44e2003-12-23 08:09:43 +00001522#else
hassof390d2c2004-09-10 20:48:21 +00001523 *(tlv_ptr + 2) = NLPID_IP;
jardineb5d44e2003-12-23 08:09:43 +00001524#endif /* HAVE_IPV6 */
1525
1526 /* we should add our areas here
1527 * FIXME: we need to figure out which should be added? Adj? All? First? */
1528
1529 /* first, lets add ourselves to the IS neighbours info */
hassof390d2c2004-09-10 20:48:21 +00001530 /* the 2 is for the TL plus 1 for the virtual field */
1531 tlv_ptr = lsppdu_realloc (lsp, MTYPE_ISIS_TLV, 3);
1532 *tlv_ptr = IS_NEIGHBOURS; /* Type */
1533 *(tlv_ptr + 2) = 0; /* virtual is zero */
1534 lsp->tlv_data.is_neighs = list_new (); /* new list of is_neighbours */
jardineb5d44e2003-12-23 08:09:43 +00001535 /* assign space for the is_neigh at the pdu end */
hassof390d2c2004-09-10 20:48:21 +00001536 is_neigh = (struct is_neigh *) lsppdu_realloc (lsp, MTYPE_ISIS_TLV,
1537 sizeof (struct is_neigh));
jardineb5d44e2003-12-23 08:09:43 +00001538 /* add this node to our list */
hassof390d2c2004-09-10 20:48:21 +00001539 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
jardineb5d44e2003-12-23 08:09:43 +00001540 /* FIXME: Do we need our designated address here? */
hassof390d2c2004-09-10 20:48:21 +00001541 memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN + 1);
jardineb5d44e2003-12-23 08:09:43 +00001542 /* FIXME: Where should we really get our own LSPs metrics from? */
hassof390d2c2004-09-10 20:48:21 +00001543 circuit = (struct isis_circuit *) listhead (circuit_list);
1544 /* is_neigh->metrics = circuit->metrics[lsp->level -1]; */
jardineb5d44e2003-12-23 08:09:43 +00001545 /* Length */
hassof390d2c2004-09-10 20:48:21 +00001546 *(tlv_ptr + 1) =
1547 (lsp->tlv_data.is_neighs->count * sizeof (struct is_neigh) + 1);
jardineb5d44e2003-12-23 08:09:43 +00001548
1549 /* FIXME: scan for adjencecies and add them */
1550
1551 /* FIXME: add reachability info */
1552
hassof390d2c2004-09-10 20:48:21 +00001553 /* adding dynamic hostname if needed */
1554 if (area->dynhostname)
1555 {
1556 tlv_ptr = lsppdu_realloc (lsp, MTYPE_ISIS_TLV, 2); /* the 2 is for the TL */
1557 *tlv_ptr = DYNAMIC_HOSTNAME; /* Type */
1558 *(tlv_ptr + 1) = strlen (unix_hostname ()); /* Length */
1559 lsp->tlv_data.hostname = (struct hostname *)
1560 (lsppdu_realloc (lsp, MTYPE_ISIS_TLV,
1561 /* the -1 is to fit the length in the struct */
1562 strlen (unix_hostname ())) - 1);
1563 memcpy (lsp->tlv_data.hostname->name, unix_hostname (),
1564 strlen (unix_hostname ()));
1565 }
jardineb5d44e2003-12-23 08:09:43 +00001566
1567}
hasso92365882005-01-18 13:53:33 +00001568#endif /* 0 */
jardineb5d44e2003-12-23 08:09:43 +00001569
1570/*
1571 * 7.3.7 Generation on non-pseudonode LSPs
1572 */
hasso92365882005-01-18 13:53:33 +00001573static int
hassof390d2c2004-09-10 20:48:21 +00001574lsp_generate_non_pseudo (struct isis_area *area, int level)
1575{
jardineb5d44e2003-12-23 08:09:43 +00001576 struct isis_lsp *oldlsp, *newlsp;
1577 u_int32_t seq_num = 0;
1578 u_char lspid[ISIS_SYS_ID_LEN + 2];
1579
1580 memset (&lspid, 0, ISIS_SYS_ID_LEN + 2);
1581 memcpy (&lspid, isis->sysid, ISIS_SYS_ID_LEN);
1582
1583 /* only builds the lsp if the area shares the level */
hassof390d2c2004-09-10 20:48:21 +00001584 if ((area->is_type & level) == level)
1585 {
1586 oldlsp = lsp_search (lspid, area->lspdb[level - 1]);
1587 if (oldlsp)
1588 {
1589 seq_num = ntohl (oldlsp->lsp_header->seq_num);
1590 lsp_search_and_destroy (oldlsp->lsp_header->lsp_id,
1591 area->lspdb[level - 1]);
1592 /* FIXME: we should actually initiate a purge */
1593 }
1594 newlsp = lsp_new (lspid, area->max_lsp_lifetime[level - 1], seq_num,
1595 area->is_type, 0, level);
1596 newlsp->own_lsp = 1;
jardineb5d44e2003-12-23 08:09:43 +00001597
hassof390d2c2004-09-10 20:48:21 +00001598 lsp_insert (newlsp, area->lspdb[level - 1]);
1599 /* build_lsp_data (newlsp, area); */
1600 lsp_build_nonpseudo (newlsp, area);
1601 /* time to calculate our checksum */
1602 lsp_seqnum_update (newlsp);
1603 }
jardineb5d44e2003-12-23 08:09:43 +00001604
1605 /* DEBUG_ADJ_PACKETS */
hassof390d2c2004-09-10 20:48:21 +00001606 if (isis->debugs & DEBUG_ADJ_PACKETS)
1607 {
1608 /* FIXME: is this place right? fix missing info */
hasso529d65b2004-12-24 00:14:50 +00001609 zlog_debug ("ISIS-Upd (%s): Building L%d LSP", area->area_tag, level);
hassof390d2c2004-09-10 20:48:21 +00001610 }
jardineb5d44e2003-12-23 08:09:43 +00001611
1612 return ISIS_OK;
1613}
1614
1615/*
1616 * 7.3.9 Generation of level 1 LSPs (non-pseudonode)
1617 */
1618int
1619lsp_l1_generate (struct isis_area *area)
1620{
hassof390d2c2004-09-10 20:48:21 +00001621 THREAD_TIMER_ON (master, area->t_lsp_refresh[0], lsp_refresh_l1, area,
1622 MAX_LSP_GEN_INTERVAL);
jardineb5d44e2003-12-23 08:09:43 +00001623
1624 return lsp_generate_non_pseudo (area, 1);
1625}
1626
jardineb5d44e2003-12-23 08:09:43 +00001627/*
1628 * 7.3.9 Generation of level 2 LSPs (non-pseudonode)
1629 */
1630int
1631lsp_l2_generate (struct isis_area *area)
1632{
hassof390d2c2004-09-10 20:48:21 +00001633 THREAD_TIMER_ON (master, area->t_lsp_refresh[1], lsp_refresh_l2, area,
1634 MAX_LSP_GEN_INTERVAL);
jardineb5d44e2003-12-23 08:09:43 +00001635
1636 return lsp_generate_non_pseudo (area, 2);
1637}
1638
hasso92365882005-01-18 13:53:33 +00001639static int
jardineb5d44e2003-12-23 08:09:43 +00001640lsp_non_pseudo_regenerate (struct isis_area *area, int level)
1641{
1642 dict_t *lspdb = area->lspdb[level - 1];
1643 struct isis_lsp *lsp, *frag;
1644 struct listnode *node;
1645 u_char lspid[ISIS_SYS_ID_LEN + 2];
1646
1647 memset (lspid, 0, ISIS_SYS_ID_LEN + 2);
1648 memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN);
hassof390d2c2004-09-10 20:48:21 +00001649
jardineb5d44e2003-12-23 08:09:43 +00001650 lsp = lsp_search (lspid, lspdb);
jardineb5d44e2003-12-23 08:09:43 +00001651
hassof390d2c2004-09-10 20:48:21 +00001652 if (!lsp)
1653 {
1654 zlog_err
1655 ("ISIS-Upd (%s): lsp_non_pseudo_regenerate(): no L%d LSP found!",
1656 area->area_tag, level);
jardineb5d44e2003-12-23 08:09:43 +00001657
hassof390d2c2004-09-10 20:48:21 +00001658 return ISIS_ERROR;
1659 }
1660
1661 lsp_clear_data (lsp);
jardineb5d44e2003-12-23 08:09:43 +00001662 lsp_build_nonpseudo (lsp, area);
hassof390d2c2004-09-10 20:48:21 +00001663 lsp->lsp_header->rem_lifetime = htons (isis_jitter
1664 (area->max_lsp_lifetime[level - 1],
1665 MAX_AGE_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00001666 lsp_seqnum_update (lsp);
hassof390d2c2004-09-10 20:48:21 +00001667
1668 if (isis->debugs & DEBUG_UPDATE_PACKETS)
1669 {
hasso529d65b2004-12-24 00:14:50 +00001670 zlog_debug ("ISIS-Upd (%s): refreshing our L%d LSP %s, "
1671 "seq 0x%08x, cksum 0x%04x lifetime %us",
1672 area->area_tag,
1673 level,
1674 rawlspid_print (lsp->lsp_header->lsp_id),
1675 ntohl (lsp->lsp_header->seq_num),
1676 ntohs (lsp->lsp_header->checksum),
1677 ntohs (lsp->lsp_header->rem_lifetime));
hassof390d2c2004-09-10 20:48:21 +00001678 }
jardineb5d44e2003-12-23 08:09:43 +00001679
1680 lsp->last_generated = time (NULL);
1681 area->lsp_regenerate_pending[level - 1] = 0;
1682 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
paul1eb8ef22005-04-07 07:30:20 +00001683 for (ALL_LIST_ELEMENTS_RO (lsp->lspu.frags, node, frag))
hassof390d2c2004-09-10 20:48:21 +00001684 {
hassof390d2c2004-09-10 20:48:21 +00001685 frag->lsp_header->rem_lifetime = htons (isis_jitter
1686 (area->
1687 max_lsp_lifetime[level - 1],
1688 MAX_AGE_JITTER));
1689 ISIS_FLAGS_SET_ALL (frag->SRMflags);
1690 }
jardineb5d44e2003-12-23 08:09:43 +00001691
1692 if (area->ip_circuits)
1693 isis_spf_schedule (area, level);
1694#ifdef HAVE_IPV6
1695 if (area->ipv6_circuits)
1696 isis_spf_schedule6 (area, level);
1697#endif
1698 return ISIS_OK;
1699}
1700
jardineb5d44e2003-12-23 08:09:43 +00001701/*
1702 * Done at least every MAX_LSP_GEN_INTERVAL. Search own LSPs, update holding
1703 * time and set SRM
1704 */
hassof390d2c2004-09-10 20:48:21 +00001705int
jardineb5d44e2003-12-23 08:09:43 +00001706lsp_refresh_l1 (struct thread *thread)
1707{
1708 struct isis_area *area;
1709 unsigned long ref_time;
1710
1711 area = THREAD_ARG (thread);
1712 assert (area);
hassof390d2c2004-09-10 20:48:21 +00001713
jardineb5d44e2003-12-23 08:09:43 +00001714 area->t_lsp_refresh[0] = NULL;
hassof390d2c2004-09-10 20:48:21 +00001715 if (area->is_type & IS_LEVEL_1)
jardineb5d44e2003-12-23 08:09:43 +00001716 lsp_non_pseudo_regenerate (area, 1);
hassof390d2c2004-09-10 20:48:21 +00001717
1718 ref_time = area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
jardineb5d44e2003-12-23 08:09:43 +00001719 MAX_LSP_GEN_INTERVAL : area->lsp_refresh[0];
1720
hassof390d2c2004-09-10 20:48:21 +00001721 THREAD_TIMER_ON (master, area->t_lsp_refresh[0], lsp_refresh_l1, area,
1722 isis_jitter (ref_time, MAX_AGE_JITTER));
hassod70f99e2004-02-11 20:26:31 +00001723
jardineb5d44e2003-12-23 08:09:43 +00001724 return ISIS_OK;
1725}
1726
hassof390d2c2004-09-10 20:48:21 +00001727int
jardineb5d44e2003-12-23 08:09:43 +00001728lsp_refresh_l2 (struct thread *thread)
1729{
1730 struct isis_area *area;
1731 unsigned long ref_time;
1732
1733 area = THREAD_ARG (thread);
1734 assert (area);
hassof390d2c2004-09-10 20:48:21 +00001735
jardineb5d44e2003-12-23 08:09:43 +00001736 area->t_lsp_refresh[1] = NULL;
hassof390d2c2004-09-10 20:48:21 +00001737 if (area->is_type & IS_LEVEL_2)
jardineb5d44e2003-12-23 08:09:43 +00001738 lsp_non_pseudo_regenerate (area, 2);
1739
hassof390d2c2004-09-10 20:48:21 +00001740 ref_time = area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ?
jardineb5d44e2003-12-23 08:09:43 +00001741 MAX_LSP_GEN_INTERVAL : area->lsp_refresh[1];
1742
hassof390d2c2004-09-10 20:48:21 +00001743 THREAD_TIMER_ON (master, area->t_lsp_refresh[1], lsp_refresh_l2, area,
1744 isis_jitter (ref_time, MAX_AGE_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00001745
jardineb5d44e2003-12-23 08:09:43 +00001746 return ISIS_OK;
1747}
1748
jardineb5d44e2003-12-23 08:09:43 +00001749/*
1750 * Something has changed -> regenerate LSP
1751 */
1752
hasso92365882005-01-18 13:53:33 +00001753static int
jardineb5d44e2003-12-23 08:09:43 +00001754lsp_l1_regenerate (struct thread *thread)
1755{
1756 struct isis_area *area;
1757
1758 area = THREAD_ARG (thread);
1759 area->lsp_regenerate_pending[0] = 0;
1760
1761 return lsp_non_pseudo_regenerate (area, 1);
1762}
1763
hasso92365882005-01-18 13:53:33 +00001764static int
jardineb5d44e2003-12-23 08:09:43 +00001765lsp_l2_regenerate (struct thread *thread)
1766{
1767 struct isis_area *area;
1768
1769 area = THREAD_ARG (thread);
1770 area->lsp_regenerate_pending[1] = 0;
hassof390d2c2004-09-10 20:48:21 +00001771
jardineb5d44e2003-12-23 08:09:43 +00001772 return lsp_non_pseudo_regenerate (area, 2);
1773}
1774
hassof390d2c2004-09-10 20:48:21 +00001775int
jardineb5d44e2003-12-23 08:09:43 +00001776lsp_regenerate_schedule (struct isis_area *area)
1777{
1778 struct isis_lsp *lsp;
1779 u_char id[ISIS_SYS_ID_LEN + 2];
1780 time_t now, diff;
hassof390d2c2004-09-10 20:48:21 +00001781 memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
1782 LSP_PSEUDO_ID (id) = LSP_FRAGMENT (id) = 0;
jardineb5d44e2003-12-23 08:09:43 +00001783 now = time (NULL);
1784 /*
1785 * First level 1
1786 */
hassof390d2c2004-09-10 20:48:21 +00001787 if (area->is_type & IS_LEVEL_1)
1788 {
1789 lsp = lsp_search (id, area->lspdb[0]);
1790 if (!lsp || area->lsp_regenerate_pending[0])
1791 goto L2;
1792 /*
1793 * Throttle avoidance
1794 */
1795 diff = now - lsp->last_generated;
1796 if (diff < MIN_LSP_GEN_INTERVAL)
1797 {
1798 area->lsp_regenerate_pending[0] = 1;
1799 thread_add_timer (master, lsp_l1_regenerate, area,
1800 MIN_LSP_GEN_INTERVAL - diff);
hasso12a5cae2004-09-19 19:39:26 +00001801 goto L2;
hassof390d2c2004-09-10 20:48:21 +00001802 }
1803 else
1804 lsp_non_pseudo_regenerate (area, 1);
1805 }
jardineb5d44e2003-12-23 08:09:43 +00001806 /*
1807 * then 2
1808 */
hassof390d2c2004-09-10 20:48:21 +00001809L2:
1810 if (area->is_type & IS_LEVEL_2)
1811 {
1812 lsp = lsp_search (id, area->lspdb[1]);
1813 if (!lsp || area->lsp_regenerate_pending[1])
1814 return ISIS_OK;
1815 /*
1816 * Throttle avoidance
1817 */
1818 diff = now - lsp->last_generated;
1819 if (diff < MIN_LSP_GEN_INTERVAL)
1820 {
1821 area->lsp_regenerate_pending[1] = 1;
1822 thread_add_timer (master, lsp_l2_regenerate, area,
1823 MIN_LSP_GEN_INTERVAL - diff);
1824 return ISIS_OK;
1825 }
1826 else
1827 lsp_non_pseudo_regenerate (area, 2);
1828 }
1829
1830 return ISIS_OK;
jardineb5d44e2003-12-23 08:09:43 +00001831}
1832
1833/*
1834 * Funcs for pseudonode LSPs
1835 */
1836
1837/*
1838 * 7.3.8 and 7.3.10 Generation of level 1 and 2 pseudonode LSPs
1839 */
hasso92365882005-01-18 13:53:33 +00001840static void
hassof390d2c2004-09-10 20:48:21 +00001841lsp_build_pseudo (struct isis_lsp *lsp, struct isis_circuit *circuit,
1842 int level)
jardineb5d44e2003-12-23 08:09:43 +00001843{
1844 struct isis_adjacency *adj;
1845 struct is_neigh *is_neigh;
1846 struct es_neigh *es_neigh;
1847 struct list *adj_list;
paul1eb8ef22005-04-07 07:30:20 +00001848 struct listnode *node, *nnode;
jardineb5d44e2003-12-23 08:09:43 +00001849 struct isis_passwd *passwd;
1850
1851 assert (circuit);
1852 assert (circuit->circ_type == CIRCUIT_T_BROADCAST);
hassof390d2c2004-09-10 20:48:21 +00001853
jardineb5d44e2003-12-23 08:09:43 +00001854 if (!circuit->u.bc.is_dr[level - 1])
hassof390d2c2004-09-10 20:48:21 +00001855 return; /* we are not DIS on this circuit */
1856
jardineb5d44e2003-12-23 08:09:43 +00001857 lsp->level = level;
1858 if (level == 1)
1859 lsp->lsp_header->lsp_bits |= IS_LEVEL_1;
1860 else
1861 lsp->lsp_header->lsp_bits |= IS_LEVEL_2;
1862
1863 /*
1864 * add self to IS neighbours
1865 */
hassof390d2c2004-09-10 20:48:21 +00001866 if (lsp->tlv_data.is_neighs == NULL)
1867 {
1868 lsp->tlv_data.is_neighs = list_new ();
1869 lsp->tlv_data.is_neighs->del = free_tlv;
1870 }
paul15935e92005-05-03 09:27:23 +00001871 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1872
jardineb5d44e2003-12-23 08:09:43 +00001873 memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
1874 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
hassof390d2c2004-09-10 20:48:21 +00001875
1876 adj_list = list_new ();
1877 isis_adj_build_up_list (circuit->u.bc.adjdb[level - 1], adj_list);
1878
paul1eb8ef22005-04-07 07:30:20 +00001879 for (ALL_LIST_ELEMENTS (adj_list, node, nnode, adj))
hassof390d2c2004-09-10 20:48:21 +00001880 {
hassof390d2c2004-09-10 20:48:21 +00001881 if (adj->circuit_t & level)
1882 {
1883 if ((level == 1 && adj->sys_type == ISIS_SYSTYPE_L1_IS) ||
1884 (level == 1 && adj->sys_type == ISIS_SYSTYPE_L2_IS &&
1885 adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
1886 (level == 2 && adj->sys_type == ISIS_SYSTYPE_L2_IS))
1887 {
1888 /* an IS neighbour -> add it */
paul15935e92005-05-03 09:27:23 +00001889 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1890
hassof390d2c2004-09-10 20:48:21 +00001891 memcpy (&is_neigh->neigh_id, adj->sysid, ISIS_SYS_ID_LEN);
1892 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
1893 }
1894 else if (level == 1 && adj->sys_type == ISIS_SYSTYPE_ES)
1895 {
1896 /* an ES neigbour add it, if we are building level 1 LSP */
1897 /* FIXME: the tlv-format is hard to use here */
1898 if (lsp->tlv_data.es_neighs == NULL)
1899 {
1900 lsp->tlv_data.es_neighs = list_new ();
1901 lsp->tlv_data.es_neighs->del = free_tlv;
1902 }
paul15935e92005-05-03 09:27:23 +00001903 es_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct es_neigh));
1904
hassof390d2c2004-09-10 20:48:21 +00001905 memcpy (&es_neigh->first_es_neigh, adj->sysid, ISIS_SYS_ID_LEN);
1906 listnode_add (lsp->tlv_data.es_neighs, is_neigh);
1907 }
1908 }
jardineb5d44e2003-12-23 08:09:43 +00001909 }
hassof390d2c2004-09-10 20:48:21 +00001910
jardineb5d44e2003-12-23 08:09:43 +00001911 /*
1912 * Add the authentication info if it's present
1913 */
hassof390d2c2004-09-10 20:48:21 +00001914 (level == 1) ? (passwd = &circuit->area->area_passwd) :
1915 (passwd = &circuit->area->domain_passwd);
1916 if (passwd->type)
1917 {
1918 memcpy (&lsp->tlv_data.auth_info, passwd, sizeof (struct isis_passwd));
1919 tlv_add_authinfo (passwd->type, passwd->len, passwd->passwd, lsp->pdu);
1920 }
jardineb5d44e2003-12-23 08:09:43 +00001921
1922 if (lsp->tlv_data.is_neighs && listcount (lsp->tlv_data.is_neighs) > 0)
1923 tlv_add_is_neighs (lsp->tlv_data.is_neighs, lsp->pdu);
1924
1925 if (lsp->tlv_data.es_neighs && listcount (lsp->tlv_data.es_neighs) > 0)
1926 tlv_add_is_neighs (lsp->tlv_data.es_neighs, lsp->pdu);
1927
paul9985f832005-02-09 15:51:56 +00001928 lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
hassof390d2c2004-09-10 20:48:21 +00001929 iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
1930 ntohs (lsp->lsp_header->pdu_len) - 12, 12);
1931
jardineb5d44e2003-12-23 08:09:43 +00001932 list_delete (adj_list);
1933
1934 return;
1935}
1936
hasso92365882005-01-18 13:53:33 +00001937static int
jardineb5d44e2003-12-23 08:09:43 +00001938lsp_pseudo_regenerate (struct isis_circuit *circuit, int level)
1939{
1940 dict_t *lspdb = circuit->area->lspdb[level - 1];
1941 struct isis_lsp *lsp;
1942 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
hassof390d2c2004-09-10 20:48:21 +00001943
jardineb5d44e2003-12-23 08:09:43 +00001944 memcpy (lsp_id, isis->sysid, ISIS_SYS_ID_LEN);
hassof390d2c2004-09-10 20:48:21 +00001945 LSP_PSEUDO_ID (lsp_id) = circuit->circuit_id;
1946 LSP_FRAGMENT (lsp_id) = 0;
1947
jardineb5d44e2003-12-23 08:09:43 +00001948 lsp = lsp_search (lsp_id, lspdb);
hassof390d2c2004-09-10 20:48:21 +00001949
1950 if (!lsp)
1951 {
1952 zlog_err ("lsp_pseudo_regenerate(): no l%d LSP %s found!", level,
1953 rawlspid_print (lsp_id));
1954 return ISIS_ERROR;
1955 }
1956 lsp_clear_data (lsp);
jardineb5d44e2003-12-23 08:09:43 +00001957
1958 lsp_build_pseudo (lsp, circuit, level);
1959
hassof390d2c2004-09-10 20:48:21 +00001960 lsp->lsp_header->rem_lifetime =
jardineb5d44e2003-12-23 08:09:43 +00001961 htons (isis_jitter (circuit->area->max_lsp_lifetime[level - 1],
hassof390d2c2004-09-10 20:48:21 +00001962 MAX_AGE_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00001963
1964 lsp_inc_seqnum (lsp, 0);
hassof390d2c2004-09-10 20:48:21 +00001965
1966 if (isis->debugs & DEBUG_UPDATE_PACKETS)
1967 {
hasso529d65b2004-12-24 00:14:50 +00001968 zlog_debug ("ISIS-Upd (%s): refreshing pseudo LSP L%d %s",
1969 circuit->area->area_tag, level,
1970 rawlspid_print (lsp->lsp_header->lsp_id));
hassof390d2c2004-09-10 20:48:21 +00001971 }
jardineb5d44e2003-12-23 08:09:43 +00001972
1973 lsp->last_generated = time (NULL);
1974 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
hassof390d2c2004-09-10 20:48:21 +00001975
jardineb5d44e2003-12-23 08:09:43 +00001976 return ISIS_OK;
1977}
1978
jardineb5d44e2003-12-23 08:09:43 +00001979int
1980lsp_l1_refresh_pseudo (struct thread *thread)
1981{
1982 struct isis_circuit *circuit;
1983 int retval;
1984 unsigned long ref_time;
1985
hassof390d2c2004-09-10 20:48:21 +00001986 circuit = THREAD_ARG (thread);
1987
jardineb5d44e2003-12-23 08:09:43 +00001988 if (!circuit->u.bc.is_dr[0])
hassof390d2c2004-09-10 20:48:21 +00001989 return ISIS_ERROR; /* FIXME: purge and such */
1990
hasso13c48f72004-09-10 21:19:13 +00001991 circuit->u.bc.t_refresh_pseudo_lsp[0] = NULL;
1992
jardineb5d44e2003-12-23 08:09:43 +00001993 retval = lsp_pseudo_regenerate (circuit, 1);
hassof390d2c2004-09-10 20:48:21 +00001994
1995 ref_time = circuit->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
jardineb5d44e2003-12-23 08:09:43 +00001996 MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[0];
1997
hassof390d2c2004-09-10 20:48:21 +00001998 THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[0],
1999 lsp_l1_refresh_pseudo, circuit,
2000 isis_jitter (ref_time, MAX_AGE_JITTER));
2001
jardineb5d44e2003-12-23 08:09:43 +00002002 return retval;
2003}
2004
hassof390d2c2004-09-10 20:48:21 +00002005int
jardineb5d44e2003-12-23 08:09:43 +00002006lsp_l1_pseudo_generate (struct isis_circuit *circuit)
2007{
2008 struct isis_lsp *lsp;
2009 u_char id[ISIS_SYS_ID_LEN + 2];
2010 unsigned long ref_time;
2011
hassof390d2c2004-09-10 20:48:21 +00002012 memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
2013 LSP_FRAGMENT (id) = 0;
2014 LSP_PSEUDO_ID (id) = circuit->circuit_id;
jardineb5d44e2003-12-23 08:09:43 +00002015
2016 /*
2017 * If for some reason have a pseudo LSP in the db already -> regenerate
2018 */
2019 if (lsp_search (id, circuit->area->lspdb[0]))
2020 return lsp_pseudo_regenerate (circuit, 1);
2021 lsp = lsp_new (id, circuit->area->max_lsp_lifetime[0],
hassof390d2c2004-09-10 20:48:21 +00002022 1, circuit->area->is_type, 0, 1);
2023
jardineb5d44e2003-12-23 08:09:43 +00002024 lsp_build_pseudo (lsp, circuit, 1);
hassof390d2c2004-09-10 20:48:21 +00002025
jardineb5d44e2003-12-23 08:09:43 +00002026 lsp->own_lsp = 1;
2027 lsp_insert (lsp, circuit->area->lspdb[0]);
2028 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
2029
hassof390d2c2004-09-10 20:48:21 +00002030 ref_time = circuit->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
jardineb5d44e2003-12-23 08:09:43 +00002031 MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[0];
2032
hassof390d2c2004-09-10 20:48:21 +00002033 THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[0],
2034 lsp_l1_refresh_pseudo, circuit,
2035 isis_jitter (ref_time, MAX_AGE_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00002036
2037 return lsp_regenerate_schedule (circuit->area);
2038}
2039
2040int
2041lsp_l2_refresh_pseudo (struct thread *thread)
2042{
2043 struct isis_circuit *circuit;
2044 int retval;
2045 unsigned long ref_time;
hassof390d2c2004-09-10 20:48:21 +00002046 circuit = THREAD_ARG (thread);
2047
jardineb5d44e2003-12-23 08:09:43 +00002048 if (!circuit->u.bc.is_dr[1])
hassof390d2c2004-09-10 20:48:21 +00002049 return ISIS_ERROR; /* FIXME: purge and such */
2050
hasso13c48f72004-09-10 21:19:13 +00002051 circuit->u.bc.t_refresh_pseudo_lsp[1] = NULL;
2052
jardineb5d44e2003-12-23 08:09:43 +00002053 retval = lsp_pseudo_regenerate (circuit, 2);
2054
hassof390d2c2004-09-10 20:48:21 +00002055 ref_time = circuit->area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ?
jardineb5d44e2003-12-23 08:09:43 +00002056 MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[1];
2057
hassof390d2c2004-09-10 20:48:21 +00002058 THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[1],
2059 lsp_l2_refresh_pseudo, circuit,
2060 isis_jitter (ref_time, MAX_AGE_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00002061
jardineb5d44e2003-12-23 08:09:43 +00002062 return retval;
2063}
2064
hassof390d2c2004-09-10 20:48:21 +00002065int
jardineb5d44e2003-12-23 08:09:43 +00002066lsp_l2_pseudo_generate (struct isis_circuit *circuit)
2067{
2068 struct isis_lsp *lsp;
2069 u_char id[ISIS_SYS_ID_LEN + 2];
2070 unsigned long ref_time;
2071
hassof390d2c2004-09-10 20:48:21 +00002072 memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
2073 LSP_FRAGMENT (id) = 0;
2074 LSP_PSEUDO_ID (id) = circuit->circuit_id;
jardineb5d44e2003-12-23 08:09:43 +00002075
2076 if (lsp_search (id, circuit->area->lspdb[1]))
2077 return lsp_pseudo_regenerate (circuit, 2);
2078
2079 lsp = lsp_new (id, circuit->area->max_lsp_lifetime[1],
hassof390d2c2004-09-10 20:48:21 +00002080 1, circuit->area->is_type, 0, 2);
jardineb5d44e2003-12-23 08:09:43 +00002081
2082 lsp_build_pseudo (lsp, circuit, 2);
hassof390d2c2004-09-10 20:48:21 +00002083
2084 ref_time = circuit->area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ?
jardineb5d44e2003-12-23 08:09:43 +00002085 MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[1];
2086
2087
2088 lsp->own_lsp = 1;
2089 lsp_insert (lsp, circuit->area->lspdb[1]);
2090 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
hassof390d2c2004-09-10 20:48:21 +00002091
2092 THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[1],
2093 lsp_l2_refresh_pseudo, circuit,
2094 isis_jitter (ref_time, MAX_AGE_JITTER));
2095
jardineb5d44e2003-12-23 08:09:43 +00002096 return lsp_regenerate_schedule (circuit->area);
2097}
2098
jardineb5d44e2003-12-23 08:09:43 +00002099/*
2100 * Walk through LSPs for an area
2101 * - set remaining lifetime
2102 * - set LSPs with SRMflag set for sending
2103 */
hassof390d2c2004-09-10 20:48:21 +00002104int
jardineb5d44e2003-12-23 08:09:43 +00002105lsp_tick (struct thread *thread)
2106{
2107 struct isis_area *area;
2108 struct isis_circuit *circuit;
2109 struct isis_lsp *lsp;
2110 struct list *lsp_list;
paul1eb8ef22005-04-07 07:30:20 +00002111 struct listnode *lspnode, *lspnnode, *cnode;
jardineb5d44e2003-12-23 08:09:43 +00002112 dnode_t *dnode, *dnode_next;
2113 int level;
2114
2115 lsp_list = list_new ();
hassof390d2c2004-09-10 20:48:21 +00002116
jardineb5d44e2003-12-23 08:09:43 +00002117 area = THREAD_ARG (thread);
2118 assert (area);
hasso13c48f72004-09-10 21:19:13 +00002119 area->t_tick = NULL;
hassof390d2c2004-09-10 20:48:21 +00002120 THREAD_TIMER_ON (master, area->t_tick, lsp_tick, area, 1);
jardineb5d44e2003-12-23 08:09:43 +00002121
2122 /*
2123 * Build a list of LSPs with (any) SRMflag set
2124 * and removed the ones that have aged out
2125 */
hassof390d2c2004-09-10 20:48:21 +00002126 for (level = 0; level < ISIS_LEVELS; level++)
2127 {
2128 if (area->lspdb[level] && dict_count (area->lspdb[level]) > 0)
2129 {
2130 dnode = dict_first (area->lspdb[level]);
2131 while (dnode != NULL)
2132 {
2133 dnode_next = dict_next (area->lspdb[level], dnode);
2134 lsp = dnode_get (dnode);
2135 lsp_set_time (lsp);
2136 if (lsp->age_out == 0)
2137 {
jardineb5d44e2003-12-23 08:09:43 +00002138
hasso529d65b2004-12-24 00:14:50 +00002139 zlog_debug ("ISIS-Upd (%s): L%u LSP %s seq 0x%08x aged out",
2140 area->area_tag,
2141 lsp->level,
2142 rawlspid_print (lsp->lsp_header->lsp_id),
2143 ntohl (lsp->lsp_header->seq_num));
jardineb5d44e2003-12-23 08:09:43 +00002144
hassof390d2c2004-09-10 20:48:21 +00002145 lsp_destroy (lsp);
2146 dict_delete (area->lspdb[level], dnode);
2147 }
2148 else if (flags_any_set (lsp->SRMflags))
2149 listnode_add (lsp_list, lsp);
2150 dnode = dnode_next;
2151 }
jardineb5d44e2003-12-23 08:09:43 +00002152
hassof390d2c2004-09-10 20:48:21 +00002153 /*
2154 * Send LSPs on circuits indicated by the SRMflags
2155 */
2156 if (listcount (lsp_list) > 0)
2157 {
paul1eb8ef22005-04-07 07:30:20 +00002158 for (ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit))
hassof390d2c2004-09-10 20:48:21 +00002159 {
paul1eb8ef22005-04-07 07:30:20 +00002160 for (ALL_LIST_ELEMENTS (lsp_list, lspnode, lspnnode, lsp))
hassof390d2c2004-09-10 20:48:21 +00002161 {
hassof390d2c2004-09-10 20:48:21 +00002162 if (ISIS_CHECK_FLAG (lsp->SRMflags, circuit))
2163 {
2164 /* FIXME: if same or elder lsp is already in lsp
2165 * queue */
2166 listnode_add (circuit->lsp_queue, lsp);
2167 thread_add_event (master, send_lsp, circuit, 0);
2168 }
2169 }
2170 }
2171 }
2172 list_delete_all_node (lsp_list);
2173 }
jardineb5d44e2003-12-23 08:09:43 +00002174 }
jardineb5d44e2003-12-23 08:09:43 +00002175
2176 list_delete (lsp_list);
2177
2178 return ISIS_OK;
2179}
2180
jardineb5d44e2003-12-23 08:09:43 +00002181void
hassof390d2c2004-09-10 20:48:21 +00002182lsp_purge_dr (u_char * id, struct isis_circuit *circuit, int level)
jardineb5d44e2003-12-23 08:09:43 +00002183{
2184 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +00002185
jardineb5d44e2003-12-23 08:09:43 +00002186 lsp = lsp_search (id, circuit->area->lspdb[level - 1]);
hassof390d2c2004-09-10 20:48:21 +00002187
2188 if (lsp && lsp->purged == 0)
2189 {
2190 lsp->lsp_header->rem_lifetime = htons (0);
2191 lsp->lsp_header->pdu_len =
2192 htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
2193 lsp->purged = 0;
2194 iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
2195 ntohs (lsp->lsp_header->pdu_len) - 12, 12);
2196 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
2197 }
2198
jardineb5d44e2003-12-23 08:09:43 +00002199 return;
2200}
2201
2202/*
2203 * Purge own LSP that is received and we don't have.
2204 * -> Do as in 7.3.16.4
2205 */
2206void
hassof390d2c2004-09-10 20:48:21 +00002207lsp_purge_non_exist (struct isis_link_state_hdr *lsp_hdr,
2208 struct isis_area *area)
jardineb5d44e2003-12-23 08:09:43 +00002209{
2210 struct isis_lsp *lsp;
2211
2212 /*
2213 * We need to create the LSP to be purged
2214 */
hasso529d65b2004-12-24 00:14:50 +00002215 zlog_debug ("LSP PURGE NON EXIST");
jardineb5d44e2003-12-23 08:09:43 +00002216 lsp = XMALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
2217 memset (lsp, 0, sizeof (struct isis_lsp));
hassof390d2c2004-09-10 20:48:21 +00002218 /*FIXME: BUG BUG BUG! the lsp doesn't exist here! */
2219 /*did smt here, maybe good probably not */
jardineb5d44e2003-12-23 08:09:43 +00002220 lsp->level = ((lsp_hdr->lsp_bits & LSPBIT_IST) == IS_LEVEL_1) ? 1 : 2;
2221 lsp->pdu = stream_new (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
hassof390d2c2004-09-10 20:48:21 +00002222 lsp->isis_header = (struct isis_fixed_hdr *) STREAM_DATA (lsp->pdu);
jardineb5d44e2003-12-23 08:09:43 +00002223 fill_fixed_hdr (lsp->isis_header, (lsp->level == 1) ? L1_LINK_STATE
hassof390d2c2004-09-10 20:48:21 +00002224 : L2_LINK_STATE);
2225 lsp->lsp_header = (struct isis_link_state_hdr *) (STREAM_DATA (lsp->pdu) +
2226 ISIS_FIXED_HDR_LEN);
jardineb5d44e2003-12-23 08:09:43 +00002227 memcpy (lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN);
hassof390d2c2004-09-10 20:48:21 +00002228
jardineb5d44e2003-12-23 08:09:43 +00002229 /*
2230 * Retain only LSP header
2231 */
2232 lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
2233 /*
2234 * Set the remaining lifetime to 0
2235 */
2236 lsp->lsp_header->rem_lifetime = 0;
2237 /*
2238 * Put the lsp into LSPdb
2239 */
hassof390d2c2004-09-10 20:48:21 +00002240 lsp_insert (lsp, area->lspdb[lsp->level - 1]);
jardineb5d44e2003-12-23 08:09:43 +00002241
2242 /*
2243 * Send in to whole area
2244 */
2245 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
hassof390d2c2004-09-10 20:48:21 +00002246
jardineb5d44e2003-12-23 08:09:43 +00002247 return;
2248}
2249
2250#ifdef TOPOLOGY_GENERATE
hasso92365882005-01-18 13:53:33 +00002251static int
jardineb5d44e2003-12-23 08:09:43 +00002252top_lsp_refresh (struct thread *thread)
2253{
hassof390d2c2004-09-10 20:48:21 +00002254 struct isis_lsp *lsp;
jardineb5d44e2003-12-23 08:09:43 +00002255
2256 lsp = THREAD_ARG (thread);
2257 assert (lsp);
2258
2259 lsp->t_lsp_top_ref = NULL;
2260
hassof390d2c2004-09-10 20:48:21 +00002261 lsp->lsp_header->rem_lifetime =
2262 htons (isis_jitter (MAX_AGE, MAX_AGE_JITTER));
2263 lsp->lsp_header->seq_num = htonl (ntohl (lsp->lsp_header->seq_num) + 1);
jardineb5d44e2003-12-23 08:09:43 +00002264
2265 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
hassof390d2c2004-09-10 20:48:21 +00002266 if (isis->debugs & DEBUG_UPDATE_PACKETS)
2267 {
hasso529d65b2004-12-24 00:14:50 +00002268 zlog_debug ("ISIS-Upd (): refreshing Topology L1 %s",
2269 rawlspid_print (lsp->lsp_header->lsp_id));
hassof390d2c2004-09-10 20:48:21 +00002270 }
jardineb5d44e2003-12-23 08:09:43 +00002271
2272 /* time to calculate our checksum */
2273 iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
hassof390d2c2004-09-10 20:48:21 +00002274 ntohs (lsp->lsp_header->pdu_len) - 12, 12);
2275 THREAD_TIMER_ON (master, lsp->t_lsp_top_ref, top_lsp_refresh, lsp,
2276 isis_jitter (MAX_LSP_GEN_INTERVAL, MAX_LSP_GEN_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00002277
2278 return ISIS_OK;
2279}
2280
2281void
2282generate_topology_lsps (struct isis_area *area)
2283{
2284 struct listnode *node;
2285 int i, max = 0;
2286 struct arc *arc;
2287 u_char lspid[ISIS_SYS_ID_LEN + 2];
2288 struct isis_lsp *lsp;
2289
2290 /* first we find the maximal node */
paula8f03df2005-04-10 15:58:10 +00002291 for (ALL_LIST_ELEMENTS_RO (area->topology, node, arc))
hassof390d2c2004-09-10 20:48:21 +00002292 {
2293 if (arc->from_node > max)
2294 max = arc->from_node;
2295 if (arc->to_node > max)
2296 max = arc->to_node;
jardineb5d44e2003-12-23 08:09:43 +00002297 }
2298
hassof390d2c2004-09-10 20:48:21 +00002299 for (i = 1; i < (max + 1); i++)
2300 {
2301 memcpy (lspid, area->topology_baseis, ISIS_SYS_ID_LEN);
2302 LSP_PSEUDO_ID (lspid) = 0x00;
2303 LSP_FRAGMENT (lspid) = 0x00;
2304 lspid[ISIS_SYS_ID_LEN - 1] = (i & 0xFF);
2305 lspid[ISIS_SYS_ID_LEN - 2] = ((i >> 8) & 0xFF);
jardineb5d44e2003-12-23 08:09:43 +00002306
hassof390d2c2004-09-10 20:48:21 +00002307 lsp = lsp_new (lspid, isis_jitter (area->max_lsp_lifetime[0],
2308 MAX_AGE_JITTER), 1, IS_LEVEL_1, 0,
2309 1);
2310 lsp->from_topology = 1;
2311 /* creating data based on topology */
2312 build_topology_lsp_data (lsp, area, i);
2313 /* time to calculate our checksum */
2314 iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
2315 ntohs (lsp->lsp_header->pdu_len) - 12, 12);
2316 THREAD_TIMER_ON (master, lsp->t_lsp_top_ref, top_lsp_refresh, lsp,
2317 isis_jitter (MAX_LSP_GEN_INTERVAL,
2318 MAX_LSP_GEN_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00002319
hassof390d2c2004-09-10 20:48:21 +00002320 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
2321 lsp_insert (lsp, area->lspdb[0]);
jardineb5d44e2003-12-23 08:09:43 +00002322
hassof390d2c2004-09-10 20:48:21 +00002323 }
jardineb5d44e2003-12-23 08:09:43 +00002324}
2325
2326void
2327remove_topology_lsps (struct isis_area *area)
2328{
2329 struct isis_lsp *lsp;
2330 dnode_t *dnode, *dnode_next;
2331
2332 dnode = dict_first (area->lspdb[0]);
hassof390d2c2004-09-10 20:48:21 +00002333 while (dnode != NULL)
2334 {
2335 dnode_next = dict_next (area->lspdb[0], dnode);
2336 lsp = dnode_get (dnode);
2337 if (lsp->from_topology)
2338 {
2339 THREAD_TIMER_OFF (lsp->t_lsp_top_ref);
2340 lsp_destroy (lsp);
2341 dict_delete (area->lspdb[0], dnode);
2342 }
2343 dnode = dnode_next;
jardineb5d44e2003-12-23 08:09:43 +00002344 }
jardineb5d44e2003-12-23 08:09:43 +00002345}
2346
2347void
hassof390d2c2004-09-10 20:48:21 +00002348build_topology_lsp_data (struct isis_lsp *lsp, struct isis_area *area,
jardineb5d44e2003-12-23 08:09:43 +00002349 int lsp_top_num)
2350{
paula8f03df2005-04-10 15:58:10 +00002351 struct listnode *node, *nnode;
jardineb5d44e2003-12-23 08:09:43 +00002352 struct arc *arc;
2353 u_char *tlv_ptr;
2354 struct is_neigh *is_neigh;
2355 int to_lsp = 0;
2356 char buff[200];
2357
2358 /* add our nlpids */
hassof390d2c2004-09-10 20:48:21 +00002359 /* the 2 is for the TL plus 1 for the nlpid */
2360 tlv_ptr = lsppdu_realloc (lsp, MTYPE_ISIS_TLV, 3);
2361 *tlv_ptr = PROTOCOLS_SUPPORTED; /* Type */
2362 *(tlv_ptr + 1) = 1; /* one protocol */
2363 *(tlv_ptr + 2) = NLPID_IP;
2364 lsp->tlv_data.nlpids = (struct nlpids *) (tlv_ptr + 1);
jardineb5d44e2003-12-23 08:09:43 +00002365
2366 /* first, lets add the tops */
hassof390d2c2004-09-10 20:48:21 +00002367 /* the 2 is for the TL plus 1 for the virtual field */
2368 tlv_ptr = lsppdu_realloc (lsp, MTYPE_ISIS_TLV, 3);
2369 *tlv_ptr = IS_NEIGHBOURS; /* Type */
2370 *(tlv_ptr + 1) = 1; /* this is the virtual char len */
2371 *(tlv_ptr + 2) = 0; /* virtual is zero */
2372 lsp->tlv_data.is_neighs = list_new (); /* new list of is_neighbours */
jardineb5d44e2003-12-23 08:09:43 +00002373
2374 /* add reachability for this IS for simulated 1 */
hassof390d2c2004-09-10 20:48:21 +00002375 if (lsp_top_num == 1)
2376 {
jardineb5d44e2003-12-23 08:09:43 +00002377 /* assign space for the is_neigh at the pdu end */
hassof390d2c2004-09-10 20:48:21 +00002378 is_neigh = (struct is_neigh *) lsppdu_realloc (lsp, MTYPE_ISIS_TLV,
2379 sizeof (struct
2380 is_neigh));
jardineb5d44e2003-12-23 08:09:43 +00002381 /* add this node to our list */
hassof390d2c2004-09-10 20:48:21 +00002382 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
2383 memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
jardineb5d44e2003-12-23 08:09:43 +00002384 LSP_PSEUDO_ID (is_neigh->neigh_id) = 0x00;
hassof390d2c2004-09-10 20:48:21 +00002385 is_neigh->metrics.metric_default = 0x00; /* no special reason */
jardineb5d44e2003-12-23 08:09:43 +00002386 is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
2387 is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
2388 is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
2389 /* don't forget the length */
hassof390d2c2004-09-10 20:48:21 +00002390 *(tlv_ptr + 1) += IS_NEIGHBOURS_LEN; /* the -1 is the virtual */
2391 /* no need to check for fragging here, it is a lonely is_reach */
jardineb5d44e2003-12-23 08:09:43 +00002392 }
hassof390d2c2004-09-10 20:48:21 +00002393
2394 /* addding is reachabilities */
paula8f03df2005-04-10 15:58:10 +00002395 for (ALL_LIST_ELEMENTS (area->topology, node, nnode, arc))
hassof390d2c2004-09-10 20:48:21 +00002396 {
2397 if ((arc->from_node == lsp_top_num) || (arc->to_node == lsp_top_num))
2398 {
2399 if (arc->to_node == lsp_top_num)
2400 to_lsp = arc->from_node;
2401 if (arc->from_node == lsp_top_num)
2402 to_lsp = arc->to_node;
2403
2404 /* if the length here is about to cross the FF limit, we reTLV */
2405 if (*(tlv_ptr + 1) >= (0xFF - IS_NEIGHBOURS_LEN))
2406 {
2407 /* retlv */
2408 /* the 2 is for the TL plus 1 for the virtual field */
2409 tlv_ptr = lsppdu_realloc (lsp, MTYPE_ISIS_TLV, 3);
2410 *tlv_ptr = IS_NEIGHBOURS; /* Type */
2411 *(tlv_ptr + 1) = 1; /* this is the virtual char len */
2412 *(tlv_ptr + 2) = 0; /* virtual is zero */
2413 }
2414 /* doing this here assures us that we won't add an "empty" tlv */
2415 /* assign space for the is_neigh at the pdu end */
2416 is_neigh = (struct is_neigh *) lsppdu_realloc (lsp, MTYPE_ISIS_TLV,
2417 sizeof (struct
2418 is_neigh));
2419 /* add this node to our list */
2420 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
2421 memcpy (&is_neigh->neigh_id, area->topology_baseis, ISIS_SYS_ID_LEN);
2422 LSP_PSEUDO_ID (is_neigh->neigh_id) = 0x00;
2423 is_neigh->neigh_id[ISIS_SYS_ID_LEN - 1] = (to_lsp & 0xFF);
2424 is_neigh->neigh_id[ISIS_SYS_ID_LEN - 2] = ((to_lsp >> 8) & 0xFF);
2425 is_neigh->metrics.metric_default = arc->distance;
2426 is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
2427 is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
2428 is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
2429 /* don't forget the length */
2430 *(tlv_ptr + 1) += IS_NEIGHBOURS_LEN; /* the -1 is the virtual */
2431 }
jardineb5d44e2003-12-23 08:09:43 +00002432 }
2433
hassof390d2c2004-09-10 20:48:21 +00002434 /* adding dynamic hostname if needed */
2435 if (area->dynhostname)
2436 {
2437 memset (buff, 0x00, 200);
2438 sprintf (buff, "feedme%d", lsp_top_num);
2439 /* the 2 is for the TL */
2440 tlv_ptr = lsppdu_realloc (lsp, MTYPE_ISIS_TLV, 2);
2441 *tlv_ptr = DYNAMIC_HOSTNAME; /* Type */
2442 *(tlv_ptr + 1) = strlen (buff); /* Length */
2443 /* the -1 is to fit the length in the struct */
2444 lsp->tlv_data.hostname = (struct hostname *)
2445 (lsppdu_realloc (lsp, MTYPE_ISIS_TLV, strlen (buff)) - 1);
2446 memcpy (lsp->tlv_data.hostname->name, buff, strlen (buff));
2447 }
jardineb5d44e2003-12-23 08:09:43 +00002448}
2449#endif /* TOPOLOGY_GENERATE */