Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / iface.c @ 99f5fc14

History | View | Annotate | Download (15 KB)

1
/*
2
 *        BIRD -- OSPF
3
 *
4
 *        (c) 1999--2005 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_is[] = { "down", "loop", "waiting", "point-to-point", "drother",
12
  "backup", "dr"
13
};
14

    
15
char *ospf_ism[] = { "interface up", "wait timer fired", "backup seen",
16
  "neighbor change", "loop indicated", "unloop indicated", "interface down"
17
};
18

    
19
char *ospf_it[] = { "broadcast", "nbma", "point-to-point", "virtual link" };
20

    
21
static void
22
poll_timer_hook(timer * timer)
23
{
24
  log("POLL!");
25
  ospf_hello_send(timer, 1, NULL);
26
}
27

    
28
static void
29
hello_timer_hook(timer * timer)
30
{
31
  ospf_hello_send(timer, 0, NULL);
32
}
33

    
34
static void
35
wait_timer_hook(timer * timer)
36
{
37
  struct ospf_iface *ifa = (struct ospf_iface *) timer->data;
38
  struct proto *p = &ifa->oa->po->proto;
39

    
40
  OSPF_TRACE(D_EVENTS, "Wait timer fired on interface %s.", ifa->iface->name);
41
  ospf_iface_sm(ifa, ISM_WAITF);
42
}
43

    
44
u32
45
rxbufsize(struct ospf_iface *ifa)
46
{
47
  switch(ifa->rxbuf)
48
  {
49
    case OSPF_RXBUF_NORMAL:
50
      return (ifa->iface->mtu * 2);
51
      break;
52
    case OSPF_RXBUF_LARGE:
53
      return OSPF_MAX_PKT_SIZE;
54
      break;
55
    default:
56
      return ifa->rxbuf;
57
      break;
58
  }
59
}
60

    
61
static sock *
62
ospf_open_socket(struct ospf_iface *ifa, int mc)
63
{
64
  sock *ipsk;
65
  struct proto *p = &ifa->oa->po->proto;
66

    
67
  ipsk = sk_new(p->pool);
68
  ipsk->type = SK_IP;
69
  ipsk->dport = OSPF_PROTO;
70

    
71
#ifdef OSPFv2
72
  /* FIXME - why there is IPA_NONE on multicast sockets ? */
73
  if (mc)
74
    ipsk->saddr = IPA_NONE;
75
  else
76
    ipsk->saddr = ifa->iface->addr->ip;
77
#else /* OSPFv3 */
78
  ipsk->saddr = ifa->lladdr;
79
#endif
80

    
81
  ipsk->tos = IP_PREC_INTERNET_CONTROL;
82
  ipsk->ttl = 1;
83
  if (ifa->type == OSPF_IT_VLINK)
84
    ipsk->ttl = 255;
85
  ipsk->rx_hook = ospf_rx_hook;
86
  ipsk->tx_hook = ospf_tx_hook;
87
  ipsk->err_hook = ospf_err_hook;
88
  ipsk->iface = ifa->iface;
89
  ipsk->rbsize = rxbufsize(ifa);
90
  ipsk->tbsize = ifa->iface->mtu;
91
  ipsk->data = (void *) ifa;
92
  if (sk_open(ipsk) != 0)
93
    goto err;
94

    
95
#ifdef OSPFv3
96
  /* 12 is an offset of the checksum in an OSPF packet */
97
  if (sk_set_ipv6_checksum(ipsk, 12) < 0)
98
    goto err;
99
#endif
100

    
101
  if (mc)
102
  {
103
    if (sk_setup_multicast(ipsk) < 0)
104
      goto err;
105

    
106
    if (sk_join_group(ipsk, AllSPFRouters) < 0)
107
      goto err;
108
  }
109

    
110
  return ipsk;
111

    
112
 err:
113
  rfree(ipsk);
114
  return NULL;
115
}
116

    
117

    
118
/**
119
 * ospf_iface_chstate - handle changes of interface state
120
 * @ifa: OSPF interface
121
 * @state: new state
122
 *
123
 * Many actions must be taken according to interface state changes. New network
124
 * LSAs must be originated, flushed, new multicast sockets to listen for messages for
125
 * %ALLDROUTERS have to be opened, etc.
126
 */
