Revision 153f02da nest/iface.c

View differences:

nest/iface.c
32 32
#include "lib/resource.h"
33 33
#include "lib/string.h"
34 34
#include "conf/conf.h"
35
#include "sysdep/unix/krt.h"
35 36

  
36 37
static pool *if_pool;
37 38

  
38 39
list iface_list;
39 40

  
41
static void if_recalc_preferred(struct iface *i);
42

  
40 43
/**
41 44
 * ifa_dump - dump interface address
42 45
 * @a: interface address descriptor
......
183 186
	    (c & IF_CHANGE_DOWN) ? "goes down" :
184 187
	    (c & IF_CHANGE_MTU) ? "changes MTU" :
185 188
	    (c & IF_CHANGE_LINK) ? "changes link" :
189
	    (c & IF_CHANGE_PREFERRED) ? "changes preferred address" :
186 190
	    (c & IF_CHANGE_CREATE) ? "created" :
187 191
	    "sends unknown event");
188 192
      p->if_notify(p, c, i);
......
211 215

  
212 216
  if (c & IF_CHANGE_DOWN)
213 217
    WALK_LIST(a, i->addrs)
214
      {
215
	a->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
216
	ifa_notify_change_(IF_CHANGE_DOWN, a);
217
      }
218
      ifa_notify_change_(IF_CHANGE_DOWN, a);
218 219

  
219 220
  WALK_LIST(p, proto_list)
220 221
    if_send_notify(p, c, i);
221 222

  
222 223
  if (c & IF_CHANGE_UP)
223 224
    WALK_LIST(a, i->addrs)
224
      {
225
	a->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
226
	ifa_notify_change_(IF_CHANGE_UP, a);
227
      }
225
      ifa_notify_change_(IF_CHANGE_UP, a);
228 226

  
229 227
  if (c & IF_CHANGE_UP)
230 228
    neigh_if_up(i);
......
233 231
    neigh_if_link(i);
234 232
}
235 233

  
236
static unsigned
237
if_recalc_flags(struct iface *i, unsigned flags)
234
static uint
235
if_recalc_flags(struct iface *i UNUSED, uint flags)
238 236
{
239
  if ((flags & (IF_SHUTDOWN | IF_TMP_DOWN)) ||
240
      !(flags & IF_ADMIN_UP) ||
241
      !i->addr)
242
    flags &= ~IF_UP;
243
  else
237
  if ((flags & IF_ADMIN_UP) && !(flags & (IF_SHUTDOWN | IF_TMP_DOWN)))
244 238
    flags |= IF_UP;
239
  else
240
    flags &= ~IF_UP;
241

  
245 242
  return flags;
246 243
}
247 244

  
248 245
static void
249
if_change_flags(struct iface *i, unsigned flags)
246
if_change_flags(struct iface *i, uint flags)
250 247
{
251
  unsigned of = i->flags;
252

  
248
  uint of = i->flags;
253 249
  i->flags = if_recalc_flags(i, flags);
250

  
254 251
  if ((i->flags ^ of) & IF_UP)
255 252
    if_notify_change((i->flags & IF_UP) ? IF_CHANGE_UP : IF_CHANGE_DOWN, i);
256 253
}
......
298 295
  WALK_LIST(i, iface_list)
299 296
    if (!strcmp(new->name, i->name))
300 297
      {
301
	new->addr = i->addr;
302 298
	new->flags = if_recalc_flags(new, new->flags);
303 299
	c = if_what_changed(i, new);
304 300
	if (c & IF_CHANGE_TOO_MUCH)	/* Changed a lot, convert it to down/up */
......
306 302
	    DBG("Interface %s changed too much -- forcing down/up transition\n", i->name);
307 303
	    if_change_flags(i, i->flags | IF_TMP_DOWN);
308 304
	    rem_node(&i->n);
309
	    new->addr = i->addr;
305
	    new->addr4 = i->addr4;
306
	    new->addr6 = i->addr6;
307
	    new->llv6 = i->llv6;
308
	    new->sysdep = i->sysdep;
