Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / iface.c @ 2f9955b5

History | View | Annotate | Download (27.7 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", "ptp", "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", "ptp", "ptmp", "virtual link" };
20

    
21
static void
22
poll_timer_hook(timer * timer)
23
{
24
  ospf_hello_send(timer->data, OHS_POLL, NULL);
25
}
26

    
27
static void
28
hello_timer_hook(timer * timer)
29
{
30
  ospf_hello_send(timer->data, OHS_HELLO, NULL);
31
}
32

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

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

    
43
static void ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa);
44

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

    
62
struct nbma_node *
63
find_nbma_node_in(list *nnl, ip_addr ip)
64
{
65
  struct nbma_node *nn;
66
  WALK_LIST(nn, *nnl)
67
    if (ipa_equal(nn->ip, ip))
68
      return nn;
69
  return NULL;
70
}
71

    
72
static int
73
ospf_sk_open(struct ospf_iface *ifa)
74
{
75
  sock *sk = sk_new(ifa->pool);
76
  sk->type = SK_IP;
77
  sk->dport = OSPF_PROTO;
78
  sk->saddr = IPA_NONE;
79

    
80
  sk->tos = IP_PREC_INTERNET_CONTROL;
81
  sk->rx_hook = ospf_rx_hook;
82
  sk->tx_hook = ospf_tx_hook;
83
  sk->err_hook = ospf_err_hook;
84
  sk->iface = ifa->iface;
85
  sk->rbsize = rxbufsize(ifa);
86
  sk->tbsize = rxbufsize(ifa);
87
  sk->data = (void *) ifa;
88
  sk->flags = SKF_LADDR_RX;
89

    
90
  if (sk_open(sk) != 0)
91
    goto err;
92

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

    
99
  /*
100
   * For OSPFv2: When sending a packet, it is important to have a
101
   * proper source address. We expect that when we send one-hop
102
   * unicast packets, OS chooses a source address according to the
103
   * destination address (to be in the same prefix). We also expect
104
   * that when we send multicast packets, OS uses the source address
105
   * from sk->saddr registered to OS by sk_setup_multicast(). This
106
   * behavior is needed to implement multiple virtual ifaces (struct
107
   * ospf_iface) on one physical iface and is signalized by
108
   * CONFIG_MC_PROPER_SRC.
109
   *
110
   * If this behavior is not available (for example on BSD), we create
111
   * non-stub iface just for the primary IP address (see
112
   * ospf_iface_stubby()) and we expect OS to use primary IP address
113
   * as a source address for both unicast and multicast packets.
114
   *
115
   * FIXME: the primary IP address is currently just the
116
   * lexicographically smallest address on an interface, it should be
117
   * signalized by sysdep code which one is really the primary.
118
   */
119

    
120
  sk->saddr = ifa->addr->ip;
121
  if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP))
122
  {
123
    sk->ttl = 1;        /* Hack, this will affect just multicast packets */
124

    
125
    if (sk_setup_multicast(sk) < 0)
126
      goto err;
127

    
128
    if (sk_join_group(sk, AllSPFRouters) < 0)
129
      goto err;
130
  }
131

    
132
  ifa->sk = sk;
133
  ifa->sk_dr = 0;
134
  return 1;
135

    
136
 err:
137
  rfree(sk);
138
  return 0;
139
}
140

    
141
static inline void
142
ospf_sk_join_dr(struct ospf_iface *ifa)
143
{
144
  if (ifa->sk_dr)
145
    return;
146

    
147
  sk_join_group(ifa->sk, AllDRouters);
148
  ifa->sk_dr = 1;
149
}
150

    
151
static inline void
152
ospf_sk_leave_dr(struct ospf_iface *ifa)
153
{
154
  if (!ifa->sk_dr)
155
    return;
156

    
157
  sk_leave_group(ifa->sk, AllDRouters);
158
  ifa->sk_dr = 0;
159
}
160

    
161
static void
162
ospf_iface_down(struct ospf_iface *ifa)
163
{
164
  struct ospf_neighbor *n, *nx;
165
  struct proto_ospf *po = ifa->oa->po;
166
  struct proto *p = &po->proto;
167
  struct ospf_iface *iff;
168

    
169
  if (ifa->type != OSPF_IT_VLINK)
170
  {
171
#ifdef OSPFv2
172
    OSPF_TRACE(D_EVENTS, "Removing interface %s (%I/%d) from area %R",
173
               ifa->iface->name, ifa->addr->prefix, ifa->addr->pxlen, ifa->oa->areaid);
174
#else
175
    OSPF_TRACE(D_EVENTS, "Removing interface %s (IID %d) from area %R",
176
               ifa->iface->name, ifa->instance_id, ifa->oa->areaid);
177
#endif
178

    
179
    /* First of all kill all the related vlinks */
180
    WALK_LIST(iff, po->iface_list)
181
    {
182
      if ((iff->type == OSPF_IT_VLINK) && (iff->vifa == ifa))
183
        ospf_iface_sm(iff, ISM_DOWN);
184
    }
185
  }
186

    
187
  WALK_LIST_DELSAFE(n, nx, ifa->neigh_list)
188
  {
189
    OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip);
190
    ospf_neigh_remove(n);
191
  }
192

    
193
  if (ifa->hello_timer)
