Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / iface.c @ 04632fd7

History | View | Annotate | Download (33.4 KB)

1
/*
2
 *        BIRD -- OSPF
3
 *
4
 *        (c) 1999--2005 Ondrej Filip <feela@network.cz>
5
 *        (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
6
 *        (c) 2009--2014 CZ.NIC z.s.p.o.
7
 *
8
 *        Can be freely distributed and used under the terms of the GNU GPL.
9
 */
10

    
11
#include "ospf.h"
12

    
13

    
14
const char *ospf_is_names[] = {
15
  "Down", "Loopback", "Waiting", "PtP", "DROther", "Backup", "DR"
16
};
17

    
18
const char *ospf_ism_names[] = {
19
  "InterfaceUp", "WaitTimer", "BackupSeen", "NeighborChange",
20
  "LoopInd", "UnloopInd", "InterfaceDown"
21
};
22

    
23
const char *ospf_it[] = { "broadcast", "nbma", "ptp", "ptmp", "virtual link" };
24

    
25

    
26
static void
27
poll_timer_hook(timer * timer)
28
{
29
  ospf_send_hello(timer->data, OHS_POLL, NULL);
30
}
31

    
32
static void
33
hello_timer_hook(timer * timer)
34
{
35
  ospf_send_hello(timer->data, OHS_HELLO, NULL);
36
}
37

    
38
static void
39
wait_timer_hook(timer * timer)
40
{
41
  struct ospf_iface *ifa = (struct ospf_iface *) timer->data;
42
  struct ospf_proto *p = ifa->oa->po;
43

    
44
  OSPF_TRACE(D_EVENTS, "Wait timer fired on %s", ifa->ifname);
45
  ospf_iface_sm(ifa, ISM_WAITF);
46
}
47

    
48
static inline uint
49
ifa_tx_length(struct ospf_iface *ifa)
50
{
51
  return ifa->cf->tx_length ?: ifa->iface->mtu;
52
}
53

    
54
static inline uint
55
ifa_bufsize(struct ospf_iface *ifa)
56
{
57
  uint bsize = ifa->cf->rx_buffer ?: ifa->iface->mtu;
58
  return MAX(bsize, ifa->tx_length);
59
}
60

    
61
static inline uint
62
ifa_flood_queue_size(struct ospf_iface *ifa)
63
{
64
  return ifa->tx_length / 24;
65
}
66

    
67
int
68
ospf_iface_assure_bufsize(struct ospf_iface *ifa, uint plen)
69
{
70
  struct ospf_proto *p = ifa->oa->po;
71

    
72
  plen += ospf_is_v2(p) ? IP4_HEADER_LENGTH : IP6_HEADER_LENGTH;
73

    
74
  /* This is relevant just for OSPFv2 */
75
  if (ifa->autype == OSPF_AUTH_CRYPT)
76
    plen += OSPF_AUTH_CRYPT_SIZE;
77

    
78
  if (plen <= ifa->sk->tbsize)
79
    return 0;
80

    
81
  if (ifa->cf->rx_buffer || (plen > 0xffff))
82
    return -1;
83

    
84
  plen = BIRD_ALIGN(plen, 1024);
85
  plen = MIN(plen, 0xffff);
86
  sk_set_tbsize(ifa->sk, plen);
87
  return 1;
88
}
89

    
90

    
91
struct nbma_node *
92
find_nbma_node_(list *nnl, ip_addr ip)
93
{
94
  struct nbma_node *nn;
95

    
96
  WALK_LIST(nn, *nnl)
97
    if (ipa_equal(nn->ip, ip))
98
      return nn;
99

    
100
  return NULL;
101
}
102

    
103

    
104
static int
105
ospf_sk_open(struct ospf_iface *ifa)
106
{
107
  struct ospf_proto *p = ifa->oa->po;
108

    
109
  sock *sk = sk_new(ifa->pool);
110
  sk->type = SK_IP;
111
  sk->dport = OSPF_PROTO;
112
  sk->saddr = ifa->addr->ip;
113
  sk->iface = ifa->iface;
114
  sk->af = ospf_is_v2(p) ? AF_INET : AF_INET6;
115

    
116
  sk->tos = ifa->cf->tx_tos;
117
  sk->priority = ifa->cf->tx_priority;
118
  sk->rx_hook = ospf_rx_hook;
119
  // sk->tx_hook = ospf_tx_hook;
120
  sk->err_hook = ospf_err_hook;
121
  sk->rbsize = sk->tbsize = ifa_bufsize(ifa);
122
  sk->data = (void *) ifa;
123
  sk->flags = SKF_LADDR_RX | (ifa->check_ttl ? SKF_TTL_RX : 0);
124
  sk->ttl = ifa->cf->ttl_security ? 255 : 1;
125

    
126
  if (sk_open(sk) < 0)
127
    goto err;
128

    
129
  /* 12 is an offset of the checksum in an OSPFv3 packet */
130
  if (ospf_is_v3(p))
131
    if (sk_set_ipv6_checksum(sk, 12) < 0)
132
      goto err;
133

    
134
  if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP))
135
  {
136
    if (ifa->cf->real_bcast)
137
    {
138
      ifa->all_routers = ifa->addr->brd;
139
      ifa->des_routers = IPA_NONE;
140

    
141
      if (sk_setup_broadcast(sk) < 0)
142
        goto err;
143
    }
144
    else
145
    {
146
      ifa->all_routers = ospf_is_v2(p) ? IP4_OSPF_ALL_ROUTERS : IP6_OSPF_ALL_ROUTERS;
147
      ifa->des_routers = ospf_is_v2(p) ? IP4_OSPF_DES_ROUTERS : IP6_OSPF_DES_ROUTERS;
148

    
149
      if (sk_setup_multicast(sk) < 0)
150
        goto err;
151

    
152
      if (sk_join_group(sk, ifa->all_routers) < 0)
153
        goto err;
154
    }
155
  }
156

    
157
  ifa->sk = sk;
158
  ifa->sk_dr = 0;
159
  return 1;
160

    
161
 err:
162
  sk_log_error(sk, p->p.name);
163
  rfree(sk);
164
  return 0;
