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