Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / neighbor.c @ 48e5f32d

History | View | Annotate | Download (15.6 KB)

1 4364b47e Ondrej Filip
/*
2
 *        BIRD -- OSPF
3
 *
4 39e517d4 Ondrej Filip
 *        (c) 1999 - 2004 Ondrej Filip <feela@network.cz>
5 4364b47e Ondrej Filip
 *
6
 *        Can be freely distributed and used under the terms of the GNU GPL.
7
 */
8
9
#include "ospf.h"
10
11 2e10a170 Ondrej Filip
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 79f036ef Ondrej Filip
  "negotiation done", "exstart done", "bad ls request", "load done",
24
  "adjacency ok?", "sequence mismatch", "1-way received", "kill neighbor",
25 2e10a170 Ondrej Filip
  "inactivity timer", "line down"
26
};
27 79f036ef Ondrej Filip
28 0844b65d Ondrej Zajicek
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 39e517d4 Ondrej Filip
47 0dd7ccc7 Ondrej Zajicek
/* Resets LSA request and retransmit lists.
48 0844b65d Ondrej Zajicek
 * 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 39e517d4 Ondrej Filip
59
struct ospf_neighbor *
60
ospf_neighbor_new(struct ospf_iface *ifa)
61
{
62 86c84d76 Ondrej Filip
  struct proto *p = (struct proto *) (ifa->oa->po);
63 0844b65d Ondrej Zajicek
  struct proto_ospf *po = ifa->oa->po;
64 39e517d4 Ondrej Filip
  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 3e2bd0f1 Ondrej Filip
  n->csn = 0;
72 2e10a170 Ondrej Filip
  n->state = NEIGHBOR_DOWN;
73 39e517d4 Ondrej Filip
74 0844b65d Ondrej Zajicek
  init_lists(n);
75
  s_init(&(n->dbsi), &(po->lsal));
76
77 39e517d4 Ondrej Filip
  n->inactim = tm_new(pool);
78
  n->inactim->data = n;
79
  n->inactim->randomize = 0;
80
  n->inactim->hook = neighbor_timer_hook;
81
  n->inactim->recurrent = 0;
82
  DBG("%s: Installing inactivity timer.\n", p->name);
83
84
  n->rxmt_timer = tm_new(pool);
85
  n->rxmt_timer->data = n;
86
  n->rxmt_timer->randomize = 0;
87
  n->rxmt_timer->hook = rxmt_timer_hook;
88
  n->rxmt_timer->recurrent = ifa->rxmtint;
89 2e10a170 Ondrej Filip
  tm_start(n->rxmt_timer, n->ifa->rxmtint);
90 39e517d4 Ondrej Filip
  DBG("%s: Installing rxmt timer.\n", p->name);
91
92
  n->ackd_timer = tm_new(pool);
93
  n->ackd_timer->data = n;
94
  n->ackd_timer->randomize = 0;
95
  n->ackd_timer->hook = ackd_timer_hook;
96 2e10a170 Ondrej Filip
  n->ackd_timer->recurrent = ifa->rxmtint / 2;
97 c76ba51a Ondrej Filip
  init_list(&n->ackl[ACKL_DIRECT]);
98
  init_list(&n->ackl[ACKL_DELAY]);
99 2e10a170 Ondrej Filip
  tm_start(n->ackd_timer, n->ifa->rxmtint / 2);
100 39e517d4 Ondrej Filip
  DBG("%s: Installing ackd timer.\n", p->name);
101
102 2e10a170 Ondrej Filip
  return (n);
103 39e517d4 Ondrej Filip
}
104
105 7ab3ff6a Ondrej Filip
/**
106
 * neigh_chstate - handles changes related to new or lod state of neighbor
107
 * @n: OSPF neighbor
108
 * @state: new state
109
 *
110 baa5dd6c Ondrej Filip
 * Many actions have to be taken acording to a change of state of a neighbor. It
111 7ab3ff6a Ondrej Filip
 * starts rxmt timers, call interface state machine etc.
112
 */
