]> git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/neighbor.c
c5d44dec85093be5c3e1919d81c9156ba5ae42fd
[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
32
33 static void
34 init_lists(struct ospf_proto *p, struct ospf_neighbor *n)
35 {
36 s_init_list(&(n->lsrql));
37 n->lsrqi = SHEAD(n->lsrql);
38 n->lsrqh = ospf_top_new(p, n->pool);
39
40 s_init_list(&(n->lsrtl));
41 n->lsrth = ospf_top_new(p, n->pool);
42 }
43
44 static void
45 release_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 }
55 }
56
57 /* Resets LSA request and retransmit lists.
58 * We do not reset DB summary list iterator here,
59 * it is reset during entering EXCHANGE state.
60 */
61 static void
62 reset_lists(struct ospf_proto *p, struct ospf_neighbor *n)
63 {
64 release_lsrtl(p, n);
65 ospf_top_free(n->lsrqh);
66 ospf_top_free(n->lsrth);
67 ospf_reset_lsack_queue(n);
68
69 tm_stop(n->dbdes_timer);
70 tm_stop(n->lsrq_timer);
71 tm_stop(n->lsrt_timer);
72 tm_stop(n->ackd_timer);
73
74 init_lists(p, n);
75 }
76
77 struct ospf_neighbor *
78 ospf_neighbor_new(struct ospf_iface *ifa)
79 {
80 struct ospf_proto *p = ifa->oa->po;
81 struct pool *pool = rp_new(p->p.pool, "OSPF Neighbor");
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);
87 n->adj = 0;
88 n->csn = 0;
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_set(pool, inactivity_timer_hook, n, 0, 0);
98 n->dbdes_timer = tm_new_set(pool, dbdes_timer_hook, n, 0, ifa->rxmtint);
99 n->lsrq_timer = tm_new_set(pool, lsrq_timer_hook, n, 0, ifa->rxmtint);
100 n->lsrt_timer = tm_new_set(pool, lsrt_timer_hook, n, 0, ifa->rxmtint);
101 n->ackd_timer = tm_new_set(pool, ackd_timer_hook, n, 0, ifa->rxmtint / 2);
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
112 if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
113 {
114 struct nbma_node *nn = find_nbma_node(ifa, n->ip);
115 if (nn)
116 nn->found = 0;
117 }
118
119 s_get(&(n->dbsi));
120 release_lsrtl(p, n);
121 rem_node(NODE n);
122 rfree(n->pool);
123
124 OSPF_TRACE(D_EVENTS, "Neighbor %R on %s removed", n->rid, ifa->ifname);
125 }
126
127 /**
128 * ospf_neigh_chstate - handles changes related to new or lod state of neighbor
129 * @n: OSPF neighbor
130 * @state: new state
131 *
132 * Many actions have to be taken acording to a change of state of a neighbor. It
133 * starts rxmt timers, call interface state machine etc.
134 */
135 static void
136 ospf_neigh_chstate(struct ospf_neighbor *n, u8 state)
137 {
138 struct ospf_iface *ifa = n->ifa;
139 struct ospf_proto *p = ifa->oa->po;
140 u8 old_state = n->state;
141 int old_fadj = ifa->fadj;
142
143 if (state == old_state)
144 return;
145
146 OSPF_TRACE(D_EVENTS, "Neighbor %R on %s changed state from %s to %s",
147 n->rid, ifa->ifname, ospf_ns_names[old_state], ospf_ns_names[state]);
148
149 n->state = state;
150
151 /* Increase number of partial adjacencies */
152 if ((state == NEIGHBOR_EXCHANGE) || (state == NEIGHBOR_LOADING))
153 p->padj++;
154
155 /* Decrease number of partial adjacencies */
156 if ((old_state == NEIGHBOR_EXCHANGE) || (old_state == NEIGHBOR_LOADING))
157 p->padj--;
158
159 /* Increase number of full adjacencies */
160 if (state == NEIGHBOR_FULL)
161 ifa->fadj++;
162
163 /* Decrease number of full adjacencies */
164 if (old_state == NEIGHBOR_FULL)
165 ifa->fadj--;
166
167 if (ifa->fadj != old_fadj)
168 {
169 /* RFC 2328 12.4 Event 4 - neighbor enters/leaves Full state */
170 ospf_notify_rt_lsa(ifa->oa);
171 ospf_notify_net_lsa(ifa);
172
173 /* RFC 2328 12.4 Event 8 - vlink state change */
174 if (ifa->type == OSPF_IT_VLINK)
175 ospf_notify_rt_lsa(ifa->voa);
176 }
177
178 if (state == NEIGHBOR_EXSTART)
179 {
180 /* First time adjacency */
181 if (n->adj == 0)
182 n->dds = random_u32();
183
184 n->dds++;
185 n->myimms = DBDES_IMMS;
186
187 tm_start(n->dbdes_timer, 0);
188 tm_start(n->ackd_timer, ifa->rxmtint / 2);
189 }
190
191 if (state > NEIGHBOR_EXSTART)
192 n->myimms &= ~DBDES_I;
193
194 /* Generate NeighborChange event if needed, see RFC 2328 9.2 */
195 if ((state == NEIGHBOR_2WAY) && (old_state < NEIGHBOR_2WAY))
196 ospf_iface_sm(ifa, ISM_NEICH);
197 if ((state < NEIGHBOR_2WAY) && (old_state >= NEIGHBOR_2WAY))
198 ospf_iface_sm(ifa, ISM_NEICH);
199 }
200
201 /**
202 * ospf_neigh_sm - ospf neighbor state machine
203 * @n: neighor
204 * @event: actual event
205 *
206 * This part implements the neighbor state machine as described in 10.3 of
207 * RFC 2328. The only difference is that state %NEIGHBOR_ATTEMPT is not
208 * used. We discover neighbors on nonbroadcast networks in the
209 * same way as on broadcast networks. The only difference is in
210 * sending hello packets. These are sent to IPs listed in
211 * @ospf_iface->nbma_list .
212 */
213 void
214 ospf_neigh_sm(struct ospf_neighbor *n, int event)
215 {
216 struct ospf_proto *p = n->ifa->oa->po;
217
218 DBG("Neighbor state machine for %R on %s, event %s\n",
219 n->rid, n->ifa->ifname, ospf_inm_names[event]);
220
221 switch (event)
222 {
223 case INM_START:
224 ospf_neigh_chstate(n, NEIGHBOR_ATTEMPT);
225 /* NBMA are used different way */
226 break;
227
228 case INM_HELLOREC:
229 if (n->state < NEIGHBOR_INIT)
230 ospf_neigh_chstate(n, NEIGHBOR_INIT);
231
232 /* Restart inactivity timer */
233 tm_start(n->inactim, n->ifa->deadint);
234 break;
235
236 case INM_2WAYREC:
237 if (n->state < NEIGHBOR_2WAY)
238 ospf_neigh_chstate(n, NEIGHBOR_2WAY);
239 if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
240 ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
241 break;
242
243 case INM_NEGDONE:
244 if (n->state == NEIGHBOR_EXSTART)
245 {
246 ospf_neigh_chstate(n, NEIGHBOR_EXCHANGE);
247
248 /* Reset DB summary list iterator */
249 s_get(&(n->dbsi));
250 s_init(&(n->dbsi), &p->lsal);
251
252 /* Add MaxAge LSA entries to retransmission list */
253 ospf_add_flushed_to_lsrt(p, n);
254 }
255 else
256 bug("NEGDONE and I'm not in EXSTART?");
257 break;
258
259 case INM_EXDONE:
260 if (!EMPTY_SLIST(n->lsrql))
261 ospf_neigh_chstate(n, NEIGHBOR_LOADING);
262 else
263 ospf_neigh_chstate(n, NEIGHBOR_FULL);
264 break;
265
266 case INM_LOADDONE:
267 ospf_neigh_chstate(n, NEIGHBOR_FULL);
268 break;
269
270 case INM_ADJOK:
271 /* Can In build adjacency? */
272 if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
273 {
274 ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
275 }
276 else if ((n->state >= NEIGHBOR_EXSTART) && !can_do_adj(n))
277 {
278 reset_lists(p, n);
279 ospf_neigh_chstate(n, NEIGHBOR_2WAY);
280 }
281 break;
282
283 case INM_SEQMIS:
284 case INM_BADLSREQ:
285 if (n->state >= NEIGHBOR_EXCHANGE)
286 {
287 reset_lists(p, n);
288 ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
289 }
290 break;
291
292 case INM_KILLNBR:
293 case INM_LLDOWN:
294 case INM_INACTTIM:
295 /* No need for reset_lists() */
296 ospf_neigh_chstate(n, NEIGHBOR_DOWN);
297 ospf_neigh_down(n);
298 break;
299
300 case INM_1WAYREC:
301 reset_lists(p, n);
302 ospf_neigh_chstate(n, NEIGHBOR_INIT);
303 break;
304
305 default:
306 bug("%s: INM - Unknown event?", p->p.name);
307 break;
308 }
309 }
310
311 static int
312 can_do_adj(struct ospf_neighbor *n)
313 {
314 struct ospf_iface *ifa = n->ifa;
315 struct ospf_proto *p = ifa->oa->po;
316 int i = 0;
317
318 switch (ifa->type)
319 {
320 case OSPF_IT_PTP:
321 case OSPF_IT_PTMP:
322 case OSPF_IT_VLINK:
323 i = 1;
324 break;
325 case OSPF_IT_BCAST:
326 case OSPF_IT_NBMA:
327 switch (ifa->state)
328 {
329 case OSPF_IS_DOWN:
330 case OSPF_IS_LOOP:
331 bug("%s: Iface %s in down state?", p->p.name, ifa->ifname);
332 break;
333 case OSPF_IS_WAITING:
334 DBG("%s: Neighbor? on iface %s\n", p->p.name, ifa->ifname);
335 break;
336 case OSPF_IS_DROTHER:
337 if (((n->rid == ifa->drid) || (n->rid == ifa->bdrid))
338 && (n->state >= NEIGHBOR_2WAY))
339 i = 1;
340 break;
341 case OSPF_IS_PTP:
342 case OSPF_IS_BACKUP:
343 case OSPF_IS_DR:
344 if (n->state >= NEIGHBOR_2WAY)
345 i = 1;
346 break;
347 default:
348 bug("%s: Iface %s in unknown state?", p->p.name, ifa->ifname);
349 break;
350 }
351 break;
352 default:
353 bug("%s: Iface %s is unknown type?", p->p.name, ifa->ifname);
354 break;
355 }
356 DBG("%s: Iface %s can_do_adj=%d\n", p->p.name, ifa->ifname, i);
357 return i;
358 }
359
360
361 static inline u32 neigh_get_id(struct ospf_proto *p, struct ospf_neighbor *n)
362 { return ospf_is_v2(p) ? ipa_to_u32(n->ip) : n->rid; }
363
364 static struct ospf_neighbor *
365 elect_bdr(struct ospf_proto *p, list nl)
366 {
367 struct ospf_neighbor *neigh, *n1, *n2;
368 u32 nid;
369
370 n1 = NULL;
371 n2 = NULL;
372 WALK_LIST(neigh, nl) /* First try those decl. themselves */
373 {
374 nid = neigh_get_id(p, neigh);
375
376 if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
377 if (neigh->priority > 0) /* Eligible */
378 if (neigh->dr != nid) /* And not decl. itself DR */
379 {
380 if (neigh->bdr == nid) /* Declaring BDR */
381 {
382 if (n1 != NULL)
383 {
384 if (neigh->priority > n1->priority)
385 n1 = neigh;
386 else if (neigh->priority == n1->priority)
387 if (neigh->rid > n1->rid)
388 n1 = neigh;
389 }
390 else
391 {
392 n1 = neigh;
393 }
394 }
395 else /* And NOT declaring BDR */
396 {
397 if (n2 != NULL)
398 {
399 if (neigh->priority > n2->priority)
400 n2 = neigh;
401 else if (neigh->priority == n2->priority)
402 if (neigh->rid > n2->rid)
403 n2 = neigh;
404 }
405 else
406 {
407 n2 = neigh;
408 }
409 }
410 }
411 }
412 if (n1 == NULL)
413 n1 = n2;
414
415 return (n1);
416 }
417
418 static struct ospf_neighbor *
419 elect_dr(struct ospf_proto *p, list nl)
420 {
421 struct ospf_neighbor *neigh, *n;
422 u32 nid;
423
424 n = NULL;
425 WALK_LIST(neigh, nl) /* And now DR */
426 {
427 nid = neigh_get_id(p, neigh);
428
429 if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
430 if (neigh->priority > 0) /* Eligible */
431 if (neigh->dr == nid) /* And declaring itself DR */
432 {
433 if (n != NULL)
434 {
435 if (neigh->priority > n->priority)
436 n = neigh;
437 else if (neigh->priority == n->priority)
438 if (neigh->rid > n->rid)
439 n = neigh;
440 }
441 else
442 {
443 n = neigh;
444 }
445 }
446 }
447
448 return (n);
449 }
450
451 /**
452 * ospf_dr_election - (Backup) Designed Router election
453 * @ifa: actual interface
454 *
455 * When the wait timer fires, it is time to elect (Backup) Designated Router.
456 * Structure describing me is added to this list so every electing router has
457 * the same list. Backup Designated Router is elected before Designated
458 * Router. This process is described in 9.4 of RFC 2328. The function is
459 * supposed to be called only from ospf_iface_sm() as a part of the interface
460 * state machine.
461 */
462 void
463 ospf_dr_election(struct ospf_iface *ifa)
464 {
465 struct ospf_proto *p = ifa->oa->po;
466 struct ospf_neighbor *neigh, *ndr, *nbdr, me;
467 u32 myid = p->router_id;
468
469 DBG("(B)DR election.\n");
470
471 me.state = NEIGHBOR_2WAY;
472 me.rid = myid;
473 me.priority = ifa->priority;
474 me.ip = ifa->addr->ip;
475
476 me.dr = ospf_is_v2(p) ? ipa_to_u32(ifa->drip) : ifa->drid;
477 me.bdr = ospf_is_v2(p) ? ipa_to_u32(ifa->bdrip) : ifa->bdrid;
478 me.iface_id = ifa->iface_id;
479
480 add_tail(&ifa->neigh_list, NODE & me);
481
482 nbdr = elect_bdr(p, ifa->neigh_list);
483 ndr = elect_dr(p, ifa->neigh_list);
484
485 if (ndr == NULL)
486 ndr = nbdr;
487
488 /* 9.4. (4) */
489 if (((ifa->drid == myid) && (ndr != &me))
490 || ((ifa->drid != myid) && (ndr == &me))
491 || ((ifa->bdrid == myid) && (nbdr != &me))
492 || ((ifa->bdrid != myid) && (nbdr == &me)))
493 {
494 me.dr = ndr ? neigh_get_id(p, ndr) : 0;
495 me.bdr = nbdr ? neigh_get_id(p, nbdr) : 0;
496
497 nbdr = elect_bdr(p, ifa->neigh_list);
498 ndr = elect_dr(p, ifa->neigh_list);
499
500 if (ndr == NULL)
501 ndr = nbdr;
502 }
503
504 rem_node(NODE & me);
505
506
507 u32 old_drid = ifa->drid;
508 u32 old_bdrid = ifa->bdrid;
509
510 ifa->drid = ndr ? ndr->rid : 0;
511 ifa->drip = ndr ? ndr->ip : IPA_NONE;
512 ifa->dr_iface_id = ndr ? ndr->iface_id : 0;
513
514 ifa->bdrid = nbdr ? nbdr->rid : 0;
515 ifa->bdrip = nbdr ? nbdr->ip : IPA_NONE;
516
517 DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid);
518
519 /* We are part of the interface state machine */
520 if (ifa->drid == myid)
521 ospf_iface_chstate(ifa, OSPF_IS_DR);
522 else if (ifa->bdrid == myid)
523 ospf_iface_chstate(ifa, OSPF_IS_BACKUP);
524 else
525 ospf_iface_chstate(ifa, OSPF_IS_DROTHER);
526
527 /* Review neighbor adjacencies if DR or BDR changed */
528 if ((ifa->drid != old_drid) || (ifa->bdrid != old_bdrid))
529 WALK_LIST(neigh, ifa->neigh_list)
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);
536 }
537
538 struct ospf_neighbor *
539 find_neigh(struct ospf_iface *ifa, u32 rid)
540 {
541 struct ospf_neighbor *n;
542 WALK_LIST(n, ifa->neigh_list)
543 if (n->rid == rid)
544 return n;
545 return NULL;
546 }
547
548 struct ospf_neighbor *
549 find_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;
555 return NULL;
556 }
557
558 static void
559 inactivity_timer_hook(timer * timer)
560 {
561 struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
562 struct ospf_proto *p = n->ifa->oa->po;
563
564 OSPF_TRACE(D_EVENTS, "Inactivity timer expired for nbr %R on %s",
565 n->rid, n->ifa->ifname);
566 ospf_neigh_sm(n, INM_INACTTIM);
567 }
568
569 static void
570 ospf_neigh_bfd_hook(struct bfd_request *req)
571 {
572 struct ospf_neighbor *n = req->data;
573 struct ospf_proto *p = n->ifa->oa->po;
574
575 if (req->down)
576 {
577 OSPF_TRACE(D_EVENTS, "BFD session down for nbr %R on %s",
578 n->rid, n->ifa->ifname);
579 ospf_neigh_sm(n, INM_INACTTIM);
580 }
581 }
582
583 void
584 ospf_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
598 static void
599 dbdes_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
613 static void
614 lsrq_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
625 static void
626 lsrt_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
637 static void
638 ackd_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
647 void
648 ospf_sh_neigh_info(struct ospf_neighbor *n)
649 {
650 struct ospf_iface *ifa = n->ifa;
651 char *pos = "PtP ";
652 char etime[6];
653 int exp, sec, min;
654
655 exp = n->inactim->expires - now;
656 sec = exp % 60;
657 min = exp / 60;
658 if (min > 59)
659 {
660 bsprintf(etime, "-Inf-");
661 }
662 else
663 {
664 bsprintf(etime, "%02u:%02u", min, sec);
665 }
666
667 if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
668 {
669 if (n->rid == ifa->drid)
670 pos = "DR ";
671 else if (n->rid == ifa->bdrid)
672 pos = "BDR ";
673 else
674 pos = "Other";
675 }
676
677 cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority,
678 ospf_ns_names[n->state], pos, etime, ifa->ifname, n->ip);
679 }