194
    tm_stop(ifa->hello_timer);
195

    
196
  if (ifa->poll_timer)
197
    tm_stop(ifa->poll_timer);
198

    
199
  if (ifa->wait_timer)
200
    tm_stop(ifa->wait_timer);
201

    
202
  if (ifa->type == OSPF_IT_VLINK)
203
  {
204
    ifa->vifa = NULL;
205
    ifa->iface = NULL;
206
    ifa->addr = NULL;
207
    ifa->sk = NULL;
208
    ifa->cost = 0;
209
    ifa->vip = IPA_NONE;
210
  }
211

    
212
  ifa->rt_pos_beg = 0;
213
  ifa->rt_pos_end = 0;
214
#ifdef OSPFv3
215
  ifa->px_pos_beg = 0;
216
  ifa->px_pos_end = 0;
217
#endif
218
}
219

    
220

    
221
void
222
ospf_iface_remove(struct ospf_iface *ifa)
223
{
224
  struct proto *p = &ifa->oa->po->proto;
225
  if (ifa->type == OSPF_IT_VLINK)
226
    OSPF_TRACE(D_EVENTS, "Removing vlink to %R via area %R", ifa->vid, ifa->voa->areaid);
227

    
228
  ospf_iface_sm(ifa, ISM_DOWN);
229
  rem_node(NODE ifa);
230
  rfree(ifa->pool);
231
}
232

    
233
void
234
ospf_iface_shutdown(struct ospf_iface *ifa)
235
{
236
  if (ifa->state > OSPF_IS_DOWN)
237
    ospf_hello_send(ifa, OHS_SHUTDOWN, NULL);
238
}
239

    
240
/**
241
 * ospf_iface_chstate - handle changes of interface state
242
 * @ifa: OSPF interface
243
 * @state: new state
244
 *
245
 * Many actions must be taken according to interface state changes. New network
246
 * LSAs must be originated, flushed, new multicast sockets to listen for messages for
247
 * %ALLDROUTERS have to be opened, etc.
248
 */
249
void
250
ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
251
{
252
  struct proto_ospf *po = ifa->oa->po;
253
  struct proto *p = &po->proto;
254
  u8 oldstate = ifa->state;
255

    
256
  if (oldstate == state)
257
    return;
258

    
259
  ifa->state = state;
260

    
261
  if (ifa->type == OSPF_IT_VLINK)
262
    OSPF_TRACE(D_EVENTS, "Changing state of virtual link %R from %s to %s",
263
               ifa->vid, ospf_is[oldstate], ospf_is[state]);
264
  else
265
    OSPF_TRACE(D_EVENTS, "Changing state of iface %s from %s to %s",
266
               ifa->iface->name, ospf_is[oldstate], ospf_is[state]);
267

    
268
  if ((ifa->type == OSPF_IT_BCAST) && ifa->sk)
269
  {
270
    if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
271
      ospf_sk_join_dr(ifa);
272
    else
273
      ospf_sk_leave_dr(ifa);
274
  }
275

    
276
  if ((oldstate == OSPF_IS_DR) && (ifa->net_lsa != NULL))
277
  {
278
    ifa->net_lsa->lsa.age = LSA_MAXAGE;
279
    if (state >= OSPF_IS_WAITING)
280
      ospf_lsupd_flush_nlsa(po, ifa->net_lsa);
281

    
282
    if (can_flush_lsa(po))
283
      flush_lsa(ifa->net_lsa, po);
284
    ifa->net_lsa = NULL;
285
  }
286

    
287
  if ((oldstate > OSPF_IS_LOOP) && (state <= OSPF_IS_LOOP))
288
    ospf_iface_down(ifa);
289

    
290
  schedule_rt_lsa(ifa->oa);
291
  // FIXME flushling of link LSA
292
}
293

    
294
/**
295
 * ospf_iface_sm - OSPF interface state machine
296
 * @ifa: OSPF interface
297
 * @event: event comming to state machine
298
 *
299
 * This fully respects 9.3 of RFC 2328 except we have slightly
300
 * different handling of %DOWN and %LOOP state. We remove intefaces
301
 * that are %DOWN. %DOWN state is used when an interface is waiting
302
 * for a lock. %LOOP state is used when an interface does not have a
303
 * link.
304
 */
305
void
306
ospf_iface_sm(struct ospf_iface *ifa, int event)
307
{
308
  DBG("SM on %s %s. Event is '%s'\n", (ifa->type == OSPF_IT_VLINK) ? "vlink" : "iface",
309
    ifa->iface ? ifa->iface->name : "(none)" , ospf_ism[event]);
310

    
311
  switch (event)
312
  {
313
  case ISM_UP:
314
    if (ifa->state <= OSPF_IS_LOOP)
315
    {
316
      /* Now, nothing should be adjacent */
317
      if ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_PTMP) || (ifa->type == OSPF_IT_VLINK))
318
      {
319
        ospf_iface_chstate(ifa, OSPF_IS_PTP);
320
      }
321
      else
322
      {
323
        if (ifa->priority == 0)
324
          ospf_iface_chstate(ifa, OSPF_IS_DROTHER);
325
        else
326
        {
327
          ospf_iface_chstate(ifa, OSPF_IS_WAITING);
328
          if (ifa->wait_timer)
329
            tm_start(ifa->wait_timer, ifa->waitint);
330
        }
331
      }
332

    
333
      if (ifa->hello_timer)
334
        tm_start(ifa->hello_timer, ifa->helloint);
335

    
336
      if (ifa->poll_timer)
337
        tm_start(ifa->poll_timer, ifa->pollint);
338

    
339
      ospf_hello_send(ifa, OHS_HELLO, NULL);
340
      schedule_link_lsa(ifa);
341
    }
