Commit f6dd0388 authored by Pavel Tvrdík's avatar Pavel Tvrdík
Browse files

Merge branch 'master' into birdtest

parents 3b59d075 fce764f9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ What do we support:
	o  Static routes
	o  Inter-table protocol
	o  IPv6 router advertisements
	o  Bidirectional Forwarding Detection (BFD)
	o  Command-line interface (using the `birdc' client; to get
	   some help, just press `?')
	o  Soft reconfiguration -- no online commands for changing the
+43 −21
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ struct sym_scope {
static struct sym_scope *conf_this_scope;

static int cf_hash(byte *c);
static struct symbol *cf_find_sym(byte *c, unsigned int h0);
static inline struct symbol * cf_get_sym(byte *c, uint h0);

linpool *cfg_mem;

@@ -194,7 +194,7 @@ else: {
	}
      k=k->next;
    }
  cf_lval.s = cf_find_sym(yytext, h);
  cf_lval.s = cf_get_sym(yytext, h);
  return SYM;
}

@@ -426,8 +426,9 @@ check_eof(void)
}

static struct symbol *
cf_new_sym(byte *c, unsigned int h)
cf_new_sym(byte *c, uint h0)
{
  uint h = h0 & (SYM_HASH_SIZE-1);
  struct symbol *s, **ht;
  int l;

@@ -449,56 +450,77 @@ cf_new_sym(byte *c, unsigned int h)
}

static struct symbol *
cf_find_sym(byte *c, unsigned int h0)
cf_find_sym(struct config *cfg, byte *c, uint h0)
{
  unsigned int h = h0 & (SYM_HASH_SIZE-1);
  uint h = h0 & (SYM_HASH_SIZE-1);
  struct symbol *s, **ht;

  if (ht = new_config->sym_hash)
  if (ht = cfg->sym_hash)
    {
      for(s = ht[h]; s; s=s->next)
	if (!strcmp(s->name, c) && s->scope->active)
	  return s;
    }
  if (new_config->sym_fallback)
  if (ht = cfg->sym_fallback)
    {
      /* We know only top-level scope is active */
      for(s = new_config->sym_fallback[h]; s; s=s->next)
      for(s = ht[h]; s; s=s->next)
	if (!strcmp(s->name, c) && s->scope->active)
	  return s;
    }
  return cf_new_sym(c, h);

  return NULL;
}

static inline struct symbol *
cf_get_sym(byte *c, uint h0)
{
  return cf_find_sym(new_config, c, h0) ?: cf_new_sym(c, h0);
}

/**
 * cf_find_symbol - find a symbol by name
 * @cfg: specificed config
 * @c: symbol name
 *
 * This functions searches the symbol table for a symbol of given
 * name. First it examines the current scope, then the second recent
 * one and so on until it either finds the symbol and returns a pointer
 * to its &symbol structure or reaches the end of the scope chain
 * and returns %NULL to signify no match.
 * This functions searches the symbol table in the config @cfg for a symbol of
 * given name. First it examines the current scope, then the second recent one
 * and so on until it either finds the symbol and returns a pointer to its
 * &symbol structure or reaches the end of the scope chain and returns %NULL to
 * signify no match.
 */
struct symbol *
cf_find_symbol(byte *c)
cf_find_symbol(struct config *cfg, byte *c)
{
  return cf_find_sym(c, cf_hash(c));
  return cf_find_sym(cfg, c, cf_hash(c));
}

/**
 * cf_get_symbol - get a symbol by name
 * @c: symbol name
 *
 * This functions searches the symbol table of the currently parsed config
 * (@new_config) for a symbol of given name. It returns either the already
 * existing symbol or a newly allocated undefined (%SYM_VOID) symbol if no
 * existing symbol is found.
 */
struct symbol *
cf_get_symbol(byte *c)
{
  return cf_get_sym(c, cf_hash(c));
}

