]> git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/neighbor.c
Temporary OSPFv3 development commit
[thirdparty/bird.git] / proto / ospf / neighbor.c
1 /*
2 * BIRD -- OSPF
3 *
4 * (c) 1999 - 2004 Ondrej Filip <feela@network.cz>
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9 #include "ospf.h"
10
11 char *ospf_ns[] = { " down",
12 " attempt",
13 " init",
14 " 2way",
15 " exstart",
16 "exchange",
17 " loading",
18 " full"
19 };
20
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"
26 };
27
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);
34
35 static void
36 init_lists(struct ospf_neighbor *n)
37 {
38 s_init_list(&(n->lsrql));
39 n->lsrqh = ospf_top_new(n->pool);
40 s_init(&(n->lsrqi), &(n->lsrql));
41
42 s_init_list(&(n->lsrtl));
43 n->lsrth = ospf_top_new(n->pool);
44 s_init(&(n->lsrti), &(n->lsrtl));
45 }
46
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.
50 */
51 static void
52 reset_lists(struct ospf_neighbor *n)
53 {
54 ospf_top_free(n->lsrqh);
55 ospf_top_free(n->lsrth);
56 init_lists(n);
57 }
58
59 struct ospf_neighbor *
60 ospf_neighbor_new(struct ospf_iface *ifa)
61 {
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));
66
67 n->pool = pool;
68 n->ifa = ifa;
69 add_tail(&ifa->neigh_list, NODE n);
70 n->adj = 0;
71 n->csn = 0;
72 n->ldbdes = mb_allocz(pool, ifa->iface->mtu);
73 n->state = NEIGHBOR_DOWN;
74
75 init_lists(n);
76 s_init(&(n->dbsi), &(po->lsal));
77
78 n->inactim = tm_new(pool);
79 n->inactim->data = n;
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);
84
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);
92
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);
102
103 return (n);
104 }
105
106 /**
107 * neigh_chstate - handles changes related to new or lod state of neighbor
108 * @n: OSPF neighbor
109 * @state: new state
110 *
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.
113 */
114
115 static void
116 neigh_chstate(struct ospf_neighbor *n, u8 state)
117 {
118 u8 oldstate;
119
120 oldstate = n->state;
121
122 if (oldstate != state)
123 {
124 struct ospf_iface *ifa = n->ifa;
125 struct proto_ospf *po = ifa->oa->po;
126 struct proto *p = &po->proto;
127
128 n->state = state;
129
130 OSPF_TRACE(D_EVENTS, "Neighbor %I changes state from \"%s\" to \"%s\".",
131 n->ip, ospf_ns[oldstate], ospf_ns[state]);
132
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);
137
138 if (oldstate == NEIGHBOR_FULL) /* Decrease number of adjacencies */
139 {
140 ifa->fadj--;
141 schedule_rt_lsa(ifa->oa);
142 if (ifa->type == OSPF_IT_VLINK) schedule_rt_lsa(ifa->voa);
143 schedule_net_lsa(ifa);
144 }
145
146 if (state == NEIGHBOR_FULL) /* Increase number of adjacencies */
147 {
148 ifa->fadj++;
149 schedule_rt_lsa(ifa->oa);
150 if (ifa->type == OSPF_IT_VLINK) schedule_rt_lsa(ifa->voa);
151 schedule_net_lsa(ifa);
152 }
153 if (state == NEIGHBOR_EXSTART)
154 {
155 if (n->adj == 0) /* First time adjacency */
156 {
157 n->dds = random_u32();
158 }
159 n->dds++;
160 n->myimms.byte = 0;
161 n->myimms.bit.ms = 1;
162 n->myimms.bit.m = 1;
163 n->myimms.bit.i = 1;
164 }
165 if (state > NEIGHBOR_EXSTART)
166 n->myimms.bit.i = 0;
167 }
168 }
169
170 static struct ospf_neighbor *
171 electbdr(list nl)
172 {
173 struct ospf_neighbor *neigh, *n1, *n2;
174 u32 nid;
175
176 #ifdef OSPFv2
177 nid = ipa_to_u32(neigh->ip);
178 #else /* OSPFv3 */
179 nid = neigh->rid;
180 #endif
181
182 n1 = NULL;
183 n2 = NULL;
184 WALK_LIST(neigh, nl) /* First try those decl. themselves */
185 {
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 */
189 {
190 if (neigh->bdr == nid) /* Declaring BDR */
191 {
192 if (n1 != NULL)
193 {
194 if (neigh->priority > n1->priority)
195 n1 = neigh;
196 else if (neigh->priority == n1->priority)
197 if (neigh->rid > n1->rid)
198 n1 = neigh;
199 }
200 else
201 {
202 n1 = neigh;
203 }
204 }
205 else /* And NOT declaring BDR */
206 {
207 if (n2 != NULL)
208 {
209 if (neigh->priority > n2->priority)
210 n2 = neigh;
211 else if (neigh->priority == n2->priority)
212 if (neigh->rid > n2->rid)
213 n2 = neigh;
214 }
215 else
216 {
217 n2 = neigh;
218 }
219 }
220 }
221 }
222 if (n1 == NULL)
223 n1 = n2;
224
225 return (n1);
226 }
227
228 static struct ospf_neighbor *
229 electdr(list nl)
230 {
231 struct ospf_neighbor *neigh, *n;
232 u32 nid;
233
234 #ifdef OSPFv2
235 nid = ipa_to_u32(neigh->ip);
236 #else /* OSPFv3 */
237 nid = neigh->rid;
238 #endif
239
240 n = NULL;
241 WALK_LIST(neigh, nl) /* And now DR */
242 {
243 if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
244 if (neigh->priority > 0) /* Eligible */
245 if (neigh->dr == nid) /* And declaring itself DR */
246 {
247 if (n != NULL)
248 {
249 if (neigh->priority > n->priority)
250 n = neigh;
251 else if (neigh->priority == n->priority)
252 if (neigh->rid > n->rid)
253 n = neigh;
254 }
255 else
256 {
257 n = neigh;
258 }
259 }
260 }
261
262 return (n);
263 }
264
265 static int
266 can_do_adj(struct ospf_neighbor *n)
267 {
268 struct ospf_iface *ifa;
269 struct proto *p;
270 int i;
271
272 ifa = n->ifa;
273 p = (struct proto *) (ifa->oa->po);
274 i = 0;
275
276 switch (ifa->type)
277 {
278 case OSPF_IT_PTP:
279 case OSPF_IT_VLINK:
280 i = 1;
281 break;
282 case OSPF_IT_BCAST:
283 case OSPF_IT_NBMA:
284 switch (ifa->state)
285 {
286 case OSPF_IS_DOWN:
287 bug("%s: Iface %s in down state?", p->name, ifa->iface->name);
288 break;
289 case OSPF_IS_WAITING:
290 DBG("%s: Neighbor? on iface %s\n", p->name, ifa->iface->name);
291 break;
292 case OSPF_IS_DROTHER:
293 if (((n->rid == ifa->drid) || (n->rid == ifa->bdrid))
294 && (n->state >= NEIGHBOR_2WAY))
295 i = 1;
296 break;
297 case OSPF_IS_PTP:
298 case OSPF_IS_BACKUP:
299 case OSPF_IS_DR:
300 if (n->state >= NEIGHBOR_2WAY)
301 i = 1;
302 break;
303 default:
304 bug("%s: Iface %s in unknown state?", p->name, ifa->iface->name);
305 break;
306 }
307 break;
308 default:
309 bug("%s: Iface %s is unknown type?", p->name, ifa->iface->name);
310 break;
311 }
312 DBG("%s: Iface %s can_do_adj=%d\n", p->name, ifa->iface->name, i);
313 return i;
314 }
315
316 /**
317 * ospf_neigh_sm - ospf neighbor state machine
318 * @n: neighor
319 * @event: actual event
320 *
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 .
327 */
328 void
329 ospf_neigh_sm(struct ospf_neighbor *n, int event)
330 {
331 struct proto_ospf *po = n->ifa->oa->po;
332 struct proto *p = &po->proto;
333
334 DBG("Neighbor state machine for neighbor %I, event '%s'\n", n->ip,
335 ospf_inm[event]);
336
337 switch (event)
338 {
339 case INM_START:
340 neigh_chstate(n, NEIGHBOR_ATTEMPT);
341 /* NBMA are used different way */
342 break;
343 case INM_HELLOREC:
344 switch (n->state)
345 {
346 case NEIGHBOR_ATTEMPT:
347 case NEIGHBOR_DOWN:
348 neigh_chstate(n, NEIGHBOR_INIT);
349 default:
350 tm_start(n->inactim, n->ifa->dead); /* Restart inactivity timer */
351 break;
352 }
353 break;
354 case INM_2WAYREC:
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);
359 break;
360 case INM_NEGDONE:
361 if (n->state == NEIGHBOR_EXSTART)
362 {
363 neigh_chstate(n, NEIGHBOR_EXCHANGE);
364
365 /* Reset DB summary list iterator */
366 s_get(&(n->dbsi));
367 s_init(&(n->dbsi), &po->lsal);
368
369 while (!EMPTY_LIST(n->ackl[ACKL_DELAY]))
370 {
371 struct lsah_n *no;
372 no = (struct lsah_n *) HEAD(n->ackl[ACKL_DELAY]);
373 rem_node(NODE no);
374 mb_free(no);
375 }
376 }
377 else
378 bug("NEGDONE and I'm not in EXSTART?");
379 break;
380 case INM_EXDONE:
381 neigh_chstate(n, NEIGHBOR_LOADING);
382 break;
383 case INM_LOADDONE:
384 neigh_chstate(n, NEIGHBOR_FULL);
385 break;
386 case INM_ADJOK:
387 switch (n->state)
388 {
389 case NEIGHBOR_2WAY:
390 /* Can In build adjacency? */
391 if (can_do_adj(n))
392 {
393 neigh_chstate(n, NEIGHBOR_EXSTART);
394 }
395 break;
396 default:
397 if (n->state >= NEIGHBOR_EXSTART)
398 if (!can_do_adj(n))
399 {
400 reset_lists(n);
401 neigh_chstate(n, NEIGHBOR_2WAY);
402 }
403 break;
404 }
405 break;
406 case INM_SEQMIS:
407 case INM_BADLSREQ:
408 if (n->state >= NEIGHBOR_EXCHANGE)
409 {
410 reset_lists(n);
411 neigh_chstate(n, NEIGHBOR_EXSTART);
412 }
413 break;
414 case INM_KILLNBR:
415 case INM_LLDOWN:
416 case INM_INACTTIM:
417 reset_lists(n);
418 neigh_chstate(n, NEIGHBOR_DOWN);
419 break;
420 case INM_1WAYREC:
421 reset_lists(n);
422 neigh_chstate(n, NEIGHBOR_INIT);
423 break;
424 default:
425 bug("%s: INM - Unknown event?", p->name);
426 break;
427 }
428 }
429
430 /**
431 * bdr_election - (Backup) Designed Router election
432 * @ifa: actual interface
433 *
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.
438 */
439 void
440 bdr_election(struct ospf_iface *ifa)
441 {
442 struct ospf_neighbor *neigh, *ndr, *nbdr, me;
443 u32 myid;
444 int doadj;
445 struct proto *p = &ifa->oa->po->proto;
446
447 DBG("(B)DR election.\n");
448
449 myid = p->cf->global->router_id;
450
451 me.state = NEIGHBOR_2WAY;
452 me.rid = myid;
453 me.priority = ifa->priority;
454 me.ip = ifa->iface->addr->ip;
455
456 #ifdef OSPFv2
457 me.dr = ipa_to_u32(ifa->drip);
458 me.bdr = ipa_to_u32(ifa->bdrip);
459 #else /* OSPFv3 */
460 me.dr = ifa->drid;
461 me.bdr = ifa->bdrid;
462 me.iface_id = ifa->iface->index;
463 #endif
464
465 add_tail(&ifa->neigh_list, NODE & me);
466
467 nbdr = electbdr(ifa->neigh_list);
468 ndr = electdr(ifa->neigh_list);
469
470 if (ndr == NULL)
471 ndr = nbdr;
472
473 /* 9.4. (4) */
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)))
478 {
479 #ifdef OSPFv2
480 me.dr = ndr ? ipa_to_u32(ndr->ip) : IPA_NONE;
481 me.bdr = nbdr ? ipa_to_u32(nbdr->ip) : IPA_NONE;
482 #else /* OSPFv3 */
483 me.dr = ndr ? ndr->rid : 0;
484 me.bdr = nbdr ? nbdr->rid : 0;
485 #endif
486
487 nbdr = electbdr(ifa->neigh_list);
488 ndr = electdr(ifa->neigh_list);
489
490 if (ndr == NULL)
491 ndr = nbdr;
492 }
493
494 u32 odrid = ifa->drid;
495 u32 obdrid = ifa->bdrid;
496
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;
501
502 #ifdef OSPFv3
503 ifa->dr_iface_id = ndr ? ndr->iface_id : 0;
504 #endif
505
506 DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid);
507
508 doadj = ((ifa->drid != odrid) || (ifa->bdrid != obdrid));
509
510 if (myid == ifa->drid)
511 ospf_iface_chstate(ifa, OSPF_IS_DR);
512 else
513 {
514 if (myid == ifa->bdrid)
515 ospf_iface_chstate(ifa, OSPF_IS_BACKUP);
516 else
517 ospf_iface_chstate(ifa, OSPF_IS_DROTHER);
518 }
519
520 rem_node(NODE & me);
521
522 if (doadj)
523 {
524 WALK_LIST(neigh, ifa->neigh_list)
525 {
526 ospf_neigh_sm(neigh, INM_ADJOK);
527 }
528 }
529 }
530
531 struct ospf_neighbor *
532 find_neigh(struct ospf_iface *ifa, u32 rid)
533 {
534 struct ospf_neighbor *n;
535
536 WALK_LIST(n, ifa->neigh_list) if (n->rid == rid)
537 return n;
538 return NULL;
539 }
540
541
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)
545 {
546 struct ospf_neighbor *n = NULL, *m;
547 struct ospf_iface *ifa;
548
549 WALK_LIST(ifa, po->iface_list) if ((m = find_neigh(ifa, rid)) != NULL)
550 {
551 if (m->state >= NEIGHBOR_2WAY)
552 {
553 if (n == NULL)
554 n = m;
555 else if (m->ifa->cost < n->ifa->cost)
556 n = m;
557 }
558 }
559 return n;
560 }
561
562 struct ospf_area *
563 ospf_find_area(struct proto_ospf *po, u32 aid)
564 {
565 struct ospf_area *oa;
566 WALK_LIST(oa, po->area_list)
567 if (((struct ospf_area *) oa)->areaid == aid)
568 return oa;
569 return NULL;
570 }
571
572 /* Neighbor is inactive for a long time. Remove it. */
573 static void
574 neighbor_timer_hook(timer * timer)
575 {
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;
579
580 OSPF_TRACE(D_EVENTS,
581 "Inactivity timer fired on interface %s for neighbor %I.",
582 ifa->iface->name, n->ip);
583 ospf_neigh_remove(n);
584 }
585
586 void
587 ospf_neigh_remove(struct ospf_neighbor *n)
588 {
589 struct ospf_iface *ifa = n->ifa;
590 struct proto *p = &ifa->oa->po->proto;
591
592 s_get(&(n->dbsi));
593 neigh_chstate(n, NEIGHBOR_DOWN);
594 rem_node(NODE n);
595 rfree(n->pool);
596 OSPF_TRACE(D_EVENTS, "Deleting neigbor.");
597 }
598
599 void
600 ospf_sh_neigh_info(struct ospf_neighbor *n)
601 {
602 struct ospf_iface *ifa = n->ifa;
603 char *pos = "other";
604 char etime[6];
605 int exp, sec, min;
606
607 exp = n->inactim->expires - now;
608 sec = exp % 60;
609 min = exp / 60;
610 if (min > 59)
611 {
612 bsprintf(etime, "-Inf-");
613 }
614 else
615 {
616 bsprintf(etime, "%02u:%02u", min, sec);
617 }
618
619 if (n->rid == ifa->drid)
620 pos = "dr ";
621 if (n->rid == ifa->bdrid)
622 pos = "bdr ";
623 if ((n->ifa->type == OSPF_IT_PTP) || (n->ifa->type == OSPF_IT_VLINK))
624 pos = "ptp ";
625
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));
629 }
630
631 static void
632 rxmt_timer_hook(timer * timer)
633 {
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;
637
638 DBG("%s: RXMT timer fired on interface %s for neigh: %I.\n",
639 p->name, n->ifa->iface->name, n->ip);
640
641 if(n->state < NEIGHBOR_EXSTART) return;
642
643 if (n->state == NEIGHBOR_EXSTART)
644 {
645 ospf_dbdes_send(n, 1);
646 return;
647 }
648
649 if ((n->state == NEIGHBOR_EXCHANGE) && n->myimms.bit.ms) /* I'm master */
650 ospf_dbdes_send(n, 0);
651
652
653 if (n->state < NEIGHBOR_FULL)
654 ospf_lsreq_send(n); /* EXCHANGE or LOADING */
655 else
656 {
657 if (!EMPTY_SLIST(n->lsrtl)) /* FULL */
658 {
659 list uplist;
660 slab *upslab;
661 struct l_lsr_head *llsh;
662
663 init_list(&uplist);
664 upslab = sl_new(n->pool, sizeof(struct l_lsr_head));
665
666 WALK_SLIST(en, n->lsrtl)
667 {
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);
677 }
678 ospf_lsupd_send_list(n, &uplist);
679 rfree(upslab);
680 }
681 }
682 }
683
684 static void
685 ackd_timer_hook(timer * t)
686 {
687 struct ospf_neighbor *n = t->data;
688 ospf_lsack_send(n, ACKL_DELAY);
689 }