]>
git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/neighbor.c
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.
8 * Can be freely distributed and used under the terms of the GNU GPL.
14 const char *ospf_ns_names
[] = {
15 "Down", "Attempt", "Init", "2-Way", "ExStart", "Exchange", "Loading", "Full"
18 const char *ospf_inm_names
[] = {
19 "HelloReceived", "Start", "2-WayReceived", "NegotiationDone", "ExchangeDone",
20 "BadLSReq", "LoadingDone", "AdjOK?", "SeqNumberMismatch", "1-WayReceived",
21 "KillNbr", "InactivityTimer", "LLDown"
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
);
36 init_lists(struct ospf_proto
*p
, struct ospf_neighbor
*n
)
38 s_init_list(&(n
->lsrql
));
39 n
->lsrqi
= SHEAD(n
->lsrql
);
40 n
->lsrqh
= ospf_top_new(p
, n
->pool
);
42 s_init_list(&(n
->lsrtl
));
43 n
->lsrth
= ospf_top_new(p
, n
->pool
);
47 release_lsrtl(struct ospf_proto
*p
, struct ospf_neighbor
*n
)
49 struct top_hash_entry
*ret
, *en
;
51 WALK_SLIST(ret
, n
->lsrtl
)
53 en
= ospf_hash_find_entry(p
->gr
, ret
);
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.
64 reset_lists(struct ospf_proto
*p
, struct ospf_neighbor
*n
)
67 ospf_top_free(n
->lsrqh
);
68 ospf_top_free(n
->lsrth
);
69 ospf_reset_lsack_queue(n
);
71 tm_stop(n
->dbdes_timer
);
72 tm_stop(n
->lsrq_timer
);
73 tm_stop(n
->lsrt_timer
);
74 tm_stop(n
->ackd_timer
);
79 struct ospf_neighbor
*
80 ospf_neighbor_new(struct ospf_iface
*ifa
)
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
));
88 add_tail(&ifa
->neigh_list
, NODE n
);
89 n
->state
= NEIGHBOR_DOWN
;
92 s_init(&(n
->dbsi
), &(p
->lsal
));
94 init_list(&n
->ackl
[ACKL_DIRECT
]);
95 init_list(&n
->ackl
[ACKL_DELAY
]);
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);
107 ospf_neigh_down(struct ospf_neighbor
*n
)
109 struct ospf_iface
*ifa
= n
->ifa
;
110 struct ospf_proto
*p
= ifa
->oa
->po
;
113 if ((ifa
->type
== OSPF_IT_NBMA
) || (ifa
->type
== OSPF_IT_PTMP
))
115 struct nbma_node
*nn
= find_nbma_node(ifa
, n
->ip
);
125 OSPF_TRACE(D_EVENTS
, "Neighbor %R on %s removed", rid
, ifa
->ifname
);
129 * ospf_neigh_chstate - handles changes related to new or lod state of neighbor
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.
137 ospf_neigh_chstate(struct ospf_neighbor
*n
, u8 state
)
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
;
144 if (state
== old_state
)
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
]);
152 /* Increase number of partial adjacencies */
153 if ((state
== NEIGHBOR_EXCHANGE
) || (state
== NEIGHBOR_LOADING
))
156 /* Decrease number of partial adjacencies */
157 if ((old_state
== NEIGHBOR_EXCHANGE
) || (old_state
== NEIGHBOR_LOADING
))
160 /* Increase number of full adjacencies */
161 if (state
== NEIGHBOR_FULL
)
164 /* Decrease number of full adjacencies */
165 if (old_state
== NEIGHBOR_FULL
)
168 if ((ifa
->fadj
!= old_fadj
) && !n
->gr_active
)
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
);
174 /* RFC 2328 12.4 Event 8 - vlink state change */
175 if (ifa
->type
== OSPF_IT_VLINK
)
176 ospf_notify_rt_lsa(ifa
->voa
);
179 if (state
== NEIGHBOR_EXSTART
)
181 /* First time adjacency attempt */
182 if (old_state
< NEIGHBOR_EXSTART
)
183 n
->dds
= random_u32();
186 n
->myimms
= DBDES_IMMS
;
187 n
->got_my_rt_lsa
= 0;
189 tm_start(n
->dbdes_timer
, 0);
190 tm_start(n
->ackd_timer
, ifa
->rxmtint S
/ 2);
193 if (state
> NEIGHBOR_EXSTART
)
194 n
->myimms
&= ~DBDES_I
;
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
);
204 * ospf_neigh_sm - ospf neighbor state machine
206 * @event: actual event
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 .
216 ospf_neigh_sm(struct ospf_neighbor
*n
, int event
)
218 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
220 DBG("Neighbor state machine for %R on %s, event %s\n",
221 n
->rid
, n
->ifa
->ifname
, ospf_inm_names
[event
]);
226 ospf_neigh_chstate(n
, NEIGHBOR_ATTEMPT
);
227 /* NBMA are used different way */
231 if (n
->state
< NEIGHBOR_INIT
)
232 ospf_neigh_chstate(n
, NEIGHBOR_INIT
);
234 /* Restart inactivity timer */
235 tm_start(n
->inactim
, n
->ifa
->deadint S
);
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
);
246 if (n
->state
== NEIGHBOR_EXSTART
)
248 ospf_neigh_chstate(n
, NEIGHBOR_EXCHANGE
);
250 /* Reset DB summary list iterator */
252 s_init(&(n
->dbsi
), &p
->lsal
);
254 /* Add MaxAge LSA entries to retransmission list */
255 ospf_add_flushed_to_lsrt(p
, n
);
258 bug("NEGDONE and I'm not in EXSTART?");
262 if (!EMPTY_SLIST(n
->lsrql
))
263 ospf_neigh_chstate(n
, NEIGHBOR_LOADING
);
265 ospf_neigh_chstate(n
, NEIGHBOR_FULL
);
269 ospf_neigh_chstate(n
, NEIGHBOR_FULL
);
273 /* Can In build adjacency? */
274 if ((n
->state
== NEIGHBOR_2WAY
) && can_do_adj(n
))
276 ospf_neigh_chstate(n
, NEIGHBOR_EXSTART
);
278 else if ((n
->state
>= NEIGHBOR_EXSTART
) && !can_do_adj(n
))
281 ospf_neigh_chstate(n
, NEIGHBOR_2WAY
);
287 if (n
->state
>= NEIGHBOR_EXCHANGE
)
290 ospf_neigh_chstate(n
, NEIGHBOR_EXSTART
);
297 if (n
->gr_active
&& (event
== INM_INACTTIM
))
299 /* Just down the neighbor, but do not remove it */
301 ospf_neigh_chstate(n
, NEIGHBOR_DOWN
);
306 ospf_neigh_stop_graceful_restart_(n
);
308 /* No need for reset_lists() */
309 ospf_neigh_chstate(n
, NEIGHBOR_DOWN
);
315 ospf_neigh_chstate(n
, NEIGHBOR_INIT
);
319 bug("%s: INM - Unknown event?", p
->p
.name
);
325 can_do_adj(struct ospf_neighbor
*n
)
327 struct ospf_iface
*ifa
= n
->ifa
;
328 struct ospf_proto
*p
= ifa
->oa
->po
;
344 bug("%s: Iface %s in down state?", p
->p
.name
, ifa
->ifname
);
346 case OSPF_IS_WAITING
:
347 DBG("%s: Neighbor? on iface %s\n", p
->p
.name
, ifa
->ifname
);
349 case OSPF_IS_DROTHER
:
350 if (((n
->rid
== ifa
->drid
) || (n
->rid
== ifa
->bdrid
))
351 && (n
->state
>= NEIGHBOR_2WAY
))
357 if (n
->state
>= NEIGHBOR_2WAY
)
361 bug("%s: Iface %s in unknown state?", p
->p
.name
, ifa
->ifname
);
366 bug("%s: Iface %s is unknown type?", p
->p
.name
, ifa
->ifname
);
369 DBG("%s: Iface %s can_do_adj=%d\n", p
->p
.name
, ifa
->ifname
, i
);
374 ospf_neigh_start_graceful_restart(struct ospf_neighbor
*n
, uint gr_time
)
376 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
378 OSPF_TRACE(D_EVENTS
, "Neighbor %R on %s started graceful restart",
379 n
->rid
, n
->ifa
->ifname
);
384 n
->gr_timer
= tm_new_init(n
->pool
, graceful_restart_timeout
, n
, 0, 0);
385 tm_start(n
->gr_timer
, gr_time S
);
389 ospf_neigh_stop_graceful_restart_(struct ospf_neighbor
*n
)
391 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
392 struct ospf_iface
*ifa
= n
->ifa
;
400 ospf_notify_rt_lsa(ifa
->oa
);
401 ospf_notify_net_lsa(ifa
);
403 if (ifa
->type
== OSPF_IT_VLINK
)
404 ospf_notify_rt_lsa(ifa
->voa
);
406 ospf_iface_sm(ifa
, ISM_NEICH
);
410 ospf_neigh_stop_graceful_restart(struct ospf_neighbor
*n
)
412 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
414 OSPF_TRACE(D_EVENTS
, "Neighbor %R on %s finished graceful restart",
415 n
->rid
, n
->ifa
->ifname
);
417 ospf_neigh_stop_graceful_restart_(n
);
421 ospf_neigh_cancel_graceful_restart(struct ospf_neighbor
*n
)
423 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
425 OSPF_TRACE(D_EVENTS
, "Graceful restart canceled for nbr %R on %s",
426 n
->rid
, n
->ifa
->ifname
);
428 ospf_neigh_stop_graceful_restart_(n
);
430 if (n
->state
== NEIGHBOR_DOWN
)
435 graceful_restart_timeout(timer
*t
)
437 struct ospf_neighbor
*n
= t
->data
;
438 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
440 OSPF_TRACE(D_EVENTS
, "Graceful restart timer expired for nbr %R on %s",
441 n
->rid
, n
->ifa
->ifname
);
443 ospf_neigh_stop_graceful_restart_(n
);
445 if (n
->state
== NEIGHBOR_DOWN
)
450 changes_in_lsrtl(struct ospf_neighbor
*n
)
452 /* This could be improved, see RFC 3623 3.1 (2) */
454 struct top_hash_entry
*en
;
455 WALK_SLIST(en
, n
->lsrtl
)
456 if (LSA_FUNCTION(en
->lsa_type
) <= LSA_FUNCTION(LSA_T_NSSA
))
463 ospf_neigh_notify_grace_lsa(struct ospf_neighbor
*n
, struct top_hash_entry
*en
)
465 struct ospf_iface
*ifa
= n
->ifa
;
466 struct ospf_proto
*p
= ifa
->oa
->po
;
468 /* In OSPFv2, neighbors are identified by either IP or Router ID, based on network type */
470 if (ospf_is_v2(p
) && ((t
== OSPF_IT_BCAST
) || (t
== OSPF_IT_NBMA
) || (t
== OSPF_IT_PTMP
)))
472 struct ospf_tlv
*tlv
= lsa_get_tlv(en
, LSA_GR_ADDRESS
);
473 if (!tlv
|| tlv
->length
!= 4)
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
);
482 if (n
->rid
!= en
->lsa
.rt
)
483 n
= find_neigh(ifa
, en
->lsa
.rt
);
489 if (en
->lsa
.age
< LSA_MAXAGE
)
491 u32 period
= lsa_get_tlv_u32(en
, LSA_GR_PERIOD
);
493 /* Exception for updating grace period */
496 tm_start(n
->gr_timer
, (period S
) - (en
->lsa
.age S
));
500 /* RFC 3623 3.1 (1) - full adjacency */
501 if (n
->state
!= NEIGHBOR_FULL
)
504 /* RFC 3623 3.1 (2) - no changes in LSADB */
505 if (changes_in_lsrtl(n
))
508 /* RFC 3623 3.1 (3) - grace period not expired */
509 if (en
->lsa
.age
>= period
)
512 /* RFC 3623 3.1 (4) - helper mode allowed */
516 /* RFC 3623 3.1 (5) - no local graceful restart */
517 if (p
->p
.gr_recovery
)
520 ospf_neigh_start_graceful_restart(n
, period
- en
->lsa
.age
);
522 else /* Grace-LSA is flushed */
525 ospf_neigh_stop_graceful_restart(n
);
530 ospf_neigh_lsadb_changed_(struct ospf_proto
*p
, struct top_hash_entry
*en
)
532 struct ospf_iface
*ifa
;
533 struct ospf_neighbor
*n
, *nx
;
535 if (LSA_FUNCTION(en
->lsa_type
) > LSA_FUNCTION(LSA_T_NSSA
))
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
)
543 ospf_neigh_cancel_graceful_restart(n
);
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
; }
551 static struct ospf_neighbor
*
552 elect_bdr(struct ospf_proto
*p
, list nl
)
554 struct ospf_neighbor
*neigh
, *n1
, *n2
;
559 WALK_LIST(neigh
, nl
) /* First try those decl. themselves */
561 nid
= neigh_get_id(p
, neigh
);
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 */
567 if (neigh
->bdr
== nid
) /* Declaring BDR */
571 if (neigh
->priority
> n1
->priority
)
573 else if (neigh
->priority
== n1
->priority
)
574 if (neigh
->rid
> n1
->rid
)
582 else /* And NOT declaring BDR */
586 if (neigh
->priority
> n2
->priority
)
588 else if (neigh
->priority
== n2
->priority
)
589 if (neigh
->rid
> n2
->rid
)
605 static struct ospf_neighbor
*
606 elect_dr(struct ospf_proto
*p
, list nl
)
608 struct ospf_neighbor
*neigh
, *n
;
612 WALK_LIST(neigh
, nl
) /* And now DR */
614 nid
= neigh_get_id(p
, neigh
);
616 if (neigh
->state
>= NEIGHBOR_2WAY
) /* Higher than 2WAY */
617 if (neigh
->priority
> 0) /* Eligible */
618 if (neigh
->dr
== nid
) /* And declaring itself DR */
622 if (neigh
->priority
> n
->priority
)
624 else if (neigh
->priority
== n
->priority
)
625 if (neigh
->rid
> n
->rid
)
639 * ospf_dr_election - (Backup) Designed Router election
640 * @ifa: actual interface
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
650 ospf_dr_election(struct ospf_iface
*ifa
)
652 struct ospf_proto
*p
= ifa
->oa
->po
;
653 struct ospf_neighbor
*neigh
, *ndr
, *nbdr
, me
;
654 u32 myid
= p
->router_id
;
656 DBG("(B)DR election.\n");
658 me
.state
= NEIGHBOR_2WAY
;
660 me
.priority
= ifa
->priority
;
661 me
.ip
= ifa
->addr
->ip
;
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
;
667 add_tail(&ifa
->neigh_list
, NODE
& me
);
669 nbdr
= elect_bdr(p
, ifa
->neigh_list
);
670 ndr
= elect_dr(p
, ifa
->neigh_list
);
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
)))
681 me
.dr
= ndr
? neigh_get_id(p
, ndr
) : 0;
682 me
.bdr
= nbdr
? neigh_get_id(p
, nbdr
) : 0;
684 nbdr
= elect_bdr(p
, ifa
->neigh_list
);
685 ndr
= elect_dr(p
, ifa
->neigh_list
);
694 u32 old_drid
= ifa
->drid
;
695 u32 old_bdrid
= ifa
->bdrid
;
696 ip_addr none
= ospf_is_v2(p
) ? IPA_NONE4
: IPA_NONE6
;
698 ifa
->drid
= ndr
? ndr
->rid
: 0;
699 ifa
->drip
= ndr
? ndr
->ip
: none
;
700 ifa
->dr_iface_id
= ndr
? ndr
->iface_id
: 0;
702 ifa
->bdrid
= nbdr
? nbdr
->rid
: 0;
703 ifa
->bdrip
= nbdr
? nbdr
->ip
: none
;
705 DBG("DR=%R, BDR=%R\n", ifa
->drid
, ifa
->bdrid
);
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
);
713 ospf_iface_chstate(ifa
, OSPF_IS_DROTHER
);
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
);
721 /* RFC 2328 12.4 Event 3 - DR change */
722 if (ifa
->drid
!= old_drid
)
723 ospf_notify_rt_lsa(ifa
->oa
);
726 struct ospf_neighbor
*
727 find_neigh(struct ospf_iface
*ifa
, u32 rid
)
729 struct ospf_neighbor
*n
;
730 WALK_LIST(n
, ifa
->neigh_list
)
736 struct ospf_neighbor
*
737 find_neigh_by_ip(struct ospf_iface
*ifa
, ip_addr ip
)
739 struct ospf_neighbor
*n
;
740 WALK_LIST(n
, ifa
->neigh_list
)
741 if (ipa_equal(n
->ip
, ip
))
747 inactivity_timer_hook(timer
* timer
)
749 struct ospf_neighbor
*n
= (struct ospf_neighbor
*) timer
->data
;
750 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
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
);
758 ospf_neigh_bfd_hook(struct bfd_request
*req
)
760 struct ospf_neighbor
*n
= req
->data
;
761 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
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
);
772 ospf_neigh_update_bfd(struct ospf_neighbor
*n
, int use_bfd
)
774 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
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
);
781 if (!use_bfd
&& n
->bfd_req
)
790 dbdes_timer_hook(timer
*t
)
792 struct ospf_neighbor
*n
= t
->data
;
793 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
795 // OSPF_TRACE(D_EVENTS, "DBDES timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
797 if (n
->state
== NEIGHBOR_EXSTART
)
798 ospf_send_dbdes(p
, n
);
800 if ((n
->state
== NEIGHBOR_EXCHANGE
) && (n
->myimms
& DBDES_MS
))
801 ospf_rxmt_dbdes(p
, n
);
803 if ((n
->state
> NEIGHBOR_LOADING
) && !(n
->myimms
& DBDES_MS
))
805 ospf_reset_ldd(p
, n
);
806 tm_stop(n
->dbdes_timer
);
811 lsrq_timer_hook(timer
*t
)
813 struct ospf_neighbor
*n
= t
->data
;
814 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
816 // OSPF_TRACE(D_EVENTS, "LSRQ timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
818 if ((n
->state
>= NEIGHBOR_EXCHANGE
) && !EMPTY_SLIST(n
->lsrql
))
819 ospf_send_lsreq(p
, n
);
823 lsrt_timer_hook(timer
*t
)
825 struct ospf_neighbor
*n
= t
->data
;
826 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
828 // OSPF_TRACE(D_EVENTS, "LSRT timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
830 if ((n
->state
>= NEIGHBOR_EXCHANGE
) && !EMPTY_SLIST(n
->lsrtl
))
831 ospf_rxmt_lsupd(p
, n
);
835 ackd_timer_hook(timer
*t
)
837 struct ospf_neighbor
*n
= t
->data
;
838 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
840 ospf_send_lsack(p
, n
, ACKL_DELAY
);
845 ospf_sh_neigh_info(struct ospf_neighbor
*n
)
847 struct ospf_iface
*ifa
= n
->ifa
;
850 if ((ifa
->type
== OSPF_IT_BCAST
) || (ifa
->type
== OSPF_IT_NBMA
))
852 if (n
->rid
== ifa
->drid
)
854 else if (n
->rid
== ifa
->bdrid
)
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
);