113
114 0844b65d Ondrej Zajicek
static void
115 4364b47e Ondrej Filip
neigh_chstate(struct ospf_neighbor *n, u8 state)
116
{
117 eae4fcf2 Ondrej Filip
  u8 oldstate;
118 4364b47e Ondrej Filip
119 2e10a170 Ondrej Filip
  oldstate = n->state;
120 eae4fcf2 Ondrej Filip
121 2e10a170 Ondrej Filip
  if (oldstate != state)
122 4364b47e Ondrej Filip
  {
123 2e10a170 Ondrej Filip
    struct ospf_iface *ifa = n->ifa;
124
    struct proto_ospf *po = ifa->oa->po;
125
    struct proto *p = &po->proto;
126 4057093f Ondrej Filip
127 2e10a170 Ondrej Filip
    n->state = state;
128 4057093f Ondrej Filip
129 2e10a170 Ondrej Filip
    OSPF_TRACE(D_EVENTS, "Neighbor %I changes state from \"%s\" to \"%s\".",
130
               n->ip, ospf_ns[oldstate], ospf_ns[state]);
131 4057093f Ondrej Filip
132 2e10a170 Ondrej Filip
    if ((state == NEIGHBOR_2WAY) && (oldstate < NEIGHBOR_2WAY))
133 b9ed99f7 Ondrej Filip
      ospf_iface_sm(ifa, ISM_NEICH);
134 2e10a170 Ondrej Filip
    if ((state < NEIGHBOR_2WAY) && (oldstate >= NEIGHBOR_2WAY))
135 b9ed99f7 Ondrej Filip
      ospf_iface_sm(ifa, ISM_NEICH);
136 4057093f Ondrej Filip
137 2e10a170 Ondrej Filip
    if (oldstate == NEIGHBOR_FULL)        /* Decrease number of adjacencies */
138 9bc1808a Ondrej Filip
    {
139 d345cda5 Ondrej Filip
      ifa->fadj--;
140 70a38319 Ondrej Filip
      schedule_rt_lsa(ifa->oa);
141 5d3f5552 Ondrej Filip
      if (ifa->type == OSPF_IT_VLINK) schedule_rt_lsa(ifa->voa);
142 78e2c6cc Ondrej Filip
      schedule_net_lsa(ifa);
143 9bc1808a Ondrej Filip
    }
144 2e10a170 Ondrej Filip
145
    if (state == NEIGHBOR_FULL)        /* Increase number of adjacencies */
146 9bc1808a Ondrej Filip
    {
147 d345cda5 Ondrej Filip
      ifa->fadj++;
148 70a38319 Ondrej Filip
      schedule_rt_lsa(ifa->oa);
149 3b16080c Ondrej Filip
      if (ifa->type == OSPF_IT_VLINK) schedule_rt_lsa(ifa->voa);
150 78e2c6cc Ondrej Filip
      schedule_net_lsa(ifa);
151 9bc1808a Ondrej Filip
    }
152 2e10a170 Ondrej Filip
    if (state == NEIGHBOR_EXSTART)
153 eae4fcf2 Ondrej Filip
    {
154 2e10a170 Ondrej Filip
      if (n->adj == 0)                /* First time adjacency */
155 eae4fcf2 Ondrej Filip
      {
156 2e10a170 Ondrej Filip
        n->dds = random_u32();
157 eae4fcf2 Ondrej Filip
      }
158
      n->dds++;
159 2e10a170 Ondrej Filip
      n->myimms.byte = 0;
160
      n->myimms.bit.ms = 1;
161
      n->myimms.bit.m = 1;
162
      n->myimms.bit.i = 1;
163 eae4fcf2 Ondrej Filip
    }
164 2e10a170 Ondrej Filip
    if (state > NEIGHBOR_EXSTART)
165
      n->myimms.bit.i = 0;
166 4364b47e Ondrej Filip
  }
167
}
168
169 0844b65d Ondrej Zajicek
static struct ospf_neighbor *
170 4364b47e Ondrej Filip
electbdr(list nl)
171
{
172 2e10a170 Ondrej Filip
  struct ospf_neighbor *neigh, *n1, *n2;
173 c3226991 Ondrej Zajicek
  u32 nid;
174
175 2e10a170 Ondrej Filip
  n1 = NULL;
176
  n2 = NULL;
177 c3226991 Ondrej Zajicek
  WALK_LIST(neigh, nl)                        /* First try those decl. themselves */
178 4364b47e Ondrej Filip
  {
179 b49e6f5a Ondrej Zajicek
#ifdef OSPFv2
180
    nid = ipa_to_u32(neigh->ip);
181
#else /* OSPFv3 */
182
    nid = neigh->rid;
183
#endif
184
185 2e10a170 Ondrej Filip
    if (neigh->state >= NEIGHBOR_2WAY)        /* Higher than 2WAY */
186 c3226991 Ondrej Zajicek
      if (neigh->priority > 0)                /* Eligible */
187
        if (neigh->dr != nid)                /* And not decl. itself DR */
188 4364b47e Ondrej Filip
        {
189 c3226991 Ondrej Zajicek
          if (neigh->bdr == nid)        /* Declaring BDR */
190 2e10a170 Ondrej Filip
          {
191
            if (n1 != NULL)
192
            {
193
              if (neigh->priority > n1->priority)
194
                n1 = neigh;
195
              else if (neigh->priority == n1->priority)
196
                if (neigh->rid > n1->rid)
197
                  n1 = neigh;
198
            }
199 4364b47e Ondrej Filip
            else
200 2e10a170 Ondrej Filip
            {
201
              n1 = neigh;
202
            }
203
          }
204
          else                        /* And NOT declaring BDR */
205
          {
206
            if (n2 != NULL)
207
            {
208
              if (neigh->priority > n2->priority)
209
                n2 = neigh;
210
              else if (neigh->priority == n2->priority)
211
                if (neigh->rid > n2->rid)
212
                  n2 = neigh;
213
            }
214 4364b47e Ondrej Filip
            else
215 2e10a170 Ondrej Filip
            {
216
              n2 = neigh;
217
            }
218
          }
219
        }
220 4364b47e Ondrej Filip
  }
221 2e10a170 Ondrej Filip
  if (n1 == NULL)
222
    n1 = n2;
223 4364b47e Ondrej Filip
224 2e10a170 Ondrej Filip
  return (n1);
225 4364b47e Ondrej Filip
}
226
227 0844b65d Ondrej Zajicek
static struct ospf_neighbor *
228 4364b47e Ondrej Filip
electdr(list nl)
229
{
230 2e10a170 Ondrej Filip
  struct ospf_neighbor *neigh, *n;
231 c3226991 Ondrej Zajicek
  u32 nid;
232
233 b49e6f5a Ondrej Zajicek
  n = NULL;
234
  WALK_LIST(neigh, nl)                        /* And now DR */
235
  {
236 c3226991 Ondrej Zajicek
#ifdef OSPFv2
237 b49e6f5a Ondrej Zajicek
    nid = ipa_to_u32(neigh->ip);
238 c3226991 Ondrej Zajicek
#else /* OSPFv3 */
239 b49e6f5a Ondrej Zajicek
    nid = neigh->rid;
240 c3226991 Ondrej Zajicek
#endif
241 4364b47e Ondrej Filip
242 2e10a170 Ondrej Filip
    if (neigh->state >= NEIGHBOR_2WAY)        /* Higher than 2WAY */
243 c3226991 Ondrej Zajicek
      if (neigh->priority > 0)                /* Eligible */
244
        if (neigh->dr == nid)                /* And declaring itself DR */
245 4364b47e Ondrej Filip
        {
246 2e10a170 Ondrej Filip
          if (n != NULL)
247
          {
248
            if (neigh->priority > n->priority)
249
              n = neigh;
250
            else if (neigh->priority == n->priority)
251
              if (neigh->rid > n->rid)
252
                n = neigh;
253
          }
254 4364b47e Ondrej Filip
          else
255 2e10a170 Ondrej Filip
          {
256
            n = neigh;
257
          }
258
        }
259 4364b47e Ondrej Filip
  }
260
261 2e10a170 Ondrej Filip
  return (n);
262 4364b47e Ondrej Filip
}
263
264 9831e591 Martin Mares
static int
265 4364b47e Ondrej Filip
can_do_adj(struct ospf_neighbor *n)
266
{
267
  struct ospf_iface *ifa;
268
  struct proto *p;
269
  int i;
270
271 2e10a170 Ondrej Filip
  ifa = n->ifa;
272 86c84d76 Ondrej Filip
  p = (struct proto *) (ifa->oa->po);
273 2e10a170 Ondrej Filip
  i = 0;
274 4364b47e Ondrej Filip
275 2e10a170 Ondrej Filip
  switch (ifa->type)
276 4364b47e Ondrej Filip
  {
277 2e10a170 Ondrej Filip
  case OSPF_IT_PTP:
278 919f5411 Ondrej Zajicek
  case OSPF_IT_PTMP:
279 2e10a170 Ondrej Filip
  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 391931d4 Ondrej Zajicek
    case OSPF_IS_LOOP:
288 48e5f32d Ondrej Zajicek
      bug("%s: Iface %s in down state?", p->name, ifa->ifname);
289 4364b47e Ondrej Filip
      break;
290 2e10a170 Ondrej Filip
    case OSPF_IS_WAITING:
291 48e5f32d Ondrej Zajicek
      DBG("%s: Neighbor? on iface %s\n", p->name, ifa->ifname);
292 2e10a170 Ondrej Filip
      break;
293
    case OSPF_IS_DROTHER:
294
      if (((n->rid == ifa->drid) || (n->rid == ifa->bdrid))
295
          && (n->state >= NEIGHBOR_2WAY))
296
        i = 1;
297
      break;
298
    case OSPF_IS_PTP:
299
    case OSPF_IS_BACKUP:
300
    case OSPF_IS_DR:
301
      if (n->state >= NEIGHBOR_2WAY)
302
        i = 1;
303 4364b47e Ondrej Filip
      break;
304
    default:
305 48e5f32d Ondrej Zajicek
      bug("%s: Iface %s in unknown state?", p->name, ifa->ifname);
306 4364b47e Ondrej Filip
      break;
307 2e10a170 Ondrej Filip
    }
308
    break;
309
  default:
310 48e5f32d Ondrej Zajicek
    bug("%s: Iface %s is unknown type?", p->name, ifa->ifname);
311 2e10a170 Ondrej Filip
    break;
312 4364b47e Ondrej Filip
  }
