]> git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/neighbor.c
OSPF: Fix formatting of 'show ospf neighbors'
[thirdparty/bird.git] / proto / ospf / neighbor.c
1 /*
2 * BIRD -- OSPF
3 *
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.
7 *
8 * Can be freely distributed and used under the terms of the GNU GPL.
9 */
10
11 #include "ospf.h"
12
13
14 const char *ospf_ns_names[] = {
15 "Down", "Attempt", "Init", "2-Way", "ExStart", "Exchange", "Loading", "Full"
16 };
17
18 const char *ospf_inm_names[] = {
19 "HelloReceived", "Start", "2-WayReceived", "NegotiationDone", "ExchangeDone",
20 "BadLSReq", "LoadingDone", "AdjOK?", "SeqNumberMismatch", "1-WayReceived",
21 "KillNbr", "InactivityTimer", "LLDown"
22 };
23
24
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);
31 static void ospf_neigh_stop_graceful_restart_(struct ospf_neighbor *n);
32 static void graceful_restart_timeout(timer *t);
33
34
35 static void
36 init_lists(struct ospf_proto *p, struct ospf_neighbor *n)
37 {
38 s_init_list(&(n->lsrql));
39 n->lsrqi = SHEAD(n->lsrql);
40 n->lsrqh = ospf_top_new(p, n->pool);
41
42 s_init_list(&(n->lsrtl));
43 n->lsrth = ospf_top_new(p, n->pool);
44 }
45
46 static void
47 release_lsrtl(struct ospf_proto *p, struct ospf_neighbor *n)
48 {
49 struct top_hash_entry *ret, *en;
50
51 WALK_SLIST(ret, n->lsrtl)
52 {
53 en = ospf_hash_find_entry(p->gr, ret);
54 if (en)
55 en->ret_count--;
56 }
57 }
58
59 /* Resets LSA request and retransmit lists.
60 * We do not reset DB summary list iterator here,
61 * it is reset during entering EXCHANGE state.
62 */
63 static void
64 reset_lists(struct ospf_proto *p, struct ospf_neighbor *n)
65 {
66 release_lsrtl(p, n);
67 ospf_top_free(n->lsrqh);
68 ospf_top_free(n->lsrth);
69 ospf_reset_lsack_queue(n);
70
71 tm_stop(n->dbdes_timer);
72 tm_stop(n->lsrq_timer);
73 tm_stop(n->lsrt_timer);
74 tm_stop(n->ackd_timer);
75
76 init_lists(p, n);
77 }
78
79 struct ospf_neighbor *
80 ospf_neighbor_new(struct ospf_iface *ifa)
81 {
82 struct ospf_proto *p = ifa->oa->po;
83 struct pool *pool = rp_new(p->p.pool, "OSPF Neighbor");
84 struct ospf_neighbor *n = mb_allocz(pool, sizeof(struct ospf_neighbor));
85
86 n->pool = pool;
87 n->ifa = ifa;
88 add_tail(&ifa->neigh_list, NODE n);
89 n->state = NEIGHBOR_DOWN;
90
91 init_lists(p, n);
92 s_init(&(n->dbsi), &(p->lsal));
93
94 init_list(&n->ackl[ACKL_DIRECT]);
95 init_list(&n->ackl[ACKL_DELAY]);
96
97 n->inactim = tm_new_init(pool, inactivity_timer_hook, n, 0, 0);
98 n->dbdes_timer = tm_new_init(pool, dbdes_timer_hook, n, ifa->rxmtint S, 0);
99 n->lsrq_timer = tm_new_init(pool, lsrq_timer_hook, n, ifa->rxmtint S, 0);
100 n->lsrt_timer = tm_new_init(pool, lsrt_timer_hook, n, ifa->rxmtint S, 0);
101 n->ackd_timer = tm_new_init(pool, ackd_timer_hook, n, ifa->rxmtint S / 2, 0);
102
103 return (n);
104 }
105
106 static void
107 ospf_neigh_down(struct ospf_neighbor *n)
108 {
109 struct ospf_iface *ifa = n->ifa;
110 struct ospf_proto *p = ifa->oa->po;
111 u32 rid = n->rid;
112
113 if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
114 {
115 struct nbma_node *nn = find_nbma_node(ifa, n->ip);
116 if (nn)
117 nn->found = 0;
118 }
119
120 s_get(&(n->dbsi));
121 release_lsrtl(p, n);
122 rem_node(NODE n);
123 rfree(n->pool);
124
125 OSPF_TRACE(D_EVENTS, "Neighbor %R on %s removed", rid, ifa->ifname);
126 }
127
128 /**
129 * ospf_neigh_chstate - handles changes related to new or lod state of neighbor
130 * @n: OSPF neighbor
131 * @state: new state
132 *
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.
135 */
136 static void
137 ospf_neigh_chstate(struct ospf_neighbor *n, u8 state)
138 {
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;
143
144 if (state == old_state)
145 return;
146
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]);
149
150 n->state = state;
151
152 /* Increase number of partial adjacencies */
153 if ((state == NEIGHBOR_EXCHANGE) || (state == NEIGHBOR_LOADING))
154 p->padj++;
155
156 /* Decrease number of partial adjacencies */
157 if ((old_state == NEIGHBOR_EXCHANGE) || (old_state == NEIGHBOR_LOADING))
158 p->padj--;
159
160 /* Increase number of full adjacencies */
161 if (state == NEIGHBOR_FULL)
162 ifa->fadj++;
163
164 /* Decrease number of full adjacencies */
165 if (old_state == NEIGHBOR_FULL)
166 ifa->fadj--;
167
168 if ((ifa->fadj != old_fadj) && !n->gr_active)
169 {
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);
173
174 /* RFC 2328 12.4 Event 8 - vlink state change */
175 if (ifa->type == OSPF_IT_VLINK)
176 ospf_notify_rt_lsa(ifa->voa);
177 }
178
179 if (state == NEIGHBOR_EXSTART)
180 {
181 /* First time adjacency attempt */
182 if (old_state < NEIGHBOR_EXSTART)
183 n->dds = random_u32();
184
185 n->dds++;
186 n->myimms = DBDES_IMMS;
187 n->got_my_rt_lsa = 0;
188
189 tm_start(n->dbdes_timer, 0);
190 tm_start(n->ackd_timer, ifa->rxmtint S / 2);
191 }
192
193 if (state > NEIGHBOR_EXSTART)
194 n->myimms &= ~DBDES_I;
195
196 /* Generate NeighborChange event if needed, see RFC 2328 9.2 */
197 if ((state == NEIGHBOR_2WAY) && (old_state < NEIGHBOR_2WAY) && !n->gr_active)
198 ospf_iface_sm(ifa, ISM_NEICH);
199 if ((state < NEIGHBOR_2WAY) && (old_state >= NEIGHBOR_2WAY) && !n->gr_active)
200 ospf_iface_sm(ifa, ISM_NEICH);
201 }
202
203 /**
204 * ospf_neigh_sm - ospf neighbor state machine
205 * @n: neighor
206 * @event: actual event
207 *
208 * This part implements the neighbor state machine as described in 10.3 of
209 * RFC 2328. The only difference is that state %NEIGHBOR_ATTEMPT is not
210 * used. We discover neighbors on nonbroadcast networks in the
211 * same way as on broadcast networks. The only difference is in
212 * sending hello packets. These are sent to IPs listed in
213 * @ospf_iface->nbma_list .
214 */
215 void
216 ospf_neigh_sm(struct ospf_neighbor *n, int event)
217 {
218 struct ospf_proto *p = n->ifa->oa->po;
219
220 DBG("Neighbor state machine for %R on %s, event %s\n",
221 n->rid, n->ifa->ifname, ospf_inm_names[event]);
222
223 switch (event)
224 {
225 case INM_START:
226 ospf_neigh_chstate(n, NEIGHBOR_ATTEMPT);
227 /* NBMA are used different way */
228 break;
229
230 case INM_HELLOREC:
231 if (n->state < NEIGHBOR_INIT)
232 ospf_neigh_chstate(n, NEIGHBOR_INIT);
233
234 /* Restart inactivity timer */
235 tm_start(n->inactim, n->ifa->deadint S);
236 break;
237
238 case INM_2WAYREC:
239 if (n->state < NEIGHBOR_2WAY)
240 ospf_neigh_chstate(n, NEIGHBOR_2WAY);
241 if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
242 ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
243 break;
244
245 case INM_NEGDONE:
246 if (n->state == NEIGHBOR_EXSTART)
247 {
248 ospf_neigh_chstate(n, NEIGHBOR_EXCHANGE);
249
250 /* Reset DB summary list iterator */
251 s_get(&(n->dbsi));
252 s_init(&(n->dbsi), &p->lsal);
253
254 /* Add MaxAge LSA entries to retransmission list */
255 ospf_add_flushed_to_lsrt(p, n);
256 }
257 else
258 bug("NEGDONE and I'm not in EXSTART?");
259 break;
260
261 case INM_EXDONE:
262 if (!EMPTY_SLIST(n->lsrql))
263 ospf_neigh_chstate(n, NEIGHBOR_LOADING);
264 else
265 ospf_neigh_chstate(n, NEIGHBOR_FULL);
266 break;
267
268 case INM_LOADDONE:
269 ospf_neigh_chstate(n, NEIGHBOR_FULL);
270 break;
271
272 case INM_ADJOK:
273 /* Can In build adjacency? */
274 if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
275 {
276 ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
277 }
278 else if ((n->state >= NEIGHBOR_EXSTART) && !can_do_adj(n))
279 {
280 reset_lists(p, n);
281 ospf_neigh_chstate(n, NEIGHBOR_2WAY);
282 }
283 break;
284
285 case INM_SEQMIS:
286 case INM_BADLSREQ:
287 if (n->state >= NEIGHBOR_EXCHANGE)
288 {
289 reset_lists(p, n);
290 ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
291 }
292 break;
293
294 case INM_KILLNBR:
295 case INM_LLDOWN:
296 case INM_INACTTIM:
297 if (n->gr_active && (event == INM_INACTTIM))
298 {
299 /* Just down the neighbor, but do not remove it */
300 reset_lists(p, n);
301 ospf_neigh_chstate(n, NEIGHBOR_DOWN);
302 break;
303 }
304
305 if (n->gr_active)
306 ospf_neigh_stop_graceful_restart_(n);
307
308 /* No need for reset_lists() */
309 ospf_neigh_chstate(n, NEIGHBOR_DOWN);
310 ospf_neigh_down(n);
311 break;
312
313 case INM_1WAYREC:
314 reset_lists(p, n);
315 ospf_neigh_chstate(n, NEIGHBOR_INIT);
316 break;
317
318 default:
319 bug("%s: INM - Unknown event?", p->p.name);
320 break;
321 }
322 }
323
324 static int
325 can_do_adj(struct ospf_neighbor *n)
326 {
327 struct ospf_iface *ifa = n->ifa;
328 struct ospf_proto *p = ifa->oa->po;
329 int i = 0;
330
331 switch (ifa->type)
332 {
333 case OSPF_IT_PTP:
334 case OSPF_IT_PTMP:
335 case OSPF_IT_VLINK:
336 i = 1;
337 break;
338 case OSPF_IT_BCAST:
339 case OSPF_IT_NBMA:
340 switch (ifa->state)
341 {
342 case OSPF_IS_DOWN:
343 case OSPF_IS_LOOP:
344 bug("%s: Iface %s in down state?", p->p.name, ifa->ifname);
345 break;
346 case OSPF_IS_WAITING:
347 DBG("%s: Neighbor? on iface %s\n", p->p.name, ifa->ifname);
348 break;
349 case OSPF_IS_DROTHER:
350 if (((n->rid == ifa->drid) || (n->rid == ifa->bdrid))
351 && (n->state >= NEIGHBOR_2WAY))
352 i = 1;
353 break;
354 case OSPF_IS_PTP:
355 case OSPF_IS_BACKUP:
356 case OSPF_IS_DR:
357 if (n->state >= NEIGHBOR_2WAY)
358 i = 1;
359 break;
360 default:
361 bug("%s: Iface %s in unknown state?", p->p.name, ifa->ifname);
362 break;
363 }
364 break;
365 default:
366 bug("%s: Iface %s is unknown type?", p->p.name, ifa->ifname);
367 break;
368 }
369 DBG("%s: Iface %s can_do_adj=%d\n", p->p.name, ifa->ifname, i);
370 return i;
371 }
372
373 static void
374 ospf_neigh_start_graceful_restart(struct ospf_neighbor *n, uint gr_time)
375 {
376 struct ospf_proto *p = n->ifa->oa->po;
377
378 OSPF_TRACE(D_EVENTS, "Neighbor %R on %s started graceful restart",
379 n->rid, n->ifa->ifname);
380
381 n->gr_active = 1;
382 p->gr_count++;
383
384 n->gr_timer = tm_new_init(n->pool, graceful_restart_timeout, n, 0, 0);
385 tm_start(n->gr_timer, gr_time S);
386 }
387
388 static void
389 ospf_neigh_stop_graceful_restart_(struct ospf_neighbor *n)
390 {
391 struct ospf_proto *p = n->ifa->oa->po;
392 struct ospf_iface *ifa = n->ifa;
393
394 n->gr_active = 0;
395 p->gr_count--;
396
397 rfree(n->gr_timer);
398 n->gr_timer = NULL;
399
400 ospf_notify_rt_lsa(ifa->oa);
401 ospf_notify_net_lsa(ifa);
402
403 if (ifa->type == OSPF_IT_VLINK)
404 ospf_notify_rt_lsa(ifa->voa);
405
406 ospf_iface_sm(ifa, ISM_NEICH);
407 }
408
409 static void
410 ospf_neigh_stop_graceful_restart(struct ospf_neighbor *n)
411 {
412 struct ospf_proto *p = n->ifa->oa->po;
413
414 OSPF_TRACE(D_EVENTS, "Neighbor %R on %s finished graceful restart",
415 n->rid, n->ifa->ifname);
416
417 ospf_neigh_stop_graceful_restart_(n);
418 }
419
420 void
421 ospf_neigh_cancel_graceful_restart(struct ospf_neighbor *n)
422 {
423 struct ospf_proto *p = n->ifa->oa->po;
424
425 OSPF_TRACE(D_EVENTS, "Graceful restart canceled for nbr %R on %s",
426 n->rid, n->ifa->ifname);
427
428 ospf_neigh_stop_graceful_restart_(n);
429
430 if (n->state == NEIGHBOR_DOWN)
431 ospf_neigh_down(n);
432 }
433
434 static void
435 graceful_restart_timeout(timer *t)
436 {
437 struct ospf_neighbor *n = t->data;
438 struct ospf_proto *p = n->ifa->oa->po;
439
440 OSPF_TRACE(D_EVENTS, "Graceful restart timer expired for nbr %R on %s",
441 n->rid, n->ifa->ifname);
442
443 ospf_neigh_stop_graceful_restart_(n);
444
445 if (n->state == NEIGHBOR_DOWN)
446 ospf_neigh_down(n);
447 }
448
449 static inline int
450 changes_in_lsrtl(struct ospf_neighbor *n)
451 {
452 /* This could be improved, see RFC 3623 3.1 (2) */
453
454 struct top_hash_entry *en;
455 WALK_SLIST(en, n->lsrtl)
456 if (LSA_FUNCTION(en->lsa_type) <= LSA_FUNCTION(LSA_T_NSSA))
457 return 1;
458
459 return 0;
460 }
461
462 void
463 ospf_neigh_notify_grace_lsa(struct ospf_neighbor *n, struct top_hash_entry *en)
464 {
465 struct ospf_iface *ifa = n->ifa;
466 struct ospf_proto *p = ifa->oa->po;
467
468 /* In OSPFv2, neighbors are identified by either IP or Router ID, based on network type */
469 uint t = ifa->type;
470 if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP)))
471 {
472 struct ospf_tlv *tlv = lsa_get_tlv(en, LSA_GR_ADDRESS);
473 if (!tlv || tlv->length != 4)
474 return;
475
476 ip_addr addr = ipa_from_u32(tlv->data[0]);
477 if (!ipa_equal(n->ip, addr))
478 n = find_neigh_by_ip(ifa, addr);
479 }
480 else
481 {
482 if (n->rid != en->lsa.rt)
483 n = find_neigh(ifa, en->lsa.rt);
484 }
485
486 if (!n)
487 return;
488
489 if (en->lsa.age < LSA_MAXAGE)
490 {
491 u32 period = lsa_get_tlv_u32(en, LSA_GR_PERIOD);
492
493 /* Exception for updating grace period */
494 if (n->gr_active)
495 {
496 tm_start(n->gr_timer, (period S) - (en->lsa.age S));
497 return;
498 }
499
500 /* RFC 3623 3.1 (1) - full adjacency */
501 if (n->state != NEIGHBOR_FULL)
502 return;
503
504 /* RFC 3623 3.1 (2) - no changes in LSADB */
505 if (changes_in_lsrtl(n))
506 return;
507
508 /* RFC 3623 3.1 (3) - grace period not expired */
509 if (en->lsa.age >= period)
510 return;
511
512 /* RFC 3623 3.1 (4) - helper mode allowed */
513 if (!p->gr_mode)
514 return;
515
516 /* RFC 3623 3.1 (5) - no local graceful restart */
517 if (p->p.gr_recovery)
518 return;
519
520 ospf_neigh_start_graceful_restart(n, period - en->lsa.age);
521 }
522 else /* Grace-LSA is flushed */
523 {
524 if (n->gr_active)
525 ospf_neigh_stop_graceful_restart(n);
526 }
527 }
528
529 void
530 ospf_neigh_lsadb_changed_(struct ospf_proto *p, struct top_hash_entry *en)
531 {
532 struct ospf_iface *ifa;
533 struct ospf_neighbor *n, *nx;
534
535 if (LSA_FUNCTION(en->lsa_type) > LSA_FUNCTION(LSA_T_NSSA))
536 return;
537
538 /* RFC 3623 3.2 (3) - cancel graceful restart when LSdb changed */
539 WALK_LIST(ifa, p->iface_list)
540 if (lsa_flooding_allowed(en->lsa_type, en->domain, ifa))
541 WALK_LIST_DELSAFE(n, nx, ifa->neigh_list)
542 if (n->gr_active)
543 ospf_neigh_cancel_graceful_restart(n);
544 }
545
546
547
548 static inline u32 neigh_get_id(struct ospf_proto *p, struct ospf_neighbor *n)
549 { return ospf_is_v2(p) ? ipa_to_u32(n->ip) : n->rid; }
550
551 static struct ospf_neighbor *
552 elect_bdr(struct ospf_proto *p, list nl)
553 {
554 struct ospf_neighbor *neigh, *n1, *n2;
555 u32 nid;
556
557 n1 = NULL;
558 n2 = NULL;
559 WALK_LIST(neigh, nl) /* First try those decl. themselves */
560 {
561 nid = neigh_get_id(p, neigh);
562
563 if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
564 if (neigh->priority > 0) /* Eligible */
565 if (neigh->dr != nid) /* And not decl. itself DR */
566 {
567 if (neigh->bdr == nid) /* Declaring BDR */
568 {
569 if (n1 != NULL)
570 {
571 if (neigh->priority > n1->priority)
572 n1 = neigh;
573 else if (neigh->priority == n1->priority)
574 if (neigh->rid > n1->rid)
575 n1 = neigh;
576 }
577 else
578 {
579 n1 = neigh;
580 }
581 }
582 else /* And NOT declaring BDR */
583 {
584 if (n2 != NULL)
585 {
586 if (neigh->priority > n2->priority)
587 n2 = neigh;
588 else if (neigh->priority == n2->priority)
589 if (neigh->rid > n2->rid)
590 n2 = neigh;
591 }
592 else
593 {
594 n2 = neigh;
595 }
596 }
597 }
598 }
599 if (n1 == NULL)
600 n1 = n2;
601
602 return (n1);
603 }
604
605 static struct ospf_neighbor *
606 elect_dr(struct ospf_proto *p, list nl)
607 {
608 struct ospf_neighbor *neigh, *n;
609 u32 nid;
610
611 n = NULL;
612 WALK_LIST(neigh, nl) /* And now DR */
613 {
614 nid = neigh_get_id(p, neigh);
615
616 if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
617 if (neigh->priority > 0) /* Eligible */
618 if (neigh->dr == nid) /* And declaring itself DR */
619 {
620 if (n != NULL)
621 {
622 if (neigh->priority > n->priority)
623 n = neigh;
624 else if (neigh->priority == n->priority)
625 if (neigh->rid > n->rid)
626 n = neigh;
627 }
628 else
629 {
630 n = neigh;
631 }
632 }
633 }
634
635 return (n);
636 }
637
638 /**
639 * ospf_dr_election - (Backup) Designed Router election
640 * @ifa: actual interface
641 *
642 * When the wait timer fires, it is time to elect (Backup) Designated Router.
643 * Structure describing me is added to this list so every electing router has
644 * the same list. Backup Designated Router is elected before Designated
645 * Router. This process is described in 9.4 of RFC 2328. The function is
646 * supposed to be called only from ospf_iface_sm() as a part of the interface
647 * state machine.
648 */
649 void
650 ospf_dr_election(struct ospf_iface *ifa)
651 {
652 struct ospf_proto *p = ifa->oa->po;
653 struct ospf_neighbor *neigh, *ndr, *nbdr, me;
654 u32 myid = p->router_id;
655
656 DBG("(B)DR election.\n");
657
658 me.state = NEIGHBOR_2WAY;
659 me.rid = myid;
660 me.priority = ifa->priority;
661 me.ip = ifa->addr->ip;
662
663 me.dr = ospf_is_v2(p) ? ipa_to_u32(ifa->drip) : ifa->drid;
664 me.bdr = ospf_is_v2(p) ? ipa_to_u32(ifa->bdrip) : ifa->bdrid;
665 me.iface_id = ifa->iface_id;
666
667 add_tail(&ifa->neigh_list, NODE & me);
668
669 nbdr = elect_bdr(p, ifa->neigh_list);
670 ndr = elect_dr(p, ifa->neigh_list);
671
672 if (ndr == NULL)
673 ndr = nbdr;
674
675 /* 9.4. (4) */
676 if (((ifa->drid == myid) && (ndr != &me))
677 || ((ifa->drid != myid) && (ndr == &me))
678 || ((ifa->bdrid == myid) && (nbdr != &me))
679 || ((ifa->bdrid != myid) && (nbdr == &me)))
680 {
681 me.dr = ndr ? neigh_get_id(p, ndr) : 0;
682 me.bdr = nbdr ? neigh_get_id(p, nbdr) : 0;
683
684 nbdr = elect_bdr(p, ifa->neigh_list);
685 ndr = elect_dr(p, ifa->neigh_list);
686
687 if (ndr == NULL)
688 ndr = nbdr;
689 }
690
691 rem_node(NODE & me);
692
693
694 u32 old_drid = ifa->drid;
695 u32 old_bdrid = ifa->bdrid;
696 ip_addr none = ospf_is_v2(p) ? IPA_NONE4 : IPA_NONE6;
697
698 ifa->drid = ndr ? ndr->rid : 0;
699 ifa->drip = ndr ? ndr->ip : none;
700 ifa->dr_iface_id = ndr ? ndr->iface_id : 0;
701
702 ifa->bdrid = nbdr ? nbdr->rid : 0;
703 ifa->bdrip = nbdr ? nbdr->ip : none;
704
705 DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid);
706
707 /* We are part of the interface state machine */
708 if (ifa->drid == myid)
709 ospf_iface_chstate(ifa, OSPF_IS_DR);
710 else if (ifa->bdrid == myid)
711 ospf_iface_chstate(ifa, OSPF_IS_BACKUP);
712 else
713 ospf_iface_chstate(ifa, OSPF_IS_DROTHER);
714
715 /* Review neighbor adjacencies if DR or BDR changed */
716 if ((ifa->drid != old_drid) || (ifa->bdrid != old_bdrid))
717 WALK_LIST(neigh, ifa->neigh_list)
718 if (neigh->state >= NEIGHBOR_2WAY)
719 ospf_neigh_sm(neigh, INM_ADJOK);
720
721 /* RFC 2328 12.4 Event 3 - DR change */
722 if (ifa->drid != old_drid)
723 ospf_notify_rt_lsa(ifa->oa);
724 }
725
726 struct ospf_neighbor *
727 find_neigh(struct ospf_iface *ifa, u32 rid)
728 {
729 struct ospf_neighbor *n;
730 WALK_LIST(n, ifa->neigh_list)
731 if (n->rid == rid)
732 return n;
733 return NULL;
734 }
735
736 struct ospf_neighbor *
737 find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip)
738 {
739 struct ospf_neighbor *n;
740 WALK_LIST(n, ifa->neigh_list)
741 if (ipa_equal(n->ip, ip))
742 return n;
743 return NULL;
744 }
745
746 static void
747 inactivity_timer_hook(timer * timer)
748 {
749 struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
750 struct ospf_proto *p = n->ifa->oa->po;
751
752 OSPF_TRACE(D_EVENTS, "Inactivity timer expired for nbr %R on %s",
753 n->rid, n->ifa->ifname);
754 ospf_neigh_sm(n, INM_INACTTIM);
755 }
756
757 static void
758 ospf_neigh_bfd_hook(struct bfd_request *req)
759 {
760 struct ospf_neighbor *n = req->data;
761 struct ospf_proto *p = n->ifa->oa->po;
762
763 if (req->down)
764 {
765 OSPF_TRACE(D_EVENTS, "BFD session down for nbr %R on %s",
766 n->rid, n->ifa->ifname);
767 ospf_neigh_sm(n, INM_INACTTIM);
768 }
769 }
770
771 void
772 ospf_neigh_update_bfd(struct ospf_neighbor *n, int use_bfd)
773 {
774 struct ospf_proto *p = n->ifa->oa->po;
775
776 if (use_bfd && !n->bfd_req)
777 n->bfd_req = bfd_request_session(n->pool, n->ip, n->ifa->addr->ip,
778 n->ifa->iface, p->p.vrf,
779 ospf_neigh_bfd_hook, n);
780
781 if (!use_bfd && n->bfd_req)
782 {
783 rfree(n->bfd_req);
784 n->bfd_req = NULL;
785 }
786 }
787
788
789 static void
790 dbdes_timer_hook(timer *t)
791 {
792 struct ospf_neighbor *n = t->data;
793 struct ospf_proto *p = n->ifa->oa->po;
794
795 // OSPF_TRACE(D_EVENTS, "DBDES timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
796
797 if (n->state == NEIGHBOR_EXSTART)
798 ospf_send_dbdes(p, n);
799
800 if ((n->state == NEIGHBOR_EXCHANGE) && (n->myimms & DBDES_MS))
801 ospf_rxmt_dbdes(p, n);
802
803 if ((n->state > NEIGHBOR_LOADING) && !(n->myimms & DBDES_MS))
804 {
805 ospf_reset_ldd(p, n);
806 tm_stop(n->dbdes_timer);
807 }
808 }
809
810 static void
811 lsrq_timer_hook(timer *t)
812 {
813 struct ospf_neighbor *n = t->data;
814 struct ospf_proto *p = n->ifa->oa->po;
815
816 // OSPF_TRACE(D_EVENTS, "LSRQ timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
817
818 if ((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrql))
819 ospf_send_lsreq(p, n);
820 }
821
822 static void
823 lsrt_timer_hook(timer *t)
824 {
825 struct ospf_neighbor *n = t->data;
826 struct ospf_proto *p = n->ifa->oa->po;
827
828 // OSPF_TRACE(D_EVENTS, "LSRT timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
829
830 if ((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrtl))
831 ospf_rxmt_lsupd(p, n);
832 }
833
834 static void
835 ackd_timer_hook(timer *t)
836 {
837 struct ospf_neighbor *n = t->data;
838 struct ospf_proto *p = n->ifa->oa->po;
839
840 ospf_send_lsack(p, n, ACKL_DELAY);
841 }
842
843
844 void
845 ospf_sh_neigh_info(struct ospf_neighbor *n)
846 {
847 struct ospf_iface *ifa = n->ifa;
848 char *pos = "PtP ";
849
850 if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
851 {
852 if (n->rid == ifa->drid)
853 pos = "DR ";
854 else if (n->rid == ifa->bdrid)
855 pos = "BDR ";
856 else
857 pos = "Other";
858 }
859
860 cli_msg(-1013, "%-12R\t%3u\t%s/%s\t%6t\t%-10s %I",
861 n->rid, n->priority, ospf_ns_names[n->state], pos,
862 tm_remains(n->inactim), ifa->ifname, n->ip);
863 }