342
    break;
343

    
344
  case ISM_BACKS:
345
  case ISM_WAITF:
346
    if (ifa->state == OSPF_IS_WAITING)
347
    {
348
      bdr_election(ifa);
349
    }
350
    break;
351

    
352
  case ISM_NEICH:
353
    if ((ifa->state == OSPF_IS_DROTHER) || (ifa->state == OSPF_IS_DR) ||
354
        (ifa->state == OSPF_IS_BACKUP))
355
    {
356
      bdr_election(ifa);
357
      schedule_rt_lsa(ifa->oa);
358
    }
359
    break;
360

    
361
  case ISM_LOOP:
362
    if ((ifa->state > OSPF_IS_LOOP) && ifa->check_link)
363
      ospf_iface_chstate(ifa, OSPF_IS_LOOP);
364
    break;
365

    
366
  case ISM_UNLOOP:
367
    /* Immediate go UP */
368
    if (ifa->state == OSPF_IS_LOOP)
369
      ospf_iface_sm(ifa, ISM_UP);
370
    break;
371

    
372
  case ISM_DOWN:
373
    ospf_iface_chstate(ifa, OSPF_IS_DOWN);
374
    break;
375

    
376
  default:
377
    bug("OSPF_I_SM - Unknown event?");
378
    break;
379
  }
380

    
381
}
382

    
383
static u8
384
ospf_iface_classify_int(struct iface *ifa, struct ifa *addr)
385
{
386
  if (ipa_nonzero(addr->opposite))
387
    return (ifa->flags & IF_MULTICAST) ? OSPF_IT_PTP :  OSPF_IT_PTMP;
388

    
389
  if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) ==
390
      (IF_MULTIACCESS | IF_MULTICAST))
391
    return OSPF_IT_BCAST;
392

    
393
  if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) == IF_MULTIACCESS)
394
    return OSPF_IT_NBMA;
395

    
396
  return OSPF_IT_PTP;
