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>