struct symbol *
cf_default_name(char *template, int *counter)
{
  char buf[32];
  char buf[SYM_MAX_LEN];
  struct symbol *s;
  char *perc = strchr(template, '%');

  for(;;)
    {
      bsprintf(buf, template, ++(*counter));
      s = cf_find_sym(buf, cf_hash(buf));
      if (!s)
	break;
      s = cf_get_sym(buf, cf_hash(buf));
      if (s->class == SYM_VOID)
	return s;
      if (!perc)
@@ -529,7 +551,7 @@ cf_define_symbol(struct symbol *sym, int type, void *def)
    {
      if (sym->scope == conf_this_scope)
	cf_error("Symbol already defined");
      sym = cf_new_sym(sym->name, cf_hash(sym->name) & (SYM_HASH_SIZE-1));
      sym = cf_new_sym(sym->name, cf_hash(sym->name));
    }
  sym->class = type;
  sym->def = def;
+39 −26
Original line number Diff line number Diff line
@@ -20,19 +20,19 @@
 *
 * There can exist up to four different configurations at one time: an active
 * one (pointed to by @config), configuration we are just switching from
 * (@old_config), one queued for the next reconfiguration (@future_config;
 * if there is one and the user wants to reconfigure once again, we just
 * free the previous queued config and replace it with the new one) and
 * finally a config being parsed (@new_config). The stored @old_config 
 * is also used for undo reconfiguration, which works in a similar way.
 * Reconfiguration could also have timeout (using @config_timer) and undo
 * is automatically called if the new configuration is not confirmed later.
 * (@old_config), one queued for the next reconfiguration (@future_config; if
 * there is one and the user wants to reconfigure once again, we just free the
 * previous queued config and replace it with the new one) and finally a config
 * being parsed (@new_config). The stored @old_config is also used for undo
 * reconfiguration, which works in a similar way. Reconfiguration could also
 * have timeout (using @config_timer) and undo is automatically called if the
 * new configuration is not confirmed later. The new config (@new_config) and
 * associated linear pool (@cfg_mem) is non-NULL only during parsing.
 *
 * Loading of new configuration is very simple: just call config_alloc()
 * to get a new &config structure, then use config_parse() to parse a
 * configuration file and fill all fields of the structure
 * and finally ask the config manager to switch to the new
 * config by calling config_commit().
 * Loading of new configuration is very simple: just call config_alloc() to get
 * a new &config structure, then use config_parse() to parse a configuration
 * file and fill all fields of the structure and finally ask the config manager
 * to switch to the new config by calling config_commit().
 *
 * CLI commands are parsed in a very similar way -- there is also a stripped-down
 * &config structure associated with them and they are lex-ed and parsed by the
@@ -86,10 +86,15 @@ config_alloc(byte *name)
  linpool *l = lp_new(p, 4080);
  struct config *c = lp_allocz(l, sizeof(struct config));

  /* Duplication of name string in local linear pool */
  uint nlen = strlen(name) + 1;
  char *ndup = lp_allocu(l, nlen);
  memcpy(ndup, name, nlen);

  c->mrtdump_file = -1; /* Hack, this should be sysdep-specific */
  c->pool = p;
  cfg_mem = c->mem = l;
  c->file_name = cfg_strdup(name);
  c->mem = l;
  c->file_name = ndup;
  c->load_time = now;
  c->tf_route = c->tf_proto = (struct timeformat){"%T", "%F", 20*3600};
  c->tf_base = c->tf_log = (struct timeformat){"%F %T", NULL, 0};
@@ -114,11 +119,13 @@ config_alloc(byte *name)
int
config_parse(struct config *c)
{
  int done = 0;
  DBG("Parsing configuration file `%s'\n", c->file_name);
  new_config = c;
  cfg_mem = c->mem;
  if (setjmp(conf_jmpbuf))
    return 0;
    goto cleanup;

  cf_lex_init(0, c);
  sysdep_preconfig(c);
  protos_preconfig(c);
@@ -132,7 +139,12 @@ config_parse(struct config *c)
  if (!c->router_id)
    cf_error("Router ID must be configured manually on IPv6 routers");
#endif
  return 1;
  done = 1;

cleanup:
  new_config = NULL;
  cfg_mem = NULL;
  return done;
}

/**
@@ -145,14 +157,22 @@ config_parse(struct config *c)
int
cli_parse(struct config *c)
{
  new_config = c;
  int done = 0;
  c->sym_fallback = config->sym_hash;
  new_config = c;
  cfg_mem = c->mem;
  if (setjmp(conf_jmpbuf))
    return 0;
    goto cleanup;

  cf_lex_init(1, c);
  cf_parse();
  return 1;
  done = 1;

cleanup:
  c->sym_fallback = NULL;
  new_config = NULL;
  cfg_mem = NULL;
  return done;
}

/**
@@ -232,10 +252,6 @@ config_do_commit(struct config *c, int type)
  if (old_config && !config->shutdown)
    log(L_INFO "Reconfiguring");

  /* This should not be necessary, but it seems there are some
     functions that access new_config instead of config */
  new_config = config;

  if (old_config)
    old_config->obstacle_count++;

@@ -249,9 +265,6 @@ config_do_commit(struct config *c, int type)
  DBG("protos_commit\n");
  protos_commit(c, old_config, force_restart, type);

  /* Just to be sure nobody uses that now */
  new_config = NULL;

  int obs = 0;
  if (old_config)
    obs = --old_config->obstacle_count;
+3 −1
Original line number Diff line number Diff line
@@ -149,7 +149,9 @@ int cf_lex(void);
void cf_lex_init(int is_cli, struct config *c);
void cf_lex_unwind(void);

struct symbol *cf_find_symbol(byte *c);
struct symbol *cf_find_symbol(struct config *cfg, byte *c);

struct symbol *cf_get_symbol(byte *c);
struct symbol *cf_default_name(char *template, int *counter);
struct symbol *cf_define_symbol(struct symbol *symbol, int type, void *def);
void cf_push_scope(struct symbol *);
+35 −4
Original line number Diff line number Diff line
@@ -1571,7 +1571,7 @@ RFC 4271<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4271.txt">
It also supports the community attributes
(RFC 1997<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc1997.txt">),
capability negotiation
(RFC 3392<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc3392.txt">),
(RFC 5492<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc5492.txt">),
MD5 password authentication
(RFC 2385<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc2385.txt">),
extended communities
@@ -1707,7 +1707,11 @@ using the following configuration parameters:
	<cf/bgp_next_hop/ is used if it is directly reachable, otherwise the
	neighbor IP address is used. Recursive mode means that the gateway is
	computed by an IGP routing table lookup for the IP address from
	<cf/bgp_next_hop/. Recursive mode is the behavior specified by the BGP
	<cf/bgp_next_hop/. Note that there is just one level of indirection in
	recursive mode - the route obtained by the lookup must not be recursive
	itself, to prevent mutually recursive routes.

	Recursive mode is the behavior specified by the BGP
	standard. Direct mode is simpler, does not require any routes in a
	routing table, and was used in older versions of BIRD, but does not
	handle well nontrivial iBGP setups and multihop. Recursive mode is
@@ -2081,7 +2085,6 @@ interfaces to be defined for them to work with.
<p><descrip>

	<tag>scan time <m/number/</tag>

	Time in seconds between two scans of the network interface list. On
	systems where we are notified about interface status changes
	asynchronously (such as newer versions of Linux), we need to scan the
@@ -2227,6 +2230,18 @@ limitations can be overcome using another routing table and the pipe protocol.
	a graceful restart recovery is active, the Kernel protocol will defer
	synchronization of routing tables until the end of the recovery. Note
	that import of kernel routes to BIRD is not affected.

	<tag>merge paths <M>switch</M> [limit <M>number</M>]</tag>
	Usually, only best routes are exported to the kernel protocol. With path
	merging enabled, both best routes and equivalent non-best routes are
	merged during export to generate one ECMP (equal-cost multipath) route
	for each network. This is useful e.g. for BGP multipath. Note that best
	routes are still pivotal for route export (responsible for most
	properties of resulting ECMP routes), while exported non-best routes are
	responsible just for additional multipath next hops. This option also
	allows to specify a limit on maximal number of nexthops in one route. By
	default, multipath merging is disabled. If enabled, default value of the
	limit is 16.
</descrip>

<sect1>Attributes
@@ -2254,6 +2269,20 @@ these attributes:
	The realm of the route. Can be used for traffic classification.
</descrip>

<p>In Linux, there is also a plenty of obscure route attributes mostly focused
on tuning TCP performance of local connections. BIRD supports most of these
attributes, see Linux or iproute2 documentation for their meaning. Attributes
<cf/krt_lock_*/ and <cf/krt_feature_*/ have type bool, others have type int.
Supported attributes are:

<cf/krt_mtu/, <cf/krt_lock_mtu/, <cf/krt_window/, <cf/krt_lock_window/,
<cf/krt_rtt/, <cf/krt_lock_rtt/, <cf/krt_rttvar/, <cf/krt_lock_rttvar/,
<cf/krt_sstresh/, <cf/krt_lock_sstresh/, <cf/krt_cwnd/, <cf/krt_lock_cwnd/,
<cf/krt_advmss/, <cf/krt_lock_advmss/, <cf/krt_reordering/, <cf/krt_lock_reordering/,
<cf/krt_hoplimit/, <cf/krt_lock_hoplimit/, <cf/krt_rto_min/, <cf/krt_lock_rto_min/,
<cf/krt_initcwnd/, <cf/krt_initrwnd/, <cf/krt_quickack/,
<cf/krt_feature_ecn/, <cf/krt_feature_allfrag/

<sect1>Example

<p>A simple configuration can look this way:
@@ -3382,7 +3411,9 @@ of the protocol contains mainly a list of static routes:

<descrip>
	<tag>route <m/prefix/ via <m/ip/</tag>
	Static route through a neighboring router.
	Static route through a neighboring router. For link-local next hops,
	interface can be specified as a part of the address (e.g.,
	<cf/via fe80::1234%eth0/).

	<tag>route <m/prefix/ multipath via <m/ip/ [weight <m/num/] [via ...]</tag>
	Static multipath route. Contains several nexthops (gateways), possibly
Loading