313 48e5f32d Ondrej Zajicek
  DBG("%s: Iface %s can_do_adj=%d\n", p->name, ifa->ifname, i);
314 4364b47e Ondrej Filip
  return i;
315
}
316
317 7ab3ff6a Ondrej Filip
/**
318
 * ospf_neigh_sm - ospf neighbor state machine
319
 * @n: neighor
320
 * @event: actual event
321
 *
322 baa5dd6c Ondrej Filip
 * This part implements the neighbor state machine as described in 10.3 of
323
 * RFC 2328. The only difference is that state %NEIGHBOR_ATTEMPT is not
324
 * used. We discover neighbors on nonbroadcast networks in the
325
 * same way as on broadcast networks. The only difference is in
326
 * sending hello packets. These are sent to IPs listed in
327 7ab3ff6a Ondrej Filip
 * @ospf_iface->nbma_list .
328
 */
329 4364b47e Ondrej Filip
void
330
ospf_neigh_sm(struct ospf_neighbor *n, int event)
331
{
332 86c84d76 Ondrej Filip
  struct proto_ospf *po = n->ifa->oa->po;
333
  struct proto *p = &po->proto;
334 4364b47e Ondrej Filip
335 23d67029 Ondrej Zajicek
  DBG("Neighbor state machine for neighbor %I, event '%s'\n", n->ip,
336 2e10a170 Ondrej Filip
             ospf_inm[event]);
337 79f036ef Ondrej Filip
338 2e10a170 Ondrej Filip
  switch (event)
339 4364b47e Ondrej Filip
  {
340 2e10a170 Ondrej Filip
  case INM_START:
341
    neigh_chstate(n, NEIGHBOR_ATTEMPT);
342
    /* NBMA are used different way */
343
    break;
344
  case INM_HELLOREC:
345
    switch (n->state)
346
    {
347
    case NEIGHBOR_ATTEMPT:
348
    case NEIGHBOR_DOWN:
349
      neigh_chstate(n, NEIGHBOR_INIT);
350
    default:
351 8e48831a Ondrej Zajicek
      tm_start(n->inactim, n->ifa->deadint);        /* Restart inactivity timer */
352 4364b47e Ondrej Filip
      break;
353 2e10a170 Ondrej Filip
    }
354
    break;
355
  case INM_2WAYREC:
356
    if (n->state < NEIGHBOR_2WAY)
357
      neigh_chstate(n, NEIGHBOR_2WAY);
358
    if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
359
      neigh_chstate(n, NEIGHBOR_EXSTART);
360
    break;
361
  case INM_NEGDONE:
362
    if (n->state == NEIGHBOR_EXSTART)
363
    {
364
      neigh_chstate(n, NEIGHBOR_EXCHANGE);
365 0844b65d Ondrej Zajicek
366
      /* Reset DB summary list iterator */
367
      s_get(&(n->dbsi));
368 86c84d76 Ondrej Filip
      s_init(&(n->dbsi), &po->lsal);
369 0844b65d Ondrej Zajicek
370 2e10a170 Ondrej Filip
      while (!EMPTY_LIST(n->ackl[ACKL_DELAY]))
371 4364b47e Ondrej Filip
      {
372 2e10a170 Ondrej Filip
        struct lsah_n *no;
373
        no = (struct lsah_n *) HEAD(n->ackl[ACKL_DELAY]);
374
        rem_node(NODE no);
375
        mb_free(no);
376 4364b47e Ondrej Filip
      }
377 2e10a170 Ondrej Filip
    }
378
    else
379
      bug("NEGDONE and I'm not in EXSTART?");
380
    break;
381
  case INM_EXDONE:
382
    neigh_chstate(n, NEIGHBOR_LOADING);
383
    break;
384
  case INM_LOADDONE:
385
    neigh_chstate(n, NEIGHBOR_FULL);
386
    break;
387
  case INM_ADJOK:
388
    switch (n->state)
389
    {
390
    case NEIGHBOR_2WAY:
391
      /* Can In build adjacency? */
392
      if (can_do_adj(n))
393 4364b47e Ondrej Filip
      {
394 2e10a170 Ondrej Filip
        neigh_chstate(n, NEIGHBOR_EXSTART);
395 4364b47e Ondrej Filip
      }
396
      break;
397
    default:
398 2e10a170 Ondrej Filip
      if (n->state >= NEIGHBOR_EXSTART)
399
        if (!can_do_adj(n))
400
        {
401 0844b65d Ondrej Zajicek
          reset_lists(n);
402 2e10a170 Ondrej Filip
          neigh_chstate(n, NEIGHBOR_2WAY);
403
        }
404 4364b47e Ondrej Filip
      break;
405 2e10a170 Ondrej Filip
    }
406
    break;
407
  case INM_SEQMIS:
408
  case INM_BADLSREQ:
409
    if (n->state >= NEIGHBOR_EXCHANGE)
410
    {
411 0844b65d Ondrej Zajicek
      reset_lists(n);
412 2e10a170 Ondrej Filip
      neigh_chstate(n, NEIGHBOR_EXSTART);
413
    }
414
    break;
415
  case INM_KILLNBR:
416
  case INM_LLDOWN:
417
  case INM_INACTTIM:
418 0844b65d Ondrej Zajicek
    reset_lists(n);
419 2e10a170 Ondrej Filip
    neigh_chstate(n, NEIGHBOR_DOWN);
420
    break;
421
  case INM_1WAYREC:
422 0844b65d Ondrej Zajicek
    reset_lists(n);
423 2e10a170 Ondrej Filip
    neigh_chstate(n, NEIGHBOR_INIT);
424
    break;
425
  default:
426
    bug("%s: INM - Unknown event?", p->name);
427
    break;
428 4364b47e Ondrej Filip
  }
429
}
430
431 7ab3ff6a Ondrej Filip
/**
432
 * bdr_election - (Backup) Designed Router election
433
 * @ifa: actual interface
434
 *
435 baa5dd6c Ondrej Filip
 * When the wait timer fires, it is time to elect (Backup) Designated Router.
436 7ab3ff6a Ondrej Filip
 * Structure describing me is added to this list so every electing router
437 baa5dd6c Ondrej Filip
 * has the same list. Backup Designated Router is elected before Designated
438 7ab3ff6a Ondrej Filip
 * Router. This process is described in 9.4 of RFC 2328.
439
 */