127
void
128
ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
129
{
130
  struct proto_ospf *po = ifa->oa->po;
131
  struct proto *p = &po->proto;
132
  u8 oldstate = ifa->state;
133

    
134
  if (oldstate != state)
135
  {
136
    ifa->state = state;
137

    
138
    if (ifa->type == OSPF_IT_VLINK)
139
    {
140
      OSPF_TRACE(D_EVENTS,
141
                 "Changing state of virtual link %R from \"%s\" into \"%s\".",
142
                 ifa->vid, ospf_is[oldstate], ospf_is[state]);
143
      if (state == OSPF_IS_PTP)
144
      {
145
        ifa->sk = ospf_open_socket(ifa, 0);
146
      }
147
    }
148
    else
149
    {
150
      OSPF_TRACE(D_EVENTS,
151
                 "Changing state of iface: %s from \"%s\" into \"%s\".",
152
                 ifa->iface->name, ospf_is[oldstate], ospf_is[state]);
153
      if (ifa->iface->flags & IF_MULTICAST)
154
      {
155
        if ((ifa->type != OSPF_IT_NBMA) && (ifa->ioprob == OSPF_I_OK) &&
156
            ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR)))
157
        {
158
          if (!ifa->dr_up == 0)
159
          {
160
            /* FIXME some error handing ? */
161
            sk_join_group(ifa->sk, AllDRouters);
162
            ifa->dr_up = 1;
163
          }
164
        }
165
        else if (ifa->dr_up)
166
        {
167
          sk_leave_group(ifa->sk, AllDRouters);
168
          ifa->dr_up = 0;
169
        }
170
        if ((oldstate == OSPF_IS_DR) && (ifa->net_lsa != NULL))
171
        {
172
          ifa->net_lsa->lsa.age = LSA_MAXAGE;
173
          if (state >= OSPF_IS_WAITING)
174
          {
175
            ospf_lsupd_flush_nlsa(po, ifa->net_lsa);
176
          }
177
          if (can_flush_lsa(po))
178
            flush_lsa(ifa->net_lsa, po);
179
          ifa->net_lsa = NULL;
180
        }
181
      }
182
    }
183
  }
184
}
185

    
186
static void
187
ospf_iface_down(struct ospf_iface *ifa)
188
{
189
  struct ospf_neighbor *n, *nx;
190
  struct proto_ospf *po = ifa->oa->po;
191
  struct proto *p = &po->proto;
192
  struct ospf_iface *iff;
193

    
194
  /* First of all kill all the related vlinks */
195
  if (ifa->type != OSPF_IT_VLINK)
196
  {
197
    WALK_LIST(iff, po->iface_list)
198
    {
199
      if ((iff->type == OSPF_IT_VLINK) && (iff->iface == ifa->iface))
200
        ospf_iface_down(iff);
201
    }
202
  }
203

    
204
  WALK_LIST_DELSAFE(n, nx, ifa->neigh_list)
205
  {
206
    OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip);
207
    ospf_neigh_remove(n);
208
  }
209

    
210
  rfree(ifa->sk);
211
  ifa->sk = NULL;
212

    
213
  if (ifa->type == OSPF_IT_VLINK)
214
  {
215
    ifa->iface = NULL;
216
    return;
217
  }
218
  else
219
  {
220
    rfree(ifa->wait_timer);
221
    rfree(ifa->hello_timer);
222
    rfree(ifa->poll_timer);
223
    rfree(ifa->lock);
224
    rem_node(NODE ifa);
225
    mb_free(ifa);
226
  }
227
}
228

    
229
/**
230
 * ospf_iface_sm - OSPF interface state machine
231
 * @ifa: OSPF interface
232
 * @event: event comming to state machine
233
 *
234
 * This fully respects 9.3 of RFC 2328 except we don't use %LOOP state of
235
 * interface.
236
 */