397
}
398

    
399
static inline u8
400
ospf_iface_classify(u8 type, struct ifa *addr)
401
{
402
  return (type != OSPF_IT_UNDEF) ? type : ospf_iface_classify_int(addr->iface, addr);
403
}
404

    
405

    
406
struct ospf_iface *
407
ospf_iface_find(struct proto_ospf *p, struct iface *what)
408
{
409
  struct ospf_iface *i;
410

    
411
  WALK_LIST(i, p->iface_list) if ((i->iface == what) && (i->type != OSPF_IT_VLINK))
412
    return i;
413
  return NULL;
414
}
415

    
416
static void
417
ospf_iface_add(struct object_lock *lock)
418
{
419
  struct ospf_iface *ifa = lock->data;
420
  struct proto_ospf *po = ifa->oa->po;
421
  struct proto *p = &po->proto;
422

    
423
  /* Open socket if interface is not stub */
424
  if (! ifa->stub && ! ospf_sk_open(ifa))
425
  {
426
    log(L_ERR "%s: Socket open failed on interface %s, declaring as stub", p->name, ifa->iface->name);
427
    ifa->ioprob = OSPF_I_SK;
428
    ifa->stub = 1;
429
  }
430

    
431
  if (! ifa->stub)
432
  {
433
    ifa->hello_timer = tm_new_set(ifa->pool, hello_timer_hook, ifa, 0, ifa->helloint);
434

    
435
    if (ifa->type == OSPF_IT_NBMA)
436
      ifa->poll_timer = tm_new_set(ifa->pool, poll_timer_hook, ifa, 0, ifa->pollint);
437

    
438
    if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
439
      ifa->wait_timer = tm_new_set(ifa->pool, wait_timer_hook, ifa, 0, 0);
440
  }
441

    
442
  /* Do iface UP, unless there is no link and we use link detection */
443
  ospf_iface_sm(ifa, (ifa->check_link && !(ifa->iface->flags & IF_LINK_UP)) ? ISM_LOOP : ISM_UP);
444
}
445

    
446
static inline void
447
add_nbma_node(struct ospf_iface *ifa, struct nbma_node *src, int found)
448
{
449
  struct nbma_node *n = mb_alloc(ifa->pool, sizeof(struct nbma_node));
450
  add_tail(&ifa->nbma_list, NODE n);
451
  n->ip = src->ip;
452
  n->eligible = src->eligible;
453
  n->found = found;
454
}
455

    
456
static int
457
ospf_iface_stubby(struct ospf_iface_patt *ip, struct ifa *addr)
458
{
459
  if (! addr)
460
    return 0;
461

    
462
  /* a host/loopback address */
463
  if (addr->flags & IA_HOST)
464
    return 1;
465

    
466
  /*
467
   * We cannot properly support multiple OSPF ifaces on real iface
468
   * with multiple prefixes, therefore we force OSPF ifaces with
469
   * non-primary IP prefixes to be stub.
470
   */
471
#if defined(OSPFv2) && !defined(CONFIG_MC_PROPER_SRC)
472
  if (! (addr->flags & IA_PRIMARY))
473
    return 1;
474
#endif
475

    
476
  return ip->stub;
477
}
478

    
479
void
480
ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *ip)
481
{
482
  struct proto *p = &oa->po->proto;
483
  struct iface *iface = addr ? addr->iface : NULL;
484
  struct pool *pool;
485

    
486
  struct ospf_iface *ifa;
487
  struct nbma_node *nb;
488
  struct object_lock *lock;
489

    
490
  if (ip->type == OSPF_IT_VLINK)
491
    OSPF_TRACE(D_EVENTS, "Adding vlink to %R via area %R", ip->vid, ip->voa);
492
  else
493
  {
494
#ifdef OSPFv2
495
    OSPF_TRACE(D_EVENTS, "Adding interface %s (%I/%d) to area %R",
496
               iface->name, addr->prefix, addr->pxlen, oa->areaid);
497
#else
498
    OSPF_TRACE(D_EVENTS, "Adding interface %s (IID %d) to area %R",
499
               iface->name, ip->instance_id, oa->areaid);
500
#endif
501
  }
502

    
503
  pool = rp_new(p->pool, "OSPF Interface");
504
  ifa = mb_allocz(pool, sizeof(struct ospf_iface));
505
  ifa->iface = iface;
506
  ifa->addr = addr;
507
  ifa->oa = oa;
508
  ifa->cf = ip;
509
  ifa->pool = pool;
510

    
511
  ifa->cost = ip->cost;
512
  ifa->rxmtint = ip->rxmtint;
513
  ifa->inftransdelay = ip->inftransdelay;
514
  ifa->priority = ip->priority;
515
  ifa->helloint = ip->helloint;
516
  ifa->pollint = ip->pollint;
517
  ifa->strictnbma = ip->strictnbma;
518
  ifa->waitint = ip->waitint;
519
  ifa->deadint = ip->deadint;
520
  ifa->stub = ospf_iface_stubby(ip, addr);
521
  ifa->ioprob = OSPF_I_OK;
522
  ifa->rxbuf = ip->rxbuf;
523
  ifa->check_link = ip->check_link;
524
  ifa->ecmp_weight = ip->ecmp_weight;
525

    
526
#ifdef OSPFv2
527
  ifa->autype = ip->autype;
528
  ifa->passwords = ip->passwords;
529
#endif
530

    
531
#ifdef OSPFv3
532
  ifa->instance_id = ip->instance_id;
533
#endif
534

    
535
  ifa->type = ospf_iface_classify(ip->type, addr);
536

    
537
  /* Check validity of interface type */
538
  int old_type = ifa->type;
539

    
540
#ifdef OSPFv2
541
  if ((ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_PEER))
542
    ifa->type = OSPF_IT_PTP;
543

    
544
  if ((ifa->type == OSPF_IT_NBMA) && (addr->flags & IA_PEER))
545
    ifa->type = OSPF_IT_PTMP;
546
#endif
547

    
548
  if ((ifa->type == OSPF_IT_BCAST) && !(iface->flags & IF_MULTICAST))
549
    ifa->type = OSPF_IT_NBMA;
550

    
551
  if ((ifa->type == OSPF_IT_PTP) && !(iface->flags & IF_MULTICAST))
552
    ifa->type = OSPF_IT_PTMP;
553

    
554
  if (ifa->type != old_type)
555
    log(L_WARN "%s: Cannot use interface %s as %s, forcing %s",
556
        p->name, iface->name, ospf_it[old_type], ospf_it[ifa->type]);
557

    
558

    
559
  init_list(&ifa->neigh_list);
560
  init_list(&ifa->nbma_list);
561

    
562
  WALK_LIST(nb, ip->nbma_list)
563
    if (ipa_in_net(nb->ip, addr->prefix, addr->pxlen))
564
      add_nbma_node(ifa, nb, 0);
565

    
566
  ifa->state = OSPF_IS_DOWN;
567
  add_tail(&oa->po->iface_list, NODE ifa);
568

    
569
  if (ifa->type == OSPF_IT_VLINK)
570
  {
571
    ifa->voa = ospf_find_area(oa->po, ip->voa);
572
    ifa->vid = ip->vid;
573
    return;                        /* Don't lock, don't add sockets */
574
  }
575

    
576
  /*
577
   * In some cases we allow more ospf_ifaces on one physical iface.
578
   * In OSPFv2, if they use different IP address prefix.
579
   * In OSPFv3, if they use different instance_id.
580
   * Therefore, we store such info to lock->addr field.
581
   */
582

    
583
  lock = olock_new(pool);
584
#ifdef OSPFv2
585
  lock->addr = ifa->addr->prefix;
586
#else /* OSPFv3 */
587
  lock->addr = _MI(0,0,0,ifa->instance_id);
588
#endif
589
  lock->type = OBJLOCK_IP;
590
  lock->port = OSPF_PROTO;
591
  lock->iface = iface;
592
  lock->data = ifa;
593
  lock->hook = ospf_iface_add;
594

    
595
  olock_acquire(lock);
596
}
597

    
598
static void
599
ospf_iface_change_timer(timer *tm, unsigned val)
600
{
601
  if (!tm)
602
    return;
603

    
604
  tm->recurrent = val;
605

    
606
  if (tm->expires)
607
    tm_start(tm, val);
608
}
609

    
610
int
611
ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
612
{
613
  struct proto *p = &ifa->oa->po->proto;
614
  struct nbma_node *nb, *nbx;
615
  char *ifname = (ifa->type != OSPF_IT_VLINK) ? ifa->iface->name : "vlink";
616

    
617
  /* Type could be changed in ospf_iface_new(),
618
     but if config values are same then also results are same */
619
  int old_type = ospf_iface_classify(ifa->cf->type, ifa->addr);
620
  int new_type = ospf_iface_classify(new->type, ifa->addr);
621
  if (old_type != new_type)
622
    return 0;
623

    
624
  int new_stub = ospf_iface_stubby(new, ifa->addr);
625
  if (ifa->stub != new_stub)
626
    return 0;
627

    
628
  ifa->cf = new;
629
  ifa->marked = 0;
630

    
631

    
632
  /* HELLO TIMER */
633
  if (ifa->helloint != new->helloint)
634
  {
635
    OSPF_TRACE(D_EVENTS, "Changing hello interval on interface %s from %d to %d",
636
               ifname, ifa->helloint, new->helloint);
637

    
638
    ifa->helloint = new->helloint;
639
    ospf_iface_change_timer(ifa->hello_timer, ifa->helloint);
640
  }
641

    
642
  /* RXMT TIMER */
643
  if (ifa->rxmtint != new->rxmtint)
644
  {
645
    OSPF_TRACE(D_EVENTS, "Changing retransmit interval on interface %s from %d to %d",
646
               ifname, ifa->rxmtint, new->rxmtint);
647

    
648
    ifa->rxmtint = new->rxmtint;
649
  }
650

    
651
  /* POLL TIMER */
652
  if (ifa->pollint != new->pollint)
653
  {
654
    OSPF_TRACE(D_EVENTS, "Changing poll interval on interface %s from %d to %d",
655
               ifname, ifa->pollint, new->pollint);
656

    
657
    ifa->pollint = new->pollint;
658
    ospf_iface_change_timer(ifa->poll_timer, ifa->pollint);
659
  }
660

    
661
  /* WAIT TIMER */
662
  if (ifa->waitint != new->waitint)
663
  {
664
    OSPF_TRACE(D_EVENTS, "Changing wait interval on interface %s from %d to %d",
665
               ifname, ifa->waitint, new->waitint);
666

    
667
    ifa->waitint = new->waitint;
668
    if (ifa->wait_timer && ifa->wait_timer->expires)
669
      tm_start(ifa->wait_timer, ifa->waitint);
670
  }
671

    
672
  /* DEAD TIMER */
673
  if (ifa->deadint != new->deadint)
674
  {
675
    OSPF_TRACE(D_EVENTS, "Changing dead interval on interface %s from %d to %d",
676
               ifname, ifa->deadint, new->deadint);
677
    ifa->deadint = new->deadint;
678
  }
679

    
680
  /* INFTRANS */
681
  if (ifa->inftransdelay != new->inftransdelay)
682
  {
683
    OSPF_TRACE(D_EVENTS, "Changing transmit delay on interface %s from %d to %d",
684
                     ifname, ifa->inftransdelay, new->inftransdelay);
685
    ifa->inftransdelay = new->inftransdelay;
686
  }
687

    
688
#ifdef OSPFv2        
689
  /* AUTHENTICATION */
690
  if (ifa->autype != new->autype)
691
  {
692
    OSPF_TRACE(D_EVENTS, "Changing authentication type on interface %s", ifname);
693
    ifa->autype = new->autype;
694
  }
695

    
696
  /* Update passwords */
697
  ifa->passwords = new->passwords;
698
#endif
699

    
700
  /* Remaining options are just for proper interfaces */
701
  if (ifa->type == OSPF_IT_VLINK)
702
    return 1;
703

    
704

    
705
  /* COST */
706
  if (ifa->cost != new->cost)
707
  {
708
    OSPF_TRACE(D_EVENTS, "Changing cost on interface %s from %d to %d",
709
               ifname, ifa->cost, new->cost);
710

    
711
    ifa->cost = new->cost;
712
  }
713

    
714
  /* PRIORITY */
715
  if (ifa->priority != new->priority)
716
  {
717
    OSPF_TRACE(D_EVENTS, "Changing priority on interface %s from %d to %d",
718
               ifname, ifa->priority, new->priority);
719
    ifa->priority = new->priority;
720
  }
721

    
722
  /* STRICT NBMA */
723
  if (ifa->strictnbma != new->strictnbma)
724
  {
725
    OSPF_TRACE(D_EVENTS, "Changing NBMA strictness on interface %s", ifname);
726
    ifa->strictnbma = new->strictnbma;
727
  }
728

    
729
  /* NBMA LIST - remove or update old */
730
  WALK_LIST_DELSAFE(nb, nbx, ifa->nbma_list)
731
  {
732
    struct nbma_node *nb2 = find_nbma_node_in(&new->nbma_list, nb->ip);
733
    if (nb2)
734
    {
735
      if (nb->eligible != nb2->eligible)
736
      {
737
        OSPF_TRACE(D_EVENTS, "Changing eligibility of neighbor %I on interface %s",
738
                   nb->ip, ifname);
739
        nb->eligible = nb2->eligible;
740
      }
741
    }
742
    else
743
    {
744
      OSPF_TRACE(D_EVENTS, "Removing NBMA neighbor %I on interface %s",
745
                       nb->ip, ifname);
746
      rem_node(NODE nb);
747
      mb_free(nb);
748
    }
749
  }
750

    
751
  /* NBMA LIST - add new */
752
  WALK_LIST(nb, new->nbma_list)
753
  {
754
    if (!ipa_in_net(nb->ip, ifa->addr->prefix, ifa->addr->pxlen))
755
      continue;
756

    
757
    if (! find_nbma_node(ifa, nb->ip))
758
    {
759
      OSPF_TRACE(D_EVENTS, "Adding NBMA neighbor %I on interface %s",
760
                 nb->ip, ifname);
761
      add_nbma_node(ifa, nb, !!find_neigh_by_ip(ifa, nb->ip));
762
    }
763
  }
764

    
765
  /* RX BUFF */
766
  if (ifa->rxbuf != new->rxbuf)
767
  {
768
    OSPF_TRACE(D_EVENTS, "Changing rxbuf interface %s from %d to %d",
769
               ifname, ifa->rxbuf, new->rxbuf);
770
    ifa->rxbuf = new->rxbuf;
771
    ospf_iface_change_mtu(ifa->oa->po, ifa);
772
  }
773

    
774
  /* LINK */
775
  if (ifa->check_link != new->check_link)
776
  {
777
    OSPF_TRACE(D_EVENTS, "%s link check on interface %s",
778
               new->check_link ? "Enabling" : "Disabling", ifname);
779
    ifa->check_link = new->check_link;
780

    
781
    if (!(ifa->iface->flags & IF_LINK_UP))
782
      ospf_iface_sm(ifa, ifa->check_link ? ISM_LOOP : ISM_UNLOOP);
783
  }
784

    
785
  /* ECMP weight */
786
  if (ifa->ecmp_weight != new->ecmp_weight)
787
  {
788
    OSPF_TRACE(D_EVENTS, "Changing ECMP weight of interface %s from %d to %d",
789
               ifname, (int)ifa->ecmp_weight + 1, (int)new->ecmp_weight + 1);
790
    ifa->ecmp_weight = new->ecmp_weight;
791
  }
792

    
793
  /* instance_id is not updated - it is part of key */
794

    
795
  return 1;
796
}
797

    
798

    
799
#ifdef OSPFv2
800

    
801
static inline struct ospf_iface_patt *
802
ospf_iface_patt_find(struct ospf_area_config *ac, struct ifa *a)
803
{
804
  return (struct ospf_iface_patt *) iface_patt_find(&ac->patt_list, a->iface, a);
805
}
806

    
807
void
808
ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
809
{
810
  struct proto_ospf *po = (struct proto_ospf *) p;
811

    
812
  if (a->flags & IA_SECONDARY)
813
    return;
814

    
815
  if (a->scope <= SCOPE_LINK)
816
    return;
817

    
818
  /* In OSPFv2, we create OSPF iface for each address. */
819
  if (flags & IF_CHANGE_UP)
820
  {
821
    int done = 0;
822
    struct ospf_area *oa;
823
    WALK_LIST(oa, po->area_list)
824
    {
825
      struct ospf_iface_patt *ip;
826
      if (ip = ospf_iface_patt_find(oa->ac, a))
827
      {
828
        if (!done)
829
          ospf_iface_new(oa, a, ip);
830
        done++;
831
      }
832
    }
833

    
834
    if (done > 1)
835
      log(L_WARN "%s: Interface %s (IP %I) matches for multiple areas", p->name,  a->iface->name, a->ip);
836
  }
837

    
838
  if (flags & IF_CHANGE_DOWN)
839
  {
840
    struct ospf_iface *ifa, *ifx;
841
    WALK_LIST_DELSAFE(ifa, ifx, po->iface_list)
842
    {
843
      if ((ifa->type != OSPF_IT_VLINK) && (ifa->addr == a))
844
        ospf_iface_remove(ifa);
845
      /* See a note in ospf_iface_notify() */
846
    }
847
  }
848
}
849

    
850
static struct ospf_iface *
851
ospf_iface_find_by_key(struct ospf_area *oa, struct ifa *a)
852
{
853
  struct ospf_iface *ifa;
854
  WALK_LIST(ifa, oa->po->iface_list)
855
    if ((ifa->addr == a) && (ifa->oa == oa) && (ifa->type != OSPF_IT_VLINK))
856
      return ifa;
857

    
858
  return NULL;
859
}
860

    
861
void
862
ospf_ifaces_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
863
{
864
  struct ospf_iface_patt *ip;
865
  struct iface *iface;
866
  struct ifa *a;
867

    
868
  WALK_LIST(iface, iface_list)
869
    WALK_LIST(a, iface->addrs)
870
    {
871
      if (a->flags & IA_SECONDARY)
872
        continue;
873

    
874
      if (a->scope <= SCOPE_LINK)
875
        continue;
876

    
877
      if (ip = ospf_iface_patt_find(oa->ac, a))
878
      {
879
        /* Main inner loop */
880
        struct ospf_iface *ifa = ospf_iface_find_by_key(oa, a);
881
        if (ifa)
882
        {
883
          if (ospf_iface_reconfigure(ifa, ip))
884
            continue;
885

    
886
          /* Hard restart */
887
          ospf_iface_shutdown(ifa);
888
          ospf_iface_remove(ifa);
889
        }
890
        
891
        ospf_iface_new(oa, a, ip);
892
      }
893
    }
894
}
895

    
896

    
897
#else /* OSPFv3 */
898

    
899
struct ospf_iface_patt *
900
ospf_iface_patt_find(struct ospf_area_config *ac, struct iface *iface, int iid)
901
{
902
  struct ospf_iface_patt *pt, *res = NULL;
903

    
904
  WALK_LIST(pt, ac->patt_list)
905
    if ((pt->instance_id >= iid) && (iface_patt_match(&pt->i, iface, NULL)) &&
906
        (!res || (pt->instance_id < res->instance_id)))
907
      res = pt;
908

    
909
  return res;
910
}
911

    
912
void
913
ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
914
{
915
  struct proto_ospf *po = (struct proto_ospf *) p;
916

    
917
  if (a->flags & IA_SECONDARY)
918
    return;
919

    
920
  if (a->scope < SCOPE_LINK)
921
    return;
922

    
923
  /* In OSPFv3, we create OSPF iface for link-local address,
924
     other addresses are used for link-LSA. */
925
  if (a->scope == SCOPE_LINK)
926
  {
927
    if (flags & IF_CHANGE_UP)
928
    {
929
      int done0 = 0;
930
      struct ospf_area *oa;
931

    
932
      WALK_LIST(oa, po->area_list)
933
      {
934
        int iid = 0;
935

    
936
        struct ospf_iface_patt *ip;
937
        while (ip = ospf_iface_patt_find(oa->ac, a->iface, iid))
938
        {
939
          ospf_iface_new(oa, a, ip);
940
          if (ip->instance_id == 0)
941
            done0++;
942
          iid = ip->instance_id + 1;
943
        }
944
      }
945

    
946
      if (done0 > 1)
947
        log(L_WARN "%s: Interface %s matches for multiple areas",
948
            p->name,  a->iface->name);
949
    }
950

    
951
    if (flags & IF_CHANGE_DOWN)
952
    {
953
      struct ospf_iface *ifa, *ifx;
954
      WALK_LIST_DELSAFE(ifa, ifx, po->iface_list)
955
      {
956
        if ((ifa->type != OSPF_IT_VLINK) && (ifa->addr == a))
957
          ospf_iface_remove(ifa);
958
        /* See a note in ospf_iface_notify() */
959
      }
960
    }
961
  }
962
  else
963
  {
964
    struct ospf_iface *ifa;
965
    WALK_LIST(ifa, po->iface_list)
966
    {
967
      if (ifa->iface == a->iface)
968
      {
969
        schedule_rt_lsa(ifa->oa);
970
        /* Event 5 from RFC5340 4.4.3. */
971
        schedule_link_lsa(ifa);
972
        return;
973
      }
974
    }
975
  }
976
}
977

    
978
static struct ospf_iface *
979
ospf_iface_find_by_key(struct ospf_area *oa, struct ifa *a, int iid)
980
{
981
  struct ospf_iface *ifa;
982
  WALK_LIST(ifa, oa->po->iface_list)
983
    if ((ifa->addr == a) && (ifa->oa == oa) && (ifa->instance_id == iid) && (ifa->type != OSPF_IT_VLINK))
984
      return ifa;
985

    
986
  return NULL;
987
}
988

    
989
void
990
ospf_ifaces_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
991
{
992
  struct ospf_iface_patt *ip;
993
  struct iface *iface;
994
  struct ifa *a;
995

    
996
  WALK_LIST(iface, iface_list)
997
    WALK_LIST(a, iface->addrs)
998
    {
999
      if (a->flags & IA_SECONDARY)
1000
        continue;
1001

    
1002
      if (a->scope != SCOPE_LINK)
1003
        continue;
1004

    
1005
      int iid = 0;
1006
      while (ip = ospf_iface_patt_find(nac, iface, iid))
1007
      {
1008
        iid = ip->instance_id + 1;
1009

    
1010
        /* Main inner loop */
1011
        struct ospf_iface *ifa = ospf_iface_find_by_key(oa, a, ip->instance_id);
1012
        if (ifa)
1013
        {
1014
          if (ospf_iface_reconfigure(ifa, ip))
1015
            continue;
1016

    
1017
          /* Hard restart */
1018
          ospf_iface_shutdown(ifa);
1019
          ospf_iface_remove(ifa);
1020
        }
1021

    
1022
        ospf_iface_new(oa, a, ip);
1023
      }
1024
    }
1025
}
1026

    
1027
#endif
1028

    
1029
static void
1030
ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa)
1031
{
1032
  struct proto *p = &po->proto;
1033
  struct ospf_packet *op;
1034
  struct ospf_neighbor *n;
1035
  OSPF_TRACE(D_EVENTS, "Changing MTU on interface %s", ifa->iface->name);
1036

    
1037
  if (ifa->sk)
1038
  {
1039
    ifa->sk->rbsize = rxbufsize(ifa);
1040
    ifa->sk->tbsize = rxbufsize(ifa);
1041
    sk_reallocate(ifa->sk);
1042
  }
1043

    
1044
  WALK_LIST(n, ifa->neigh_list)
1045
  {
1046
    op = (struct ospf_packet *) n->ldbdes;
1047
    n->ldbdes = mb_allocz(n->pool, ifa->iface->mtu);
1048

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

    
1052
    mb_free(op);
1053
  }
1054
}
1055

    
1056
static void
1057
ospf_iface_notify(struct proto_ospf *po, unsigned flags, struct ospf_iface *ifa)
1058
{
1059
  if (flags & IF_CHANGE_DOWN)
1060
  {
1061
    ospf_iface_remove(ifa);
1062
    return;
1063
  }
1064

    
1065
  if (flags & IF_CHANGE_LINK)
1066
    ospf_iface_sm(ifa, (ifa->iface->flags & IF_LINK_UP) ? ISM_UNLOOP : ISM_LOOP);
1067

    
1068
  if (flags & IF_CHANGE_MTU)
1069
    ospf_iface_change_mtu(po, ifa);
1070
}
1071

    
1072
void
1073
ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface)
1074
{
1075
  struct proto_ospf *po = (struct proto_ospf *) p;
1076

    
1077
  /*
1078
  if (iface->flags & IF_IGNORE)
1079
    return;
1080
  */
1081

    
1082
  /* Going up means that there are no such ifaces yet */
1083
  if (flags & IF_CHANGE_UP)
1084
    return;
1085

    
1086
  struct ospf_iface *ifa, *ifx;
1087
  WALK_LIST_DELSAFE(ifa, ifx, po->iface_list)
1088
    if ((ifa->type != OSPF_IT_VLINK) && (ifa->iface == iface))
1089
      ospf_iface_notify(po, flags, ifa);
1090

    
1091
  /* We use here that even shutting down iface also shuts down
1092
     the vlinks, but vlinks are not freed and stays in the
1093
     iface_list even when down */
1094
}
1095

    
1096
void
1097
ospf_iface_info(struct ospf_iface *ifa)
1098
{
1099
  char *strict = "";
1100

    
1101
  if (ifa->strictnbma &&
1102
      ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP)))