165
}
166

    
167
static inline void
168
ospf_sk_join_dr(struct ospf_iface *ifa)
169
{
170
  if (ifa->sk_dr)
171
    return;
172

    
173
  if (sk_join_group(ifa->sk, ifa->des_routers) < 0)
174
    sk_log_error(ifa->sk, ifa->oa->po->p.name);
175

    
176
  ifa->sk_dr = 1;
177
}
178

    
179
static inline void
180
ospf_sk_leave_dr(struct ospf_iface *ifa)
181
{
182
  if (!ifa->sk_dr)
183
    return;
184

    
185
  if (sk_leave_group(ifa->sk, ifa->des_routers) < 0)
186
    sk_log_error(ifa->sk, ifa->oa->po->p.name);
187

    
188
  ifa->sk_dr = 0;
189
}
190

    
191
void
192
ospf_open_vlink_sk(struct ospf_proto *p)
193
{
194
  sock *sk = sk_new(p->p.pool);
195
  sk->type = SK_IP;
196
  sk->dport = OSPF_PROTO;
197
  sk->af = ospf_is_v2(p) ? AF_INET : AF_INET6;
198

    
199
  /* FIXME: configurable tos/priority ? */
200
  sk->tos = IP_PREC_INTERNET_CONTROL;
201
  sk->priority = sk_priority_control;
202
  sk->err_hook = ospf_verr_hook;
203

    
204
  sk->rbsize = 0;
205
  sk->tbsize = ospf_is_v2(p) ? IP4_MIN_MTU : IP6_MIN_MTU;
206
  sk->data = (void *) p;
207
  sk->flags = 0;
208

    
209
  if (sk_open(sk) < 0)
210
    goto err;
211

    
212
  /* 12 is an offset of the checksum in an OSPFv3 packet */
213
  if (ospf_is_v3(p))
214
    if (sk_set_ipv6_checksum(sk, 12) < 0)
215
      goto err;
216

    
217
  p->vlink_sk = sk;
218
  return;
219

    
220
 err:
221
  sk_log_error(sk, p->p.name);
222
  log(L_ERR "%s: Cannot open virtual link socket", p->p.name);
223
  rfree(sk);
224
}
225

    
226
static void
227
ospf_iface_down(struct ospf_iface *ifa)
228
{
229
  struct ospf_proto *p = ifa->oa->po;
230
  struct ospf_neighbor *n, *nx;
231
  struct ospf_iface *iff;
232

    
233
  if (ifa->type != OSPF_IT_VLINK)
234
  {
235
    if (ospf_is_v3(ifa->oa->po))
236
      OSPF_TRACE(D_EVENTS, "Removing interface %s (IID %d) from area %R",
237
                 ifa->ifname, ifa->instance_id, ifa->oa->areaid);
238
    else if (ifa->addr->flags & IA_PEER)
239
      OSPF_TRACE(D_EVENTS, "Removing interface %s (peer %I) from area %R",
240
                 ifa->ifname, ifa->addr->opposite, ifa->oa->areaid);
241
    else
242
      OSPF_TRACE(D_EVENTS, "Removing interface %s (%N) from area %R",
243
                 ifa->ifname, &ifa->addr->prefix, ifa->oa->areaid);
244

    
245
    /* First of all kill all the related vlinks */
246
    WALK_LIST(iff, p->iface_list)
247
    {
248
      if ((iff->type == OSPF_IT_VLINK) && (iff->vifa == ifa))
249
        ospf_iface_sm(iff, ISM_DOWN);
250
    }
251
  }
252

    
253
  WALK_LIST_DELSAFE(n, nx, ifa->neigh_list)
254
    ospf_neigh_sm(n, INM_KILLNBR);
255

    
256
  if (ifa->hello_timer)
257
    tm_stop(ifa->hello_timer);
258

    
259
  if (ifa->poll_timer)
260
    tm_stop(ifa->poll_timer);
261

    
262
  if (ifa->wait_timer)
263
    tm_stop(ifa->wait_timer);
264

    
265
  ospf_flush2_lsa(p, &ifa->link_lsa);
266
  ospf_flush2_lsa(p, &ifa->net_lsa);
267
  ospf_flush2_lsa(p, &ifa->pxn_lsa);
268

    
269
  if (ifa->type == OSPF_IT_VLINK)
270
  {
271
    ifa->vifa = NULL;
272
    ifa->addr = NULL;
273
    ifa->cost = 0;
274
    ifa->vip = IPA_NONE;
275
  }
276

    
277
  ifa->rt_pos_beg = 0;
278
  ifa->rt_pos_end = 0;
279
  ifa->px_pos_beg = 0;
280
  ifa->px_pos_end = 0;
281
}
282

    
283

    
284
void
285
ospf_iface_remove(struct ospf_iface *ifa)
286
{
287
  struct ospf_proto *p = ifa->oa->po;
288
  int i;
289

    
290
  if (ifa->type == OSPF_IT_VLINK)
291
    OSPF_TRACE(D_EVENTS, "Removing vlink to %R via area %R", ifa->vid, ifa->voa->areaid);
292

    
293
  /* Release LSAs from flood queue */
294
  if (!ifa->stub)
295
    for (i = 0; i < ifa->flood_queue_used; i++)
296
      ifa->flood_queue[i]->ret_count--;
297

    
298
  ospf_iface_sm(ifa, ISM_DOWN);
299
  rem_node(NODE ifa);
300
  rfree(ifa->pool);
301
}
302

    
303
void
304
ospf_iface_shutdown(struct ospf_iface *ifa)
305
{
306
  if (ifa->state > OSPF_IS_DOWN)
307
    ospf_send_hello(ifa, OHS_SHUTDOWN, NULL);
308
}
309

    
310
/**
311
 * ospf_iface_chstate - handle changes of interface state
312
 * @ifa: OSPF interface
313
 * @state: new state
314
 *
315
 * Many actions must be taken according to interface state changes. New network
316
 * LSAs must be originated, flushed, new multicast sockets to listen for messages for
317
 * %ALLDROUTERS have to be opened, etc.
318
 */
319
void
320
ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
321
{
322
  struct ospf_proto *p = ifa->oa->po;
323
  u8 oldstate = ifa->state;
324

    
325
  if (state == oldstate)
326
    return;
327

    
328
  OSPF_TRACE(D_EVENTS, "Interface %s changed state from %s to %s",
329
             ifa->ifname, ospf_is_names[oldstate], ospf_is_names[state]);
330

    
331
  ifa->state = state;
332

    
333
  if ((ifa->type == OSPF_IT_BCAST) && ipa_nonzero(ifa->des_routers) && ifa->sk)
334
  {
335
    if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
336
      ospf_sk_join_dr(ifa);
337
    else
338
      ospf_sk_leave_dr(ifa);
339
  }
340

    
341
  if ((oldstate > OSPF_IS_LOOP) && (state <= OSPF_IS_LOOP))
342
    ospf_iface_down(ifa);
343

    
344
  /* RFC 2328 12.4 Event 2 - iface state change */
345
  ospf_notify_rt_lsa(ifa->oa);
346

    
347
  /* RFC 5340 4.4.3 Event 1 - iface state change */
348
  ospf_notify_link_lsa(ifa);
349

    
350
  /* RFC 2328 12.4 Event 3 - iface enters/leaves DR state */
351
  ospf_notify_net_lsa(ifa);
352
}
353

    
354
/**
355
 * ospf_iface_sm - OSPF interface state machine
356
 * @ifa: OSPF interface
357
 * @event: event comming to state machine
358
 *
359
 * This fully respects 9.3 of RFC 2328 except we have slightly
360
 * different handling of %DOWN and %LOOP state. We remove intefaces
361
 * that are %DOWN. %DOWN state is used when an interface is waiting
362
 * for a lock. %LOOP state is used when an interface does not have a
363
 * link.
364
 */