310 309
	    memcpy(&new->addrs, &i->addrs, sizeof(i->addrs));
311 310
	    memcpy(i, new, sizeof(*i));
312
	    i->flags &= ~IF_UP; /* IF_TMP_DOWN will be added later */
311
	    i->flags &= ~IF_UP; 	/* IF_TMP_DOWN will be added later */
313 312
	    goto newif;
314 313
	  }
315 314

  
......
340 339
    {
341 340
      i->flags &= ~IF_UPDATED;
342 341
      WALK_LIST(a, i->addrs)
343
	a->flags &= ~IF_UPDATED;
342
	a->flags &= ~IA_UPDATED;
344 343
    }
345 344
}
346 345

  
347 346
void
348 347
if_end_partial_update(struct iface *i)
349 348
{
349
  if (i->flags & IF_NEEDS_RECALC)
350
    if_recalc_preferred(i);
351

  
350 352
  if (i->flags & IF_TMP_DOWN)
351 353
    if_change_flags(i, i->flags & ~IF_TMP_DOWN);
352 354
}
......
364 366
      else
365 367
	{
366 368
	  WALK_LIST_DELSAFE(a, b, i->addrs)
367
	    if (!(a->flags & IF_UPDATED))
369
	    if (!(a->flags & IA_UPDATED))
368 370
	      ifa_delete(a);
369 371
	  if_end_partial_update(i);
370 372
	}
......
461 463
  return i;
462 464
}
463 465

  
464
struct ifa *kif_choose_primary(struct iface *i);
466
static inline void
467
if_set_preferred(struct ifa **pos, struct ifa *new)
468
{
469
  if (*pos)
470
    (*pos)->flags &= ~IA_PRIMARY;
471
  if (new)
472
    new->flags |= IA_PRIMARY;
465 473

  
466
static int
467
ifa_recalc_primary(struct iface *i)
474
  *pos = new;
475
}
476

  
477
static void
478
if_recalc_preferred(struct iface *i)
468 479
{
469
  struct ifa *a = kif_choose_primary(i);
480
  /*
481
   * Preferred address selection priority:
482
   * 1) Address configured in Device protocol
483
   * 2) Sysdep IPv4 address (BSD)
484
   * 3) Old preferred address
485
   * 4) First address in list
486
   */
470 487

  
471
  if (a == i->addr)
472
    return 0;
488
  struct kif_iface_config *ic = kif_get_iface_config(i);
489
  struct ifa *a4 = i->addr4, *a6 = i->addr6, *ll = i->llv6;
490
  ip_addr pref_v4 = ic->pref_v4;
491
  uint change = 0;
492

  
493
  if (kif_update_sysdep_addr(i))
494
    change |= IF_CHANGE_SYSDEP;
473 495

  
474
  if (i->addr)
475
    i->addr->flags &= ~IA_PRIMARY;
496
  /* BSD sysdep address */
497
  if (ipa_zero(pref_v4) && ip4_nonzero(i->sysdep))
498
    pref_v4 = ipa_from_ip4(i->sysdep);
476 499

  
477
  if (a)
500
  struct ifa *a;
501
  WALK_LIST(a, i->addrs)
478 502
    {
479
      a->flags |= IA_PRIMARY;
480
      rem_node(&a->n);
481
      add_head(&i->addrs, &a->n);
503
      /* Secondary address is never selected */
504
      if (a->flags & IA_SECONDARY)
505
	continue;
506

  
507
      if (ipa_is_ip4(a->ip)) {
508
	if (!a4 || ipa_equal(a->ip, pref_v4))
509
	  a4 = a;
510
      } else if (!ipa_is_link_local(a->ip)) {
511
	if (!a6 || ipa_equal(a->ip, ic->pref_v6))
512
	  a6 = a;
513
      } else {
514
	if (!ll || ipa_equal(a->ip, ic->pref_ll))
515
	  ll = a;
516
      }
482 517
    }
483 518

  
484
  i->addr = a;
485
  return 1;
519
  if (a4 != i->addr4)
520
  {
521
    if_set_preferred(&i->addr4, a4);
522
    change |= IF_CHANGE_ADDR4;
523
  }
524

  
525
  if (a6 != i->addr6)
526
  {
527
    if_set_preferred(&i->addr6, a6);
528
    change |= IF_CHANGE_ADDR6;
529
  }
530

  
531
  if (ll != i->llv6)
532
  {
533
    if_set_preferred(&i->llv6, ll);
534
    change |= IF_CHANGE_LLV6;
535
  }
536

  
537
  i->flags &= ~IF_NEEDS_RECALC;
538

  
539
  /*
540
   * FIXME: There should be proper notification instead of iface restart:
541
   * if_notify_change(change, i)
542
   */
543
  if (change)
544
    if_change_flags(i, i->flags | IF_TMP_DOWN);
486 545
}
487 546

  
488 547
void
489
ifa_recalc_all_primary_addresses(void)
548
if_recalc_all_preferred_addresses(void)
490 549
{
491 550
  struct iface *i;
492 551

  
493 552
  WALK_LIST(i, iface_list)
494
    {
495
      if (ifa_recalc_primary(i))
496
	if_change_flags(i, i->flags | IF_TMP_DOWN);
497
    }
553
  {
554
    if_recalc_preferred(i);
555

  
556
    if (i->flags & IF_TMP_DOWN)
557
      if_change_flags(i, i->flags & ~IF_TMP_DOWN);
558
  }
498 559
}
499 560

  
500 561
static inline int
......
526 587
	    b->scope == a->scope &&