237
void
238
ospf_iface_sm(struct ospf_iface *ifa, int event)
239
{
240
  struct ospf_area *oa = ifa->oa;
241

    
242
  DBG("SM on %s %s. Event is '%s'\n", (ifa->type == OSPF_IT_VLINK) ? "vlink" : "iface",
243
    ifa->iface ? ifa->iface->name : "(none)" , ospf_ism[event]);
244

    
245
  switch (event)
246
  {
247
  case ISM_UP:
248
    if (ifa->state == OSPF_IS_DOWN)
249
    {
250
      /* Now, nothing should be adjacent */
251
      if ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_VLINK))
252
      {
253
        ospf_iface_chstate(ifa, OSPF_IS_PTP);
254
      }
255
      else
256
      {
257
        if (ifa->priority == 0)
258
          ospf_iface_chstate(ifa, OSPF_IS_DROTHER);
259
        else
260
        {
261
          ospf_iface_chstate(ifa, OSPF_IS_WAITING);
262
          tm_start(ifa->wait_timer, ifa->waitint);
263
        }
264
      }
265

    
266
      tm_start(ifa->hello_timer, ifa->helloint);
267

    
268
      if (ifa->poll_timer)
269
        tm_start(ifa->poll_timer, ifa->pollint);
270

    
271
      hello_timer_hook(ifa->hello_timer);
272
    }
273
    schedule_link_lsa(ifa);
274
    schedule_rt_lsa(ifa->oa);
275
    break;
276
  case ISM_BACKS:
277
  case ISM_WAITF:
278
    if (ifa->state == OSPF_IS_WAITING)
279
    {
280
      bdr_election(ifa);
281
    }
282
    break;
283
  case ISM_NEICH:
284
    if ((ifa->state == OSPF_IS_DROTHER) || (ifa->state == OSPF_IS_DR) ||
285
        (ifa->state == OSPF_IS_BACKUP))
286
    {
287
      bdr_election(ifa);
288
      schedule_rt_lsa(ifa->oa);
289
    }
290
    break;
291
  case ISM_DOWN:
292
    ospf_iface_chstate(ifa, OSPF_IS_DOWN);
293
    ospf_iface_down(ifa);
294
    schedule_link_lsa(ifa);
295
    schedule_rt_lsa(oa);
296
    break;
297
  case ISM_LOOP:                /* Useless? */
298
    ospf_iface_chstate(ifa, OSPF_IS_LOOP);
299
    ospf_iface_down(ifa);
300
    schedule_rt_lsa(ifa->oa);
301
    break;
302
  case ISM_UNLOOP:
303
    ospf_iface_chstate(ifa, OSPF_IS_DOWN);
304
    schedule_rt_lsa(ifa->oa);
305
    break;
306
  default:
307
    bug("OSPF_I_SM - Unknown event?");
308
    break;
309
  }
310

    
311
}
312

    
313
#if 0
314
static sock *
315
ospf_open_mc_socket(struct ospf_iface *ifa)
316
{
317
  sock *mcsk;
318
  struct proto *p = &ifa->oa->po->proto;
319

320
  mcsk = sk_new(p->pool);
321
  mcsk->type = SK_IP_MC;
322
  mcsk->sport = 0;
323
  mcsk->dport = OSPF_PROTO;
324

325
#ifdef OSPFv2
326
  mcsk->saddr = AllSPFRouters;
327
#else /* OSPFv3 */
328
  // mcsk->saddr = AllSPFRouters;
329
  mcsk->saddr = ifa->lladdr;
330
#endif
331

    
332
  mcsk->daddr = AllSPFRouters;
333
  mcsk->tos = IP_PREC_INTERNET_CONTROL;
334
  mcsk->ttl = 1;
335
  mcsk->rx_hook = ospf_rx_hook;
336
  mcsk->tx_hook = ospf_tx_hook;
337
  mcsk->err_hook = ospf_err_hook;
338
  mcsk->iface = ifa->iface;
339
  mcsk->rbsize = rxbufsize(ifa);
340
  mcsk->tbsize = ifa->iface->mtu;
341
  mcsk->data = (void *) ifa;
342
  if (sk_open(mcsk) != 0)
343
  {
344
    DBG("%s: SK_OPEN: mc open failed.\n", p->name);
345
    return (NULL);
346
  }
347
  DBG("%s: SK_OPEN: mc opened.\n", p->name);
348
  return (mcsk);
349
}
350
#endif
351

    
352
u8
353
ospf_iface_clasify(struct iface * ifa)
354
{
355
  if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) ==