365
void
366
ospf_iface_sm(struct ospf_iface *ifa, int event)
367
{
368
  DBG("SM on %s. Event is '%s'\n", ifa->ifname, ospf_ism_names[event]);
369

    
370
  switch (event)
371
  {
372
  case ISM_UP:
373
    if (ifa->state <= OSPF_IS_LOOP)
374
    {
375
      /* Now, nothing should be adjacent */
376
      if ((ifa->type == OSPF_IT_PTP) ||
377
          (ifa->type == OSPF_IT_PTMP) ||
378
          (ifa->type == OSPF_IT_VLINK))
379
      {
380
        ospf_iface_chstate(ifa, OSPF_IS_PTP);
381
      }
382
      else
383
      {
384
        if (ifa->priority == 0)
385
          ospf_iface_chstate(ifa, OSPF_IS_DROTHER);
386
        else
387
        {
388
          ospf_iface_chstate(ifa, OSPF_IS_WAITING);
389
          if (ifa->wait_timer)
390
            tm_start(ifa->wait_timer, ifa->waitint);
391
        }
392
      }
393

    
394
      if (ifa->hello_timer)
395
        tm_start(ifa->hello_timer, ifa->helloint);
396

    
397
      if (ifa->poll_timer)
398
        tm_start(ifa->poll_timer, ifa->pollint);
399

    
400
      ospf_send_hello(ifa, OHS_HELLO, NULL);
401
    }
402
    break;
403

    
404
  case ISM_BACKS:
405
  case ISM_WAITF:
406
    if (ifa->state == OSPF_IS_WAITING)
407
      ospf_dr_election(ifa);
408
    break;
409

    
410
  case ISM_NEICH:
411
    if (ifa->state >= OSPF_IS_DROTHER)
412
      ospf_dr_election(ifa);
413
    break;
414

    
415
  case ISM_LOOP:
416
    if ((ifa->state > OSPF_IS_LOOP) && ifa->check_link)
417
      ospf_iface_chstate(ifa, OSPF_IS_LOOP);
418
    break;
419

    
420
  case ISM_UNLOOP:
421
    /* Immediate go UP */
422
    if (ifa->state == OSPF_IS_LOOP)
423
      ospf_iface_sm(ifa, ISM_UP);
424
    break;
425

    
426
  case ISM_DOWN:
427
    ospf_iface_chstate(ifa, OSPF_IS_DOWN);
428
    break;
429

    
430
  default:
431
    bug("OSPF_I_SM - Unknown event?");
432
    break;
433
  }
434

    
435
}
436

    
437
static u8
438
ospf_iface_classify_(struct iface *ifa, struct ifa *addr)
439
{
440
  if (ipa_nonzero(addr->opposite))
441
    return (ifa->flags & IF_MULTICAST) ? OSPF_IT_PTP :  OSPF_IT_PTMP;
442

    
443
  if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) ==
444
      (IF_MULTIACCESS | IF_MULTICAST))
445
    return OSPF_IT_BCAST;
446

    
447
  if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) == IF_MULTIACCESS)
448
    return OSPF_IT_NBMA;
449

    
450
  return OSPF_IT_PTP;
