]> git.proxmox.com Git - mirror_frr.git/blob - isisd/isis_lsp.c
* isis_lsp.c: Better output of detailed LSP printout and fixed TE IPv4
[mirror_frr.git] / isisd / isis_lsp.c
1 /*
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 */
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <zebra.h>
27
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
59 #define LSP_MEMORY_PREASSIGN
60
61 extern struct isis *isis;
62 extern struct thread_master *master;
63 extern struct in_addr router_id_zebra;
64
65 /* staticly assigned vars for printing purposes */
66 char lsp_bits_string[200]; /* FIXME: enough ? */
67
68 int
69 lsp_id_cmp (u_char * id1, u_char * id2)
70 {
71 return memcmp (id1, id2, ISIS_SYS_ID_LEN + 2);
72 }
73
74 dict_t *
75 lsp_db_init (void)
76 {
77 dict_t *dict;
78
79 dict = dict_create (DICTCOUNT_T_MAX, (dict_comp_t) lsp_id_cmp);
80
81 return dict;
82 }
83
84 struct isis_lsp *
85 lsp_search (u_char * id, dict_t * lspdb)
86 {
87 dnode_t *node;
88
89 #ifdef EXTREME_DEBUG
90 dnode_t *dn;
91
92 zlog_debug ("searching db");
93 for (dn = dict_first (lspdb); dn; dn = dict_next (lspdb, dn))
94 {
95 zlog_debug ("%s\t%pX", rawlspid_print ((char *) dnode_getkey (dn)),
96 dnode_get (dn));
97 }
98 #endif /* EXTREME DEBUG */
99
100 node = dict_lookup (lspdb, id);
101
102 if (node)
103 return (struct isis_lsp *) dnode_get (node);
104
105 return NULL;
106 }
107
108 static void
109 lsp_clear_data (struct isis_lsp *lsp)
110 {
111 if (!lsp)
112 return;
113
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 }
121 if (lsp->tlv_data.is_neighs)
122 list_delete (lsp->tlv_data.is_neighs);
123 if (lsp->tlv_data.area_addrs)
124 list_delete (lsp->tlv_data.area_addrs);
125 if (lsp->tlv_data.es_neighs)
126 list_delete (lsp->tlv_data.es_neighs);
127 if (lsp->tlv_data.ipv4_addrs)
128 list_delete (lsp->tlv_data.ipv4_addrs);
129 if (lsp->tlv_data.ipv4_int_reachs)
130 list_delete (lsp->tlv_data.ipv4_int_reachs);
131 if (lsp->tlv_data.ipv4_ext_reachs)
132 list_delete (lsp->tlv_data.ipv4_ext_reachs);
133 #ifdef HAVE_IPV6
134 if (lsp->tlv_data.ipv6_addrs)
135 list_delete (lsp->tlv_data.ipv6_addrs);
136 if (lsp->tlv_data.ipv6_reachs)
137 list_delete (lsp->tlv_data.ipv6_reachs);
138 #endif /* HAVE_IPV6 */
139
140 memset (&lsp->tlv_data, 0, sizeof (struct tlvs));
141
142 return;
143 }
144
145 static void
146 lsp_destroy (struct isis_lsp *lsp)
147 {
148 if (!lsp)
149 return;
150
151 lsp_clear_data (lsp);
152
153 if (LSP_FRAGMENT (lsp->lsp_header->lsp_id) == 0 && lsp->lspu.frags)
154 {
155 list_delete (lsp->lspu.frags);
156 }
157
158 if (lsp->pdu)
159 stream_free (lsp->pdu);
160 XFREE (MTYPE_ISIS_LSP, lsp);
161 }
162
163 void
164 lsp_db_destroy (dict_t * lspdb)
165 {
166 dnode_t *dnode, *next;
167 struct isis_lsp *lsp;
168
169 dnode = dict_first (lspdb);
170 while (dnode)
171 {
172 next = dict_next (lspdb, dnode);
173 lsp = dnode_get (dnode);
174 lsp_destroy (lsp);
175 dict_delete_free (lspdb, dnode);
176 dnode = next;
177 }
178
179 dict_free (lspdb);
180
181 return;
182 }
183
184 /*
185 * Remove all the frags belonging to the given lsp
186 */
187 static void
188 lsp_remove_frags (struct list *frags, dict_t * lspdb)
189 {
190 dnode_t *dnode;
191 struct listnode *lnode, *lnnode;
192 struct isis_lsp *lsp;
193
194 for (ALL_LIST_ELEMENTS (frags, lnode, lnnode, lsp))
195 {
196 dnode = dict_lookup (lspdb, lsp->lsp_header->lsp_id);
197 lsp_destroy (lsp);
198 dnode_destroy (dict_delete (lspdb, dnode));
199 }
200
201 list_delete_all_node (frags);
202
203 return;
204 }
205
206 void
207 lsp_search_and_destroy (u_char * id, dict_t * lspdb)
208 {
209 dnode_t *node;
210 struct isis_lsp *lsp;
211
212 node = dict_lookup (lspdb, id);
213 if (node)
214 {
215 node = dict_delete (lspdb, node);
216 lsp = dnode_get (node);
217 /*
218 * If this is a zero lsp, remove all the frags now
219 */
220 if (LSP_FRAGMENT (lsp->lsp_header->lsp_id) == 0)
221 {
222 if (lsp->lspu.frags)
223 lsp_remove_frags (lsp->lspu.frags, lspdb);
224 }
225 else
226 {
227 /*
228 * else just remove this frag, from the zero lsps' frag list
229 */
230 if (lsp->lspu.zero_lsp && lsp->lspu.zero_lsp->lspu.frags)
231 listnode_delete (lsp->lspu.zero_lsp->lspu.frags, lsp);
232 }
233 lsp_destroy (lsp);
234 dnode_destroy (node);
235 }
236 }
237
238 /*
239 * Compares a LSP to given values
240 * Params are given in net order
241 */
242 int
243 lsp_compare (char *areatag, struct isis_lsp *lsp, u_int32_t seq_num,
244 u_int16_t checksum, u_int16_t rem_lifetime)
245 {
246 /* no point in double ntohl on seqnum */
247 if (lsp->lsp_header->seq_num == seq_num &&
248 lsp->lsp_header->checksum == checksum &&
249 /*comparing with 0, no need to do ntohl */
250 ((lsp->lsp_header->rem_lifetime == 0 && rem_lifetime == 0) ||
251 (lsp->lsp_header->rem_lifetime != 0 && rem_lifetime != 0)))
252 {
253 if (isis->debugs & DEBUG_SNP_PACKETS)
254 {
255 zlog_debug ("ISIS-Snp (%s): LSP %s seq 0x%08x, cksum 0x%04x,"
256 " lifetime %us",
257 areatag,
258 rawlspid_print (lsp->lsp_header->lsp_id),
259 ntohl (lsp->lsp_header->seq_num),
260 ntohs (lsp->lsp_header->checksum),
261 ntohs (lsp->lsp_header->rem_lifetime));
262 zlog_debug ("ISIS-Snp (%s): is equal to ours seq 0x%08x,"
263 " cksum 0x%04x, lifetime %us",
264 areatag,
265 ntohl (seq_num), ntohs (checksum), ntohs (rem_lifetime));
266 }
267 return LSP_EQUAL;
268 }
269
270 if (ntohl (seq_num) >= ntohl (lsp->lsp_header->seq_num))
271 {
272 if (isis->debugs & DEBUG_SNP_PACKETS)
273 {
274 zlog_debug ("ISIS-Snp (%s): LSP %s seq 0x%08x, cksum 0x%04x,"
275 " lifetime %us",
276 areatag,
277 rawlspid_print (lsp->lsp_header->lsp_id),
278 ntohl (seq_num), ntohs (checksum), ntohs (rem_lifetime));
279 zlog_debug ("ISIS-Snp (%s): is newer than ours seq 0x%08x, "
280 "cksum 0x%04x, lifetime %us",
281 areatag,
282 ntohl (lsp->lsp_header->seq_num),
283 ntohs (lsp->lsp_header->checksum),
284 ntohs (lsp->lsp_header->rem_lifetime));
285 }
286 return LSP_NEWER;
287 }
288 if (isis->debugs & DEBUG_SNP_PACKETS)
289 {
290 zlog_debug
291 ("ISIS-Snp (%s): LSP %s seq 0x%08x, cksum 0x%04x, lifetime %us",
292 areatag, rawlspid_print (lsp->lsp_header->lsp_id), ntohl (seq_num),
293 ntohs (checksum), ntohs (rem_lifetime));
294 zlog_debug ("ISIS-Snp (%s): is older than ours seq 0x%08x,"
295 " cksum 0x%04x, lifetime %us", areatag,
296 ntohl (lsp->lsp_header->seq_num),
297 ntohs (lsp->lsp_header->checksum),
298 ntohs (lsp->lsp_header->rem_lifetime));
299 }
300
301 return LSP_OLDER;
302 }
303
304 void
305 lsp_inc_seqnum (struct isis_lsp *lsp, u_int32_t seq_num)
306 {
307 u_int32_t newseq;
308
309 if (seq_num == 0 || ntohl (lsp->lsp_header->seq_num) > seq_num)
310 newseq = ntohl (lsp->lsp_header->seq_num) + 1;
311 else
312 newseq = seq_num++;
313
314 lsp->lsp_header->seq_num = htonl (newseq);
315 iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
316 ntohs (lsp->lsp_header->pdu_len) - 12, 12);
317
318 return;
319 }
320
321 /*
322 * Genetates checksum for LSP and its frags
323 */
324 static void
325 lsp_seqnum_update (struct isis_lsp *lsp0)
326 {
327 struct isis_lsp *lsp;
328 struct listnode *node, *nnode;
329
330 lsp_inc_seqnum (lsp0, 0);
331
332 if (!lsp0->lspu.frags)
333 return;
334
335 for (ALL_LIST_ELEMENTS (lsp0->lspu.frags, node, nnode, lsp))
336 lsp_inc_seqnum (lsp, 0);
337
338 return;
339 }
340
341 int
342 isis_lsp_authinfo_check (struct stream *stream, struct isis_area *area,
343 int pdulen, struct isis_passwd *passwd)
344 {
345 uint32_t expected = 0, found;
346 struct tlvs tlvs;
347 int retval = 0;
348
349 expected |= TLVFLAG_AUTH_INFO;
350 retval = parse_tlvs (area->area_tag, stream->data +
351 ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN,
352 pdulen - ISIS_FIXED_HDR_LEN
353 - ISIS_LSP_HDR_LEN, &expected, &found, &tlvs);
354 if (retval || !(found & TLVFLAG_AUTH_INFO))
355 return 1; /* Auth fail (parsing failed or no auth-tlv) */
356
357 return authentication_check (passwd, &tlvs.auth_info);
358 }
359
360 static void
361 lsp_update_data (struct isis_lsp *lsp, struct stream *stream,
362 struct isis_area *area)
363 {
364 uint32_t expected = 0, found;
365 int retval;
366
367 /* copying only the relevant part of our stream */
368 lsp->pdu = stream_dup (stream);
369
370 /* setting pointers to the correct place */
371 lsp->isis_header = (struct isis_fixed_hdr *) (STREAM_DATA (lsp->pdu));
372 lsp->lsp_header = (struct isis_link_state_hdr *) (STREAM_DATA (lsp->pdu) +
373 ISIS_FIXED_HDR_LEN);
374 lsp->age_out = ZERO_AGE_LIFETIME;
375 lsp->installed = time (NULL);
376 /*
377 * Get LSP data i.e. TLVs
378 */
379 expected |= TLVFLAG_AUTH_INFO;
380 expected |= TLVFLAG_AREA_ADDRS;
381 expected |= TLVFLAG_IS_NEIGHS;
382 if ((lsp->lsp_header->lsp_bits & 3) == 3) /* a level 2 LSP */
383 expected |= TLVFLAG_PARTITION_DESIG_LEVEL2_IS;
384 expected |= TLVFLAG_NLPID;
385 if (area->dynhostname)
386 expected |= TLVFLAG_DYN_HOSTNAME;
387 if (area->newmetric)
388 {
389 expected |= TLVFLAG_TE_IS_NEIGHS;
390 expected |= TLVFLAG_TE_IPV4_REACHABILITY;
391 expected |= TLVFLAG_TE_ROUTER_ID;
392 }
393 expected |= TLVFLAG_IPV4_ADDR;
394 expected |= TLVFLAG_IPV4_INT_REACHABILITY;
395 expected |= TLVFLAG_IPV4_EXT_REACHABILITY;
396 #ifdef HAVE_IPV6
397 expected |= TLVFLAG_IPV6_ADDR;
398 expected |= TLVFLAG_IPV6_REACHABILITY;
399 #endif /* HAVE_IPV6 */
400
401 retval = parse_tlvs (area->area_tag, lsp->pdu->data +
402 ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN,
403 ntohs (lsp->lsp_header->pdu_len) - ISIS_FIXED_HDR_LEN
404 - ISIS_LSP_HDR_LEN, &expected, &found, &lsp->tlv_data);
405
406 if (found & TLVFLAG_DYN_HOSTNAME)
407 {
408 if (area->dynhostname)
409 isis_dynhn_insert (lsp->lsp_header->lsp_id, lsp->tlv_data.hostname,
410 (lsp->lsp_header->lsp_bits & LSPBIT_IST) ==
411 IS_LEVEL_1_AND_2 ? IS_LEVEL_2 :
412 (lsp->lsp_header->lsp_bits & LSPBIT_IST));
413 }
414
415 }
416
417 void
418 lsp_update (struct isis_lsp *lsp, struct isis_link_state_hdr *lsp_hdr,
419 struct stream *stream, struct isis_area *area, int level)
420 {
421 dnode_t *dnode = NULL;
422
423 /* Remove old LSP from LSP database. */
424 dnode = dict_lookup (area->lspdb[level - 1], lsp->lsp_header->lsp_id);
425 if (dnode)
426 dnode_destroy (dict_delete (area->lspdb[level - 1], dnode));
427
428 /* free the old lsp data */
429 XFREE (MTYPE_STREAM_DATA, lsp->pdu);
430 lsp_clear_data (lsp);
431
432 /* rebuild the lsp data */
433 lsp_update_data (lsp, stream, area);
434
435 /* set the new values for lsp header */
436 memcpy (lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN);
437
438 if (dnode)
439 lsp_insert (lsp, area->lspdb[level - 1]);
440 }
441
442 /* creation of LSP directly from what we received */
443 struct isis_lsp *
444 lsp_new_from_stream_ptr (struct stream *stream,
445 u_int16_t pdu_len, struct isis_lsp *lsp0,
446 struct isis_area *area)
447 {
448 struct isis_lsp *lsp;
449
450 lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
451 lsp_update_data (lsp, stream, area);
452
453 if (lsp0 == NULL)
454 {
455 /*
456 * zero lsp -> create the list for fragments
457 */
458 lsp->lspu.frags = list_new ();
459 }
460 else
461 {
462 /*
463 * a fragment -> set the backpointer and add this to zero lsps frag list
464 */
465 lsp->lspu.zero_lsp = lsp0;
466 listnode_add (lsp0->lspu.frags, lsp);
467 }
468
469 return lsp;
470 }
471
472 struct isis_lsp *
473 lsp_new (u_char * lsp_id, u_int16_t rem_lifetime, u_int32_t seq_num,
474 u_int8_t lsp_bits, u_int16_t checksum, int level)
475 {
476 struct isis_lsp *lsp;
477
478 lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
479 if (!lsp)
480 {
481 /* FIXME: set lspdbol bit */
482 zlog_warn ("lsp_new(): out of memory");
483 return NULL;
484 }
485 #ifdef LSP_MEMORY_PREASSIGN
486 lsp->pdu = stream_new (1514); /*Should be minimal mtu? yup... */
487 #else
488 /* We need to do realloc on TLVs additions */
489 lsp->pdu = malloc (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
490 #endif /* LSP_MEMORY_PREASSIGN */
491 if (LSP_FRAGMENT (lsp_id) == 0)
492 lsp->lspu.frags = list_new ();
493 lsp->isis_header = (struct isis_fixed_hdr *) (STREAM_DATA (lsp->pdu));
494 lsp->lsp_header = (struct isis_link_state_hdr *)
495 (STREAM_DATA (lsp->pdu) + ISIS_FIXED_HDR_LEN);
496
497 /* at first we fill the FIXED HEADER */
498 (level == 1) ? fill_fixed_hdr (lsp->isis_header, L1_LINK_STATE) :
499 fill_fixed_hdr (lsp->isis_header, L2_LINK_STATE);
500
501 /* now for the LSP HEADER */
502 /* Minimal LSP PDU size */
503 lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
504 memcpy (lsp->lsp_header->lsp_id, lsp_id, ISIS_SYS_ID_LEN + 2);
505 lsp->lsp_header->checksum = checksum; /* Provided in network order */
506 lsp->lsp_header->seq_num = htonl (seq_num);
507 lsp->lsp_header->rem_lifetime = htons (rem_lifetime);
508 lsp->lsp_header->lsp_bits = lsp_bits;
509 lsp->level = level;
510 lsp->age_out = ZERO_AGE_LIFETIME;
511
512 stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
513
514 if (isis->debugs & DEBUG_EVENTS)
515 zlog_debug ("New LSP with ID %s-%02x-%02x seqnum %08x",
516 sysid_print (lsp_id), LSP_PSEUDO_ID (lsp->lsp_header->lsp_id),
517 LSP_FRAGMENT (lsp->lsp_header->lsp_id),
518 ntohl (lsp->lsp_header->seq_num));
519
520 return lsp;
521 }
522
523 void
524 lsp_insert (struct isis_lsp *lsp, dict_t * lspdb)
525 {
526 dict_alloc_insert (lspdb, lsp->lsp_header->lsp_id, lsp);
527 }
528
529 /*
530 * Build a list of LSPs with non-zero ht bounded by start and stop ids
531 */
532 void
533 lsp_build_list_nonzero_ht (u_char * start_id, u_char * stop_id,
534 struct list *list, dict_t * lspdb)
535 {
536 dnode_t *first, *last, *curr;
537
538 first = dict_lower_bound (lspdb, start_id);
539 if (!first)
540 return;
541
542 last = dict_upper_bound (lspdb, stop_id);
543
544 curr = first;
545
546 if (((struct isis_lsp *) (curr->dict_data))->lsp_header->rem_lifetime)
547 listnode_add (list, first->dict_data);
548
549 while (curr)
550 {
551 curr = dict_next (lspdb, curr);
552 if (curr &&
553 ((struct isis_lsp *) (curr->dict_data))->lsp_header->rem_lifetime)
554 listnode_add (list, curr->dict_data);
555 if (curr == last)
556 break;
557 }
558
559 return;
560 }
561
562 /*
563 * Build a list of all LSPs bounded by start and stop ids
564 */
565 void
566 lsp_build_list (u_char * start_id, u_char * stop_id,
567 struct list *list, dict_t * lspdb)
568 {
569 dnode_t *first, *last, *curr;
570
571 first = dict_lower_bound (lspdb, start_id);
572 if (!first)
573 return;
574
575 last = dict_upper_bound (lspdb, stop_id);
576
577 curr = first;
578
579 listnode_add (list, first->dict_data);
580
581 while (curr)
582 {
583 curr = dict_next (lspdb, curr);
584 if (curr)
585 listnode_add (list, curr->dict_data);
586 if (curr == last)
587 break;
588 }
589
590 return;
591 }
592
593 /*
594 * Build a list of LSPs with SSN flag set for the given circuit
595 */
596 void
597 lsp_build_list_ssn (struct isis_circuit *circuit, struct list *list,
598 dict_t * lspdb)
599 {
600 dnode_t *dnode, *next;
601 struct isis_lsp *lsp;
602
603 dnode = dict_first (lspdb);
604 while (dnode != NULL)
605 {
606 next = dict_next (lspdb, dnode);
607 lsp = dnode_get (dnode);
608 if (ISIS_CHECK_FLAG (lsp->SSNflags, circuit))
609 listnode_add (list, lsp);
610 dnode = next;
611 }
612
613 return;
614 }
615
616 static void
617 lsp_set_time (struct isis_lsp *lsp)
618 {
619 assert (lsp);
620
621 if (lsp->lsp_header->rem_lifetime == 0)
622 {
623 if (lsp->age_out != 0)
624 lsp->age_out--;
625 return;
626 }
627
628 /* If we are turning 0 */
629 /* ISO 10589 - 7.3.16.4 first paragraph */
630
631 if (ntohs (lsp->lsp_header->rem_lifetime) == 1)
632 {
633 /* 7.3.16.4 a) set SRM flags on all */
634 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
635 /* 7.3.16.4 b) retain only the header FIXME */
636 /* 7.3.16.4 c) record the time to purge FIXME (other way to do it) */
637 }
638
639 lsp->lsp_header->rem_lifetime =
640 htons (ntohs (lsp->lsp_header->rem_lifetime) - 1);
641 }
642
643 static void
644 lspid_print (u_char * lsp_id, u_char * trg, char dynhost, char frag)
645 {
646 struct isis_dynhn *dyn = NULL;
647 u_char id[SYSID_STRLEN];
648
649 if (dynhost)
650 dyn = dynhn_find_by_id (lsp_id);
651 else
652 dyn = NULL;
653
654 if (dyn)
655 sprintf ((char *)id, "%.14s", dyn->name.name);
656 else if (!memcmp (isis->sysid, lsp_id, ISIS_SYS_ID_LEN) & dynhost)
657 sprintf ((char *)id, "%.14s", unix_hostname ());
658 else
659 {
660 memcpy (id, sysid_print (lsp_id), 15);
661 }
662 if (frag)
663 sprintf ((char *)trg, "%s.%02x-%02x", id, LSP_PSEUDO_ID (lsp_id),
664 LSP_FRAGMENT (lsp_id));
665 else
666 sprintf ((char *)trg, "%s.%02x", id, LSP_PSEUDO_ID (lsp_id));
667 }
668
669 /* Convert the lsp attribute bits to attribute string */
670 const char *
671 lsp_bits2string (u_char * lsp_bits)
672 {
673 char *pos = lsp_bits_string;
674
675 if (!*lsp_bits)
676 return " none";
677
678 /* we only focus on the default metric */
679 pos += sprintf (pos, "%d/",
680 ISIS_MASK_LSP_ATT_DEFAULT_BIT (*lsp_bits) ? 1 : 0);
681
682 pos += sprintf (pos, "%d/",
683 ISIS_MASK_LSP_PARTITION_BIT (*lsp_bits) ? 1 : 0);
684
685 pos += sprintf (pos, "%d", ISIS_MASK_LSP_OL_BIT (*lsp_bits) ? 1 : 0);
686
687 *(pos) = '\0';
688
689 return lsp_bits_string;
690 }
691
692 /* this function prints the lsp on show isis database */
693 static void
694 lsp_print (dnode_t * node, struct vty *vty, char dynhost)
695 {
696 struct isis_lsp *lsp = dnode_get (node);
697 u_char LSPid[255];
698
699 lspid_print (lsp->lsp_header->lsp_id, LSPid, dynhost, 1);
700 vty_out (vty, "%-21s%c ", LSPid, lsp->own_lsp ? '*' : ' ');
701 vty_out (vty, "0x%08x ", ntohl (lsp->lsp_header->seq_num));
702 vty_out (vty, "0x%04x ", ntohs (lsp->lsp_header->checksum));
703
704 if (ntohs (lsp->lsp_header->rem_lifetime) == 0)
705 vty_out (vty, " (%2u)", lsp->age_out);
706 else
707 vty_out (vty, "%5u", ntohs (lsp->lsp_header->rem_lifetime));
708
709 vty_out (vty, " %s%s",
710 lsp_bits2string (&lsp->lsp_header->lsp_bits), VTY_NEWLINE);
711 }
712
713 static void
714 lsp_print_detail (dnode_t * node, struct vty *vty, char dynhost)
715 {
716 struct isis_lsp *lsp = dnode_get (node);
717 struct area_addr *area_addr;
718 int i;
719 struct listnode *lnode, *lnnode;
720 struct is_neigh *is_neigh;
721 struct te_is_neigh *te_is_neigh;
722 struct ipv4_reachability *ipv4_reach;
723 struct in_addr *ipv4_addr;
724 struct te_ipv4_reachability *te_ipv4_reach;
725 #ifdef HAVE_IPV6
726 struct ipv6_reachability *ipv6_reach;
727 struct in6_addr in6;
728 #endif
729 u_char LSPid[255];
730 u_char hostname[255];
731 u_char buff[BUFSIZ];
732 u_char ipv4_reach_prefix[20];
733 u_char ipv4_reach_mask[20];
734 u_char ipv4_address[20];
735
736 lspid_print (lsp->lsp_header->lsp_id, LSPid, dynhost, 1);
737 lsp_print (node, vty, dynhost);
738
739 /* for all area address */
740 if (lsp->tlv_data.area_addrs)
741 for (ALL_LIST_ELEMENTS (lsp->tlv_data.area_addrs, lnode,
742 lnnode, area_addr))
743 {
744 vty_out (vty, " Area Address: %s%s",
745 isonet_print (area_addr->area_addr, area_addr->addr_len),
746 VTY_NEWLINE);
747 }
748
749 /* for the nlpid tlv */
750 if (lsp->tlv_data.nlpids)
751 {
752 for (i = 0; i < lsp->tlv_data.nlpids->count; i++)
753 {
754 switch (lsp->tlv_data.nlpids->nlpids[i])
755 {
756 case NLPID_IP:
757 case NLPID_IPV6:
758 vty_out (vty, " NLPID: 0x%X%s",
759 lsp->tlv_data.nlpids->nlpids[i], VTY_NEWLINE);
760 break;
761 default:
762 vty_out (vty, " NLPID: %s%s", "unknown", VTY_NEWLINE);
763 break;
764 }
765 }
766 }
767
768 /* for the hostname tlv */
769 if (lsp->tlv_data.hostname)
770 {
771 bzero (hostname, sizeof (hostname));
772 memcpy (hostname, lsp->tlv_data.hostname->name,
773 lsp->tlv_data.hostname->namelen);
774 vty_out (vty, " Hostname: %s%s", hostname, VTY_NEWLINE);
775 }
776
777 if (lsp->tlv_data.ipv4_addrs)
778 for (ALL_LIST_ELEMENTS (lsp->tlv_data.ipv4_addrs, lnode,
779 lnnode, ipv4_addr))
780 {
781 memcpy (ipv4_address, inet_ntoa (*ipv4_addr), sizeof (ipv4_address));
782 vty_out (vty, " IP: %s%s", ipv4_address, VTY_NEWLINE);
783 }
784
785 /* TE router id */
786 if (lsp->tlv_data.router_id)
787 {
788 memcpy (ipv4_address, inet_ntoa (lsp->tlv_data.router_id->id),
789 sizeof (ipv4_address));
790 vty_out (vty, " Router ID: %s%s", ipv4_address, VTY_NEWLINE);
791 }
792
793 /* for the IS neighbor tlv */
794 if (lsp->tlv_data.is_neighs)
795 for (ALL_LIST_ELEMENTS (lsp->tlv_data.is_neighs, lnode, lnnode, is_neigh))
796 {
797 lspid_print (is_neigh->neigh_id, LSPid, dynhost, 0);
798 vty_out (vty, " Metric: %-10d IS %s%s",
799 is_neigh->metrics.metric_default, LSPid, VTY_NEWLINE);
800 }
801
802 /* for the internal reachable tlv */
803 if (lsp->tlv_data.ipv4_int_reachs)
804 for (ALL_LIST_ELEMENTS (lsp->tlv_data.ipv4_int_reachs, lnode,
805 lnnode, ipv4_reach))
806 {
807 memcpy (ipv4_reach_prefix, inet_ntoa (ipv4_reach->prefix),
808 sizeof (ipv4_reach_prefix));
809 memcpy (ipv4_reach_mask, inet_ntoa (ipv4_reach->mask),
810 sizeof (ipv4_reach_mask));
811 vty_out (vty, " Metric: %-10d IP-Internal %s %s%s",
812 ipv4_reach->metrics.metric_default, ipv4_reach_prefix,
813 ipv4_reach_mask, VTY_NEWLINE);
814 }
815
816 /* for the external reachable tlv */
817 if (lsp->tlv_data.ipv4_ext_reachs)
818 for (ALL_LIST_ELEMENTS (lsp->tlv_data.ipv4_ext_reachs, lnode,
819 lnnode, ipv4_reach))
820 {
821 memcpy (ipv4_reach_prefix, inet_ntoa (ipv4_reach->prefix),
822 sizeof (ipv4_reach_prefix));
823 memcpy (ipv4_reach_mask, inet_ntoa (ipv4_reach->mask),
824 sizeof (ipv4_reach_mask));
825 vty_out (vty, " Metric: %-10d IP-External %s %s%s",
826 ipv4_reach->metrics.metric_default, ipv4_reach_prefix,
827 ipv4_reach_mask, VTY_NEWLINE);
828 }
829
830 /* IPv6 tlv */
831 #ifdef HAVE_IPV6
832 if (lsp->tlv_data.ipv6_reachs)
833 for (ALL_LIST_ELEMENTS (lsp->tlv_data.ipv6_reachs, lnode,
834 lnnode, ipv6_reach))
835 {
836 memset (&in6, 0, sizeof (in6));
837 memcpy (in6.s6_addr, ipv6_reach->prefix,
838 PSIZE (ipv6_reach->prefix_len));
839 inet_ntop (AF_INET6, &in6, (char *)buff, BUFSIZ);
840 if ((ipv6_reach->control_info &&
841 CTRL_INFO_DISTRIBUTION) == DISTRIBUTION_INTERNAL)
842 vty_out (vty, " Metric: %-10d IPv6-Internal %s/%d%s",
843 ntohl (ipv6_reach->metric),
844 buff, ipv6_reach->prefix_len, VTY_NEWLINE);
845 else
846 vty_out (vty, " Metric: %-10d IPv6-External %s/%d%s",
847 ntohl (ipv6_reach->metric),
848 buff, ipv6_reach->prefix_len, VTY_NEWLINE);
849 }
850 #endif
851
852 /* TE IS neighbor tlv */
853 if (lsp->tlv_data.te_is_neighs)
854 for (ALL_LIST_ELEMENTS (lsp->tlv_data.te_is_neighs, lnode,
855 lnnode, te_is_neigh))
856 {
857 uint32_t metric;
858 memcpy (&metric, te_is_neigh->te_metric, 3);
859 lspid_print (te_is_neigh->neigh_id, LSPid, dynhost, 0);
860 vty_out (vty, " Metric: %-10d IS-Extended %s%s",
861 ntohl (metric << 8), LSPid, VTY_NEWLINE);
862 }
863
864 /* TE IPv4 tlv */
865 if (lsp->tlv_data.te_ipv4_reachs)
866 for (ALL_LIST_ELEMENTS (lsp->tlv_data.te_ipv4_reachs, lnode,
867 lnnode, te_ipv4_reach))
868 {
869 /* FIXME: There should be better way to output this stuff. */
870 vty_out (vty, " Metric: %-10d IP-Extended %s/%d%s",
871 ntohl (te_ipv4_reach->te_metric),
872 inet_ntoa (newprefix2inaddr (&te_ipv4_reach->prefix_start,
873 te_ipv4_reach->control)),
874 te_ipv4_reach->control & 0x3F, VTY_NEWLINE);
875 }
876
877 return;
878 }
879
880 /* print all the lsps info in the local lspdb */
881 int
882 lsp_print_all (struct vty *vty, dict_t * lspdb, char detail, char dynhost)
883 {
884
885 dnode_t *node = dict_first (lspdb), *next;
886 int lsp_count = 0;
887
888 /* print the title, for both modes */
889 vty_out (vty, "LSP ID LSP Seq Num LSP Checksum "
890 "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 }
903 }
904 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 }
913 }
914
915 return lsp_count;
916 }
917
918 #if 0
919 /* this function reallocate memory to an lsp pdu, with an additional
920 * size of memory, it scans the lsp and moves all pointers the
921 * way they should */
922 static u_char *
923 lsppdu_realloc (struct isis_lsp * lsp, int memorytype, int size)
924 {
925 u_char *retval;
926
927 retval = STREAM_DATA (lsp->pdu) + ntohs (lsp->lsp_header->pdu_len);
928 #ifdef LSP_MEMORY_PREASSIGN
929 lsp->lsp_header->pdu_len = htons (ntohs (lsp->lsp_header->pdu_len) + size);
930 return retval;
931 #else /* otherwise we have to move all pointers */
932 u_char *newpdu;
933 newpdu = stream_new (ntohs (lsp->lsp_header->pdu_len) + size);
934 stream_put (newpdu, STREAM_DATA(lsp->pdu), ntohs (lsp->lsp_header->pdu_len));
935 XFREE (memorytype, lsp->pdu);
936 lsp->pdu = newpdu;
937 lsp->isis_header = (struct isis_fixed_hdr *) STREAM_DATA (lsp->pdu);
938 lsp->lsp_header = (struct isis_link_state_hdr *)
939 (STREAM_DATA (lsp->pdu) + ISIS_FIXED_HDR_LEN);
940 htons (ntohs (lsp->lsp_header->pdu_len) += size);
941 return STREAM_DATA (lsp->pdu) + (lsp->lsp_header->pdu_len - size);
942 #endif /* LSP_MEMORY_PREASSIGN */
943 }
944 #endif
945
946 #if 0 /* Saving the old one just in case :) */
947 /*
948 * Builds the lsp->tlv_data
949 * and writes the tlvs into lsp->pdu
950 */
951 void
952 lsp_build_nonpseudo (struct isis_lsp *lsp, struct isis_area *area)
953 {
954 struct is_neigh *is_neigh;
955 struct listnode *node, *nnode, *ipnode, *ipnnode;
956 int level = lsp->level;
957 struct isis_circuit *circuit;
958 struct prefix_ipv4 *ipv4;
959 struct ipv4_reachability *ipreach;
960 struct isis_adjacency *nei;
961 #ifdef HAVE_IPV6
962 struct prefix_ipv6 *ipv6;
963 struct ipv6_reachability *ip6reach;
964 #endif /* HAVE_IPV6 */
965
966 /*
967 * First add the tlvs related to area
968 */
969
970 /* Area addresses */
971 if (lsp->tlv_data.area_addrs == NULL)
972 lsp->tlv_data.area_addrs = list_new ();
973 list_add_list (lsp->tlv_data.area_addrs, area->area_addrs);
974 /* Protocols Supported */
975 if (area->ip_circuits > 0
976 #ifdef HAVE_IPV6
977 || area->ipv6_circuits > 0
978 #endif /* HAVE_IPV6 */
979 )
980 {
981 lsp->tlv_data.nlpids = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct nlpids));
982 lsp->tlv_data.nlpids->count = 0;
983 if (area->ip_circuits > 0)
984 {
985 lsp->tlv_data.nlpids->count++;
986 lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP;
987 }
988 #ifdef HAVE_IPV6
989 if (area->ipv6_circuits > 0)
990 {
991 lsp->tlv_data.nlpids->count++;
992 lsp->tlv_data.nlpids->nlpids[lsp->tlv_data.nlpids->count - 1] =
993 NLPID_IPV6;
994 }
995 #endif /* HAVE_IPV6 */
996 }
997 /* Dynamic Hostname */
998 if (area->dynhostname)
999 {
1000 lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV,
1001 sizeof (struct hostname));
1002 memcpy (&lsp->tlv_data.hostname->name, unix_hostname (),
1003 strlen (unix_hostname ()));
1004 lsp->tlv_data.hostname->namelen = strlen (unix_hostname ());
1005 }
1006 #ifdef TOPOLOGY_GENERATE
1007 /*
1008 * If we have a topology in this area, we need to connect this lsp to
1009 * the first topology lsp
1010 */
1011 if ((area->topology) && (level == 1))
1012 {
1013 if (lsp->tlv_data.is_neighs == NULL)
1014 lsp->tlv_data.is_neighs = list_new ();
1015 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1016 memcpy (&is_neigh->neigh_id, area->topology_baseis, ISIS_SYS_ID_LEN);
1017 /* connected to the first */
1018 is_neigh->neigh_id[ISIS_SYS_ID_LEN - 1] = (0x01);
1019 /* this is actually the same system, why mess the SPT */
1020 is_neigh->metrics.metric_default = 0;
1021 is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
1022 is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
1023 is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
1024 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
1025
1026 }
1027 #endif
1028
1029 /*
1030 * Then add tlvs related to circuits
1031 */
1032 for (ALL_LIST_ELEMENTS (area->circuit_list, node, nnode, circuit))
1033 {
1034 if (circuit->state != C_STATE_UP)
1035 continue;
1036
1037 /*
1038 * Add IPv4 internal reachability of this circuit
1039 */
1040 if (circuit->ip_router && circuit->ip_addrs &&
1041 circuit->ip_addrs->count > 0)
1042 {
1043 if (lsp->tlv_data.ipv4_int_reachs == NULL)
1044 {
1045 lsp->tlv_data.ipv4_int_reachs = list_new ();
1046 lsp->tlv_data.ipv4_int_reachs->del = free_tlv;
1047 }
1048 for (ALL_LIST_ELEMENTS (circuit->ip_addrs, ipnode, ipnnode, ipv4))
1049 {
1050 ipreach =
1051 XCALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv4_reachability));
1052 ipreach->metrics = circuit->metrics[level - 1];
1053 ipreach->prefix = ipv4->prefix;
1054 masklen2ip (ipv4->prefixlen, &ipreach->mask);
1055 listnode_add (lsp->tlv_data.ipv4_int_reachs, ipreach);
1056 }
1057 }
1058 #ifdef HAVE_IPV6
1059 /*
1060 * Add IPv6 reachability of this circuit
1061 */
1062 if (circuit->ipv6_router && circuit->ipv6_non_link &&
1063 circuit->ipv6_non_link->count > 0)
1064 {
1065 if (lsp->tlv_data.ipv6_reachs == NULL)
1066 {
1067 lsp->tlv_data.ipv6_reachs = list_new ();
1068 lsp->tlv_data.ipv6_reachs->del = free_tlv;
1069 }
1070 for (ALL_LIST_ELEMENTS (circuit->ipv6_non_link, ipnode,
1071 ipnnode, ipv6))
1072 {
1073 ip6reach =
1074 XCALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv6_reachability));
1075 ip6reach->metric =
1076 htonl (circuit->metrics[level - 1].metric_default);
1077 ip6reach->control_info = 0;
1078 ip6reach->prefix_len = ipv6->prefixlen;
1079 memcpy (&ip6reach->prefix, ipv6->prefix.s6_addr,
1080 (ipv6->prefixlen + 7) / 8);
1081 listnode_add (lsp->tlv_data.ipv6_reachs, ip6reach);
1082 }
1083 }
1084 #endif /* HAVE_IPV6 */
1085
1086 switch (circuit->circ_type)
1087 {
1088 case CIRCUIT_T_BROADCAST:
1089 if (level & circuit->circuit_is_type)
1090 {
1091 if (lsp->tlv_data.is_neighs == NULL)
1092 {
1093 lsp->tlv_data.is_neighs = list_new ();
1094 lsp->tlv_data.is_neighs->del = free_tlv;
1095 }
1096 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1097 if (level == 1)
1098 memcpy (&is_neigh->neigh_id,
1099 circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
1100 else
1101 memcpy (&is_neigh->neigh_id,
1102 circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
1103 is_neigh->metrics = circuit->metrics[level - 1];
1104 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
1105 }
1106 break;
1107 case CIRCUIT_T_P2P:
1108 nei = circuit->u.p2p.neighbor;
1109 if (nei && (level & nei->circuit_t))
1110 {
1111 if (lsp->tlv_data.is_neighs == NULL)
1112 {
1113 lsp->tlv_data.is_neighs = list_new ();
1114 lsp->tlv_data.is_neighs->del = free_tlv;
1115 }
1116 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1117 memcpy (&is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN);
1118 is_neigh->metrics = circuit->metrics[level - 1];
1119 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
1120 }
1121 break;
1122 case CIRCUIT_T_STATIC_IN:
1123 zlog_warn ("lsp_area_create: unsupported circuit type");
1124 break;
1125 case CIRCUIT_T_STATIC_OUT:
1126 zlog_warn ("lsp_area_create: unsupported circuit type");
1127 break;
1128 case CIRCUIT_T_DA:
1129 zlog_warn ("lsp_area_create: unsupported circuit type");
1130 break;
1131 default:
1132 zlog_warn ("lsp_area_create: unknown circuit type");
1133 }
1134 }
1135
1136 if (lsp->tlv_data.nlpids)
1137 tlv_add_nlpid (lsp->tlv_data.nlpids, lsp->pdu);
1138 if (lsp->tlv_data.hostname)
1139 tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu);
1140 if (lsp->tlv_data.area_addrs && listcount (lsp->tlv_data.area_addrs) > 0)
1141 tlv_add_area_addrs (lsp->tlv_data.area_addrs, lsp->pdu);
1142 if (lsp->tlv_data.is_neighs && listcount (lsp->tlv_data.is_neighs) > 0)
1143 tlv_add_is_neighs (lsp->tlv_data.is_neighs, lsp->pdu);
1144 if (lsp->tlv_data.ipv4_int_reachs &&
1145 listcount (lsp->tlv_data.ipv4_int_reachs) > 0)
1146 tlv_add_ipv4_reachs (lsp->tlv_data.ipv4_int_reachs, lsp->pdu);
1147 #ifdef HAVE_IPV6
1148 if (lsp->tlv_data.ipv6_reachs && listcount (lsp->tlv_data.ipv6_reachs) > 0)
1149 tlv_add_ipv6_reachs (lsp->tlv_data.ipv6_reachs, lsp->pdu);
1150 #endif /* HAVE_IPV6 */
1151
1152 lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
1153
1154 return;
1155 }
1156 #endif
1157
1158 #define FRAG_THOLD(S,T) \
1159 ((STREAM_SIZE(S)*T)/100)
1160
1161 /* stream*, area->lsp_frag_threshold, increment */
1162 #define FRAG_NEEDED(S,T,I) \
1163 (STREAM_SIZE(S)-STREAM_REMAIN(S)+(I) > FRAG_THOLD(S,T))
1164
1165 static void
1166 lsp_tlv_fit (struct isis_lsp *lsp, struct list **from, struct list **to,
1167 int tlvsize, int frag_thold,
1168 int tlv_build_func (struct list *, struct stream *))
1169 {
1170 int count, i;
1171
1172 /* can we fit all ? */
1173 if (!FRAG_NEEDED (lsp->pdu, frag_thold, listcount (*from) * tlvsize + 2))
1174 {
1175 tlv_build_func (*from, lsp->pdu);
1176 *to = *from;
1177 *from = NULL;
1178 }
1179 else if (!FRAG_NEEDED (lsp->pdu, frag_thold, tlvsize + 2))
1180 {
1181 /* fit all we can */
1182 count = FRAG_THOLD (lsp->pdu, frag_thold) - 2 -
1183 (STREAM_SIZE (lsp->pdu) - STREAM_REMAIN (lsp->pdu));
1184 if (count)
1185 count = count / tlvsize;
1186 for (i = 0; i < count; i++)
1187 {
1188 listnode_add (*to, listgetdata (listhead (*from)));
1189 listnode_delete (*from, listgetdata (listhead (*from)));
1190 }
1191 tlv_build_func (*to, lsp->pdu);
1192 }
1193 lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
1194 return;
1195 }
1196
1197 static struct isis_lsp *
1198 lsp_next_frag (u_char frag_num, struct isis_lsp *lsp0, struct isis_area *area,
1199 int level)
1200 {
1201 struct isis_lsp *lsp;
1202 u_char frag_id[ISIS_SYS_ID_LEN + 2];
1203
1204 memcpy (frag_id, lsp0->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 1);
1205 LSP_FRAGMENT (frag_id) = frag_num;
1206 lsp = lsp_search (frag_id, area->lspdb[level - 1]);
1207 if (lsp)
1208 {
1209 /*
1210 * Clear the TLVs, but inherit the authinfo
1211 */
1212 lsp_clear_data (lsp);
1213 if (lsp0->tlv_data.auth_info.type)
1214 {
1215 memcpy (&lsp->tlv_data.auth_info, &lsp->tlv_data.auth_info,
1216 sizeof (struct isis_passwd));
1217 tlv_add_authinfo (lsp->tlv_data.auth_info.type,
1218 lsp->tlv_data.auth_info.len,
1219 lsp->tlv_data.auth_info.passwd, lsp->pdu);
1220 }
1221 return lsp;
1222 }
1223 lsp = lsp_new (frag_id, area->max_lsp_lifetime[level - 1], 0, area->is_type,
1224 0, level);
1225 lsp->own_lsp = 1;
1226 lsp_insert (lsp, area->lspdb[level - 1]);
1227 listnode_add (lsp0->lspu.frags, lsp);
1228 lsp->lspu.zero_lsp = lsp0;
1229 /*
1230 * Copy the authinfo from zero LSP
1231 */
1232 if (lsp0->tlv_data.auth_info.type)
1233 {
1234 memcpy (&lsp->tlv_data.auth_info, &lsp->tlv_data.auth_info,
1235 sizeof (struct isis_passwd));
1236 tlv_add_authinfo (lsp->tlv_data.auth_info.type,
1237 lsp->tlv_data.auth_info.len,
1238 lsp->tlv_data.auth_info.passwd, lsp->pdu);
1239 }
1240 return lsp;
1241 }
1242
1243 /*
1244 * Builds the LSP data part. This func creates a new frag whenever
1245 * area->lsp_frag_threshold is exceeded.
1246 */
1247 #if 1
1248 static void
1249 lsp_build_nonpseudo (struct isis_lsp *lsp, struct isis_area *area)
1250 {
1251 struct is_neigh *is_neigh;
1252 struct listnode *node, *nnode, *ipnode, *ipnnode;
1253 int level = lsp->level;
1254 struct isis_circuit *circuit;
1255 struct prefix_ipv4 *ipv4;
1256 struct ipv4_reachability *ipreach;
1257 struct isis_adjacency *nei;
1258 #ifdef HAVE_IPV6
1259 struct prefix_ipv6 *ipv6, *ip6prefix;
1260 struct ipv6_reachability *ip6reach;
1261 #endif /* HAVE_IPV6 */
1262 struct tlvs tlv_data;
1263 struct isis_lsp *lsp0 = lsp;
1264 struct isis_passwd *passwd;
1265 struct in_addr *routerid;
1266
1267 /*
1268 * First add the tlvs related to area
1269 */
1270
1271 /* Area addresses */
1272 if (lsp->tlv_data.area_addrs == NULL)
1273 lsp->tlv_data.area_addrs = list_new ();
1274 list_add_list (lsp->tlv_data.area_addrs, area->area_addrs);
1275 /* Protocols Supported */
1276 if (area->ip_circuits > 0
1277 #ifdef HAVE_IPV6
1278 || area->ipv6_circuits > 0
1279 #endif /* HAVE_IPV6 */
1280 )
1281 {
1282 lsp->tlv_data.nlpids = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct nlpids));
1283 lsp->tlv_data.nlpids->count = 0;
1284 if (area->ip_circuits > 0)
1285 {
1286 lsp->tlv_data.nlpids->count++;
1287 lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP;
1288 }
1289 #ifdef HAVE_IPV6
1290 if (area->ipv6_circuits > 0)
1291 {
1292 lsp->tlv_data.nlpids->count++;
1293 lsp->tlv_data.nlpids->nlpids[lsp->tlv_data.nlpids->count - 1] =
1294 NLPID_IPV6;
1295 }
1296 #endif /* HAVE_IPV6 */
1297 }
1298 /* Dynamic Hostname */
1299 if (area->dynhostname)
1300 {
1301 lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV,
1302 sizeof (struct hostname));
1303
1304 memcpy (lsp->tlv_data.hostname->name, unix_hostname (),
1305 strlen (unix_hostname ()));
1306 lsp->tlv_data.hostname->namelen = strlen (unix_hostname ());
1307 }
1308
1309 /*
1310 * Building the zero lsp
1311 */
1312
1313 /* Reset stream endp. Stream is always there and on every LSP refresh only
1314 * TLV part of it is overwritten. So we must seek past header we will not
1315 * touch. */
1316 stream_reset (lsp->pdu);
1317 stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
1318
1319 /*
1320 * Add the authentication info if its present
1321 */
1322 (level == 1) ? (passwd = &area->area_passwd) :
1323 (passwd = &area->domain_passwd);
1324 if (passwd->type)
1325 {
1326 memcpy (&lsp->tlv_data.auth_info, passwd, sizeof (struct isis_passwd));
1327 tlv_add_authinfo (passwd->type, passwd->len, passwd->passwd, lsp->pdu);
1328 }
1329 if (lsp->tlv_data.nlpids)
1330 tlv_add_nlpid (lsp->tlv_data.nlpids, lsp->pdu);
1331 if (lsp->tlv_data.hostname)
1332 tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu);
1333 if (lsp->tlv_data.area_addrs && listcount (lsp->tlv_data.area_addrs) > 0)
1334 tlv_add_area_addrs (lsp->tlv_data.area_addrs, lsp->pdu);
1335
1336 memset (&tlv_data, 0, sizeof (struct tlvs));
1337 /*
1338 * IPv4 address TLV. We don't follow "C" vendor, but "J" vendor behavior -
1339 * one IPv4 address is put into LSP and this address is same as router id.
1340 */
1341 if (router_id_zebra.s_addr != 0)
1342 {
1343 if (lsp->tlv_data.ipv4_addrs == NULL)
1344 {
1345 lsp->tlv_data.ipv4_addrs = list_new ();
1346 lsp->tlv_data.ipv4_addrs->del = free_tlv;
1347 }
1348
1349 routerid = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct in_addr));
1350 routerid->s_addr = router_id_zebra.s_addr;
1351
1352 listnode_add (lsp->tlv_data.ipv4_addrs, routerid);
1353
1354 /*
1355 * FIXME: Using add_tlv() directly is hack, but tlv_add_ip_addrs()
1356 * expects list of prefix_ipv4 structures, but we have list of
1357 * in_addr structures.
1358 */
1359 add_tlv (IPV4_ADDR, IPV4_MAX_BYTELEN, (u_char *) &routerid->s_addr,
1360 lsp->pdu);
1361 }
1362
1363 #ifdef TOPOLOGY_GENERATE
1364 /* If topology exists (and we create topology for level 1 only), create
1365 * (hardcoded) link to topology. */
1366 if (area->topology && level == 1)
1367 {
1368 if (tlv_data.is_neighs == NULL)
1369 tlv_data.is_neighs = list_new ();
1370 is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1371 memset (is_neigh, 0, sizeof (struct is_neigh));
1372
1373 memcpy (&is_neigh->neigh_id, area->topology_baseis, ISIS_SYS_ID_LEN);
1374 is_neigh->neigh_id[ISIS_SYS_ID_LEN - 1] = (1 & 0xFF);
1375 is_neigh->neigh_id[ISIS_SYS_ID_LEN - 2] = ((1 >> 8) & 0xFF);
1376 is_neigh->metrics.metric_default = 0x01;
1377 is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
1378 is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
1379 is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
1380 listnode_add (tlv_data.is_neighs, is_neigh);
1381 }
1382 #endif /* TOPOLOGY_GENERATE */
1383
1384 /*
1385 * Then build lists of tlvs related to circuits
1386 */
1387 for (ALL_LIST_ELEMENTS (area->circuit_list, node, nnode, circuit))
1388 {
1389 if (circuit->state != C_STATE_UP)
1390 continue;
1391
1392 /*
1393 * Add IPv4 internal reachability of this circuit
1394 */
1395 if (circuit->ip_router && circuit->ip_addrs &&
1396 circuit->ip_addrs->count > 0)
1397 {
1398 if (tlv_data.ipv4_int_reachs == NULL)
1399 {
1400 tlv_data.ipv4_int_reachs = list_new ();
1401 tlv_data.ipv4_int_reachs->del = free_tlv;
1402 }
1403 for (ALL_LIST_ELEMENTS (circuit->ip_addrs, ipnode, ipnnode, ipv4))
1404 {
1405 ipreach =
1406 XCALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv4_reachability));
1407 ipreach->metrics = circuit->metrics[level - 1];
1408 masklen2ip (ipv4->prefixlen, &ipreach->mask);
1409 ipreach->prefix.s_addr = ((ipreach->mask.s_addr) &
1410 (ipv4->prefix.s_addr));
1411 listnode_add (tlv_data.ipv4_int_reachs, ipreach);
1412 }
1413
1414 }
1415 #ifdef HAVE_IPV6
1416 /*
1417 * Add IPv6 reachability of this circuit
1418 */
1419 if (circuit->ipv6_router && circuit->ipv6_non_link &&
1420 circuit->ipv6_non_link->count > 0)
1421 {
1422
1423 if (tlv_data.ipv6_reachs == NULL)
1424 {
1425 tlv_data.ipv6_reachs = list_new ();
1426 tlv_data.ipv6_reachs->del = free_tlv;
1427 }
1428 for (ALL_LIST_ELEMENTS (circuit->ipv6_non_link, ipnode, ipnnode,
1429 ipv6))
1430 {
1431 ip6reach =
1432 XCALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv6_reachability));
1433 ip6reach->metric =
1434 htonl (circuit->metrics[level - 1].metric_default);
1435 ip6reach->control_info = 0;
1436 ip6reach->prefix_len = ipv6->prefixlen;
1437 memcpy (&ip6prefix, &ipv6, sizeof(ip6prefix));
1438 apply_mask_ipv6 (ip6prefix);
1439 memcpy (ip6reach->prefix, ip6prefix->prefix.s6_addr,
1440 sizeof (ip6reach->prefix));
1441 listnode_add (tlv_data.ipv6_reachs, ip6reach);
1442 }
1443 }
1444 #endif /* HAVE_IPV6 */
1445
1446 switch (circuit->circ_type)
1447 {
1448 case CIRCUIT_T_BROADCAST:
1449 if (level & circuit->circuit_is_type)
1450 {
1451 if (tlv_data.is_neighs == NULL)
1452 {
1453 tlv_data.is_neighs = list_new ();
1454 tlv_data.is_neighs->del = free_tlv;
1455 }
1456 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1457 if (level == 1)
1458 memcpy (is_neigh->neigh_id,
1459 circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
1460 else
1461 memcpy (is_neigh->neigh_id,
1462 circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
1463 is_neigh->metrics = circuit->metrics[level - 1];
1464 listnode_add (tlv_data.is_neighs, is_neigh);
1465 }
1466 break;
1467 case CIRCUIT_T_P2P:
1468 nei = circuit->u.p2p.neighbor;
1469 if (nei && (level & nei->circuit_t))
1470 {
1471 if (tlv_data.is_neighs == NULL)
1472 {
1473 tlv_data.is_neighs = list_new ();
1474 tlv_data.is_neighs->del = free_tlv;
1475 }
1476 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1477 memcpy (is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN);
1478 is_neigh->metrics = circuit->metrics[level - 1];
1479 listnode_add (tlv_data.is_neighs, is_neigh);
1480 }
1481 break;
1482 case CIRCUIT_T_STATIC_IN:
1483 zlog_warn ("lsp_area_create: unsupported circuit type");
1484 break;
1485 case CIRCUIT_T_STATIC_OUT:
1486 zlog_warn ("lsp_area_create: unsupported circuit type");
1487 break;
1488 case CIRCUIT_T_DA:
1489 zlog_warn ("lsp_area_create: unsupported circuit type");
1490 break;
1491 default:
1492 zlog_warn ("lsp_area_create: unknown circuit type");
1493 }
1494 }
1495
1496 while (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs))
1497 {
1498 if (lsp->tlv_data.ipv4_int_reachs == NULL)
1499 lsp->tlv_data.ipv4_int_reachs = list_new ();
1500 lsp_tlv_fit (lsp, &tlv_data.ipv4_int_reachs,
1501 &lsp->tlv_data.ipv4_int_reachs,
1502 IPV4_REACH_LEN, area->lsp_frag_threshold,
1503 tlv_add_ipv4_reachs);
1504 if (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs))
1505 lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
1506 lsp0, area, level);
1507 }
1508
1509 #ifdef HAVE_IPV6
1510 while (tlv_data.ipv6_reachs && listcount (tlv_data.ipv6_reachs))
1511 {
1512 if (lsp->tlv_data.ipv6_reachs == NULL)
1513 lsp->tlv_data.ipv6_reachs = list_new ();
1514 lsp_tlv_fit (lsp, &tlv_data.ipv6_reachs,
1515 &lsp->tlv_data.ipv6_reachs,
1516 IPV6_REACH_LEN, area->lsp_frag_threshold,
1517 tlv_add_ipv6_reachs);
1518 if (tlv_data.ipv6_reachs && listcount (tlv_data.ipv6_reachs))
1519 lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
1520 lsp0, area, level);
1521 }
1522 #endif /* HAVE_IPV6 */
1523
1524 while (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
1525 {
1526 if (lsp->tlv_data.is_neighs == NULL)
1527 lsp->tlv_data.is_neighs = list_new ();
1528 lsp_tlv_fit (lsp, &tlv_data.is_neighs,
1529 &lsp->tlv_data.is_neighs,
1530 IS_NEIGHBOURS_LEN, area->lsp_frag_threshold,
1531 tlv_add_is_neighs);
1532 if (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
1533 lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
1534 lsp0, area, level);
1535 }
1536
1537 return;
1538 }
1539 #endif
1540
1541 #if 0 /* Old code? */
1542 static void
1543 build_lsp_data (struct isis_lsp *lsp, struct isis_area *area)
1544 {
1545 struct list *circuit_list = area->circuit_list;
1546 struct isis_circuit *circuit;
1547 u_char *tlv_ptr;
1548 struct is_neigh *is_neigh;
1549
1550
1551 /* add our nlpids */
1552 /* the 2 is for the TL plus 1 for the nlpid */
1553 tlv_ptr = lsppdu_realloc (lsp, MTYPE_ISIS_TLV, 3);
1554 *tlv_ptr = PROTOCOLS_SUPPORTED; /* Type */
1555 *(tlv_ptr + 1) = 1; /* one protocol */
1556 #ifdef HAVE_IPV6 /*dunno if its right */
1557 *(tlv_ptr + 2) = NLPID_IPV6;
1558 #else
1559 *(tlv_ptr + 2) = NLPID_IP;
1560 #endif /* HAVE_IPV6 */
1561
1562 /* we should add our areas here
1563 * FIXME: we need to figure out which should be added? Adj? All? First? */
1564
1565 /* first, lets add ourselves to the IS neighbours info */
1566 /* the 2 is for the TL plus 1 for the virtual field */
1567 tlv_ptr = lsppdu_realloc (lsp, MTYPE_ISIS_TLV, 3);
1568 *tlv_ptr = IS_NEIGHBOURS; /* Type */
1569 *(tlv_ptr + 2) = 0; /* virtual is zero */
1570 lsp->tlv_data.is_neighs = list_new (); /* new list of is_neighbours */
1571 /* assign space for the is_neigh at the pdu end */
1572 is_neigh = (struct is_neigh *) lsppdu_realloc (lsp, MTYPE_ISIS_TLV,
1573 sizeof (struct is_neigh));
1574 /* add this node to our list */
1575 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
1576 /* FIXME: Do we need our designated address here? */
1577 memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN + 1);
1578 /* FIXME: Where should we really get our own LSPs metrics from? */
1579 circuit = (struct isis_circuit *) listhead (circuit_list);
1580 /* is_neigh->metrics = circuit->metrics[lsp->level -1]; */
1581 /* Length */
1582 *(tlv_ptr + 1) =
1583 (lsp->tlv_data.is_neighs->count * sizeof (struct is_neigh) + 1);
1584
1585 /* FIXME: scan for adjencecies and add them */
1586
1587 /* FIXME: add reachability info */
1588
1589 /* adding dynamic hostname if needed */
1590 if (area->dynhostname)
1591 {
1592 tlv_ptr = lsppdu_realloc (lsp, MTYPE_ISIS_TLV, 2); /* the 2 is for the TL */
1593 *tlv_ptr = DYNAMIC_HOSTNAME; /* Type */
1594 *(tlv_ptr + 1) = strlen (unix_hostname ()); /* Length */
1595 lsp->tlv_data.hostname = (struct hostname *)
1596 (lsppdu_realloc (lsp, MTYPE_ISIS_TLV,
1597 /* the -1 is to fit the length in the struct */
1598 strlen (unix_hostname ())) - 1);
1599 memcpy (lsp->tlv_data.hostname->name, unix_hostname (),
1600 strlen (unix_hostname ()));
1601 }
1602
1603 }
1604 #endif /* 0 */
1605
1606 /*
1607 * 7.3.7 Generation on non-pseudonode LSPs
1608 */
1609 static int
1610 lsp_generate_non_pseudo (struct isis_area *area, int level)
1611 {
1612 struct isis_lsp *oldlsp, *newlsp;
1613 u_int32_t seq_num = 0;
1614 u_char lspid[ISIS_SYS_ID_LEN + 2];
1615
1616 memset (&lspid, 0, ISIS_SYS_ID_LEN + 2);
1617 memcpy (&lspid, isis->sysid, ISIS_SYS_ID_LEN);
1618
1619 /* only builds the lsp if the area shares the level */
1620 if ((area->is_type & level) == level)
1621 {
1622 oldlsp = lsp_search (lspid, area->lspdb[level - 1]);
1623 if (oldlsp)
1624 {
1625 seq_num = ntohl (oldlsp->lsp_header->seq_num);
1626 lsp_search_and_destroy (oldlsp->lsp_header->lsp_id,
1627 area->lspdb[level - 1]);
1628 /* FIXME: we should actually initiate a purge */
1629 }
1630 newlsp = lsp_new (lspid, area->max_lsp_lifetime[level - 1], seq_num,
1631 area->is_type, 0, level);
1632 newlsp->own_lsp = 1;
1633
1634 lsp_insert (newlsp, area->lspdb[level - 1]);
1635 /* build_lsp_data (newlsp, area); */
1636 lsp_build_nonpseudo (newlsp, area);
1637 /* time to calculate our checksum */
1638 lsp_seqnum_update (newlsp);
1639 }
1640
1641 /* DEBUG_ADJ_PACKETS */
1642 if (isis->debugs & DEBUG_ADJ_PACKETS)
1643 {
1644 /* FIXME: is this place right? fix missing info */
1645 zlog_debug ("ISIS-Upd (%s): Building L%d LSP", area->area_tag, level);
1646 }
1647
1648 return ISIS_OK;
1649 }
1650
1651 /*
1652 * 7.3.9 Generation of level 1 LSPs (non-pseudonode)
1653 */
1654 int
1655 lsp_l1_generate (struct isis_area *area)
1656 {
1657 THREAD_TIMER_ON (master, area->t_lsp_refresh[0], lsp_refresh_l1, area,
1658 MAX_LSP_GEN_INTERVAL);
1659
1660 return lsp_generate_non_pseudo (area, 1);
1661 }
1662
1663 /*
1664 * 7.3.9 Generation of level 2 LSPs (non-pseudonode)
1665 */
1666 int
1667 lsp_l2_generate (struct isis_area *area)
1668 {
1669 THREAD_TIMER_ON (master, area->t_lsp_refresh[1], lsp_refresh_l2, area,
1670 MAX_LSP_GEN_INTERVAL);
1671
1672 return lsp_generate_non_pseudo (area, 2);
1673 }
1674
1675 static int
1676 lsp_non_pseudo_regenerate (struct isis_area *area, int level)
1677 {
1678 dict_t *lspdb = area->lspdb[level - 1];
1679 struct isis_lsp *lsp, *frag;
1680 struct listnode *node;
1681 u_char lspid[ISIS_SYS_ID_LEN + 2];
1682
1683 memset (lspid, 0, ISIS_SYS_ID_LEN + 2);
1684 memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN);
1685
1686 lsp = lsp_search (lspid, lspdb);
1687
1688 if (!lsp)
1689 {
1690 zlog_err
1691 ("ISIS-Upd (%s): lsp_non_pseudo_regenerate(): no L%d LSP found!",
1692 area->area_tag, level);
1693
1694 return ISIS_ERROR;
1695 }
1696
1697 lsp_clear_data (lsp);
1698 lsp_build_nonpseudo (lsp, area);
1699 lsp->lsp_header->rem_lifetime = htons (isis_jitter
1700 (area->max_lsp_lifetime[level - 1],
1701 MAX_AGE_JITTER));
1702 lsp_seqnum_update (lsp);
1703
1704 if (isis->debugs & DEBUG_UPDATE_PACKETS)
1705 {
1706 zlog_debug ("ISIS-Upd (%s): refreshing our L%d LSP %s, "
1707 "seq 0x%08x, cksum 0x%04x lifetime %us",
1708 area->area_tag,
1709 level,
1710 rawlspid_print (lsp->lsp_header->lsp_id),
1711 ntohl (lsp->lsp_header->seq_num),
1712 ntohs (lsp->lsp_header->checksum),
1713 ntohs (lsp->lsp_header->rem_lifetime));
1714 }
1715
1716 lsp->last_generated = time (NULL);
1717 area->lsp_regenerate_pending[level - 1] = 0;
1718 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
1719 for (ALL_LIST_ELEMENTS_RO (lsp->lspu.frags, node, frag))
1720 {
1721 frag->lsp_header->rem_lifetime = htons (isis_jitter
1722 (area->
1723 max_lsp_lifetime[level - 1],
1724 MAX_AGE_JITTER));
1725 ISIS_FLAGS_SET_ALL (frag->SRMflags);
1726 }
1727
1728 if (area->ip_circuits)
1729 isis_spf_schedule (area, level);
1730 #ifdef HAVE_IPV6
1731 if (area->ipv6_circuits)
1732 isis_spf_schedule6 (area, level);
1733 #endif
1734 return ISIS_OK;
1735 }
1736
1737 /*
1738 * Done at least every MAX_LSP_GEN_INTERVAL. Search own LSPs, update holding
1739 * time and set SRM
1740 */
1741 int
1742 lsp_refresh_l1 (struct thread *thread)
1743 {
1744 struct isis_area *area;
1745 unsigned long ref_time;
1746
1747 area = THREAD_ARG (thread);
1748 assert (area);
1749
1750 area->t_lsp_refresh[0] = NULL;
1751 if (area->is_type & IS_LEVEL_1)
1752 lsp_non_pseudo_regenerate (area, 1);
1753
1754 ref_time = area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
1755 MAX_LSP_GEN_INTERVAL : area->lsp_refresh[0];
1756
1757 THREAD_TIMER_ON (master, area->t_lsp_refresh[0], lsp_refresh_l1, area,
1758 isis_jitter (ref_time, MAX_AGE_JITTER));
1759
1760 return ISIS_OK;
1761 }
1762
1763 int
1764 lsp_refresh_l2 (struct thread *thread)
1765 {
1766 struct isis_area *area;
1767 unsigned long ref_time;
1768
1769 area = THREAD_ARG (thread);
1770 assert (area);
1771
1772 area->t_lsp_refresh[1] = NULL;
1773 if (area->is_type & IS_LEVEL_2)
1774 lsp_non_pseudo_regenerate (area, 2);
1775
1776 ref_time = area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ?
1777 MAX_LSP_GEN_INTERVAL : area->lsp_refresh[1];
1778
1779 THREAD_TIMER_ON (master, area->t_lsp_refresh[1], lsp_refresh_l2, area,
1780 isis_jitter (ref_time, MAX_AGE_JITTER));
1781
1782 return ISIS_OK;
1783 }
1784
1785 /*
1786 * Something has changed -> regenerate LSP
1787 */
1788
1789 static int
1790 lsp_l1_regenerate (struct thread *thread)
1791 {
1792 struct isis_area *area;
1793
1794 area = THREAD_ARG (thread);
1795 area->lsp_regenerate_pending[0] = 0;
1796
1797 return lsp_non_pseudo_regenerate (area, 1);
1798 }
1799
1800 static int
1801 lsp_l2_regenerate (struct thread *thread)
1802 {
1803 struct isis_area *area;
1804
1805 area = THREAD_ARG (thread);
1806 area->lsp_regenerate_pending[1] = 0;
1807
1808 return lsp_non_pseudo_regenerate (area, 2);
1809 }
1810
1811 int
1812 lsp_regenerate_schedule (struct isis_area *area)
1813 {
1814 struct isis_lsp *lsp;
1815 u_char id[ISIS_SYS_ID_LEN + 2];
1816 time_t now, diff;
1817 memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
1818 LSP_PSEUDO_ID (id) = LSP_FRAGMENT (id) = 0;
1819 now = time (NULL);
1820 /*
1821 * First level 1
1822 */
1823 if (area->is_type & IS_LEVEL_1)
1824 {
1825 lsp = lsp_search (id, area->lspdb[0]);
1826 if (!lsp || area->lsp_regenerate_pending[0])
1827 goto L2;
1828 /*
1829 * Throttle avoidance
1830 */
1831 diff = now - lsp->last_generated;
1832 if (diff < MIN_LSP_GEN_INTERVAL)
1833 {
1834 area->lsp_regenerate_pending[0] = 1;
1835 thread_add_timer (master, lsp_l1_regenerate, area,
1836 MIN_LSP_GEN_INTERVAL - diff);
1837 goto L2;
1838 }
1839 else
1840 lsp_non_pseudo_regenerate (area, 1);
1841 }
1842 /*
1843 * then 2
1844 */
1845 L2:
1846 if (area->is_type & IS_LEVEL_2)
1847 {
1848 lsp = lsp_search (id, area->lspdb[1]);
1849 if (!lsp || area->lsp_regenerate_pending[1])
1850 return ISIS_OK;
1851 /*
1852 * Throttle avoidance
1853 */
1854 diff = now - lsp->last_generated;
1855 if (diff < MIN_LSP_GEN_INTERVAL)
1856 {
1857 area->lsp_regenerate_pending[1] = 1;
1858 thread_add_timer (master, lsp_l2_regenerate, area,
1859 MIN_LSP_GEN_INTERVAL - diff);
1860 return ISIS_OK;
1861 }
1862 else
1863 lsp_non_pseudo_regenerate (area, 2);
1864 }
1865
1866 return ISIS_OK;
1867 }
1868
1869 /*
1870 * Funcs for pseudonode LSPs
1871 */
1872
1873 /*
1874 * 7.3.8 and 7.3.10 Generation of level 1 and 2 pseudonode LSPs
1875 */
1876 static void
1877 lsp_build_pseudo (struct isis_lsp *lsp, struct isis_circuit *circuit,
1878 int level)
1879 {
1880 struct isis_adjacency *adj;
1881 struct is_neigh *is_neigh;
1882 struct es_neigh *es_neigh;
1883 struct list *adj_list;
1884 struct listnode *node, *nnode;
1885 struct isis_passwd *passwd;
1886
1887 assert (circuit);
1888 assert (circuit->circ_type == CIRCUIT_T_BROADCAST);
1889
1890 if (!circuit->u.bc.is_dr[level - 1])
1891 return; /* we are not DIS on this circuit */
1892
1893 lsp->level = level;
1894 if (level == 1)
1895 lsp->lsp_header->lsp_bits |= IS_LEVEL_1;
1896 else
1897 lsp->lsp_header->lsp_bits |= IS_LEVEL_2;
1898
1899 /*
1900 * add self to IS neighbours
1901 */
1902 if (lsp->tlv_data.is_neighs == NULL)
1903 {
1904 lsp->tlv_data.is_neighs = list_new ();
1905 lsp->tlv_data.is_neighs->del = free_tlv;
1906 }
1907 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1908
1909 memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
1910 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
1911
1912 adj_list = list_new ();
1913 isis_adj_build_up_list (circuit->u.bc.adjdb[level - 1], adj_list);
1914
1915 for (ALL_LIST_ELEMENTS (adj_list, node, nnode, adj))
1916 {
1917 if (adj->circuit_t & level)
1918 {
1919 if ((level == 1 && adj->sys_type == ISIS_SYSTYPE_L1_IS) ||
1920 (level == 1 && adj->sys_type == ISIS_SYSTYPE_L2_IS &&
1921 adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
1922 (level == 2 && adj->sys_type == ISIS_SYSTYPE_L2_IS))
1923 {
1924 /* an IS neighbour -> add it */
1925 is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
1926
1927 memcpy (&is_neigh->neigh_id, adj->sysid, ISIS_SYS_ID_LEN);
1928 listnode_add (lsp->tlv_data.is_neighs, is_neigh);
1929 }
1930 else if (level == 1 && adj->sys_type == ISIS_SYSTYPE_ES)
1931 {
1932 /* an ES neigbour add it, if we are building level 1 LSP */
1933 /* FIXME: the tlv-format is hard to use here */
1934 if (lsp->tlv_data.es_neighs == NULL)
1935 {
1936 lsp->tlv_data.es_neighs = list_new ();
1937 lsp->tlv_data.es_neighs->del = free_tlv;
1938 }
1939 es_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct es_neigh));
1940
1941 memcpy (&es_neigh->first_es_neigh, adj->sysid, ISIS_SYS_ID_LEN);
1942 listnode_add (lsp->tlv_data.es_neighs, es_neigh);
1943 }
1944 }
1945 }
1946
1947 /* Reset endp of stream to overwrite only TLV part of it. */
1948 stream_reset (lsp->pdu);
1949 stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
1950
1951 /*
1952 * Add the authentication info if it's present
1953 */
1954 (level == 1) ? (passwd = &circuit->area->area_passwd) :
1955 (passwd = &circuit->area->domain_passwd);
1956 if (passwd->type)
1957 {
1958 memcpy (&lsp->tlv_data.auth_info, passwd, sizeof (struct isis_passwd));
1959 tlv_add_authinfo (passwd->type, passwd->len, passwd->passwd, lsp->pdu);
1960 }
1961
1962 if (lsp->tlv_data.is_neighs && listcount (lsp->tlv_data.is_neighs) > 0)
1963 tlv_add_is_neighs (lsp->tlv_data.is_neighs, lsp->pdu);
1964
1965 if (lsp->tlv_data.es_neighs && listcount (lsp->tlv_data.es_neighs) > 0)
1966 tlv_add_is_neighs (lsp->tlv_data.es_neighs, lsp->pdu);
1967
1968 lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
1969 iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
1970 ntohs (lsp->lsp_header->pdu_len) - 12, 12);
1971
1972 list_delete (adj_list);
1973
1974 return;
1975 }
1976
1977 static int
1978 lsp_pseudo_regenerate (struct isis_circuit *circuit, int level)
1979 {
1980 dict_t *lspdb = circuit->area->lspdb[level - 1];
1981 struct isis_lsp *lsp;
1982 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
1983
1984 memcpy (lsp_id, isis->sysid, ISIS_SYS_ID_LEN);
1985 LSP_PSEUDO_ID (lsp_id) = circuit->circuit_id;
1986 LSP_FRAGMENT (lsp_id) = 0;
1987
1988 lsp = lsp_search (lsp_id, lspdb);
1989
1990 if (!lsp)
1991 {
1992 zlog_err ("lsp_pseudo_regenerate(): no l%d LSP %s found!", level,
1993 rawlspid_print (lsp_id));
1994 return ISIS_ERROR;
1995 }
1996 lsp_clear_data (lsp);
1997
1998 lsp_build_pseudo (lsp, circuit, level);
1999
2000 lsp->lsp_header->rem_lifetime =
2001 htons (isis_jitter (circuit->area->max_lsp_lifetime[level - 1],
2002 MAX_AGE_JITTER));
2003
2004 lsp_inc_seqnum (lsp, 0);
2005
2006 if (isis->debugs & DEBUG_UPDATE_PACKETS)
2007 {
2008 zlog_debug ("ISIS-Upd (%s): refreshing pseudo LSP L%d %s",
2009 circuit->area->area_tag, level,
2010 rawlspid_print (lsp->lsp_header->lsp_id));
2011 }
2012
2013 lsp->last_generated = time (NULL);
2014 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
2015
2016 return ISIS_OK;
2017 }
2018
2019 int
2020 lsp_l1_refresh_pseudo (struct thread *thread)
2021 {
2022 struct isis_circuit *circuit;
2023 int retval;
2024 unsigned long ref_time;
2025
2026 circuit = THREAD_ARG (thread);
2027
2028 if (!circuit->u.bc.is_dr[0])
2029 return ISIS_ERROR; /* FIXME: purge and such */
2030
2031 circuit->u.bc.t_refresh_pseudo_lsp[0] = NULL;
2032
2033 retval = lsp_pseudo_regenerate (circuit, 1);
2034
2035 ref_time = circuit->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
2036 MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[0];
2037
2038 THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[0],
2039 lsp_l1_refresh_pseudo, circuit,
2040 isis_jitter (ref_time, MAX_AGE_JITTER));
2041
2042 return retval;
2043 }
2044
2045 int
2046 lsp_l1_pseudo_generate (struct isis_circuit *circuit)
2047 {
2048 struct isis_lsp *lsp;
2049 u_char id[ISIS_SYS_ID_LEN + 2];
2050 unsigned long ref_time;
2051
2052 memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
2053 LSP_FRAGMENT (id) = 0;
2054 LSP_PSEUDO_ID (id) = circuit->circuit_id;
2055
2056 /*
2057 * If for some reason have a pseudo LSP in the db already -> regenerate
2058 */
2059 if (lsp_search (id, circuit->area->lspdb[0]))
2060 return lsp_pseudo_regenerate (circuit, 1);
2061 lsp = lsp_new (id, circuit->area->max_lsp_lifetime[0],
2062 1, circuit->area->is_type, 0, 1);
2063
2064 lsp_build_pseudo (lsp, circuit, 1);
2065
2066 lsp->own_lsp = 1;
2067 lsp_insert (lsp, circuit->area->lspdb[0]);
2068 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
2069
2070 ref_time = circuit->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
2071 MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[0];
2072
2073 THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[0],
2074 lsp_l1_refresh_pseudo, circuit,
2075 isis_jitter (ref_time, MAX_AGE_JITTER));
2076
2077 return lsp_regenerate_schedule (circuit->area);
2078 }
2079
2080 int
2081 lsp_l2_refresh_pseudo (struct thread *thread)
2082 {
2083 struct isis_circuit *circuit;
2084 int retval;
2085 unsigned long ref_time;
2086 circuit = THREAD_ARG (thread);
2087
2088 if (!circuit->u.bc.is_dr[1])
2089 return ISIS_ERROR; /* FIXME: purge and such */
2090
2091 circuit->u.bc.t_refresh_pseudo_lsp[1] = NULL;
2092
2093 retval = lsp_pseudo_regenerate (circuit, 2);
2094
2095 ref_time = circuit->area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ?
2096 MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[1];
2097
2098 THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[1],
2099 lsp_l2_refresh_pseudo, circuit,
2100 isis_jitter (ref_time, MAX_AGE_JITTER));
2101
2102 return retval;
2103 }
2104
2105 int
2106 lsp_l2_pseudo_generate (struct isis_circuit *circuit)
2107 {
2108 struct isis_lsp *lsp;
2109 u_char id[ISIS_SYS_ID_LEN + 2];
2110 unsigned long ref_time;
2111
2112 memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
2113 LSP_FRAGMENT (id) = 0;
2114 LSP_PSEUDO_ID (id) = circuit->circuit_id;
2115
2116 if (lsp_search (id, circuit->area->lspdb[1]))
2117 return lsp_pseudo_regenerate (circuit, 2);
2118
2119 lsp = lsp_new (id, circuit->area->max_lsp_lifetime[1],
2120 1, circuit->area->is_type, 0, 2);
2121
2122 lsp_build_pseudo (lsp, circuit, 2);
2123
2124 ref_time = circuit->area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ?
2125 MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[1];
2126
2127
2128 lsp->own_lsp = 1;
2129 lsp_insert (lsp, circuit->area->lspdb[1]);
2130 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
2131
2132 THREAD_TIMER_ON (master, circuit->u.bc.t_refresh_pseudo_lsp[1],
2133 lsp_l2_refresh_pseudo, circuit,
2134 isis_jitter (ref_time, MAX_AGE_JITTER));
2135
2136 return lsp_regenerate_schedule (circuit->area);
2137 }
2138
2139 /*
2140 * Walk through LSPs for an area
2141 * - set remaining lifetime
2142 * - set LSPs with SRMflag set for sending
2143 */
2144 int
2145 lsp_tick (struct thread *thread)
2146 {
2147 struct isis_area *area;
2148 struct isis_circuit *circuit;
2149 struct isis_lsp *lsp;
2150 struct list *lsp_list;
2151 struct listnode *lspnode, *lspnnode, *cnode;
2152 dnode_t *dnode, *dnode_next;
2153 int level;
2154
2155 lsp_list = list_new ();
2156
2157 area = THREAD_ARG (thread);
2158 assert (area);
2159 area->t_tick = NULL;
2160 THREAD_TIMER_ON (master, area->t_tick, lsp_tick, area, 1);
2161
2162 /*
2163 * Build a list of LSPs with (any) SRMflag set
2164 * and removed the ones that have aged out
2165 */
2166 for (level = 0; level < ISIS_LEVELS; level++)
2167 {
2168 if (area->lspdb[level] && dict_count (area->lspdb[level]) > 0)
2169 {
2170 dnode = dict_first (area->lspdb[level]);
2171 while (dnode != NULL)
2172 {
2173 dnode_next = dict_next (area->lspdb[level], dnode);
2174 lsp = dnode_get (dnode);
2175 lsp_set_time (lsp);
2176 if (lsp->age_out == 0)
2177 {
2178
2179 zlog_debug ("ISIS-Upd (%s): L%u LSP %s seq 0x%08x aged out",
2180 area->area_tag,
2181 lsp->level,
2182 rawlspid_print (lsp->lsp_header->lsp_id),
2183 ntohl (lsp->lsp_header->seq_num));
2184 #ifdef TOPOLOGY_GENERATE
2185 if (lsp->from_topology)
2186 THREAD_TIMER_OFF (lsp->t_lsp_top_ref);
2187 #endif /* TOPOLOGY_GENERATE */
2188 lsp_destroy (lsp);
2189 dict_delete (area->lspdb[level], dnode);
2190 }
2191 else if (flags_any_set (lsp->SRMflags))
2192 listnode_add (lsp_list, lsp);
2193 dnode = dnode_next;
2194 }
2195
2196 /*
2197 * Send LSPs on circuits indicated by the SRMflags
2198 */
2199 if (listcount (lsp_list) > 0)
2200 {
2201 for (ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit))
2202 {
2203 for (ALL_LIST_ELEMENTS (lsp_list, lspnode, lspnnode, lsp))
2204 {
2205 if (ISIS_CHECK_FLAG (lsp->SRMflags, circuit))
2206 {
2207 /* FIXME: if same or elder lsp is already in lsp
2208 * queue */
2209 listnode_add (circuit->lsp_queue, lsp);
2210 thread_add_event (master, send_lsp, circuit, 0);
2211 }
2212 }
2213 }
2214 }
2215 list_delete_all_node (lsp_list);
2216 }
2217 }
2218
2219 list_delete (lsp_list);
2220
2221 return ISIS_OK;
2222 }
2223
2224 void
2225 lsp_purge_dr (u_char * id, struct isis_circuit *circuit, int level)
2226 {
2227 struct isis_lsp *lsp;
2228
2229 lsp = lsp_search (id, circuit->area->lspdb[level - 1]);
2230
2231 if (lsp && lsp->purged == 0)
2232 {
2233 lsp->lsp_header->rem_lifetime = htons (0);
2234 lsp->lsp_header->pdu_len =
2235 htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
2236 lsp->purged = 0;
2237 iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
2238 ntohs (lsp->lsp_header->pdu_len) - 12, 12);
2239 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
2240 }
2241
2242 return;
2243 }
2244
2245 /*
2246 * Purge own LSP that is received and we don't have.
2247 * -> Do as in 7.3.16.4
2248 */
2249 void
2250 lsp_purge_non_exist (struct isis_link_state_hdr *lsp_hdr,
2251 struct isis_area *area)
2252 {
2253 struct isis_lsp *lsp;
2254
2255 /*
2256 * We need to create the LSP to be purged
2257 */
2258 zlog_debug ("LSP PURGE NON EXIST");
2259 lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
2260 /*FIXME: BUG BUG BUG! the lsp doesn't exist here! */
2261 /*did smt here, maybe good probably not */
2262 lsp->level = ((lsp_hdr->lsp_bits & LSPBIT_IST) == IS_LEVEL_1) ? 1 : 2;
2263 lsp->pdu = stream_new (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
2264 lsp->isis_header = (struct isis_fixed_hdr *) STREAM_DATA (lsp->pdu);
2265 fill_fixed_hdr (lsp->isis_header, (lsp->level == 1) ? L1_LINK_STATE
2266 : L2_LINK_STATE);
2267 lsp->lsp_header = (struct isis_link_state_hdr *) (STREAM_DATA (lsp->pdu) +
2268 ISIS_FIXED_HDR_LEN);
2269 memcpy (lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN);
2270
2271 /*
2272 * Retain only LSP header
2273 */
2274 lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
2275 /*
2276 * Set the remaining lifetime to 0
2277 */
2278 lsp->lsp_header->rem_lifetime = 0;
2279 /*
2280 * Put the lsp into LSPdb
2281 */
2282 lsp_insert (lsp, area->lspdb[lsp->level - 1]);
2283
2284 /*
2285 * Send in to whole area
2286 */
2287 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
2288
2289 return;
2290 }
2291
2292 #ifdef TOPOLOGY_GENERATE
2293 static int
2294 top_lsp_refresh (struct thread *thread)
2295 {
2296 struct isis_lsp *lsp;
2297 unsigned long ref_time;
2298
2299 lsp = THREAD_ARG (thread);
2300 assert (lsp);
2301
2302 lsp->t_lsp_top_ref = NULL;
2303
2304 lsp_seqnum_update (lsp);
2305
2306 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
2307 if (isis->debugs & DEBUG_UPDATE_PACKETS)
2308 {
2309 zlog_debug ("ISIS-Upd (): refreshing Topology L1 %s",
2310 rawlspid_print (lsp->lsp_header->lsp_id));
2311 }
2312 lsp->lsp_header->rem_lifetime =
2313 htons (isis_jitter (lsp->area->max_lsp_lifetime[0], MAX_AGE_JITTER));
2314
2315 ref_time = lsp->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
2316 MAX_LSP_GEN_INTERVAL : lsp->area->lsp_refresh[0];
2317
2318 THREAD_TIMER_ON (master, lsp->t_lsp_top_ref, top_lsp_refresh, lsp,
2319 isis_jitter (ref_time, MAX_LSP_GEN_JITTER));
2320
2321 return ISIS_OK;
2322 }
2323
2324 void
2325 generate_topology_lsps (struct isis_area *area)
2326 {
2327 struct listnode *node;
2328 int i, max = 0;
2329 struct arc *arc;
2330 u_char lspid[ISIS_SYS_ID_LEN + 2];
2331 struct isis_lsp *lsp;
2332 unsigned long ref_time;
2333
2334 /* first we find the maximal node */
2335 for (ALL_LIST_ELEMENTS_RO (area->topology, node, arc))
2336 {
2337 if (arc->from_node > max)
2338 max = arc->from_node;
2339 if (arc->to_node > max)
2340 max = arc->to_node;
2341 }
2342
2343 for (i = 1; i < (max + 1); i++)
2344 {
2345 memcpy (lspid, area->topology_baseis, ISIS_SYS_ID_LEN);
2346 LSP_PSEUDO_ID (lspid) = 0x00;
2347 LSP_FRAGMENT (lspid) = 0x00;
2348 lspid[ISIS_SYS_ID_LEN - 1] = (i & 0xFF);
2349 lspid[ISIS_SYS_ID_LEN - 2] = ((i >> 8) & 0xFF);
2350
2351 lsp = lsp_new (lspid, isis_jitter (area->max_lsp_lifetime[0],
2352 MAX_AGE_JITTER), 1, IS_LEVEL_1, 0, 1);
2353 if (!lsp)
2354 return;
2355 lsp->from_topology = 1;
2356 lsp->area = area;
2357
2358 /* Creating LSP data based on topology info. */
2359 build_topology_lsp_data (lsp, area, i);
2360 /* Checksum is also calculated here. */
2361 lsp_seqnum_update (lsp);
2362
2363 ref_time = area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ?
2364 MAX_LSP_GEN_INTERVAL : area->lsp_refresh[0];
2365
2366 THREAD_TIMER_ON (master, lsp->t_lsp_top_ref, top_lsp_refresh, lsp,
2367 isis_jitter (ref_time, MAX_LSP_GEN_JITTER));
2368 ISIS_FLAGS_SET_ALL (lsp->SRMflags);
2369 lsp_insert (lsp, area->lspdb[0]);
2370 }
2371 }
2372
2373 void
2374 remove_topology_lsps (struct isis_area *area)
2375 {
2376 struct isis_lsp *lsp;
2377 dnode_t *dnode, *dnode_next;
2378
2379 dnode = dict_first (area->lspdb[0]);
2380 while (dnode != NULL)
2381 {
2382 dnode_next = dict_next (area->lspdb[0], dnode);
2383 lsp = dnode_get (dnode);
2384 if (lsp->from_topology)
2385 {
2386 THREAD_TIMER_OFF (lsp->t_lsp_top_ref);
2387 lsp_destroy (lsp);
2388 dict_delete (area->lspdb[0], dnode);
2389 }
2390 dnode = dnode_next;
2391 }
2392 }
2393
2394 void
2395 build_topology_lsp_data (struct isis_lsp *lsp, struct isis_area *area,
2396 int lsp_top_num)
2397 {
2398 struct listnode *node, *nnode;
2399 struct arc *arc;
2400 struct is_neigh *is_neigh;
2401 char buff[200];
2402 struct tlvs tlv_data;
2403 struct isis_lsp *lsp0 = lsp;
2404
2405 /* Add area addresses. FIXME: Is it needed at all? */
2406 if (lsp->tlv_data.area_addrs == NULL)
2407 lsp->tlv_data.area_addrs = list_new ();
2408 list_add_list (lsp->tlv_data.area_addrs, area->area_addrs);
2409
2410 if (lsp->tlv_data.nlpids == NULL)
2411 lsp->tlv_data.nlpids = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct nlpids));
2412 lsp->tlv_data.nlpids->count = 1;
2413 lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP;
2414
2415 if (area->dynhostname)
2416 {
2417 lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV,
2418 sizeof (struct hostname));
2419 memset (buff, 0x00, 200);
2420 sprintf (buff, "%s%d", area->topology_basedynh ? area->topology_basedynh :
2421 "feedme", lsp_top_num);
2422 memcpy (lsp->tlv_data.hostname->name, buff, strlen (buff));
2423 lsp->tlv_data.hostname->namelen = strlen (buff);
2424 }
2425
2426 if (lsp->tlv_data.nlpids)
2427 tlv_add_nlpid (lsp->tlv_data.nlpids, lsp->pdu);
2428 if (lsp->tlv_data.hostname)
2429 tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu);
2430 if (lsp->tlv_data.area_addrs && listcount (lsp->tlv_data.area_addrs) > 0)
2431 tlv_add_area_addrs (lsp->tlv_data.area_addrs, lsp->pdu);
2432
2433 memset (&tlv_data, 0, sizeof (struct tlvs));
2434 if (tlv_data.is_neighs == NULL)
2435 tlv_data.is_neighs = list_new ();
2436
2437 /* Add reachability for this IS for simulated 1. */
2438 if (lsp_top_num == 1)
2439 {
2440 is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
2441 memset (is_neigh, 0, sizeof (struct is_neigh));
2442
2443 memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
2444 LSP_PSEUDO_ID (is_neigh->neigh_id) = 0x00;
2445 /* Metric MUST NOT be 0, unless it's not alias TLV. */
2446 is_neigh->metrics.metric_default = 0x01;
2447 is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
2448 is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
2449 is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
2450 listnode_add (tlv_data.is_neighs, is_neigh);
2451 }
2452
2453 /* Add IS reachabilities. */
2454 for (ALL_LIST_ELEMENTS (area->topology, node, nnode, arc))
2455 {
2456 int to_lsp = 0;
2457
2458 if ((lsp_top_num != arc->from_node) && (lsp_top_num != arc->to_node))
2459 continue;
2460
2461 if (lsp_top_num == arc->from_node)
2462 to_lsp = arc->to_node;
2463 else
2464 to_lsp = arc->from_node;
2465
2466 is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
2467 memset (is_neigh, 0, sizeof (struct is_neigh));
2468
2469 memcpy (&is_neigh->neigh_id, area->topology_baseis, ISIS_SYS_ID_LEN);
2470 is_neigh->neigh_id[ISIS_SYS_ID_LEN - 1] = (to_lsp & 0xFF);
2471 is_neigh->neigh_id[ISIS_SYS_ID_LEN - 2] = ((to_lsp >> 8) & 0xFF);
2472 is_neigh->metrics.metric_default = arc->distance;
2473 is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
2474 is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
2475 is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
2476 listnode_add (tlv_data.is_neighs, is_neigh);
2477 }
2478
2479 while (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
2480 {
2481 if (lsp->tlv_data.is_neighs == NULL)
2482 lsp->tlv_data.is_neighs = list_new ();
2483 lsp_tlv_fit (lsp, &tlv_data.is_neighs,
2484 &lsp->tlv_data.is_neighs,
2485 IS_NEIGHBOURS_LEN, area->lsp_frag_threshold,
2486 tlv_add_is_neighs);
2487 if (tlv_data.is_neighs && listcount (tlv_data.is_neighs))
2488 lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
2489 lsp0, area, IS_LEVEL_1);
2490 }
2491
2492 free_tlvs (&tlv_data);
2493 return;
2494 }
2495 #endif /* TOPOLOGY_GENERATE */