Revision cf98be7b nest/rt-table.c

View differences:

nest/rt-table.c
69 69
    {
70 70
      a0 = ipa_and(a, ipa_mkmask(len));
71 71
      n = fib_find(&tab->fib, &a0, len);
72
      if (n && n->routes)
72
      if (n && rte_is_valid(n->routes))
73 73
	return n;
74 74
      len--;
75 75
    }
......
139 139
{
140 140
  int (*better)(rte *, rte *);
141 141

  
142
  if (!old)
142
  if (!rte_is_valid(old))
143 143
    return 1;
144
  if (!rte_is_valid(new))
145
    return 0;
146

  
144 147
  if (new->pref > old->pref)
145 148
    return 1;
146 149
  if (new->pref < old->pref)
......
399 402
  rte *old_free = NULL;
400 403
  rte *r;
401 404

  
402
  /* Used to track whether we met old_changed position. If it is NULL
403
     it was the first and met it implicitly before current best route. */
404
  int old_meet = (old_changed && !before_old) ? 1 : 0;
405
  /* Used to track whether we met old_changed position. If before_old is NULL
406
     old_changed was the first and we met it implicitly before current best route. */
407
  int old_meet = old_changed && !before_old;
408

  
409
  /* Note that before_old is either NULL or valid (not rejected) route.
410
     If old_changed is valid, before_old have to be too. If old changed route
411
     was not valid, caller must use NULL for both old_changed and before_old. */
405 412

  
406 413
  if (new_changed)
407 414
    stats->exp_updates_received++;
......
409 416
    stats->exp_withdraws_received++;
410 417

  
411 418
  /* First, find the new_best route - first accepted by filters */
412
  for (r=net->routes; r; r=r->next)
419
  for (r=net->routes; rte_is_valid(r); r=r->next)
413 420
    {
414 421
      if (new_best = export_filter(ah, r, &new_free, &tmpa, 0))
415 422
	break;
......
428 435
  if (feed)
429 436
    {
430 437
      if (feed == 2)	/* refeed */
431
	old_best = new_best ? new_best : net->routes;
438
	old_best = new_best ? new_best :
439
	  (rte_is_valid(net->routes) ? net->routes : NULL);
432 440
      else
433 441
	old_best = NULL;
434 442

  
......
477 485
    }
478 486

  
479 487
  /* Fourth case */
480
  for (r=r->next; r; r=r->next)
488
  for (r=r->next; rte_is_valid(r); r=r->next)
481 489
    {
482 490
      if (old_best = export_filter(ah, r, &old_free, NULL, 1))
483 491
	goto found;
......
531 539
static void
532 540
rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, rte *before_old, ea_list *tmpa)
533 541
{
534
  struct announce_hook *a;
542
  if (!rte_is_valid(old))
543
    old = before_old = NULL;
544

  
545
  if (!rte_is_valid(new))
546
    new = NULL;
547

  
548
  if (!old && !new)
549
    return;
535 550

  
536 551
  if (type == RA_OPTIMAL)
537 552
    {
......
544 559
	rt_notify_hostcache(tab, net);
545 560
    }
546 561

  
562
  struct announce_hook *a;
547 563
  WALK_LIST(a, tab->hooks)
548 564
    {
549 565
      ASSERT(a->proto->core_state == FS_HAPPY || a->proto->core_state == FS_FEEDING);
......
650 666
	  if (new && rte_same(old, new))
651 667
	    {
652 668
	      /* No changes, ignore the new route */
653
	      stats->imp_updates_ignored++;
654
	      rte_trace_in(D_ROUTES, p, new, "ignored");
669

  
670
	      if (!rte_is_rejected(new))
671
		{
672
		  stats->imp_updates_ignored++;
673
		  rte_trace_in(D_ROUTES, p, new, "ignored");
674
		}
675

  
655 676
	      rte_free_quick(new);
656 677
#ifdef CONFIG_RIP
657 678
	      /* lastmod is used internally by RIP as the last time
......
680 701
  struct proto_limit *l = ah->in_limit;
681 702
  if (l && !old && new)
682 703
    {
683
      if (stats->imp_routes >= l->limit)
684
	proto_notify_limit(ah, l, stats->imp_routes);
704
      u32 all_routes = stats->imp_routes + stats->rej_routes;
705

  
706
      if (all_routes >= l->limit)
707
	proto_notify_limit(ah, l, all_routes);
685 708

  
686 709
      if (l->state == PLS_BLOCKED)
687 710
	{
......
692 715
	}
693 716
    }
694 717

  
695
  if (new)
718
  if (new && !rte_is_rejected(new))
696 719
    stats->imp_updates_accepted++;
697 720
  else
698 721
    stats->imp_withdraws_accepted++;
699 722

  
700 723
  if (new)
701
    stats->imp_routes++;
724
    rte_is_rejected(new) ? stats->rej_routes++ : stats->imp_routes++;
702 725
  if (old)
703
    stats->imp_routes--;
726
    rte_is_rejected(old) ? stats->rej_routes-- : stats->imp_routes--;
704 727

  
705 728
  if (table->config->sorted)
706 729
    {
......
900 923
	  stats->imp_updates_invalid++;
901 924
	  goto drop;
902 925
	}
926

  
903 927
      if (filter == FILTER_REJECT)
904 928
	{
905 929
	  stats->imp_updates_filtered++;
906 930
	  rte_trace_in(D_FILTERS, p, new, "filtered out");
907
	  goto drop;
931

  
932
	  if (! ah->in_keep_rejected)
933
	    goto drop;
934

  
935
	  /* new is a private copy, i could modify it */
936
	  new->flags |= REF_REJECTED;
908 937
	}
909
      if (src->make_tmp_attrs)
910
	tmpa = src->make_tmp_attrs(new, rte_update_pool);
911
      if (filter)
938
      else
912 939
	{
913
	  ea_list *old_tmpa = tmpa;
914
	  int fr = f_run(filter, &new, &tmpa, rte_update_pool, 0);
915
	  if (fr > F_ACCEPT)
940
	  if (src->make_tmp_attrs)
941
	    tmpa = src->make_tmp_attrs(new, rte_update_pool);
942
	  if (filter && (filter != FILTER_REJECT))
916 943
	    {
917
	      stats->imp_updates_filtered++;
918
	      rte_trace_in(D_FILTERS, p, new, "filtered out");
919
	      goto drop;
944
	      ea_list *old_tmpa = tmpa;
945
	      int fr = f_run(filter, &new, &tmpa, rte_update_pool, 0);
946
	      if (fr > F_ACCEPT)
947
		{
948
		  stats->imp_updates_filtered++;
949
		  rte_trace_in(D_FILTERS, p, new, "filtered out");
950

  
951
		  if (! ah->in_keep_rejected)
952
		    goto drop;
953

  
954
		  new->flags |= REF_REJECTED;
955
		}
956
	      if (tmpa != old_tmpa && src->store_tmp_attrs)
957
		src->store_tmp_attrs(new, tmpa);
920 958
	    }
921
	  if (tmpa != old_tmpa && src->store_tmp_attrs)
922
	    src->store_tmp_attrs(new, tmpa);
923 959
	}
960

  
924 961
      if (!(new->attrs->aflags & RTAF_CACHED)) /* Need to copy attributes */
925 962
	new->attrs = rta_lookup(new->attrs);
926 963
      new->flags |= REF_COW;
......
1553 1590
	  return 0;
1554 1591
	}
1555 1592

  
1593
      /* XXXX perhaps we should change feed for RA_ACCEPTED to not use 'new' */
1594

  
1556 1595
      if ((p->accept_ra_types == RA_OPTIMAL) ||
1557 1596
	  (p->accept_ra_types == RA_ACCEPTED))
1558
	if (e)
1597
	if (rte_is_valid(e))
1559 1598
	  {
1560 1599
	    if (p->core_state != FS_FEEDING)
1561 1600
	      return 1;  /* In the meantime, the protocol fell down. */
......
1564 1603
	  }
1565 1604

  
1566 1605
      if (p->accept_ra_types == RA_ANY)
1567
	for(e = n->routes; e != NULL; e = e->next)
1606
	for(e = n->routes; rte_is_valid(e); e = e->next)
1568 1607
	  {
1569 1608
	    if (p->core_state != FS_FEEDING)
1570 1609
	      return 1;  /* In the meantime, the protocol fell down. */
......
1817 1856
  net *n = net_route(tab, he->addr, MAX_PREFIX_LENGTH);
1818 1857
  if (n)
1819 1858
    {
1820
      rta *a = n->routes->attrs;
1859
      rte *e = n->routes;
1860
      rta *a = e->attrs;
1821 1861
      pxlen = n->n.pxlen;
1822 1862

  
1823 1863
      if (a->hostentry)
......
1850 1890
	}
1851 1891

  
1852 1892
      he->src = rta_clone(a);
1853
      he->igp_metric = rt_get_igp_metric(n->routes);
1893
      he->igp_metric = rt_get_igp_metric(e);
1854 1894
    }
1855 1895

  
1856 1896
 done:
......
1980 2020
  int ok;
1981 2021

  
1982 2022
  bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen);
1983
  if (n->routes)
1984
    d->net_counter++;
2023

  
1985 2024
  for(e=n->routes; e; e=e->next)
1986 2025
    {
2026
      if (rte_is_rejected(e) != d->rejected)
2027
	continue;
2028

  
1987 2029
      struct ea_list *tmpa;
1988 2030
      struct proto *p0 = e->attrs->proto;
1989 2031
      struct proto *p1 = d->export_protocol;
1990 2032
      struct proto *p2 = d->show_protocol;
2033

  
2034
      if (ia[0])
2035
	d->net_counter++;
1991 2036
      d->rt_counter++;
1992 2037
      ee = e;
1993 2038
      rte_update_lock();		/* We use the update buffer for filtering */

Also available in: Unified diff