451
}
452

    
453
static inline u8
454
ospf_iface_classify(u8 type, struct ifa *addr)
455
{
456
  return (type != OSPF_IT_UNDEF) ? type : ospf_iface_classify_(addr->iface, addr);
457
}
458

    
459

    
460
struct ospf_iface *
461
ospf_iface_find(struct ospf_proto *p, struct iface *what)
462
{
463
  struct ospf_iface *ifa;
464

    
465
  WALK_LIST(ifa, p->iface_list)
466
    if ((ifa->iface == what) && (ifa->type != OSPF_IT_VLINK))
467
      return ifa;
468

    
469
  return NULL;
470
}
471

    
472
static void
473
ospf_iface_add(struct object_lock *lock)
474
{
475
  struct ospf_iface *ifa = lock->data;
476
  struct ospf_proto *p = ifa->oa->po;
477

    
478
  /* Open socket if interface is not stub */
479
  if (! ifa->stub && ! ospf_sk_open(ifa))
480
  {
481
    log(L_ERR "%s: Cannot open socket for %s, declaring as stub", p->p.name, ifa->ifname);
482
    ifa->ioprob = OSPF_I_SK;
483
    ifa->stub = 1;
484
  }
485

    
486
  if (! ifa->stub)
487
  {
488
    ifa->hello_timer = tm_new_set(ifa->pool, hello_timer_hook, ifa, 0, ifa->helloint);
489

    
490
    if (ifa->type == OSPF_IT_NBMA)
491
      ifa->poll_timer = tm_new_set(ifa->pool, poll_timer_hook, ifa, 0, ifa->pollint);
492

    
493
    if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
494
      ifa->wait_timer = tm_new_set(ifa->pool, wait_timer_hook, ifa, 0, 0);
495

    
496
    ifa->flood_queue_size = ifa_flood_queue_size(ifa);
497
    ifa->flood_queue = mb_allocz(ifa->pool, ifa->flood_queue_size * sizeof(void *));
498
  }
499

    
500
  /* Do iface UP, unless there is no link (then wait in LOOP state) */
501
  if (!ifa->check_link || (ifa->iface->flags & IF_LINK_UP))
502
    ospf_iface_sm(ifa, ISM_UP);
503
  else
504
    ospf_iface_chstate(ifa, OSPF_IS_LOOP);
505
}
506

    
507
static inline void
508
add_nbma_node(struct ospf_iface *ifa, struct nbma_node *src, int found)
509
{
510
  struct nbma_node *n = mb_alloc(ifa->pool, sizeof(struct nbma_node));
511
  add_tail(&ifa->nbma_list, NODE n);
512
  n->ip = src->ip;
513
  n->eligible = src->eligible;
514
  n->found = found;
515
}
516

    
517
static int
518
ospf_iface_stubby(struct ospf_iface_patt *ip, struct ifa *addr)
519
{
520
  /* a host address */
521
  if (addr->flags & IA_HOST)
522
    return 1;
523

    
524
  /* a loopback iface */
525
  if (addr->iface->flags & IF_LOOPBACK)
526
    return 1;
527

    
528
  return ip->stub;
529
}
530

    
531
void
532
ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *ip)
533
{
534
  struct ospf_proto *p = oa->po;
535
  struct iface *iface = addr->iface;
536
  struct ospf_iface *ifa;
537
  struct pool *pool;
538

    
539
  if (ospf_is_v3(p))
540
    OSPF_TRACE(D_EVENTS, "Adding interface %s (IID %d) to area %R",
541
               iface->name, ip->instance_id, oa->areaid);
542
  else if (addr->flags & IA_PEER)
543
    OSPF_TRACE(D_EVENTS, "Adding interface %s (peer %I) to area %R",
544
               iface->name, addr->opposite, oa->areaid);
545
  else
546
    OSPF_TRACE(D_EVENTS, "Adding interface %s (%N) to area %R",
547
               iface->name, &addr->prefix, oa->areaid);
548

    
549
  pool = rp_new(p->p.pool, "OSPF Interface");
550
  ifa = mb_allocz(pool, sizeof(struct ospf_iface));
551
  ifa->iface = iface;
552
  ifa->addr = addr;
553
  ifa->oa = oa;
554
  ifa->cf = ip;
555
  ifa->pool = pool;
556

    
557
  ifa->iface_id = iface->index;
558
  ifa->ifname = iface->name;
559

    
560
  ifa->cost = ip->cost;
561
  ifa->rxmtint = ip->rxmtint;
562
  ifa->inftransdelay = ip->inftransdelay;
563
  ifa->priority = ip->priority;
564
  ifa->helloint = ip->helloint;
565
  ifa->pollint = ip->pollint;
566
  ifa->strictnbma = ip->strictnbma;
567
  ifa->waitint = ip->waitint;
568
  ifa->deadint = ip->deadint;
569
  ifa->stub = ospf_iface_stubby(ip, addr);
570
  ifa->ioprob = OSPF_I_OK;
571
  ifa->tx_length = ifa_tx_length(ifa);
572
  ifa->check_link = ip->check_link;
573
  ifa->ecmp_weight = ip->ecmp_weight;
574
  ifa->check_ttl = (ip->ttl_security == 1);
575
  ifa->bfd = ip->bfd;
576
  ifa->autype = ip->autype;
577
  ifa->passwords = ip->passwords;
578
  ifa->instance_id = ip->instance_id;
579

    
580
  ifa->ptp_netmask = !(addr->flags & IA_PEER);
581
  if (ip->ptp_netmask < 2)
582
    ifa->ptp_netmask = ip->ptp_netmask;
583

    
584
  ifa->drip = ifa->bdrip = ospf_is_v2(p) ? IPA_NONE4 : IPA_NONE6;
585

    
586
  ifa->type = ospf_iface_classify(ip->type, addr);
587

    
588
  /* Check validity of interface type */
589
  int old_type = ifa->type;
590
  u32 if_multi_flag = ip->real_bcast ? IF_BROADCAST : IF_MULTICAST;
591

    
592
  if (ospf_is_v2(p) && (ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_PEER))
593
    ifa->type = OSPF_IT_PTP;
594

    
595
  if (ospf_is_v2(p) && (ifa->type == OSPF_IT_NBMA) && (addr->flags & IA_PEER))
596
    ifa->type = OSPF_IT_PTMP;
597

    
598
  if ((ifa->type == OSPF_IT_BCAST) && !(iface->flags & if_multi_flag))
599
    ifa->type = OSPF_IT_NBMA;
600

    
601
  if ((ifa->type == OSPF_IT_PTP) && !(iface->flags & if_multi_flag))
602
    ifa->type = OSPF_IT_PTMP;
603

    
604
  if (ifa->type != old_type)
605
    log(L_WARN "%s: Cannot use interface %s as %s, forcing %s",
606
        p->p.name, iface->name, ospf_it[old_type], ospf_it[ifa->type]);
607

    
608

    
609
  if ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_PTMP))
610
    ifa->link_lsa_suppression = ip->link_lsa_suppression;
611

    
612
  ifa->state = OSPF_IS_DOWN;
613
  init_list(&ifa->neigh_list);
614
  init_list(&ifa->nbma_list);
615

    
616
  struct nbma_node *nb;
617
  WALK_LIST(nb, ip->nbma_list)
618
  {
619
    /* In OSPFv3, addr is link-local while configured neighbors could
620
       have global IP (although RFC 5340 C.5 says link-local addresses
621
       should be used). Because OSPFv3 iface is not subnet-specific,
622
       there is no need for ipa_in_net() check */
623

    
624
    if (ospf_is_v2(p) && !ipa_in_netX(nb->ip, &addr->prefix))
625
      continue;
626

    
627
    if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip))
628
      log(L_WARN "%s: Configured neighbor address (%I) should be link-local",
629
          p->p.name, nb->ip);
630

    
631
    add_nbma_node(ifa, nb, 0);
632
  }
633

    
634
  add_tail(&oa->po->iface_list, NODE ifa);
635

    
636
  struct object_lock *lock = olock_new(pool);
637
  lock->addr = ospf_is_v2(p) ? ipa_from_ip4(net4_prefix(&ifa->addr->prefix)) : IPA_NONE;
638
  lock->type = OBJLOCK_IP;
639
  lock->port = OSPF_PROTO;
640
  lock->inst = ifa->instance_id;
641
  lock->iface = iface;
642
  lock->data = ifa;
643
  lock->hook = ospf_iface_add;
644

    
645
  olock_acquire(lock);