1103
    strict = "(strict)";
1104

    
1105
  if (ifa->type == OSPF_IT_VLINK)
1106
  {
1107
    cli_msg(-1015, "Virtual link to %R:", ifa->vid);
1108
    cli_msg(-1015, "\tPeer IP: %I", ifa->vip);
1109
    cli_msg(-1015, "\tTransit area: %R (%u)", ifa->voa->areaid,
1110
            ifa->voa->areaid);
1111
    cli_msg(-1015, "\tInterface: \"%s\"",
1112
            (ifa->iface ? ifa->iface->name : "(none)"));
1113
  }
1114
  else
1115
  {
1116
#ifdef OSPFv2
1117
    if (ifa->addr->flags & IA_PEER)
1118
      cli_msg(-1015, "Interface %s (peer %I)", ifa->iface->name, ifa->addr->opposite);
1119
    else
1120
      cli_msg(-1015, "Interface %s (%I/%d)", ifa->iface->name, ifa->addr->prefix, ifa->addr->pxlen);
1121
#else /* OSPFv3 */
1122
    cli_msg(-1015, "Interface %s (IID %d)", ifa->iface->name, ifa->instance_id);
1123
#endif
1124
    cli_msg(-1015, "\tType: %s %s", ospf_it[ifa->type], strict);
1125
    cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid);
