]>
git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/neighbor.c
ee1e8d0fd074b4fb0905ec0c3ff27c3880aefe15
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.
13 char *ospf_ns
[] = { " down",
23 const char *ospf_inm
[] =
24 { "hello received", "neighbor start", "2-way received",
25 "negotiation done", "exstart done", "bad ls request", "load done",
26 "adjacency ok?", "sequence mismatch", "1-way received", "kill neighbor",
27 "inactivity timer", "line down"
30 static void neigh_chstate(struct ospf_neighbor
*n
, u8 state
);
31 static void neighbor_timer_hook(timer
* timer
);
32 static void rxmt_timer_hook(timer
* timer
);
33 static void ackd_timer_hook(timer
* t
);
36 init_lists(struct ospf_proto
*p
, struct ospf_neighbor
*n
)
38 s_init_list(&(n
->lsrql
));
39 n
->lsrqh
= ospf_top_new(p
, n
->pool
);
41 s_init_list(&(n
->lsrtl
));
42 n
->lsrth
= ospf_top_new(p
, n
->pool
);
46 release_lsrtl(struct ospf_proto
*p
, struct ospf_neighbor
*n
)
48 struct top_hash_entry
*ret
, *en
;
50 WALK_SLIST(ret
, n
->lsrtl
)
52 en
= ospf_hash_find_entry(p
->gr
, ret
);
58 /* Resets LSA request and retransmit lists.
59 * We do not reset DB summary list iterator here,
60 * it is reset during entering EXCHANGE state.
63 reset_lists(struct ospf_proto
*p
, struct ospf_neighbor
*n
)
66 ospf_top_free(n
->lsrqh
);
67 ospf_top_free(n
->lsrth
);
71 struct ospf_neighbor
*
72 ospf_neighbor_new(struct ospf_iface
*ifa
)
74 struct ospf_proto
*p
= ifa
->oa
->po
;
75 struct pool
*pool
= rp_new(p
->p
.pool
, "OSPF Neighbor");
76 struct ospf_neighbor
*n
= mb_allocz(pool
, sizeof(struct ospf_neighbor
));
80 add_tail(&ifa
->neigh_list
, NODE n
);
83 n
->state
= NEIGHBOR_DOWN
;
86 s_init(&(n
->dbsi
), &(p
->lsal
));
88 n
->inactim
= tm_new(pool
);
90 n
->inactim
->randomize
= 0;
91 n
->inactim
->hook
= neighbor_timer_hook
;
92 n
->inactim
->recurrent
= 0;
93 DBG("%s: Installing inactivity timer.\n", p
->p
.name
);
95 n
->rxmt_timer
= tm_new(pool
);
96 n
->rxmt_timer
->data
= n
;
97 n
->rxmt_timer
->randomize
= 0;
98 n
->rxmt_timer
->hook
= rxmt_timer_hook
;
99 n
->rxmt_timer
->recurrent
= ifa
->rxmtint
;
100 tm_start(n
->rxmt_timer
, n
->ifa
->rxmtint
);
101 DBG("%s: Installing rxmt timer.\n", p
->p
.name
);
103 n
->ackd_timer
= tm_new(pool
);
104 n
->ackd_timer
->data
= n
;
105 n
->ackd_timer
->randomize
= 0;
106 n
->ackd_timer
->hook
= ackd_timer_hook
;
107 n
->ackd_timer
->recurrent
= ifa
->rxmtint
/ 2;
108 init_list(&n
->ackl
[ACKL_DIRECT
]);
109 init_list(&n
->ackl
[ACKL_DELAY
]);
110 tm_start(n
->ackd_timer
, n
->ifa
->rxmtint
/ 2);
111 DBG("%s: Installing ackd timer.\n", p
->p
.name
);
117 * neigh_chstate - handles changes related to new or lod state of neighbor
121 * Many actions have to be taken acording to a change of state of a neighbor. It
122 * starts rxmt timers, call interface state machine etc.
125 neigh_chstate(struct ospf_neighbor
*n
, u8 state
)
127 struct ospf_iface
*ifa
= n
->ifa
;
128 struct ospf_proto
*p
= ifa
->oa
->po
;
129 u8 old_state
= n
->state
;
130 int old_fadj
= ifa
->fadj
;
132 if (state
== old_state
)
135 OSPF_TRACE(D_EVENTS
, "Neighbor %I changes state from %s to %s",
136 n
->ip
, ospf_ns
[old_state
], ospf_ns
[state
]);
140 if ((state
== NEIGHBOR_2WAY
) && (old_state
< NEIGHBOR_2WAY
))
141 ospf_iface_sm(ifa
, ISM_NEICH
);
142 if ((state
< NEIGHBOR_2WAY
) && (old_state
>= NEIGHBOR_2WAY
))
143 ospf_iface_sm(ifa
, ISM_NEICH
);
145 /* Increase number of partial adjacencies */
146 if ((state
== NEIGHBOR_EXCHANGE
) || (state
== NEIGHBOR_LOADING
))
149 /* Decrease number of partial adjacencies */
150 if ((old_state
== NEIGHBOR_EXCHANGE
) || (old_state
== NEIGHBOR_LOADING
))
153 /* Increase number of full adjacencies */
154 if (state
== NEIGHBOR_FULL
)
157 /* Decrease number of full adjacencies */
158 if (old_state
== NEIGHBOR_FULL
)
161 if (ifa
->fadj
!= old_fadj
)
163 /* RFC 2328 12.4 Event 4 - neighbor enters/leaves Full state */
164 ospf_notify_rt_lsa(ifa
->oa
);
165 ospf_notify_net_lsa(ifa
);
167 /* RFC 2328 12.4 Event 8 - vlink state change */
168 if (ifa
->type
== OSPF_IT_VLINK
)
169 ospf_notify_rt_lsa(ifa
->voa
);
172 if (state
== NEIGHBOR_EXSTART
)
174 /* First time adjacency */
176 n
->dds
= random_u32();
179 n
->myimms
= DBDES_IMMS
;
182 if (state
> NEIGHBOR_EXSTART
)
183 n
->myimms
&= ~DBDES_I
;
186 static inline u32
neigh_get_id(struct ospf_proto
*p
, struct ospf_neighbor
*n
)
187 { return ospf_is_v2(p
) ? ipa_to_u32(n
->ip
) : n
->rid
; }
189 static struct ospf_neighbor
*
190 elect_bdr(struct ospf_proto
*p
, list nl
)
192 struct ospf_neighbor
*neigh
, *n1
, *n2
;
197 WALK_LIST(neigh
, nl
) /* First try those decl. themselves */
199 nid
= neigh_get_id(p
, neigh
);
201 if (neigh
->state
>= NEIGHBOR_2WAY
) /* Higher than 2WAY */
202 if (neigh
->priority
> 0) /* Eligible */
203 if (neigh
->dr
!= nid
) /* And not decl. itself DR */
205 if (neigh
->bdr
== nid
) /* Declaring BDR */
209 if (neigh
->priority
> n1
->priority
)
211 else if (neigh
->priority
== n1
->priority
)
212 if (neigh
->rid
> n1
->rid
)
220 else /* And NOT declaring BDR */
224 if (neigh
->priority
> n2
->priority
)
226 else if (neigh
->priority
== n2
->priority
)
227 if (neigh
->rid
> n2
->rid
)
243 static struct ospf_neighbor
*
244 elect_dr(struct ospf_proto
*p
, list nl
)
246 struct ospf_neighbor
*neigh
, *n
;
250 WALK_LIST(neigh
, nl
) /* And now DR */
252 nid
= neigh_get_id(p
, neigh
);
254 if (neigh
->state
>= NEIGHBOR_2WAY
) /* Higher than 2WAY */
255 if (neigh
->priority
> 0) /* Eligible */
256 if (neigh
->dr
== nid
) /* And declaring itself DR */
260 if (neigh
->priority
> n
->priority
)
262 else if (neigh
->priority
== n
->priority
)
263 if (neigh
->rid
> n
->rid
)
277 can_do_adj(struct ospf_neighbor
*n
)
279 struct ospf_iface
*ifa
= n
->ifa
;
280 struct ospf_proto
*p
= ifa
->oa
->po
;
296 bug("%s: Iface %s in down state?", p
->p
.name
, ifa
->ifname
);
298 case OSPF_IS_WAITING
:
299 DBG("%s: Neighbor? on iface %s\n", p
->p
.name
, ifa
->ifname
);
301 case OSPF_IS_DROTHER
:
302 if (((n
->rid
== ifa
->drid
) || (n
->rid
== ifa
->bdrid
))
303 && (n
->state
>= NEIGHBOR_2WAY
))
309 if (n
->state
>= NEIGHBOR_2WAY
)
313 bug("%s: Iface %s in unknown state?", p
->p
.name
, ifa
->ifname
);
318 bug("%s: Iface %s is unknown type?", p
->p
.name
, ifa
->ifname
);
321 DBG("%s: Iface %s can_do_adj=%d\n", p
->p
.name
, ifa
->ifname
, i
);
326 * ospf_neigh_sm - ospf neighbor state machine
328 * @event: actual event
330 * This part implements the neighbor state machine as described in 10.3 of
331 * RFC 2328. The only difference is that state %NEIGHBOR_ATTEMPT is not
332 * used. We discover neighbors on nonbroadcast networks in the
333 * same way as on broadcast networks. The only difference is in
334 * sending hello packets. These are sent to IPs listed in
335 * @ospf_iface->nbma_list .
338 ospf_neigh_sm(struct ospf_neighbor
*n
, int event
)
340 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
342 DBG("Neighbor state machine for neighbor %I, event '%s'\n", n
->ip
,
348 neigh_chstate(n
, NEIGHBOR_ATTEMPT
);
349 /* NBMA are used different way */
353 if ((n
->state
== NEIGHBOR_DOWN
) ||
354 (n
->state
== NEIGHBOR_ATTEMPT
))
355 neigh_chstate(n
, NEIGHBOR_INIT
);
357 /* Restart inactivity timer */
358 tm_start(n
->inactim
, n
->ifa
->deadint
);
362 if (n
->state
< NEIGHBOR_2WAY
)
363 neigh_chstate(n
, NEIGHBOR_2WAY
);
364 if ((n
->state
== NEIGHBOR_2WAY
) && can_do_adj(n
))
365 neigh_chstate(n
, NEIGHBOR_EXSTART
);
369 if (n
->state
== NEIGHBOR_EXSTART
)
371 neigh_chstate(n
, NEIGHBOR_EXCHANGE
);
373 /* Reset DB summary list iterator */
375 s_init(&(n
->dbsi
), &p
->lsal
);
377 /* Add MaxAge LSA entries to retransmission list */
378 ospf_add_flushed_to_lsrt(p
, n
);
380 /* FIXME: Why is this here ? */
381 ospf_reset_lsack_queue(n
);
384 bug("NEGDONE and I'm not in EXSTART?");
388 neigh_chstate(n
, NEIGHBOR_LOADING
);
392 neigh_chstate(n
, NEIGHBOR_FULL
);
399 /* Can In build adjacency? */
402 neigh_chstate(n
, NEIGHBOR_EXSTART
);
406 if (n
->state
>= NEIGHBOR_EXSTART
)
410 neigh_chstate(n
, NEIGHBOR_2WAY
);
418 if (n
->state
>= NEIGHBOR_EXCHANGE
)
421 neigh_chstate(n
, NEIGHBOR_EXSTART
);
429 neigh_chstate(n
, NEIGHBOR_DOWN
);
434 neigh_chstate(n
, NEIGHBOR_INIT
);
438 bug("%s: INM - Unknown event?", p
->p
.name
);
444 * ospf_dr_election - (Backup) Designed Router election
445 * @ifa: actual interface
447 * When the wait timer fires, it is time to elect (Backup) Designated Router.
448 * Structure describing me is added to this list so every electing router
449 * has the same list. Backup Designated Router is elected before Designated
450 * Router. This process is described in 9.4 of RFC 2328.
453 ospf_dr_election(struct ospf_iface
*ifa
)
455 struct ospf_proto
*p
= ifa
->oa
->po
;
456 struct ospf_neighbor
*neigh
, *ndr
, *nbdr
, me
;
457 u32 myid
= p
->router_id
;
459 DBG("(B)DR election.\n");
461 me
.state
= NEIGHBOR_2WAY
;
463 me
.priority
= ifa
->priority
;
464 me
.ip
= ifa
->addr
->ip
;
466 me
.dr
= ospf_is_v2(p
) ? ipa_to_u32(ifa
->drip
) : ifa
->drid
;
467 me
.bdr
= ospf_is_v2(p
) ? ipa_to_u32(ifa
->bdrip
) : ifa
->bdrid
;
468 me
.iface_id
= ifa
->iface_id
;
470 add_tail(&ifa
->neigh_list
, NODE
& me
);
472 nbdr
= elect_bdr(p
, ifa
->neigh_list
);
473 ndr
= elect_dr(p
, ifa
->neigh_list
);
479 if (((ifa
->drid
== myid
) && (ndr
!= &me
))
480 || ((ifa
->drid
!= myid
) && (ndr
== &me
))
481 || ((ifa
->bdrid
== myid
) && (nbdr
!= &me
))
482 || ((ifa
->bdrid
!= myid
) && (nbdr
== &me
)))
484 me
.dr
= ndr
? neigh_get_id(p
, ndr
) : 0;
485 me
.bdr
= nbdr
? neigh_get_id(p
, nbdr
) : 0;
487 nbdr
= elect_bdr(p
, ifa
->neigh_list
);
488 ndr
= elect_dr(p
, ifa
->neigh_list
);
497 u32 old_drid
= ifa
->drid
;
498 u32 old_bdrid
= ifa
->bdrid
;
500 ifa
->drid
= ndr
? ndr
->rid
: 0;
501 ifa
->drip
= ndr
? ndr
->ip
: IPA_NONE
;
502 ifa
->dr_iface_id
= ndr
? ndr
->iface_id
: 0;
504 ifa
->bdrid
= nbdr
? nbdr
->rid
: 0;
505 ifa
->bdrip
= nbdr
? nbdr
->ip
: IPA_NONE
;
507 DBG("DR=%R, BDR=%R\n", ifa
->drid
, ifa
->bdrid
);
509 if (ifa
->drid
== myid
)
510 ospf_iface_chstate(ifa
, OSPF_IS_DR
);
511 else if (ifa
->bdrid
== myid
)
512 ospf_iface_chstate(ifa
, OSPF_IS_BACKUP
);
514 ospf_iface_chstate(ifa
, OSPF_IS_DROTHER
);
516 /* Review neighbor adjacencies if DR or BDR changed */
517 if ((ifa
->drid
!= old_drid
) || (ifa
->bdrid
!= old_bdrid
))
518 WALK_LIST(neigh
, ifa
->neigh_list
)
519 if (neigh
->state
>= NEIGHBOR_2WAY
)
520 ospf_neigh_sm(neigh
, INM_ADJOK
);
522 /* RFC 2328 12.4 Event 3 - DR change */
523 if (ifa
->drid
!= old_drid
)
524 ospf_notify_rt_lsa(ifa
->oa
);
527 struct ospf_neighbor
*
528 find_neigh(struct ospf_iface
*ifa
, u32 rid
)
530 struct ospf_neighbor
*n
;
531 WALK_LIST(n
, ifa
->neigh_list
)
537 struct ospf_neighbor
*
538 find_neigh_by_ip(struct ospf_iface
*ifa
, ip_addr ip
)
540 struct ospf_neighbor
*n
;
541 WALK_LIST(n
, ifa
->neigh_list
)
542 if (ipa_equal(n
->ip
, ip
))
547 /* Neighbor is inactive for a long time. Remove it. */
549 neighbor_timer_hook(timer
* timer
)
551 struct ospf_neighbor
*n
= (struct ospf_neighbor
*) timer
->data
;
552 struct ospf_iface
*ifa
= n
->ifa
;
553 struct ospf_proto
*p
= ifa
->oa
->po
;
555 OSPF_TRACE(D_EVENTS
, "Inactivity timer fired on interface %s for neighbor %I",
557 ospf_neigh_remove(n
);
561 ospf_neigh_remove(struct ospf_neighbor
*n
)
563 struct ospf_iface
*ifa
= n
->ifa
;
564 struct ospf_proto
*p
= ifa
->oa
->po
;
566 if ((ifa
->type
== OSPF_IT_NBMA
) || (ifa
->type
== OSPF_IT_PTMP
))
568 struct nbma_node
*nn
= find_nbma_node(ifa
, n
->ip
);
573 neigh_chstate(n
, NEIGHBOR_DOWN
);
579 OSPF_TRACE(D_EVENTS
, "Deleting neigbor %R", n
->rid
);
583 ospf_neigh_bfd_hook(struct bfd_request
*req
)
585 struct ospf_neighbor
*n
= req
->data
;
586 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
590 OSPF_TRACE(D_EVENTS
, "BFD session down for %I on %s", n
->ip
, n
->ifa
->ifname
);
591 ospf_neigh_remove(n
);
596 ospf_neigh_update_bfd(struct ospf_neighbor
*n
, int use_bfd
)
598 if (use_bfd
&& !n
->bfd_req
)
599 n
->bfd_req
= bfd_request_session(n
->pool
, n
->ip
, n
->ifa
->addr
->ip
, n
->ifa
->iface
,
600 ospf_neigh_bfd_hook
, n
);
602 if (!use_bfd
&& n
->bfd_req
)
611 ospf_sh_neigh_info(struct ospf_neighbor
*n
)
613 struct ospf_iface
*ifa
= n
->ifa
;
618 exp
= n
->inactim
->expires
- now
;
623 bsprintf(etime
, "-Inf-");
627 bsprintf(etime
, "%02u:%02u", min
, sec
);
630 if (n
->rid
== ifa
->drid
)
632 else if (n
->rid
== ifa
->bdrid
)
634 else if ((n
->ifa
->type
== OSPF_IT_PTP
) || (n
->ifa
->type
== OSPF_IT_PTMP
) ||
635 (n
->ifa
->type
== OSPF_IT_VLINK
))
638 cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n
->rid
, n
->priority
,
639 ospf_ns
[n
->state
], pos
, etime
, ifa
->ifname
, n
->ip
);
643 rxmt_timer_hook(timer
*t
)
645 struct ospf_neighbor
*n
= t
->data
;
646 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
648 DBG("%s: RXMT timer fired on interface %s for neigh %I\n",
649 p
->p
.name
, n
->ifa
->ifname
, n
->ip
);
653 case NEIGHBOR_EXSTART
:
654 ospf_send_dbdes(p
, n
, 1);
657 case NEIGHBOR_EXCHANGE
:
658 if (n
->myimms
& DBDES_MS
)
659 ospf_send_dbdes(p
, n
, 0);
660 case NEIGHBOR_LOADING
:
661 ospf_send_lsreq(p
, n
);
665 /* LSA retransmissions */
666 if (!EMPTY_SLIST(n
->lsrtl
))
667 ospf_rxmt_lsupd(p
, n
);
676 ackd_timer_hook(timer
*t
)
678 struct ospf_neighbor
*n
= t
->data
;
679 struct ospf_proto
*p
= n
->ifa
->oa
->po
;
681 DBG("%s: ACKD timer fired on interface %s for neigh %I\n",
682 p
->p
.name
, n
->ifa
->ifname
, n
->ip
);
684 ospf_send_lsack(p
, n
, ACKL_DELAY
);