646
}
647

    
648
void
649
ospf_iface_new_vlink(struct ospf_proto *p, struct ospf_iface_patt *ip)
650
{
651
  struct ospf_iface *ifa;
652
  struct pool *pool;
653

    
654
  if (!p->vlink_sk)
655
    return;
656

    
657
  OSPF_TRACE(D_EVENTS, "Adding vlink to %R via area %R", ip->vid, ip->voa);
658

    
659
  /* Vlink ifname is stored just after the ospf_iface structure */
660

    
661
  pool = rp_new(p->p.pool, "OSPF Vlink");
662
  ifa = mb_allocz(pool, sizeof(struct ospf_iface) + 16);
663
  ifa->oa = p->backbone;
664
  ifa->cf = ip;
665
  ifa->pool = pool;
666

    
667
  /* Assign iface ID, for vlinks, this is ugly hack */
668
  u32 vlink_id = p->last_vlink_id++;
669
  ifa->iface_id = vlink_id + OSPF_VLINK_ID_OFFSET;
670
  ifa->ifname = (void *) (ifa + 1);
671
  bsprintf(ifa->ifname, "vlink%d", vlink_id);
672

    
673
  ifa->voa = ospf_find_area(p, ip->voa);
674
  ifa->vid = ip->vid;
675
  ifa->sk = p->vlink_sk;
676

    
677
  ifa->helloint = ip->helloint;
678
  ifa->rxmtint = ip->rxmtint;
679
  ifa->waitint = ip->waitint;
680
  ifa->deadint = ip->deadint;
681
  ifa->inftransdelay = ip->inftransdelay;
682
  ifa->tx_length = ospf_is_v2(p) ? IP4_MIN_MTU : IP6_MIN_MTU;
683
  ifa->autype = ip->autype;
684
  ifa->passwords = ip->passwords;
685
  ifa->instance_id = ip->instance_id;
686

    
687
  ifa->type = OSPF_IT_VLINK;
688

    
689
  ifa->state = OSPF_IS_DOWN;
690
  init_list(&ifa->neigh_list);
691
  init_list(&ifa->nbma_list);
692

    
693
  add_tail(&p->iface_list, NODE ifa);
694

    
695
  ifa->hello_timer = tm_new_set(ifa->pool, hello_timer_hook, ifa, 0, ifa->helloint);
696

    
697
  ifa->flood_queue_size = ifa_flood_queue_size(ifa);
698
  ifa->flood_queue = mb_allocz(ifa->pool, ifa->flood_queue_size * sizeof(void *));
699
}
700

    
701
static void
702
ospf_iface_change_timer(timer *tm, uint val)
703
{
704
  if (!tm)
705
    return;
706

    
707
  tm->recurrent = val;
708

    
709
  if (tm->expires)
710
    tm_start(tm, val);
711
}
712

    
713
static inline void
714
ospf_iface_update_flood_queue_size(struct ospf_iface *ifa)
715
{
716
  uint old_size = ifa->flood_queue_size;
717
  uint new_size = ifa_flood_queue_size(ifa);
718

    
719
  if (new_size <= old_size)
720
    return;
721

    
722
  ifa->flood_queue_size = new_size;
723
  ifa->flood_queue = mb_realloc(ifa->flood_queue, new_size * sizeof(void *));
724
  bzero(ifa->flood_queue + old_size, (new_size - old_size) * sizeof(void *));
725
}
726

    
727
int
728
ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
729
{
730
  struct ospf_proto *p = ifa->oa->po;
731
  struct ospf_iface_patt *old = ifa->cf;
732
  char *ifname = ifa->ifname;
733

    
734
  /* Type could be changed in ospf_iface_new(),
735
     but if config values are same then also results are same */
736
  int old_type = ospf_iface_classify(old->type, ifa->addr);
737
  int new_type = ospf_iface_classify(new->type, ifa->addr);
738
  if (old_type != new_type)
739
    return 0;
740

    
741
  int new_stub = ospf_iface_stubby(new, ifa->addr);
742
  if (ifa->stub != new_stub)
743
    return 0;
744

    
745
  /* Change of these options would require to reset the iface socket */
746
  if ((new->real_bcast != old->real_bcast) ||
747
      (new->tx_tos != old->tx_tos) ||
748
      (new->tx_priority != old->tx_priority) ||
749
      (new->ttl_security != old->ttl_security))
750
    return 0;
751

    
752
  ifa->cf = new;
753
  ifa->marked = 0;
754

    
755

    
756
  /* HELLO TIMER */
757
  if (ifa->helloint != new->helloint)
758
  {
759
    OSPF_TRACE(D_EVENTS, "Changing hello interval of %s from %d to %d",
760
               ifname, ifa->helloint, new->helloint);
761

    
762
    ifa->helloint = new->helloint;
763
    ospf_iface_change_timer(ifa->hello_timer, ifa->helloint);
764
  }
765

    
766
  /* RXMT TIMER */
767
  if (ifa->rxmtint != new->rxmtint)
768
  {
769
    OSPF_TRACE(D_EVENTS, "Changing retransmit interval of %s from %d to %d",
770
               ifname, ifa->rxmtint, new->rxmtint);
771

    
772
    ifa->rxmtint = new->rxmtint;
773
    /* FIXME: Update neighbors' timers */
774
  }
775

    
776
  /* POLL TIMER */
777
  if (ifa->pollint != new->pollint)
778
  {
779
    OSPF_TRACE(D_EVENTS, "Changing poll interval of %s from %d to %d",
780
               ifname, ifa->pollint, new->pollint);
781

    
782
    ifa->pollint = new->pollint;
783
    ospf_iface_change_timer(ifa->poll_timer, ifa->pollint);
784
  }
785

    
786
  /* WAIT TIMER */
787
  if (ifa->waitint != new->waitint)
788
  {
789
    OSPF_TRACE(D_EVENTS, "Changing wait interval of %s from %d to %d",
790
               ifname, ifa->waitint, new->waitint);
791

    
792
    ifa->waitint = new->waitint;
793
    if (ifa->wait_timer && ifa->wait_timer->expires)
794
      tm_start(ifa->wait_timer, ifa->waitint);
795
  }
796

    
797
  /* DEAD TIMER */
798
  if (ifa->deadint != new->deadint)
799
  {
800
    OSPF_TRACE(D_EVENTS, "Changing dead interval of %s from %d to %d",
801
               ifname, ifa->deadint, new->deadint);
802
    ifa->deadint = new->deadint;
803
  }
804

    
805
  /* INFTRANS */
806
  if (ifa->inftransdelay != new->inftransdelay)
807
  {
808
    OSPF_TRACE(D_EVENTS, "Changing transmit delay of %s from %d to %d",
809
                     ifname, ifa->inftransdelay, new->inftransdelay);
810
    ifa->inftransdelay = new->inftransdelay;
811
  }
812

    
813
  /* AUTHENTICATION */
814
  if (ifa->autype != new->autype)
815
  {
816
    OSPF_TRACE(D_EVENTS, "Changing authentication type of %s", ifname);
817
    ifa->autype = new->autype;
818
  }
819

    
820
  /* Update passwords */
821
  ifa->passwords = new->passwords;
822

    
823
  /* Remaining options are just for proper interfaces */
824
  if (ifa->type == OSPF_IT_VLINK)
825
    return 1;
826

    
827

    
828
  /* COST */
829
  if (ifa->cost != new->cost)
830
  {
831
    OSPF_TRACE(D_EVENTS, "Changing cost of %s from %d to %d",
832
               ifname, ifa->cost, new->cost);
833

    
834
    ifa->cost = new->cost;
835
  }
836

    
837
  /* PRIORITY */
838
  if (ifa->priority != new->priority)
839
  {
840
    OSPF_TRACE(D_EVENTS, "Changing priority of %s from %d to %d",
841
               ifname, ifa->priority, new->priority);
842

    
843
    ifa->priority = new->priority;
844
    ospf_notify_link_lsa(ifa);
845
  }
846

    
847
  /* STRICT NBMA */
848
  if (ifa->strictnbma != new->strictnbma)
849
  {
850
    OSPF_TRACE(D_EVENTS, "Changing NBMA strictness of %s from %d to %d",
851
               ifname, ifa->strictnbma, new->strictnbma);
852
    ifa->strictnbma = new->strictnbma;
853
  }
854

    
855
  struct nbma_node *nb, *nbx;
856

    
857
  /* NBMA LIST - remove or update old */
858
  WALK_LIST_DELSAFE(nb, nbx, ifa->nbma_list)
859
  {
860
    struct nbma_node *nb2 = find_nbma_node_(&new->nbma_list, nb->ip);
861
    if (nb2)
862
    {
863
      if (nb->eligible != nb2->eligible)
864
      {
865
        OSPF_TRACE(D_EVENTS, "Changing eligibility of NBMA neighbor %I on %s",
866
                   nb->ip, ifname);
867
        nb->eligible = nb2->eligible;
868
      }
869
    }
870
    else
871
    {
872
      OSPF_TRACE(D_EVENTS, "Removing NBMA neighbor %I on %s",
873
                       nb->ip, ifname);
874
      rem_node(NODE nb);
875
      mb_free(nb);
876
    }
877
  }
878

    
879
  /* NBMA LIST - add new */
880
  WALK_LIST(nb, new->nbma_list)
881
  {
882
    /* See related note in ospf_iface_new() */
883
    if (ospf_is_v2(p) && !ipa_in_netX(nb->ip, &ifa->addr->prefix))
884
      continue;
885

    
886
    if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip))
