]>
git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/neighbor.c
c5d44dec85093be5c3e1919d81c9156ba5ae42fd
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
);
34 init_lists(struct ospf_proto
*p
, struct ospf_neighbor
*n
)
36 s_init_list(&(n
->lsrql
));
37 n
->lsrqi
= SHEAD(n
->lsrql
);
38 n
->lsrqh
= ospf_top_new(p
, n
->pool
);
40 s_init_list(&(n
->lsrtl
));
41 n
->lsrth
= ospf_top_new(p
, n
->pool
);
45 release_lsrtl(struct ospf_proto
*p
, struct ospf_neighbor
*n
)
47 struct top_hash_entry
*ret
, *en
;
49 WALK_SLIST(ret
, n
->lsrtl
)
51 en
= ospf_hash_find_entry(p
->gr
, ret
);
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.
62 reset_lists(struct ospf_proto
*p
, struct ospf_neighbor
*n
)
65 ospf_top_free(n
->lsrqh
);
66 ospf_top_free(n
->lsrth
);
67 ospf_reset_lsack_queue(n
);
69 tm_stop(n
->dbdes_timer
);
70 tm_stop(n
->lsrq_timer
);
71 tm_stop(n
->lsrt_timer
);
72 tm_stop(n
->ackd_timer
);
77 struct ospf_neighbor
*
78 ospf_neighbor_new(struct ospf_iface
*ifa
)
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
));
86 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_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);
107 ospf_neigh_down(struct ospf_neighbor
*n
)
109 struct ospf_iface
*ifa
= n
->ifa
;
110 struct ospf_proto
*p
= ifa
->oa
->po
;
112 if ((ifa
->type
== OSPF_IT_NBMA
) || (ifa
->type
== OSPF_IT_PTMP
))
114 struct nbma_node
*nn
= find_nbma_node(ifa
, n
->ip
);
124 OSPF_TRACE(D_EVENTS
, "Neighbor %R on %s removed", n
->rid
, ifa
->ifname
);
128 * ospf_neigh_chstate - handles changes related to new or lod state of neighbor
132 * Many actions have to be taken acording to a change of state of a neighbor. It
133 * starts rxmt timers, call interface state machine etc.
136 ospf_neigh_chstate(struct ospf_neighbor
*n
, u8 state
)
138 struct ospf_iface
*ifa
= n
->ifa
;
139 struct ospf_proto
*p
= ifa
->oa
->po
;
140 u8 old_state
= n
->state
;
141 int old_fadj
= ifa
->fadj
;
143 if (state
== old_state
)
146 OSPF_TRACE(D_EVENTS
, "Neighbor %R on %s changed state from %s to %s",
147 n
->rid
, ifa
->ifname
, ospf_ns_names
[old_state
], ospf_ns_names
[state
]);
151 /* Increase number of partial adjacencies */
152 if ((state
== NEIGHBOR_EXCHANGE
) || (state
== NEIGHBOR_LOADING
))
155 /* Decrease number of partial adjacencies */
156 if ((old_state
== NEIGHBOR_EXCHANGE
) || (old_state
== NEIGHBOR_LOADING
))
159 /* Increase number of full adjacencies */
160 if (state
== NEIGHBOR_FULL
)
163 /* Decrease number of full adjacencies */
164 if (old_state
== NEIGHBOR_FULL
)
167 if (ifa
->fadj
!= old_fadj
)
169 /* RFC 2328 12.4 Event 4 - neighbor enters/leaves Full state */
170 ospf_notify_rt_lsa(ifa
->oa
);
171 ospf_notify_net_lsa(ifa
);
173 /* RFC 2328 12.4 Event 8 - vlink state change */
174 if (ifa
->type
== OSPF_IT_VLINK
)
175 ospf_notify_rt_lsa(ifa
->voa
);
178 if (state
== NEIGHBOR_EXSTART
)
180 /* First time adjacency */
182 n
->dds
= random_u32();
185 n
->myimms
= DBDES_IMMS
;
187 tm_start(n
->dbdes_timer
, 0);
188 tm_start(n
->ackd_timer
, ifa
->rxmtint
/ 2);
191 if (state
> NEIGHBOR_EXSTART
)
192 n
->myimms
&= ~DBDES_I
;
194 /* Generate NeighborChange event if needed, see RFC 2328 9.2 */
195 if ((state
== NEIGHBOR_2WAY
) && (old_state
< NEIGHBOR_2WAY
))
196 ospf_iface_sm(ifa
, ISM_NEICH
);
197 if ((state
< NEIGHBOR_2WAY
) && (old_state
>= NEIGHBOR_2WAY
))
198 ospf_iface_sm(ifa
, ISM_NEICH
);
202 * ospf_neigh_sm - ospf neighbor state machine
204 * @event: actual event
206 * This part implements the neighbor state machine as described in 10.3 of
207 * RFC 2328. The only difference is that state %NEIGHBOR_ATTEMPT is not
208 * used. We discover neighbors on nonbroadcast networks in the
209 * same way as on broadcast networks. The only difference is in
210 * sending hello packets. These are sent to IPs listed in
211 * @ospf_iface->nbma_list .
214 ospf_neigh_sm(struct ospf_neighbor
*n
, int event
)
216 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
218 DBG("Neighbor state machine for %R on %s, event %s\n",
219 n
->rid
, n
->ifa
->ifname
, ospf_inm_names
[event
]);
224 ospf_neigh_chstate(n
, NEIGHBOR_ATTEMPT
);
225 /* NBMA are used different way */
229 if (n
->state
< NEIGHBOR_INIT
)
230 ospf_neigh_chstate(n
, NEIGHBOR_INIT
);
232 /* Restart inactivity timer */
233 tm_start(n
->inactim
, n
->ifa
->deadint
);
237 if (n
->state
< NEIGHBOR_2WAY
)
238 ospf_neigh_chstate(n
, NEIGHBOR_2WAY
);
239 if ((n
->state
== NEIGHBOR_2WAY
) && can_do_adj(n
))
240 ospf_neigh_chstate(n
, NEIGHBOR_EXSTART
);
244 if (n
->state
== NEIGHBOR_EXSTART
)
246 ospf_neigh_chstate(n
, NEIGHBOR_EXCHANGE
);
248 /* Reset DB summary list iterator */
250 s_init(&(n
->dbsi
), &p
->lsal
);
252 /* Add MaxAge LSA entries to retransmission list */
253 ospf_add_flushed_to_lsrt(p
, n
);
256 bug("NEGDONE and I'm not in EXSTART?");
260 if (!EMPTY_SLIST(n
->lsrql
))
261 ospf_neigh_chstate(n
, NEIGHBOR_LOADING
);
263 ospf_neigh_chstate(n
, NEIGHBOR_FULL
);
267 ospf_neigh_chstate(n
, NEIGHBOR_FULL
);
271 /* Can In build adjacency? */
272 if ((n
->state
== NEIGHBOR_2WAY
) && can_do_adj(n
))
274 ospf_neigh_chstate(n
, NEIGHBOR_EXSTART
);
276 else if ((n
->state
>= NEIGHBOR_EXSTART
) && !can_do_adj(n
))
279 ospf_neigh_chstate(n
, NEIGHBOR_2WAY
);
285 if (n
->state
>= NEIGHBOR_EXCHANGE
)
288 ospf_neigh_chstate(n
, NEIGHBOR_EXSTART
);
295 /* No need for reset_lists() */
296 ospf_neigh_chstate(n
, NEIGHBOR_DOWN
);
302 ospf_neigh_chstate(n
, NEIGHBOR_INIT
);
306 bug("%s: INM - Unknown event?", p
->p
.name
);
312 can_do_adj(struct ospf_neighbor
*n
)
314 struct ospf_iface
*ifa
= n
->ifa
;
315 struct ospf_proto
*p
= ifa
->oa
->po
;
331 bug("%s: Iface %s in down state?", p
->p
.name
, ifa
->ifname
);
333 case OSPF_IS_WAITING
:
334 DBG("%s: Neighbor? on iface %s\n", p
->p
.name
, ifa
->ifname
);
336 case OSPF_IS_DROTHER
:
337 if (((n
->rid
== ifa
->drid
) || (n
->rid
== ifa
->bdrid
))
338 && (n
->state
>= NEIGHBOR_2WAY
))
344 if (n
->state
>= NEIGHBOR_2WAY
)
348 bug("%s: Iface %s in unknown state?", p
->p
.name
, ifa
->ifname
);
353 bug("%s: Iface %s is unknown type?", p
->p
.name
, ifa
->ifname
);
356 DBG("%s: Iface %s can_do_adj=%d\n", p
->p
.name
, ifa
->ifname
, i
);
361 static inline u32
neigh_get_id(struct ospf_proto
*p
, struct ospf_neighbor
*n
)
362 { return ospf_is_v2(p
) ? ipa_to_u32(n
->ip
) : n
->rid
; }
364 static struct ospf_neighbor
*
365 elect_bdr(struct ospf_proto
*p
, list nl
)
367 struct ospf_neighbor
*neigh
, *n1
, *n2
;
372 WALK_LIST(neigh
, nl
) /* First try those decl. themselves */
374 nid
= neigh_get_id(p
, neigh
);
376 if (neigh
->state
>= NEIGHBOR_2WAY
) /* Higher than 2WAY */
377 if (neigh
->priority
> 0) /* Eligible */
378 if (neigh
->dr
!= nid
) /* And not decl. itself DR */
380 if (neigh
->bdr
== nid
) /* Declaring BDR */
384 if (neigh
->priority
> n1
->priority
)
386 else if (neigh
->priority
== n1
->priority
)
387 if (neigh
->rid
> n1
->rid
)
395 else /* And NOT declaring BDR */
399 if (neigh
->priority
> n2
->priority
)
401 else if (neigh
->priority
== n2
->priority
)
402 if (neigh
->rid
> n2
->rid
)
418 static struct ospf_neighbor
*
419 elect_dr(struct ospf_proto
*p
, list nl
)
421 struct ospf_neighbor
*neigh
, *n
;
425 WALK_LIST(neigh
, nl
) /* And now DR */
427 nid
= neigh_get_id(p
, neigh
);
429 if (neigh
->state
>= NEIGHBOR_2WAY
) /* Higher than 2WAY */
430 if (neigh
->priority
> 0) /* Eligible */
431 if (neigh
->dr
== nid
) /* And declaring itself DR */
435 if (neigh
->priority
> n
->priority
)
437 else if (neigh
->priority
== n
->priority
)
438 if (neigh
->rid
> n
->rid
)
452 * ospf_dr_election - (Backup) Designed Router election
453 * @ifa: actual interface
455 * When the wait timer fires, it is time to elect (Backup) Designated Router.
456 * Structure describing me is added to this list so every electing router has
457 * the same list. Backup Designated Router is elected before Designated
458 * Router. This process is described in 9.4 of RFC 2328. The function is
459 * supposed to be called only from ospf_iface_sm() as a part of the interface
463 ospf_dr_election(struct ospf_iface
*ifa
)
465 struct ospf_proto
*p
= ifa
->oa
->po
;
466 struct ospf_neighbor
*neigh
, *ndr
, *nbdr
, me
;
467 u32 myid
= p
->router_id
;
469 DBG("(B)DR election.\n");
471 me
.state
= NEIGHBOR_2WAY
;
473 me
.priority
= ifa
->priority
;
474 me
.ip
= ifa
->addr
->ip
;
476 me
.dr
= ospf_is_v2(p
) ? ipa_to_u32(ifa
->drip
) : ifa
->drid
;
477 me
.bdr
= ospf_is_v2(p
) ? ipa_to_u32(ifa
->bdrip
) : ifa
->bdrid
;
478 me
.iface_id
= ifa
->iface_id
;
480 add_tail(&ifa
->neigh_list
, NODE
& me
);
482 nbdr
= elect_bdr(p
, ifa
->neigh_list
);
483 ndr
= elect_dr(p
, ifa
->neigh_list
);
489 if (((ifa
->drid
== myid
) && (ndr
!= &me
))
490 || ((ifa
->drid
!= myid
) && (ndr
== &me
))
491 || ((ifa
->bdrid
== myid
) && (nbdr
!= &me
))
492 || ((ifa
->bdrid
!= myid
) && (nbdr
== &me
)))
494 me
.dr
= ndr
? neigh_get_id(p
, ndr
) : 0;
495 me
.bdr
= nbdr
? neigh_get_id(p
, nbdr
) : 0;
497 nbdr
= elect_bdr(p
, ifa
->neigh_list
);
498 ndr
= elect_dr(p
, ifa
->neigh_list
);
507 u32 old_drid
= ifa
->drid
;
508 u32 old_bdrid
= ifa
->bdrid
;
510 ifa
->drid
= ndr
? ndr
->rid
: 0;
511 ifa
->drip
= ndr
? ndr
->ip
: IPA_NONE
;
512 ifa
->dr_iface_id
= ndr
? ndr
->iface_id
: 0;
514 ifa
->bdrid
= nbdr
? nbdr
->rid
: 0;
515 ifa
->bdrip
= nbdr
? nbdr
->ip
: IPA_NONE
;
517 DBG("DR=%R, BDR=%R\n", ifa
->drid
, ifa
->bdrid
);
519 /* We are part of the interface state machine */
520 if (ifa
->drid
== myid
)
521 ospf_iface_chstate(ifa
, OSPF_IS_DR
);
522 else if (ifa
->bdrid
== myid
)
523 ospf_iface_chstate(ifa
, OSPF_IS_BACKUP
);
525 ospf_iface_chstate(ifa
, OSPF_IS_DROTHER
);
527 /* Review neighbor adjacencies if DR or BDR changed */
528 if ((ifa
->drid
!= old_drid
) || (ifa
->bdrid
!= old_bdrid
))
529 WALK_LIST(neigh
, ifa
->neigh_list
)
530 if (neigh
->state
>= NEIGHBOR_2WAY
)
531 ospf_neigh_sm(neigh
, INM_ADJOK
);
533 /* RFC 2328 12.4 Event 3 - DR change */
534 if (ifa
->drid
!= old_drid
)
535 ospf_notify_rt_lsa(ifa
->oa
);
538 struct ospf_neighbor
*
539 find_neigh(struct ospf_iface
*ifa
, u32 rid
)
541 struct ospf_neighbor
*n
;
542 WALK_LIST(n
, ifa
->neigh_list
)
548 struct ospf_neighbor
*
549 find_neigh_by_ip(struct ospf_iface
*ifa
, ip_addr ip
)
551 struct ospf_neighbor
*n
;
552 WALK_LIST(n
, ifa
->neigh_list
)
553 if (ipa_equal(n
->ip
, ip
))
559 inactivity_timer_hook(timer
* timer
)
561 struct ospf_neighbor
*n
= (struct ospf_neighbor
*) timer
->data
;
562 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
564 OSPF_TRACE(D_EVENTS
, "Inactivity timer expired for nbr %R on %s",
565 n
->rid
, n
->ifa
->ifname
);
566 ospf_neigh_sm(n
, INM_INACTTIM
);
570 ospf_neigh_bfd_hook(struct bfd_request
*req
)
572 struct ospf_neighbor
*n
= req
->data
;
573 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
577 OSPF_TRACE(D_EVENTS
, "BFD session down for nbr %R on %s",
578 n
->rid
, n
->ifa
->ifname
);
579 ospf_neigh_sm(n
, INM_INACTTIM
);
584 ospf_neigh_update_bfd(struct ospf_neighbor
*n
, int use_bfd
)
586 if (use_bfd
&& !n
->bfd_req
)
587 n
->bfd_req
= bfd_request_session(n
->pool
, n
->ip
, n
->ifa
->addr
->ip
, n
->ifa
->iface
,
588 ospf_neigh_bfd_hook
, n
);
590 if (!use_bfd
&& n
->bfd_req
)
599 dbdes_timer_hook(timer
*t
)
601 struct ospf_neighbor
*n
= t
->data
;
602 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
604 // OSPF_TRACE(D_EVENTS, "DBDES timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
606 if (n
->state
== NEIGHBOR_EXSTART
)
607 ospf_send_dbdes(p
, n
);
609 if ((n
->state
== NEIGHBOR_EXCHANGE
) && (n
->myimms
& DBDES_MS
))
610 ospf_rxmt_dbdes(p
, n
);
614 lsrq_timer_hook(timer
*t
)
616 struct ospf_neighbor
*n
= t
->data
;
617 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
619 // OSPF_TRACE(D_EVENTS, "LSRQ timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
621 if ((n
->state
>= NEIGHBOR_EXCHANGE
) && !EMPTY_SLIST(n
->lsrql
))
622 ospf_send_lsreq(p
, n
);
626 lsrt_timer_hook(timer
*t
)
628 struct ospf_neighbor
*n
= t
->data
;
629 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
631 // OSPF_TRACE(D_EVENTS, "LSRT timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
633 if ((n
->state
>= NEIGHBOR_EXCHANGE
) && !EMPTY_SLIST(n
->lsrtl
))
634 ospf_rxmt_lsupd(p
, n
);
638 ackd_timer_hook(timer
*t
)
640 struct ospf_neighbor
*n
= t
->data
;
641 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
643 ospf_send_lsack(p
, n
, ACKL_DELAY
);
648 ospf_sh_neigh_info(struct ospf_neighbor
*n
)
650 struct ospf_iface
*ifa
= n
->ifa
;
655 exp
= n
->inactim
->expires
- now
;
660 bsprintf(etime
, "-Inf-");
664 bsprintf(etime
, "%02u:%02u", min
, sec
);
667 if ((ifa
->type
== OSPF_IT_BCAST
) || (ifa
->type
== OSPF_IT_NBMA
))
669 if (n
->rid
== ifa
->drid
)
671 else if (n
->rid
== ifa
->bdrid
)
677 cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n
->rid
, n
->priority
,
678 ospf_ns_names
[n
->state
], pos
, etime
, ifa
->ifname
, n
->ip
);