Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (15.6 KB)

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->state = NEIGHBOR_DOWN;
73

    
74
  init_lists(n);
75
  s_init(&(n->dbsi), &(po->lsal));
76

    
77
  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
  tm_start(n->rxmt_timer, n->ifa->rxmtint);
90
  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
  n->ackd_timer->recurrent = ifa->rxmtint / 2;
97
  init_list(&n->ackl[ACKL_DIRECT]);
98
  init_list(&n->ackl[ACKL_DELAY]);
99
  tm_start(n->ackd_timer, n->ifa->rxmtint / 2);
100
  DBG("%s: Installing ackd timer.\n", p->name);
101

    
102
  return (n);
103
}
104

    
105
/**
106
 * neigh_chstate - handles changes related to new or lod state of neighbor
107
 * @n: OSPF neighbor
108
 * @state: new state
109
 *
110
 * Many actions have to be taken acording to a change of state of a neighbor. It
111
 * starts rxmt timers, call interface state machine etc.
112
 */
113

    
114
static void
115
neigh_chstate(struct ospf_neighbor *n, u8 state)
116
{
117
  u8 oldstate;
118

    
119
  oldstate = n->state;
120

    
121
  if (oldstate != state)
122
  {
123
    struct ospf_iface *ifa = n->ifa;
124
    struct proto_ospf *po = ifa->oa->po;
125
    struct proto *p = &po->proto;
126

    
127
    n->state = state;
128

    
129
    OSPF_TRACE(D_EVENTS, "Neighbor %I changes state from \"%s\" to \"%s\".",
130
               n->ip, ospf_ns[oldstate], ospf_ns[state]);
131

    
132
    if ((state == NEIGHBOR_2WAY) && (oldstate < NEIGHBOR_2WAY))
133
      ospf_iface_sm(ifa, ISM_NEICH);
134
    if ((state < NEIGHBOR_2WAY) && (oldstate >= NEIGHBOR_2WAY))
135
      ospf_iface_sm(ifa, ISM_NEICH);
136

    
137
    if (oldstate == NEIGHBOR_FULL)        /* Decrease number of adjacencies */
138
    {
139
      ifa->fadj--;
140
      schedule_rt_lsa(ifa->oa);
141
      if (ifa->type == OSPF_IT_VLINK) schedule_rt_lsa(ifa->voa);
142
      schedule_net_lsa(ifa);
143
    }
144

    
145
    if (state == NEIGHBOR_FULL)        /* Increase number of adjacencies */
146
    {
147
      ifa->fadj++;
148
      schedule_rt_lsa(ifa->oa);
149
      if (ifa->type == OSPF_IT_VLINK) schedule_rt_lsa(ifa->voa);
150
      schedule_net_lsa(ifa);
151
    }
152
    if (state == NEIGHBOR_EXSTART)
153
    {
154
      if (n->adj == 0)                /* First time adjacency */
155
      {
156
        n->dds = random_u32();
157
      }
158
      n->dds++;
159
      n->myimms.byte = 0;
160
      n->myimms.bit.ms = 1;
161
      n->myimms.bit.m = 1;
162
      n->myimms.bit.i = 1;
163
    }
164
    if (state > NEIGHBOR_EXSTART)
165
      n->myimms.bit.i = 0;
166
  }
167
}
168

    
169
static struct ospf_neighbor *
170
electbdr(list nl)
171
{
172
  struct ospf_neighbor *neigh, *n1, *n2;
173
  u32 nid;
174

    
175
  n1 = NULL;
176
  n2 = NULL;
177
  WALK_LIST(neigh, nl)                        /* First try those decl. themselves */
178
  {
179
#ifdef OSPFv2
180
    nid = ipa_to_u32(neigh->ip);
181
#else /* OSPFv3 */
182
    nid = neigh->rid;
183
#endif
184

    
185
    if (neigh->state >= NEIGHBOR_2WAY)        /* Higher than 2WAY */
186
      if (neigh->priority > 0)                /* Eligible */
187
        if (neigh->dr != nid)                /* And not decl. itself DR */
188
        {
189
          if (neigh->bdr == nid)        /* Declaring BDR */
190
          {
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
            else
200
            {
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
            else
215
            {
216
              n2 = neigh;
217
            }
218
          }
219
        }
220
  }
221
  if (n1 == NULL)
222
    n1 = n2;
223

    
224
  return (n1);
225
}
226

    
227
static struct ospf_neighbor *
228
electdr(list nl)
229
{
230
  struct ospf_neighbor *neigh, *n;
231
  u32 nid;
232

    
233
  n = NULL;
234
  WALK_LIST(neigh, nl)                        /* And now DR */
235
  {
236
#ifdef OSPFv2
237
    nid = ipa_to_u32(neigh->ip);
238
#else /* OSPFv3 */
239
    nid = neigh->rid;
240
#endif
241

    
242
    if (neigh->state >= NEIGHBOR_2WAY)        /* Higher than 2WAY */
243
      if (neigh->priority > 0)                /* Eligible */
244
        if (neigh->dr == nid)                /* And declaring itself DR */
245
        {
246
          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
          else
255
          {
256
            n = neigh;
257
          }
258
        }
259
  }
260

    
261
  return (n);
262
}
263

    
264
static int
265
can_do_adj(struct ospf_neighbor *n)
266
{
267
  struct ospf_iface *ifa;
268
  struct proto *p;
269
  int i;
270

    
271
  ifa = n->ifa;
272
  p = (struct proto *) (ifa->oa->po);
273
  i = 0;
274

    
275
  switch (ifa->type)
276
  {
277
  case OSPF_IT_PTP:
278
  case OSPF_IT_PTMP:
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
    case OSPF_IS_LOOP:
288
      bug("%s: Iface %s in down state?", p->name, ifa->ifname);
289
      break;
290
    case OSPF_IS_WAITING:
291
      DBG("%s: Neighbor? on iface %s\n", p->name, ifa->ifname);
292
      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
      break;
304
    default:
305
      bug("%s: Iface %s in unknown state?", p->name, ifa->ifname);
306
      break;
307
    }
308
    break;
309
  default:
310
    bug("%s: Iface %s is unknown type?", p->name, ifa->ifname);
311
    break;
312
  }
313
  DBG("%s: Iface %s can_do_adj=%d\n", p->name, ifa->ifname, i);
314
  return i;
315
}
316

    
317
/**
318
 * ospf_neigh_sm - ospf neighbor state machine
319
 * @n: neighor
320
 * @event: actual event
321
 *
322
 * 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
 * @ospf_iface->nbma_list .
328
 */
