File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ospfd / ospf_neighbor.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:12 2016 UTC (7 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

    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 and PointToPoint interfaces, where
   49:  * neighbours are 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:       oi->type == OSPF_IFTYPE_POINTOPOINT)
   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: 
  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: 
  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
  293:  * otherwise use the ospf_nbr_lookup() wrapper, which deals
  294:  * with virtual link and PointToPoint neighbours
  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: {
  386:   if (oi->type == OSPF_IFTYPE_VIRTUALLINK ||
  387:       oi->type == OSPF_IFTYPE_POINTOPOINT)
  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: 
  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 */
  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>