356
      (IF_MULTIACCESS | IF_MULTICAST))
357
    return OSPF_IT_BCAST;
358

    
359
  if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) == IF_MULTIACCESS)
360
    return OSPF_IT_NBMA;
361

    
362
  return OSPF_IT_PTP;
363
}
364

    
365
struct ospf_iface *
366
ospf_iface_find(struct proto_ospf *p, struct iface *what)
367
{
368
  struct ospf_iface *i;
369

    
370
  WALK_LIST(i, p->iface_list) if ((i->iface == what) && (i->type != OSPF_IT_VLINK))
371
    return i;
372
  return NULL;
373
}
374

    
375
static void
376
ospf_iface_add(struct object_lock *lock)
377
{
378
  struct ospf_iface *ifa = lock->data;
379
  struct proto_ospf *po = ifa->oa->po;
380
  struct proto *p = &po->proto;
381
  struct iface *iface = lock->iface;
382

    
383
  ifa->lock = lock;
384

    
385
  ifa->ioprob = OSPF_I_OK;
386

    
387
  ifa->sk = ospf_open_socket(ifa, ifa->type != OSPF_IT_NBMA);
388
  if (ifa->sk == NULL)
389
  {
390
    log("%s: Huh? could not open ip socket on interface %s?", p->name,
391
        iface->name);
392
    log("%s: Declaring as stub.", p->name);
393
    ifa->stub = 1;
394
    ifa->ioprob += OSPF_I_IP;
395
  }
396

    
397
  ifa->state = OSPF_IS_DOWN;
398
  ospf_iface_sm(ifa, ISM_UP);
399
}
400

    
401
void
402
ospf_iface_new(struct proto_ospf *po, struct iface *iface,
403
               struct ospf_area_config *ac, struct ospf_iface_patt *ip)