329
void
330
ospf_neigh_sm(struct ospf_neighbor *n, int event)
331
{
332
  struct proto_ospf *po = n->ifa->oa->po;
333
  struct proto *p = &po->proto;
334

    
335
  DBG("Neighbor state machine for neighbor %I, event '%s'\n", n->ip,
336
             ospf_inm[event]);
337

    
338
  switch (event)
339
  {
340
  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
      tm_start(n->inactim, n->ifa->deadint);        /* Restart inactivity timer */
352
      break;
353
    }
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

    
366
      /* Reset DB summary list iterator */
367
      s_get(&(n->dbsi));
368
      s_init(&(n->dbsi), &po->lsal);
369

    
370
      while (!EMPTY_LIST(n->ackl[ACKL_DELAY]))
371
      {
372
        struct lsah_n *no;
373
        no = (struct lsah_n *) HEAD(n->ackl[ACKL_DELAY]);
374
        rem_node(NODE no);
375
        mb_free(no);
376
      }
377
    }
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
      {
394
        neigh_chstate(n, NEIGHBOR_EXSTART);
395
      }
396
      break;
397
    default:
398
      if (n->state >= NEIGHBOR_EXSTART)
399
        if (!can_do_adj(n))
400
        {
401
          reset_lists(n);
402
          neigh_chstate(n, NEIGHBOR_2WAY);
403
        }
404
      break;
405
    }
406
    break;
407
  case INM_SEQMIS:
408
  case INM_BADLSREQ:
409
    if (n->state >= NEIGHBOR_EXCHANGE)
410
    {
411
      reset_lists(n);
412
      neigh_chstate(n, NEIGHBOR_EXSTART);
413
    }
414
    break;
415
  case INM_KILLNBR:
416
  case INM_LLDOWN:
417
  case INM_INACTTIM:
418
    reset_lists(n);
419
    neigh_chstate(n, NEIGHBOR_DOWN);
420
    break;
421
  case INM_1WAYREC:
422
    reset_lists(n);
423
    neigh_chstate(n, NEIGHBOR_INIT);
424
    break;
425
  default:
426
    bug("%s: INM - Unknown event?", p->name);
427
    break;
428
  }
429
}
430

    
431
/**
432
 * bdr_election - (Backup) Designed Router election
433
 * @ifa: actual interface
434
 *
435
 * When the wait timer fires, it is time to elect (Backup) Designated Router.
436
 * Structure describing me is added to this list so every electing router
437
 * has the same list. Backup Designated Router is elected before Designated
438
 * Router. This process is described in 9.4 of RFC 2328.
439
 */
440
void
441
bdr_election(struct ospf_iface *ifa)
442
{
443
  struct proto_ospf *po = ifa->oa->po;
444
  u32 myid = po->router_id;
445
  struct ospf_neighbor *neigh, *ndr, *nbdr, me;
446
  int doadj;
447

    
448
  DBG("(B)DR election.\n");
449

    
450
  me.state = NEIGHBOR_2WAY;
451
  me.rid = myid;
452
  me.priority = ifa->priority;
453
  me.ip = ifa->addr->ip;
454

    
455
#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
  me.iface_id = ifa->iface_id;
462
#endif
463

    
464
  add_tail(&ifa->neigh_list, NODE & me);
465

    
466
  nbdr = electbdr(ifa->neigh_list);
467
  ndr = electdr(ifa->neigh_list);
468

    
469
  if (ndr == NULL)
470
    ndr = nbdr;
471

    
472
  /* 9.4. (4) */
473
  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
  {
478
#ifdef OSPFv2
479
    me.dr = ndr ? ipa_to_u32(ndr->ip) : 0;
480
    me.bdr = nbdr ? ipa_to_u32(nbdr->ip) : 0;
481
#else /* OSPFv3 */
482
    me.dr = ndr ? ndr->rid : 0;
483
    me.bdr = nbdr ? nbdr->rid : 0;
484
#endif
485

    
486
    nbdr = electbdr(ifa->neigh_list);
487
    ndr = electdr(ifa->neigh_list);
488

    
489
    if (ndr == NULL)
490
      ndr = nbdr;
491
  }
492

    
493
  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

    
505
  DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid);