440 4364b47e Ondrej Filip
void
441 7ab3ff6a Ondrej Filip
bdr_election(struct ospf_iface *ifa)
442 4364b47e Ondrej Filip
{
443 8a70a13e Ondrej Zajicek
  struct proto_ospf *po = ifa->oa->po;
444
  u32 myid = po->router_id;
445 2e10a170 Ondrej Filip
  struct ospf_neighbor *neigh, *ndr, *nbdr, me;
446 4364b47e Ondrej Filip
  int doadj;
447
448 423230f2 Ondrej Filip
  DBG("(B)DR election.\n");
449 4364b47e Ondrej Filip
450 2e10a170 Ondrej Filip
  me.state = NEIGHBOR_2WAY;
451
  me.rid = myid;
452
  me.priority = ifa->priority;
453 353729f5 Ondrej Zajicek
  me.ip = ifa->addr->ip;
454 4364b47e Ondrej Filip
455 c3226991 Ondrej Zajicek
#ifdef OSPFv2
456
  me.dr = ipa_to_u32(ifa->drip);
457
  me.bdr = ipa_to_u32(ifa->bdrip);
458
#else /* OSPFv3 */
459
  me.dr = ifa->drid;
460
  me.bdr = ifa->bdrid;
461 dd4da6f6 Ondrej Zajicek
  me.iface_id = ifa->iface_id;
462 c3226991 Ondrej Zajicek
#endif
463
464 2e10a170 Ondrej Filip
  add_tail(&ifa->neigh_list, NODE & me);
465 4364b47e Ondrej Filip
466 2e10a170 Ondrej Filip
  nbdr = electbdr(ifa->neigh_list);
467
  ndr = electdr(ifa->neigh_list);
468 4364b47e Ondrej Filip
469 2e10a170 Ondrej Filip
  if (ndr == NULL)
470
    ndr = nbdr;
471 4364b47e Ondrej Filip
472 c3226991 Ondrej Zajicek
  /* 9.4. (4) */
473 2e10a170 Ondrej Filip
  if (((ifa->drid == myid) && (ndr != &me))
474
      || ((ifa->drid != myid) && (ndr == &me))
475
      || ((ifa->bdrid == myid) && (nbdr != &me))
476
      || ((ifa->bdrid != myid) && (nbdr == &me)))
477 4364b47e Ondrej Filip
  {
478 c3226991 Ondrej Zajicek
#ifdef OSPFv2
479 f9c799a0 Ondrej Zajicek
    me.dr = ndr ? ipa_to_u32(ndr->ip) : 0;
480
    me.bdr = nbdr ? ipa_to_u32(nbdr->ip) : 0;
481 c3226991 Ondrej Zajicek
#else /* OSPFv3 */
482
    me.dr = ndr ? ndr->rid : 0;
483
    me.bdr = nbdr ? nbdr->rid : 0;
484
#endif
485 2e10a170 Ondrej Filip
486
    nbdr = electbdr(ifa->neigh_list);
487
    ndr = electdr(ifa->neigh_list);
488 423230f2 Ondrej Filip
489 c3226991 Ondrej Zajicek
    if (ndr == NULL)
490
      ndr = nbdr;
491 28950169 Ondrej Filip
  }
492
493 c3226991 Ondrej Zajicek
  u32 odrid = ifa->drid;
494
  u32 obdrid = ifa->bdrid;
495
 
496
  ifa->drid = ndr ? ndr->rid : 0;
497
  ifa->drip = ndr ? ndr->ip  : IPA_NONE;
498
  ifa->bdrid = nbdr ? nbdr->rid : 0;
499
  ifa->bdrip = nbdr ? nbdr->ip  : IPA_NONE;
500
501
#ifdef OSPFv3
502
  ifa->dr_iface_id = ndr ? ndr->iface_id : 0;
503
#endif
504 4364b47e Ondrej Filip
505 3aab39f5 Ondrej Zajicek
  DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid);