404
{
405
  struct proto *p = &po->proto;
406
  struct ospf_iface *ifa;
407
  struct nbma_node *nbma, *nb;
408
  struct object_lock *lock;
409
  struct ospf_area *oa;
410

    
411
  ifa = mb_allocz(p->pool, sizeof(struct ospf_iface));
412
  ifa->iface = iface;
413

    
414
  ifa->cost = ip->cost;
415
  ifa->rxmtint = ip->rxmtint;
416
  ifa->inftransdelay = ip->inftransdelay;
417
  ifa->priority = ip->priority;
418
  ifa->helloint = ip->helloint;
419
  ifa->pollint = ip->pollint;
420
  ifa->strictnbma = ip->strictnbma;
421
  ifa->waitint = ip->waitint;
422
  ifa->dead = (ip->dead == 0) ? ip->deadc * ifa->helloint : ip->dead;
423
  ifa->stub = ip->stub;
424

    
425
#ifdef OSPFv2
426
  ifa->autype = ip->autype;
427
  ifa->passwords = ip->passwords;
428
#endif
429

    
430
#ifdef OSPFv3
431
  ifa->instance_id = ip->instance_id;
432

    
433
  ifa->lladdr = IPA_NONE;
434

    
435
  /* Find link-local address */
436
  if (ifa->type != OSPF_IT_VLINK)
437
    {
438
      struct ifa *a;
439
      WALK_LIST(a, iface->addrs)
440
        if (a->scope == SCOPE_LINK)
441
          {
442
            ifa->lladdr = a->ip;
443
            break;
444
          }
445

    
446
      if (! ipa_nonzero(ifa->lladdr))
447
        log(L_WARN "%s: Missing link local address on interface %s", p->name,  iface->name);
448
    }
449
#endif
450

    
451
  ifa->rxbuf = ip->rxbuf;
452

    
453
  if (ip->type == OSPF_IT_UNDEF)
454
    ifa->type = ospf_iface_clasify(ifa->iface);
455
  else
456
    ifa->type = ip->type;
457

    
458
  init_list(&ifa->neigh_list);
459
  init_list(&ifa->nbma_list);
460

    
461
  WALK_LIST(nb, ip->nbma_list)
462
  {
463
    nbma = mb_alloc(p->pool, sizeof(struct nbma_node));
464
    nbma->ip = nb->ip;
465
    nbma->eligible = nb->eligible;
466
    add_tail(&ifa->nbma_list, NODE nbma);
467
  }
468

    
469
  /* Add hello timer */
470
  ifa->hello_timer = tm_new(p->pool);
471
  ifa->hello_timer->data = ifa;
472
  ifa->hello_timer->randomize = 0;
473
  ifa->hello_timer->hook = hello_timer_hook;
474
  ifa->hello_timer->recurrent = ifa->helloint;
475
  DBG("%s: Installing hello timer. (%u)\n", p->name, ifa->helloint);
476

    
477
  if (ifa->type == OSPF_IT_NBMA)
478
  {
479
    ifa->poll_timer = tm_new(p->pool);
480
    ifa->poll_timer->data = ifa;
481
    ifa->poll_timer->randomize = 0;
482
    ifa->poll_timer->hook = poll_timer_hook;
483
    ifa->poll_timer->recurrent = ifa->pollint;
484
    DBG("%s: Installing poll timer. (%u)\n", p->name, ifa->pollint);
485
  }
486
  else
487
    ifa->poll_timer = NULL;
488

    
489
  ifa->wait_timer = tm_new(p->pool);
490
  ifa->wait_timer->data = ifa;
491
  ifa->wait_timer->randomize = 0;
492
  ifa->wait_timer->hook = wait_timer_hook;
493
  ifa->wait_timer->recurrent = 0;
494
  DBG("%s: Installing wait timer. (%u)\n", p->name, ifa->waitint);
495
  add_tail(&((struct proto_ospf *) p)->iface_list, NODE ifa);
496
  ifa->state = OSPF_IS_DOWN;
497

    
498
  ifa->oa = NULL;
499
  WALK_LIST(oa, po->area_list)
500
  {
501
    if (oa->areaid == ac->areaid)
502
    {
503
      ifa->oa = oa;
504
      break;
505
    }
506
  }
507

    
508
  if (!ifa->oa)
509
    bug("Cannot add any area to accepted Interface");
510
  else
511

    
512
  if (ifa->type == OSPF_IT_VLINK)
513
  {
514
    ifa->oa = po->backbone;
515
    ifa->voa = oa;
516
    ifa->vid = ip->vid;
517
    return;                        /* Don't lock, don't add sockets */
518
  }
519

    
520
  lock = olock_new(p->pool);
521
  lock->addr = AllSPFRouters;
522
  lock->type = OBJLOCK_IP;
523
  lock->port = OSPF_PROTO;
524
  lock->iface = iface;
525
  lock->data = ifa;
526
  lock->hook = ospf_iface_add;
527

    
528
  olock_acquire(lock);
529
}
530

    
531
void
532
ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa)
533
{
534
  struct proto *p = &po->proto;
535
  struct ospf_packet *op;
536
  struct ospf_neighbor *n;
537
  OSPF_TRACE(D_EVENTS, "Changing MTU on interface %s.", ifa->iface->name);
538

    
539
  if (ifa->sk)
540
  {
541
    ifa->sk->rbsize = rxbufsize(ifa);
542
    ifa->sk->tbsize = ifa->iface->mtu;
543
    sk_reallocate(ifa->sk);
544
  }
545

    
546
  WALK_LIST(n, ifa->neigh_list)
547
  {
548
    op = (struct ospf_packet *) n->ldbdes;
549
    n->ldbdes = mb_allocz(n->pool, ifa->iface->mtu);
550

    
551
    if (ntohs(op->length) <= ifa->iface->mtu)        /* If the packet in old buffer is bigger, let it filled by zeros */
552
      memcpy(n->ldbdes, op, ifa->iface->mtu);        /* If the packet is old is same or smaller, copy it */
553

    
554
    rfree(op);
555
  }
556
}
557

    
558
void
559
ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface)
560
{
561
  struct proto_ospf *po = (struct proto_ospf *) p;
562
  struct ospf_config *c = (struct ospf_config *) (p->cf);
563
  struct ospf_area_config *ac;
564
  struct ospf_iface_patt *ip = NULL;
565
  struct ospf_iface *ifa;
566

    
567
  DBG("%s: If notify called\n", p->name);
568
  if (iface->flags & IF_IGNORE)
569
    return;
570

    
571
  if (flags & IF_CHANGE_UP)
572
  {
573
    WALK_LIST(ac, c->area_list)
574
    {
575
      if (ip = (struct ospf_iface_patt *)
576
          iface_patt_find(&ac->patt_list, iface))
577
        break;
578
    }
579

    
580
    if (ip)
581
    {
582
      OSPF_TRACE(D_EVENTS, "Using interface %s.", iface->name);
583
      ospf_iface_new(po, iface, ac, ip);
584
    }
585
  }
586

    
587
  if (flags & IF_CHANGE_DOWN)
588
  {
589
    if ((ifa = ospf_iface_find((struct proto_ospf *) p, iface)) != NULL)
590
    {
591
      OSPF_TRACE(D_EVENTS, "Killing interface %s.", iface->name);
592
      ospf_iface_sm(ifa, ISM_DOWN);
593
    }
594
  }
595

    
596
  if (flags & IF_CHANGE_MTU)
597
  {
598
    if ((ifa = ospf_iface_find((struct proto_ospf *) p, iface)) != NULL)
599
      ospf_iface_change_mtu(po, ifa);
600
  }
601
}
602

    
603
void
604
ospf_iface_info(struct ospf_iface *ifa)
605
{
606
  char *strict = "(strict)";
607

    
608
  if ((ifa->type != OSPF_IT_NBMA) || (ifa->strictnbma == 0))
609
    strict = "";
610
  if (ifa->type == OSPF_IT_VLINK)
611
  {
612
    cli_msg(-1015, "Virtual link to %R:", ifa->vid);
613
    cli_msg(-1015, "\tPeer IP: %I", ifa->vip);
614
    cli_msg(-1015, "\tTransit area: %R (%u)", ifa->voa->areaid,
615
            ifa->voa->areaid);
616
    cli_msg(-1015, "\tInterface: \"%s\"",
617
            (ifa->iface ? ifa->iface->name : "(none)"));
618
  }
619
  else
620
  {
621
    cli_msg(-1015, "Interface \"%s\":",
622
            (ifa->iface ? ifa->iface->name : "(none)"));
623
    cli_msg(-1015, "\tType: %s %s", ospf_it[ifa->type], strict);
624
    cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid);
625
  }