1126
  }
1127
  cli_msg(-1015, "\tState: %s %s", ospf_is[ifa->state],
1128
          ifa->stub ? "(stub)" : "");
1129
  cli_msg(-1015, "\tPriority: %u", ifa->priority);
1130
  cli_msg(-1015, "\tCost: %u", ifa->cost);
1131
  if (ifa->oa->po->ecmp)
1132
    cli_msg(-1015, "\tECMP weight: %d", ((int) ifa->ecmp_weight) + 1);
1133
  cli_msg(-1015, "\tHello timer: %u", ifa->helloint);
1134

    
1135
  if (ifa->type == OSPF_IT_NBMA)
1136
  {
1137
    cli_msg(-1015, "\tPoll timer: %u", ifa->pollint);
1138
  }
1139
  cli_msg(-1015, "\tWait timer: %u", ifa->waitint);
1140
  cli_msg(-1015, "\tDead timer: %u", ifa->deadint);
1141
  cli_msg(-1015, "\tRetransmit timer: %u", ifa->rxmtint);
1142
  if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
1143
  {
1144
    cli_msg(-1015, "\tDesigned router (ID): %R", ifa->drid);
1145
    cli_msg(-1015, "\tDesigned router (IP): %I", ifa->drip);
1146
    cli_msg(-1015, "\tBackup designed router (ID): %R", ifa->bdrid);
1147
    cli_msg(-1015, "\tBackup designed router (IP): %I", ifa->bdrip);
1148
  }
1149
}
1150