887
      log(L_WARN "%s: Configured neighbor address (%I) should be link-local",
888
          p->p.name, nb->ip);
889

    
890
    if (! find_nbma_node(ifa, nb->ip))
891
    {
892
      OSPF_TRACE(D_EVENTS, "Adding NBMA neighbor %I on %s",
893
                 nb->ip, ifname);
894
      add_nbma_node(ifa, nb, !!find_neigh_by_ip(ifa, nb->ip));
895
    }
896
  }
897

    
898
  int update_buffers = 0;
899

    
900
  /* TX LENGTH */
901
  if (old->tx_length != new->tx_length)
902
  {
903
    OSPF_TRACE(D_EVENTS, "Changing TX length of %s from %d to %d",
904
               ifname, old->tx_length, new->tx_length);
905

    
906
    /* ifa cannot be vlink */
907
    ifa->tx_length = ifa_tx_length(ifa);
908
    update_buffers = 1;
909

    
910
    if (!ifa->stub)
911
      ospf_iface_update_flood_queue_size(ifa);
912
  }
913

    
914
  /* RX BUFFER */
915
  if (old->rx_buffer != new->rx_buffer)
916
  {
917
    OSPF_TRACE(D_EVENTS, "Changing buffer size of %s from %d to %d",
918
               ifname, old->rx_buffer, new->rx_buffer);
919

    
920
    /* ifa cannot be vlink */
921
    update_buffers = 1;
922
  }
923

    
924
  /* Buffer size depends on both tx_length and rx_buffer options */
925
  if (update_buffers && ifa->sk)
926
  {
927
    uint bsize = ifa_bufsize(ifa);
928
    sk_set_rbsize(ifa->sk, bsize);
929
    sk_set_tbsize(ifa->sk, bsize);
930
  }
931

    
932
  /* LINK */
933
  if (ifa->check_link != new->check_link)
934
  {
935
    OSPF_TRACE(D_EVENTS, "%s link check for %s",
936
               new->check_link ? "Enabling" : "Disabling", ifname);
937
    ifa->check_link = new->check_link;
938

    
939
    /* ifa cannot be vlink */
940
    if (!(ifa->iface->flags & IF_LINK_UP))
941
      ospf_iface_sm(ifa, ifa->check_link ? ISM_LOOP : ISM_UNLOOP);
942
  }
943

    
944
  /* ECMP weight */
945
  if (ifa->ecmp_weight != new->ecmp_weight)
946
  {
947
    OSPF_TRACE(D_EVENTS, "Changing ECMP weight of %s from %d to %d",
948
               ifname, (int)ifa->ecmp_weight + 1, (int)new->ecmp_weight + 1);
949
    ifa->ecmp_weight = new->ecmp_weight;
950
  }
951

    
952
  /* Link LSA suppression */
953
  if (((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_PTMP)) &&
954
      (ifa->link_lsa_suppression != new->link_lsa_suppression))
955
  {
956
    OSPF_TRACE(D_EVENTS, "Changing link LSA suppression of %s from %d to %d",
957
               ifname, ifa->link_lsa_suppression, new->link_lsa_suppression);
958

    
959
    ifa->link_lsa_suppression = new->link_lsa_suppression;
960
    ospf_notify_link_lsa(ifa);
961
  }
962

    
963
  /* BFD */
964
  if (ifa->bfd != new->bfd)
965
  {
966
    OSPF_TRACE(D_EVENTS, "%s BFD for %s",
967
               new->bfd ? "Enabling" : "Disabling", ifname);
968
    ifa->bfd = new->bfd;
969

    
970
    struct ospf_neighbor *n;
971
    WALK_LIST(n, ifa->neigh_list)
972
      ospf_neigh_update_bfd(n, ifa->bfd);
973
  }
974

    
975

    
976
  /* instance_id is not updated - it is part of key */
977

    
978
  return 1;
979
}
980

    
981

    
982
/*
983
 * State for matching iface pattterns walk
984
 *
985
 * This is significantly different in OSPFv2 and OSPFv3.
986
 * In OSPFv2, OSPF ifaces are created for each IP prefix (struct ifa)
987
 * In OSPFv3, OSPF ifaces are created based on real iface (struct iface)
988
 * We support instance_id for both OSPFv2 (RFC 6549) and OSPFv3.
989
 *
990
 * We process one ifa/iface and match it for all configured instance IDs. We
991
 * maintain bitfields to track whether given instance ID was already matched.
992
 * We have two bitfields, one global (active) and one per area (ignore), to
993
 * detect misconfigured cases where one iface with one instance ID matches in
994
 * multiple areas.
995
 */
