]>
git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/neighbor.c
4 * (c) 1999 - 2004 Ondrej Filip <feela@network.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
11 char *ospf_ns
[] = { " down",
21 const char *ospf_inm
[] =
22 { "hello received", "neighbor start", "2-way received",
23 "negotiation done", "exstart done", "bad ls request", "load done",
24 "adjacency ok?", "sequence mismatch", "1-way received", "kill neighbor",
25 "inactivity timer", "line down"
28 static void neigh_chstate(struct ospf_neighbor
*n
, u8 state
);
29 static struct ospf_neighbor
*electbdr(list nl
);
30 static struct ospf_neighbor
*electdr(list nl
);
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_neighbor
*n
)
38 s_init_list(&(n
->lsrql
));
39 n
->lsrqh
= ospf_top_new(n
->pool
);
40 s_init(&(n
->lsrqi
), &(n
->lsrql
));
42 s_init_list(&(n
->lsrtl
));
43 n
->lsrth
= ospf_top_new(n
->pool
);
44 s_init(&(n
->lsrti
), &(n
->lsrtl
));
47 /* Resets LSA request and retransmit lists.
48 * We do not reset DB summary list iterator here,
49 * it is reset during entering EXCHANGE state.
52 reset_lists(struct ospf_neighbor
*n
)
54 ospf_top_free(n
->lsrqh
);
55 ospf_top_free(n
->lsrth
);
59 struct ospf_neighbor
*
60 ospf_neighbor_new(struct ospf_iface
*ifa
)
62 struct proto
*p
= (struct proto
*) (ifa
->oa
->po
);
63 struct proto_ospf
*po
= ifa
->oa
->po
;
64 struct pool
*pool
= rp_new(p
->pool
, "OSPF Neighbor");
65 struct ospf_neighbor
*n
= mb_allocz(pool
, sizeof(struct ospf_neighbor
));
69 add_tail(&ifa
->neigh_list
, NODE n
);
72 n
->ldbdes
= mb_allocz(pool
, ifa
->iface
->mtu
);
73 n
->state
= NEIGHBOR_DOWN
;
76 s_init(&(n
->dbsi
), &(po
->lsal
));
78 n
->inactim
= tm_new(pool
);
80 n
->inactim
->randomize
= 0;
81 n
->inactim
->hook
= neighbor_timer_hook
;
82 n
->inactim
->recurrent
= 0;
83 DBG("%s: Installing inactivity timer.\n", p
->name
);
85 n
->rxmt_timer
= tm_new(pool
);
86 n
->rxmt_timer
->data
= n
;
87 n
->rxmt_timer
->randomize
= 0;
88 n
->rxmt_timer
->hook
= rxmt_timer_hook
;
89 n
->rxmt_timer
->recurrent
= ifa
->rxmtint
;
90 tm_start(n
->rxmt_timer
, n
->ifa
->rxmtint
);
91 DBG("%s: Installing rxmt timer.\n", p
->name
);
93 n
->ackd_timer
= tm_new(pool
);
94 n
->ackd_timer
->data
= n
;
95 n
->ackd_timer
->randomize
= 0;
96 n
->ackd_timer
->hook
= ackd_timer_hook
;
97 n
->ackd_timer
->recurrent
= ifa
->rxmtint
/ 2;
98 init_list(&n
->ackl
[ACKL_DIRECT
]);
99 init_list(&n
->ackl
[ACKL_DELAY
]);
100 tm_start(n
->ackd_timer
, n
->ifa
->rxmtint
/ 2);
101 DBG("%s: Installing ackd timer.\n", p
->name
);
107 * neigh_chstate - handles changes related to new or lod state of neighbor
111 * Many actions have to be taken acording to a change of state of a neighbor. It
112 * starts rxmt timers, call interface state machine etc.
116 neigh_chstate(struct ospf_neighbor
*n
, u8 state
)
122 if (oldstate
!= state
)
124 struct ospf_iface
*ifa
= n
->ifa
;
125 struct proto_ospf
*po
= ifa
->oa
->po
;
126 struct proto
*p
= &po
->proto
;
130 OSPF_TRACE(D_EVENTS
, "Neighbor %I changes state from \"%s\" to \"%s\".",
131 n
->ip
, ospf_ns
[oldstate
], ospf_ns
[state
]);
133 if ((state
== NEIGHBOR_2WAY
) && (oldstate
< NEIGHBOR_2WAY
))
134 ospf_iface_sm(ifa
, ISM_NEICH
);
135 if ((state
< NEIGHBOR_2WAY
) && (oldstate
>= NEIGHBOR_2WAY
))
136 ospf_iface_sm(ifa
, ISM_NEICH
);
138 if (oldstate
== NEIGHBOR_FULL
) /* Decrease number of adjacencies */
141 schedule_rt_lsa(ifa
->oa
);
142 if (ifa
->type
== OSPF_IT_VLINK
) schedule_rt_lsa(ifa
->voa
);
143 schedule_net_lsa(ifa
);
146 if (state
== NEIGHBOR_FULL
) /* Increase number of adjacencies */
149 schedule_rt_lsa(ifa
->oa
);
150 if (ifa
->type
== OSPF_IT_VLINK
) schedule_rt_lsa(ifa
->voa
);
151 schedule_net_lsa(ifa
);
153 if (state
== NEIGHBOR_EXSTART
)
155 if (n
->adj
== 0) /* First time adjacency */
157 n
->dds
= random_u32();
161 n
->myimms
.bit
.ms
= 1;
165 if (state
> NEIGHBOR_EXSTART
)
170 static struct ospf_neighbor
*
173 struct ospf_neighbor
*neigh
, *n1
, *n2
;
177 nid
= ipa_to_u32(neigh
->ip
);
184 WALK_LIST(neigh
, nl
) /* First try those decl. themselves */
186 if (neigh
->state
>= NEIGHBOR_2WAY
) /* Higher than 2WAY */
187 if (neigh
->priority
> 0) /* Eligible */
188 if (neigh
->dr
!= nid
) /* And not decl. itself DR */
190 if (neigh
->bdr
== nid
) /* Declaring BDR */
194 if (neigh
->priority
> n1
->priority
)
196 else if (neigh
->priority
== n1
->priority
)
197 if (neigh
->rid
> n1
->rid
)
205 else /* And NOT declaring BDR */
209 if (neigh
->priority
> n2
->priority
)
211 else if (neigh
->priority
== n2
->priority
)
212 if (neigh
->rid
> n2
->rid
)
228 static struct ospf_neighbor
*
231 struct ospf_neighbor
*neigh
, *n
;
235 nid
= ipa_to_u32(neigh
->ip
);
241 WALK_LIST(neigh
, nl
) /* And now DR */
243 if (neigh
->state
>= NEIGHBOR_2WAY
) /* Higher than 2WAY */
244 if (neigh
->priority
> 0) /* Eligible */
245 if (neigh
->dr
== nid
) /* And declaring itself DR */
249 if (neigh
->priority
> n
->priority
)
251 else if (neigh
->priority
== n
->priority
)
252 if (neigh
->rid
> n
->rid
)
266 can_do_adj(struct ospf_neighbor
*n
)
268 struct ospf_iface
*ifa
;
273 p
= (struct proto
*) (ifa
->oa
->po
);
287 bug("%s: Iface %s in down state?", p
->name
, ifa
->iface
->name
);
289 case OSPF_IS_WAITING
:
290 DBG("%s: Neighbor? on iface %s\n", p
->name
, ifa
->iface
->name
);
292 case OSPF_IS_DROTHER
:
293 if (((n
->rid
== ifa
->drid
) || (n
->rid
== ifa
->bdrid
))
294 && (n
->state
>= NEIGHBOR_2WAY
))
300 if (n
->state
>= NEIGHBOR_2WAY
)
304 bug("%s: Iface %s in unknown state?", p
->name
, ifa
->iface
->name
);
309 bug("%s: Iface %s is unknown type?", p
->name
, ifa
->iface
->name
);
312 DBG("%s: Iface %s can_do_adj=%d\n", p
->name
, ifa
->iface
->name
, i
);
317 * ospf_neigh_sm - ospf neighbor state machine
319 * @event: actual event
321 * This part implements the neighbor state machine as described in 10.3 of
322 * RFC 2328. The only difference is that state %NEIGHBOR_ATTEMPT is not
323 * used. We discover neighbors on nonbroadcast networks in the
324 * same way as on broadcast networks. The only difference is in
325 * sending hello packets. These are sent to IPs listed in
326 * @ospf_iface->nbma_list .
329 ospf_neigh_sm(struct ospf_neighbor
*n
, int event
)
331 struct proto_ospf
*po
= n
->ifa
->oa
->po
;
332 struct proto
*p
= &po
->proto
;
334 DBG("Neighbor state machine for neighbor %I, event '%s'\n", n
->ip
,
340 neigh_chstate(n
, NEIGHBOR_ATTEMPT
);
341 /* NBMA are used different way */
346 case NEIGHBOR_ATTEMPT
:
348 neigh_chstate(n
, NEIGHBOR_INIT
);
350 tm_start(n
->inactim
, n
->ifa
->dead
); /* Restart inactivity timer */
355 if (n
->state
< NEIGHBOR_2WAY
)
356 neigh_chstate(n
, NEIGHBOR_2WAY
);
357 if ((n
->state
== NEIGHBOR_2WAY
) && can_do_adj(n
))
358 neigh_chstate(n
, NEIGHBOR_EXSTART
);
361 if (n
->state
== NEIGHBOR_EXSTART
)
363 neigh_chstate(n
, NEIGHBOR_EXCHANGE
);
365 /* Reset DB summary list iterator */
367 s_init(&(n
->dbsi
), &po
->lsal
);
369 while (!EMPTY_LIST(n
->ackl
[ACKL_DELAY
]))
372 no
= (struct lsah_n
*) HEAD(n
->ackl
[ACKL_DELAY
]);
378 bug("NEGDONE and I'm not in EXSTART?");
381 neigh_chstate(n
, NEIGHBOR_LOADING
);
384 neigh_chstate(n
, NEIGHBOR_FULL
);
390 /* Can In build adjacency? */
393 neigh_chstate(n
, NEIGHBOR_EXSTART
);
397 if (n
->state
>= NEIGHBOR_EXSTART
)
401 neigh_chstate(n
, NEIGHBOR_2WAY
);
408 if (n
->state
>= NEIGHBOR_EXCHANGE
)
411 neigh_chstate(n
, NEIGHBOR_EXSTART
);
418 neigh_chstate(n
, NEIGHBOR_DOWN
);
422 neigh_chstate(n
, NEIGHBOR_INIT
);
425 bug("%s: INM - Unknown event?", p
->name
);
431 * bdr_election - (Backup) Designed Router election
432 * @ifa: actual interface
434 * When the wait timer fires, it is time to elect (Backup) Designated Router.
435 * Structure describing me is added to this list so every electing router
436 * has the same list. Backup Designated Router is elected before Designated
437 * Router. This process is described in 9.4 of RFC 2328.
440 bdr_election(struct ospf_iface
*ifa
)
442 struct ospf_neighbor
*neigh
, *ndr
, *nbdr
, me
;
445 struct proto
*p
= &ifa
->oa
->po
->proto
;
447 DBG("(B)DR election.\n");
449 myid
= p
->cf
->global
->router_id
;
451 me
.state
= NEIGHBOR_2WAY
;
453 me
.priority
= ifa
->priority
;
454 me
.ip
= ifa
->iface
->addr
->ip
;
457 me
.dr
= ipa_to_u32(ifa
->drip
);
458 me
.bdr
= ipa_to_u32(ifa
->bdrip
);
462 me
.iface_id
= ifa
->iface
->index
;
465 add_tail(&ifa
->neigh_list
, NODE
& me
);
467 nbdr
= electbdr(ifa
->neigh_list
);
468 ndr
= electdr(ifa
->neigh_list
);
474 if (((ifa
->drid
== myid
) && (ndr
!= &me
))
475 || ((ifa
->drid
!= myid
) && (ndr
== &me
))
476 || ((ifa
->bdrid
== myid
) && (nbdr
!= &me
))
477 || ((ifa
->bdrid
!= myid
) && (nbdr
== &me
)))
480 me
.dr
= ndr
? ipa_to_u32(ndr
->ip
) : IPA_NONE
;
481 me
.bdr
= nbdr
? ipa_to_u32(nbdr
->ip
) : IPA_NONE
;
483 me
.dr
= ndr
? ndr
->rid
: 0;
484 me
.bdr
= nbdr
? nbdr
->rid
: 0;
487 nbdr
= electbdr(ifa
->neigh_list
);
488 ndr
= electdr(ifa
->neigh_list
);
494 u32 odrid
= ifa
->drid
;
495 u32 obdrid
= ifa
->bdrid
;
497 ifa
->drid
= ndr
? ndr
->rid
: 0;
498 ifa
->drip
= ndr
? ndr
->ip
: IPA_NONE
;
499 ifa
->bdrid
= nbdr
? nbdr
->rid
: 0;
500 ifa
->bdrip
= nbdr
? nbdr
->ip
: IPA_NONE
;
503 ifa
->dr_iface_id
= ndr
? ndr
->iface_id
: 0;
506 DBG("DR=%R, BDR=%R\n", ifa
->drid
, ifa
->bdrid
);
508 doadj
= ((ifa
->drid
!= odrid
) || (ifa
->bdrid
!= obdrid
));
510 if (myid
== ifa
->drid
)
511 ospf_iface_chstate(ifa
, OSPF_IS_DR
);
514 if (myid
== ifa
->bdrid
)
515 ospf_iface_chstate(ifa
, OSPF_IS_BACKUP
);
517 ospf_iface_chstate(ifa
, OSPF_IS_DROTHER
);
524 WALK_LIST(neigh
, ifa
->neigh_list
)
526 ospf_neigh_sm(neigh
, INM_ADJOK
);
531 struct ospf_neighbor
*
532 find_neigh(struct ospf_iface
*ifa
, u32 rid
)
534 struct ospf_neighbor
*n
;
536 WALK_LIST(n
, ifa
->neigh_list
) if (n
->rid
== rid
)
542 /* Find a closest neighbor which is at least 2-Way */
543 struct ospf_neighbor
*
544 find_neigh_noifa(struct proto_ospf
*po
, u32 rid
)
546 struct ospf_neighbor
*n
= NULL
, *m
;
547 struct ospf_iface
*ifa
;
549 WALK_LIST(ifa
, po
->iface_list
) if ((m
= find_neigh(ifa
, rid
)) != NULL
)
551 if (m
->state
>= NEIGHBOR_2WAY
)
555 else if (m
->ifa
->cost
< n
->ifa
->cost
)
563 ospf_find_area(struct proto_ospf
*po
, u32 aid
)
565 struct ospf_area
*oa
;
566 WALK_LIST(oa
, po
->area_list
)
567 if (((struct ospf_area
*) oa
)->areaid
== aid
)
572 /* Neighbor is inactive for a long time. Remove it. */
574 neighbor_timer_hook(timer
* timer
)
576 struct ospf_neighbor
*n
= (struct ospf_neighbor
*) timer
->data
;
577 struct ospf_iface
*ifa
= n
->ifa
;
578 struct proto
*p
= &ifa
->oa
->po
->proto
;
581 "Inactivity timer fired on interface %s for neighbor %I.",
582 ifa
->iface
->name
, n
->ip
);
583 ospf_neigh_remove(n
);
587 ospf_neigh_remove(struct ospf_neighbor
*n
)
589 struct ospf_iface
*ifa
= n
->ifa
;
590 struct proto
*p
= &ifa
->oa
->po
->proto
;
593 neigh_chstate(n
, NEIGHBOR_DOWN
);
596 OSPF_TRACE(D_EVENTS
, "Deleting neigbor.");
600 ospf_sh_neigh_info(struct ospf_neighbor
*n
)
602 struct ospf_iface
*ifa
= n
->ifa
;
607 exp
= n
->inactim
->expires
- now
;
612 bsprintf(etime
, "-Inf-");
616 bsprintf(etime
, "%02u:%02u", min
, sec
);
619 if (n
->rid
== ifa
->drid
)
621 if (n
->rid
== ifa
->bdrid
)
623 if ((n
->ifa
->type
== OSPF_IT_PTP
) || (n
->ifa
->type
== OSPF_IT_VLINK
))
626 cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-1I\t%-10s", n
->rid
, n
->priority
,
627 ospf_ns
[n
->state
], pos
, etime
, n
->ip
,
628 (ifa
->type
== OSPF_IT_VLINK
? "vlink" : ifa
->iface
->name
));
632 rxmt_timer_hook(timer
* timer
)
634 struct ospf_neighbor
*n
= (struct ospf_neighbor
*) timer
->data
;
635 struct proto
*p
= &n
->ifa
->oa
->po
->proto
;
636 struct top_hash_entry
*en
;
638 DBG("%s: RXMT timer fired on interface %s for neigh: %I.\n",
639 p
->name
, n
->ifa
->iface
->name
, n
->ip
);
641 if(n
->state
< NEIGHBOR_EXSTART
) return;
643 if (n
->state
== NEIGHBOR_EXSTART
)
645 ospf_dbdes_send(n
, 1);
649 if ((n
->state
== NEIGHBOR_EXCHANGE
) && n
->myimms
.bit
.ms
) /* I'm master */
650 ospf_dbdes_send(n
, 0);
653 if (n
->state
< NEIGHBOR_FULL
)
654 ospf_lsreq_send(n
); /* EXCHANGE or LOADING */
657 if (!EMPTY_SLIST(n
->lsrtl
)) /* FULL */
661 struct l_lsr_head
*llsh
;
664 upslab
= sl_new(n
->pool
, sizeof(struct l_lsr_head
));
666 WALK_SLIST(en
, n
->lsrtl
)
668 if ((SNODE en
)->next
== (SNODE en
))
669 bug("RTList is cycled");
670 llsh
= sl_alloc(upslab
);
671 llsh
->lsh
.id
= en
->lsa
.id
;
672 llsh
->lsh
.rt
= en
->lsa
.rt
;
673 llsh
->lsh
.type
= en
->lsa
.type
;
674 DBG("Working on ID: %R, RT: %R, Type: %u\n",
675 en
->lsa
.id
, en
->lsa
.rt
, en
->lsa
.type
);
676 add_tail(&uplist
, NODE llsh
);
678 ospf_lsupd_send_list(n
, &uplist
);
685 ackd_timer_hook(timer
* t
)
687 struct ospf_neighbor
*n
= t
->data
;
688 ospf_lsack_send(n
, ACKL_DELAY
);