Commit 26822d8f authored by Ondrej Zajicek's avatar Ondrej Zajicek
Browse files

Finalize RA_ACCEPTED handling.

parent b7f3df79
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@ CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OF
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE, ROA, MAX, FLUSH)
CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION)
CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED)
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC)

CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
@@ -64,7 +64,7 @@ CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID)
%type <ro> roa_args
%type <rot> roa_table_arg
%type <sd> sym_args
%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_or_preexport roa_mode
%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_or_preexport roa_mode tab_sorted
%type <ps> proto_patt proto_patt2

CF_GRAMMAR
@@ -110,10 +110,17 @@ listen_opt:

/* Creation of routing tables */

tab_sorted:
          { $$ = 0; }
 | SORTED { $$ = 1; }
 ;

CF_ADDTO(conf, newtab)

newtab: TABLE SYM {
   rt_new_table($2);
newtab: TABLE SYM tab_sorted {
   struct rtable_config *cf;
   cf = rt_new_table($2);
   cf->sorted = $3;
   }
 ;

+1 −0
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ struct rtable_config {
  struct proto_config *krt_attached;	/* Kernel syncer attached to this table */
  int gc_max_ops;			/* Maximum number of operations before GC is run */
  int gc_min_time;			/* Minimum time between two consecutive GC runs */
  byte sorted;				/* Routes of network are sorted according to rte_better() */
};

typedef struct rtable {
+90 −13
Original line number Diff line number Diff line
@@ -423,7 +423,7 @@ rt_notify_accepted(struct announce_hook *ah, net *net, rte *new_changed, rte *ol
  if (!new_best)
    return;

  /* Third case, we use r insead of new_best, because export_filter() could change it */
  /* Third case, we use r instead of new_best, because export_filter() could change it */
  if (r != new_changed)
    {
      if (new_free)
@@ -432,7 +432,7 @@ rt_notify_accepted(struct announce_hook *ah, net *net, rte *new_changed, rte *ol
    }

  /* Fourth case */
  for (; r; r=r->next)
  for (r=r->next; r; r=r->next)
    {
      if (old_best = export_filter(ah, r, &old_free, NULL, 1))
	goto found;
@@ -642,20 +642,92 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str
  if (old)
    stats->imp_routes--;

  if (table->config->sorted)
    {
      /* If routes are sorted, just insert new route to appropriate position */
      if (new)
	{
      for (k=&net->routes; *k; k=&(*k)->next)
	  if (before_old && !rte_better(new, before_old))
	    k = &before_old->next;
	  else
	    k = &net->routes;

	  for (; *k; k=&(*k)->next)
	    if (rte_better(new, *k))
	      break;

      new->lastmod = now;
	  new->next = *k;
	  *k = new;
	}
    }
  else
    {
      /* If routes are not sorted, find the best route and move it on
	 the first position. There are several optimized cases. */

      rte_trace_in(D_ROUTES, p, new, net->routes == new ? "added [best]" : "added");
      if (src->rte_recalculate && src->rte_recalculate(table, net, new, old, old_best))
	goto do_recalculate;

      if (new && rte_better(new, old_best))
	{
	  /* The first case - the new route is cleary optimal,
	     we link it at the first position */

	  new->next = net->routes;
	  net->routes = new;
	}
      else if (old == old_best)
	{
	  /* The second case - the old best route disappeared, we add the
	     new route (if we have any) to the list (we don't care about
	     position) and then we elect the new optimal route and relink
	     that route at the first position and announce it. New optimal
	     route might be NULL if there is no more routes */

	do_recalculate:
	  /* Add the new route to the list */
	  if (new)
	    {
	      new->next = net->routes;
	      net->routes = new;
	    }

  /* Log the route removal */
	  /* Find a new optimal route (if there is any) */
	  if (net->routes)
	    {
	      rte **bp = &net->routes;
	      for (k=&(*bp)->next; *k; k=&(*k)->next)
		if (rte_better(*k, *bp))
		  bp = k;

	      /* And relink it */
	      rte *best = *bp;
	      *bp = best->next;
	      best->next = net->routes;
	      net->routes = best;
	    }
	}
      else if (new)
	{
	  /* The third case - the new route is not better than the old
	     best route (therefore old_best != NULL) and the old best
	     route was not removed (therefore old_best == net->routes).
	     We just link the new route after the old best route. */

	  ASSERT(net->routes != NULL);
	  new->next = net->routes->next;
	  net->routes->next = new;
	}
      /* The fourth (empty) case - suboptimal route was removed, nothing to do */
    }

  if (new)
    new->lastmod = now;

  /* Log the route change */
  if (new)
    rte_trace_in(D_ROUTES, p, new, net->routes == new ? "added [best]" : "added");

  if (!new && (p->debug & D_ROUTES))
    {
      if (old != old_best)
@@ -666,8 +738,11 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str
	rte_trace_in(D_ROUTES, p, old, "removed [sole]");
    }

  /* Propagate the route change */
  rte_announce(table, RA_ANY, net, new, old, NULL, tmpa);
  if (net->routes != old_best)
    rte_announce(table, RA_OPTIMAL, net, net->routes, old_best, NULL, tmpa);
  if (table->config->sorted)
    rte_announce(table, RA_ACCEPTED, net, new, old, before_old, tmpa);

  if (!net->routes &&
@@ -1336,6 +1411,8 @@ rt_commit(struct config *new, struct config *old)
		  r->table = ot;
		  ot->name = r->name;
		  ot->config = r;
		  if (o->sorted != r->sorted)
		    log(L_WARN "Reconfiguration of rtable sorted flag not implemented");
		}
	      else
		{
+2 −1
Original line number Diff line number Diff line
@@ -1258,7 +1258,8 @@ same_group(rte *r, u32 lpref, u32 lasn)
static inline int
use_deterministic_med(rte *r)
{
  return ((struct bgp_proto *) r->attrs->proto)->cf->deterministic_med;
  struct proto *P = r->attrs->proto;
  return (P->proto == &proto_bgp) && ((struct bgp_proto *) P)->cf->deterministic_med;
}

int
+13 −4
Original line number Diff line number Diff line
@@ -955,14 +955,14 @@ bgp_check_config(struct bgp_config *c)
  if (internal && c->rs_client)
    cf_error("Only external neighbor can be RS client");

  /*

  if (c->multihop && (c->gw_mode == GW_DIRECT))
    cf_error("Multihop BGP cannot use direct gateway mode");

  if (c->multihop && (ipa_has_link_scope(c->remote_ip) || 
		      ipa_has_link_scope(c->source_addr)))
    cf_error("Multihop BGP cannot be used with link-local addresses");
  */


  /* Different default based on rs_client */
  if (!c->missing_lladdr)
@@ -970,8 +970,17 @@ bgp_check_config(struct bgp_config *c)

  /* Different default for gw_mode */
  if (!c->gw_mode)
    // c->gw_mode = (c->multihop || internal) ? GW_RECURSIVE : GW_DIRECT;
    c->gw_mode = GW_DIRECT;
    c->gw_mode = (c->multihop || internal) ? GW_RECURSIVE : GW_DIRECT;


  if ((c->gw_mode == GW_RECURSIVE) && c->c.table->sorted)
    cf_error("BGP in recursive mode prohibits sorted table");

  if (c->deterministic_med && c->c.table->sorted)
    cf_error("BGP with deterministic MED prohibits sorted table");

  if (c->secondary && !c->c.table->sorted)
    cf_error("BGP with secondary option requires sorted table");
}

static int
Loading