Return to neighbor.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / proto / ospf |
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: }