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