Annotation of embedaddon/bird2/proto/ospf/neighbor.c, revision 1.1.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: static void ospf_neigh_stop_graceful_restart_(struct ospf_neighbor *n);
                     32: static void graceful_restart_timeout(timer *t);
                     33: 
                     34: 
                     35: static void
                     36: init_lists(struct ospf_proto *p, struct ospf_neighbor *n)
                     37: {
                     38:   s_init_list(&(n->lsrql));
                     39:   n->lsrqi = SHEAD(n->lsrql);
                     40:   n->lsrqh = ospf_top_new(p, n->pool);
                     41: 
                     42:   s_init_list(&(n->lsrtl));
                     43:   n->lsrth = ospf_top_new(p, n->pool);
                     44: }
                     45: 
                     46: static void
                     47: release_lsrtl(struct ospf_proto *p, struct ospf_neighbor *n)
                     48: {
                     49:   struct top_hash_entry *ret, *en;
                     50: 
                     51:   WALK_SLIST(ret, n->lsrtl)
                     52:   {
                     53:     en = ospf_hash_find_entry(p->gr, ret);
                     54:     if (en)
                     55:       en->ret_count--;
                     56:   }
                     57: }
                     58: 
                     59: /* Resets LSA request and retransmit lists.
                     60:  * We do not reset DB summary list iterator here,
                     61:  * it is reset during entering EXCHANGE state.
                     62:  */
                     63: static void
                     64: reset_lists(struct ospf_proto *p, struct ospf_neighbor *n)
                     65: {
                     66:   release_lsrtl(p, n);
                     67:   ospf_top_free(n->lsrqh);
                     68:   ospf_top_free(n->lsrth);
                     69:   ospf_reset_lsack_queue(n);
                     70: 
                     71:   tm_stop(n->dbdes_timer);
                     72:   tm_stop(n->lsrq_timer);
                     73:   tm_stop(n->lsrt_timer);
                     74:   tm_stop(n->ackd_timer);
                     75: 
                     76:   init_lists(p, n);
                     77: }
                     78: 
                     79: struct ospf_neighbor *
                     80: ospf_neighbor_new(struct ospf_iface *ifa)
                     81: {
                     82:   struct ospf_proto *p = ifa->oa->po;
                     83:   struct pool *pool = rp_new(p->p.pool, "OSPF Neighbor");
                     84:   struct ospf_neighbor *n = mb_allocz(pool, sizeof(struct ospf_neighbor));
                     85: 
                     86:   n->pool = pool;
                     87:   n->ifa = ifa;
                     88:   add_tail(&ifa->neigh_list, NODE n);
                     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_init(pool, inactivity_timer_hook, n, 0, 0);
                     98:   n->dbdes_timer = tm_new_init(pool, dbdes_timer_hook, n, ifa->rxmtint S, 0);
                     99:   n->lsrq_timer = tm_new_init(pool, lsrq_timer_hook, n, ifa->rxmtint S, 0);
                    100:   n->lsrt_timer = tm_new_init(pool, lsrt_timer_hook, n, ifa->rxmtint S, 0);
                    101:   n->ackd_timer = tm_new_init(pool, ackd_timer_hook, n, ifa->rxmtint S / 2, 0);
                    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) && !n->gr_active)
                    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 attempt */
                    182:     if (old_state < NEIGHBOR_EXSTART)
                    183:       n->dds = random_u32();
                    184: 
                    185:     n->dds++;
                    186:     n->myimms = DBDES_IMMS;
                    187:     n->got_my_rt_lsa = 0;
                    188: 
                    189:     tm_start(n->dbdes_timer, 0);
                    190:     tm_start(n->ackd_timer, ifa->rxmtint S / 2);
                    191:   }
                    192: 
                    193:   if (state > NEIGHBOR_EXSTART)
                    194:     n->myimms &= ~DBDES_I;
                    195: 
                    196:   /* Generate NeighborChange event if needed, see RFC 2328 9.2 */
                    197:   if ((state == NEIGHBOR_2WAY) && (old_state < NEIGHBOR_2WAY) && !n->gr_active)
                    198:     ospf_iface_sm(ifa, ISM_NEICH);
                    199:   if ((state < NEIGHBOR_2WAY) && (old_state >= NEIGHBOR_2WAY) && !n->gr_active)
                    200:     ospf_iface_sm(ifa, ISM_NEICH);
                    201: }
                    202: 
                    203: /**
                    204:  * ospf_neigh_sm - ospf neighbor state machine
                    205:  * @n: neighor
                    206:  * @event: actual event
                    207:  *
                    208:  * This part implements the neighbor state machine as described in 10.3 of
                    209:  * RFC 2328. The only difference is that state %NEIGHBOR_ATTEMPT is not
                    210:  * used. We discover neighbors on nonbroadcast networks in the
                    211:  * same way as on broadcast networks. The only difference is in
                    212:  * sending hello packets. These are sent to IPs listed in
                    213:  * @ospf_iface->nbma_list .
                    214:  */
                    215: void
                    216: ospf_neigh_sm(struct ospf_neighbor *n, int event)
                    217: {
                    218:   struct ospf_proto *p = n->ifa->oa->po;
                    219: 
                    220:   DBG("Neighbor state machine for %R on %s, event %s\n",
                    221:       n->rid, n->ifa->ifname, ospf_inm_names[event]);
                    222: 
                    223:   switch (event)
                    224:   {
                    225:   case INM_START:
                    226:     ospf_neigh_chstate(n, NEIGHBOR_ATTEMPT);
                    227:     /* NBMA are used different way */
                    228:     break;
                    229: 
                    230:   case INM_HELLOREC:
                    231:     if (n->state < NEIGHBOR_INIT)
                    232:       ospf_neigh_chstate(n, NEIGHBOR_INIT);
                    233: 
                    234:     /* Restart inactivity timer */
                    235:     tm_start(n->inactim, n->ifa->deadint S);
                    236:     break;
                    237: 
                    238:   case INM_2WAYREC:
                    239:     if (n->state < NEIGHBOR_2WAY)
                    240:       ospf_neigh_chstate(n, NEIGHBOR_2WAY);
                    241:     if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
                    242:       ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
                    243:     break;
                    244: 
                    245:   case INM_NEGDONE:
                    246:     if (n->state == NEIGHBOR_EXSTART)
                    247:     {
                    248:       ospf_neigh_chstate(n, NEIGHBOR_EXCHANGE);
                    249: 
                    250:       /* Reset DB summary list iterator */
                    251:       s_get(&(n->dbsi));
                    252:       s_init(&(n->dbsi), &p->lsal);
                    253: 
                    254:       /* Add MaxAge LSA entries to retransmission list */
                    255:       ospf_add_flushed_to_lsrt(p, n);
                    256:     }
                    257:     else
                    258:       bug("NEGDONE and I'm not in EXSTART?");
                    259:     break;
                    260: 
                    261:   case INM_EXDONE:
                    262:     if (!EMPTY_SLIST(n->lsrql))
                    263:       ospf_neigh_chstate(n, NEIGHBOR_LOADING);
                    264:     else
                    265:       ospf_neigh_chstate(n, NEIGHBOR_FULL);
                    266:     break;
                    267: 
                    268:   case INM_LOADDONE:
                    269:     ospf_neigh_chstate(n, NEIGHBOR_FULL);
                    270:     break;
                    271: 
                    272:   case INM_ADJOK:
                    273:     /* Can In build adjacency? */
                    274:     if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
                    275:     {
                    276:       ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
                    277:     }
                    278:     else if ((n->state >= NEIGHBOR_EXSTART) && !can_do_adj(n))
                    279:     {
                    280:       reset_lists(p, n);
                    281:       ospf_neigh_chstate(n, NEIGHBOR_2WAY);
                    282:     }
                    283:     break;
                    284: 
                    285:   case INM_SEQMIS:
                    286:   case INM_BADLSREQ:
                    287:     if (n->state >= NEIGHBOR_EXCHANGE)
                    288:     {
                    289:       reset_lists(p, n);
                    290:       ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
                    291:     }
                    292:     break;
                    293: 
                    294:   case INM_KILLNBR:
                    295:   case INM_LLDOWN:
                    296:   case INM_INACTTIM:
                    297:     if (n->gr_active && (event == INM_INACTTIM))
                    298:     {
                    299:       /* Just down the neighbor, but do not remove it */
                    300:       reset_lists(p, n);
                    301:       ospf_neigh_chstate(n, NEIGHBOR_DOWN);
                    302:       break;
                    303:     }
                    304: 
                    305:     if (n->gr_active)
                    306:       ospf_neigh_stop_graceful_restart_(n);
                    307: 
                    308:     /* No need for reset_lists() */
                    309:     ospf_neigh_chstate(n, NEIGHBOR_DOWN);
                    310:     ospf_neigh_down(n);
                    311:     break;
                    312: 
                    313:   case INM_1WAYREC:
                    314:     reset_lists(p, n);
                    315:     ospf_neigh_chstate(n, NEIGHBOR_INIT);
                    316:     break;
                    317: 
                    318:   default:
                    319:     bug("%s: INM - Unknown event?", p->p.name);
                    320:     break;
                    321:   }
                    322: }
                    323: 
                    324: static int
                    325: can_do_adj(struct ospf_neighbor *n)
                    326: {
                    327:   struct ospf_iface *ifa = n->ifa;
                    328:   struct ospf_proto *p = ifa->oa->po;
                    329:   int i = 0;
                    330: 
                    331:   switch (ifa->type)
                    332:   {
                    333:   case OSPF_IT_PTP:
                    334:   case OSPF_IT_PTMP:
                    335:   case OSPF_IT_VLINK:
                    336:     i = 1;
                    337:     break;
                    338:   case OSPF_IT_BCAST:
                    339:   case OSPF_IT_NBMA:
                    340:     switch (ifa->state)
                    341:     {
                    342:     case OSPF_IS_DOWN:
                    343:     case OSPF_IS_LOOP:
                    344:       bug("%s: Iface %s in down state?", p->p.name, ifa->ifname);
                    345:       break;
                    346:     case OSPF_IS_WAITING:
                    347:       DBG("%s: Neighbor? on iface %s\n", p->p.name, ifa->ifname);
                    348:       break;
                    349:     case OSPF_IS_DROTHER:
                    350:       if (((n->rid == ifa->drid) || (n->rid == ifa->bdrid))
                    351:          && (n->state >= NEIGHBOR_2WAY))
                    352:        i = 1;
                    353:       break;
                    354:     case OSPF_IS_PTP:
                    355:     case OSPF_IS_BACKUP:
                    356:     case OSPF_IS_DR:
                    357:       if (n->state >= NEIGHBOR_2WAY)
                    358:        i = 1;
                    359:       break;
                    360:     default:
                    361:       bug("%s: Iface %s in unknown state?", p->p.name, ifa->ifname);
                    362:       break;
                    363:     }
                    364:     break;
                    365:   default:
                    366:     bug("%s: Iface %s is unknown type?", p->p.name, ifa->ifname);
                    367:     break;
                    368:   }
                    369:   DBG("%s: Iface %s can_do_adj=%d\n", p->p.name, ifa->ifname, i);
                    370:   return i;
                    371: }
                    372: 
                    373: static void
                    374: ospf_neigh_start_graceful_restart(struct ospf_neighbor *n, uint gr_time)
                    375: {
                    376:   struct ospf_proto *p = n->ifa->oa->po;
                    377: 
                    378:   OSPF_TRACE(D_EVENTS, "Neighbor %R on %s started graceful restart",
                    379:             n->rid, n->ifa->ifname);
                    380: 
                    381:   n->gr_active = 1;
                    382:   p->gr_count++;
                    383: 
                    384:   n->gr_timer = tm_new_init(n->pool, graceful_restart_timeout, n, 0, 0);
                    385:   tm_start(n->gr_timer, gr_time S);
                    386: }
                    387: 
                    388: static void
                    389: ospf_neigh_stop_graceful_restart_(struct ospf_neighbor *n)
                    390: {
                    391:   struct ospf_proto *p = n->ifa->oa->po;
                    392:   struct ospf_iface *ifa = n->ifa;
                    393: 
                    394:   n->gr_active = 0;
                    395:   p->gr_count--;
                    396: 
                    397:   rfree(n->gr_timer);
                    398:   n->gr_timer = NULL;
                    399: 
                    400:   ospf_notify_rt_lsa(ifa->oa);
                    401:   ospf_notify_net_lsa(ifa);
                    402: 
                    403:   if (ifa->type == OSPF_IT_VLINK)
                    404:     ospf_notify_rt_lsa(ifa->voa);
                    405: 
                    406:   ospf_iface_sm(ifa, ISM_NEICH);
                    407: }
                    408: 
                    409: static void
                    410: ospf_neigh_stop_graceful_restart(struct ospf_neighbor *n)
                    411: {
                    412:   struct ospf_proto *p = n->ifa->oa->po;
                    413: 
                    414:   OSPF_TRACE(D_EVENTS, "Neighbor %R on %s finished graceful restart",
                    415:             n->rid, n->ifa->ifname);
                    416: 
                    417:   ospf_neigh_stop_graceful_restart_(n);
                    418: }
                    419: 
                    420: void
                    421: ospf_neigh_cancel_graceful_restart(struct ospf_neighbor *n)
                    422: {
                    423:   struct ospf_proto *p = n->ifa->oa->po;
                    424: 
                    425:   OSPF_TRACE(D_EVENTS, "Graceful restart canceled for nbr %R on %s",
                    426:             n->rid, n->ifa->ifname);
                    427: 
                    428:   ospf_neigh_stop_graceful_restart_(n);
                    429: 
                    430:   if (n->state == NEIGHBOR_DOWN)
                    431:     ospf_neigh_down(n);
                    432: }
                    433: 
                    434: static void
                    435: graceful_restart_timeout(timer *t)
                    436: {
                    437:   struct ospf_neighbor *n = t->data;
                    438:   struct ospf_proto *p = n->ifa->oa->po;
                    439: 
                    440:   OSPF_TRACE(D_EVENTS, "Graceful restart timer expired for nbr %R on %s",
                    441:             n->rid, n->ifa->ifname);
                    442: 
                    443:   ospf_neigh_stop_graceful_restart_(n);
                    444: 
                    445:   if (n->state == NEIGHBOR_DOWN)
                    446:     ospf_neigh_down(n);
                    447: }
                    448: 
                    449: static inline int
                    450: changes_in_lsrtl(struct ospf_neighbor *n)
                    451: {
                    452:   /* This could be improved, see RFC 3623 3.1 (2) */
                    453: 
                    454:   struct top_hash_entry *en;
                    455:   WALK_SLIST(en, n->lsrtl)
                    456:     if (LSA_FUNCTION(en->lsa_type) <= LSA_FUNCTION(LSA_T_NSSA))
                    457:       return 1;
                    458: 
                    459:   return 0;
                    460: }
                    461: 
                    462: void
                    463: ospf_neigh_notify_grace_lsa(struct ospf_neighbor *n, struct top_hash_entry *en)
                    464: {
                    465:   struct ospf_iface *ifa = n->ifa;
                    466:   struct ospf_proto *p = ifa->oa->po;
                    467: 
                    468:   /* In OSPFv2, neighbors are identified by either IP or Router ID, based on network type */
                    469:   uint t = ifa->type;
                    470:   if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP)))
                    471:   {
                    472:     struct ospf_tlv *tlv = lsa_get_tlv(en, LSA_GR_ADDRESS);
                    473:     if (!tlv || tlv->length != 4)
                    474:       return;
                    475: 
                    476:     ip_addr addr = ipa_from_u32(tlv->data[0]);
                    477:     if (!ipa_equal(n->ip, addr))
                    478:       n = find_neigh_by_ip(ifa, addr);
                    479:   }
                    480:   else
                    481:   {
                    482:     if (n->rid != en->lsa.rt)
                    483:       n = find_neigh(ifa, en->lsa.rt);
                    484:   }
                    485: 
                    486:   if (!n)
                    487:     return;
                    488: 
                    489:   if (en->lsa.age < LSA_MAXAGE)
                    490:   {
                    491:     u32 period = lsa_get_tlv_u32(en, LSA_GR_PERIOD);
                    492: 
                    493:     /* Exception for updating grace period */
                    494:     if (n->gr_active)
                    495:     {
                    496:       tm_start(n->gr_timer, (period S) - (en->lsa.age S));
                    497:       return;
                    498:     }
                    499: 
                    500:     /* RFC 3623 3.1 (1) - full adjacency */
                    501:     if (n->state != NEIGHBOR_FULL)
                    502:       return;
                    503: 
                    504:     /* RFC 3623 3.1 (2) - no changes in LSADB */
                    505:     if (changes_in_lsrtl(n))
                    506:       return;
                    507: 
                    508:     /* RFC 3623 3.1 (3) - grace period not expired */
                    509:     if (en->lsa.age >= period)
                    510:       return;
                    511: 
                    512:     /* RFC 3623 3.1 (4) - helper mode allowed */
                    513:     if (!p->gr_mode)
                    514:       return;
                    515: 
                    516:     /* RFC 3623 3.1 (5) - no local graceful restart */
                    517:     if (p->p.gr_recovery)
                    518:       return;
                    519: 
                    520:     ospf_neigh_start_graceful_restart(n, period - en->lsa.age);
                    521:   }
                    522:   else /* Grace-LSA is flushed */
                    523:   {
                    524:     if (n->gr_active)
                    525:       ospf_neigh_stop_graceful_restart(n);
                    526:   }
                    527: }
                    528: 
                    529: void
                    530: ospf_neigh_lsadb_changed_(struct ospf_proto *p, struct top_hash_entry *en)
                    531: {
                    532:   struct ospf_iface *ifa;
                    533:   struct ospf_neighbor *n, *nx;
                    534: 
                    535:   if (LSA_FUNCTION(en->lsa_type) > LSA_FUNCTION(LSA_T_NSSA))
                    536:     return;
                    537: 
                    538:   /* RFC 3623 3.2 (3) - cancel graceful restart when LSdb changed */
                    539:   WALK_LIST(ifa, p->iface_list)
                    540:     if (lsa_flooding_allowed(en->lsa_type, en->domain, ifa))
                    541:       WALK_LIST_DELSAFE(n, nx, ifa->neigh_list)
                    542:        if (n->gr_active)
                    543:          ospf_neigh_cancel_graceful_restart(n);
                    544: }
                    545: 
                    546: 
                    547: 
                    548: static inline u32 neigh_get_id(struct ospf_proto *p, struct ospf_neighbor *n)
                    549: { return ospf_is_v2(p) ? ipa_to_u32(n->ip) : n->rid; }
                    550: 
                    551: static struct ospf_neighbor *
                    552: elect_bdr(struct ospf_proto *p, list nl)
                    553: {
                    554:   struct ospf_neighbor *neigh, *n1, *n2;
                    555:   u32 nid;
                    556: 
                    557:   n1 = NULL;
                    558:   n2 = NULL;
                    559:   WALK_LIST(neigh, nl)                 /* First try those decl. themselves */
                    560:   {
                    561:     nid = neigh_get_id(p, neigh);
                    562: 
                    563:     if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
                    564:       if (neigh->priority > 0)         /* Eligible */
                    565:        if (neigh->dr != nid)           /* And not decl. itself DR */
                    566:        {
                    567:          if (neigh->bdr == nid)        /* Declaring BDR */
                    568:          {
                    569:            if (n1 != NULL)
                    570:            {
                    571:              if (neigh->priority > n1->priority)
                    572:                n1 = neigh;
                    573:              else if (neigh->priority == n1->priority)
                    574:                if (neigh->rid > n1->rid)
                    575:                  n1 = neigh;
                    576:            }
                    577:            else
                    578:            {
                    579:              n1 = neigh;
                    580:            }
                    581:          }
                    582:          else                  /* And NOT declaring BDR */
                    583:          {
                    584:            if (n2 != NULL)
                    585:            {
                    586:              if (neigh->priority > n2->priority)
                    587:                n2 = neigh;
                    588:              else if (neigh->priority == n2->priority)
                    589:                if (neigh->rid > n2->rid)
                    590:                  n2 = neigh;
                    591:            }
                    592:            else
                    593:            {
                    594:              n2 = neigh;
                    595:            }
                    596:          }
                    597:        }
                    598:   }
                    599:   if (n1 == NULL)
                    600:     n1 = n2;
                    601: 
                    602:   return (n1);
                    603: }
                    604: 
                    605: static struct ospf_neighbor *
                    606: elect_dr(struct ospf_proto *p, list nl)
                    607: {
                    608:   struct ospf_neighbor *neigh, *n;
                    609:   u32 nid;
                    610: 
                    611:   n = NULL;
                    612:   WALK_LIST(neigh, nl)                 /* And now DR */
                    613:   {
                    614:     nid = neigh_get_id(p, neigh);
                    615: 
                    616:     if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
                    617:       if (neigh->priority > 0)         /* Eligible */
                    618:        if (neigh->dr == nid)           /* And declaring itself DR */
                    619:        {
                    620:          if (n != NULL)
                    621:          {
                    622:            if (neigh->priority > n->priority)
                    623:              n = neigh;
                    624:            else if (neigh->priority == n->priority)
                    625:              if (neigh->rid > n->rid)
                    626:                n = neigh;
                    627:          }
                    628:          else
                    629:          {
                    630:            n = neigh;
                    631:          }
                    632:        }
                    633:   }
                    634: 
                    635:   return (n);
                    636: }
                    637: 
                    638: /**
                    639:  * ospf_dr_election - (Backup) Designed Router election
                    640:  * @ifa: actual interface
                    641:  *
                    642:  * When the wait timer fires, it is time to elect (Backup) Designated Router.
                    643:  * Structure describing me is added to this list so every electing router has
                    644:  * the same list. Backup Designated Router is elected before Designated
                    645:  * Router. This process is described in 9.4 of RFC 2328. The function is
                    646:  * supposed to be called only from ospf_iface_sm() as a part of the interface
                    647:  * state machine.
                    648:  */
                    649: void
                    650: ospf_dr_election(struct ospf_iface *ifa)
                    651: {
                    652:   struct ospf_proto *p = ifa->oa->po;
                    653:   struct ospf_neighbor *neigh, *ndr, *nbdr, me;
                    654:   u32 myid = p->router_id;
                    655: 
                    656:   DBG("(B)DR election.\n");
                    657: 
                    658:   me.state = NEIGHBOR_2WAY;
                    659:   me.rid = myid;
                    660:   me.priority = ifa->priority;
                    661:   me.ip = ifa->addr->ip;
                    662: 
                    663:   me.dr  = ospf_is_v2(p) ? ipa_to_u32(ifa->drip) : ifa->drid;
                    664:   me.bdr = ospf_is_v2(p) ? ipa_to_u32(ifa->bdrip) : ifa->bdrid;
                    665:   me.iface_id = ifa->iface_id;
                    666: 
                    667:   add_tail(&ifa->neigh_list, NODE & me);
                    668: 
                    669:   nbdr = elect_bdr(p, ifa->neigh_list);
                    670:   ndr = elect_dr(p, ifa->neigh_list);
                    671: 
                    672:   if (ndr == NULL)
                    673:     ndr = nbdr;
                    674: 
                    675:   /* 9.4. (4) */
                    676:   if (((ifa->drid == myid) && (ndr != &me))
                    677:       || ((ifa->drid != myid) && (ndr == &me))
                    678:       || ((ifa->bdrid == myid) && (nbdr != &me))
                    679:       || ((ifa->bdrid != myid) && (nbdr == &me)))
                    680:   {
                    681:     me.dr = ndr ? neigh_get_id(p, ndr) : 0;
                    682:     me.bdr = nbdr ? neigh_get_id(p, nbdr) : 0;
                    683: 
                    684:     nbdr = elect_bdr(p, ifa->neigh_list);
                    685:     ndr = elect_dr(p, ifa->neigh_list);
                    686: 
                    687:     if (ndr == NULL)
                    688:       ndr = nbdr;
                    689:   }
                    690: 
                    691:   rem_node(NODE & me);
                    692: 
                    693: 
                    694:   u32 old_drid = ifa->drid;
                    695:   u32 old_bdrid = ifa->bdrid;
                    696:   ip_addr none = ospf_is_v2(p) ? IPA_NONE4 : IPA_NONE6;
                    697: 
                    698:   ifa->drid = ndr ? ndr->rid : 0;
                    699:   ifa->drip = ndr ? ndr->ip  : none;
                    700:   ifa->dr_iface_id = ndr ? ndr->iface_id : 0;
                    701: 
                    702:   ifa->bdrid = nbdr ? nbdr->rid : 0;
                    703:   ifa->bdrip = nbdr ? nbdr->ip  : none;
                    704: 
                    705:   DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid);
                    706: 
                    707:   /* We are part of the interface state machine */
                    708:   if (ifa->drid == myid)
                    709:     ospf_iface_chstate(ifa, OSPF_IS_DR);
                    710:   else if (ifa->bdrid == myid)
                    711:     ospf_iface_chstate(ifa, OSPF_IS_BACKUP);
                    712:   else
                    713:     ospf_iface_chstate(ifa, OSPF_IS_DROTHER);
                    714: 
                    715:   /* Review neighbor adjacencies if DR or BDR changed */
                    716:   if ((ifa->drid != old_drid) || (ifa->bdrid != old_bdrid))
                    717:     WALK_LIST(neigh, ifa->neigh_list)
                    718:       if (neigh->state >= NEIGHBOR_2WAY)
                    719:        ospf_neigh_sm(neigh, INM_ADJOK);
                    720: 
                    721:   /* RFC 2328 12.4 Event 3 - DR change */
                    722:   if (ifa->drid != old_drid)
                    723:     ospf_notify_rt_lsa(ifa->oa);
                    724: }
                    725: 
                    726: struct ospf_neighbor *
                    727: find_neigh(struct ospf_iface *ifa, u32 rid)
                    728: {
                    729:   struct ospf_neighbor *n;
                    730:   WALK_LIST(n, ifa->neigh_list)
                    731:     if (n->rid == rid)
                    732:       return n;
                    733:   return NULL;
                    734: }
                    735: 
                    736: struct ospf_neighbor *
                    737: find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip)
                    738: {
                    739:   struct ospf_neighbor *n;
                    740:   WALK_LIST(n, ifa->neigh_list)
                    741:     if (ipa_equal(n->ip, ip))
                    742:       return n;
                    743:   return NULL;
                    744: }
                    745: 
                    746: static void
                    747: inactivity_timer_hook(timer * timer)
                    748: {
                    749:   struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
                    750:   struct ospf_proto *p = n->ifa->oa->po;
                    751: 
                    752:   OSPF_TRACE(D_EVENTS, "Inactivity timer expired for nbr %R on %s",
                    753:             n->rid, n->ifa->ifname);
                    754:   ospf_neigh_sm(n, INM_INACTTIM);
                    755: }
                    756: 
                    757: static void
                    758: ospf_neigh_bfd_hook(struct bfd_request *req)
                    759: {
                    760:   struct ospf_neighbor *n = req->data;
                    761:   struct ospf_proto *p = n->ifa->oa->po;
                    762: 
                    763:   if (req->down)
                    764:   {
                    765:     OSPF_TRACE(D_EVENTS, "BFD session down for nbr %R on %s",
                    766:               n->rid, n->ifa->ifname);
                    767:     ospf_neigh_sm(n, INM_INACTTIM);
                    768:   }
                    769: }
                    770: 
                    771: void
                    772: ospf_neigh_update_bfd(struct ospf_neighbor *n, int use_bfd)
                    773: {
                    774:   struct ospf_proto *p = n->ifa->oa->po;
                    775: 
                    776:   if (use_bfd && !n->bfd_req)
                    777:     n->bfd_req = bfd_request_session(n->pool, n->ip, n->ifa->addr->ip,
                    778:                                     n->ifa->iface, p->p.vrf,
                    779:                                     ospf_neigh_bfd_hook, n);
                    780: 
                    781:   if (!use_bfd && n->bfd_req)
                    782:   {
                    783:     rfree(n->bfd_req);
                    784:     n->bfd_req = NULL;
                    785:   }
                    786: }
                    787: 
                    788: 
                    789: static void
                    790: dbdes_timer_hook(timer *t)
                    791: {
                    792:   struct ospf_neighbor *n = t->data;
                    793:   struct ospf_proto *p = n->ifa->oa->po;
                    794: 
                    795:   // OSPF_TRACE(D_EVENTS, "DBDES timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
                    796: 
                    797:   if (n->state == NEIGHBOR_EXSTART)
                    798:     ospf_send_dbdes(p, n);
                    799: 
                    800:   if ((n->state == NEIGHBOR_EXCHANGE) && (n->myimms & DBDES_MS))
                    801:     ospf_rxmt_dbdes(p, n);
                    802: 
                    803:   if ((n->state > NEIGHBOR_LOADING) && !(n->myimms & DBDES_MS))
                    804:   {
                    805:     ospf_reset_ldd(p, n);
                    806:     tm_stop(n->dbdes_timer);
                    807:   }
                    808: }
                    809: 
                    810: static void
                    811: lsrq_timer_hook(timer *t)
                    812: {
                    813:   struct ospf_neighbor *n = t->data;
                    814:   struct ospf_proto *p = n->ifa->oa->po;
                    815: 
                    816:   // OSPF_TRACE(D_EVENTS, "LSRQ timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
                    817: 
                    818:   if ((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrql))
                    819:     ospf_send_lsreq(p, n);
                    820: }
                    821: 
                    822: static void
                    823: lsrt_timer_hook(timer *t)
                    824: {
                    825:   struct ospf_neighbor *n = t->data;
                    826:   struct ospf_proto *p = n->ifa->oa->po;
                    827: 
                    828:   // OSPF_TRACE(D_EVENTS, "LSRT timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
                    829: 
                    830:   if ((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrtl))
                    831:     ospf_rxmt_lsupd(p, n);
                    832: }
                    833: 
                    834: static void
                    835: ackd_timer_hook(timer *t)
                    836: {
                    837:   struct ospf_neighbor *n = t->data;
                    838:   struct ospf_proto *p = n->ifa->oa->po;
                    839: 
                    840:   ospf_send_lsack(p, n, ACKL_DELAY);
                    841: }
                    842: 
                    843: 
                    844: void
                    845: ospf_sh_neigh_info(struct ospf_neighbor *n)
                    846: {
                    847:   struct ospf_iface *ifa = n->ifa;
                    848:   char *pos = "PtP  ";
                    849: 
                    850:   if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
                    851:   {
                    852:     if (n->rid == ifa->drid)
                    853:       pos = "DR   ";
                    854:     else if (n->rid == ifa->bdrid)
                    855:       pos = "BDR  ";
                    856:     else
                    857:       pos = "Other";
                    858:   }
                    859: 
                    860:   cli_msg(-1013, "%-12R\t%3u\t%s/%s\t%6t\t%-10s %I",
                    861:          n->rid, n->priority, ospf_ns_names[n->state], pos,
                    862:          tm_remains(n->inactim), ifa->ifname, n->ip);
                    863: }

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