527 588
	    !((b->flags ^ a->flags) & IA_PEER))
528 589
	  {
529
	    b->flags |= IF_UPDATED;
590
	    b->flags |= IA_UPDATED;
530 591
	    return b;
531 592
	  }
532 593
	ifa_delete(b);
......
534 595
      }
535 596

  
536 597
  if ((a->prefix.type == NET_IP4) && (i->flags & IF_BROADCAST) && ipa_zero(a->brd))
537
    log(L_ERR "Missing broadcast address for interface %s", i->name);
598
    log(L_WARN "Missing broadcast address for interface %s", i->name);
538 599

  
539 600
  b = mb_alloc(if_pool, sizeof(struct ifa));
540 601
  memcpy(b, a, sizeof(struct ifa));
541 602
  add_tail(&i->addrs, &b->n);
542
  b->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
543
  if (ifa_recalc_primary(i))
544
    if_change_flags(i, i->flags | IF_TMP_DOWN);
545
  if (b->flags & IF_UP)
603
  b->flags |= IA_UPDATED;
604

  
605
  i->flags |= IF_NEEDS_RECALC;
606
  if (i->flags & IF_UP)
546 607
    ifa_notify_change(IF_CHANGE_CREATE | IF_CHANGE_UP, b);
547 608
  return b;
548 609
}
......
565 626
    if (ifa_same(b, a))
566 627
      {
567 628
	rem_node(&b->n);
568
	if (b->flags & IF_UP)
569
	  {
570
	    b->flags &= ~IF_UP;
571
	    ifa_notify_change(IF_CHANGE_DOWN, b);
572
	  }
629

  
573 630
	if (b->flags & IA_PRIMARY)
574 631
	  {
575
	    if_change_flags(i, i->flags | IF_TMP_DOWN);
576
	    ifa_recalc_primary(i);
632
	    /*
633
	     * We unlink deleted preferred address and mark for recalculation.
634
	     * FIXME: This could break if we make iface scan non-atomic, as
635
	     * protocols still could use the freed address until they get
636
	     * if_notify from preferred route recalculation.
637
	     */
638
	    if (b == i->addr4) i->addr4 = NULL;
639
	    if (b == i->addr6) i->addr6 = NULL;
640
	    if (b == i->llv6) i->llv6 = NULL;
641
	    i->flags |= IF_NEEDS_RECALC;
577 642
	  }
643

  
644
	if (i->flags & IF_UP)
645
	  ifa_notify_change(IF_CHANGE_DOWN, b);
646

  
578 647
	mb_free(b);
579 648
	return;
580 649
      }
