]>
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",
20 const char *ospf_inm
[]={ "hello received", "neighbor start", "2-way received",
21 "negotiation done", "exstart done", "bad ls request", "load done",
22 "adjacency ok?", "sequence mismatch", "1-way received", "kill neighbor",
23 "inactivity timer", "line down" };
26 void neighbor_timer_hook(timer
*timer
);
27 void rxmt_timer_hook(timer
*timer
);
28 void ackd_timer_hook(timer
*t
);
30 struct ospf_neighbor
*
31 ospf_neighbor_new(struct ospf_iface
*ifa
)
33 struct proto
*p
= (struct proto
*)(ifa
->proto
);
34 struct pool
*pool
= rp_new(p
->pool
, "OSPF Neighbor");
35 struct ospf_neighbor
*n
= mb_allocz(pool
, sizeof(struct ospf_neighbor
));
39 add_tail(&ifa
->neigh_list
, NODE n
);
41 n
->ldbdes
=mb_alloc(pool
, ifa
->iface
->mtu
);
42 n
->state
=NEIGHBOR_DOWN
;
44 n
->inactim
= tm_new(pool
);
46 n
->inactim
->randomize
= 0;
47 n
->inactim
->hook
= neighbor_timer_hook
;
48 n
->inactim
->recurrent
= 0;
49 DBG("%s: Installing inactivity timer.\n", p
->name
);
51 n
->rxmt_timer
= tm_new(pool
);
52 n
->rxmt_timer
->data
= n
;
53 n
->rxmt_timer
->randomize
= 0;
54 n
->rxmt_timer
->hook
= rxmt_timer_hook
;
55 n
->rxmt_timer
->recurrent
= ifa
->rxmtint
;
56 s_init_list(&(n
->lsrql
));
57 n
->lsrqh
= ospf_top_new(pool
, n
->ifa
->proto
);
58 s_init_list(&(n
->lsrtl
));
59 n
->lsrth
= ospf_top_new(pool
, n
->ifa
->proto
);
60 s_init(&(n
->lsrqi
), &(n
->lsrql
));
61 s_init(&(n
->lsrti
), &(n
->lsrtl
));
62 tm_start(n
->rxmt_timer
,n
->ifa
->rxmtint
);
63 DBG("%s: Installing rxmt timer.\n", p
->name
);
65 n
->ackd_timer
= tm_new(pool
);
66 n
->ackd_timer
->data
= n
;
67 n
->ackd_timer
->randomize
= 0;
68 n
->ackd_timer
->hook
= ackd_timer_hook
;
69 n
->ackd_timer
->recurrent
= ifa
->rxmtint
/2;
70 init_list(&n
->ackl
[ACKL_DIRECT
]);
71 init_list(&n
->ackl
[ACKL_DELAY
]);
72 tm_start(n
->ackd_timer
,n
->ifa
->rxmtint
/2);
73 DBG("%s: Installing ackd timer.\n", p
->name
);
79 * neigh_chstate - handles changes related to new or lod state of neighbor
83 * Many actions have to be taken acording to a change of state of a neighbor. It
84 * starts rxmt timers, call interface state machine etc.
88 neigh_chstate(struct ospf_neighbor
*n
, u8 state
)
96 struct ospf_iface
*ifa
=n
->ifa
;
97 struct proto_ospf
*po
=ifa
->oa
->po
;
98 struct proto
*p
=&po
->proto
;
102 OSPF_TRACE( D_EVENTS
, "Neighbor %I changes state from \"%s\" to \"%s\".",
103 n
->ip
, ospf_ns
[oldstate
], ospf_ns
[state
]);
105 if((state
==NEIGHBOR_2WAY
) && (oldstate
<NEIGHBOR_2WAY
))
106 ospf_int_sm(ifa
, ISM_NEICH
);
107 if((state
<NEIGHBOR_2WAY
) && (oldstate
>=NEIGHBOR_2WAY
))
108 ospf_int_sm(ifa
, ISM_NEICH
);
110 if(oldstate
==NEIGHBOR_FULL
) /* Decrease number of adjacencies */
113 schedule_rt_lsa(ifa
->oa
);
114 schedule_net_lsa(ifa
);
117 if(state
==NEIGHBOR_FULL
) /* Increase number of adjacencies */
120 schedule_rt_lsa(ifa
->oa
);
121 schedule_net_lsa(ifa
);
123 if(state
==NEIGHBOR_EXSTART
)
125 if(n
->adj
==0) /* First time adjacency */
135 if(state
>NEIGHBOR_EXSTART
) n
->myimms
.bit
.i
=0;
139 struct ospf_neighbor
*
142 struct ospf_neighbor
*neigh
,*n1
,*n2
;
146 WALK_LIST (neigh
, nl
) /* First try those decl. themselves */
148 if(neigh
->state
>=NEIGHBOR_2WAY
) /* Higher than 2WAY */
149 if(neigh
->priority
>0) /* Eligible */
150 if(ipa_compare(neigh
->ip
,neigh
->dr
)!=0) /* And not decl. itself DR */
152 if(ipa_compare(neigh
->ip
,neigh
->bdr
)==0) /* Declaring BDR */
156 if(neigh
->priority
>n1
->priority
) n1
=neigh
;
157 else if(neigh
->priority
==n1
->priority
)
158 if(neigh
->rid
>n1
->rid
) n1
=neigh
;
165 else /* And NOT declaring BDR */
169 if(neigh
->priority
>n2
->priority
) n2
=neigh
;
170 else if(neigh
->priority
==n2
->priority
)
171 if(neigh
->rid
>n2
->rid
) n2
=neigh
;
185 struct ospf_neighbor
*
188 struct ospf_neighbor
*neigh
,*n
;
191 WALK_LIST (neigh
, nl
) /* And now DR */
193 if(neigh
->state
>=NEIGHBOR_2WAY
) /* Higher than 2WAY */
194 if(neigh
->priority
>0) /* Eligible */
195 if(ipa_compare(neigh
->ip
,neigh
->dr
)==0) /* And declaring itself DR */
199 if(neigh
->priority
>n
->priority
) n
=neigh
;
200 else if(neigh
->priority
==n
->priority
)
201 if(neigh
->rid
>n
->rid
) n
=neigh
;
214 can_do_adj(struct ospf_neighbor
*n
)
216 struct ospf_iface
*ifa
;
221 p
=(struct proto
*)(ifa
->proto
);
235 bug("%s: Iface %s in down state?", p
->name
, ifa
->iface
->name
);
237 case OSPF_IS_WAITING
:
238 DBG("%s: Neighbor? on iface %s\n",p
->name
, ifa
->iface
->name
);
240 case OSPF_IS_DROTHER
:
241 if(((n
->rid
==ifa
->drid
) || (n
->rid
==ifa
->bdrid
))
242 && (n
->state
>=NEIGHBOR_2WAY
)) i
=1;
247 if(n
->state
>=NEIGHBOR_2WAY
) i
=1;
250 bug("%s: Iface %s in unknown state?",p
->name
, ifa
->iface
->name
);
255 bug("%s: Iface %s is unknown type?",p
->name
, ifa
->iface
->name
);
258 DBG("%s: Iface %s can_do_adj=%d\n",p
->name
, ifa
->iface
->name
,i
);
263 * ospf_neigh_sm - ospf neighbor state machine
265 * @event: actual event
267 * This part implements the neighbor state machine as described in 10.3 of
268 * RFC 2328. The only difference is that state %NEIGHBOR_ATTEMPT is not
269 * used. We discover neighbors on nonbroadcast networks in the
270 * same way as on broadcast networks. The only difference is in
271 * sending hello packets. These are sent to IPs listed in
272 * @ospf_iface->nbma_list .
275 ospf_neigh_sm(struct ospf_neighbor
*n
, int event
)
277 struct proto
*p
=(struct proto
*)(n
->ifa
->proto
);
278 struct proto_ospf
*po
=n
->ifa
->proto
;
280 DBG("%s: Neighbor state machine for neighbor %I, event \"%s\".\n",
281 p
->name
, n
->rid
, ospf_inm
[event
]);
286 neigh_chstate(n
,NEIGHBOR_ATTEMPT
);
287 /* NBMA are used different way */
292 case NEIGHBOR_ATTEMPT
:
294 neigh_chstate(n
, NEIGHBOR_INIT
);
296 tm_start(n
->inactim
, n
->ifa
->deadc
*n
->ifa
->helloint
); /* Restart inactivity timer */
301 if(n
->state
<NEIGHBOR_2WAY
) neigh_chstate(n
,NEIGHBOR_2WAY
);
302 if((n
->state
==NEIGHBOR_2WAY
) && can_do_adj(n
))
303 neigh_chstate(n
,NEIGHBOR_EXSTART
);
306 if(n
->state
==NEIGHBOR_EXSTART
)
308 neigh_chstate(n
,NEIGHBOR_EXCHANGE
);
309 s_init(&(n
->dbsi
), &(n
->ifa
->oa
->lsal
));
310 while(!EMPTY_LIST(n
->ackl
[ACKL_DELAY
]))
313 no
=(struct lsah_n
*)HEAD(n
->ackl
[ACKL_DELAY
]);
318 else bug("NEGDONE and I'm not in EXSTART?");
321 neigh_chstate(n
,NEIGHBOR_LOADING
);
324 neigh_chstate(n
,NEIGHBOR_FULL
);
330 /* Can In build adjacency? */
333 neigh_chstate(n
,NEIGHBOR_EXSTART
);
337 if(n
->state
>=NEIGHBOR_EXSTART
)
340 neigh_chstate(n
,NEIGHBOR_2WAY
);
346 OSPF_TRACE(D_EVENTS
, "Seq mis!");
348 OSPF_TRACE(D_EVENTS
, "Bad LS req!");
349 if(n
->state
>=NEIGHBOR_EXCHANGE
)
351 neigh_chstate(n
,NEIGHBOR_EXSTART
);
357 neigh_chstate(n
,NEIGHBOR_DOWN
);
360 neigh_chstate(n
,NEIGHBOR_INIT
);
363 bug("%s: INM - Unknown event?",p
->name
);
369 * bdr_election - (Backup) Designed Router election
370 * @ifa: actual interface
372 * When the wait timer fires, it is time to elect (Backup) Designated Router.
373 * Structure describing me is added to this list so every electing router
374 * has the same list. Backup Designated Router is elected before Designated
375 * Router. This process is described in 9.4 of RFC 2328.
378 bdr_election(struct ospf_iface
*ifa
)
380 struct ospf_neighbor
*neigh
,*ndr
,*nbdr
,me
,*tmp
;
382 ip_addr ndrip
, nbdrip
;
384 struct proto
*p
=&ifa
->proto
->proto
;
386 DBG("(B)DR election.\n");
388 myid
=p
->cf
->global
->router_id
;
390 me
.state
=NEIGHBOR_2WAY
;
392 me
.priority
=ifa
->priority
;
395 me
.ip
=ifa
->iface
->addr
->ip
;
397 add_tail(&ifa
->neigh_list
, NODE
&me
);
399 nbdr
=electbdr(ifa
->neigh_list
);
400 ndr
=electdr(ifa
->neigh_list
);
402 if(ndr
==NULL
) ndr
=nbdr
;
404 if(((ifa
->drid
==myid
) && (ndr
!=&me
))
405 || ((ifa
->drid
!=myid
) && (ndr
==&me
))
406 || ((ifa
->bdrid
==myid
) && (nbdr
!=&me
))
407 || ((ifa
->bdrid
!=myid
) && (nbdr
==&me
)))
409 if(ndr
==NULL
) ifa
->drip
=me
.dr
=ipa_from_u32(0);
410 else ifa
->drip
=me
.dr
=ndr
->ip
;
412 if(nbdr
==NULL
) ifa
->bdrip
=me
.bdr
=ipa_from_u32(0);
413 else ifa
->bdrip
=me
.bdr
=nbdr
->ip
;
415 nbdr
=electbdr(ifa
->neigh_list
);
416 ndr
=electdr(ifa
->neigh_list
);
419 if(ndr
==NULL
) ndrip
=ipa_from_u32(0);
422 if(nbdr
==NULL
) nbdrip
=ipa_from_u32(0);
423 else nbdrip
=nbdr
->ip
;
426 if((ipa_compare(ifa
->drip
,ndrip
)!=0) || (ipa_compare(ifa
->bdrip
,nbdrip
)!=0))
432 ifa
->drip
=ipa_from_u32(0);
443 ifa
->bdrip
=ipa_from_u32(0);
447 ifa
->bdrid
=nbdr
->rid
;
451 DBG("DR=%I, BDR=%I\n", ifa
->drid
, ifa
->bdrid
);
453 if(myid
==ifa
->drid
) iface_chstate(ifa
, OSPF_IS_DR
);
456 if(myid
==ifa
->bdrid
) iface_chstate(ifa
, OSPF_IS_BACKUP
);
457 else iface_chstate(ifa
, OSPF_IS_DROTHER
);
464 WALK_LIST (neigh
, ifa
->neigh_list
)
466 ospf_neigh_sm(neigh
, INM_ADJOK
);
471 struct ospf_neighbor
*
472 find_neigh(struct ospf_iface
*ifa
, u32 rid
)
474 struct ospf_neighbor
*n
;
476 WALK_LIST (n
, ifa
->neigh_list
)
483 /* Find a closest neighbor which is at leas 2-Way */
484 struct ospf_neighbor
*
485 find_neigh_noifa(struct proto_ospf
*po
, u32 rid
)
487 struct ospf_neighbor
*n
=NULL
,*m
;
488 struct ospf_iface
*ifa
;
490 WALK_LIST (ifa
, po
->iface_list
)
491 if((m
=find_neigh(ifa
, rid
))!=NULL
)
493 if(m
->state
>=NEIGHBOR_2WAY
)
497 if(m
->ifa
->cost
< n
->ifa
->cost
) n
=m
;
504 ospf_find_area(struct proto_ospf
*po
, u32 aid
)
506 struct ospf_area
*oa
;
507 WALK_LIST(NODE oa
,po
->area_list
)
508 if(((struct ospf_area
*)oa
)->areaid
==aid
) return oa
;
512 /* Neighbor is inactive for a long time. Remove it. */
514 neighbor_timer_hook(timer
*timer
)
516 struct ospf_neighbor
*n
;
517 struct ospf_iface
*ifa
;
520 n
=(struct ospf_neighbor
*)timer
->data
;
522 p
=(struct proto
*)(ifa
->proto
);
523 OSPF_TRACE(D_EVENTS
,"Inactivity timer fired on interface %s for neighbor %I.",
524 ifa
->iface
->name
, n
->ip
);
525 ospf_neigh_remove(n
);
529 ospf_neigh_remove(struct ospf_neighbor
*n
)
531 struct ospf_iface
*ifa
;
535 p
=(struct proto
*)(ifa
->proto
);
536 neigh_chstate(n
, NEIGHBOR_DOWN
);
539 OSPF_TRACE(D_EVENTS
, "Deleting neigbor.");
543 ospf_sh_neigh_info(struct ospf_neighbor
*n
)
545 struct ospf_iface
*ifa
=n
->ifa
;
550 exp
=n
->inactim
->expires
-now
;
555 bsprintf(etime
,"-Inf-");
559 bsprintf(etime
,"%02u:%02u", min
, sec
);
562 if(n
->rid
==ifa
->drid
) pos
="dr ";
563 if(n
->rid
==ifa
->bdrid
) pos
="bdr ";
564 if(n
->ifa
->type
==OSPF_IT_PTP
) pos
="ptp ";
566 cli_msg(-1013,"%-1I\t%3u\t%s/%s\t%-5s\t%-1I\t%-10s",n
->rid
, n
->priority
,
567 ospf_ns
[n
->state
], pos
, etime
, n
->ip
,ifa
->iface
->name
);
571 rxmt_timer_hook(timer
*timer
)
573 struct ospf_neighbor
*n
= (struct ospf_neighbor
*)timer
->data
;
574 struct ospf_iface
*ifa
= n
->ifa
;
575 struct proto
*p
= (struct proto
*)(ifa
->proto
);
576 struct top_hash_entry
*en
;
578 DBG("%s: RXMT timer fired on interface %s for neigh: %I.\n",
579 p
->name
, ifa
->iface
->name
, n
->ip
);
580 if (n
->state
< NEIGHBOR_LOADING
) ospf_dbdes_send(n
);
582 if(n
->state
< NEIGHBOR_FULL
) ospf_lsreq_send(n
);
585 if(!EMPTY_SLIST(n
->lsrtl
))
589 struct l_lsr_head
*llsh
;
592 upslab
=sl_new(n
->pool
,sizeof(struct l_lsr_head
));
594 WALK_SLIST(SNODE en
,n
->lsrtl
)
596 if((SNODE en
)->next
==(SNODE en
)) bug("RTList is cycled");
597 llsh
=sl_alloc(upslab
);
598 llsh
->lsh
.id
=en
->lsa
.id
;
599 llsh
->lsh
.rt
=en
->lsa
.rt
;
600 llsh
->lsh
.type
=en
->lsa
.type
;
601 DBG("Working on ID: %I, RT: %I, Type: %u\n",
602 en
->lsa
.id
, en
->lsa
.rt
, en
->lsa
.type
);
603 add_tail(&uplist
, NODE llsh
);
605 ospf_lsupd_tx_list(n
, &uplist
);
612 ackd_timer_hook(timer
*t
)
614 struct ospf_neighbor
*n
=t
->data
;
615 ospf_lsack_send(n
, ACKL_DELAY
);