506 4364b47e Ondrej Filip
507 c3226991 Ondrej Zajicek
  doadj = ((ifa->drid != odrid) || (ifa->bdrid != obdrid));
508
509 2e10a170 Ondrej Filip
  if (myid == ifa->drid)
510
    ospf_iface_chstate(ifa, OSPF_IS_DR);
511 4364b47e Ondrej Filip
  else
512
  {
513 2e10a170 Ondrej Filip
    if (myid == ifa->bdrid)
514
      ospf_iface_chstate(ifa, OSPF_IS_BACKUP);
515
    else
516
      ospf_iface_chstate(ifa, OSPF_IS_DROTHER);
517 4364b47e Ondrej Filip
  }
518
519 2e10a170 Ondrej Filip
  rem_node(NODE & me);
520 4364b47e Ondrej Filip
521 2e10a170 Ondrej Filip
  if (doadj)
522 4364b47e Ondrej Filip
  {
523 2e10a170 Ondrej Filip
    WALK_LIST(neigh, ifa->neigh_list)
524 4364b47e Ondrej Filip
    {
525
      ospf_neigh_sm(neigh, INM_ADJOK);
526
    }
527
  }
528
}
529
530
struct ospf_neighbor *
531
find_neigh(struct ospf_iface *ifa, u32 rid)
532
{
533
  struct ospf_neighbor *n;
534 919f5411 Ondrej Zajicek
  WALK_LIST(n, ifa->neigh_list)
535
    if (n->rid == rid)
536
      return n;
537
  return NULL;
538
}
539 4364b47e Ondrej Filip
540 919f5411 Ondrej Zajicek
struct ospf_neighbor *
541
find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip)
542
{
543
  struct ospf_neighbor *n;
544
  WALK_LIST(n, ifa->neigh_list)
545
    if (ipa_equal(n->ip, ip))
546
      return n;
547 4364b47e Ondrej Filip
  return NULL;
548
}
549
550 c7e46aae Ondrej Filip
/* Neighbor is inactive for a long time. Remove it. */
551 0844b65d Ondrej Zajicek
static void
552 2e10a170 Ondrej Filip
neighbor_timer_hook(timer * timer)
553 c7e46aae Ondrej Filip
{
554 86c84d76 Ondrej Filip
  struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
555
  struct ospf_iface *ifa = n->ifa;
556
  struct proto *p = &ifa->oa->po->proto;
557 c7e46aae Ondrej Filip
558 48e5f32d Ondrej Zajicek
  OSPF_TRACE(D_EVENTS, "Inactivity timer fired on interface %s for neighbor %I.",
559
             ifa->ifname, n->ip);
560 18a0c0bb Ondrej Filip
  ospf_neigh_remove(n);
561
}
562
563
void
564
ospf_neigh_remove(struct ospf_neighbor *n)
565
{
566 86c84d76 Ondrej Filip
  struct ospf_iface *ifa = n->ifa;
567
  struct proto *p = &ifa->oa->po->proto;
568 18a0c0bb Ondrej Filip
569 919f5411 Ondrej Zajicek
  if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
570
  {
571
    struct nbma_node *nn = find_nbma_node(ifa, n->ip);
572
    if (nn)
573
      nn->found = 0;
574
  }
575
576 0844b65d Ondrej Zajicek
  s_get(&(n->dbsi));
577 c7e46aae Ondrej Filip
  neigh_chstate(n, NEIGHBOR_DOWN);
578
  rem_node(NODE n);
579 035f6acb Ondrej Filip
  rfree(n->pool);
580 abcbfd04 Ondrej Filip
  OSPF_TRACE(D_EVENTS, "Deleting neigbor.");
581 18a0c0bb Ondrej Filip
}
582 a783e259 Ondrej Filip
583 1ec52253 Ondrej Zajicek
static void
584
ospf_neigh_bfd_hook(struct bfd_request *req)
585
{
586
  struct ospf_neighbor *n = req->data;
587
  struct proto *p = &n->ifa->oa->po->proto;
588
589
  if (req->down)
590
  {
591
    OSPF_TRACE(D_EVENTS, "BFD session down for %I on %s",
592 48e5f32d Ondrej Zajicek
               n->ip, n->ifa->ifname);
593 1ec52253 Ondrej Zajicek
594
    ospf_neigh_remove(n);
595
  }
596
}
597
598
void
599
ospf_neigh_update_bfd(struct ospf_neighbor *n, int use_bfd)
600
{
601
  if (use_bfd && !n->bfd_req)
602
    n->bfd_req = bfd_request_session(n->pool, n->ip, n->ifa->addr->ip, n->ifa->iface,
603
                                     ospf_neigh_bfd_hook, n);
604
605
  if (!use_bfd && n->bfd_req)
606
  {
607
    rfree(n->bfd_req);
608
    n->bfd_req = NULL;
609
  }
610
}
611
612
613 a783e259 Ondrej Filip
void
614
ospf_sh_neigh_info(struct ospf_neighbor *n)
615
{
616 2e10a170 Ondrej Filip
  struct ospf_iface *ifa = n->ifa;
617
  char *pos = "other";
618
  char etime[6];
619
  int exp, sec, min;
620
621
  exp = n->inactim->expires - now;
622 6eb4b73f Ondrej Filip
  sec = exp % 60;
623
  min = exp / 60;
624 2e10a170 Ondrej Filip
  if (min > 59)
625
  {
626
    bsprintf(etime, "-Inf-");
627
  }
628
  else
629
  {
630
    bsprintf(etime, "%02u:%02u", min, sec);
631
  }
632
633
  if (n->rid == ifa->drid)
634
    pos = "dr   ";
635 919f5411 Ondrej Zajicek
  else if (n->rid == ifa->bdrid)
636 2e10a170 Ondrej Filip
    pos = "bdr  ";
637 919f5411 Ondrej Zajicek
  else if ((n->ifa->type == OSPF_IT_PTP) || (n->ifa->type == OSPF_IT_PTMP) ||
638
           (n->ifa->type == OSPF_IT_VLINK))
639 2e10a170 Ondrej Filip
    pos = "ptp  ";
640
641 cf31112f Ondrej Zajicek
  cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority,
642 48e5f32d Ondrej Zajicek
          ospf_ns[n->state], pos, etime, ifa->ifname, n->ip);