......
741 810
static void
742 811
if_show_addr(struct ifa *a)
743 812
{
744
  byte opp[IPA_MAX_TEXT_LENGTH + 16];
813
  byte *flg, opp[IPA_MAX_TEXT_LENGTH + 16];
814

  
815
  flg = (a->flags & IA_PRIMARY) ? "Preferred, " : (a->flags & IA_SECONDARY) ? "Secondary, " : "";
745 816

  
746 817
  if (ipa_nonzero(a->opposite))
747
    bsprintf(opp, ", opposite %I", a->opposite);
818
    bsprintf(opp, "opposite %I, ", a->opposite);
748 819
  else
749 820
    opp[0] = 0;
750
  cli_msg(-1003, "\t%I/%d (%s%s, scope %s)",
751
	  a->ip, a->prefix.pxlen,
752
	  (a->flags & IA_PRIMARY) ? "Primary" : (a->flags & IA_SECONDARY) ? "Secondary" : "Unselected",
753
	  opp, ip_scope_text(a->scope));
821

  
822
  cli_msg(-1003, "\t%I/%d (%s%sscope %s)",
823
	  a->ip, a->prefix.pxlen, flg, opp, ip_scope_text(a->scope));
754 824
}
755 825

  
756 826
void
......
765 835
      if (i->flags & IF_SHUTDOWN)
766 836
	continue;
767 837

  
768
      cli_msg(-1001, "%s %s (index=%d)", i->name, (i->flags & IF_UP) ? "up" : "DOWN", i->index);
838
      cli_msg(-1001, "%s %s (index=%d)", i->name, (i->flags & IF_UP) ? "Up" : "Down", i->index);
769 839
      if (!(i->flags & IF_MULTIACCESS))
770 840
	type = "PtP";
771 841
      else
......
779 849
	      (i->flags & IF_LOOPBACK) ? " Loopback" : "",
780 850
	      (i->flags & IF_IGNORE) ? " Ignored" : "",
781 851
	      i->mtu);
782
      if (i->addr)
783
	if_show_addr(i->addr);
852

  
853
      WALK_LIST(a, i->addrs)
854
	if (a->prefix.type == NET_IP4)
855
	  if_show_addr(a);
856

  
784 857
      WALK_LIST(a, i->addrs)
785
	if (a != i->addr)
858
	if (a->prefix.type == NET_IP6)
786 859
	  if_show_addr(a);
787 860
    }
788 861
  cli_msg(0, "");
......
792 865
if_show_summary(void)
793 866
{
794 867
  struct iface *i;
795
  byte addr[IPA_MAX_TEXT_LENGTH + 16];
796 868

  
797
  cli_msg(-2005, "interface state address");
869
  cli_msg(-2005,  "%-10s %-6s %-18s %s", "Interface", "State", "IPv4 address", "IPv6 address");
798 870
  WALK_LIST(i, iface_list)
799 871
    {
800
      if (i->addr)
801
	bsprintf(addr, "%I/%d", i->addr->ip, i->addr->prefix.pxlen);
872
      byte a4[IPA_MAX_TEXT_LENGTH + 17];
873
      byte a6[IPA_MAX_TEXT_LENGTH + 17];
874

  
875
      if (i->addr4)
876
	bsprintf(a4, "%I/%d", i->addr4->ip, i->addr4->prefix.pxlen);
802 877
      else
803
	addr[0] = 0;
804
      cli_msg(-1005, "%-9s %-5s %s", i->name, (i->flags & IF_UP) ? "up" : "DOWN", addr);
878
	a4[0] = 0;
879

  
880
      if (i->addr6)
881
	bsprintf(a6, "%I/%d", i->addr6->ip, i->addr6->prefix.pxlen);
882
      else
883
	a6[0] = 0;
884

  
885
      cli_msg(-1005, "%-10s %-6s %-18s %s",
886
	      i->name, (i->flags & IF_UP) ? "Up" : "Down", a4, a6);
805 887
    }
806 888
  cli_msg(0, "");
807 889
}

Also available in: Unified diff