blob: 7b4491c2fa886eb45ad441613a4cd0d935b6d043 [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);
hassoaa4376e2005-09-26 17:39:48 +0000123 if (lsp->tlv_data.te_is_neighs)
124 list_delete (lsp->tlv_data.te_is_neighs);
jardineb5d44e2003-12-23 08:09:43 +0000125 if (lsp->tlv_data.area_addrs)
126 list_delete (lsp->tlv_data.area_addrs);
127 if (lsp->tlv_data.es_neighs)
128 list_delete (lsp->tlv_data.es_neighs);
129 if (lsp->tlv_data.ipv4_addrs)
130 list_delete (lsp->tlv_data.ipv4_addrs);
131 if (lsp->tlv_data.ipv4_int_reachs)
132 list_delete (lsp->tlv_data.ipv4_int_reachs);
133 if (lsp->tlv_data.ipv4_ext_reachs)
134 list_delete (lsp->tlv_data.ipv4_ext_reachs);
hassoaa4376e2005-09-26 17:39:48 +0000135 if (lsp->tlv_data.te_ipv4_reachs)
136 list_delete (lsp->tlv_data.te_ipv4_reachs);
jardineb5d44e2003-12-23 08:09:43 +0000137#ifdef HAVE_IPV6
138 if (lsp->tlv_data.ipv6_addrs)
139 list_delete (lsp->tlv_data.ipv6_addrs);
140 if (lsp->tlv_data.ipv6_reachs)
141 list_delete (lsp->tlv_data.ipv6_reachs);
142#endif /* HAVE_IPV6 */
143
144 memset (&lsp->tlv_data, 0, sizeof (struct tlvs));
145
146 return;
147}
148
hasso92365882005-01-18 13:53:33 +0000149static void
jardineb5d44e2003-12-23 08:09:43 +0000150lsp_destroy (struct isis_lsp *lsp)
151{
152 if (!lsp)
153 return;
hassof390d2c2004-09-10 20:48:21 +0000154
jardineb5d44e2003-12-23 08:09:43 +0000155 lsp_clear_data (lsp);
hassof390d2c2004-09-10 20:48:21 +0000156
157 if (LSP_FRAGMENT (lsp->lsp_header->lsp_id) == 0 && lsp->lspu.frags)
158 {
jardineb5d44e2003-12-23 08:09:43 +0000159 list_delete (lsp->lspu.frags);
hassof390d2c2004-09-10 20:48:21 +0000160 }
161
jardineb5d44e2003-12-23 08:09:43 +0000162 if (lsp->pdu)
163 stream_free (lsp->pdu);
164 XFREE (MTYPE_ISIS_LSP, lsp);
165}
166
hassof390d2c2004-09-10 20:48:21 +0000167void
168lsp_db_destroy (dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +0000169{
170 dnode_t *dnode, *next;
171 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +0000172
jardineb5d44e2003-12-23 08:09:43 +0000173 dnode = dict_first (lspdb);
hassof390d2c2004-09-10 20:48:21 +0000174 while (dnode)
175 {
176 next = dict_next (lspdb, dnode);
177 lsp = dnode_get (dnode);
178 lsp_destroy (lsp);
179 dict_delete_free (lspdb, dnode);
180 dnode = next;
181 }
182
jardineb5d44e2003-12-23 08:09:43 +0000183 dict_free (lspdb);
hassof390d2c2004-09-10 20:48:21 +0000184
jardineb5d44e2003-12-23 08:09:43 +0000185 return;
186}
187
188/*
189 * Remove all the frags belonging to the given lsp
190 */
hasso92365882005-01-18 13:53:33 +0000191static void
hassof390d2c2004-09-10 20:48:21 +0000192lsp_remove_frags (struct list *frags, dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +0000193{
194 dnode_t *dnode;
paul1eb8ef22005-04-07 07:30:20 +0000195 struct listnode *lnode, *lnnode;
jardineb5d44e2003-12-23 08:09:43 +0000196 struct isis_lsp *lsp;
197
paul1eb8ef22005-04-07 07:30:20 +0000198 for (ALL_LIST_ELEMENTS (frags, lnode, lnnode, lsp))
hassof390d2c2004-09-10 20:48:21 +0000199 {
hassof390d2c2004-09-10 20:48:21 +0000200 dnode = dict_lookup (lspdb, lsp->lsp_header->lsp_id);
201 lsp_destroy (lsp);
202 dnode_destroy (dict_delete (lspdb, dnode));
203 }
204
jardineb5d44e2003-12-23 08:09:43 +0000205 list_delete_all_node (frags);
hassof390d2c2004-09-10 20:48:21 +0000206
jardineb5d44e2003-12-23 08:09:43 +0000207 return;
208}
209
210void
hassof390d2c2004-09-10 20:48:21 +0000211lsp_search_and_destroy (u_char * id, dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +0000212{
213 dnode_t *node;
214 struct isis_lsp *lsp;
215
216 node = dict_lookup (lspdb, id);
hassof390d2c2004-09-10 20:48:21 +0000217 if (node)
218 {
219 node = dict_delete (lspdb, node);
220 lsp = dnode_get (node);
221 /*
222 * If this is a zero lsp, remove all the frags now
223 */
224 if (LSP_FRAGMENT (lsp->lsp_header->lsp_id) == 0)
225 {
226 if (lsp->lspu.frags)
227 lsp_remove_frags (lsp->lspu.frags, lspdb);
228 }
229 else
230 {
231 /*
232 * else just remove this frag, from the zero lsps' frag list
233 */
234 if (lsp->lspu.zero_lsp && lsp->lspu.zero_lsp->lspu.frags)
235 listnode_delete (lsp->lspu.zero_lsp->lspu.frags, lsp);
236 }
237 lsp_destroy (lsp);
238 dnode_destroy (node);
jardineb5d44e2003-12-23 08:09:43 +0000239 }
jardineb5d44e2003-12-23 08:09:43 +0000240}
241
242/*
243 * Compares a LSP to given values
244 * Params are given in net order
245 */
hassof390d2c2004-09-10 20:48:21 +0000246int
247lsp_compare (char *areatag, struct isis_lsp *lsp, u_int32_t seq_num,
jardineb5d44e2003-12-23 08:09:43 +0000248 u_int16_t checksum, u_int16_t rem_lifetime)
249{
hassof390d2c2004-09-10 20:48:21 +0000250 /* no point in double ntohl on seqnum */
251 if (lsp->lsp_header->seq_num == seq_num &&
jardineb5d44e2003-12-23 08:09:43 +0000252 lsp->lsp_header->checksum == checksum &&
253 /*comparing with 0, no need to do ntohl */
254 ((lsp->lsp_header->rem_lifetime == 0 && rem_lifetime == 0) ||
hassof390d2c2004-09-10 20:48:21 +0000255 (lsp->lsp_header->rem_lifetime != 0 && rem_lifetime != 0)))
256 {
257 if (isis->debugs & DEBUG_SNP_PACKETS)
258 {
hasso529d65b2004-12-24 00:14:50 +0000259 zlog_debug ("ISIS-Snp (%s): LSP %s seq 0x%08x, cksum 0x%04x,"
260 " lifetime %us",
261 areatag,
262 rawlspid_print (lsp->lsp_header->lsp_id),
263 ntohl (lsp->lsp_header->seq_num),
264 ntohs (lsp->lsp_header->checksum),
265 ntohs (lsp->lsp_header->rem_lifetime));
266 zlog_debug ("ISIS-Snp (%s): is equal to ours seq 0x%08x,"
267 " cksum 0x%04x, lifetime %us",
268 areatag,
269 ntohl (seq_num), ntohs (checksum), ntohs (rem_lifetime));
hassof390d2c2004-09-10 20:48:21 +0000270 }
271 return LSP_EQUAL;
jardineb5d44e2003-12-23 08:09:43 +0000272 }
jardineb5d44e2003-12-23 08:09:43 +0000273
hassof390d2c2004-09-10 20:48:21 +0000274 if (ntohl (seq_num) >= ntohl (lsp->lsp_header->seq_num))
275 {
276 if (isis->debugs & DEBUG_SNP_PACKETS)
277 {
hasso529d65b2004-12-24 00:14:50 +0000278 zlog_debug ("ISIS-Snp (%s): LSP %s seq 0x%08x, cksum 0x%04x,"
279 " lifetime %us",
280 areatag,
281 rawlspid_print (lsp->lsp_header->lsp_id),
282 ntohl (seq_num), ntohs (checksum), ntohs (rem_lifetime));
283 zlog_debug ("ISIS-Snp (%s): is newer than ours seq 0x%08x, "
284 "cksum 0x%04x, lifetime %us",
285 areatag,
286 ntohl (lsp->lsp_header->seq_num),
287 ntohs (lsp->lsp_header->checksum),
288 ntohs (lsp->lsp_header->rem_lifetime));
hassof390d2c2004-09-10 20:48:21 +0000289 }
290 return LSP_NEWER;
jardineb5d44e2003-12-23 08:09:43 +0000291 }
hassof390d2c2004-09-10 20:48:21 +0000292 if (isis->debugs & DEBUG_SNP_PACKETS)
293 {
hasso529d65b2004-12-24 00:14:50 +0000294 zlog_debug
hassof390d2c2004-09-10 20:48:21 +0000295 ("ISIS-Snp (%s): LSP %s seq 0x%08x, cksum 0x%04x, lifetime %us",
296 areatag, rawlspid_print (lsp->lsp_header->lsp_id), ntohl (seq_num),
297 ntohs (checksum), ntohs (rem_lifetime));
hasso529d65b2004-12-24 00:14:50 +0000298 zlog_debug ("ISIS-Snp (%s): is older than ours seq 0x%08x,"
299 " cksum 0x%04x, lifetime %us", areatag,
300 ntohl (lsp->lsp_header->seq_num),
301 ntohs (lsp->lsp_header->checksum),
302 ntohs (lsp->lsp_header->rem_lifetime));
hassof390d2c2004-09-10 20:48:21 +0000303 }
jardineb5d44e2003-12-23 08:09:43 +0000304
305 return LSP_OLDER;
306}
307
hassof390d2c2004-09-10 20:48:21 +0000308void
jardineb5d44e2003-12-23 08:09:43 +0000309lsp_inc_seqnum (struct isis_lsp *lsp, u_int32_t seq_num)
310{
311 u_int32_t newseq;
hassof390d2c2004-09-10 20:48:21 +0000312
jardineb5d44e2003-12-23 08:09:43 +0000313 if (seq_num == 0 || ntohl (lsp->lsp_header->seq_num) > seq_num)
314 newseq = ntohl (lsp->lsp_header->seq_num) + 1;
315 else
hassof390d2c2004-09-10 20:48:21 +0000316 newseq = seq_num++;
317
jardineb5d44e2003-12-23 08:09:43 +0000318 lsp->lsp_header->seq_num = htonl (newseq);
hassof390d2c2004-09-10 20:48:21 +0000319 iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
320 ntohs (lsp->lsp_header->pdu_len) - 12, 12);
jardineb5d44e2003-12-23 08:09:43 +0000321
322 return;
323}
324
325/*
326 * Genetates checksum for LSP and its frags
327 */
hasso92365882005-01-18 13:53:33 +0000328static void
jardineb5d44e2003-12-23 08:09:43 +0000329lsp_seqnum_update (struct isis_lsp *lsp0)
330{
331 struct isis_lsp *lsp;
hasso3fdb2dd2005-09-28 18:45:54 +0000332 struct listnode *node;
hassof390d2c2004-09-10 20:48:21 +0000333
jardineb5d44e2003-12-23 08:09:43 +0000334 lsp_inc_seqnum (lsp0, 0);
335
336 if (!lsp0->lspu.frags)
337 return;
338
hasso3fdb2dd2005-09-28 18:45:54 +0000339 for (ALL_LIST_ELEMENTS_RO (lsp0->lspu.frags, node, lsp))
paul1eb8ef22005-04-07 07:30:20 +0000340 lsp_inc_seqnum (lsp, 0);
hassof390d2c2004-09-10 20:48:21 +0000341
jardineb5d44e2003-12-23 08:09:43 +0000342 return;
343}
344
hassof390d2c2004-09-10 20:48:21 +0000345int
jardineb5d44e2003-12-23 08:09:43 +0000346isis_lsp_authinfo_check (struct stream *stream, struct isis_area *area,
hassof390d2c2004-09-10 20:48:21 +0000347 int pdulen, struct isis_passwd *passwd)
jardineb5d44e2003-12-23 08:09:43 +0000348{
349 uint32_t expected = 0, found;
350 struct tlvs tlvs;
351 int retval = 0;
352
353 expected |= TLVFLAG_AUTH_INFO;
354 retval = parse_tlvs (area->area_tag, stream->data +
hassof390d2c2004-09-10 20:48:21 +0000355 ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN,
356 pdulen - ISIS_FIXED_HDR_LEN
357 - ISIS_LSP_HDR_LEN, &expected, &found, &tlvs);
jardineb5d44e2003-12-23 08:09:43 +0000358 if (retval || !(found & TLVFLAG_AUTH_INFO))
hassof390d2c2004-09-10 20:48:21 +0000359 return 1; /* Auth fail (parsing failed or no auth-tlv) */
jardineb5d44e2003-12-23 08:09:43 +0000360
361 return authentication_check (passwd, &tlvs.auth_info);
362}
363
hasso92365882005-01-18 13:53:33 +0000364static void
hassof390d2c2004-09-10 20:48:21 +0000365lsp_update_data (struct isis_lsp *lsp, struct stream *stream,
366 struct isis_area *area)
jardineb5d44e2003-12-23 08:09:43 +0000367{
hassof390d2c2004-09-10 20:48:21 +0000368 uint32_t expected = 0, found;
jardineb5d44e2003-12-23 08:09:43 +0000369 int retval;
hassof390d2c2004-09-10 20:48:21 +0000370
jardineb5d44e2003-12-23 08:09:43 +0000371 /* copying only the relevant part of our stream */
paul15935e92005-05-03 09:27:23 +0000372 lsp->pdu = stream_dup (stream);
373
jardineb5d44e2003-12-23 08:09:43 +0000374 /* setting pointers to the correct place */
hassof390d2c2004-09-10 20:48:21 +0000375 lsp->isis_header = (struct isis_fixed_hdr *) (STREAM_DATA (lsp->pdu));
376 lsp->lsp_header = (struct isis_link_state_hdr *) (STREAM_DATA (lsp->pdu) +
377 ISIS_FIXED_HDR_LEN);
jardineb5d44e2003-12-23 08:09:43 +0000378 lsp->age_out = ZERO_AGE_LIFETIME;
hassof390d2c2004-09-10 20:48:21 +0000379 lsp->installed = time (NULL);
jardineb5d44e2003-12-23 08:09:43 +0000380 /*
381 * Get LSP data i.e. TLVs
382 */
383 expected |= TLVFLAG_AUTH_INFO;
384 expected |= TLVFLAG_AREA_ADDRS;
385 expected |= TLVFLAG_IS_NEIGHS;
hassof390d2c2004-09-10 20:48:21 +0000386 if ((lsp->lsp_header->lsp_bits & 3) == 3) /* a level 2 LSP */
jardineb5d44e2003-12-23 08:09:43 +0000387 expected |= TLVFLAG_PARTITION_DESIG_LEVEL2_IS;
388 expected |= TLVFLAG_NLPID;
389 if (area->dynhostname)
390 expected |= TLVFLAG_DYN_HOSTNAME;
hassof390d2c2004-09-10 20:48:21 +0000391 if (area->newmetric)
392 {
393 expected |= TLVFLAG_TE_IS_NEIGHS;
394 expected |= TLVFLAG_TE_IPV4_REACHABILITY;
395 expected |= TLVFLAG_TE_ROUTER_ID;
396 }
jardineb5d44e2003-12-23 08:09:43 +0000397 expected |= TLVFLAG_IPV4_ADDR;
398 expected |= TLVFLAG_IPV4_INT_REACHABILITY;
399 expected |= TLVFLAG_IPV4_EXT_REACHABILITY;
400#ifdef HAVE_IPV6
401 expected |= TLVFLAG_IPV6_ADDR;
402 expected |= TLVFLAG_IPV6_REACHABILITY;
403#endif /* HAVE_IPV6 */
404
405 retval = parse_tlvs (area->area_tag, lsp->pdu->data +
hassof390d2c2004-09-10 20:48:21 +0000406 ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN,
407 ntohs (lsp->lsp_header->pdu_len) - ISIS_FIXED_HDR_LEN
408 - ISIS_LSP_HDR_LEN, &expected, &found, &lsp->tlv_data);
jardineb5d44e2003-12-23 08:09:43 +0000409
hassof390d2c2004-09-10 20:48:21 +0000410 if (found & TLVFLAG_DYN_HOSTNAME)
411 {
412 if (area->dynhostname)
413 isis_dynhn_insert (lsp->lsp_header->lsp_id, lsp->tlv_data.hostname,
414 (lsp->lsp_header->lsp_bits & LSPBIT_IST) ==
415 IS_LEVEL_1_AND_2 ? IS_LEVEL_2 :
416 (lsp->lsp_header->lsp_bits & LSPBIT_IST));
417 }
jardineb5d44e2003-12-23 08:09:43 +0000418
419}
420
421void
422lsp_update (struct isis_lsp *lsp, struct isis_link_state_hdr *lsp_hdr,
hassoa96d8d12005-09-16 14:44:23 +0000423 struct stream *stream, struct isis_area *area, int level)
jardineb5d44e2003-12-23 08:09:43 +0000424{
hasso4eda93a2005-09-18 17:51:02 +0000425 dnode_t *dnode = NULL;
hassoa96d8d12005-09-16 14:44:23 +0000426
427 /* Remove old LSP from LSP database. */
hasso4eda93a2005-09-18 17:51:02 +0000428 dnode = dict_lookup (area->lspdb[level - 1], lsp->lsp_header->lsp_id);
429 if (dnode)
430 dnode_destroy (dict_delete (area->lspdb[level - 1], dnode));
hassoa96d8d12005-09-16 14:44:23 +0000431
hassof390d2c2004-09-10 20:48:21 +0000432 /* free the old lsp data */
jardineb5d44e2003-12-23 08:09:43 +0000433 XFREE (MTYPE_STREAM_DATA, lsp->pdu);
434 lsp_clear_data (lsp);
435
436 /* rebuild the lsp data */
437 lsp_update_data (lsp, stream, area);
438
hassof390d2c2004-09-10 20:48:21 +0000439 /* set the new values for lsp header */
jardineb5d44e2003-12-23 08:09:43 +0000440 memcpy (lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN);
hassoa96d8d12005-09-16 14:44:23 +0000441
hasso4eda93a2005-09-18 17:51:02 +0000442 if (dnode)
443 lsp_insert (lsp, area->lspdb[level - 1]);
jardineb5d44e2003-12-23 08:09:43 +0000444}
445
jardineb5d44e2003-12-23 08:09:43 +0000446/* creation of LSP directly from what we received */
447struct isis_lsp *
hassof390d2c2004-09-10 20:48:21 +0000448lsp_new_from_stream_ptr (struct stream *stream,
449 u_int16_t pdu_len, struct isis_lsp *lsp0,
450 struct isis_area *area)
jardineb5d44e2003-12-23 08:09:43 +0000451{
452 struct isis_lsp *lsp;
453
hassoaac372f2005-09-01 17:52:33 +0000454 lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
jardineb5d44e2003-12-23 08:09:43 +0000455 lsp_update_data (lsp, stream, area);
hassof390d2c2004-09-10 20:48:21 +0000456
457 if (lsp0 == NULL)
458 {
459 /*
460 * zero lsp -> create the list for fragments
461 */
462 lsp->lspu.frags = list_new ();
463 }
464 else
465 {
466 /*
467 * a fragment -> set the backpointer and add this to zero lsps frag list
468 */
469 lsp->lspu.zero_lsp = lsp0;
470 listnode_add (lsp0->lspu.frags, lsp);
471 }
472
jardineb5d44e2003-12-23 08:09:43 +0000473 return lsp;
474}
475
476struct isis_lsp *
hassof390d2c2004-09-10 20:48:21 +0000477lsp_new (u_char * lsp_id, u_int16_t rem_lifetime, u_int32_t seq_num,
478 u_int8_t lsp_bits, u_int16_t checksum, int level)
jardineb5d44e2003-12-23 08:09:43 +0000479{
480 struct isis_lsp *lsp;
481
hassoaac372f2005-09-01 17:52:33 +0000482 lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
hassof390d2c2004-09-10 20:48:21 +0000483 if (!lsp)
484 {
485 /* FIXME: set lspdbol bit */
486 zlog_warn ("lsp_new(): out of memory");
487 return NULL;
488 }
jardineb5d44e2003-12-23 08:09:43 +0000489#ifdef LSP_MEMORY_PREASSIGN
hassof390d2c2004-09-10 20:48:21 +0000490 lsp->pdu = stream_new (1514); /*Should be minimal mtu? yup... */
jardineb5d44e2003-12-23 08:09:43 +0000491#else
hassof390d2c2004-09-10 20:48:21 +0000492 /* We need to do realloc on TLVs additions */
493 lsp->pdu = malloc (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
jardineb5d44e2003-12-23 08:09:43 +0000494#endif /* LSP_MEMORY_PREASSIGN */
495 if (LSP_FRAGMENT (lsp_id) == 0)
496 lsp->lspu.frags = list_new ();
hassof390d2c2004-09-10 20:48:21 +0000497 lsp->isis_header = (struct isis_fixed_hdr *) (STREAM_DATA (lsp->pdu));
498 lsp->lsp_header = (struct isis_link_state_hdr *)
499 (STREAM_DATA (lsp->pdu) + ISIS_FIXED_HDR_LEN);
500
jardineb5d44e2003-12-23 08:09:43 +0000501 /* at first we fill the FIXED HEADER */
hassof390d2c2004-09-10 20:48:21 +0000502 (level == 1) ? fill_fixed_hdr (lsp->isis_header, L1_LINK_STATE) :
503 fill_fixed_hdr (lsp->isis_header, L2_LINK_STATE);
504
jardineb5d44e2003-12-23 08:09:43 +0000505 /* now for the LSP HEADER */
506 /* Minimal LSP PDU size */
hassof390d2c2004-09-10 20:48:21 +0000507 lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
jardineb5d44e2003-12-23 08:09:43 +0000508 memcpy (lsp->lsp_header->lsp_id, lsp_id, ISIS_SYS_ID_LEN + 2);
hassof390d2c2004-09-10 20:48:21 +0000509 lsp->lsp_header->checksum = checksum; /* Provided in network order */
jardineb5d44e2003-12-23 08:09:43 +0000510 lsp->lsp_header->seq_num = htonl (seq_num);
511 lsp->lsp_header->rem_lifetime = htons (rem_lifetime);
512 lsp->lsp_header->lsp_bits = lsp_bits;
513 lsp->level = level;
514 lsp->age_out = ZERO_AGE_LIFETIME;
515
paul9985f832005-02-09 15:51:56 +0000516 stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
jardineb5d44e2003-12-23 08:09:43 +0000517
hassoc89c05d2005-09-04 21:36:36 +0000518 if (isis->debugs & DEBUG_EVENTS)
519 zlog_debug ("New LSP with ID %s-%02x-%02x seqnum %08x",
520 sysid_print (lsp_id), LSP_PSEUDO_ID (lsp->lsp_header->lsp_id),
521 LSP_FRAGMENT (lsp->lsp_header->lsp_id),
522 ntohl (lsp->lsp_header->seq_num));
jardineb5d44e2003-12-23 08:09:43 +0000523
524 return lsp;
525}
526
527void
hassof390d2c2004-09-10 20:48:21 +0000528lsp_insert (struct isis_lsp *lsp, dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +0000529{
530 dict_alloc_insert (lspdb, lsp->lsp_header->lsp_id, lsp);
531}
532
533/*
534 * Build a list of LSPs with non-zero ht bounded by start and stop ids
535 */
hassof390d2c2004-09-10 20:48:21 +0000536void
537lsp_build_list_nonzero_ht (u_char * start_id, u_char * stop_id,
538 struct list *list, dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +0000539{
540 dnode_t *first, *last, *curr;
541
542 first = dict_lower_bound (lspdb, start_id);
543 if (!first)
544 return;
hassof390d2c2004-09-10 20:48:21 +0000545
jardineb5d44e2003-12-23 08:09:43 +0000546 last = dict_upper_bound (lspdb, stop_id);
hassof390d2c2004-09-10 20:48:21 +0000547
jardineb5d44e2003-12-23 08:09:43 +0000548 curr = first;
hassof390d2c2004-09-10 20:48:21 +0000549
550 if (((struct isis_lsp *) (curr->dict_data))->lsp_header->rem_lifetime)
jardineb5d44e2003-12-23 08:09:43 +0000551 listnode_add (list, first->dict_data);
552
hassof390d2c2004-09-10 20:48:21 +0000553 while (curr)
554 {
555 curr = dict_next (lspdb, curr);
556 if (curr &&
557 ((struct isis_lsp *) (curr->dict_data))->lsp_header->rem_lifetime)
558 listnode_add (list, curr->dict_data);
559 if (curr == last)
560 break;
561 }
562
jardineb5d44e2003-12-23 08:09:43 +0000563 return;
564}
565
566/*
567 * Build a list of all LSPs bounded by start and stop ids
568 */
hassof390d2c2004-09-10 20:48:21 +0000569void
570lsp_build_list (u_char * start_id, u_char * stop_id,
571 struct list *list, dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +0000572{
573 dnode_t *first, *last, *curr;
574
575 first = dict_lower_bound (lspdb, start_id);
576 if (!first)
577 return;
hassof390d2c2004-09-10 20:48:21 +0000578
jardineb5d44e2003-12-23 08:09:43 +0000579 last = dict_upper_bound (lspdb, stop_id);
hassof390d2c2004-09-10 20:48:21 +0000580
jardineb5d44e2003-12-23 08:09:43 +0000581 curr = first;
hassof390d2c2004-09-10 20:48:21 +0000582
jardineb5d44e2003-12-23 08:09:43 +0000583 listnode_add (list, first->dict_data);
584
hassof390d2c2004-09-10 20:48:21 +0000585 while (curr)
586 {
587 curr = dict_next (lspdb, curr);
588 if (curr)
589 listnode_add (list, curr->dict_data);
590 if (curr == last)
591 break;
592 }
593
jardineb5d44e2003-12-23 08:09:43 +0000594 return;
595}
596
597/*
598 * Build a list of LSPs with SSN flag set for the given circuit
599 */
600void
hassof390d2c2004-09-10 20:48:21 +0000601lsp_build_list_ssn (struct isis_circuit *circuit, struct list *list,
602 dict_t * lspdb)
jardineb5d44e2003-12-23 08:09:43 +0000603{
604 dnode_t *dnode, *next;
605 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +0000606
jardineb5d44e2003-12-23 08:09:43 +0000607 dnode = dict_first (lspdb);
hassof390d2c2004-09-10 20:48:21 +0000608 while (dnode != NULL)
609 {
610 next = dict_next (lspdb, dnode);
611 lsp = dnode_get (dnode);
612 if (ISIS_CHECK_FLAG (lsp->SSNflags, circuit))
613 listnode_add (list, lsp);
614 dnode = next;
615 }
616
jardineb5d44e2003-12-23 08:09:43 +0000617 return;
618}
619
hasso92365882005-01-18 13:53:33 +0000620static void
jardineb5d44e2003-12-23 08:09:43 +0000621lsp_set_time (struct isis_lsp *lsp)
622{
623 assert (lsp);
hassof390d2c2004-09-10 20:48:21 +0000624
625 if (lsp->lsp_header->rem_lifetime == 0)
626 {
627 if (lsp->age_out != 0)
628 lsp->age_out--;
629 return;
630 }
jardineb5d44e2003-12-23 08:09:43 +0000631
632 /* If we are turning 0 */
633 /* ISO 10589 - 7.3.16.4 first paragraph */
634
hassof390d2c2004-09-10 20:48:21 +0000635 if (ntohs (lsp->lsp_header->rem_lifetime) == 1)
636 {
637 /* 7.3.16.4 a) set SRM flags on all */
638 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
639 /* 7.3.16.4 b) retain only the header FIXME */
640 /* 7.3.16.4 c) record the time to purge FIXME (other way to do it) */
641 }
jardineb5d44e2003-12-23 08:09:43 +0000642
hassof390d2c2004-09-10 20:48:21 +0000643 lsp->lsp_header->rem_lifetime =
jardineb5d44e2003-12-23 08:09:43 +0000644 htons (ntohs (lsp->lsp_header->rem_lifetime) - 1);
645}
646
hasso92365882005-01-18 13:53:33 +0000647static void
hassof390d2c2004-09-10 20:48:21 +0000648lspid_print (u_char * lsp_id, u_char * trg, char dynhost, char frag)
jardineb5d44e2003-12-23 08:09:43 +0000649{
650 struct isis_dynhn *dyn = NULL;
hassof390d2c2004-09-10 20:48:21 +0000651 u_char id[SYSID_STRLEN];
jardineb5d44e2003-12-23 08:09:43 +0000652
653 if (dynhost)
654 dyn = dynhn_find_by_id (lsp_id);
655 else
656 dyn = NULL;
657
658 if (dyn)
hassof7c43dc2004-09-26 16:24:14 +0000659 sprintf ((char *)id, "%.14s", dyn->name.name);
jardineb5d44e2003-12-23 08:09:43 +0000660 else if (!memcmp (isis->sysid, lsp_id, ISIS_SYS_ID_LEN) & dynhost)
hassof7c43dc2004-09-26 16:24:14 +0000661 sprintf ((char *)id, "%.14s", unix_hostname ());
jardineb5d44e2003-12-23 08:09:43 +0000662 else
hassof390d2c2004-09-10 20:48:21 +0000663 {
664 memcpy (id, sysid_print (lsp_id), 15);
665 }
666 if (frag)
hassof7c43dc2004-09-26 16:24:14 +0000667 sprintf ((char *)trg, "%s.%02x-%02x", id, LSP_PSEUDO_ID (lsp_id),
hassof390d2c2004-09-10 20:48:21 +0000668 LSP_FRAGMENT (lsp_id));
669 else
hassof7c43dc2004-09-26 16:24:14 +0000670 sprintf ((char *)trg, "%s.%02x", id, LSP_PSEUDO_ID (lsp_id));
jardineb5d44e2003-12-23 08:09:43 +0000671}
672
hassof390d2c2004-09-10 20:48:21 +0000673/* Convert the lsp attribute bits to attribute string */
hasso1cd80842004-10-07 20:07:40 +0000674const char *
hassof390d2c2004-09-10 20:48:21 +0000675lsp_bits2string (u_char * lsp_bits)
676{
677 char *pos = lsp_bits_string;
jardineb5d44e2003-12-23 08:09:43 +0000678
hassof390d2c2004-09-10 20:48:21 +0000679 if (!*lsp_bits)
jardineb5d44e2003-12-23 08:09:43 +0000680 return " none";
681
682 /* we only focus on the default metric */
683 pos += sprintf (pos, "%d/",
hassof390d2c2004-09-10 20:48:21 +0000684 ISIS_MASK_LSP_ATT_DEFAULT_BIT (*lsp_bits) ? 1 : 0);
jardineb5d44e2003-12-23 08:09:43 +0000685
686 pos += sprintf (pos, "%d/",
hassof390d2c2004-09-10 20:48:21 +0000687 ISIS_MASK_LSP_PARTITION_BIT (*lsp_bits) ? 1 : 0);
jardineb5d44e2003-12-23 08:09:43 +0000688
hassof390d2c2004-09-10 20:48:21 +0000689 pos += sprintf (pos, "%d", ISIS_MASK_LSP_OL_BIT (*lsp_bits) ? 1 : 0);
690
jardineb5d44e2003-12-23 08:09:43 +0000691 *(pos) = '\0';
jardineb5d44e2003-12-23 08:09:43 +0000692
hassof390d2c2004-09-10 20:48:21 +0000693 return lsp_bits_string;
jardineb5d44e2003-12-23 08:09:43 +0000694}
695
696/* this function prints the lsp on show isis database */
hasso92365882005-01-18 13:53:33 +0000697static void
hassof390d2c2004-09-10 20:48:21 +0000698lsp_print (dnode_t * node, struct vty *vty, char dynhost)
jardineb5d44e2003-12-23 08:09:43 +0000699{
hassof390d2c2004-09-10 20:48:21 +0000700 struct isis_lsp *lsp = dnode_get (node);
jardineb5d44e2003-12-23 08:09:43 +0000701 u_char LSPid[255];
702
703 lspid_print (lsp->lsp_header->lsp_id, LSPid, dynhost, 1);
hassof390d2c2004-09-10 20:48:21 +0000704 vty_out (vty, "%-21s%c ", LSPid, lsp->own_lsp ? '*' : ' ');
705 vty_out (vty, "0x%08x ", ntohl (lsp->lsp_header->seq_num));
706 vty_out (vty, "0x%04x ", ntohs (lsp->lsp_header->checksum));
jardineb5d44e2003-12-23 08:09:43 +0000707
hassof390d2c2004-09-10 20:48:21 +0000708 if (ntohs (lsp->lsp_header->rem_lifetime) == 0)
709 vty_out (vty, " (%2u)", lsp->age_out);
jardineb5d44e2003-12-23 08:09:43 +0000710 else
hassof390d2c2004-09-10 20:48:21 +0000711 vty_out (vty, "%5u", ntohs (lsp->lsp_header->rem_lifetime));
jardineb5d44e2003-12-23 08:09:43 +0000712
713 vty_out (vty, " %s%s",
hassof390d2c2004-09-10 20:48:21 +0000714 lsp_bits2string (&lsp->lsp_header->lsp_bits), VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +0000715}
716
hasso92365882005-01-18 13:53:33 +0000717static void
hassof390d2c2004-09-10 20:48:21 +0000718lsp_print_detail (dnode_t * node, struct vty *vty, char dynhost)
jardineb5d44e2003-12-23 08:09:43 +0000719{
720 struct isis_lsp *lsp = dnode_get (node);
721 struct area_addr *area_addr;
hassof390d2c2004-09-10 20:48:21 +0000722 int i;
hasso3fdb2dd2005-09-28 18:45:54 +0000723 struct listnode *lnode;
jardineb5d44e2003-12-23 08:09:43 +0000724 struct is_neigh *is_neigh;
725 struct te_is_neigh *te_is_neigh;
726 struct ipv4_reachability *ipv4_reach;
727 struct in_addr *ipv4_addr;
728 struct te_ipv4_reachability *te_ipv4_reach;
729#ifdef HAVE_IPV6
730 struct ipv6_reachability *ipv6_reach;
731 struct in6_addr in6;
732#endif
733 u_char LSPid[255];
734 u_char hostname[255];
735 u_char buff[BUFSIZ];
jardineb5d44e2003-12-23 08:09:43 +0000736 u_char ipv4_reach_prefix[20];
737 u_char ipv4_reach_mask[20];
738 u_char ipv4_address[20];
739
740 lspid_print (lsp->lsp_header->lsp_id, LSPid, dynhost, 1);
hassof390d2c2004-09-10 20:48:21 +0000741 lsp_print (node, vty, dynhost);
jardineb5d44e2003-12-23 08:09:43 +0000742
743 /* for all area address */
hassof390d2c2004-09-10 20:48:21 +0000744 if (lsp->tlv_data.area_addrs)
hasso3fdb2dd2005-09-28 18:45:54 +0000745 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.area_addrs, lnode, area_addr))
hassof390d2c2004-09-10 20:48:21 +0000746 {
hasso1cd80842004-10-07 20:07:40 +0000747 vty_out (vty, " Area Address: %s%s",
hassof390d2c2004-09-10 20:48:21 +0000748 isonet_print (area_addr->area_addr, area_addr->addr_len),
749 VTY_NEWLINE);
750 }
paul1eb8ef22005-04-07 07:30:20 +0000751
jardineb5d44e2003-12-23 08:09:43 +0000752 /* for the nlpid tlv */
hassof390d2c2004-09-10 20:48:21 +0000753 if (lsp->tlv_data.nlpids)
754 {
755 for (i = 0; i < lsp->tlv_data.nlpids->count; i++)
756 {
757 switch (lsp->tlv_data.nlpids->nlpids[i])
758 {
759 case NLPID_IP:
760 case NLPID_IPV6:
hasso1cd80842004-10-07 20:07:40 +0000761 vty_out (vty, " NLPID: 0x%X%s",
hassof390d2c2004-09-10 20:48:21 +0000762 lsp->tlv_data.nlpids->nlpids[i], VTY_NEWLINE);
763 break;
764 default:
hasso1cd80842004-10-07 20:07:40 +0000765 vty_out (vty, " NLPID: %s%s", "unknown", VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +0000766 break;
767 }
768 }
769 }
jardineb5d44e2003-12-23 08:09:43 +0000770
771 /* for the hostname tlv */
hassof390d2c2004-09-10 20:48:21 +0000772 if (lsp->tlv_data.hostname)
773 {
774 bzero (hostname, sizeof (hostname));
775 memcpy (hostname, lsp->tlv_data.hostname->name,
776 lsp->tlv_data.hostname->namelen);
777 vty_out (vty, " Hostname: %s%s", hostname, VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +0000778 }
hassof390d2c2004-09-10 20:48:21 +0000779
780 if (lsp->tlv_data.ipv4_addrs)
hasso3fdb2dd2005-09-28 18:45:54 +0000781 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_addrs, lnode, ipv4_addr))
hassof390d2c2004-09-10 20:48:21 +0000782 {
783 memcpy (ipv4_address, inet_ntoa (*ipv4_addr), sizeof (ipv4_address));
784 vty_out (vty, " IP: %s%s", ipv4_address, VTY_NEWLINE);
785 }
hassof390d2c2004-09-10 20:48:21 +0000786
hasso1cd80842004-10-07 20:07:40 +0000787 /* TE router id */
788 if (lsp->tlv_data.router_id)
789 {
790 memcpy (ipv4_address, inet_ntoa (lsp->tlv_data.router_id->id),
791 sizeof (ipv4_address));
792 vty_out (vty, " Router ID: %s%s", ipv4_address, VTY_NEWLINE);
793 }
794
795 /* for the IS neighbor tlv */
796 if (lsp->tlv_data.is_neighs)
hasso3fdb2dd2005-09-28 18:45:54 +0000797 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, lnode, is_neigh))
hasso1cd80842004-10-07 20:07:40 +0000798 {
799 lspid_print (is_neigh->neigh_id, LSPid, dynhost, 0);
hasso96e30382005-09-19 06:35:47 +0000800 vty_out (vty, " Metric: %-10d IS %s%s",
hasso1cd80842004-10-07 20:07:40 +0000801 is_neigh->metrics.metric_default, LSPid, VTY_NEWLINE);
802 }
hasso1cd80842004-10-07 20:07:40 +0000803
jardineb5d44e2003-12-23 08:09:43 +0000804 /* for the internal reachable tlv */
805 if (lsp->tlv_data.ipv4_int_reachs)
hasso3fdb2dd2005-09-28 18:45:54 +0000806 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_int_reachs, lnode,
807 ipv4_reach))
hassof390d2c2004-09-10 20:48:21 +0000808 {
809 memcpy (ipv4_reach_prefix, inet_ntoa (ipv4_reach->prefix),
810 sizeof (ipv4_reach_prefix));
811 memcpy (ipv4_reach_mask, inet_ntoa (ipv4_reach->mask),
812 sizeof (ipv4_reach_mask));
hasso96e30382005-09-19 06:35:47 +0000813 vty_out (vty, " Metric: %-10d IP-Internal %s %s%s",
hassof390d2c2004-09-10 20:48:21 +0000814 ipv4_reach->metrics.metric_default, ipv4_reach_prefix,
815 ipv4_reach_mask, VTY_NEWLINE);
816 }
hasso2097cd82003-12-23 11:51:08 +0000817
818 /* for the external reachable tlv */
819 if (lsp->tlv_data.ipv4_ext_reachs)
hasso3fdb2dd2005-09-28 18:45:54 +0000820 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_ext_reachs, lnode,
821 ipv4_reach))
hassof390d2c2004-09-10 20:48:21 +0000822 {
823 memcpy (ipv4_reach_prefix, inet_ntoa (ipv4_reach->prefix),
824 sizeof (ipv4_reach_prefix));
825 memcpy (ipv4_reach_mask, inet_ntoa (ipv4_reach->mask),
826 sizeof (ipv4_reach_mask));
hasso96e30382005-09-19 06:35:47 +0000827 vty_out (vty, " Metric: %-10d IP-External %s %s%s",
hassof390d2c2004-09-10 20:48:21 +0000828 ipv4_reach->metrics.metric_default, ipv4_reach_prefix,
829 ipv4_reach_mask, VTY_NEWLINE);
830 }
paul1eb8ef22005-04-07 07:30:20 +0000831
hasso2097cd82003-12-23 11:51:08 +0000832 /* IPv6 tlv */
833#ifdef HAVE_IPV6
834 if (lsp->tlv_data.ipv6_reachs)
hasso3fdb2dd2005-09-28 18:45:54 +0000835 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv6_reachs, lnode, ipv6_reach))
hassof390d2c2004-09-10 20:48:21 +0000836 {
837 memset (&in6, 0, sizeof (in6));
838 memcpy (in6.s6_addr, ipv6_reach->prefix,
839 PSIZE (ipv6_reach->prefix_len));
hassof7c43dc2004-09-26 16:24:14 +0000840 inet_ntop (AF_INET6, &in6, (char *)buff, BUFSIZ);
hasso2097cd82003-12-23 11:51:08 +0000841 if ((ipv6_reach->control_info &&
hassof390d2c2004-09-10 20:48:21 +0000842 CTRL_INFO_DISTRIBUTION) == DISTRIBUTION_INTERNAL)
hasso96e30382005-09-19 06:35:47 +0000843 vty_out (vty, " Metric: %-10d IPv6-Internal %s/%d%s",
hassof390d2c2004-09-10 20:48:21 +0000844 ntohl (ipv6_reach->metric),
845 buff, ipv6_reach->prefix_len, VTY_NEWLINE);
hasso2097cd82003-12-23 11:51:08 +0000846 else
hasso96e30382005-09-19 06:35:47 +0000847 vty_out (vty, " Metric: %-10d IPv6-External %s/%d%s",
hassof390d2c2004-09-10 20:48:21 +0000848 ntohl (ipv6_reach->metric),
849 buff, ipv6_reach->prefix_len, VTY_NEWLINE);
hasso2097cd82003-12-23 11:51:08 +0000850 }
851#endif
paul1eb8ef22005-04-07 07:30:20 +0000852
hasso1cd80842004-10-07 20:07:40 +0000853 /* TE IS neighbor tlv */
jardineb5d44e2003-12-23 08:09:43 +0000854 if (lsp->tlv_data.te_is_neighs)
hasso3fdb2dd2005-09-28 18:45:54 +0000855 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, lnode, te_is_neigh))
hassof390d2c2004-09-10 20:48:21 +0000856 {
hasso96e30382005-09-19 06:35:47 +0000857 uint32_t metric;
858 memcpy (&metric, te_is_neigh->te_metric, 3);
hassof390d2c2004-09-10 20:48:21 +0000859 lspid_print (te_is_neigh->neigh_id, LSPid, dynhost, 0);
hasso96e30382005-09-19 06:35:47 +0000860 vty_out (vty, " Metric: %-10d IS-Extended %s%s",
861 ntohl (metric << 8), LSPid, VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +0000862 }
jardineb5d44e2003-12-23 08:09:43 +0000863
hasso1cd80842004-10-07 20:07:40 +0000864 /* TE IPv4 tlv */
jardineb5d44e2003-12-23 08:09:43 +0000865 if (lsp->tlv_data.te_ipv4_reachs)
hasso3fdb2dd2005-09-28 18:45:54 +0000866 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_ipv4_reachs, lnode,
867 te_ipv4_reach))
hassof390d2c2004-09-10 20:48:21 +0000868 {
hasso1cd80842004-10-07 20:07:40 +0000869 /* FIXME: There should be better way to output this stuff. */
hasso96e30382005-09-19 06:35:47 +0000870 vty_out (vty, " Metric: %-10d IP-Extended %s/%d%s",
hasso1cd80842004-10-07 20:07:40 +0000871 ntohl (te_ipv4_reach->te_metric),
hassof390d2c2004-09-10 20:48:21 +0000872 inet_ntoa (newprefix2inaddr (&te_ipv4_reach->prefix_start,
873 te_ipv4_reach->control)),
hasso1cd80842004-10-07 20:07:40 +0000874 te_ipv4_reach->control & 0x3F, VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +0000875 }
jardineb5d44e2003-12-23 08:09:43 +0000876
hassof390d2c2004-09-10 20:48:21 +0000877 return;
jardineb5d44e2003-12-23 08:09:43 +0000878}
879
880/* print all the lsps info in the local lspdb */
hassof390d2c2004-09-10 20:48:21 +0000881int
882lsp_print_all (struct vty *vty, dict_t * lspdb, char detail, char dynhost)
jardineb5d44e2003-12-23 08:09:43 +0000883{
884
hassof390d2c2004-09-10 20:48:21 +0000885 dnode_t *node = dict_first (lspdb), *next;
jardineb5d44e2003-12-23 08:09:43 +0000886 int lsp_count = 0;
887
888 /* print the title, for both modes */
889 vty_out (vty, "LSP ID LSP Seq Num LSP Checksum "
hassof390d2c2004-09-10 20:48:21 +0000890 "LSP Holdtime ATT/P/OL%s", VTY_NEWLINE);
891
892 if (detail == ISIS_UI_LEVEL_BRIEF)
893 {
894 while (node != NULL)
895 {
896 /* I think it is unnecessary, so I comment it out */
897 /* dict_contains (lspdb, node); */
898 next = dict_next (lspdb, node);
899 lsp_print (node, vty, dynhost);
900 node = next;
901 lsp_count++;
902 }
jardineb5d44e2003-12-23 08:09:43 +0000903 }
hassof390d2c2004-09-10 20:48:21 +0000904 else if (detail == ISIS_UI_LEVEL_DETAIL)
905 {
906 while (node != NULL)
907 {
908 next = dict_next (lspdb, node);
909 lsp_print_detail (node, vty, dynhost);
910 node = next;
911 lsp_count++;
912 }
jardineb5d44e2003-12-23 08:09:43 +0000913 }
jardineb5d44e2003-12-23 08:09:43 +0000914
915 return lsp_count;
916}
917
jardineb5d44e2003-12-23 08:09:43 +0000918#define FRAG_THOLD(S,T) \
919((STREAM_SIZE(S)*T)/100)
920
921/* stream*, area->lsp_frag_threshold, increment */
922#define FRAG_NEEDED(S,T,I) \
923 (STREAM_SIZE(S)-STREAM_REMAIN(S)+(I) > FRAG_THOLD(S,T))
924
hassoaa4376e2005-09-26 17:39:48 +0000925/* FIXME: It shouldn't be necessary to pass tlvsize here, TLVs can have
926 * variable length (TE TLVs, sub TLVs). */
hasso92365882005-01-18 13:53:33 +0000927static void
jardineb5d44e2003-12-23 08:09:43 +0000928lsp_tlv_fit (struct isis_lsp *lsp, struct list **from, struct list **to,
hassof390d2c2004-09-10 20:48:21 +0000929 int tlvsize, int frag_thold,
930 int tlv_build_func (struct list *, struct stream *))
jardineb5d44e2003-12-23 08:09:43 +0000931{
932 int count, i;
hassof390d2c2004-09-10 20:48:21 +0000933
jardineb5d44e2003-12-23 08:09:43 +0000934 /* can we fit all ? */
hassof390d2c2004-09-10 20:48:21 +0000935 if (!FRAG_NEEDED (lsp->pdu, frag_thold, listcount (*from) * tlvsize + 2))
936 {
937 tlv_build_func (*from, lsp->pdu);
938 *to = *from;
939 *from = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000940 }
hassof390d2c2004-09-10 20:48:21 +0000941 else if (!FRAG_NEEDED (lsp->pdu, frag_thold, tlvsize + 2))
942 {
943 /* fit all we can */
944 count = FRAG_THOLD (lsp->pdu, frag_thold) - 2 -
945 (STREAM_SIZE (lsp->pdu) - STREAM_REMAIN (lsp->pdu));
946 if (count)
947 count = count / tlvsize;
948 for (i = 0; i < count; i++)
949 {
paul1eb8ef22005-04-07 07:30:20 +0000950 listnode_add (*to, listgetdata (listhead (*from)));
951 listnode_delete (*from, listgetdata (listhead (*from)));
hassof390d2c2004-09-10 20:48:21 +0000952 }
953 tlv_build_func (*to, lsp->pdu);
954 }
paul9985f832005-02-09 15:51:56 +0000955 lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
jardineb5d44e2003-12-23 08:09:43 +0000956 return;
957}
958
hasso92365882005-01-18 13:53:33 +0000959static struct isis_lsp *
hassof390d2c2004-09-10 20:48:21 +0000960lsp_next_frag (u_char frag_num, struct isis_lsp *lsp0, struct isis_area *area,
961 int level)
jardineb5d44e2003-12-23 08:09:43 +0000962{
963 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +0000964 u_char frag_id[ISIS_SYS_ID_LEN + 2];
965
jardineb5d44e2003-12-23 08:09:43 +0000966 memcpy (frag_id, lsp0->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 1);
967 LSP_FRAGMENT (frag_id) = frag_num;
968 lsp = lsp_search (frag_id, area->lspdb[level - 1]);
hassof390d2c2004-09-10 20:48:21 +0000969 if (lsp)
970 {
971 /*
972 * Clear the TLVs, but inherit the authinfo
973 */
974 lsp_clear_data (lsp);
975 if (lsp0->tlv_data.auth_info.type)
976 {
977 memcpy (&lsp->tlv_data.auth_info, &lsp->tlv_data.auth_info,
978 sizeof (struct isis_passwd));
979 tlv_add_authinfo (lsp->tlv_data.auth_info.type,
980 lsp->tlv_data.auth_info.len,
981 lsp->tlv_data.auth_info.passwd, lsp->pdu);
982 }
983 return lsp;
jardineb5d44e2003-12-23 08:09:43 +0000984 }
jardineb5d44e2003-12-23 08:09:43 +0000985 lsp = lsp_new (frag_id, area->max_lsp_lifetime[level - 1], 0, area->is_type,
hassof390d2c2004-09-10 20:48:21 +0000986 0, level);
jardineb5d44e2003-12-23 08:09:43 +0000987 lsp->own_lsp = 1;
hassof390d2c2004-09-10 20:48:21 +0000988 lsp_insert (lsp, area->lspdb[level - 1]);
jardineb5d44e2003-12-23 08:09:43 +0000989 listnode_add (lsp0->lspu.frags, lsp);
990 lsp->lspu.zero_lsp = lsp0;
991 /*
992 * Copy the authinfo from zero LSP
993 */
hassof390d2c2004-09-10 20:48:21 +0000994 if (lsp0->tlv_data.auth_info.type)
995 {
996 memcpy (&lsp->tlv_data.auth_info, &lsp->tlv_data.auth_info,
997 sizeof (struct isis_passwd));
998 tlv_add_authinfo (lsp->tlv_data.auth_info.type,
999 lsp->tlv_data.auth_info.len,
1000 lsp->tlv_data.auth_info.passwd, lsp->pdu);
1001 }
jardineb5d44e2003-12-23 08:09:43 +00001002 return lsp;
1003}
1004
1005/*
1006 * Builds the LSP data part. This func creates a new frag whenever
1007 * area->lsp_frag_threshold is exceeded.
1008 */
hasso92365882005-01-18 13:53:33 +00001009static void
jardineb5d44e2003-12-23 08:09:43 +00001010lsp_build_nonpseudo (struct isis_lsp *lsp, struct isis_area *area)
1011{
1012 struct is_neigh *is_neigh;
hassoaa4376e2005-09-26 17:39:48 +00001013 struct te_is_neigh *te_is_neigh;
hasso3fdb2dd2005-09-28 18:45:54 +00001014 struct listnode *node, *ipnode;
jardineb5d44e2003-12-23 08:09:43 +00001015 int level = lsp->level;
1016 struct isis_circuit *circuit;
1017 struct prefix_ipv4 *ipv4;
1018 struct ipv4_reachability *ipreach;
hassoaa4376e2005-09-26 17:39:48 +00001019 struct te_ipv4_reachability *te_ipreach;
jardineb5d44e2003-12-23 08:09:43 +00001020 struct isis_adjacency *nei;
1021#ifdef HAVE_IPV6
hasso67851572004-09-21 14:17:04 +00001022 struct prefix_ipv6 *ipv6, *ip6prefix;
jardineb5d44e2003-12-23 08:09:43 +00001023 struct ipv6_reachability *ip6reach;
1024#endif /* HAVE_IPV6 */
1025 struct tlvs tlv_data;
1026 struct isis_lsp *lsp0 = lsp;
1027 struct isis_passwd *passwd;
hasso18a6dce2004-10-03 18:18:34 +00001028 struct in_addr *routerid;
jardineb5d44e2003-12-23 08:09:43 +00001029
1030 /*
1031 * First add the tlvs related to area
1032 */
hassof390d2c2004-09-10 20:48:21 +00001033
jardineb5d44e2003-12-23 08:09:43 +00001034 /* Area addresses */
1035 if (lsp->tlv_data.area_addrs == NULL)
1036 lsp->tlv_data.area_addrs = list_new ();
1037 list_add_list (lsp->tlv_data.area_addrs, area->area_addrs);
1038 /* Protocols Supported */
hassof390d2c2004-09-10 20:48:21 +00001039 if (area->ip_circuits > 0
jardineb5d44e2003-12-23 08:09:43 +00001040#ifdef HAVE_IPV6
1041 || area->ipv6_circuits > 0
1042#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +00001043 )
jardineb5d44e2003-12-23 08:09:43 +00001044 {
hassoaac372f2005-09-01 17:52:33 +00001045 lsp->tlv_data.nlpids = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct nlpids));
jardineb5d44e2003-12-23 08:09:43 +00001046 lsp->tlv_data.nlpids->count = 0;
hassof390d2c2004-09-10 20:48:21 +00001047 if (area->ip_circuits > 0)
1048 {
1049 lsp->tlv_data.nlpids->count++;
1050 lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP;
1051 }
jardineb5d44e2003-12-23 08:09:43 +00001052#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001053 if (area->ipv6_circuits > 0)
1054 {
1055 lsp->tlv_data.nlpids->count++;
1056 lsp->tlv_data.nlpids->nlpids[lsp->tlv_data.nlpids->count - 1] =
1057 NLPID_IPV6;
1058 }
jardineb5d44e2003-12-23 08:09:43 +00001059#endif /* HAVE_IPV6 */
1060 }
1061 /* Dynamic Hostname */
hassof390d2c2004-09-10 20:48:21 +00001062 if (area->dynhostname)
1063 {
1064 lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV,
1065 sizeof (struct hostname));
jardin9e867fe2003-12-23 08:56:18 +00001066
hassof390d2c2004-09-10 20:48:21 +00001067 memcpy (lsp->tlv_data.hostname->name, unix_hostname (),
1068 strlen (unix_hostname ()));
1069 lsp->tlv_data.hostname->namelen = strlen (unix_hostname ());
1070 }
jardineb5d44e2003-12-23 08:09:43 +00001071
1072 /*
1073 * Building the zero lsp
1074 */
hassoaac372f2005-09-01 17:52:33 +00001075
1076 /* Reset stream endp. Stream is always there and on every LSP refresh only
1077 * TLV part of it is overwritten. So we must seek past header we will not
1078 * touch. */
hassoc89c05d2005-09-04 21:36:36 +00001079 stream_reset (lsp->pdu);
hassoaac372f2005-09-01 17:52:33 +00001080 stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
1081
jardineb5d44e2003-12-23 08:09:43 +00001082 /*
1083 * Add the authentication info if its present
1084 */
hassof390d2c2004-09-10 20:48:21 +00001085 (level == 1) ? (passwd = &area->area_passwd) :
1086 (passwd = &area->domain_passwd);
1087 if (passwd->type)
1088 {
1089 memcpy (&lsp->tlv_data.auth_info, passwd, sizeof (struct isis_passwd));
1090 tlv_add_authinfo (passwd->type, passwd->len, passwd->passwd, lsp->pdu);
1091 }
jardineb5d44e2003-12-23 08:09:43 +00001092 if (lsp->tlv_data.nlpids)
1093 tlv_add_nlpid (lsp->tlv_data.nlpids, lsp->pdu);
1094 if (lsp->tlv_data.hostname)
1095 tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu);
hassof390d2c2004-09-10 20:48:21 +00001096 if (lsp->tlv_data.area_addrs && listcount (lsp->tlv_data.area_addrs) > 0)
jardineb5d44e2003-12-23 08:09:43 +00001097 tlv_add_area_addrs (lsp->tlv_data.area_addrs, lsp->pdu);
hassof390d2c2004-09-10 20:48:21 +00001098
hasso81ad8f62005-09-26 17:58:24 +00001099 /* IPv4 address and TE router ID TLVs. In case of the first one we don't
1100 * follow "C" vendor, but "J" vendor behavior - one IPv4 address is put into
1101 * LSP and this address is same as router id. */
hasso18a6dce2004-10-03 18:18:34 +00001102 if (router_id_zebra.s_addr != 0)
1103 {
hasso18a6dce2004-10-03 18:18:34 +00001104 if (lsp->tlv_data.ipv4_addrs == NULL)
hassobe7d65d2005-09-02 01:38:16 +00001105 {
1106 lsp->tlv_data.ipv4_addrs = list_new ();
1107 lsp->tlv_data.ipv4_addrs->del = free_tlv;
1108 }
hasso18a6dce2004-10-03 18:18:34 +00001109
1110 routerid = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct in_addr));
1111 routerid->s_addr = router_id_zebra.s_addr;
hasso18a6dce2004-10-03 18:18:34 +00001112 listnode_add (lsp->tlv_data.ipv4_addrs, routerid);
hasso81ad8f62005-09-26 17:58:24 +00001113 tlv_add_in_addr (routerid, lsp->pdu, IPV4_ADDR);
hasso18a6dce2004-10-03 18:18:34 +00001114
hasso81ad8f62005-09-26 17:58:24 +00001115 /* Exactly same data is put into TE router ID TLV, but only if new style
1116 * TLV's are in use. */
1117 if (area->newmetric)
1118 {
1119 lsp->tlv_data.router_id = XMALLOC (MTYPE_ISIS_TLV,
1120 sizeof (struct in_addr));
1121 lsp->tlv_data.router_id->id.s_addr = router_id_zebra.s_addr;
1122 tlv_add_in_addr (&lsp->tlv_data.router_id->id, lsp->pdu, TE_ROUTER_ID);
1123 }
hasso18a6dce2004-10-03 18:18:34 +00001124 }
hassof1082d12005-09-19 04:23:34 +00001125
hasso81ad8f62005-09-26 17:58:24 +00001126 memset (&tlv_data, 0, sizeof (struct tlvs));
1127
hassof1082d12005-09-19 04:23:34 +00001128#ifdef TOPOLOGY_GENERATE
1129 /* If topology exists (and we create topology for level 1 only), create
1130 * (hardcoded) link to topology. */
1131 if (area->topology && level == 1)
1132 {
1133 if (tlv_data.is_neighs == NULL)
hassoaa4376e2005-09-26 17:39:48 +00001134 {
1135 tlv_data.is_neighs = list_new ();
1136 tlv_data.is_neighs->del = free_tlv;
1137 }
hasso3fdb2dd2005-09-28 18:45:54 +00001138 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
hassof1082d12005-09-19 04:23:34 +00001139
1140 memcpy (&is_neigh->neigh_id, area->topology_baseis, ISIS_SYS_ID_LEN);
1141 is_neigh->neigh_id[ISIS_SYS_ID_LEN - 1] = (1 & 0xFF);
1142 is_neigh->neigh_id[ISIS_SYS_ID_LEN - 2] = ((1 >> 8) & 0xFF);
1143 is_neigh->metrics.metric_default = 0x01;
1144 is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
1145 is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
1146 is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
1147 listnode_add (tlv_data.is_neighs, is_neigh);
1148 }
1149#endif /* TOPOLOGY_GENERATE */
1150
hasso18a6dce2004-10-03 18:18:34 +00001151 /*
jardineb5d44e2003-12-23 08:09:43 +00001152 * Then build lists of tlvs related to circuits
1153 */
hasso3fdb2dd2005-09-28 18:45:54 +00001154 for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit))
hassof390d2c2004-09-10 20:48:21 +00001155 {
hassof390d2c2004-09-10 20:48:21 +00001156 if (circuit->state != C_STATE_UP)
1157 continue;
jardineb5d44e2003-12-23 08:09:43 +00001158
hassof390d2c2004-09-10 20:48:21 +00001159 /*
1160 * Add IPv4 internal reachability of this circuit
1161 */
1162 if (circuit->ip_router && circuit->ip_addrs &&
1163 circuit->ip_addrs->count > 0)
1164 {
hassoaa4376e2005-09-26 17:39:48 +00001165 if (area->oldmetric)
hassof390d2c2004-09-10 20:48:21 +00001166 {
hassoaa4376e2005-09-26 17:39:48 +00001167 if (tlv_data.ipv4_int_reachs == NULL)
1168 {
1169 tlv_data.ipv4_int_reachs = list_new ();
1170 tlv_data.ipv4_int_reachs->del = free_tlv;
1171 }
hasso3fdb2dd2005-09-28 18:45:54 +00001172 for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, ipnode, ipv4))
hassoaa4376e2005-09-26 17:39:48 +00001173 {
1174 ipreach =
1175 XMALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv4_reachability));
1176 ipreach->metrics = circuit->metrics[level - 1];
1177 masklen2ip (ipv4->prefixlen, &ipreach->mask);
1178 ipreach->prefix.s_addr = ((ipreach->mask.s_addr) &
1179 (ipv4->prefix.s_addr));
1180 listnode_add (tlv_data.ipv4_int_reachs, ipreach);
1181 }
hassobe7d65d2005-09-02 01:38:16 +00001182 tlv_data.ipv4_int_reachs->del = free_tlv;
hassof390d2c2004-09-10 20:48:21 +00001183 }
hassoaa4376e2005-09-26 17:39:48 +00001184 if (area->newmetric)
hassof390d2c2004-09-10 20:48:21 +00001185 {
hassoaa4376e2005-09-26 17:39:48 +00001186 if (tlv_data.te_ipv4_reachs == NULL)
1187 {
1188 tlv_data.te_ipv4_reachs = list_new ();
1189 tlv_data.te_ipv4_reachs->del = free_tlv;
1190 }
hasso3fdb2dd2005-09-28 18:45:54 +00001191 for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, ipnode, ipv4))
hassoaa4376e2005-09-26 17:39:48 +00001192 {
1193 /* FIXME All this assumes that we have no sub TLVs. */
1194 te_ipreach = XCALLOC (MTYPE_ISIS_TLV,
1195 sizeof (struct te_ipv4_reachability) +
1196 ((ipv4->prefixlen + 7)/8) - 1);
hasso309ddb12005-09-26 18:06:47 +00001197
1198 if (area->oldmetric)
1199 te_ipreach->te_metric = htonl (circuit->metrics[level - 1].metric_default);
1200 else
1201 te_ipreach->te_metric = htonl (circuit->te_metric[level - 1]);
1202
hassoaa4376e2005-09-26 17:39:48 +00001203 te_ipreach->control = (ipv4->prefixlen & 0x3F);
1204 memcpy (&te_ipreach->prefix_start, &ipv4->prefix.s_addr,
1205 (ipv4->prefixlen + 7)/8);
1206 listnode_add (tlv_data.te_ipv4_reachs, te_ipreach);
1207 }
hassof390d2c2004-09-10 20:48:21 +00001208 }
hassof390d2c2004-09-10 20:48:21 +00001209 }
jardineb5d44e2003-12-23 08:09:43 +00001210#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001211 /*
1212 * Add IPv6 reachability of this circuit
1213 */
1214 if (circuit->ipv6_router && circuit->ipv6_non_link &&
1215 circuit->ipv6_non_link->count > 0)
1216 {
1217
1218 if (tlv_data.ipv6_reachs == NULL)
1219 {
1220 tlv_data.ipv6_reachs = list_new ();
hassobe7d65d2005-09-02 01:38:16 +00001221 tlv_data.ipv6_reachs->del = free_tlv;
hassof390d2c2004-09-10 20:48:21 +00001222 }
hasso3fdb2dd2005-09-28 18:45:54 +00001223 for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, ipnode, ipv6))
hassof390d2c2004-09-10 20:48:21 +00001224 {
hassof390d2c2004-09-10 20:48:21 +00001225 ip6reach =
hassoaac372f2005-09-01 17:52:33 +00001226 XCALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv6_reachability));
hasso309ddb12005-09-26 18:06:47 +00001227
1228 if (area->oldmetric)
1229 ip6reach->metric =
1230 htonl (circuit->metrics[level - 1].metric_default);
1231 else
1232 ip6reach->metric = htonl (circuit->te_metric[level - 1]);
1233
hassof390d2c2004-09-10 20:48:21 +00001234 ip6reach->control_info = 0;
1235 ip6reach->prefix_len = ipv6->prefixlen;
hasso67851572004-09-21 14:17:04 +00001236 memcpy (&ip6prefix, &ipv6, sizeof(ip6prefix));
1237 apply_mask_ipv6 (ip6prefix);
1238 memcpy (ip6reach->prefix, ip6prefix->prefix.s6_addr,
1239 sizeof (ip6reach->prefix));
hassof390d2c2004-09-10 20:48:21 +00001240 listnode_add (tlv_data.ipv6_reachs, ip6reach);
1241 }
1242 }
1243#endif /* HAVE_IPV6 */
1244
1245 switch (circuit->circ_type)
1246 {
1247 case CIRCUIT_T_BROADCAST:
1248 if (level & circuit->circuit_is_type)
1249 {
hassoaa4376e2005-09-26 17:39:48 +00001250 if (area->oldmetric)
hassof390d2c2004-09-10 20:48:21 +00001251 {
hassoaa4376e2005-09-26 17:39:48 +00001252 if (tlv_data.is_neighs == NULL)
1253 {
1254 tlv_data.is_neighs = list_new ();
1255 tlv_data.is_neighs->del = free_tlv;
1256 }
1257 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1258 if (level == 1)
1259 memcpy (is_neigh->neigh_id,
1260 circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
1261 else
1262 memcpy (is_neigh->neigh_id,
1263 circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
1264 is_neigh->metrics = circuit->metrics[level - 1];
1265 listnode_add (tlv_data.is_neighs, is_neigh);
hassobe7d65d2005-09-02 01:38:16 +00001266 tlv_data.is_neighs->del = free_tlv;
hassof390d2c2004-09-10 20:48:21 +00001267 }
hassoaa4376e2005-09-26 17:39:48 +00001268 if (area->newmetric)
1269 {
1270 uint32_t metric;
1271
1272 if (tlv_data.te_is_neighs == NULL)
1273 {
1274 tlv_data.te_is_neighs = list_new ();
1275 tlv_data.te_is_neighs->del = free_tlv;
1276 }
1277 te_is_neigh = XCALLOC (MTYPE_ISIS_TLV,
1278 sizeof (struct te_is_neigh));
1279 if (level == 1)
1280 memcpy (te_is_neigh->neigh_id,
1281 circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
1282 else
1283 memcpy (te_is_neigh->neigh_id,
1284 circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
hasso309ddb12005-09-26 18:06:47 +00001285 if (area->oldmetric)
1286 metric =
1287 ((htonl(circuit->metrics[level - 1].metric_default) >> 8)
1288 & 0xffffff);
1289 else
1290 metric = ((htonl(*circuit->te_metric) >> 8) & 0xffffff);
1291
hassoaa4376e2005-09-26 17:39:48 +00001292 memcpy (te_is_neigh->te_metric, &metric, 3);
1293 listnode_add (tlv_data.te_is_neighs, te_is_neigh);
1294 }
hassof390d2c2004-09-10 20:48:21 +00001295 }
1296 break;
1297 case CIRCUIT_T_P2P:
1298 nei = circuit->u.p2p.neighbor;
1299 if (nei && (level & nei->circuit_t))
1300 {
hassoaa4376e2005-09-26 17:39:48 +00001301 if (area->oldmetric)
hassof390d2c2004-09-10 20:48:21 +00001302 {
hassoaa4376e2005-09-26 17:39:48 +00001303 if (tlv_data.is_neighs == NULL)
1304 {
1305 tlv_data.is_neighs = list_new ();
1306 tlv_data.is_neighs->del = free_tlv;
1307 }
1308 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1309 memcpy (is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN);
1310 is_neigh->metrics = circuit->metrics[level - 1];
1311 listnode_add (tlv_data.is_neighs, is_neigh);
hassof390d2c2004-09-10 20:48:21 +00001312 }
hassoaa4376e2005-09-26 17:39:48 +00001313 if (area->newmetric)
1314 {
1315 uint32_t metric;
1316
1317 if (tlv_data.te_is_neighs == NULL)
1318 {
1319 tlv_data.te_is_neighs = list_new ();
1320 tlv_data.te_is_neighs->del = free_tlv;
1321 }
1322 te_is_neigh = XCALLOC (MTYPE_ISIS_TLV,
1323 sizeof (struct te_is_neigh));
1324 memcpy (te_is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN);
1325 metric = ((htonl(*circuit->te_metric) >> 8) & 0xffffff);
1326 memcpy (te_is_neigh->te_metric, &metric, 3);
1327 listnode_add (tlv_data.te_is_neighs, te_is_neigh);
1328 }
hassof390d2c2004-09-10 20:48:21 +00001329 }
1330 break;
1331 case CIRCUIT_T_STATIC_IN:
1332 zlog_warn ("lsp_area_create: unsupported circuit type");
1333 break;
1334 case CIRCUIT_T_STATIC_OUT:
1335 zlog_warn ("lsp_area_create: unsupported circuit type");
1336 break;
1337 case CIRCUIT_T_DA:
1338 zlog_warn ("lsp_area_create: unsupported circuit type");
1339 break;
1340 default:
1341 zlog_warn ("lsp_area_create: unknown circuit type");
1342 }
1343 }
1344
1345 while (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs))
1346 {
1347 if (lsp->tlv_data.ipv4_int_reachs == NULL)
1348 lsp->tlv_data.ipv4_int_reachs = list_new ();
1349 lsp_tlv_fit (lsp, &tlv_data.ipv4_int_reachs,
1350 &lsp->tlv_data.ipv4_int_reachs,
1351 IPV4_REACH_LEN, area->lsp_frag_threshold,
1352 tlv_add_ipv4_reachs);
1353 if (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs))
1354 lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
1355 lsp0, area, level);
1356 }
hassoaa4376e2005-09-26 17:39:48 +00001357 /* FIXME: We pass maximum te_ipv4_reachability length to the lsp_tlv_fit()
1358 * for now. lsp_tlv_fit() needs to be fixed to deal with variable length
1359 * TLVs (sub TLVs!). */
1360 while (tlv_data.te_ipv4_reachs && listcount (tlv_data.te_ipv4_reachs))
1361 {
1362 if (lsp->tlv_data.te_ipv4_reachs == NULL)
1363 lsp->tlv_data.te_ipv4_reachs = list_new ();
1364 lsp_tlv_fit (lsp, &tlv_data.te_ipv4_reachs,
1365 &lsp->tlv_data.te_ipv4_reachs,
1366 9, area->lsp_frag_threshold, tlv_add_te_ipv4_reachs);
1367 if (tlv_data.te_ipv4_reachs && listcount (tlv_data.te_ipv4_reachs))
1368 lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
1369 lsp0, area, level);
1370 }
hassof390d2c2004-09-10 20:48:21 +00001371
1372#ifdef HAVE_IPV6
1373 while (tlv_data.ipv6_reachs && listcount (tlv_data.ipv6_reachs))
1374 {
1375 if (lsp->tlv_data.ipv6_reachs == NULL)
1376 lsp->tlv_data.ipv6_reachs = list_new ();
1377 lsp_tlv_fit (lsp, &tlv_data.ipv6_reachs,
1378 &lsp->tlv_data.ipv6_reachs,
1379 IPV6_REACH_LEN, area->lsp_frag_threshold,
1380 tlv_add_ipv6_reachs);
1381 if (tlv_data.ipv6_reachs && listcount (tlv_data.ipv6_reachs))
1382 lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
1383 lsp0, area, level);
jardineb5d44e2003-12-23 08:09:43 +00001384 }
1385#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +00001386
1387 while (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
1388 {
1389 if (lsp->tlv_data.is_neighs == NULL)
1390 lsp->tlv_data.is_neighs = list_new ();
1391 lsp_tlv_fit (lsp, &tlv_data.is_neighs,
1392 &lsp->tlv_data.is_neighs,
1393 IS_NEIGHBOURS_LEN, area->lsp_frag_threshold,
1394 tlv_add_is_neighs);
1395 if (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
1396 lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
1397 lsp0, area, level);
jardineb5d44e2003-12-23 08:09:43 +00001398 }
jardineb5d44e2003-12-23 08:09:43 +00001399
hassoaa4376e2005-09-26 17:39:48 +00001400 while (tlv_data.te_is_neighs && listcount (tlv_data.te_is_neighs))
1401 {
1402 if (lsp->tlv_data.te_is_neighs == NULL)
1403 lsp->tlv_data.te_is_neighs = list_new ();
1404 lsp_tlv_fit (lsp, &tlv_data.te_is_neighs, &lsp->tlv_data.te_is_neighs,
1405 IS_NEIGHBOURS_LEN, area->lsp_frag_threshold,
1406 tlv_add_te_is_neighs);
1407 if (tlv_data.te_is_neighs && listcount (tlv_data.te_is_neighs))
1408 lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
1409 lsp0, area, level);
1410 }
1411
1412 free_tlvs (&tlv_data);
jardineb5d44e2003-12-23 08:09:43 +00001413 return;
1414}
jardineb5d44e2003-12-23 08:09:43 +00001415
1416/*
1417 * 7.3.7 Generation on non-pseudonode LSPs
1418 */
hasso92365882005-01-18 13:53:33 +00001419static int
hassof390d2c2004-09-10 20:48:21 +00001420lsp_generate_non_pseudo (struct isis_area *area, int level)
1421{
jardineb5d44e2003-12-23 08:09:43 +00001422 struct isis_lsp *oldlsp, *newlsp;
1423 u_int32_t seq_num = 0;
1424 u_char lspid[ISIS_SYS_ID_LEN + 2];
1425
1426 memset (&lspid, 0, ISIS_SYS_ID_LEN + 2);
1427 memcpy (&lspid, isis->sysid, ISIS_SYS_ID_LEN);
1428
1429 /* only builds the lsp if the area shares the level */
hassof390d2c2004-09-10 20:48:21 +00001430 if ((area->is_type & level) == level)
1431 {
1432 oldlsp = lsp_search (lspid, area->lspdb[level - 1]);
1433 if (oldlsp)
1434 {
1435 seq_num = ntohl (oldlsp->lsp_header->seq_num);
1436 lsp_search_and_destroy (oldlsp->lsp_header->lsp_id,
1437 area->lspdb[level - 1]);
1438 /* FIXME: we should actually initiate a purge */
1439 }
1440 newlsp = lsp_new (lspid, area->max_lsp_lifetime[level - 1], seq_num,
1441 area->is_type, 0, level);
1442 newlsp->own_lsp = 1;
jardineb5d44e2003-12-23 08:09:43 +00001443
hassof390d2c2004-09-10 20:48:21 +00001444 lsp_insert (newlsp, area->lspdb[level - 1]);
1445 /* build_lsp_data (newlsp, area); */
1446 lsp_build_nonpseudo (newlsp, area);
1447 /* time to calculate our checksum */
1448 lsp_seqnum_update (newlsp);
1449 }
jardineb5d44e2003-12-23 08:09:43 +00001450
1451 /* DEBUG_ADJ_PACKETS */
hassof390d2c2004-09-10 20:48:21 +00001452 if (isis->debugs & DEBUG_ADJ_PACKETS)
1453 {
1454 /* FIXME: is this place right? fix missing info */
hasso529d65b2004-12-24 00:14:50 +00001455 zlog_debug ("ISIS-Upd (%s): Building L%d LSP", area->area_tag, level);
hassof390d2c2004-09-10 20:48:21 +00001456 }
jardineb5d44e2003-12-23 08:09:43 +00001457
1458 return ISIS_OK;
1459}
1460
1461/*
1462 * 7.3.9 Generation of level 1 LSPs (non-pseudonode)
1463 */
1464int
1465lsp_l1_generate (struct isis_area *area)
1466{
hassof390d2c2004-09-10 20:48:21 +00001467 THREAD_TIMER_ON (master, area->t_lsp_refresh[0], lsp_refresh_l1, area,
1468 MAX_LSP_GEN_INTERVAL);
jardineb5d44e2003-12-23 08:09:43 +00001469
1470 return lsp_generate_non_pseudo (area, 1);
1471}
1472
jardineb5d44e2003-12-23 08:09:43 +00001473/*
1474 * 7.3.9 Generation of level 2 LSPs (non-pseudonode)
1475 */
1476int
1477lsp_l2_generate (struct isis_area *area)
1478{
hassof390d2c2004-09-10 20:48:21 +00001479 THREAD_TIMER_ON (master, area->t_lsp_refresh[1], lsp_refresh_l2, area,
1480 MAX_LSP_GEN_INTERVAL);
jardineb5d44e2003-12-23 08:09:43 +00001481
1482 return lsp_generate_non_pseudo (area, 2);
1483}
1484
hasso92365882005-01-18 13:53:33 +00001485static int
jardineb5d44e2003-12-23 08:09:43 +00001486lsp_non_pseudo_regenerate (struct isis_area *area, int level)
1487{
1488 dict_t *lspdb = area->lspdb[level - 1];
1489 struct isis_lsp *lsp, *frag;
1490 struct listnode *node;
1491 u_char lspid[ISIS_SYS_ID_LEN + 2];
1492
1493 memset (lspid, 0, ISIS_SYS_ID_LEN + 2);
1494 memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN);
hassof390d2c2004-09-10 20:48:21 +00001495
jardineb5d44e2003-12-23 08:09:43 +00001496 lsp = lsp_search (lspid, lspdb);
jardineb5d44e2003-12-23 08:09:43 +00001497
hassof390d2c2004-09-10 20:48:21 +00001498 if (!lsp)
1499 {
1500 zlog_err
1501 ("ISIS-Upd (%s): lsp_non_pseudo_regenerate(): no L%d LSP found!",
1502 area->area_tag, level);
jardineb5d44e2003-12-23 08:09:43 +00001503
hassof390d2c2004-09-10 20:48:21 +00001504 return ISIS_ERROR;
1505 }
1506
1507 lsp_clear_data (lsp);
jardineb5d44e2003-12-23 08:09:43 +00001508 lsp_build_nonpseudo (lsp, area);
hassof390d2c2004-09-10 20:48:21 +00001509 lsp->lsp_header->rem_lifetime = htons (isis_jitter
1510 (area->max_lsp_lifetime[level - 1],
1511 MAX_AGE_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00001512 lsp_seqnum_update (lsp);
hassof390d2c2004-09-10 20:48:21 +00001513
1514 if (isis->debugs & DEBUG_UPDATE_PACKETS)
1515 {
hasso529d65b2004-12-24 00:14:50 +00001516 zlog_debug ("ISIS-Upd (%s): refreshing our L%d LSP %s, "
1517 "seq 0x%08x, cksum 0x%04x lifetime %us",
1518 area->area_tag,
1519 level,
1520 rawlspid_print (lsp->lsp_header->lsp_id),
1521 ntohl (lsp->lsp_header->seq_num),
1522 ntohs (lsp->lsp_header->checksum),
1523 ntohs (lsp->lsp_header->rem_lifetime));
hassof390d2c2004-09-10 20:48:21 +00001524 }
jardineb5d44e2003-12-23 08:09:43 +00001525
1526 lsp->last_generated = time (NULL);
1527 area->lsp_regenerate_pending[level - 1] = 0;
1528 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
paul1eb8ef22005-04-07 07:30:20 +00001529 for (ALL_LIST_ELEMENTS_RO (lsp->lspu.frags, node, frag))
hassof390d2c2004-09-10 20:48:21 +00001530 {
hassof390d2c2004-09-10 20:48:21 +00001531 frag->lsp_header->rem_lifetime = htons (isis_jitter
1532 (area->
1533 max_lsp_lifetime[level - 1],
1534 MAX_AGE_JITTER));
1535 ISIS_FLAGS_SET_ALL (frag->SRMflags);
1536 }
jardineb5d44e2003-12-23 08:09:43 +00001537
1538 if (area->ip_circuits)
1539 isis_spf_schedule (area, level);
1540#ifdef HAVE_IPV6
1541 if (area->ipv6_circuits)
1542 isis_spf_schedule6 (area, level);
1543#endif
1544 return ISIS_OK;
1545}
1546
jardineb5d44e2003-12-23 08:09:43 +00001547/*
1548 * Done at least every MAX_LSP_GEN_INTERVAL. Search own LSPs, update holding
1549 * time and set SRM
1550 */
hassof390d2c2004-09-10 20:48:21 +00001551int
jardineb5d44e2003-12-23 08:09:43 +00001552lsp_refresh_l1 (struct thread *thread)
1553{
1554 struct isis_area *area;
1555 unsigned long ref_time;
1556
1557 area = THREAD_ARG (thread);
1558 assert (area);
hassof390d2c2004-09-10 20:48:21 +00001559
jardineb5d44e2003-12-23 08:09:43 +00001560 area->t_lsp_refresh[0] = NULL;
hassof390d2c2004-09-10 20:48:21 +00001561 if (area->is_type & IS_LEVEL_1)
jardineb5d44e2003-12-23 08:09:43 +00001562 lsp_non_pseudo_regenerate (area, 1);
hassof390d2c2004-09-10 20:48:21 +00001563
1564 ref_time = area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
jardineb5d44e2003-12-23 08:09:43 +00001565 MAX_LSP_GEN_INTERVAL : area->lsp_refresh[0];
1566
hassof390d2c2004-09-10 20:48:21 +00001567 THREAD_TIMER_ON (master, area->t_lsp_refresh[0], lsp_refresh_l1, area,
1568 isis_jitter (ref_time, MAX_AGE_JITTER));
hassod70f99e2004-02-11 20:26:31 +00001569
jardineb5d44e2003-12-23 08:09:43 +00001570 return ISIS_OK;
1571}
1572
hassof390d2c2004-09-10 20:48:21 +00001573int
jardineb5d44e2003-12-23 08:09:43 +00001574lsp_refresh_l2 (struct thread *thread)
1575{
1576 struct isis_area *area;
1577 unsigned long ref_time;
1578
1579 area = THREAD_ARG (thread);
1580 assert (area);
hassof390d2c2004-09-10 20:48:21 +00001581
jardineb5d44e2003-12-23 08:09:43 +00001582 area->t_lsp_refresh[1] = NULL;
hassof390d2c2004-09-10 20:48:21 +00001583 if (area->is_type & IS_LEVEL_2)
jardineb5d44e2003-12-23 08:09:43 +00001584 lsp_non_pseudo_regenerate (area, 2);
1585
hassof390d2c2004-09-10 20:48:21 +00001586 ref_time = area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ?
jardineb5d44e2003-12-23 08:09:43 +00001587 MAX_LSP_GEN_INTERVAL : area->lsp_refresh[1];
1588
hassof390d2c2004-09-10 20:48:21 +00001589 THREAD_TIMER_ON (master, area->t_lsp_refresh[1], lsp_refresh_l2, area,
1590 isis_jitter (ref_time, MAX_AGE_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00001591
jardineb5d44e2003-12-23 08:09:43 +00001592 return ISIS_OK;
1593}
1594
jardineb5d44e2003-12-23 08:09:43 +00001595/*
1596 * Something has changed -> regenerate LSP
1597 */
1598
hasso92365882005-01-18 13:53:33 +00001599static int
jardineb5d44e2003-12-23 08:09:43 +00001600lsp_l1_regenerate (struct thread *thread)
1601{
1602 struct isis_area *area;
1603
1604 area = THREAD_ARG (thread);
1605 area->lsp_regenerate_pending[0] = 0;
1606
1607 return lsp_non_pseudo_regenerate (area, 1);
1608}
1609
hasso92365882005-01-18 13:53:33 +00001610static int
jardineb5d44e2003-12-23 08:09:43 +00001611lsp_l2_regenerate (struct thread *thread)
1612{
1613 struct isis_area *area;
1614
1615 area = THREAD_ARG (thread);
1616 area->lsp_regenerate_pending[1] = 0;
hassof390d2c2004-09-10 20:48:21 +00001617
jardineb5d44e2003-12-23 08:09:43 +00001618 return lsp_non_pseudo_regenerate (area, 2);
1619}
1620
hassof390d2c2004-09-10 20:48:21 +00001621int
jardineb5d44e2003-12-23 08:09:43 +00001622lsp_regenerate_schedule (struct isis_area *area)
1623{
1624 struct isis_lsp *lsp;
1625 u_char id[ISIS_SYS_ID_LEN + 2];
1626 time_t now, diff;
hassof390d2c2004-09-10 20:48:21 +00001627 memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
1628 LSP_PSEUDO_ID (id) = LSP_FRAGMENT (id) = 0;
jardineb5d44e2003-12-23 08:09:43 +00001629 now = time (NULL);
1630 /*
1631 * First level 1
1632 */
hassof390d2c2004-09-10 20:48:21 +00001633 if (area->is_type & IS_LEVEL_1)
1634 {
1635 lsp = lsp_search (id, area->lspdb[0]);
1636 if (!lsp || area->lsp_regenerate_pending[0])
1637 goto L2;
1638 /*
1639 * Throttle avoidance
1640 */
1641 diff = now - lsp->last_generated;
1642 if (diff < MIN_LSP_GEN_INTERVAL)
1643 {
1644 area->lsp_regenerate_pending[0] = 1;
1645 thread_add_timer (master, lsp_l1_regenerate, area,
1646 MIN_LSP_GEN_INTERVAL - diff);
hasso12a5cae2004-09-19 19:39:26 +00001647 goto L2;
hassof390d2c2004-09-10 20:48:21 +00001648 }
1649 else
1650 lsp_non_pseudo_regenerate (area, 1);
1651 }
jardineb5d44e2003-12-23 08:09:43 +00001652 /*
1653 * then 2
1654 */
hassof390d2c2004-09-10 20:48:21 +00001655L2:
1656 if (area->is_type & IS_LEVEL_2)
1657 {
1658 lsp = lsp_search (id, area->lspdb[1]);
1659 if (!lsp || area->lsp_regenerate_pending[1])
1660 return ISIS_OK;
1661 /*
1662 * Throttle avoidance
1663 */
1664 diff = now - lsp->last_generated;
1665 if (diff < MIN_LSP_GEN_INTERVAL)
1666 {
1667 area->lsp_regenerate_pending[1] = 1;
1668 thread_add_timer (master, lsp_l2_regenerate, area,
1669 MIN_LSP_GEN_INTERVAL - diff);
1670 return ISIS_OK;
1671 }
1672 else
1673 lsp_non_pseudo_regenerate (area, 2);
1674 }
1675
1676 return ISIS_OK;
jardineb5d44e2003-12-23 08:09:43 +00001677}
1678
1679/*
1680 * Funcs for pseudonode LSPs
1681 */
1682
1683/*
1684 * 7.3.8 and 7.3.10 Generation of level 1 and 2 pseudonode LSPs
1685 */
hasso92365882005-01-18 13:53:33 +00001686static void
hassof390d2c2004-09-10 20:48:21 +00001687lsp_build_pseudo (struct isis_lsp *lsp, struct isis_circuit *circuit,
1688 int level)
jardineb5d44e2003-12-23 08:09:43 +00001689{
1690 struct isis_adjacency *adj;
1691 struct is_neigh *is_neigh;
hassoaa4376e2005-09-26 17:39:48 +00001692 struct te_is_neigh *te_is_neigh;
jardineb5d44e2003-12-23 08:09:43 +00001693 struct es_neigh *es_neigh;
1694 struct list *adj_list;
hasso3fdb2dd2005-09-28 18:45:54 +00001695 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +00001696 struct isis_passwd *passwd;
1697
1698 assert (circuit);
1699 assert (circuit->circ_type == CIRCUIT_T_BROADCAST);
hassof390d2c2004-09-10 20:48:21 +00001700
jardineb5d44e2003-12-23 08:09:43 +00001701 if (!circuit->u.bc.is_dr[level - 1])
hassof390d2c2004-09-10 20:48:21 +00001702 return; /* we are not DIS on this circuit */
1703
jardineb5d44e2003-12-23 08:09:43 +00001704 lsp->level = level;
1705 if (level == 1)
1706 lsp->lsp_header->lsp_bits |= IS_LEVEL_1;
1707 else
1708 lsp->lsp_header->lsp_bits |= IS_LEVEL_2;
1709
1710 /*
1711 * add self to IS neighbours
1712 */
hassoaa4376e2005-09-26 17:39:48 +00001713 if (circuit->area->oldmetric)
hassof390d2c2004-09-10 20:48:21 +00001714 {
hassoaa4376e2005-09-26 17:39:48 +00001715 if (lsp->tlv_data.is_neighs == NULL)
1716 {
1717 lsp->tlv_data.is_neighs = list_new ();
1718 lsp->tlv_data.is_neighs->del = free_tlv;
1719 }
1720 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
paul15935e92005-05-03 09:27:23 +00001721
hassoaa4376e2005-09-26 17:39:48 +00001722 memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
1723 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
1724 }
1725 if (circuit->area->newmetric)
1726 {
1727 if (lsp->tlv_data.te_is_neighs == NULL)
1728 {
1729 lsp->tlv_data.te_is_neighs = list_new ();
1730 lsp->tlv_data.te_is_neighs->del = free_tlv;
1731 }
1732 te_is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct te_is_neigh));
1733
1734 memcpy (&te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
1735 listnode_add (lsp->tlv_data.te_is_neighs, te_is_neigh);
1736 }
hassof390d2c2004-09-10 20:48:21 +00001737
1738 adj_list = list_new ();
1739 isis_adj_build_up_list (circuit->u.bc.adjdb[level - 1], adj_list);
1740
hasso3fdb2dd2005-09-28 18:45:54 +00001741 for (ALL_LIST_ELEMENTS_RO (adj_list, node, adj))
hassof390d2c2004-09-10 20:48:21 +00001742 {
hassof390d2c2004-09-10 20:48:21 +00001743 if (adj->circuit_t & level)
1744 {
1745 if ((level == 1 && adj->sys_type == ISIS_SYSTYPE_L1_IS) ||
1746 (level == 1 && adj->sys_type == ISIS_SYSTYPE_L2_IS &&
hassoaa4376e2005-09-26 17:39:48 +00001747 adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
hassof390d2c2004-09-10 20:48:21 +00001748 (level == 2 && adj->sys_type == ISIS_SYSTYPE_L2_IS))
1749 {
1750 /* an IS neighbour -> add it */
hassoaa4376e2005-09-26 17:39:48 +00001751 if (circuit->area->oldmetric)
1752 {
1753 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
paul15935e92005-05-03 09:27:23 +00001754
hassoaa4376e2005-09-26 17:39:48 +00001755 memcpy (&is_neigh->neigh_id, adj->sysid, ISIS_SYS_ID_LEN);
1756 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
1757 }
1758 if (circuit->area->newmetric)
1759 {
1760 te_is_neigh = XCALLOC (MTYPE_ISIS_TLV,
1761 sizeof (struct te_is_neigh));
1762 memcpy (&te_is_neigh->neigh_id, adj->sysid, ISIS_SYS_ID_LEN);
1763 listnode_add (lsp->tlv_data.te_is_neighs, te_is_neigh);
1764 }
hassof390d2c2004-09-10 20:48:21 +00001765 }
1766 else if (level == 1 && adj->sys_type == ISIS_SYSTYPE_ES)
1767 {
1768 /* an ES neigbour add it, if we are building level 1 LSP */
1769 /* FIXME: the tlv-format is hard to use here */
1770 if (lsp->tlv_data.es_neighs == NULL)
1771 {
1772 lsp->tlv_data.es_neighs = list_new ();
1773 lsp->tlv_data.es_neighs->del = free_tlv;
1774 }
paul15935e92005-05-03 09:27:23 +00001775 es_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct es_neigh));
1776
hassof390d2c2004-09-10 20:48:21 +00001777 memcpy (&es_neigh->first_es_neigh, adj->sysid, ISIS_SYS_ID_LEN);
hassoaac372f2005-09-01 17:52:33 +00001778 listnode_add (lsp->tlv_data.es_neighs, es_neigh);
hassof390d2c2004-09-10 20:48:21 +00001779 }
1780 }
jardineb5d44e2003-12-23 08:09:43 +00001781 }
hassof390d2c2004-09-10 20:48:21 +00001782
hassoc0fb2a52005-09-03 16:29:40 +00001783 /* Reset endp of stream to overwrite only TLV part of it. */
hassoc89c05d2005-09-04 21:36:36 +00001784 stream_reset (lsp->pdu);
hassoc0fb2a52005-09-03 16:29:40 +00001785 stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
1786
jardineb5d44e2003-12-23 08:09:43 +00001787 /*
1788 * Add the authentication info if it's present
1789 */
hassof390d2c2004-09-10 20:48:21 +00001790 (level == 1) ? (passwd = &circuit->area->area_passwd) :
1791 (passwd = &circuit->area->domain_passwd);
1792 if (passwd->type)
1793 {
1794 memcpy (&lsp->tlv_data.auth_info, passwd, sizeof (struct isis_passwd));
1795 tlv_add_authinfo (passwd->type, passwd->len, passwd->passwd, lsp->pdu);
1796 }
jardineb5d44e2003-12-23 08:09:43 +00001797
1798 if (lsp->tlv_data.is_neighs && listcount (lsp->tlv_data.is_neighs) > 0)
1799 tlv_add_is_neighs (lsp->tlv_data.is_neighs, lsp->pdu);
1800
hassoaa4376e2005-09-26 17:39:48 +00001801 if (lsp->tlv_data.te_is_neighs && listcount (lsp->tlv_data.te_is_neighs) > 0)
1802 tlv_add_te_is_neighs (lsp->tlv_data.te_is_neighs, lsp->pdu);
1803
jardineb5d44e2003-12-23 08:09:43 +00001804 if (lsp->tlv_data.es_neighs && listcount (lsp->tlv_data.es_neighs) > 0)
1805 tlv_add_is_neighs (lsp->tlv_data.es_neighs, lsp->pdu);
1806
paul9985f832005-02-09 15:51:56 +00001807 lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
hassof390d2c2004-09-10 20:48:21 +00001808 iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
1809 ntohs (lsp->lsp_header->pdu_len) - 12, 12);
1810
jardineb5d44e2003-12-23 08:09:43 +00001811 list_delete (adj_list);
1812
1813 return;
1814}
1815
hasso92365882005-01-18 13:53:33 +00001816static int
jardineb5d44e2003-12-23 08:09:43 +00001817lsp_pseudo_regenerate (struct isis_circuit *circuit, int level)
1818{
1819 dict_t *lspdb = circuit->area->lspdb[level - 1];
1820 struct isis_lsp *lsp;
1821 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
hassof390d2c2004-09-10 20:48:21 +00001822
jardineb5d44e2003-12-23 08:09:43 +00001823 memcpy (lsp_id, isis->sysid, ISIS_SYS_ID_LEN);
hassof390d2c2004-09-10 20:48:21 +00001824 LSP_PSEUDO_ID (lsp_id) = circuit->circuit_id;
1825 LSP_FRAGMENT (lsp_id) = 0;
1826
jardineb5d44e2003-12-23 08:09:43 +00001827 lsp = lsp_search (lsp_id, lspdb);
hassof390d2c2004-09-10 20:48:21 +00001828
1829 if (!lsp)
1830 {
1831 zlog_err ("lsp_pseudo_regenerate(): no l%d LSP %s found!", level,
1832 rawlspid_print (lsp_id));
1833 return ISIS_ERROR;
1834 }
1835 lsp_clear_data (lsp);
jardineb5d44e2003-12-23 08:09:43 +00001836
1837 lsp_build_pseudo (lsp, circuit, level);
1838
hassof390d2c2004-09-10 20:48:21 +00001839 lsp->lsp_header->rem_lifetime =
jardineb5d44e2003-12-23 08:09:43 +00001840 htons (isis_jitter (circuit->area->max_lsp_lifetime[level - 1],
hassof390d2c2004-09-10 20:48:21 +00001841 MAX_AGE_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00001842
1843 lsp_inc_seqnum (lsp, 0);
hassof390d2c2004-09-10 20:48:21 +00001844
1845 if (isis->debugs & DEBUG_UPDATE_PACKETS)
1846 {
hasso529d65b2004-12-24 00:14:50 +00001847 zlog_debug ("ISIS-Upd (%s): refreshing pseudo LSP L%d %s",
1848 circuit->area->area_tag, level,
1849 rawlspid_print (lsp->lsp_header->lsp_id));
hassof390d2c2004-09-10 20:48:21 +00001850 }
jardineb5d44e2003-12-23 08:09:43 +00001851
1852 lsp->last_generated = time (NULL);
1853 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
hassof390d2c2004-09-10 20:48:21 +00001854
jardineb5d44e2003-12-23 08:09:43 +00001855 return ISIS_OK;
1856}
1857
jardineb5d44e2003-12-23 08:09:43 +00001858int
1859lsp_l1_refresh_pseudo (struct thread *thread)
1860{
1861 struct isis_circuit *circuit;
1862 int retval;
1863 unsigned long ref_time;
1864
hassof390d2c2004-09-10 20:48:21 +00001865 circuit = THREAD_ARG (thread);
1866
jardineb5d44e2003-12-23 08:09:43 +00001867 if (!circuit->u.bc.is_dr[0])
hassof390d2c2004-09-10 20:48:21 +00001868 return ISIS_ERROR; /* FIXME: purge and such */
1869
hasso13c48f72004-09-10 21:19:13 +00001870 circuit->u.bc.t_refresh_pseudo_lsp[0] = NULL;
1871
jardineb5d44e2003-12-23 08:09:43 +00001872 retval = lsp_pseudo_regenerate (circuit, 1);
hassof390d2c2004-09-10 20:48:21 +00001873
1874 ref_time = circuit->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
jardineb5d44e2003-12-23 08:09:43 +00001875 MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[0];
1876
hassof390d2c2004-09-10 20:48:21 +00001877 THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[0],
1878 lsp_l1_refresh_pseudo, circuit,
1879 isis_jitter (ref_time, MAX_AGE_JITTER));
1880
jardineb5d44e2003-12-23 08:09:43 +00001881 return retval;
1882}
1883
hassof390d2c2004-09-10 20:48:21 +00001884int
jardineb5d44e2003-12-23 08:09:43 +00001885lsp_l1_pseudo_generate (struct isis_circuit *circuit)
1886{
1887 struct isis_lsp *lsp;
1888 u_char id[ISIS_SYS_ID_LEN + 2];
1889 unsigned long ref_time;
1890
hassof390d2c2004-09-10 20:48:21 +00001891 memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
1892 LSP_FRAGMENT (id) = 0;
1893 LSP_PSEUDO_ID (id) = circuit->circuit_id;
jardineb5d44e2003-12-23 08:09:43 +00001894
1895 /*
1896 * If for some reason have a pseudo LSP in the db already -> regenerate
1897 */
1898 if (lsp_search (id, circuit->area->lspdb[0]))
1899 return lsp_pseudo_regenerate (circuit, 1);
1900 lsp = lsp_new (id, circuit->area->max_lsp_lifetime[0],
hassof390d2c2004-09-10 20:48:21 +00001901 1, circuit->area->is_type, 0, 1);
1902
jardineb5d44e2003-12-23 08:09:43 +00001903 lsp_build_pseudo (lsp, circuit, 1);
hassof390d2c2004-09-10 20:48:21 +00001904
jardineb5d44e2003-12-23 08:09:43 +00001905 lsp->own_lsp = 1;
1906 lsp_insert (lsp, circuit->area->lspdb[0]);
1907 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
1908
hassof390d2c2004-09-10 20:48:21 +00001909 ref_time = circuit->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
jardineb5d44e2003-12-23 08:09:43 +00001910 MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[0];
1911
hassof390d2c2004-09-10 20:48:21 +00001912 THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[0],
1913 lsp_l1_refresh_pseudo, circuit,
1914 isis_jitter (ref_time, MAX_AGE_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00001915
1916 return lsp_regenerate_schedule (circuit->area);
1917}
1918
1919int
1920lsp_l2_refresh_pseudo (struct thread *thread)
1921{
1922 struct isis_circuit *circuit;
1923 int retval;
1924 unsigned long ref_time;
hassof390d2c2004-09-10 20:48:21 +00001925 circuit = THREAD_ARG (thread);
1926
jardineb5d44e2003-12-23 08:09:43 +00001927 if (!circuit->u.bc.is_dr[1])
hassof390d2c2004-09-10 20:48:21 +00001928 return ISIS_ERROR; /* FIXME: purge and such */
1929
hasso13c48f72004-09-10 21:19:13 +00001930 circuit->u.bc.t_refresh_pseudo_lsp[1] = NULL;
1931
jardineb5d44e2003-12-23 08:09:43 +00001932 retval = lsp_pseudo_regenerate (circuit, 2);
1933
hassof390d2c2004-09-10 20:48:21 +00001934 ref_time = circuit->area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ?
jardineb5d44e2003-12-23 08:09:43 +00001935 MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[1];
1936
hassof390d2c2004-09-10 20:48:21 +00001937 THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[1],
1938 lsp_l2_refresh_pseudo, circuit,
1939 isis_jitter (ref_time, MAX_AGE_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00001940
jardineb5d44e2003-12-23 08:09:43 +00001941 return retval;
1942}
1943
hassof390d2c2004-09-10 20:48:21 +00001944int
jardineb5d44e2003-12-23 08:09:43 +00001945lsp_l2_pseudo_generate (struct isis_circuit *circuit)
1946{
1947 struct isis_lsp *lsp;
1948 u_char id[ISIS_SYS_ID_LEN + 2];
1949 unsigned long ref_time;
1950
hassof390d2c2004-09-10 20:48:21 +00001951 memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
1952 LSP_FRAGMENT (id) = 0;
1953 LSP_PSEUDO_ID (id) = circuit->circuit_id;
jardineb5d44e2003-12-23 08:09:43 +00001954
1955 if (lsp_search (id, circuit->area->lspdb[1]))
1956 return lsp_pseudo_regenerate (circuit, 2);
1957
1958 lsp = lsp_new (id, circuit->area->max_lsp_lifetime[1],
hassof390d2c2004-09-10 20:48:21 +00001959 1, circuit->area->is_type, 0, 2);
jardineb5d44e2003-12-23 08:09:43 +00001960
1961 lsp_build_pseudo (lsp, circuit, 2);
hassof390d2c2004-09-10 20:48:21 +00001962
1963 ref_time = circuit->area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ?
jardineb5d44e2003-12-23 08:09:43 +00001964 MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[1];
1965
1966
1967 lsp->own_lsp = 1;
1968 lsp_insert (lsp, circuit->area->lspdb[1]);
1969 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
hassof390d2c2004-09-10 20:48:21 +00001970
1971 THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[1],
1972 lsp_l2_refresh_pseudo, circuit,
1973 isis_jitter (ref_time, MAX_AGE_JITTER));
1974
jardineb5d44e2003-12-23 08:09:43 +00001975 return lsp_regenerate_schedule (circuit->area);
1976}
1977
jardineb5d44e2003-12-23 08:09:43 +00001978/*
1979 * Walk through LSPs for an area
1980 * - set remaining lifetime
1981 * - set LSPs with SRMflag set for sending
1982 */
hassof390d2c2004-09-10 20:48:21 +00001983int
jardineb5d44e2003-12-23 08:09:43 +00001984lsp_tick (struct thread *thread)
1985{
1986 struct isis_area *area;
1987 struct isis_circuit *circuit;
1988 struct isis_lsp *lsp;
1989 struct list *lsp_list;
hasso3fdb2dd2005-09-28 18:45:54 +00001990 struct listnode *lspnode, *cnode;
jardineb5d44e2003-12-23 08:09:43 +00001991 dnode_t *dnode, *dnode_next;
1992 int level;
1993
1994 lsp_list = list_new ();
hassof390d2c2004-09-10 20:48:21 +00001995
jardineb5d44e2003-12-23 08:09:43 +00001996 area = THREAD_ARG (thread);
1997 assert (area);
hasso13c48f72004-09-10 21:19:13 +00001998 area->t_tick = NULL;
hassof390d2c2004-09-10 20:48:21 +00001999 THREAD_TIMER_ON (master, area->t_tick, lsp_tick, area, 1);
jardineb5d44e2003-12-23 08:09:43 +00002000
2001 /*
2002 * Build a list of LSPs with (any) SRMflag set
2003 * and removed the ones that have aged out
2004 */
hassof390d2c2004-09-10 20:48:21 +00002005 for (level = 0; level < ISIS_LEVELS; level++)
2006 {
2007 if (area->lspdb[level] && dict_count (area->lspdb[level]) > 0)
2008 {
2009 dnode = dict_first (area->lspdb[level]);
2010 while (dnode != NULL)
2011 {
2012 dnode_next = dict_next (area->lspdb[level], dnode);
2013 lsp = dnode_get (dnode);
2014 lsp_set_time (lsp);
2015 if (lsp->age_out == 0)
2016 {
jardineb5d44e2003-12-23 08:09:43 +00002017
hasso529d65b2004-12-24 00:14:50 +00002018 zlog_debug ("ISIS-Upd (%s): L%u LSP %s seq 0x%08x aged out",
2019 area->area_tag,
2020 lsp->level,
2021 rawlspid_print (lsp->lsp_header->lsp_id),
2022 ntohl (lsp->lsp_header->seq_num));
hassof1082d12005-09-19 04:23:34 +00002023#ifdef TOPOLOGY_GENERATE
2024 if (lsp->from_topology)
2025 THREAD_TIMER_OFF (lsp->t_lsp_top_ref);
2026#endif /* TOPOLOGY_GENERATE */
hassof390d2c2004-09-10 20:48:21 +00002027 lsp_destroy (lsp);
2028 dict_delete (area->lspdb[level], dnode);
2029 }
2030 else if (flags_any_set (lsp->SRMflags))
2031 listnode_add (lsp_list, lsp);
2032 dnode = dnode_next;
2033 }
jardineb5d44e2003-12-23 08:09:43 +00002034
hassof390d2c2004-09-10 20:48:21 +00002035 /*
2036 * Send LSPs on circuits indicated by the SRMflags
2037 */
2038 if (listcount (lsp_list) > 0)
2039 {
paul1eb8ef22005-04-07 07:30:20 +00002040 for (ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit))
hassof390d2c2004-09-10 20:48:21 +00002041 {
hasso3fdb2dd2005-09-28 18:45:54 +00002042 for (ALL_LIST_ELEMENTS_RO (lsp_list, lspnode, lsp))
hassof390d2c2004-09-10 20:48:21 +00002043 {
hassof390d2c2004-09-10 20:48:21 +00002044 if (ISIS_CHECK_FLAG (lsp->SRMflags, circuit))
2045 {
2046 /* FIXME: if same or elder lsp is already in lsp
2047 * queue */
2048 listnode_add (circuit->lsp_queue, lsp);
2049 thread_add_event (master, send_lsp, circuit, 0);
2050 }
2051 }
2052 }
2053 }
2054 list_delete_all_node (lsp_list);
2055 }
jardineb5d44e2003-12-23 08:09:43 +00002056 }
jardineb5d44e2003-12-23 08:09:43 +00002057
2058 list_delete (lsp_list);
2059
2060 return ISIS_OK;
2061}
2062
jardineb5d44e2003-12-23 08:09:43 +00002063void
hassof390d2c2004-09-10 20:48:21 +00002064lsp_purge_dr (u_char * id, struct isis_circuit *circuit, int level)
jardineb5d44e2003-12-23 08:09:43 +00002065{
2066 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +00002067
jardineb5d44e2003-12-23 08:09:43 +00002068 lsp = lsp_search (id, circuit->area->lspdb[level - 1]);
hassof390d2c2004-09-10 20:48:21 +00002069
2070 if (lsp && lsp->purged == 0)
2071 {
2072 lsp->lsp_header->rem_lifetime = htons (0);
2073 lsp->lsp_header->pdu_len =
2074 htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
2075 lsp->purged = 0;
2076 iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
2077 ntohs (lsp->lsp_header->pdu_len) - 12, 12);
2078 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
2079 }
2080
jardineb5d44e2003-12-23 08:09:43 +00002081 return;
2082}
2083
2084/*
2085 * Purge own LSP that is received and we don't have.
2086 * -> Do as in 7.3.16.4
2087 */
2088void
hassof390d2c2004-09-10 20:48:21 +00002089lsp_purge_non_exist (struct isis_link_state_hdr *lsp_hdr,
2090 struct isis_area *area)
jardineb5d44e2003-12-23 08:09:43 +00002091{
2092 struct isis_lsp *lsp;
2093
2094 /*
2095 * We need to create the LSP to be purged
2096 */
hasso529d65b2004-12-24 00:14:50 +00002097 zlog_debug ("LSP PURGE NON EXIST");
hassoaac372f2005-09-01 17:52:33 +00002098 lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
hassof390d2c2004-09-10 20:48:21 +00002099 /*FIXME: BUG BUG BUG! the lsp doesn't exist here! */
2100 /*did smt here, maybe good probably not */
jardineb5d44e2003-12-23 08:09:43 +00002101 lsp->level = ((lsp_hdr->lsp_bits & LSPBIT_IST) == IS_LEVEL_1) ? 1 : 2;
2102 lsp->pdu = stream_new (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
hassof390d2c2004-09-10 20:48:21 +00002103 lsp->isis_header = (struct isis_fixed_hdr *) STREAM_DATA (lsp->pdu);
jardineb5d44e2003-12-23 08:09:43 +00002104 fill_fixed_hdr (lsp->isis_header, (lsp->level == 1) ? L1_LINK_STATE
hassof390d2c2004-09-10 20:48:21 +00002105 : L2_LINK_STATE);
2106 lsp->lsp_header = (struct isis_link_state_hdr *) (STREAM_DATA (lsp->pdu) +
2107 ISIS_FIXED_HDR_LEN);
jardineb5d44e2003-12-23 08:09:43 +00002108 memcpy (lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN);
hassof390d2c2004-09-10 20:48:21 +00002109
jardineb5d44e2003-12-23 08:09:43 +00002110 /*
2111 * Retain only LSP header
2112 */
2113 lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
2114 /*
2115 * Set the remaining lifetime to 0
2116 */
2117 lsp->lsp_header->rem_lifetime = 0;
2118 /*
2119 * Put the lsp into LSPdb
2120 */
hassof390d2c2004-09-10 20:48:21 +00002121 lsp_insert (lsp, area->lspdb[lsp->level - 1]);
jardineb5d44e2003-12-23 08:09:43 +00002122
2123 /*
2124 * Send in to whole area
2125 */
2126 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
hassof390d2c2004-09-10 20:48:21 +00002127
jardineb5d44e2003-12-23 08:09:43 +00002128 return;
2129}
2130
2131#ifdef TOPOLOGY_GENERATE
hasso92365882005-01-18 13:53:33 +00002132static int
jardineb5d44e2003-12-23 08:09:43 +00002133top_lsp_refresh (struct thread *thread)
2134{
hassof390d2c2004-09-10 20:48:21 +00002135 struct isis_lsp *lsp;
hassof1082d12005-09-19 04:23:34 +00002136 unsigned long ref_time;
jardineb5d44e2003-12-23 08:09:43 +00002137
2138 lsp = THREAD_ARG (thread);
2139 assert (lsp);
2140
2141 lsp->t_lsp_top_ref = NULL;
2142
hassof1082d12005-09-19 04:23:34 +00002143 lsp_seqnum_update (lsp);
jardineb5d44e2003-12-23 08:09:43 +00002144
2145 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
hassof390d2c2004-09-10 20:48:21 +00002146 if (isis->debugs & DEBUG_UPDATE_PACKETS)
2147 {
hasso529d65b2004-12-24 00:14:50 +00002148 zlog_debug ("ISIS-Upd (): refreshing Topology L1 %s",
2149 rawlspid_print (lsp->lsp_header->lsp_id));
hassof390d2c2004-09-10 20:48:21 +00002150 }
hassod3d74742005-09-28 18:30:51 +00002151 /* Refresh dynamic hostname in the cache. */
2152 isis_dynhn_insert (lsp->lsp_header->lsp_id, lsp->tlv_data.hostname,
2153 IS_LEVEL_1);
2154
hassof1082d12005-09-19 04:23:34 +00002155 lsp->lsp_header->rem_lifetime =
2156 htons (isis_jitter (lsp->area->max_lsp_lifetime[0], MAX_AGE_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00002157
hassof1082d12005-09-19 04:23:34 +00002158 ref_time = lsp->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
2159 MAX_LSP_GEN_INTERVAL : lsp->area->lsp_refresh[0];
2160
hassof390d2c2004-09-10 20:48:21 +00002161 THREAD_TIMER_ON (master, lsp->t_lsp_top_ref, top_lsp_refresh, lsp,
hassof1082d12005-09-19 04:23:34 +00002162 isis_jitter (ref_time, MAX_LSP_GEN_JITTER));
jardineb5d44e2003-12-23 08:09:43 +00002163
2164 return ISIS_OK;
2165}
2166
2167void
2168generate_topology_lsps (struct isis_area *area)
2169{
2170 struct listnode *node;
2171 int i, max = 0;
2172 struct arc *arc;
2173 u_char lspid[ISIS_SYS_ID_LEN + 2];
2174 struct isis_lsp *lsp;
hassof1082d12005-09-19 04:23:34 +00002175 unsigned long ref_time;
jardineb5d44e2003-12-23 08:09:43 +00002176
2177 /* first we find the maximal node */
paula8f03df2005-04-10 15:58:10 +00002178 for (ALL_LIST_ELEMENTS_RO (area->topology, node, arc))
hassof390d2c2004-09-10 20:48:21 +00002179 {
2180 if (arc->from_node > max)
2181 max = arc->from_node;
2182 if (arc->to_node > max)
2183 max = arc->to_node;
jardineb5d44e2003-12-23 08:09:43 +00002184 }
2185
hassof390d2c2004-09-10 20:48:21 +00002186 for (i = 1; i < (max + 1); i++)
2187 {
2188 memcpy (lspid, area->topology_baseis, ISIS_SYS_ID_LEN);
2189 LSP_PSEUDO_ID (lspid) = 0x00;
2190 LSP_FRAGMENT (lspid) = 0x00;
2191 lspid[ISIS_SYS_ID_LEN - 1] = (i & 0xFF);
2192 lspid[ISIS_SYS_ID_LEN - 2] = ((i >> 8) & 0xFF);
jardineb5d44e2003-12-23 08:09:43 +00002193
hassof390d2c2004-09-10 20:48:21 +00002194 lsp = lsp_new (lspid, isis_jitter (area->max_lsp_lifetime[0],
hassof1082d12005-09-19 04:23:34 +00002195 MAX_AGE_JITTER), 1, IS_LEVEL_1, 0, 1);
2196 if (!lsp)
2197 return;
hassof390d2c2004-09-10 20:48:21 +00002198 lsp->from_topology = 1;
hassof1082d12005-09-19 04:23:34 +00002199 lsp->area = area;
jardineb5d44e2003-12-23 08:09:43 +00002200
hassof1082d12005-09-19 04:23:34 +00002201 /* Creating LSP data based on topology info. */
2202 build_topology_lsp_data (lsp, area, i);
2203 /* Checksum is also calculated here. */
2204 lsp_seqnum_update (lsp);
hasso9551eea2005-09-28 18:26:25 +00002205 /* Take care of inserting dynamic hostname into cache. */
2206 isis_dynhn_insert (lspid, lsp->tlv_data.hostname, IS_LEVEL_1);
hassof1082d12005-09-19 04:23:34 +00002207
2208 ref_time = area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
2209 MAX_LSP_GEN_INTERVAL : area->lsp_refresh[0];
2210
2211 THREAD_TIMER_ON (master, lsp->t_lsp_top_ref, top_lsp_refresh, lsp,
2212 isis_jitter (ref_time, MAX_LSP_GEN_JITTER));
hassof390d2c2004-09-10 20:48:21 +00002213 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
2214 lsp_insert (lsp, area->lspdb[0]);
hassof390d2c2004-09-10 20:48:21 +00002215 }
jardineb5d44e2003-12-23 08:09:43 +00002216}
2217
2218void
2219remove_topology_lsps (struct isis_area *area)
2220{
2221 struct isis_lsp *lsp;
2222 dnode_t *dnode, *dnode_next;
2223
2224 dnode = dict_first (area->lspdb[0]);
hassof390d2c2004-09-10 20:48:21 +00002225 while (dnode != NULL)
2226 {
2227 dnode_next = dict_next (area->lspdb[0], dnode);
2228 lsp = dnode_get (dnode);
2229 if (lsp->from_topology)
2230 {
2231 THREAD_TIMER_OFF (lsp->t_lsp_top_ref);
2232 lsp_destroy (lsp);
2233 dict_delete (area->lspdb[0], dnode);
2234 }
2235 dnode = dnode_next;
jardineb5d44e2003-12-23 08:09:43 +00002236 }
jardineb5d44e2003-12-23 08:09:43 +00002237}
2238
2239void
hassof390d2c2004-09-10 20:48:21 +00002240build_topology_lsp_data (struct isis_lsp *lsp, struct isis_area *area,
jardineb5d44e2003-12-23 08:09:43 +00002241 int lsp_top_num)
2242{
hasso3fdb2dd2005-09-28 18:45:54 +00002243 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +00002244 struct arc *arc;
jardineb5d44e2003-12-23 08:09:43 +00002245 struct is_neigh *is_neigh;
hasso9551eea2005-09-28 18:26:25 +00002246 struct te_is_neigh *te_is_neigh;
jardineb5d44e2003-12-23 08:09:43 +00002247 char buff[200];
hassof1082d12005-09-19 04:23:34 +00002248 struct tlvs tlv_data;
2249 struct isis_lsp *lsp0 = lsp;
jardineb5d44e2003-12-23 08:09:43 +00002250
hassof1082d12005-09-19 04:23:34 +00002251 /* Add area addresses. FIXME: Is it needed at all? */
2252 if (lsp->tlv_data.area_addrs == NULL)
2253 lsp->tlv_data.area_addrs = list_new ();
2254 list_add_list (lsp->tlv_data.area_addrs, area->area_addrs);
jardineb5d44e2003-12-23 08:09:43 +00002255
hassof1082d12005-09-19 04:23:34 +00002256 if (lsp->tlv_data.nlpids == NULL)
2257 lsp->tlv_data.nlpids = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct nlpids));
2258 lsp->tlv_data.nlpids->count = 1;
2259 lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP;
jardineb5d44e2003-12-23 08:09:43 +00002260
hassof1082d12005-09-19 04:23:34 +00002261 if (area->dynhostname)
2262 {
2263 lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV,
2264 sizeof (struct hostname));
2265 memset (buff, 0x00, 200);
2266 sprintf (buff, "%s%d", area->topology_basedynh ? area->topology_basedynh :
2267 "feedme", lsp_top_num);
2268 memcpy (lsp->tlv_data.hostname->name, buff, strlen (buff));
2269 lsp->tlv_data.hostname->namelen = strlen (buff);
2270 }
2271
2272 if (lsp->tlv_data.nlpids)
2273 tlv_add_nlpid (lsp->tlv_data.nlpids, lsp->pdu);
2274 if (lsp->tlv_data.hostname)
2275 tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu);
2276 if (lsp->tlv_data.area_addrs && listcount (lsp->tlv_data.area_addrs) > 0)
2277 tlv_add_area_addrs (lsp->tlv_data.area_addrs, lsp->pdu);
2278
2279 memset (&tlv_data, 0, sizeof (struct tlvs));
2280 if (tlv_data.is_neighs == NULL)
hasso9551eea2005-09-28 18:26:25 +00002281 {
2282 tlv_data.is_neighs = list_new ();
2283 tlv_data.is_neighs->del = free_tlv;
2284 }
hassof1082d12005-09-19 04:23:34 +00002285
2286 /* Add reachability for this IS for simulated 1. */
hassof390d2c2004-09-10 20:48:21 +00002287 if (lsp_top_num == 1)
2288 {
hasso3fdb2dd2005-09-28 18:45:54 +00002289 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
hassof1082d12005-09-19 04:23:34 +00002290
hassof390d2c2004-09-10 20:48:21 +00002291 memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
jardineb5d44e2003-12-23 08:09:43 +00002292 LSP_PSEUDO_ID (is_neigh->neigh_id) = 0x00;
hassof1082d12005-09-19 04:23:34 +00002293 /* Metric MUST NOT be 0, unless it's not alias TLV. */
2294 is_neigh->metrics.metric_default = 0x01;
jardineb5d44e2003-12-23 08:09:43 +00002295 is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
2296 is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
2297 is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
hassof1082d12005-09-19 04:23:34 +00002298 listnode_add (tlv_data.is_neighs, is_neigh);
jardineb5d44e2003-12-23 08:09:43 +00002299 }
hassof390d2c2004-09-10 20:48:21 +00002300
hassof1082d12005-09-19 04:23:34 +00002301 /* Add IS reachabilities. */
hasso3fdb2dd2005-09-28 18:45:54 +00002302 for (ALL_LIST_ELEMENTS_RO (area->topology, node, arc))
hassof390d2c2004-09-10 20:48:21 +00002303 {
hassof1082d12005-09-19 04:23:34 +00002304 int to_lsp = 0;
2305
2306 if ((lsp_top_num != arc->from_node) && (lsp_top_num != arc->to_node))
2307 continue;
2308
2309 if (lsp_top_num == arc->from_node)
2310 to_lsp = arc->to_node;
2311 else
2312 to_lsp = arc->from_node;
2313
hasso9551eea2005-09-28 18:26:25 +00002314 if (area->oldmetric)
2315 {
2316 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
hassof1082d12005-09-19 04:23:34 +00002317
hasso9551eea2005-09-28 18:26:25 +00002318 memcpy (&is_neigh->neigh_id, area->topology_baseis, ISIS_SYS_ID_LEN);
2319 is_neigh->neigh_id[ISIS_SYS_ID_LEN - 1] = (to_lsp & 0xFF);
2320 is_neigh->neigh_id[ISIS_SYS_ID_LEN - 2] = ((to_lsp >> 8) & 0xFF);
2321 is_neigh->metrics.metric_default = arc->distance;
2322 is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
2323 is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
2324 is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
2325 listnode_add (tlv_data.is_neighs, is_neigh);
2326 }
2327
2328 if (area->newmetric)
2329 {
2330 uint32_t metric;
2331
2332 if (tlv_data.te_is_neighs == NULL)
2333 {
2334 tlv_data.te_is_neighs = list_new ();
2335 tlv_data.te_is_neighs->del = free_tlv;
2336 }
2337 te_is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct te_is_neigh));
2338 memcpy (&te_is_neigh->neigh_id, area->topology_baseis,
2339 ISIS_SYS_ID_LEN);
2340 te_is_neigh->neigh_id[ISIS_SYS_ID_LEN - 1] = (to_lsp & 0xFF);
2341 te_is_neigh->neigh_id[ISIS_SYS_ID_LEN - 2] = ((to_lsp >> 8) & 0xFF);
2342 metric = ((htonl(arc->distance) >> 8) & 0xffffff);
2343 memcpy (te_is_neigh->te_metric, &metric, 3);
2344 listnode_add (tlv_data.te_is_neighs, te_is_neigh);
2345 }
hassof390d2c2004-09-10 20:48:21 +00002346 }
hassof1082d12005-09-19 04:23:34 +00002347
2348 while (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
2349 {
2350 if (lsp->tlv_data.is_neighs == NULL)
2351 lsp->tlv_data.is_neighs = list_new ();
hasso9551eea2005-09-28 18:26:25 +00002352 lsp_tlv_fit (lsp, &tlv_data.is_neighs, &lsp->tlv_data.is_neighs,
hassof1082d12005-09-19 04:23:34 +00002353 IS_NEIGHBOURS_LEN, area->lsp_frag_threshold,
2354 tlv_add_is_neighs);
2355 if (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
2356 lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
2357 lsp0, area, IS_LEVEL_1);
2358 }
2359
hasso9551eea2005-09-28 18:26:25 +00002360 while (tlv_data.te_is_neighs && listcount (tlv_data.te_is_neighs))
2361 {
2362 if (lsp->tlv_data.te_is_neighs == NULL)
2363 lsp->tlv_data.te_is_neighs = list_new ();
2364 lsp_tlv_fit (lsp, &tlv_data.te_is_neighs, &lsp->tlv_data.te_is_neighs,
2365 IS_NEIGHBOURS_LEN, area->lsp_frag_threshold,
2366 tlv_add_te_is_neighs);
2367 if (tlv_data.te_is_neighs && listcount (tlv_data.te_is_neighs))
2368 lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
2369 lsp0, area, IS_LEVEL_1);
2370 }
2371
hassof1082d12005-09-19 04:23:34 +00002372 free_tlvs (&tlv_data);
2373 return;
jardineb5d44e2003-12-23 08:09:43 +00002374}
2375#endif /* TOPOLOGY_GENERATE */