996

    
997
struct ospf_mip_walk {
998
  u32 active[8];                /* Bitfield of active instance IDs */
999
  u32 ignore[8];                /* Bitfield of instance IDs matched in current area */
1000
  struct ospf_area *oa;                /* Current area */
1001
  struct ospf_iface_patt *ip;        /* Current iface pattern */
1002
  struct iface *iface;                /* Specified iface (input) */
1003
  struct ifa *a;                /* Specified ifa (input) */
1004
  int warn;                        /* Whether iface matched in multiple areas */
1005
};
1006

    
1007
static int
1008
ospf_walk_matching_iface_patts(struct ospf_proto *p, struct ospf_mip_walk *s)
1009
{
1010
  int id;
1011

    
1012
  if (s->ip)
1013
    goto step;
1014

    
1015
  WALK_LIST(s->oa, p->area_list)
1016
  {
1017
    if (s->oa->marked)
1018
      continue;
1019

    
1020
    WALK_LIST(s->ip, s->oa->ac->patt_list)
1021
    {
1022
      id = s->ip->instance_id;
1023
      if (BIT32_TEST(s->ignore, id))
1024
        continue;
1025

    
1026
      if (iface_patt_match(&s->ip->i, s->iface, s->a))
1027
      {
1028
        /* Now we matched ifa/iface/instance_id for the first time in current area */
1029
        BIT32_SET(s->ignore, id);
1030

    
1031
        /* If we already found it in previous areas, ignore it and add warning */
1032
        if (BIT32_TEST(s->active, id))
1033
          { s->warn = 1; continue; }
1034

    
1035
        BIT32_SET(s->active, id);
1036
        return 1;
1037
      step:
1038
        ;
1039
      }
1040
    }
1041
    BIT32_ZERO(s->ignore, 256);
1042
  }
1043

    
1044
  if (s->warn)
1045
    log(L_WARN "%s: Interface %s matches for multiple areas", p->p.name, s->iface->name);
1046

    
1047
  return 0;
1048
}
1049

    
1050

    
1051
static struct ospf_iface *
1052
ospf_iface_find_by_key(struct ospf_proto *p, struct ifa *a, int instance_id)
1053
{
1054
  struct ospf_iface *ifa;
1055

    
1056
  WALK_LIST(ifa, p->iface_list)
1057
    if ((ifa->addr == a) && (ifa->instance_id == instance_id) &&
1058
        (ifa->type != OSPF_IT_VLINK))
1059
      return ifa;
1060

    
1061
  return NULL;
1062
}
1063

    
1064

    
1065
void
1066
ospf_ifa_notify2(struct proto *P, uint flags, struct ifa *a)
1067
{
1068
  struct ospf_proto *p = (struct ospf_proto *) P;
1069

    
1070
  if (a->prefix.type != NET_IP4)
1071
    return;
1072

    
1073
  if (a->flags & IA_SECONDARY)
1074
    return;
1075

    
1076
  if (a->scope <= SCOPE_LINK)
1077
    return;
1078

    
1079
  /* In OSPFv2, we create OSPF iface for each address. */
1080
  if (flags & IF_CHANGE_UP)
1081
  {
1082
    struct ospf_mip_walk s = { .iface = a->iface, .a = a };
1083
    while (ospf_walk_matching_iface_patts(p, &s))
1084
      ospf_iface_new(s.oa, a, s.ip);
1085
  }
1086

    
1087
  if (flags & IF_CHANGE_DOWN)
1088
  {
1089
    struct ospf_iface *ifa, *ifx;
1090
    WALK_LIST_DELSAFE(ifa, ifx, p->iface_list)
1091
      if ((ifa->type != OSPF_IT_VLINK) && (ifa->addr == a))
1092
        ospf_iface_remove(ifa);
1093
    /* See a note in ospf_iface_notify() */
1094
  }
1095
}
1096

    
1097
void
1098
ospf_ifa_notify3(struct proto *P, uint flags, struct ifa *a)
1099
{
1100
  struct ospf_proto *p = (struct ospf_proto *) P;
1101

    
1102
  if (a->prefix.type != NET_IP6)
1103
    return;
1104

    
1105
  if (a->flags & IA_SECONDARY)
1106
    return;
1107

    
1108
  if (a->scope < SCOPE_LINK)
1109
    return;
1110

    
1111
  /* In OSPFv3, we create OSPF iface for link-local address,
1112
     other addresses are used for link-LSA. */
1113
  if (a->scope == SCOPE_LINK)
1114
  {
1115
    if (flags & IF_CHANGE_UP)
1116
    {
1117
      struct ospf_mip_walk s = { .iface = a->iface };
1118
      while (ospf_walk_matching_iface_patts(p, &s))
1119
        ospf_iface_new(s.oa, a, s.ip);
1120
    }
1121

    
1122
    if (flags & IF_CHANGE_DOWN)
1123
    {
1124
      struct ospf_iface *ifa, *ifx;
1125
      WALK_LIST_DELSAFE(ifa, ifx, p->iface_list)
1126
        if ((ifa->addr == a) && (ifa->type != OSPF_IT_VLINK))
1127
          ospf_iface_remove(ifa);
1128
    }
1129
  }
1130
  else
1131
  {
1132
    struct ospf_iface *ifa;
1133
    WALK_LIST(ifa, p->iface_list)
1134
      if (ifa->iface == a->iface)
1135
      {
1136
        /* RFC 5340 4.4.3 Event 5 - prefix added/deleted */
1137
        ospf_notify_link_lsa(ifa);
1138
        ospf_notify_rt_lsa(ifa->oa);
1139
      }
1140
  }
1141
}
1142

    
1143

    
1144
static void
1145
ospf_reconfigure_ifaces2(struct ospf_proto *p)
1146
{
1147
  struct iface *iface;
1148
  struct ifa *a;
1149

    
1150
  WALK_LIST(iface, iface_list)
1151
  {
1152
    if (! (iface->flags & IF_UP))
1153
      continue;
1154

    
1155
    WALK_LIST(a, iface->addrs)
1156
    {
1157
      if (a->prefix.type != NET_IP4)
1158
        continue;
1159

    
1160
      if (a->flags & IA_SECONDARY)
1161
        continue;
1162

    
1163
      if (a->scope <= SCOPE_LINK)
1164
        continue;
1165

    
1166
      struct ospf_mip_walk s = { .iface = iface, .a = a };
1167
      while (ospf_walk_matching_iface_patts(p, &s))
1168
      {
1169
        /* Main inner loop */
1170
        struct ospf_iface *ifa = ospf_iface_find_by_key(p, a, s.ip->instance_id);
1171
        if (ifa)
1172
        {
1173
          if ((ifa->oa == s.oa) && (ifa->marked < 2) &&
1174
              ospf_iface_reconfigure(ifa, s.ip))
1175
            continue;
1176

    
1177
          /* Hard restart */
1178
          log(L_INFO "%s: Restarting interface %s (%N) in area %R",
1179
              p->p.name, ifa->ifname, &a->prefix, s.oa->areaid);
1180
          ospf_iface_shutdown(ifa);
1181
          ospf_iface_remove(ifa);
1182
        }
1183

    
1184
        ospf_iface_new(s.oa, a, s.ip);
1185
      }
1186
    }
1187
  }
1188
}
1189

    
1190
static void
1191
ospf_reconfigure_ifaces3(struct ospf_proto *p)
1192
{
1193
  struct iface *iface;
1194
  struct ifa *a;
1195

    
1196
  WALK_LIST(iface, iface_list)
1197
  {
1198
    if (! (iface->flags & IF_UP))
1199
      continue;
1200

    
1201
    WALK_LIST(a, iface->addrs)
1202
    {
1203
      if (a->prefix.type != NET_IP6)
1204
        continue;
1205

    
1206
      if (a->flags & IA_SECONDARY)
1207
        continue;
1208

    
1209
      if (a->scope != SCOPE_LINK)
1210
        continue;
1211

    
1212
      struct ospf_mip_walk s = { .iface = iface };
1213
      while (ospf_walk_matching_iface_patts(p, &s))
1214
      {
1215
        /* Main inner loop */
1216
        struct ospf_iface *ifa = ospf_iface_find_by_key(p, a, s.ip->instance_id);
1217
        if (ifa)
1218
        {
1219
          if ((ifa->oa == s.oa) && (ifa->marked < 2) &&
1220
              ospf_iface_reconfigure(ifa, s.ip))
1221
            continue;
1222

    
1223
          /* Hard restart */
1224
          log(L_INFO "%s: Restarting interface %s (IID %d) in area %R",
1225
              p->p.name, ifa->ifname, ifa->instance_id, s.oa->areaid);
1226
          ospf_iface_shutdown(ifa);
1227
          ospf_iface_remove(ifa);
1228
        }
1229

    
1230
        ospf_iface_new(s.oa, a, s.ip);
1231
      }
1232
    }
1233
  }
1234
}
1235

    
1236
void
1237
ospf_reconfigure_ifaces(struct ospf_proto *p)
1238
{
1239
  if (ospf_is_v2(p))
1240
    ospf_reconfigure_ifaces2(p);
1241
  else
1242
    ospf_reconfigure_ifaces3(p);
1243
}
1244

    
1245

    
1246
static void
1247
ospf_iface_change_mtu(struct ospf_proto *p, struct ospf_iface *ifa)
1248
{
1249
  /* ifa is not vlink */
1250

    
1251
  OSPF_TRACE(D_EVENTS, "Interface %s changed MTU to %d", ifa->iface->mtu);
1252

    
1253
  ifa->tx_length = ifa_tx_length(ifa);
1254

    
1255
  if (!ifa->sk)
1256
    return;
1257

    
1258
  /* We do not shrink dynamic buffers */
1259
  uint bsize = ifa_bufsize(ifa);
1260
  if (bsize > ifa->sk->rbsize)
1261
    sk_set_rbsize(ifa->sk, bsize);
1262
  if (bsize > ifa->sk->tbsize)
1263
    sk_set_tbsize(ifa->sk, bsize);
1264

    
1265
  if (!ifa->stub)
1266
    ospf_iface_update_flood_queue_size(ifa);
1267
}
1268

    
1269
static void
1270
ospf_iface_notify(struct ospf_proto *p, uint flags, struct ospf_iface *ifa)
1271
{
1272
  /* ifa is not vlink */
1273

    
1274
  if (flags & IF_CHANGE_DOWN)
1275
  {
1276
    ospf_iface_remove(ifa);
1277
    return;
1278
  }
1279

    
1280
  if (flags & IF_CHANGE_LINK)
1281
    ospf_iface_sm(ifa, (ifa->iface->flags & IF_LINK_UP) ? ISM_UNLOOP : ISM_LOOP);
1282

    
1283
  if (flags & IF_CHANGE_MTU)
1284
    ospf_iface_change_mtu(p, ifa);
1285
}
1286

    
1287
void
1288
ospf_if_notify(struct proto *P, uint flags, struct iface *iface)
1289
{
1290
  struct ospf_proto *p = (struct ospf_proto *) P;
1291

    
1292
  /*
1293
  if (iface->flags & IF_IGNORE)
1294
    return;
1295
  */
1296

    
1297
  /* Going up means that there are no such ifaces yet */
1298
  if (flags & IF_CHANGE_UP)
1299
    return;
1300

    
1301
  struct ospf_iface *ifa, *ifx;
1302
  WALK_LIST_DELSAFE(ifa, ifx, p->iface_list)
1303
    if (ifa->iface == iface)
1304
      ospf_iface_notify(p, flags, ifa);
1305

    
1306
  /* We use here that even shutting down iface also shuts down
1307
     the vlinks, but vlinks are not freed and stays in the
1308
     iface_list even when down */
1309
}
1310

    
1311
void
1312
ospf_iface_info(struct ospf_iface *ifa)
1313
{
1314
  char *more = "";
1315

    
1316
  if (ifa->strictnbma &&
1317
      ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP)))
