Annotation of embedaddon/quagga/ospfd/ospf_neighbor.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * OSPF Neighbor functions.
        !             3:  * Copyright (C) 1999, 2000 Toshiaki Takada
        !             4:  *
        !             5:  * This file is part of GNU Zebra.
        !             6:  * 
        !             7:  * GNU Zebra is free software; you can redistribute it and/or modify
        !             8:  * it under the terms of the GNU General Public License as published
        !             9:  * by the Free Software Foundation; either version 2, or (at your
        !            10:  * option) any later version.
        !            11:  *
        !            12:  * GNU Zebra is distributed in the hope that it will be useful, but
        !            13:  * WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            15:  * General Public License for more details.
        !            16:  *
        !            17:  * You should have received a copy of the GNU General Public License
        !            18:  * along with GNU Zebra; see the file COPYING.  If not, write to the
        !            19:  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
        !            20:  * Boston, MA 02111-1307, USA.
        !            21:  */
        !            22: 
        !            23: #include <zebra.h>
        !            24: 
        !            25: #include "linklist.h"
        !            26: #include "prefix.h"
        !            27: #include "memory.h"
        !            28: #include "command.h"
        !            29: #include "thread.h"
        !            30: #include "stream.h"
        !            31: #include "table.h"
        !            32: #include "log.h"
        !            33: 
        !            34: #include "ospfd/ospfd.h"
        !            35: #include "ospfd/ospf_interface.h"
        !            36: #include "ospfd/ospf_asbr.h"
        !            37: #include "ospfd/ospf_lsa.h"
        !            38: #include "ospfd/ospf_lsdb.h"
        !            39: #include "ospfd/ospf_neighbor.h"
        !            40: #include "ospfd/ospf_nsm.h"
        !            41: #include "ospfd/ospf_packet.h"
        !            42: #include "ospfd/ospf_network.h"
        !            43: #include "ospfd/ospf_flood.h"
        !            44: #include "ospfd/ospf_dump.h"
        !            45: 
        !            46: /* Fill in the the 'key' as appropriate to retrieve the entry for nbr
        !            47:  * from the ospf_interface's nbrs table. Indexed by interface address
        !            48:  * for all cases except Virtual-link interfaces, where neighbours are
        !            49:  * indexed by router-ID instead.
        !            50:  */
        !            51: static void
        !            52: ospf_nbr_key (struct ospf_interface *oi, struct ospf_neighbor *nbr,
        !            53:               struct prefix *key)
        !            54: {
        !            55:   key->family = AF_INET;
        !            56:   key->prefixlen = IPV4_MAX_BITLEN;
        !            57: 
        !            58:   /* vlinks are indexed by router-id */
        !            59:   if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
        !            60:     key->u.prefix4 = nbr->router_id;
        !            61:   else
        !            62:     key->u.prefix4 = nbr->src;
        !            63:   return;
        !            64: }
        !            65: 
        !            66: struct ospf_neighbor *
        !            67: ospf_nbr_new (struct ospf_interface *oi)
        !            68: {
        !            69:   struct ospf_neighbor *nbr;
        !            70: 
        !            71:   /* Allcate new neighbor. */
        !            72:   nbr = XCALLOC (MTYPE_OSPF_NEIGHBOR, sizeof (struct ospf_neighbor));
        !            73: 
        !            74:   /* Relate neighbor to the interface. */
        !            75:   nbr->oi = oi;
        !            76: 
        !            77:   /* Set default values. */
        !            78:   nbr->state = NSM_Down;
        !            79: 
        !            80:   /* Set inheritance values. */
        !            81:   nbr->v_inactivity = OSPF_IF_PARAM (oi, v_wait);
        !            82:   nbr->v_db_desc = OSPF_IF_PARAM (oi, retransmit_interval);
        !            83:   nbr->v_ls_req = OSPF_IF_PARAM (oi, retransmit_interval);
        !            84:   nbr->v_ls_upd = OSPF_IF_PARAM (oi, retransmit_interval);
        !            85:   nbr->priority = -1;
        !            86: 
        !            87:   /* DD flags. */
        !            88:   nbr->dd_flags = OSPF_DD_FLAG_MS|OSPF_DD_FLAG_M|OSPF_DD_FLAG_I;
        !            89: 
        !            90:   /* Last received and sent DD. */
        !            91:   nbr->last_send = NULL;
        !            92: 
        !            93:   nbr->nbr_nbma = NULL;
        !            94: 
        !            95:   ospf_lsdb_init (&nbr->db_sum);
        !            96:   ospf_lsdb_init (&nbr->ls_rxmt);
        !            97:   ospf_lsdb_init (&nbr->ls_req);
        !            98: 
        !            99:   nbr->crypt_seqnum = 0;
        !           100: 
        !           101:   return nbr;
        !           102: }
        !           103: 
        !           104: void
        !           105: ospf_nbr_free (struct ospf_neighbor *nbr)
        !           106: {
        !           107:   /* Free DB summary list. */
        !           108:   if (ospf_db_summary_count (nbr))
        !           109:     ospf_db_summary_clear (nbr);
        !           110:     /* ospf_db_summary_delete_all (nbr); */
        !           111: 
        !           112:   /* Free ls request list. */
        !           113:   if (ospf_ls_request_count (nbr))
        !           114:     ospf_ls_request_delete_all (nbr);
        !           115: 
        !           116:   /* Free retransmit list. */
        !           117:   if (ospf_ls_retransmit_count (nbr))
        !           118:     ospf_ls_retransmit_clear (nbr);
        !           119: 
        !           120:   /* Cleanup LSDBs. */
        !           121:   ospf_lsdb_cleanup (&nbr->db_sum);
        !           122:   ospf_lsdb_cleanup (&nbr->ls_req);
        !           123:   ospf_lsdb_cleanup (&nbr->ls_rxmt);
        !           124:   
        !           125:   /* Clear last send packet. */
        !           126:   if (nbr->last_send)
        !           127:     ospf_packet_free (nbr->last_send);
        !           128: 
        !           129:   if (nbr->nbr_nbma)
        !           130:     {
        !           131:       nbr->nbr_nbma->nbr = NULL;
        !           132:       nbr->nbr_nbma = NULL;
        !           133:     }
        !           134: 
        !           135:   /* Cancel all timers. */
        !           136:   OSPF_NSM_TIMER_OFF (nbr->t_inactivity);
        !           137:   OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
        !           138:   OSPF_NSM_TIMER_OFF (nbr->t_ls_req);
        !           139:   OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
        !           140: 
        !           141:   /* Cancel all events. *//* Thread lookup cost would be negligible. */
        !           142:   thread_cancel_event (master, nbr);
        !           143: 
        !           144:   XFREE (MTYPE_OSPF_NEIGHBOR, nbr);
        !           145: }
        !           146: 
        !           147: /* Delete specified OSPF neighbor from interface. */
        !           148: void
        !           149: ospf_nbr_delete (struct ospf_neighbor *nbr)
        !           150: {
        !           151:   struct ospf_interface *oi;
        !           152:   struct route_node *rn;
        !           153:   struct prefix p;
        !           154: 
        !           155:   oi = nbr->oi;
        !           156:   
        !           157:   /* get appropriate prefix 'key' */
        !           158:   ospf_nbr_key (oi, nbr, &p);
        !           159: 
        !           160:   rn = route_node_lookup (oi->nbrs, &p);
        !           161:   if (rn)
        !           162:     {
        !           163:       /* If lookup for a NBR succeeds, the leaf route_node could
        !           164:        * only exist because there is (or was) a nbr there.
        !           165:        * If the nbr was deleted, the leaf route_node should have
        !           166:        * lost its last refcount too, and be deleted.
        !           167:        * Therefore a looked-up leaf route_node in nbrs table
        !           168:        * should never have NULL info.
        !           169:        */
        !           170:       assert (rn->info);
        !           171:       
        !           172:       if (rn->info)
        !           173:        {
        !           174:          rn->info = NULL;
        !           175:          route_unlock_node (rn);
        !           176:        }
        !           177:       else
        !           178:        zlog_info ("Can't find neighbor %s in the interface %s",
        !           179:                   inet_ntoa (nbr->src), IF_NAME (oi));
        !           180: 
        !           181:       route_unlock_node (rn);
        !           182:     }
        !           183: 
        !           184:   /* Free ospf_neighbor structure. */
        !           185:   ospf_nbr_free (nbr);
        !           186: }
        !           187: 
        !           188: /* Check myself is in the neighbor list. */
        !           189: int
        !           190: ospf_nbr_bidirectional (struct in_addr *router_id,
        !           191:                        struct in_addr *neighbors, int size)
        !           192: {
        !           193:   int i;
        !           194:   int max;
        !           195: 
        !           196:   max = size / sizeof (struct in_addr);
        !           197: 
        !           198:   for (i = 0; i < max; i ++)
        !           199:     if (IPV4_ADDR_SAME (router_id, &neighbors[i]))
        !           200:       return 1;
        !           201: 
        !           202:   return 0;
        !           203: }
        !           204: 
        !           205: /* Add self to nbr list. */
        !           206: void
        !           207: ospf_nbr_add_self (struct ospf_interface *oi)
        !           208: {
        !           209:   struct prefix p;
        !           210:   struct route_node *rn;
        !           211: 
        !           212:   /* Initial state */
        !           213:   oi->nbr_self->address = *oi->address;
        !           214:   oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority);
        !           215:   oi->nbr_self->router_id = oi->ospf->router_id;
        !           216:   oi->nbr_self->src = oi->address->u.prefix4;
        !           217:   oi->nbr_self->state = NSM_TwoWay;
        !           218:   
        !           219:   switch (oi->area->external_routing)
        !           220:     {
        !           221:       case OSPF_AREA_DEFAULT:
        !           222:         SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
        !           223:         break;
        !           224:       case OSPF_AREA_STUB:
        !           225:         UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
        !           226:         break;
        !           227:       case OSPF_AREA_NSSA:
        !           228:         UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
        !           229:         SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
        !           230:         break;
        !           231:     }
        !           232:   
        !           233:   /* Add nbr_self to nbrs table */
        !           234:   ospf_nbr_key (oi, oi->nbr_self, &p);
        !           235:   
        !           236:   rn = route_node_get (oi->nbrs, &p);
        !           237:   if (rn->info)
        !           238:     {
        !           239:       /* There is already pseudo neighbor. */
        !           240:       assert (oi->nbr_self == rn->info);
        !           241:       route_unlock_node (rn);
        !           242:     }
        !           243:   else
        !           244:     rn->info = oi->nbr_self;
        !           245: }
        !           246: 
        !           247: /* Get neighbor count by status.
        !           248:    Specify status = 0, get all neighbor other than myself. */
        !           249: int
        !           250: ospf_nbr_count (struct ospf_interface *oi, int state)
        !           251: {
        !           252:   struct ospf_neighbor *nbr;
        !           253:   struct route_node *rn;
        !           254:   int count = 0;
        !           255: 
        !           256:   for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
        !           257:     if ((nbr = rn->info))
        !           258:       if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id))
        !           259:        if (state == 0 || nbr->state == state)
        !           260:          count++;
        !           261: 
        !           262:   return count;
        !           263: }
        !           264: 
        !           265: #ifdef HAVE_OPAQUE_LSA
        !           266: int
        !           267: ospf_nbr_count_opaque_capable (struct ospf_interface *oi)
        !           268: {
        !           269:   struct ospf_neighbor *nbr;
        !           270:   struct route_node *rn;
        !           271:   int count = 0;
        !           272: 
        !           273:   for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
        !           274:     if ((nbr = rn->info))
        !           275:       if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id))
        !           276:        if (nbr->state == NSM_Full)
        !           277:          if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
        !           278:            count++;
        !           279: 
        !           280:   return count;
        !           281: }
        !           282: #endif /* HAVE_OPAQUE_LSA */
        !           283: 
        !           284: /* lookup nbr by address - use this only if you know you must
        !           285:  * otherwise use the ospf_nbr_lookup() wrapper, which deals 
        !           286:  * with virtual link neighbours
        !           287:  */
        !           288: struct ospf_neighbor *
        !           289: ospf_nbr_lookup_by_addr (struct route_table *nbrs,
        !           290:                         struct in_addr *addr)
        !           291: {
        !           292:   struct prefix p;
        !           293:   struct route_node *rn;
        !           294:   struct ospf_neighbor *nbr;
        !           295: 
        !           296:   p.family = AF_INET;
        !           297:   p.prefixlen = IPV4_MAX_BITLEN;
        !           298:   p.u.prefix4 = *addr;
        !           299: 
        !           300:   rn = route_node_lookup (nbrs, &p);
        !           301:   if (! rn)
        !           302:     return NULL;
        !           303:   
        !           304:   /* See comment in ospf_nbr_delete */
        !           305:   assert (rn->info);
        !           306: 
        !           307:   if (rn->info == NULL)
        !           308:     {
        !           309:       route_unlock_node (rn);
        !           310:       return NULL;
        !           311:     }
        !           312: 
        !           313:   nbr = (struct ospf_neighbor *) rn->info;
        !           314:   route_unlock_node (rn);
        !           315: 
        !           316:   return nbr;
        !           317: }
        !           318: 
        !           319: struct ospf_neighbor *
        !           320: ospf_nbr_lookup_by_routerid (struct route_table *nbrs,
        !           321:                             struct in_addr *id)
        !           322: {
        !           323:   struct route_node *rn;
        !           324:   struct ospf_neighbor *nbr;
        !           325: 
        !           326:   for (rn = route_top (nbrs); rn; rn = route_next (rn))
        !           327:     if ((nbr = rn->info) != NULL)
        !           328:       if (IPV4_ADDR_SAME (&nbr->router_id, id))
        !           329:        {
        !           330:          route_unlock_node(rn);
        !           331:          return nbr;
        !           332:        }
        !           333: 
        !           334:   return NULL;
        !           335: }
        !           336: 
        !           337: void
        !           338: ospf_renegotiate_optional_capabilities (struct ospf *top)
        !           339: {
        !           340:   struct listnode *node;
        !           341:   struct ospf_interface *oi;
        !           342:   struct route_table *nbrs;
        !           343:   struct route_node *rn;
        !           344:   struct ospf_neighbor *nbr;
        !           345: 
        !           346:   /* At first, flush self-originated LSAs from routing domain. */
        !           347:   ospf_flush_self_originated_lsas_now (top);
        !           348: 
        !           349:   /* Revert all neighbor status to ExStart. */
        !           350:   for (ALL_LIST_ELEMENTS_RO (top->oiflist, node, oi))
        !           351:     {
        !           352:       if ((nbrs = oi->nbrs) == NULL)
        !           353:         continue;
        !           354: 
        !           355:       for (rn = route_top (nbrs); rn; rn = route_next (rn))
        !           356:         {
        !           357:           if ((nbr = rn->info) == NULL || nbr == oi->nbr_self)
        !           358:             continue;
        !           359: 
        !           360:           if (nbr->state < NSM_ExStart)
        !           361:             continue;
        !           362: 
        !           363:           if (IS_DEBUG_OSPF_EVENT)
        !           364:             zlog_debug ("Renegotiate optional capabilities with neighbor(%s)", inet_ntoa (nbr->router_id));
        !           365: 
        !           366:           OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
        !           367:         }
        !           368:     }
        !           369: 
        !           370:   return;
        !           371: }
        !           372: 
        !           373: 
        !           374: struct ospf_neighbor *
        !           375: ospf_nbr_lookup (struct ospf_interface *oi, struct ip *iph,
        !           376:                  struct ospf_header *ospfh)
        !           377: {
        !           378:   if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
        !           379:     return (ospf_nbr_lookup_by_routerid (oi->nbrs, &ospfh->router_id));
        !           380:   else
        !           381:     return (ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src));
        !           382: }
        !           383: 
        !           384: static struct ospf_neighbor *
        !           385: ospf_nbr_add (struct ospf_interface *oi, struct ospf_header *ospfh,
        !           386:               struct prefix *p)
        !           387: {
        !           388:   struct ospf_neighbor *nbr;
        !           389:   
        !           390:   nbr = ospf_nbr_new (oi);
        !           391:   nbr->state = NSM_Down;
        !           392:   nbr->src = p->u.prefix4;
        !           393:   memcpy (&nbr->address, p, sizeof (struct prefix));
        !           394: 
        !           395:   nbr->nbr_nbma = NULL;
        !           396:   if (oi->type == OSPF_IFTYPE_NBMA)
        !           397:     {
        !           398:       struct ospf_nbr_nbma *nbr_nbma;
        !           399:       struct listnode *node;
        !           400: 
        !           401:       for (ALL_LIST_ELEMENTS_RO (oi->nbr_nbma, node, nbr_nbma))
        !           402:         {
        !           403:           if (IPV4_ADDR_SAME(&nbr_nbma->addr, &nbr->src))
        !           404:             {
        !           405:               nbr_nbma->nbr = nbr;
        !           406:               nbr->nbr_nbma = nbr_nbma;
        !           407: 
        !           408:               if (nbr_nbma->t_poll)
        !           409:                 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
        !           410: 
        !           411:               nbr->state_change = nbr_nbma->state_change + 1;
        !           412:             }
        !           413:         }
        !           414:     }
        !           415:       
        !           416:   /* New nbr, save the crypto sequence number if necessary */
        !           417:   if (ntohs (ospfh->auth_type) == OSPF_AUTH_CRYPTOGRAPHIC)
        !           418:     nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum;
        !           419:   
        !           420:   if (IS_DEBUG_OSPF_EVENT)
        !           421:     zlog_debug ("NSM[%s:%s]: start", IF_NAME (nbr->oi),
        !           422:                inet_ntoa (nbr->router_id));
        !           423:   
        !           424:   return nbr;
        !           425: }
        !           426: 
        !           427: struct ospf_neighbor *
        !           428: ospf_nbr_get (struct ospf_interface *oi, struct ospf_header *ospfh,
        !           429:               struct ip *iph, struct prefix *p)
        !           430: {
        !           431:   struct route_node *rn;
        !           432:   struct prefix key;
        !           433:   struct ospf_neighbor *nbr;
        !           434:   
        !           435:   key.family = AF_INET;
        !           436:   key.prefixlen = IPV4_MAX_BITLEN;
        !           437: 
        !           438:   if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
        !           439:     key.u.prefix4 = ospfh->router_id;   /* index vlink nbrs by router-id */
        !           440:   else
        !           441:     key.u.prefix4 = iph->ip_src;
        !           442: 
        !           443:   rn = route_node_get (oi->nbrs, &key);
        !           444:   if (rn->info)
        !           445:     {
        !           446:       route_unlock_node (rn);
        !           447:       nbr = rn->info;
        !           448:       
        !           449:       if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt)
        !           450:         {
        !           451:           nbr->src = iph->ip_src;
        !           452:           memcpy (&nbr->address, p, sizeof (struct prefix));
        !           453:         }
        !           454:     }
        !           455:   else
        !           456:     {
        !           457:       rn->info = nbr = ospf_nbr_add (oi, ospfh, p);
        !           458:     }
        !           459:   
        !           460:   nbr->router_id = ospfh->router_id;
        !           461: 
        !           462:   return nbr;
        !           463: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>