]>
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
);
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
;
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
)
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 */
183 n
->dds
= random_u32();
186 n
->myimms
= DBDES_IMMS
;
188 tm_start(n
->dbdes_timer
, 0);
189 tm_start(n
->ackd_timer
, ifa
->rxmtint
/ 2);
192 if (state
> NEIGHBOR_EXSTART
)
193 n
->myimms
&= ~DBDES_I
;
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
);
203 * ospf_neigh_sm - ospf neighbor state machine
205 * @event: actual event
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 .
215 ospf_neigh_sm(struct ospf_neighbor
*n
, int event
)
217 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
219 DBG("Neighbor state machine for %R on %s, event %s\n",
220 n
->rid
, n
->ifa
->ifname
, ospf_inm_names
[event
]);
225 ospf_neigh_chstate(n
, NEIGHBOR_ATTEMPT
);
226 /* NBMA are used different way */
230 if (n
->state
< NEIGHBOR_INIT
)
231 ospf_neigh_chstate(n
, NEIGHBOR_INIT
);
233 /* Restart inactivity timer */
234 tm_start(n
->inactim
, n
->ifa
->deadint
);
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
);
245 if (n
->state
== NEIGHBOR_EXSTART
)
247 ospf_neigh_chstate(n
, NEIGHBOR_EXCHANGE
);
249 /* Reset DB summary list iterator */
251 s_init(&(n
->dbsi
), &p
->lsal
);
253 /* Add MaxAge LSA entries to retransmission list */
254 ospf_add_flushed_to_lsrt(p
, n
);
257 bug("NEGDONE and I'm not in EXSTART?");
261 if (!EMPTY_SLIST(n
->lsrql
))
262 ospf_neigh_chstate(n
, NEIGHBOR_LOADING
);
264 ospf_neigh_chstate(n
, NEIGHBOR_FULL
);
268 ospf_neigh_chstate(n
, NEIGHBOR_FULL
);
272 /* Can In build adjacency? */
273 if ((n
->state
== NEIGHBOR_2WAY
) && can_do_adj(n
))
275 ospf_neigh_chstate(n
, NEIGHBOR_EXSTART
);
277 else if ((n
->state
>= NEIGHBOR_EXSTART
) && !can_do_adj(n
))
280 ospf_neigh_chstate(n
, NEIGHBOR_2WAY
);
286 if (n
->state
>= NEIGHBOR_EXCHANGE
)
289 ospf_neigh_chstate(n
, NEIGHBOR_EXSTART
);
296 /* No need for reset_lists() */
297 ospf_neigh_chstate(n
, NEIGHBOR_DOWN
);
303 ospf_neigh_chstate(n
, NEIGHBOR_INIT
);
307 bug("%s: INM - Unknown event?", p
->p
.name
);
313 can_do_adj(struct ospf_neighbor
*n
)
315 struct ospf_iface
*ifa
= n
->ifa
;
316 struct ospf_proto
*p
= ifa
->oa
->po
;
332 bug("%s: Iface %s in down state?", p
->p
.name
, ifa
->ifname
);
334 case OSPF_IS_WAITING
:
335 DBG("%s: Neighbor? on iface %s\n", p
->p
.name
, ifa
->ifname
);
337 case OSPF_IS_DROTHER
:
338 if (((n
->rid
== ifa
->drid
) || (n
->rid
== ifa
->bdrid
))
339 && (n
->state
>= NEIGHBOR_2WAY
))
345 if (n
->state
>= NEIGHBOR_2WAY
)
349 bug("%s: Iface %s in unknown state?", p
->p
.name
, ifa
->ifname
);
354 bug("%s: Iface %s is unknown type?", p
->p
.name
, ifa
->ifname
);
357 DBG("%s: Iface %s can_do_adj=%d\n", p
->p
.name
, ifa
->ifname
, i
);
362 static inline u32
neigh_get_id(struct ospf_proto
*p
, struct ospf_neighbor
*n
)
363 { return ospf_is_v2(p
) ? ipa_to_u32(n
->ip
) : n
->rid
; }
365 static struct ospf_neighbor
*
366 elect_bdr(struct ospf_proto
*p
, list nl
)
368 struct ospf_neighbor
*neigh
, *n1
, *n2
;
373 WALK_LIST(neigh
, nl
) /* First try those decl. themselves */
375 nid
= neigh_get_id(p
, neigh
);
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 */
381 if (neigh
->bdr
== nid
) /* Declaring BDR */
385 if (neigh
->priority
> n1
->priority
)
387 else if (neigh
->priority
== n1
->priority
)
388 if (neigh
->rid
> n1
->rid
)
396 else /* And NOT declaring BDR */
400 if (neigh
->priority
> n2
->priority
)
402 else if (neigh
->priority
== n2
->priority
)
403 if (neigh
->rid
> n2
->rid
)
419 static struct ospf_neighbor
*
420 elect_dr(struct ospf_proto
*p
, list nl
)
422 struct ospf_neighbor
*neigh
, *n
;
426 WALK_LIST(neigh
, nl
) /* And now DR */
428 nid
= neigh_get_id(p
, neigh
);
430 if (neigh
->state
>= NEIGHBOR_2WAY
) /* Higher than 2WAY */
431 if (neigh
->priority
> 0) /* Eligible */
432 if (neigh
->dr
== nid
) /* And declaring itself DR */
436 if (neigh
->priority
> n
->priority
)
438 else if (neigh
->priority
== n
->priority
)
439 if (neigh
->rid
> n
->rid
)
453 * ospf_dr_election - (Backup) Designed Router election
454 * @ifa: actual interface
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
464 ospf_dr_election(struct ospf_iface
*ifa
)
466 struct ospf_proto
*p
= ifa
->oa
->po
;
467 struct ospf_neighbor
*neigh
, *ndr
, *nbdr
, me
;
468 u32 myid
= p
->router_id
;
470 DBG("(B)DR election.\n");
472 me
.state
= NEIGHBOR_2WAY
;
474 me
.priority
= ifa
->priority
;
475 me
.ip
= ifa
->addr
->ip
;
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
;
481 add_tail(&ifa
->neigh_list
, NODE
& me
);
483 nbdr
= elect_bdr(p
, ifa
->neigh_list
);
484 ndr
= elect_dr(p
, ifa
->neigh_list
);
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
)))
495 me
.dr
= ndr
? neigh_get_id(p
, ndr
) : 0;
496 me
.bdr
= nbdr
? neigh_get_id(p
, nbdr
) : 0;
498 nbdr
= elect_bdr(p
, ifa
->neigh_list
);
499 ndr
= elect_dr(p
, ifa
->neigh_list
);
508 u32 old_drid
= ifa
->drid
;
509 u32 old_bdrid
= ifa
->bdrid
;
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;
515 ifa
->bdrid
= nbdr
? nbdr
->rid
: 0;
516 ifa
->bdrip
= nbdr
? nbdr
->ip
: IPA_NONE
;
518 DBG("DR=%R, BDR=%R\n", ifa
->drid
, ifa
->bdrid
);
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
);
526 ospf_iface_chstate(ifa
, OSPF_IS_DROTHER
);
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
);
534 /* RFC 2328 12.4 Event 3 - DR change */
535 if (ifa
->drid
!= old_drid
)
536 ospf_notify_rt_lsa(ifa
->oa
);
539 struct ospf_neighbor
*
540 find_neigh(struct ospf_iface
*ifa
, u32 rid
)
542 struct ospf_neighbor
*n
;
543 WALK_LIST(n
, ifa
->neigh_list
)
549 struct ospf_neighbor
*
550 find_neigh_by_ip(struct ospf_iface
*ifa
, ip_addr ip
)
552 struct ospf_neighbor
*n
;
553 WALK_LIST(n
, ifa
->neigh_list
)
554 if (ipa_equal(n
->ip
, ip
))
560 inactivity_timer_hook(timer
* timer
)
562 struct ospf_neighbor
*n
= (struct ospf_neighbor
*) timer
->data
;
563 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
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
);
571 ospf_neigh_bfd_hook(struct bfd_request
*req
)
573 struct ospf_neighbor
*n
= req
->data
;
574 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
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
);
585 ospf_neigh_update_bfd(struct ospf_neighbor
*n
, int use_bfd
)
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
);
591 if (!use_bfd
&& n
->bfd_req
)
600 dbdes_timer_hook(timer
*t
)
602 struct ospf_neighbor
*n
= t
->data
;
603 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
605 // OSPF_TRACE(D_EVENTS, "DBDES timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
607 if (n
->state
== NEIGHBOR_EXSTART
)
608 ospf_send_dbdes(p
, n
);
610 if ((n
->state
== NEIGHBOR_EXCHANGE
) && (n
->myimms
& DBDES_MS
))
611 ospf_rxmt_dbdes(p
, n
);
615 lsrq_timer_hook(timer
*t
)
617 struct ospf_neighbor
*n
= t
->data
;
618 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
620 // OSPF_TRACE(D_EVENTS, "LSRQ timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
622 if ((n
->state
>= NEIGHBOR_EXCHANGE
) && !EMPTY_SLIST(n
->lsrql
))
623 ospf_send_lsreq(p
, n
);
627 lsrt_timer_hook(timer
*t
)
629 struct ospf_neighbor
*n
= t
->data
;
630 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
632 // OSPF_TRACE(D_EVENTS, "LSRT timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
634 if ((n
->state
>= NEIGHBOR_EXCHANGE
) && !EMPTY_SLIST(n
->lsrtl
))
635 ospf_rxmt_lsupd(p
, n
);
639 ackd_timer_hook(timer
*t
)
641 struct ospf_neighbor
*n
= t
->data
;
642 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
644 ospf_send_lsack(p
, n
, ACKL_DELAY
);
649 ospf_sh_neigh_info(struct ospf_neighbor
*n
)
651 struct ospf_iface
*ifa
= n
->ifa
;
656 exp
= n
->inactim
->expires
- now
;
661 bsprintf(etime
, "-Inf-");
665 bsprintf(etime
, "%02u:%02u", min
, sec
);
668 if ((ifa
->type
== OSPF_IT_BCAST
) || (ifa
->type
== OSPF_IT_NBMA
))
670 if (n
->rid
== ifa
->drid
)
672 else if (n
->rid
== ifa
->bdrid
)
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
);