Annotation of embedaddon/quagga/isisd/isis_adjacency.c, revision 1.1.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>