1318
    more = " (strict)";
1319

    
1320
  if (ifa->cf->real_bcast &&
1321
      ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP)))
1322
    more = " (real)";
1323

    
1324
  if (ifa->type == OSPF_IT_VLINK)
1325
  {
1326
    cli_msg(-1015, "Virtual link %s to %R", ifa->ifname, ifa->vid);
1327
    cli_msg(-1015, "\tPeer IP: %I", ifa->vip);
1328
    cli_msg(-1015, "\tTransit area: %R (%u)", ifa->voa->areaid, ifa->voa->areaid);
1329
  }
1330
  else
1331
  {
1332
    if (ospf_is_v3(ifa->oa->po))
1333
      cli_msg(-1015, "Interface %s (IID %d)", ifa->ifname, ifa->instance_id);
1334
    else if (ifa->addr->flags & IA_PEER)
1335
      cli_msg(-1015, "Interface %s (peer %I)", ifa->ifname, ifa->addr->opposite);
1336
    else
1337
      cli_msg(-1015, "Interface %s (%N)", ifa->ifname, &ifa->addr->prefix);
1338

    
1339
    cli_msg(-1015, "\tType: %s%s", ospf_it[ifa->type], more);
1340
    cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid);
1341
  }
1342
  cli_msg(-1015, "\tState: %s%s", ospf_is_names[ifa->state], ifa->stub ? " (stub)" : "");
1343
  cli_msg(-1015, "\tPriority: %u", ifa->priority);
1344
  cli_msg(-1015, "\tCost: %u", ifa->cost);
1345
  if (ifa->oa->po->ecmp)
1346
    cli_msg(-1015, "\tECMP weight: %d", ((int) ifa->ecmp_weight) + 1);
1347
  cli_msg(-1015, "\tHello timer: %u", ifa->helloint);
1348

    
1349
  if (ifa->type == OSPF_IT_NBMA)
1350
  {
1351
    cli_msg(-1015, "\tPoll timer: %u", ifa->pollint);
1352
  }
1353
  cli_msg(-1015, "\tWait timer: %u", ifa->waitint);
1354
  cli_msg(-1015, "\tDead timer: %u", ifa->deadint);
1355
  cli_msg(-1015, "\tRetransmit timer: %u", ifa->rxmtint);
1356
  if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
1357
  {
1358
    cli_msg(-1015, "\tDesignated router (ID): %R", ifa->drid);
1359
    cli_msg(-1015, "\tDesignated router (IP): %I", ifa->drip);
1360
    cli_msg(-1015, "\tBackup designated router (ID): %R", ifa->bdrid);
1361
    cli_msg(-1015, "\tBackup designated router (IP): %I", ifa->bdrip);
1362
  }
1363
}