Annotation of embedaddon/bird/proto/ospf/neighbor.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  *     BIRD -- OSPF
        !             3:  *
        !             4:  *     (c) 1999--2004 Ondrej Filip <feela@network.cz>
        !             5:  *     (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
        !             6:  *     (c) 2009--2014 CZ.NIC z.s.p.o.
        !             7:  *
        !             8:  *     Can be freely distributed and used under the terms of the GNU GPL.
        !             9:  */
        !            10: 
        !            11: #include "ospf.h"
        !            12: 
        !            13: 
        !            14: const char *ospf_ns_names[] = {
        !            15:   "Down", "Attempt", "Init", "2-Way", "ExStart", "Exchange", "Loading", "Full"
        !            16: };
        !            17: 
        !            18: const char *ospf_inm_names[] = {
        !            19:   "HelloReceived", "Start", "2-WayReceived", "NegotiationDone", "ExchangeDone",
        !            20:   "BadLSReq", "LoadingDone", "AdjOK?", "SeqNumberMismatch", "1-WayReceived",
        !            21:   "KillNbr", "InactivityTimer", "LLDown"
        !            22: };
        !            23: 
        !            24: 
        !            25: static int can_do_adj(struct ospf_neighbor *n);
        !            26: static void inactivity_timer_hook(timer * timer);
        !            27: static void dbdes_timer_hook(timer *t);
        !            28: static void lsrq_timer_hook(timer *t);
        !            29: static void lsrt_timer_hook(timer *t);
        !            30: static void ackd_timer_hook(timer *t);
        !            31: 
        !            32: 
        !            33: static void
        !            34: init_lists(struct ospf_proto *p, struct ospf_neighbor *n)
        !            35: {
        !            36:   s_init_list(&(n->lsrql));
        !            37:   n->lsrqi = SHEAD(n->lsrql);
        !            38:   n->lsrqh = ospf_top_new(p, n->pool);
        !            39: 
        !            40:   s_init_list(&(n->lsrtl));
        !            41:   n->lsrth = ospf_top_new(p, n->pool);
        !            42: }
        !            43: 
        !            44: static void
        !            45: release_lsrtl(struct ospf_proto *p, struct ospf_neighbor *n)
        !            46: {
        !            47:   struct top_hash_entry *ret, *en;
        !            48: 
        !            49:   WALK_SLIST(ret, n->lsrtl)
        !            50:   {
        !            51:     en = ospf_hash_find_entry(p->gr, ret);
        !            52:     if (en)
        !            53:       en->ret_count--;
        !            54:   }
        !            55: }
        !            56: 
        !            57: /* Resets LSA request and retransmit lists.
        !            58:  * We do not reset DB summary list iterator here,
        !            59:  * it is reset during entering EXCHANGE state.
        !            60:  */
        !            61: static void
        !            62: reset_lists(struct ospf_proto *p, struct ospf_neighbor *n)
        !            63: {
        !            64:   release_lsrtl(p, n);
        !            65:   ospf_top_free(n->lsrqh);
        !            66:   ospf_top_free(n->lsrth);
        !            67:   ospf_reset_lsack_queue(n);
        !            68: 
        !            69:   tm_stop(n->dbdes_timer);
        !            70:   tm_stop(n->lsrq_timer);
        !            71:   tm_stop(n->lsrt_timer);
        !            72:   tm_stop(n->ackd_timer);
        !            73: 
        !            74:   init_lists(p, n);
        !            75: }
        !            76: 
        !            77: struct ospf_neighbor *
        !            78: ospf_neighbor_new(struct ospf_iface *ifa)
        !            79: {
        !            80:   struct ospf_proto *p = ifa->oa->po;
        !            81:   struct pool *pool = rp_new(p->p.pool, "OSPF Neighbor");
        !            82:   struct ospf_neighbor *n = mb_allocz(pool, sizeof(struct ospf_neighbor));
        !            83: 
        !            84:   n->pool = pool;
        !            85:   n->ifa = ifa;
        !            86:   add_tail(&ifa->neigh_list, NODE n);
        !            87:   n->adj = 0;
        !            88:   n->csn = 0;
        !            89:   n->state = NEIGHBOR_DOWN;
        !            90: 
        !            91:   init_lists(p, n);
        !            92:   s_init(&(n->dbsi), &(p->lsal));
        !            93: 
        !            94:   init_list(&n->ackl[ACKL_DIRECT]);
        !            95:   init_list(&n->ackl[ACKL_DELAY]);
        !            96: 
        !            97:   n->inactim = tm_new_set(pool, inactivity_timer_hook, n, 0, 0);
        !            98:   n->dbdes_timer = tm_new_set(pool, dbdes_timer_hook, n, 0, ifa->rxmtint);
        !            99:   n->lsrq_timer = tm_new_set(pool, lsrq_timer_hook, n, 0, ifa->rxmtint);
        !           100:   n->lsrt_timer = tm_new_set(pool, lsrt_timer_hook, n, 0, ifa->rxmtint);
        !           101:   n->ackd_timer = tm_new_set(pool, ackd_timer_hook, n, 0, ifa->rxmtint / 2);
        !           102: 
        !           103:   return (n);
        !           104: }
        !           105: 
        !           106: static void
        !           107: ospf_neigh_down(struct ospf_neighbor *n)
        !           108: {
        !           109:   struct ospf_iface *ifa = n->ifa;
        !           110:   struct ospf_proto *p = ifa->oa->po;
        !           111:   u32 rid = n->rid;
        !           112: 
        !           113:   if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
        !           114:   {
        !           115:     struct nbma_node *nn = find_nbma_node(ifa, n->ip);
        !           116:     if (nn)
        !           117:       nn->found = 0;
        !           118:   }
        !           119: 
        !           120:   s_get(&(n->dbsi));
        !           121:   release_lsrtl(p, n);
        !           122:   rem_node(NODE n);
        !           123:   rfree(n->pool);
        !           124: 
        !           125:   OSPF_TRACE(D_EVENTS, "Neighbor %R on %s removed", rid, ifa->ifname);
        !           126: }
        !           127: 
        !           128: /**
        !           129:  * ospf_neigh_chstate - handles changes related to new or lod state of neighbor
        !           130:  * @n: OSPF neighbor
        !           131:  * @state: new state
        !           132:  *
        !           133:  * Many actions have to be taken acording to a change of state of a neighbor. It
        !           134:  * starts rxmt timers, call interface state machine etc.
        !           135:  */
        !           136: static void
        !           137: ospf_neigh_chstate(struct ospf_neighbor *n, u8 state)
        !           138: {
        !           139:   struct ospf_iface *ifa = n->ifa;
        !           140:   struct ospf_proto *p = ifa->oa->po;
        !           141:   u8 old_state = n->state;
        !           142:   int old_fadj = ifa->fadj;
        !           143: 
        !           144:   if (state == old_state)
        !           145:     return;
        !           146: 
        !           147:   OSPF_TRACE(D_EVENTS, "Neighbor %R on %s changed state from %s to %s",
        !           148:             n->rid, ifa->ifname, ospf_ns_names[old_state], ospf_ns_names[state]);
        !           149: 
        !           150:   n->state = state;
        !           151: 
        !           152:   /* Increase number of partial adjacencies */
        !           153:   if ((state == NEIGHBOR_EXCHANGE) || (state == NEIGHBOR_LOADING))
        !           154:     p->padj++;
        !           155: 
        !           156:   /* Decrease number of partial adjacencies */
        !           157:   if ((old_state == NEIGHBOR_EXCHANGE) || (old_state == NEIGHBOR_LOADING))
        !           158:     p->padj--;
        !           159: 
        !           160:   /* Increase number of full adjacencies */
        !           161:   if (state == NEIGHBOR_FULL)
        !           162:     ifa->fadj++;
        !           163: 
        !           164:   /* Decrease number of full adjacencies */
        !           165:   if (old_state == NEIGHBOR_FULL)
        !           166:     ifa->fadj--;
        !           167: 
        !           168:   if (ifa->fadj != old_fadj)
        !           169:   {
        !           170:     /* RFC 2328 12.4 Event 4 - neighbor enters/leaves Full state */
        !           171:     ospf_notify_rt_lsa(ifa->oa);
        !           172:     ospf_notify_net_lsa(ifa);
        !           173: 
        !           174:     /* RFC 2328 12.4 Event 8 - vlink state change */
        !           175:     if (ifa->type == OSPF_IT_VLINK)
        !           176:       ospf_notify_rt_lsa(ifa->voa);
        !           177:   }
        !           178: 
        !           179:   if (state == NEIGHBOR_EXSTART)
        !           180:   {
        !           181:     /* First time adjacency */
        !           182:     if (n->adj == 0)
        !           183:       n->dds = random_u32();
        !           184: 
        !           185:     n->dds++;
        !           186:     n->myimms = DBDES_IMMS;
        !           187: 
        !           188:     tm_start(n->dbdes_timer, 0);
        !           189:     tm_start(n->ackd_timer, ifa->rxmtint / 2);
        !           190:   }
        !           191: 
        !           192:   if (state > NEIGHBOR_EXSTART)
        !           193:     n->myimms &= ~DBDES_I;
        !           194: 
        !           195:   /* Generate NeighborChange event if needed, see RFC 2328 9.2 */
        !           196:   if ((state == NEIGHBOR_2WAY) && (old_state < NEIGHBOR_2WAY))
        !           197:     ospf_iface_sm(ifa, ISM_NEICH);
        !           198:   if ((state < NEIGHBOR_2WAY) && (old_state >= NEIGHBOR_2WAY))
        !           199:     ospf_iface_sm(ifa, ISM_NEICH);
        !           200: }
        !           201: 
        !           202: /**
        !           203:  * ospf_neigh_sm - ospf neighbor state machine
        !           204:  * @n: neighor
        !           205:  * @event: actual event
        !           206:  *
        !           207:  * This part implements the neighbor state machine as described in 10.3 of
        !           208:  * RFC 2328. The only difference is that state %NEIGHBOR_ATTEMPT is not
        !           209:  * used. We discover neighbors on nonbroadcast networks in the
        !           210:  * same way as on broadcast networks. The only difference is in
        !           211:  * sending hello packets. These are sent to IPs listed in
        !           212:  * @ospf_iface->nbma_list .
        !           213:  */
        !           214: void
        !           215: ospf_neigh_sm(struct ospf_neighbor *n, int event)
        !           216: {
        !           217:   struct ospf_proto *p = n->ifa->oa->po;
        !           218: 
        !           219:   DBG("Neighbor state machine for %R on %s, event %s\n",
        !           220:       n->rid, n->ifa->ifname, ospf_inm_names[event]);
        !           221: 
        !           222:   switch (event)
        !           223:   {
        !           224:   case INM_START:
        !           225:     ospf_neigh_chstate(n, NEIGHBOR_ATTEMPT);
        !           226:     /* NBMA are used different way */
        !           227:     break;
        !           228: 
        !           229:   case INM_HELLOREC:
        !           230:     if (n->state < NEIGHBOR_INIT)
        !           231:       ospf_neigh_chstate(n, NEIGHBOR_INIT);
        !           232: 
        !           233:     /* Restart inactivity timer */
        !           234:     tm_start(n->inactim, n->ifa->deadint);
        !           235:     break;
        !           236: 
        !           237:   case INM_2WAYREC:
        !           238:     if (n->state < NEIGHBOR_2WAY)
        !           239:       ospf_neigh_chstate(n, NEIGHBOR_2WAY);
        !           240:     if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
        !           241:       ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
        !           242:     break;
        !           243: 
        !           244:   case INM_NEGDONE:
        !           245:     if (n->state == NEIGHBOR_EXSTART)
        !           246:     {
        !           247:       ospf_neigh_chstate(n, NEIGHBOR_EXCHANGE);
        !           248: 
        !           249:       /* Reset DB summary list iterator */
        !           250:       s_get(&(n->dbsi));
        !           251:       s_init(&(n->dbsi), &p->lsal);
        !           252: 
        !           253:       /* Add MaxAge LSA entries to retransmission list */
        !           254:       ospf_add_flushed_to_lsrt(p, n);
        !           255:     }
        !           256:     else
        !           257:       bug("NEGDONE and I'm not in EXSTART?");
        !           258:     break;
        !           259: 
        !           260:   case INM_EXDONE:
        !           261:     if (!EMPTY_SLIST(n->lsrql))
        !           262:       ospf_neigh_chstate(n, NEIGHBOR_LOADING);
        !           263:     else
        !           264:       ospf_neigh_chstate(n, NEIGHBOR_FULL);
        !           265:     break;
        !           266: 
        !           267:   case INM_LOADDONE:
        !           268:     ospf_neigh_chstate(n, NEIGHBOR_FULL);
        !           269:     break;
        !           270: 
        !           271:   case INM_ADJOK:
        !           272:     /* Can In build adjacency? */
        !           273:     if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
        !           274:     {
        !           275:       ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
        !           276:     }
        !           277:     else if ((n->state >= NEIGHBOR_EXSTART) && !can_do_adj(n))
        !           278:     {
        !           279:       reset_lists(p, n);
        !           280:       ospf_neigh_chstate(n, NEIGHBOR_2WAY);
        !           281:     }
        !           282:     break;
        !           283: 
        !           284:   case INM_SEQMIS:
        !           285:   case INM_BADLSREQ:
        !           286:     if (n->state >= NEIGHBOR_EXCHANGE)
        !           287:     {
        !           288:       reset_lists(p, n);
        !           289:       ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
        !           290:     }
        !           291:     break;
        !           292: 
        !           293:   case INM_KILLNBR:
        !           294:   case INM_LLDOWN:
        !           295:   case INM_INACTTIM:
        !           296:     /* No need for reset_lists() */
        !           297:     ospf_neigh_chstate(n, NEIGHBOR_DOWN);
        !           298:     ospf_neigh_down(n);
        !           299:     break;
        !           300: 
        !           301:   case INM_1WAYREC:
        !           302:     reset_lists(p, n);
        !           303:     ospf_neigh_chstate(n, NEIGHBOR_INIT);
        !           304:     break;
        !           305: 
        !           306:   default:
        !           307:     bug("%s: INM - Unknown event?", p->p.name);
        !           308:     break;
        !           309:   }
        !           310: }
        !           311: 
        !           312: static int
        !           313: can_do_adj(struct ospf_neighbor *n)
        !           314: {
        !           315:   struct ospf_iface *ifa = n->ifa;
        !           316:   struct ospf_proto *p = ifa->oa->po;
        !           317:   int i = 0;
        !           318: 
        !           319:   switch (ifa->type)
        !           320:   {
        !           321:   case OSPF_IT_PTP:
        !           322:   case OSPF_IT_PTMP:
        !           323:   case OSPF_IT_VLINK:
        !           324:     i = 1;
        !           325:     break;
        !           326:   case OSPF_IT_BCAST:
        !           327:   case OSPF_IT_NBMA:
        !           328:     switch (ifa->state)
        !           329:     {
        !           330:     case OSPF_IS_DOWN:
        !           331:     case OSPF_IS_LOOP:
        !           332:       bug("%s: Iface %s in down state?", p->p.name, ifa->ifname);
        !           333:       break;
        !           334:     case OSPF_IS_WAITING:
        !           335:       DBG("%s: Neighbor? on iface %s\n", p->p.name, ifa->ifname);
        !           336:       break;
        !           337:     case OSPF_IS_DROTHER:
        !           338:       if (((n->rid == ifa->drid) || (n->rid == ifa->bdrid))
        !           339:          && (n->state >= NEIGHBOR_2WAY))
        !           340:        i = 1;
        !           341:       break;
        !           342:     case OSPF_IS_PTP:
        !           343:     case OSPF_IS_BACKUP:
        !           344:     case OSPF_IS_DR:
        !           345:       if (n->state >= NEIGHBOR_2WAY)
        !           346:        i = 1;
        !           347:       break;
        !           348:     default:
        !           349:       bug("%s: Iface %s in unknown state?", p->p.name, ifa->ifname);
        !           350:       break;
        !           351:     }
        !           352:     break;
        !           353:   default:
        !           354:     bug("%s: Iface %s is unknown type?", p->p.name, ifa->ifname);
        !           355:     break;
        !           356:   }
        !           357:   DBG("%s: Iface %s can_do_adj=%d\n", p->p.name, ifa->ifname, i);
        !           358:   return i;
        !           359: }
        !           360: 
        !           361: 
        !           362: static inline u32 neigh_get_id(struct ospf_proto *p UNUSED4 UNUSED6, struct ospf_neighbor *n)
        !           363: { return ospf_is_v2(p) ? ipa_to_u32(n->ip) : n->rid; }
        !           364: 
        !           365: static struct ospf_neighbor *
        !           366: elect_bdr(struct ospf_proto *p, list nl)
        !           367: {
        !           368:   struct ospf_neighbor *neigh, *n1, *n2;
        !           369:   u32 nid;
        !           370: 
        !           371:   n1 = NULL;
        !           372:   n2 = NULL;
        !           373:   WALK_LIST(neigh, nl)                 /* First try those decl. themselves */
        !           374:   {
        !           375:     nid = neigh_get_id(p, neigh);
        !           376: 
        !           377:     if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
        !           378:       if (neigh->priority > 0)         /* Eligible */
        !           379:        if (neigh->dr != nid)           /* And not decl. itself DR */
        !           380:        {
        !           381:          if (neigh->bdr == nid)        /* Declaring BDR */
        !           382:          {
        !           383:            if (n1 != NULL)
        !           384:            {
        !           385:              if (neigh->priority > n1->priority)
        !           386:                n1 = neigh;
        !           387:              else if (neigh->priority == n1->priority)
        !           388:                if (neigh->rid > n1->rid)
        !           389:                  n1 = neigh;
        !           390:            }
        !           391:            else
        !           392:            {
        !           393:              n1 = neigh;
        !           394:            }
        !           395:          }
        !           396:          else                  /* And NOT declaring BDR */
        !           397:          {
        !           398:            if (n2 != NULL)
        !           399:            {
        !           400:              if (neigh->priority > n2->priority)
        !           401:                n2 = neigh;
        !           402:              else if (neigh->priority == n2->priority)
        !           403:                if (neigh->rid > n2->rid)
        !           404:                  n2 = neigh;
        !           405:            }
        !           406:            else
        !           407:            {
        !           408:              n2 = neigh;
        !           409:            }
        !           410:          }
        !           411:        }
        !           412:   }
        !           413:   if (n1 == NULL)
        !           414:     n1 = n2;
        !           415: 
        !           416:   return (n1);
        !           417: }
        !           418: 
        !           419: static struct ospf_neighbor *
        !           420: elect_dr(struct ospf_proto *p, list nl)
        !           421: {
        !           422:   struct ospf_neighbor *neigh, *n;
        !           423:   u32 nid;
        !           424: 
        !           425:   n = NULL;
        !           426:   WALK_LIST(neigh, nl)                 /* And now DR */
        !           427:   {
        !           428:     nid = neigh_get_id(p, neigh);
        !           429: 
        !           430:     if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
        !           431:       if (neigh->priority > 0)         /* Eligible */
        !           432:        if (neigh->dr == nid)           /* And declaring itself DR */
        !           433:        {
        !           434:          if (n != NULL)
        !           435:          {
        !           436:            if (neigh->priority > n->priority)
        !           437:              n = neigh;
        !           438:            else if (neigh->priority == n->priority)
        !           439:              if (neigh->rid > n->rid)
        !           440:                n = neigh;
        !           441:          }
        !           442:          else
        !           443:          {
        !           444:            n = neigh;
        !           445:          }
        !           446:        }
        !           447:   }
        !           448: 
        !           449:   return (n);
        !           450: }
        !           451: 
        !           452: /**
        !           453:  * ospf_dr_election - (Backup) Designed Router election
        !           454:  * @ifa: actual interface
        !           455:  *
        !           456:  * When the wait timer fires, it is time to elect (Backup) Designated Router.
        !           457:  * Structure describing me is added to this list so every electing router has
        !           458:  * the same list. Backup Designated Router is elected before Designated
        !           459:  * Router. This process is described in 9.4 of RFC 2328. The function is
        !           460:  * supposed to be called only from ospf_iface_sm() as a part of the interface
        !           461:  * state machine.
        !           462:  */
        !           463: void
        !           464: ospf_dr_election(struct ospf_iface *ifa)
        !           465: {
        !           466:   struct ospf_proto *p = ifa->oa->po;
        !           467:   struct ospf_neighbor *neigh, *ndr, *nbdr, me;
        !           468:   u32 myid = p->router_id;
        !           469: 
        !           470:   DBG("(B)DR election.\n");
        !           471: 
        !           472:   me.state = NEIGHBOR_2WAY;
        !           473:   me.rid = myid;
        !           474:   me.priority = ifa->priority;
        !           475:   me.ip = ifa->addr->ip;
        !           476: 
        !           477:   me.dr  = ospf_is_v2(p) ? ipa_to_u32(ifa->drip) : ifa->drid;
        !           478:   me.bdr = ospf_is_v2(p) ? ipa_to_u32(ifa->bdrip) : ifa->bdrid;
        !           479:   me.iface_id = ifa->iface_id;
        !           480: 
        !           481:   add_tail(&ifa->neigh_list, NODE & me);
        !           482: 
        !           483:   nbdr = elect_bdr(p, ifa->neigh_list);
        !           484:   ndr = elect_dr(p, ifa->neigh_list);
        !           485: 
        !           486:   if (ndr == NULL)
        !           487:     ndr = nbdr;
        !           488: 
        !           489:   /* 9.4. (4) */
        !           490:   if (((ifa->drid == myid) && (ndr != &me))
        !           491:       || ((ifa->drid != myid) && (ndr == &me))
        !           492:       || ((ifa->bdrid == myid) && (nbdr != &me))
        !           493:       || ((ifa->bdrid != myid) && (nbdr == &me)))
        !           494:   {
        !           495:     me.dr = ndr ? neigh_get_id(p, ndr) : 0;
        !           496:     me.bdr = nbdr ? neigh_get_id(p, nbdr) : 0;
        !           497: 
        !           498:     nbdr = elect_bdr(p, ifa->neigh_list);
        !           499:     ndr = elect_dr(p, ifa->neigh_list);
        !           500: 
        !           501:     if (ndr == NULL)
        !           502:       ndr = nbdr;
        !           503:   }
        !           504: 
        !           505:   rem_node(NODE & me);
        !           506: 
        !           507: 
        !           508:   u32 old_drid = ifa->drid;
        !           509:   u32 old_bdrid = ifa->bdrid;
        !           510: 
        !           511:   ifa->drid = ndr ? ndr->rid : 0;
        !           512:   ifa->drip = ndr ? ndr->ip  : IPA_NONE;
        !           513:   ifa->dr_iface_id = ndr ? ndr->iface_id : 0;
        !           514: 
        !           515:   ifa->bdrid = nbdr ? nbdr->rid : 0;
        !           516:   ifa->bdrip = nbdr ? nbdr->ip  : IPA_NONE;
        !           517: 
        !           518:   DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid);
        !           519: 
        !           520:   /* We are part of the interface state machine */
        !           521:   if (ifa->drid == myid)
        !           522:     ospf_iface_chstate(ifa, OSPF_IS_DR);
        !           523:   else if (ifa->bdrid == myid)
        !           524:     ospf_iface_chstate(ifa, OSPF_IS_BACKUP);
        !           525:   else
        !           526:     ospf_iface_chstate(ifa, OSPF_IS_DROTHER);
        !           527: 
        !           528:   /* Review neighbor adjacencies if DR or BDR changed */
        !           529:   if ((ifa->drid != old_drid) || (ifa->bdrid != old_bdrid))
        !           530:     WALK_LIST(neigh, ifa->neigh_list)
        !           531:       if (neigh->state >= NEIGHBOR_2WAY)
        !           532:        ospf_neigh_sm(neigh, INM_ADJOK);
        !           533: 
        !           534:   /* RFC 2328 12.4 Event 3 - DR change */
        !           535:   if (ifa->drid != old_drid)
        !           536:     ospf_notify_rt_lsa(ifa->oa);
        !           537: }
        !           538: 
        !           539: struct ospf_neighbor *
        !           540: find_neigh(struct ospf_iface *ifa, u32 rid)
        !           541: {
        !           542:   struct ospf_neighbor *n;
        !           543:   WALK_LIST(n, ifa->neigh_list)
        !           544:     if (n->rid == rid)
        !           545:       return n;
        !           546:   return NULL;
        !           547: }
        !           548: 
        !           549: struct ospf_neighbor *
        !           550: find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip)
        !           551: {
        !           552:   struct ospf_neighbor *n;
        !           553:   WALK_LIST(n, ifa->neigh_list)
        !           554:     if (ipa_equal(n->ip, ip))
        !           555:       return n;
        !           556:   return NULL;
        !           557: }
        !           558: 
        !           559: static void
        !           560: inactivity_timer_hook(timer * timer)
        !           561: {
        !           562:   struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
        !           563:   struct ospf_proto *p = n->ifa->oa->po;
        !           564: 
        !           565:   OSPF_TRACE(D_EVENTS, "Inactivity timer expired for nbr %R on %s",
        !           566:             n->rid, n->ifa->ifname);
        !           567:   ospf_neigh_sm(n, INM_INACTTIM);
        !           568: }
        !           569: 
        !           570: static void
        !           571: ospf_neigh_bfd_hook(struct bfd_request *req)
        !           572: {
        !           573:   struct ospf_neighbor *n = req->data;
        !           574:   struct ospf_proto *p = n->ifa->oa->po;
        !           575: 
        !           576:   if (req->down)
        !           577:   {
        !           578:     OSPF_TRACE(D_EVENTS, "BFD session down for nbr %R on %s",
        !           579:               n->rid, n->ifa->ifname);
        !           580:     ospf_neigh_sm(n, INM_INACTTIM);
        !           581:   }
        !           582: }
        !           583: 
        !           584: void
        !           585: ospf_neigh_update_bfd(struct ospf_neighbor *n, int use_bfd)
        !           586: {
        !           587:   if (use_bfd && !n->bfd_req)
        !           588:     n->bfd_req = bfd_request_session(n->pool, n->ip, n->ifa->addr->ip, n->ifa->iface,
        !           589:                                     ospf_neigh_bfd_hook, n);
        !           590: 
        !           591:   if (!use_bfd && n->bfd_req)
        !           592:   {
        !           593:     rfree(n->bfd_req);
        !           594:     n->bfd_req = NULL;
        !           595:   }
        !           596: }
        !           597: 
        !           598: 
        !           599: static void
        !           600: dbdes_timer_hook(timer *t)
        !           601: {
        !           602:   struct ospf_neighbor *n = t->data;
        !           603:   struct ospf_proto *p = n->ifa->oa->po;
        !           604: 
        !           605:   // OSPF_TRACE(D_EVENTS, "DBDES timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
        !           606: 
        !           607:   if (n->state == NEIGHBOR_EXSTART)
        !           608:     ospf_send_dbdes(p, n);
        !           609: 
        !           610:   if ((n->state == NEIGHBOR_EXCHANGE) && (n->myimms & DBDES_MS))
        !           611:     ospf_rxmt_dbdes(p, n);
        !           612: }
        !           613: 
        !           614: static void
        !           615: lsrq_timer_hook(timer *t)
        !           616: {
        !           617:   struct ospf_neighbor *n = t->data;
        !           618:   struct ospf_proto *p = n->ifa->oa->po;
        !           619: 
        !           620:   // OSPF_TRACE(D_EVENTS, "LSRQ timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
        !           621: 
        !           622:   if ((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrql))
        !           623:     ospf_send_lsreq(p, n);
        !           624: }
        !           625: 
        !           626: static void
        !           627: lsrt_timer_hook(timer *t)
        !           628: {
        !           629:   struct ospf_neighbor *n = t->data;
        !           630:   struct ospf_proto *p = n->ifa->oa->po;
        !           631: 
        !           632:   // OSPF_TRACE(D_EVENTS, "LSRT timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
        !           633: 
        !           634:   if ((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrtl))
        !           635:     ospf_rxmt_lsupd(p, n);
        !           636: }
        !           637: 
        !           638: static void
        !           639: ackd_timer_hook(timer *t)
        !           640: {
        !           641:   struct ospf_neighbor *n = t->data;
        !           642:   struct ospf_proto *p = n->ifa->oa->po;
        !           643: 
        !           644:   ospf_send_lsack(p, n, ACKL_DELAY);
        !           645: }
        !           646: 
        !           647: 
        !           648: void
        !           649: ospf_sh_neigh_info(struct ospf_neighbor *n)
        !           650: {
        !           651:   struct ospf_iface *ifa = n->ifa;
        !           652:   char *pos = "PtP  ";
        !           653:   char etime[6];
        !           654:   int exp, sec, min;
        !           655: 
        !           656:   exp = n->inactim->expires - now;
        !           657:   sec = exp % 60;
        !           658:   min = exp / 60;
        !           659:   if (min > 59)
        !           660:   {
        !           661:     bsprintf(etime, "-Inf-");
        !           662:   }
        !           663:   else
        !           664:   {
        !           665:     bsprintf(etime, "%02u:%02u", min, sec);
        !           666:   }
        !           667: 
        !           668:   if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
        !           669:   {
        !           670:     if (n->rid == ifa->drid)
        !           671:       pos = "DR   ";
        !           672:     else if (n->rid == ifa->bdrid)
        !           673:       pos = "BDR  ";
        !           674:     else
        !           675:       pos = "Other";
        !           676:   }
        !           677: 
        !           678:   cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority,
        !           679:          ospf_ns_names[n->state], pos, etime, ifa->ifname, n->ip);
        !           680: }

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