]> git.ipfire.org Git - thirdparty/bird.git/blame - proto/ospf/neighbor.c
OSPF: DD seqnum should be initialized only for first attempts
[thirdparty/bird.git] / proto / ospf / neighbor.c
CommitLineData
4364b47e
OF
1/*
2 * BIRD -- OSPF
3 *
70945cb6
OZ
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.
4364b47e
OF
7 *
8 * Can be freely distributed and used under the terms of the GNU GPL.
9 */
10
11#include "ospf.h"
12
f8fefde3
OZ
13
14const char *ospf_ns_names[] = {
15 "Down", "Attempt", "Init", "2-Way", "ExStart", "Exchange", "Loading", "Full"
2e10a170
OF
16};
17
f8fefde3
OZ
18const char *ospf_inm_names[] = {
19 "HelloReceived", "Start", "2-WayReceived", "NegotiationDone", "ExchangeDone",
20 "BadLSReq", "LoadingDone", "AdjOK?", "SeqNumberMismatch", "1-WayReceived",
21 "KillNbr", "InactivityTimer", "LLDown"
2e10a170 22};
79f036ef 23
f8fefde3
OZ
24
25static int can_do_adj(struct ospf_neighbor *n);
6f8bbaa1
OZ
26static void inactivity_timer_hook(timer * timer);
27static void dbdes_timer_hook(timer *t);
28static void lsrq_timer_hook(timer *t);
29static void lsrt_timer_hook(timer *t);
30static void ackd_timer_hook(timer *t);
31
0844b65d
OZ
32
33static void
a7a7372a 34init_lists(struct ospf_proto *p, struct ospf_neighbor *n)
0844b65d
OZ
35{
36 s_init_list(&(n->lsrql));
6f8bbaa1 37 n->lsrqi = SHEAD(n->lsrql);
a7a7372a 38 n->lsrqh = ospf_top_new(p, n->pool);
0844b65d
OZ
39
40 s_init_list(&(n->lsrtl));
a7a7372a
OZ
41 n->lsrth = ospf_top_new(p, n->pool);
42}
43
44static void
45release_lsrtl(struct ospf_proto *p, struct ospf_neighbor *n)
46{
47 struct top_hash_entry *ret, *en;
48
49 WALK_SLIST(ret, n->lsrtl)
50 {
51 en = ospf_hash_find_entry(p->gr, ret);
52 if (en)
53 en->ret_count--;
54 }
0844b65d 55}
39e517d4 56
0dd7ccc7 57/* Resets LSA request and retransmit lists.
742029eb 58 * We do not reset DB summary list iterator here,
0844b65d
OZ
59 * it is reset during entering EXCHANGE state.
60 */
61static void
a7a7372a 62reset_lists(struct ospf_proto *p, struct ospf_neighbor *n)
0844b65d 63{
6f8bbaa1 64 release_lsrtl(p, n);
0844b65d
OZ
65 ospf_top_free(n->lsrqh);
66 ospf_top_free(n->lsrth);
6f8bbaa1
OZ
67 ospf_reset_lsack_queue(n);
68
a6f79ca5
OZ
69 tm_stop(n->dbdes_timer);
70 tm_stop(n->lsrq_timer);
71 tm_stop(n->lsrt_timer);
72 tm_stop(n->ackd_timer);
6f8bbaa1 73
a7a7372a 74 init_lists(p, n);
0844b65d 75}
39e517d4
OF
76
77struct ospf_neighbor *
78ospf_neighbor_new(struct ospf_iface *ifa)
79{
70945cb6
OZ
80 struct ospf_proto *p = ifa->oa->po;
81 struct pool *pool = rp_new(p->p.pool, "OSPF Neighbor");
39e517d4
OF
82 struct ospf_neighbor *n = mb_allocz(pool, sizeof(struct ospf_neighbor));
83
84 n->pool = pool;
85 n->ifa = ifa;
86 add_tail(&ifa->neigh_list, NODE n);
2e10a170 87 n->state = NEIGHBOR_DOWN;
39e517d4 88
a7a7372a 89 init_lists(p, n);
70945cb6 90 s_init(&(n->dbsi), &(p->lsal));
0844b65d 91
c76ba51a
OF
92 init_list(&n->ackl[ACKL_DIRECT]);
93 init_list(&n->ackl[ACKL_DELAY]);
6f8bbaa1 94
a6f79ca5
OZ
95 n->inactim = tm_new_init(pool, inactivity_timer_hook, n, 0, 0);
96 n->dbdes_timer = tm_new_init(pool, dbdes_timer_hook, n, ifa->rxmtint S, 0);
97 n->lsrq_timer = tm_new_init(pool, lsrq_timer_hook, n, ifa->rxmtint S, 0);
98 n->lsrt_timer = tm_new_init(pool, lsrt_timer_hook, n, ifa->rxmtint S, 0);
99 n->ackd_timer = tm_new_init(pool, ackd_timer_hook, n, ifa->rxmtint S / 2, 0);
39e517d4 100
2e10a170 101 return (n);
39e517d4
OF
102}
103
f8fefde3
OZ
104static void
105ospf_neigh_down(struct ospf_neighbor *n)
106{
107 struct ospf_iface *ifa = n->ifa;
108 struct ospf_proto *p = ifa->oa->po;
a459f4df 109 u32 rid = n->rid;
f8fefde3
OZ
110
111 if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
112 {
113 struct nbma_node *nn = find_nbma_node(ifa, n->ip);
114 if (nn)
115 nn->found = 0;
116 }
117
118 s_get(&(n->dbsi));
119 release_lsrtl(p, n);
120 rem_node(NODE n);
121 rfree(n->pool);
122
a459f4df 123 OSPF_TRACE(D_EVENTS, "Neighbor %R on %s removed", rid, ifa->ifname);
f8fefde3
OZ
124}
125
7ab3ff6a 126/**
f8fefde3 127 * ospf_neigh_chstate - handles changes related to new or lod state of neighbor
7ab3ff6a
OF
128 * @n: OSPF neighbor
129 * @state: new state
130 *
baa5dd6c 131 * Many actions have to be taken acording to a change of state of a neighbor. It
7ab3ff6a
OF
132 * starts rxmt timers, call interface state machine etc.
133 */
0844b65d 134static void
f8fefde3 135ospf_neigh_chstate(struct ospf_neighbor *n, u8 state)
4364b47e 136{
70945cb6
OZ
137 struct ospf_iface *ifa = n->ifa;
138 struct ospf_proto *p = ifa->oa->po;
139 u8 old_state = n->state;
140 int old_fadj = ifa->fadj;
4364b47e 141
70945cb6
OZ
142 if (state == old_state)
143 return;
eae4fcf2 144
f8fefde3
OZ
145 OSPF_TRACE(D_EVENTS, "Neighbor %R on %s changed state from %s to %s",
146 n->rid, ifa->ifname, ospf_ns_names[old_state], ospf_ns_names[state]);
4057093f 147
70945cb6 148 n->state = state;
4057093f 149
70945cb6
OZ
150 /* Increase number of partial adjacencies */
151 if ((state == NEIGHBOR_EXCHANGE) || (state == NEIGHBOR_LOADING))
152 p->padj++;
4057093f 153
70945cb6
OZ
154 /* Decrease number of partial adjacencies */
155 if ((old_state == NEIGHBOR_EXCHANGE) || (old_state == NEIGHBOR_LOADING))
156 p->padj--;
2e10a170 157
70945cb6
OZ
158 /* Increase number of full adjacencies */
159 if (state == NEIGHBOR_FULL)
160 ifa->fadj++;
161
162 /* Decrease number of full adjacencies */
163 if (old_state == NEIGHBOR_FULL)
164 ifa->fadj--;
165
166 if (ifa->fadj != old_fadj)
167 {
168 /* RFC 2328 12.4 Event 4 - neighbor enters/leaves Full state */
169 ospf_notify_rt_lsa(ifa->oa);
170 ospf_notify_net_lsa(ifa);
171
172 /* RFC 2328 12.4 Event 8 - vlink state change */
173 if (ifa->type == OSPF_IT_VLINK)
174 ospf_notify_rt_lsa(ifa->voa);
175 }
176
177 if (state == NEIGHBOR_EXSTART)
178 {
9c94583a
OZ
179 /* First time adjacency attempt */
180 if (old_state < NEIGHBOR_EXSTART)
70945cb6
OZ
181 n->dds = random_u32();
182
183 n->dds++;
184 n->myimms = DBDES_IMMS;
6f8bbaa1 185
a6f79ca5
OZ
186 tm_start(n->dbdes_timer, 0);
187 tm_start(n->ackd_timer, ifa->rxmtint S / 2);
4364b47e 188 }
70945cb6
OZ
189
190 if (state > NEIGHBOR_EXSTART)
191 n->myimms &= ~DBDES_I;
4364b47e 192
f8fefde3
OZ
193 /* Generate NeighborChange event if needed, see RFC 2328 9.2 */
194 if ((state == NEIGHBOR_2WAY) && (old_state < NEIGHBOR_2WAY))
195 ospf_iface_sm(ifa, ISM_NEICH);
196 if ((state < NEIGHBOR_2WAY) && (old_state >= NEIGHBOR_2WAY))
197 ospf_iface_sm(ifa, ISM_NEICH);
4364b47e
OF
198}
199
7ab3ff6a
OF
200/**
201 * ospf_neigh_sm - ospf neighbor state machine
202 * @n: neighor
203 * @event: actual event
204 *
baa5dd6c
OF
205 * This part implements the neighbor state machine as described in 10.3 of
206 * RFC 2328. The only difference is that state %NEIGHBOR_ATTEMPT is not
207 * used. We discover neighbors on nonbroadcast networks in the
208 * same way as on broadcast networks. The only difference is in
209 * sending hello packets. These are sent to IPs listed in
7ab3ff6a
OF
210 * @ospf_iface->nbma_list .
211 */
4364b47e
OF
212void
213ospf_neigh_sm(struct ospf_neighbor *n, int event)
4364b47e 214{
70945cb6 215 struct ospf_proto *p = n->ifa->oa->po;
4364b47e 216
f8fefde3
OZ
217 DBG("Neighbor state machine for %R on %s, event %s\n",
218 n->rid, n->ifa->ifname, ospf_inm_names[event]);
79f036ef 219
2e10a170 220 switch (event)
4364b47e 221 {
2e10a170 222 case INM_START:
f8fefde3 223 ospf_neigh_chstate(n, NEIGHBOR_ATTEMPT);
2e10a170
OF
224 /* NBMA are used different way */
225 break;
70945cb6 226
2e10a170 227 case INM_HELLOREC:
f8fefde3
OZ
228 if (n->state < NEIGHBOR_INIT)
229 ospf_neigh_chstate(n, NEIGHBOR_INIT);
70945cb6
OZ
230
231 /* Restart inactivity timer */
a6f79ca5 232 tm_start(n->inactim, n->ifa->deadint S);
2e10a170 233 break;
70945cb6 234
2e10a170
OF
235 case INM_2WAYREC:
236 if (n->state < NEIGHBOR_2WAY)
f8fefde3 237 ospf_neigh_chstate(n, NEIGHBOR_2WAY);
2e10a170 238 if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
f8fefde3 239 ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
2e10a170 240 break;
70945cb6 241
2e10a170
OF
242 case INM_NEGDONE:
243 if (n->state == NEIGHBOR_EXSTART)
244 {
f8fefde3 245 ospf_neigh_chstate(n, NEIGHBOR_EXCHANGE);
0844b65d
OZ
246
247 /* Reset DB summary list iterator */
248 s_get(&(n->dbsi));
70945cb6 249 s_init(&(n->dbsi), &p->lsal);
0844b65d 250
a7a7372a
OZ
251 /* Add MaxAge LSA entries to retransmission list */
252 ospf_add_flushed_to_lsrt(p, n);
2e10a170
OF
253 }
254 else
255 bug("NEGDONE and I'm not in EXSTART?");
256 break;
70945cb6 257
2e10a170 258 case INM_EXDONE:
6f8bbaa1
OZ
259 if (!EMPTY_SLIST(n->lsrql))
260 ospf_neigh_chstate(n, NEIGHBOR_LOADING);
261 else
262 ospf_neigh_chstate(n, NEIGHBOR_FULL);
2e10a170 263 break;
70945cb6 264
2e10a170 265 case INM_LOADDONE:
f8fefde3 266 ospf_neigh_chstate(n, NEIGHBOR_FULL);
2e10a170 267 break;
70945cb6 268
2e10a170 269 case INM_ADJOK:
6f8bbaa1
OZ
270 /* Can In build adjacency? */
271 if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
2e10a170 272 {
6f8bbaa1
OZ
273 ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
274 }
275 else if ((n->state >= NEIGHBOR_EXSTART) && !can_do_adj(n))
276 {
277 reset_lists(p, n);
278 ospf_neigh_chstate(n, NEIGHBOR_2WAY);
2e10a170
OF
279 }
280 break;
70945cb6 281
2e10a170
OF
282 case INM_SEQMIS:
283 case INM_BADLSREQ:
284 if (n->state >= NEIGHBOR_EXCHANGE)
285 {
a7a7372a 286 reset_lists(p, n);
f8fefde3 287 ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
2e10a170
OF
288 }
289 break;
70945cb6 290
2e10a170
OF
291 case INM_KILLNBR:
292 case INM_LLDOWN:
293 case INM_INACTTIM:
f8fefde3
OZ
294 /* No need for reset_lists() */
295 ospf_neigh_chstate(n, NEIGHBOR_DOWN);
296 ospf_neigh_down(n);
2e10a170 297 break;
70945cb6 298
2e10a170 299 case INM_1WAYREC:
a7a7372a 300 reset_lists(p, n);
f8fefde3 301 ospf_neigh_chstate(n, NEIGHBOR_INIT);
2e10a170 302 break;
70945cb6 303
2e10a170 304 default:
70945cb6 305 bug("%s: INM - Unknown event?", p->p.name);
2e10a170 306 break;
4364b47e
OF
307 }
308}
309
f8fefde3
OZ
310static int
311can_do_adj(struct ospf_neighbor *n)
312{
313 struct ospf_iface *ifa = n->ifa;
314 struct ospf_proto *p = ifa->oa->po;
315 int i = 0;
316
317 switch (ifa->type)
318 {
319 case OSPF_IT_PTP:
320 case OSPF_IT_PTMP:
321 case OSPF_IT_VLINK:
322 i = 1;
323 break;
324 case OSPF_IT_BCAST:
325 case OSPF_IT_NBMA:
326 switch (ifa->state)
327 {
328 case OSPF_IS_DOWN:
329 case OSPF_IS_LOOP:
330 bug("%s: Iface %s in down state?", p->p.name, ifa->ifname);
331 break;
332 case OSPF_IS_WAITING:
333 DBG("%s: Neighbor? on iface %s\n", p->p.name, ifa->ifname);
334 break;
335 case OSPF_IS_DROTHER:
336 if (((n->rid == ifa->drid) || (n->rid == ifa->bdrid))
337 && (n->state >= NEIGHBOR_2WAY))
338 i = 1;
339 break;
340 case OSPF_IS_PTP:
341 case OSPF_IS_BACKUP:
342 case OSPF_IS_DR:
343 if (n->state >= NEIGHBOR_2WAY)
344 i = 1;
345 break;
346 default:
347 bug("%s: Iface %s in unknown state?", p->p.name, ifa->ifname);
348 break;
349 }
350 break;
351 default:
352 bug("%s: Iface %s is unknown type?", p->p.name, ifa->ifname);
353 break;
354 }
355 DBG("%s: Iface %s can_do_adj=%d\n", p->p.name, ifa->ifname, i);
356 return i;
357}
358
359
360static inline u32 neigh_get_id(struct ospf_proto *p, struct ospf_neighbor *n)
361{ return ospf_is_v2(p) ? ipa_to_u32(n->ip) : n->rid; }
362
363static struct ospf_neighbor *
364elect_bdr(struct ospf_proto *p, list nl)
365{
366 struct ospf_neighbor *neigh, *n1, *n2;
367 u32 nid;
368
369 n1 = NULL;
370 n2 = NULL;
371 WALK_LIST(neigh, nl) /* First try those decl. themselves */
372 {
373 nid = neigh_get_id(p, neigh);
374
375 if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
376 if (neigh->priority > 0) /* Eligible */
377 if (neigh->dr != nid) /* And not decl. itself DR */
378 {
379 if (neigh->bdr == nid) /* Declaring BDR */
380 {
381 if (n1 != NULL)
382 {
383 if (neigh->priority > n1->priority)
384 n1 = neigh;
385 else if (neigh->priority == n1->priority)
386 if (neigh->rid > n1->rid)
387 n1 = neigh;
388 }
389 else
390 {
391 n1 = neigh;
392 }
393 }
394 else /* And NOT declaring BDR */
395 {
396 if (n2 != NULL)
397 {
398 if (neigh->priority > n2->priority)
399 n2 = neigh;
400 else if (neigh->priority == n2->priority)
401 if (neigh->rid > n2->rid)
402 n2 = neigh;
403 }
404 else
405 {
406 n2 = neigh;
407 }
408 }
409 }
410 }
411 if (n1 == NULL)
412 n1 = n2;
413
414 return (n1);
415}
416
417static struct ospf_neighbor *
418elect_dr(struct ospf_proto *p, list nl)
419{
420 struct ospf_neighbor *neigh, *n;
421 u32 nid;
422
423 n = NULL;
424 WALK_LIST(neigh, nl) /* And now DR */
425 {
426 nid = neigh_get_id(p, neigh);
427
428 if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
429 if (neigh->priority > 0) /* Eligible */
430 if (neigh->dr == nid) /* And declaring itself DR */
431 {
432 if (n != NULL)
433 {
434 if (neigh->priority > n->priority)
435 n = neigh;
436 else if (neigh->priority == n->priority)
437 if (neigh->rid > n->rid)
438 n = neigh;
439 }
440 else
441 {
442 n = neigh;
443 }
444 }
445 }
446
447 return (n);
448}
449
7ab3ff6a 450/**
70945cb6 451 * ospf_dr_election - (Backup) Designed Router election
7ab3ff6a
OF
452 * @ifa: actual interface
453 *
baa5dd6c 454 * When the wait timer fires, it is time to elect (Backup) Designated Router.
f8fefde3
OZ
455 * Structure describing me is added to this list so every electing router has
456 * the same list. Backup Designated Router is elected before Designated
457 * Router. This process is described in 9.4 of RFC 2328. The function is
458 * supposed to be called only from ospf_iface_sm() as a part of the interface
459 * state machine.
7ab3ff6a 460 */
4364b47e 461void
70945cb6 462ospf_dr_election(struct ospf_iface *ifa)
4364b47e 463{
70945cb6 464 struct ospf_proto *p = ifa->oa->po;
2e10a170 465 struct ospf_neighbor *neigh, *ndr, *nbdr, me;
70945cb6 466 u32 myid = p->router_id;
4364b47e 467
423230f2 468 DBG("(B)DR election.\n");
4364b47e 469
2e10a170
OF
470 me.state = NEIGHBOR_2WAY;
471 me.rid = myid;
472 me.priority = ifa->priority;
353729f5 473 me.ip = ifa->addr->ip;
4364b47e 474
70945cb6
OZ
475 me.dr = ospf_is_v2(p) ? ipa_to_u32(ifa->drip) : ifa->drid;
476 me.bdr = ospf_is_v2(p) ? ipa_to_u32(ifa->bdrip) : ifa->bdrid;
dd4da6f6 477 me.iface_id = ifa->iface_id;
c3226991 478
2e10a170 479 add_tail(&ifa->neigh_list, NODE & me);
4364b47e 480
70945cb6
OZ
481 nbdr = elect_bdr(p, ifa->neigh_list);
482 ndr = elect_dr(p, ifa->neigh_list);
4364b47e 483
2e10a170
OF
484 if (ndr == NULL)
485 ndr = nbdr;
4364b47e 486
c3226991 487 /* 9.4. (4) */
2e10a170
OF
488 if (((ifa->drid == myid) && (ndr != &me))
489 || ((ifa->drid != myid) && (ndr == &me))
490 || ((ifa->bdrid == myid) && (nbdr != &me))
491 || ((ifa->bdrid != myid) && (nbdr == &me)))
4364b47e 492 {
70945cb6
OZ
493 me.dr = ndr ? neigh_get_id(p, ndr) : 0;
494 me.bdr = nbdr ? neigh_get_id(p, nbdr) : 0;
2e10a170 495
70945cb6
OZ
496 nbdr = elect_bdr(p, ifa->neigh_list);
497 ndr = elect_dr(p, ifa->neigh_list);
423230f2 498
c3226991
OZ
499 if (ndr == NULL)
500 ndr = nbdr;
28950169
OF
501 }
502
70945cb6
OZ
503 rem_node(NODE & me);
504
505
506 u32 old_drid = ifa->drid;
507 u32 old_bdrid = ifa->bdrid;
04632fd7 508 ip_addr none = ospf_is_v2(p) ? IPA_NONE4 : IPA_NONE6;
742029eb 509
c3226991 510 ifa->drid = ndr ? ndr->rid : 0;
04632fd7 511 ifa->drip = ndr ? ndr->ip : none;
70945cb6
OZ
512 ifa->dr_iface_id = ndr ? ndr->iface_id : 0;
513
c3226991 514 ifa->bdrid = nbdr ? nbdr->rid : 0;
04632fd7 515 ifa->bdrip = nbdr ? nbdr->ip : none;
c3226991 516
3aab39f5 517 DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid);
4364b47e 518
f8fefde3 519 /* We are part of the interface state machine */
70945cb6 520 if (ifa->drid == myid)
2e10a170 521 ospf_iface_chstate(ifa, OSPF_IS_DR);
70945cb6
OZ
522 else if (ifa->bdrid == myid)
523 ospf_iface_chstate(ifa, OSPF_IS_BACKUP);
4364b47e 524 else
70945cb6 525 ospf_iface_chstate(ifa, OSPF_IS_DROTHER);
4364b47e 526
70945cb6
OZ
527 /* Review neighbor adjacencies if DR or BDR changed */
528 if ((ifa->drid != old_drid) || (ifa->bdrid != old_bdrid))
2e10a170 529 WALK_LIST(neigh, ifa->neigh_list)
70945cb6
OZ
530 if (neigh->state >= NEIGHBOR_2WAY)
531 ospf_neigh_sm(neigh, INM_ADJOK);
532
533 /* RFC 2328 12.4 Event 3 - DR change */
534 if (ifa->drid != old_drid)
535 ospf_notify_rt_lsa(ifa->oa);
4364b47e
OF
536}
537
538struct ospf_neighbor *
539find_neigh(struct ospf_iface *ifa, u32 rid)
540{
541 struct ospf_neighbor *n;
919f5411
OZ
542 WALK_LIST(n, ifa->neigh_list)
543 if (n->rid == rid)
544 return n;
545 return NULL;
546}
4364b47e 547
919f5411
OZ
548struct ospf_neighbor *
549find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip)
550{
551 struct ospf_neighbor *n;
552 WALK_LIST(n, ifa->neigh_list)
553 if (ipa_equal(n->ip, ip))
554 return n;
4364b47e
OF
555 return NULL;
556}
557
0844b65d 558static void
6f8bbaa1 559inactivity_timer_hook(timer * timer)
c7e46aae 560{
86c84d76 561 struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
f8fefde3 562 struct ospf_proto *p = n->ifa->oa->po;
a7a7372a 563
6f8bbaa1 564 OSPF_TRACE(D_EVENTS, "Inactivity timer expired for nbr %R on %s",
f8fefde3
OZ
565 n->rid, n->ifa->ifname);
566 ospf_neigh_sm(n, INM_INACTTIM);
18a0c0bb 567}
a783e259 568
1ec52253
OZ
569static void
570ospf_neigh_bfd_hook(struct bfd_request *req)
571{
572 struct ospf_neighbor *n = req->data;
70945cb6 573 struct ospf_proto *p = n->ifa->oa->po;
1ec52253
OZ
574
575 if (req->down)
576 {
6f8bbaa1 577 OSPF_TRACE(D_EVENTS, "BFD session down for nbr %R on %s",
f8fefde3
OZ
578 n->rid, n->ifa->ifname);
579 ospf_neigh_sm(n, INM_INACTTIM);
1ec52253
OZ
580 }
581}
582
583void
584ospf_neigh_update_bfd(struct ospf_neighbor *n, int use_bfd)
585{
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);
589
590 if (!use_bfd && n->bfd_req)
591 {
592 rfree(n->bfd_req);
593 n->bfd_req = NULL;
594 }
595}
596
597
6f8bbaa1
OZ
598static void
599dbdes_timer_hook(timer *t)
600{
601 struct ospf_neighbor *n = t->data;
602 struct ospf_proto *p = n->ifa->oa->po;
603
604 // OSPF_TRACE(D_EVENTS, "DBDES timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
605
606 if (n->state == NEIGHBOR_EXSTART)
607 ospf_send_dbdes(p, n);
608
609 if ((n->state == NEIGHBOR_EXCHANGE) && (n->myimms & DBDES_MS))
610 ospf_rxmt_dbdes(p, n);
611}
612
613static void
614lsrq_timer_hook(timer *t)
615{
616 struct ospf_neighbor *n = t->data;
617 struct ospf_proto *p = n->ifa->oa->po;
618
619 // OSPF_TRACE(D_EVENTS, "LSRQ timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
620
621 if ((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrql))
622 ospf_send_lsreq(p, n);
623}
624
625static void
626lsrt_timer_hook(timer *t)
627{
628 struct ospf_neighbor *n = t->data;
629 struct ospf_proto *p = n->ifa->oa->po;
630
631 // OSPF_TRACE(D_EVENTS, "LSRT timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
632
633 if ((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrtl))
634 ospf_rxmt_lsupd(p, n);
635}
636
637static void
638ackd_timer_hook(timer *t)
639{
640 struct ospf_neighbor *n = t->data;
641 struct ospf_proto *p = n->ifa->oa->po;
642
643 ospf_send_lsack(p, n, ACKL_DELAY);
644}
645
646
a783e259
OF
647void
648ospf_sh_neigh_info(struct ospf_neighbor *n)
649{
2e10a170 650 struct ospf_iface *ifa = n->ifa;
6f8bbaa1 651 char *pos = "PtP ";
2e10a170 652
f8fefde3
OZ
653 if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
654 {
655 if (n->rid == ifa->drid)
6f8bbaa1 656 pos = "DR ";
f8fefde3 657 else if (n->rid == ifa->bdrid)
6f8bbaa1 658 pos = "BDR ";
f8fefde3 659 else
6f8bbaa1 660 pos = "Other";
f8fefde3 661 }
2e10a170 662
d3fa9e84
OZ
663 cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%7t\t%-10s %-1I",
664 n->rid, n->priority, ospf_ns_names[n->state], pos,
a6f79ca5 665 tm_remains(n->inactim), ifa->ifname, n->ip);
a783e259 666}