Annotation of embedaddon/quagga/isisd/isis_adjacency.c, revision 1.1
1.1 ! misho 1: /*
! 2: * IS-IS Rout(e)ing protocol - isis_adjacency.c
! 3: * handling of IS-IS adjacencies
! 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 "log.h"
! 27: #include "memory.h"
! 28: #include "hash.h"
! 29: #include "vty.h"
! 30: #include "linklist.h"
! 31: #include "thread.h"
! 32: #include "if.h"
! 33: #include "stream.h"
! 34:
! 35: #include "isisd/dict.h"
! 36: #include "isisd/include-netbsd/iso.h"
! 37: #include "isisd/isis_constants.h"
! 38: #include "isisd/isis_common.h"
! 39: #include "isisd/isisd.h"
! 40: #include "isisd/isis_circuit.h"
! 41: #include "isisd/isis_adjacency.h"
! 42: #include "isisd/isis_misc.h"
! 43: #include "isisd/isis_dr.h"
! 44: #include "isisd/isis_dynhn.h"
! 45: #include "isisd/isis_pdu.h"
! 46:
! 47: extern struct isis *isis;
! 48:
! 49: static struct isis_adjacency *
! 50: adj_alloc (u_char * id)
! 51: {
! 52: struct isis_adjacency *adj;
! 53:
! 54: adj = XCALLOC (MTYPE_ISIS_ADJACENCY, sizeof (struct isis_adjacency));
! 55: memcpy (adj->sysid, id, ISIS_SYS_ID_LEN);
! 56:
! 57: return adj;
! 58: }
! 59:
! 60: struct isis_adjacency *
! 61: isis_new_adj (u_char * id, u_char * snpa, int level,
! 62: struct isis_circuit *circuit)
! 63: {
! 64: struct isis_adjacency *adj;
! 65: int i;
! 66:
! 67: adj = adj_alloc (id); /* P2P kludge */
! 68:
! 69: if (adj == NULL)
! 70: {
! 71: zlog_err ("Out of memory!");
! 72: return NULL;
! 73: }
! 74:
! 75: if (snpa) {
! 76: memcpy (adj->snpa, snpa, 6);
! 77: } else {
! 78: memset (adj->snpa, ' ', 6);
! 79: }
! 80:
! 81: adj->circuit = circuit;
! 82: adj->level = level;
! 83: adj->flaps = 0;
! 84: adj->last_flap = time (NULL);
! 85: if (circuit->circ_type == CIRCUIT_T_BROADCAST)
! 86: {
! 87: listnode_add (circuit->u.bc.adjdb[level - 1], adj);
! 88: adj->dischanges[level - 1] = 0;
! 89: for (i = 0; i < DIS_RECORDS; i++) /* clear N DIS state change records */
! 90: {
! 91: adj->dis_record[(i * ISIS_LEVELS) + level - 1].dis
! 92: = ISIS_UNKNOWN_DIS;
! 93: adj->dis_record[(i * ISIS_LEVELS) + level - 1].last_dis_change
! 94: = time (NULL);
! 95: }
! 96: }
! 97:
! 98: return adj;
! 99: }
! 100:
! 101: struct isis_adjacency *
! 102: isis_adj_lookup (u_char * sysid, struct list *adjdb)
! 103: {
! 104: struct isis_adjacency *adj;
! 105: struct listnode *node;
! 106:
! 107: for (ALL_LIST_ELEMENTS_RO (adjdb, node, adj))
! 108: if (memcmp (adj->sysid, sysid, ISIS_SYS_ID_LEN) == 0)
! 109: return adj;
! 110:
! 111: return NULL;
! 112: }
! 113:
! 114: struct isis_adjacency *
! 115: isis_adj_lookup_snpa (u_char * ssnpa, struct list *adjdb)
! 116: {
! 117: struct listnode *node;
! 118: struct isis_adjacency *adj;
! 119:
! 120: for (ALL_LIST_ELEMENTS_RO (adjdb, node, adj))
! 121: if (memcmp (adj->snpa, ssnpa, ETH_ALEN) == 0)
! 122: return adj;
! 123:
! 124: return NULL;
! 125: }
! 126:
! 127: void
! 128: isis_delete_adj (struct isis_adjacency *adj, struct list *adjdb)
! 129: {
! 130: if (!adj)
! 131: return;
! 132: /* When we recieve a NULL list, we will know its p2p. */
! 133: if (adjdb)
! 134: listnode_delete (adjdb, adj);
! 135:
! 136: THREAD_OFF (adj->t_expire);
! 137:
! 138: if (adj->ipv4_addrs)
! 139: list_delete (adj->ipv4_addrs);
! 140: #ifdef HAVE_IPV6
! 141: if (adj->ipv6_addrs)
! 142: list_delete (adj->ipv6_addrs);
! 143: #endif
! 144:
! 145: XFREE (MTYPE_ISIS_ADJACENCY, adj);
! 146: return;
! 147: }
! 148:
! 149: void
! 150: isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state state,
! 151: const char *reason)
! 152: {
! 153: int old_state;
! 154: int level = adj->level;
! 155: struct isis_circuit *circuit;
! 156:
! 157: old_state = adj->adj_state;
! 158: adj->adj_state = state;
! 159:
! 160: circuit = adj->circuit;
! 161:
! 162: if (isis->debugs & DEBUG_ADJ_PACKETS)
! 163: {
! 164: zlog_debug ("ISIS-Adj (%s): Adjacency state change %d->%d: %s",
! 165: circuit->area->area_tag,
! 166: old_state, state, reason ? reason : "unspecified");
! 167: }
! 168:
! 169: if (circuit->circ_type == CIRCUIT_T_BROADCAST)
! 170: {
! 171: if (state == ISIS_ADJ_UP)
! 172: circuit->upadjcount[level - 1]++;
! 173: if (state == ISIS_ADJ_DOWN)
! 174: {
! 175: isis_delete_adj (adj, adj->circuit->u.bc.adjdb[level - 1]);
! 176: circuit->upadjcount[level - 1]--;
! 177: }
! 178:
! 179: list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]);
! 180: isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1],
! 181: circuit->u.bc.lan_neighs[level - 1]);
! 182: }
! 183: else if (state == ISIS_ADJ_UP)
! 184: { /* p2p interface */
! 185: if (adj->sys_type == ISIS_SYSTYPE_UNKNOWN)
! 186: send_hello (circuit, 1);
! 187:
! 188: /* update counter & timers for debugging purposes */
! 189: adj->last_flap = time (NULL);
! 190: adj->flaps++;
! 191:
! 192: /* 7.3.17 - going up on P2P -> send CSNP */
! 193: /* FIXME: yup, I know its wrong... but i will do it! (for now) */
! 194: send_csnp (circuit, 1);
! 195: send_csnp (circuit, 2);
! 196: }
! 197: else if (state == ISIS_ADJ_DOWN)
! 198: { /* p2p interface */
! 199: adj->circuit->u.p2p.neighbor = NULL;
! 200: isis_delete_adj (adj, NULL);
! 201: }
! 202: return;
! 203: }
! 204:
! 205:
! 206: void
! 207: isis_adj_print (struct isis_adjacency *adj)
! 208: {
! 209: struct isis_dynhn *dyn;
! 210: struct listnode *node;
! 211: struct in_addr *ipv4_addr;
! 212: #ifdef HAVE_IPV6
! 213: struct in6_addr *ipv6_addr;
! 214: u_char ip6[INET6_ADDRSTRLEN];
! 215: #endif /* HAVE_IPV6 */
! 216:
! 217: if (!adj)
! 218: return;
! 219: dyn = dynhn_find_by_id (adj->sysid);
! 220: if (dyn)
! 221: zlog_debug ("%s", dyn->name.name);
! 222:
! 223: zlog_debug ("SystemId %20s SNPA %s, level %d\nHolding Time %d",
! 224: adj->sysid ? sysid_print (adj->sysid) : "unknown",
! 225: snpa_print (adj->snpa), adj->level, adj->hold_time);
! 226: if (adj->ipv4_addrs && listcount (adj->ipv4_addrs) > 0)
! 227: {
! 228: zlog_debug ("IPv4 Addresses:");
! 229:
! 230: for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ipv4_addr))
! 231: zlog_debug ("%s", inet_ntoa (*ipv4_addr));
! 232: }
! 233:
! 234: #ifdef HAVE_IPV6
! 235: if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0)
! 236: {
! 237: zlog_debug ("IPv6 Addresses:");
! 238: for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr))
! 239: {
! 240: inet_ntop (AF_INET6, ipv6_addr, (char *)ip6, INET6_ADDRSTRLEN);
! 241: zlog_debug ("%s", ip6);
! 242: }
! 243: }
! 244: #endif /* HAVE_IPV6 */
! 245: zlog_debug ("Speaks: %s", nlpid2string (&adj->nlpids));
! 246:
! 247: return;
! 248: }
! 249:
! 250: int
! 251: isis_adj_expire (struct thread *thread)
! 252: {
! 253: struct isis_adjacency *adj;
! 254: int level;
! 255:
! 256: /*
! 257: * Get the adjacency
! 258: */
! 259: adj = THREAD_ARG (thread);
! 260: assert (adj);
! 261: level = adj->level;
! 262: adj->t_expire = NULL;
! 263:
! 264: /* trigger the adj expire event */
! 265: isis_adj_state_change (adj, ISIS_ADJ_DOWN, "holding time expired");
! 266:
! 267: return 0;
! 268: }
! 269:
! 270: static const char *
! 271: adj_state2string (int state)
! 272: {
! 273:
! 274: switch (state)
! 275: {
! 276: case ISIS_ADJ_INITIALIZING:
! 277: return "Initializing";
! 278: case ISIS_ADJ_UP:
! 279: return "Up";
! 280: case ISIS_ADJ_DOWN:
! 281: return "Down";
! 282: default:
! 283: return "Unknown";
! 284: }
! 285:
! 286: return NULL; /* not reached */
! 287: }
! 288:
! 289: /*
! 290: * show clns/isis neighbor (detail)
! 291: */
! 292: static void
! 293: isis_adj_print_vty2 (struct isis_adjacency *adj, struct vty *vty, char detail)
! 294: {
! 295:
! 296: #ifdef HAVE_IPV6
! 297: struct in6_addr *ipv6_addr;
! 298: u_char ip6[INET6_ADDRSTRLEN];
! 299: #endif /* HAVE_IPV6 */
! 300: struct in_addr *ip_addr;
! 301: time_t now;
! 302: struct isis_dynhn *dyn;
! 303: int level;
! 304: struct listnode *node;
! 305:
! 306: dyn = dynhn_find_by_id (adj->sysid);
! 307: if (dyn)
! 308: vty_out (vty, " %-20s", dyn->name.name);
! 309: else if (adj->sysid)
! 310: {
! 311: vty_out (vty, " %-20s", sysid_print (adj->sysid));
! 312: }
! 313: else
! 314: {
! 315: vty_out (vty, " unknown ");
! 316: }
! 317:
! 318: if (detail == ISIS_UI_LEVEL_BRIEF)
! 319: {
! 320: if (adj->circuit)
! 321: vty_out (vty, "%-12s", adj->circuit->interface->name);
! 322: else
! 323: vty_out (vty, "NULL circuit!");
! 324: vty_out (vty, "%-3u", adj->level); /* level */
! 325: vty_out (vty, "%-13s", adj_state2string (adj->adj_state));
! 326: now = time (NULL);
! 327: if (adj->last_upd)
! 328: vty_out (vty, "%-9lu", adj->last_upd + adj->hold_time - now);
! 329: else
! 330: vty_out (vty, "- ");
! 331: vty_out (vty, "%-10s", snpa_print (adj->snpa));
! 332: vty_out (vty, "%s", VTY_NEWLINE);
! 333: }
! 334:
! 335: if (detail == ISIS_UI_LEVEL_DETAIL)
! 336: {
! 337: level = adj->level;
! 338: if (adj->circuit)
! 339: vty_out (vty, "%s Interface: %s", VTY_NEWLINE, adj->circuit->interface->name); /* interface name */
! 340: else
! 341: vty_out (vty, "NULL circuit!%s", VTY_NEWLINE);
! 342: vty_out (vty, ", Level: %u", adj->level); /* level */
! 343: vty_out (vty, ", State: %s", adj_state2string (adj->adj_state));
! 344: now = time (NULL);
! 345: if (adj->last_upd)
! 346: vty_out (vty, ", Expires in %s",
! 347: time2string (adj->last_upd + adj->hold_time - now));
! 348: else
! 349: vty_out (vty, ", Expires in %s", time2string (adj->hold_time));
! 350: vty_out (vty, "%s Adjacency flaps: %u", VTY_NEWLINE, adj->flaps);
! 351: vty_out (vty, ", Last: %s ago", time2string (now - adj->last_flap));
! 352: vty_out (vty, "%s Circuit type: %s",
! 353: VTY_NEWLINE, circuit_t2string (adj->circuit_t));
! 354: vty_out (vty, ", Speaks: %s", nlpid2string (&adj->nlpids));
! 355: vty_out (vty, "%s SNPA: %s", VTY_NEWLINE, snpa_print (adj->snpa));
! 356: dyn = dynhn_find_by_id (adj->lanid);
! 357: if (dyn)
! 358: vty_out (vty, ", LAN id: %s.%02x",
! 359: dyn->name.name, adj->lanid[ISIS_SYS_ID_LEN]);
! 360: else
! 361: vty_out (vty, ", LAN id: %s.%02x",
! 362: sysid_print (adj->lanid), adj->lanid[ISIS_SYS_ID_LEN]);
! 363:
! 364: vty_out (vty, "%s Priority: %u",
! 365: VTY_NEWLINE, adj->prio[adj->level - 1]);
! 366:
! 367: vty_out (vty, ", %s, DIS flaps: %u, Last: %s ago%s",
! 368: isis_disflag2string (adj->dis_record[ISIS_LEVELS + level - 1].
! 369: dis), adj->dischanges[level - 1],
! 370: time2string (now -
! 371: (adj->dis_record[ISIS_LEVELS + level - 1].
! 372: last_dis_change)), VTY_NEWLINE);
! 373:
! 374: if (adj->ipv4_addrs && listcount (adj->ipv4_addrs) > 0)
! 375: {
! 376: vty_out (vty, " IPv4 Addresses:%s", VTY_NEWLINE);
! 377: for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ip_addr))
! 378: vty_out (vty, " %s%s", inet_ntoa (*ip_addr), VTY_NEWLINE);
! 379: }
! 380: #ifdef HAVE_IPV6
! 381: if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0)
! 382: {
! 383: vty_out (vty, " IPv6 Addresses:%s", VTY_NEWLINE);
! 384: for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr))
! 385: {
! 386: inet_ntop (AF_INET6, ipv6_addr, (char *)ip6, INET6_ADDRSTRLEN);
! 387: vty_out (vty, " %s%s", ip6, VTY_NEWLINE);
! 388: }
! 389: }
! 390: #endif /* HAVE_IPV6 */
! 391: vty_out (vty, "%s", VTY_NEWLINE);
! 392: }
! 393: return;
! 394: }
! 395:
! 396: void
! 397: isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty)
! 398: {
! 399: isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_BRIEF);
! 400: }
! 401:
! 402: void
! 403: isis_adj_print_vty_detail (struct isis_adjacency *adj, struct vty *vty)
! 404: {
! 405: isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_DETAIL);
! 406: }
! 407:
! 408: void
! 409: isis_adj_print_vty_extensive (struct isis_adjacency *adj, struct vty *vty)
! 410: {
! 411: isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_EXTENSIVE);
! 412: }
! 413:
! 414: void
! 415: isis_adj_p2p_print_vty (struct isis_adjacency *adj, struct vty *vty)
! 416: {
! 417: isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_BRIEF);
! 418: }
! 419:
! 420: void
! 421: isis_adj_p2p_print_vty_detail (struct isis_adjacency *adj, struct vty *vty)
! 422: {
! 423: isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_DETAIL);
! 424: }
! 425:
! 426: void
! 427: isis_adj_p2p_print_vty_extensive (struct isis_adjacency *adj, struct vty *vty)
! 428: {
! 429: isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_EXTENSIVE);
! 430: }
! 431:
! 432: void
! 433: isis_adjdb_iterate (struct list *adjdb, void (*func) (struct isis_adjacency *,
! 434: void *), void *arg)
! 435: {
! 436: struct listnode *node, *nnode;
! 437: struct isis_adjacency *adj;
! 438:
! 439: for (ALL_LIST_ELEMENTS (adjdb, node, nnode, adj))
! 440: (*func) (adj, arg);
! 441: }
! 442:
! 443: void
! 444: isis_adj_build_neigh_list (struct list *adjdb, struct list *list)
! 445: {
! 446: struct isis_adjacency *adj;
! 447: struct listnode *node;
! 448:
! 449: if (!list)
! 450: {
! 451: zlog_warn ("isis_adj_build_neigh_list(): NULL list");
! 452: return;
! 453: }
! 454:
! 455: for (ALL_LIST_ELEMENTS_RO (adjdb, node, adj))
! 456: {
! 457: if (!adj)
! 458: {
! 459: zlog_warn ("isis_adj_build_neigh_list(): NULL adj");
! 460: return;
! 461: }
! 462:
! 463: if ((adj->adj_state == ISIS_ADJ_UP ||
! 464: adj->adj_state == ISIS_ADJ_INITIALIZING))
! 465: listnode_add (list, adj->snpa);
! 466: }
! 467: return;
! 468: }
! 469:
! 470: void
! 471: isis_adj_build_up_list (struct list *adjdb, struct list *list)
! 472: {
! 473: struct isis_adjacency *adj;
! 474: struct listnode *node;
! 475:
! 476: if (!list)
! 477: {
! 478: zlog_warn ("isis_adj_build_up_list(): NULL list");
! 479: return;
! 480: }
! 481:
! 482: for (ALL_LIST_ELEMENTS_RO (adjdb, node, adj))
! 483: {
! 484: if (!adj)
! 485: {
! 486: zlog_warn ("isis_adj_build_up_list(): NULL adj");
! 487: return;
! 488: }
! 489:
! 490: if (adj->adj_state == ISIS_ADJ_UP)
! 491: listnode_add (list, adj);
! 492: }
! 493:
! 494: return;
! 495: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>