626
  cli_msg(-1015, "\tState: %s %s", ospf_is[ifa->state],
627
          ifa->stub ? "(stub)" : "");
628
  cli_msg(-1015, "\tPriority: %u", ifa->priority);
629
  cli_msg(-1015, "\tCost: %u", ifa->cost);
630
  cli_msg(-1015, "\tHello timer: %u", ifa->helloint);
631

    
632
  if (ifa->type == OSPF_IT_NBMA)
633
  {
634
    cli_msg(-1015, "\tPoll timer: %u", ifa->pollint);
635
  }
636
  cli_msg(-1015, "\tWait timer: %u", ifa->waitint);
637
  cli_msg(-1015, "\tDead timer: %u", ifa->dead);
638
  cli_msg(-1015, "\tRetransmit timer: %u", ifa->rxmtint);
639
  if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
640
  {
641
    cli_msg(-1015, "\tDesigned router (ID): %R", ifa->drid);
642
    cli_msg(-1015, "\tDesigned router (IP): %I", ifa->drip);
643
    cli_msg(-1015, "\tBackup designed router (ID): %R", ifa->bdrid);
644
    cli_msg(-1015, "\tBackup designed router (IP): %I", ifa->bdrip);
645
  }
646
}
647

    
648
void
649
ospf_iface_shutdown(struct ospf_iface *ifa)
650
{
651
  init_list(&ifa->neigh_list);
652
  hello_timer_hook(ifa->hello_timer);
653
}