643 a783e259 Ondrej Filip
}
644 39e517d4 Ondrej Filip
645 0844b65d Ondrej Zajicek
static void
646 2e10a170 Ondrej Filip
rxmt_timer_hook(timer * timer)
647 39e517d4 Ondrej Filip
{
648 2e10a170 Ondrej Filip
  struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
649 e81b440f Ondrej Zajicek
  // struct proto *p = &n->ifa->oa->po->proto;
650 39e517d4 Ondrej Filip
  struct top_hash_entry *en;
651
652
  DBG("%s: RXMT timer fired on interface %s for neigh: %I.\n",
653 48e5f32d Ondrej Zajicek
      p->name, n->ifa->ifname, n->ip);
654 b1f7229a Ondrej Filip
655
  if(n->state < NEIGHBOR_EXSTART) return;
656
657
  if (n->state == NEIGHBOR_EXSTART)
658
  {
659 b722fe7e Ondrej Zajicek
    ospf_dbdes_send(n, 1);
660 b1f7229a Ondrej Filip
    return;
661
  }
662
663
  if ((n->state == NEIGHBOR_EXCHANGE) && n->myimms.bit.ms)        /* I'm master */
664 b722fe7e Ondrej Zajicek
    ospf_dbdes_send(n, 0);
665 b1f7229a Ondrej Filip
666 39e517d4 Ondrej Filip
667 b1f7229a Ondrej Filip
  if (n->state < NEIGHBOR_FULL)        
668
    ospf_lsreq_send(n);        /* EXCHANGE or LOADING */
669 39e517d4 Ondrej Filip
  else
670
  {
671 b1f7229a Ondrej Filip
    if (!EMPTY_SLIST(n->lsrtl))        /* FULL */
672 39e517d4 Ondrej Filip
    {
673
      list uplist;
674
      slab *upslab;
675
      struct l_lsr_head *llsh;
676
677
      init_list(&uplist);
678 2e10a170 Ondrej Filip
      upslab = sl_new(n->pool, sizeof(struct l_lsr_head));
679 39e517d4 Ondrej Filip
680 b181f444 Ondrej Filip
      WALK_SLIST(en, n->lsrtl)
681 39e517d4 Ondrej Filip
      {
682 2e10a170 Ondrej Filip
        if ((SNODE en)->next == (SNODE en))
683
          bug("RTList is cycled");
684
        llsh = sl_alloc(upslab);
685
        llsh->lsh.id = en->lsa.id;
686
        llsh->lsh.rt = en->lsa.rt;
687
        llsh->lsh.type = en->lsa.type;
688 3aab39f5 Ondrej Zajicek
        DBG("Working on ID: %R, RT: %R, Type: %u\n",
689
            en->lsa.id, en->lsa.rt, en->lsa.type);
690 2e10a170 Ondrej Filip
        add_tail(&uplist, NODE llsh);
691 39e517d4 Ondrej Filip
      }
692 6f3203fa Ondrej Filip
      ospf_lsupd_send_list(n, &uplist);
693 39e517d4 Ondrej Filip
      rfree(upslab);
694
    }
695
  }
696
}
697
698 0844b65d Ondrej Zajicek
static void
699 2e10a170 Ondrej Filip
ackd_timer_hook(timer * t)
700 28de5133 Ondrej Filip
{
701 2e10a170 Ondrej Filip
  struct ospf_neighbor *n = t->data;
702 c76ba51a Ondrej Filip
  ospf_lsack_send(n, ACKL_DELAY);
703 28de5133 Ondrej Filip
}