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

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

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