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