506

    
507
  doadj = ((ifa->drid != odrid) || (ifa->bdrid != obdrid));
508

    
509
  if (myid == ifa->drid)
510
    ospf_iface_chstate(ifa, OSPF_IS_DR);
511
  else
512
  {
513
    if (myid == ifa->bdrid)
514
      ospf_iface_chstate(ifa, OSPF_IS_BACKUP);
515
    else
516
      ospf_iface_chstate(ifa, OSPF_IS_DROTHER);
517
  }
518

    
519
  rem_node(NODE & me);
520

    
521
  if (doadj)
522
  {
523
    WALK_LIST(neigh, ifa->neigh_list)
524
    {
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
  WALK_LIST(n, ifa->neigh_list)
535
    if (n->rid == rid)
536
      return n;
537
  return NULL;
538
}
539

    
540
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
  return NULL;
548
}
549

    
550
/* Neighbor is inactive for a long time. Remove it. */
551
static void
552
neighbor_timer_hook(timer * timer)
553
{
554
  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

    
558
  OSPF_TRACE(D_EVENTS, "Inactivity timer fired on interface %s for neighbor %I.",
559
             ifa->ifname, n->ip);
560
  ospf_neigh_remove(n);
561
}
562

    
563
void
564
ospf_neigh_remove(struct ospf_neighbor *n)
565
{
566
  struct ospf_iface *ifa = n->ifa;
567
  struct proto *p = &ifa->oa->po->proto;
568

    
569
  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
  s_get(&(n->dbsi));
577
  neigh_chstate(n, NEIGHBOR_DOWN);
578
  rem_node(NODE n);
579
  rfree(n->pool);
580
  OSPF_TRACE(D_EVENTS, "Deleting neigbor.");
581
}
582

    
583
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
               n->ip, n->ifa->ifname);
593

    
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
void
614
ospf_sh_neigh_info(struct ospf_neighbor *n)
615
{
616
  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
  sec = exp % 60;
623
  min = exp / 60;
624
  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
  else if (n->rid == ifa->bdrid)
636
    pos = "bdr  ";
637
  else if ((n->ifa->type == OSPF_IT_PTP) || (n->ifa->type == OSPF_IT_PTMP) ||
638
           (n->ifa->type == OSPF_IT_VLINK))
639
    pos = "ptp  ";
640

    
641
  cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority,
642
          ospf_ns[n->state], pos, etime, ifa->ifname, n->ip);
643
}
644

    
645
static void
646
rxmt_timer_hook(timer * timer)
647
{
648
  struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
649
  // struct proto *p = &n->ifa->oa->po->proto;
650
  struct top_hash_entry *en;
651

    
652
  DBG("%s: RXMT timer fired on interface %s for neigh: %I.\n",
653
      p->name, n->ifa->ifname, n->ip);
654

    
655
  if(n->state < NEIGHBOR_EXSTART) return;
656

    
657
  if (n->state == NEIGHBOR_EXSTART)
658
  {
659
    ospf_dbdes_send(n, 1);
660
    return;
661
  }
662

    
663
  if ((n->state == NEIGHBOR_EXCHANGE) && n->myimms.bit.ms)        /* I'm master */
664
    ospf_dbdes_send(n, 0);
665

    
666

    
667
  if (n->state < NEIGHBOR_FULL)        
668
    ospf_lsreq_send(n);        /* EXCHANGE or LOADING */
669
  else
670
  {
671
    if (!EMPTY_SLIST(n->lsrtl))        /* FULL */
672
    {
673
      list uplist;
674
      slab *upslab;
675
      struct l_lsr_head *llsh;
676

    
677
      init_list(&uplist);
678
      upslab = sl_new(n->pool, sizeof(struct l_lsr_head));
679

    
680
      WALK_SLIST(en, n->lsrtl)
681
      {
682
        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
        DBG("Working on ID: %R, RT: %R, Type: %u\n",
689
            en->lsa.id, en->lsa.rt, en->lsa.type);
690
        add_tail(&uplist, NODE llsh);
691
      }
692
      ospf_lsupd_send_list(n, &uplist);
693
      rfree(upslab);
694
    }
695
  }
696
}
697

    
698
static void
699
ackd_timer_hook(timer * t)
700
{
701
  struct ospf_neighbor *n = t->data;
702
  ospf_lsack_send(n, ACKL_DELAY);
703
}