Commit 0aeac9cb authored by Ondrej Zajicek's avatar Ondrej Zajicek
Browse files

Merge commit 'origin/bfd'

parents 8931425d 7c9930f9
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -133,6 +133,18 @@ if test "$bird_cv_struct_ip_mreqn" = yes ; then
fi
])

AC_DEFUN(BIRD_CHECK_PTHREADS,
[
  bird_tmp_cflags="$CFLAGS"

  CFLAGS="$CFLAGS -pthread"
  AC_CACHE_CHECK([whether POSIX threads are available], bird_cv_lib_pthreads,
    [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]], [[pthread_t pt; pthread_create(&pt, NULL, NULL, NULL); pthread_spinlock_t lock; pthread_spin_lock(&lock); ]])],
		    [bird_cv_lib_pthreads=yes], [bird_cv_lib_pthreads=no])])

  CFLAGS="$bird_tmp_cflags"
])

AC_DEFUN(BIRD_CHECK_GCC_OPTION,
[
  bird_tmp_cflags="$CFLAGS"
+9 −1
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ CF_DECLS
%type <iface> ipa_scope

%type <i> expr bool pxlen
%type <i32> expr_us
%type <time> datetime
%type <a> ipa
%type <px> prefix prefix_or_ipa
@@ -86,7 +87,7 @@ CF_DECLS
%left '!'
%nonassoc '.'

CF_KEYWORDS(DEFINE, ON, OFF, YES, NO)
CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US)

CF_GRAMMAR

@@ -124,6 +125,13 @@ expr:
     $$ = SYM_VAL($1).i; }
 ;


expr_us:
   expr S  { $$ = (u32) $1 * 1000000; }
 | expr MS { $$ = (u32) $1 * 1000; }
 | expr US { $$ = (u32) $1 * 1; }
 ;

/* expr_u16: expr { check_u16($1); $$ = $1; }; */

/* Switches */
+27 −6
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ AC_ARG_ENABLE(debug, [ --enable-debug enable internal debugging routin
AC_ARG_ENABLE(memcheck,	[  --enable-memcheck       check memory allocations when debugging (default: enabled)],,enable_memcheck=yes)
AC_ARG_ENABLE(client,	[  --enable-client         enable building of BIRD client (default: enabled)],,enable_client=yes)
AC_ARG_ENABLE(ipv6,	[  --enable-ipv6           enable building of IPv6 version (default: disabled)],,enable_ipv6=no)
AC_ARG_ENABLE(pthreads,	[  --enable-pthreads       enable POSIX threads support (default: detect)],,enable_pthreads=try)
AC_ARG_WITH(suffix,	[  --with-suffix=STRING    use specified suffix for BIRD files (default: 6 for IPv6 version)],[given_suffix="yes"])
AC_ARG_WITH(sysconfig,	[  --with-sysconfig=FILE   use specified BIRD system configuration file])
AC_ARG_WITH(protocols,	[  --with-protocols=LIST   include specified routing protocols (default: all)],,[with_protocols="all"])
@@ -47,11 +48,10 @@ AC_SUBST(runtimedir)
if test "$enable_ipv6" = yes ; then
	ip=ipv6
	SUFFIX=6
	all_protocols=bgp,ospf,pipe,radv,rip,static
	proto_radv=radv
else
	ip=ipv4
	SUFFIX=""
	all_protocols=bgp,ospf,pipe,rip,static
fi

if test "$given_suffix" = yes ; then
@@ -59,10 +59,6 @@ if test "$given_suffix" = yes ; then
fi
AC_SUBST(SUFFIX)

if test "$with_protocols" = all ; then
	with_protocols="$all_protocols"
fi

if test "$enable_debug" = yes ; then
	CONFIG_FILE="bird$SUFFIX.conf"
	CONTROL_SOCKET="bird$SUFFIX.ctl"
@@ -87,6 +83,23 @@ if test -z "$GCC" ; then
	AC_MSG_ERROR([This program requires the GNU C Compiler.])
fi

if test "$enable_pthreads" != no ; then
	BIRD_CHECK_PTHREADS

	if test "$bird_cv_lib_pthreads" = yes ; then
		AC_DEFINE(USE_PTHREADS)
		CFLAGS="$CFLAGS -pthread"
		LDFLAGS="$LDFLAGS -pthread"
		proto_bfd=bfd
	elif test "$enable_pthreads" = yes ; then
		AC_MSG_ERROR([POSIX threads not available.])
	fi

	if test "$enable_pthreads" = try ; then
		enable_pthreads="$bird_cv_lib_pthreads"
	fi
fi

if test "$bird_cflags_default" = yes ; then
	BIRD_CHECK_GCC_OPTION(bird_cv_c_option_wno_pointer_sign, -Wno-pointer-sign, -Wall)
	BIRD_CHECK_GCC_OPTION(bird_cv_c_option_fno_strict_aliasing, -fno-strict-aliasing)
@@ -183,6 +196,13 @@ fi

AC_SUBST(iproutedir)

all_protocols="$proto_bfd bgp ospf pipe $proto_radv rip static"
all_protocols=`echo $all_protocols | sed 's/ /,/g'`

if test "$with_protocols" = all ; then
	with_protocols="$all_protocols"
fi

AC_MSG_CHECKING([protocols])
protocols=`echo "$with_protocols" | sed 's/,/ /g'`
if test "$protocols" = no ; then protocols= ; fi
@@ -272,6 +292,7 @@ BIRD was configured with the following options:
	Iproute2 directory:	$iproutedir
	System configuration:	$sysdesc
	Debugging:		$enable_debug
	POSIX threads:		$enable_pthreads
	Routing protocols:	$protocols
	Client:			$enable_client
EOF
+250 −57
Original line number Diff line number Diff line
@@ -146,6 +146,9 @@ options. The most important ones are:
	<tag>-s <m/name of communication socket/</tag>
	use given filename for a socket for communications with the client, default is <it/prefix/<file>/var/run/bird.ctl</file>.

	<tag>-P <m/name of PID file/</tag>
	create a PID file with given filename</file>.

	<tag>-u <m/user/</tag>
	drop privileges and use that user ID, see the next section for details.

@@ -915,62 +918,63 @@ bird>
incompatible with each other (that is to prevent you from shooting in the foot).

<descrip>
	<tag/bool/ This is a boolean type, it can have only two values, <cf/true/ and
	  <cf/false/. Boolean is the only type you can use in <cf/if/
	  statements.

	<tag/int/ This is a general integer type, you can expect it to store signed values from -2000000000
	  to +2000000000. Overflows are not checked. You can use <cf/0x1234/ syntax to write hexadecimal values.

	<tag/pair/ This is a pair of two short integers. Each component can have values from 0 to
	  65535. Literals of this type are written as <cf/(1234,5678)/. The same syntax can also be
	  used to construct a pair from two arbitrary integer expressions (for example <cf/(1+2,a)/).

	<tag/quad/ This is a dotted quad of numbers used to represent
	  router IDs (and others).  Each component can have a value
	  from 0 to 255. Literals of this type are written like IPv4
	  addresses.

	<tag/string/ This is a string of characters. There are no ways
	  to modify strings in filters. You can pass them between
	  functions, assign them to variables of type <cf/string/,
	  print such variables, use standard string comparison
	  operations (e.g. <cf/=, !=, &lt;, &gt;, &lt;=, &gt;=/), but
	  you can't concatenate two strings. String literals are
	  written as <cf/"This is a string constant"/. Additionaly
	  matching <cf/&tilde;/ operator could be used to match a
	  string value against a shell pattern (represented also as a
	  string).

	<tag/ip/ This type can hold a single IP address. Depending on the compile-time configuration of BIRD you are using, it
	  is either an IPv4 or IPv6 address. IP addresses are written in the standard notation (<cf/10.20.30.40/ or <cf/fec0:3:4::1/). You can apply special operator <cf>.mask(<M>num</M>)</cf>
	  on values of type ip. It masks out all but first <cf><M>num</M></cf> bits from the IP
	  address. So <cf/1.2.3.4.mask(8) = 1.0.0.0/ is true.

	<tag/prefix/ This type can hold a network prefix consisting of IP address and prefix length. Prefix literals are written as
	  <cf><M>ipaddress</M>/<M>pxlen</M></cf>, or
	<tag/bool/ This is a boolean type, it can have only two values,
	  <cf/true/ and <cf/false/. Boolean is the only type you can use in
	  <cf/if/ statements.

	<tag/int/ This is a general integer type, you can expect it to store
	  signed values from -2000000000 to +2000000000. Overflows are not
	  checked. You can use <cf/0x1234/ syntax to write hexadecimal values.

	<tag/pair/ This is a pair of two short integers. Each component can have
	  values from 0 to 65535. Literals of this type are written as
	  <cf/(1234,5678)/. The same syntax can also be used to construct a pair
	  from two arbitrary integer expressions (for example <cf/(1+2,a)/).

	<tag/quad/ This is a dotted quad of numbers used to represent router IDs
	  (and others).  Each component can have a value from 0 to 255. Literals
	  of this type are written like IPv4 addresses.

	<tag/string/ This is a string of characters. There are no ways to modify
	  strings in filters. You can pass them between functions, assign them
	  to variables of type <cf/string/, print such variables, use standard
	  string comparison operations (e.g. <cf/=, !=, &lt;, &gt;, &lt;=,
	  &gt;=/), but you can't concatenate two strings. String literals are
	  written as <cf/"This is a string constant"/. Additionaly matching
	  <cf/&tilde;/ operator could be used to match a string value against a
	  shell pattern (represented also as a string).

	<tag/ip/ This type can hold a single IP address. Depending on the
	  compile-time configuration of BIRD you are using, it is either an IPv4
	  or IPv6 address. IP addresses are written in the standard notation
	  (<cf/10.20.30.40/ or <cf/fec0:3:4::1/). You can apply special
	  operator <cf>.mask(<M>num</M>)</cf> on values of type ip. It masks out
	  all but first <cf><M>num</M></cf> bits from the IP address. So
	  <cf/1.2.3.4.mask(8) = 1.0.0.0/ is true.

	<tag/prefix/ This type can hold a network prefix consisting of IP
	  address and prefix length. Prefix literals are written
	  as <cf><M>ipaddress</M>/<M>pxlen</M></cf>, or
	  <cf><m>ipaddress</m>/<m>netmask</m></cf>. There are two special
	  operators on prefixes:
	  <cf/.ip/ which extracts the IP address from the pair, and <cf/.len/, which separates prefix
	  length from the pair. So <cf>1.2.0.0/16.pxlen = 16</cf> is true.

	<tag/ec/ This is a specialized type used to represent BGP
	  extended community values. It is essentially a 64bit value,
	  literals of this type are usually written as <cf>(<m/kind/,
	  <m/key/, <m/value/)</cf>, where <cf/kind/ is a kind of
	  extended community (e.g. <cf/rt/ / <cf/ro/ for a route
	  target / route origin communities), the format and possible
	  values of <cf/key/ and <cf/value/ are usually integers, but
	  operators on prefixes: <cf/.ip/ which extracts the IP address from the
	  pair, and <cf/.len/, which separates prefix length from the
	  pair. So <cf>1.2.0.0/16.pxlen = 16</cf> is true.

	<tag/ec/ This is a specialized type used to represent BGP extended
	  community values. It is essentially a 64bit value, literals of this
	  type are usually written as <cf>(<m/kind/, <m/key/, <m/value/)</cf>,
	  where <cf/kind/ is a kind of extended community (e.g. <cf/rt/ /
	  <cf/ro/ for a route target / route origin communities), the format and
	  possible values of <cf/key/ and <cf/value/ are usually integers, but
	  it depends on the used kind. Similarly to pairs, ECs can be
	  constructed using expressions for <cf/key/ and
	  <cf/value/ parts, (e.g. <cf/(ro, myas, 3*10)/, where
	  <cf/myas/ is an integer variable).
	  constructed using expressions for <cf/key/ and <cf/value/ parts,
	  (e.g. <cf/(ro, myas, 3*10)/, where <cf/myas/ is an integer variable).
 
	<tag/int|pair|quad|ip|prefix|ec|enum set/
	  Filters recognize four types of sets. Sets are similar to strings: you can pass them around
	  but you can't modify them. Literals of type <cf>int set</cf> look like <cf>
	  [ 1, 2, 5..7 ]</cf>. As you can see, both simple values and ranges are permitted in
	  sets.
	<tag/int|pair|quad|ip|prefix|ec|enum set/ Filters recognize four types
	  of sets. Sets are similar to strings: you can pass them around but you
	  can't modify them. Literals of type <cf>int set</cf> look like <cf> [
	  1, 2, 5..7 ]</cf>. As you can see, both simple values and ranges are
	  permitted in sets.

	  For pair sets, expressions like <cf/(123,*)/ can be used to denote ranges (in
	  that case <cf/(123,0)..(123,65535)/). You can also use <cf/(123,5..100)/ for range
@@ -1267,6 +1271,178 @@ undefined value is regarded as empty clist for most purposes.

<chapt>Protocols

<sect><label id="sect-bfd">BFD

<sect1>Introduction

<p>Bidirectional Forwarding Detection (BFD) is not a routing protocol itself, it
is an independent tool providing liveness and failure detection. Routing
protocols like OSPF and BGP use integrated periodic "hello" messages to monitor
liveness of neighbors, but detection times of these mechanisms are high (e.g. 40
seconds by default in OSPF, could be set down to several seconds). BFD offers
universal, fast and low-overhead mechanism for failure detection, which could be
attached to any routing protocol in an advisory role.

<p>BFD consists of mostly independent BFD sessions. Each session monitors an
unicast bidirectional path between two BFD-enabled routers. This is done by
periodically sending control packets in both directions. BFD does not handle
neighbor discovery, BFD sessions are created on demand by request of other
protocols (like OSPF or BGP), which supply appropriate information like IP
addresses and associated interfaces. When a session changes its state, these
protocols are notified and act accordingly (e.g. break an OSPF adjacency when
the BFD session went down).

<p>BIRD implements basic BFD behavior as defined in
RFC 5880<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc5880.txt">
(some advanced features like the echo mode or authentication are not implemented),
IP transport for BFD as defined in
RFC 5881<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc5881.txt"> and
RFC 5883<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc5883.txt">
and interaction with client protocols as defined in
RFC 5882<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc5882.txt">.

<p>Note that BFD implementation in BIRD is currently a new feature in
development, expect some rough edges and possible UI and configuration changes
in the future. Also note that we currently support at most one protocol instance.

<sect1>Configuration

<p>BFD configuration consists mainly of multiple definitions of interfaces.
Most BFD config options are session specific. When a new session is requested
and dynamically created, it is configured from one of these definitions. For
sessions to directly connected neighbors, <cf/interface/ definitions are chosen
based on the interface associated with the session, while <cf/multihop/
definition is used for multihop sessions. If no definition is relevant, the
session is just created with the default configuration. Therefore, an empty BFD
configuration is often sufficient.

<p>Note that to use BFD for other protocols like OSPF or BGP, these protocols
also have to be configured to request BFD sessions, usually by <cf/bfd/ option.

<p>Some of BFD session options require <m/time/ value, which has to be specified
with the appropriate unit: <m/num/ <cf/s/|<cf/ms/|<cf/us/. Although microseconds
are allowed as units, practical minimum values are usually in order of tens of
milliseconds.

<code>
protocol bfd [&lt;name&gt;] {
	interface &lt;interface pattern&gt; {
		interval &lt;time&gt;;
		min rx interval &lt;time&gt;;
		min tx interval &lt;time&gt;;
		idle tx interval &lt;time&gt;;
		multiplier &lt;num&gt;;
		passive &lt;switch&gt;;
	};
	multihop {
		interval &lt;time&gt;;
		min rx interval &lt;time&gt;;
		min tx interval &lt;time&gt;;
		idle tx interval &lt;time&gt;;
		multiplier &lt;num&gt;;
		passive &lt;switch&gt;;
	};
	neighbor &lt;ip&gt; [dev "&lt;interface&gt;"] [local &lt;ip&gt;] [multihop &lt;switch&gt;];
}
</code>

<descrip>
	<tag>interface <m/pattern [, ...]/  { <m/options/ }</tag>
	Interface definitions allow to specify options for sessions associated
	with such interfaces and also may contain interface specific options.
	See <ref id="dsc-iface" name="interface"> common option for a detailed
	description of interface patterns. Note that contrary to the behavior of
	<cf/interface/ definitions of other protocols, BFD protocol would accept
	sessions (in default configuration) even on interfaces not covered by
	such definitions.

	<tag>multihop { <m/options/ }</tag>
	Multihop definitions allow to specify options for multihop BFD sessions,
	in the same manner as <cf/interface/ definitions are used for directly
	connected sessions. Currently only one such definition (for all multihop
	sessions) could be used.

	<tag>neighbor <m/ip/ [dev "<m/interface/"] [local <m/ip/] [multihop <m/switch/]</tag>
	BFD sessions are usually created on demand as requested by other
	protocols (like OSPF or BGP). This option allows to explicitly add
	a BFD session to the specified neighbor regardless of such requests.
	
	The session is identified by the IP address of the neighbor, with
	optional specification of used interface and local IP.  By default
	the neighbor must be directly connected, unless the the session is
	configured as multihop. Note that local IP must be specified for
	multihop sessions.
</descrip>

<p>Session specific options (part of <cf/interface/ and <cf/multihop/ definitions):

<descrip>
	<tag>interval <m/time/</tag>
	BFD ensures availability of the forwarding path associated with the
	session by periodically sending BFD control packets in both
	directions. The rate of such packets is controlled by two options,
	<cf/min rx interval/ and <cf/min tx interval/ (see below). This option
	is just a shorthand to set both of these options together.

	<tag>min rx interval <m/time/</tag>
	This option specifies the minimum RX interval, which is announced to the
	neighbor and used there to limit the neighbor's rate of generated BFD
	control packets. Default: 10 ms.

	<tag>min tx interval <m/time/</tag>
	This option specifies the desired TX interval, which controls the rate
	of generated BFD control packets (together with <cf/min rx interval/
	announced by the neighbor). Note that this value is used only if the BFD
	session is up, otherwise the value of <cf/idle tx interval/ is used
	instead. Default: 100 ms.

	<tag>idle tx interval <m/time/</tag>
	In order to limit unnecessary traffic in cases where a neighbor is not
	available or not running BFD, the rate of generated BFD control packets
	is lower when the BFD session is not up. This option specifies the
	desired TX interval in such cases instead of <cf/min tx interval/.
	Default: 1 s.

	<tag>multiplier <m/num/</tag>
	Failure detection time for BFD sessions is based on established rate of
	BFD control packets (<cf>min rx/tx interval</cf>) multiplied by this
	multiplier, which is essentially (ignoring jitter) a number of missed
	packets after which the session is declared down. Note that rates and
	multipliers could be different in each direction of a BFD session.
	Default: 5.

	<tag>passive <m/switch/</tag>
	Generally, both BFD session endpoinds try to establish the session by
	sending control packets to the other side. This option allows to enable
	passive mode, which means that the router does not send BFD packets
	until it has received one from the other side. Default: disabled.
</descrip>

<sect1>Example

<p><code>
protocol bfd {
	interface "eth*" {
		min rx interval 20 ms;
		min tx interval 50 ms;
		idle tx interval 300 ms;
	};
	interface "gre*" {
		interval 200 ms;
		multiplier 10;
		passive;
	};
	multihop {
		interval 200 ms;
		multiplier 10;
	};

	neighbor 192.168.1.10;
	neighbor 192.168.2.2 dev "eth2";
	neighbor 192.168.10.1 local 192.168.1.1 multihop;
}
</code>

<sect>BGP

<p>The Border Gateway Protocol is the routing protocol used for backbone
@@ -1281,8 +1457,8 @@ AS). Each AS is a part of the network with common management and
common routing policy. It is identified by a unique 16-bit number
(ASN).  Routers within each AS usually exchange AS-internal routing
information with each other using an interior gateway protocol (IGP,
such as OSPF or RIP). Boundary routers at the border of
the AS communicate global (inter-AS) network reachability information with
such as OSPF or RIP). Boundary routers at the border of the AS
communicate global (inter-AS) network reachability information with
their neighbors in the neighboring AS'es via exterior BGP (eBGP) and
redistribute received information to other routers in the AS via
interior BGP (iBGP).
@@ -1436,6 +1612,14 @@ for each neighbor using the following configuration parameters:
	as an IGP routing table. Default: the same as the table BGP is
	connected to.

	<tag>bfd <M>switch</M></tag>
	BGP could use BFD protocol as an advisory mechanism for neighbor
	liveness and failure detection. If enabled, BIRD setups a BFD session
	for the BGP neighbor and tracks its liveness by it. This has an
	advantage of an order of magnitude lower detection times in case of
	failure. Note that BFD protocol also has to be configured, see
	<ref id="sect-bfd" name="BFD"> section for details. Default: disabled.

	<tag>ttl security <m/switch/</tag> Use GTSM (RFC 5082 - the
	generalized TTL security mechanism). GTSM protects against
	spoofed packets by ignoring received packets with a smaller
@@ -2020,6 +2204,7 @@ protocol ospf &lt;name&gt; {
			real broadcast &lt;switch&gt;;
			ptp netmask &lt;switch&gt;;
			check link &lt;switch&gt;;
			bfd &lt;switch&gt;;
			ecmp weight &lt;num&gt;;
			ttl security [&lt;switch&gt;; | tx only]
			tx class|dscp &lt;num&gt;;
@@ -2294,6 +2479,14 @@ protocol ospf &lt;name&gt; {
	 prefix) is propagated. It is possible that some hardware
	 drivers or platforms do not implement this feature. Default value is no.

	<tag>bfd <M>switch</M></tag>
	OSPF could use BFD protocol as an advisory mechanism for neighbor
	liveness and failure detection. If enabled, BIRD setups a BFD session
	for each OSPF neighbor and tracks its liveness by it. This has an
	advantage of an order of magnitude lower detection times in case of
	failure. Note that BFD protocol also has to be configured, see
	<ref id="sect-bfd" name="BFD"> section for details. Default value is no.

	<tag>ttl security [<m/switch/ | tx only]</tag>
	 TTL security is a feature that protects routing protocols
	 from remote spoofed packets by using TTL 255 instead of TTL 1
+49 −80
Original line number Diff line number Diff line
@@ -59,41 +59,35 @@ adata_empty(struct linpool *pool, int l)
}

static void
pm_format(struct f_path_mask *p, byte *buf, unsigned int size)
pm_format(struct f_path_mask *p, buffer *buf)
{
  byte *end = buf + size - 16;
  buffer_puts(buf, "[= ");

  while (p)
  {
      if (buf > end)
	{
	  strcpy(buf, " ...");
	  return;
	}

    switch(p->kind)
    {
    case PM_ASN:
	  buf += bsprintf(buf, " %u", p->val);
      buffer_print(buf, "%u ", p->val);
      break;

    case PM_QUESTION:
	  buf += bsprintf(buf, " ?");
      buffer_puts(buf, "? ");
      break;

    case PM_ASTERISK:
	  buf += bsprintf(buf, " *");
      buffer_puts(buf, "* ");
      break;

    case PM_ASN_EXPR:
	  buf += bsprintf(buf, " %u", f_eval_asn((struct f_inst *) p->val));
      buffer_print(buf, "%u ", f_eval_asn((struct f_inst *) p->val));
      break;
    }

    p = p->next;
  }

  *buf = 0;
  buffer_puts(buf, "=]");
}

static inline int
@@ -103,7 +97,7 @@ int_cmp(int i1, int i2)
}

static inline int
uint_cmp(unsigned int i1, unsigned int i2)
uint_cmp(uint i1, uint i2)
{
  return (int)(i1 > i2) - (int)(i1 < i2);
}
@@ -437,60 +431,32 @@ val_in_range(struct f_val v1, struct f_val v2)
  return CMP_ERROR;
}

static void
tree_node_print(struct f_tree *t, char **sep)
{
  if (t == NULL)
    return;

  tree_node_print(t->left, sep);

  logn(*sep);
  val_print(t->from);
  if (val_compare(t->from, t->to) != 0)
    {
      logn( ".." );
      val_print(t->to);
    }
  *sep = ", ";

  tree_node_print(t->right, sep);
}

static void
tree_print(struct f_tree *t)
{
  char *sep = "";
  logn( "[" );
  tree_node_print(t, &sep);
  logn( "] " );
}

/*
 * val_print - format filter value
 * val_format - format filter value
 */
void
val_print(struct f_val v)
val_format(struct f_val v, buffer *buf)
{
  char buf2[1024];
  switch (v.type) {
  case T_VOID: logn("(void)"); return;
  case T_BOOL: logn(v.val.i ? "TRUE" : "FALSE"); return;
  case T_INT: logn("%d", v.val.i); return;
  case T_STRING: logn("%s", v.val.s); return;
  case T_IP: logn("%I", v.val.px.ip); return;
  case T_PREFIX: logn("%I/%d", v.val.px.ip, v.val.px.len); return;
  case T_PAIR: logn("(%d,%d)", v.val.i >> 16, v.val.i & 0xffff); return;
  case T_QUAD: logn("%R", v.val.i); return;
  case T_EC: ec_format(buf2, v.val.ec); logn("%s", buf2); return;
  case T_PREFIX_SET: trie_print(v.val.ti); return;
  case T_SET: tree_print(v.val.t); return;
  case T_ENUM: logn("(enum %x)%d", v.type, v.val.i); return;
  case T_PATH: as_path_format(v.val.ad, buf2, 1000); logn("(path %s)", buf2); return;
  case T_CLIST: int_set_format(v.val.ad, 1, -1, buf2, 1000); logn("(clist %s)", buf2); return;
  case T_ECLIST: ec_set_format(v.val.ad, -1, buf2, 1000); logn("(eclist %s)", buf2); return;
  case T_PATH_MASK: pm_format(v.val.path_mask, buf2, 1000); logn("(pathmask%s)", buf2); return;
  default: logn( "[unknown type %x]", v.type ); return;
  switch (v.type)
  {
  case T_VOID:	buffer_puts(buf, "(void)"); return;
  case T_BOOL:	buffer_puts(buf, v.val.i ? "TRUE" : "FALSE"); return;
  case T_INT:	buffer_print(buf, "%d", v.val.i); return;
  case T_STRING: buffer_print(buf, "%s", v.val.s); return;
  case T_IP:	buffer_print(buf, "%I", v.val.px.ip); return;
  case T_PREFIX: buffer_print(buf, "%I/%d", v.val.px.ip, v.val.px.len); return;
  case T_PAIR:	buffer_print(buf, "(%d,%d)", v.val.i >> 16, v.val.i & 0xffff); return;
  case T_QUAD:	buffer_print(buf, "%R", v.val.i); return;
  case T_EC:	ec_format(buf2, v.val.ec); buffer_print(buf, "%s", buf2); return;
  case T_PREFIX_SET: trie_format(v.val.ti, buf); return;
  case T_SET:	tree_format(v.val.t, buf); return;
  case T_ENUM:	buffer_print(buf, "(enum %x)%d", v.type, v.val.i); return;
  case T_PATH:	as_path_format(v.val.ad, buf2, 1000); buffer_print(buf, "(path %s)", buf2); return;
  case T_CLIST:	int_set_format(v.val.ad, 1, -1, buf2, 1000); buffer_print(buf, "(clist %s)", buf2); return;
  case T_ECLIST: ec_set_format(v.val.ad, -1, buf2, 1000); buffer_print(buf, "(eclist %s)", buf2); return;
  case T_PATH_MASK: pm_format(v.val.path_mask, buf); return;
  default:	buffer_print(buf, "[unknown type %x]", v.type); return;
  }
}

@@ -498,6 +464,7 @@ static struct rte **f_rte;
static struct rta *f_old_rta;
static struct ea_list **f_tmp_attrs;
static struct linpool *f_pool;
static struct buffer f_buf;
static int f_flags;

static inline void f_rte_cow(void)
@@ -786,7 +753,7 @@ interpret(struct f_inst *what)
    break;
  case 'p':
    ONEARG;
    val_print(v1);
    val_format(v1, &f_buf);
    break;
  case '?':	/* ? has really strange error value, so we can implement if ... else nicely :-) */
    ONEARG;
@@ -804,7 +771,7 @@ interpret(struct f_inst *what)
  case P('p',','):
    ONEARG;
    if (what->a2.i == F_NOP || (what->a2.i != F_NONL && what->a1.p))
      log_commit(*L_INFO);
      log_commit(*L_INFO, &f_buf);

    switch (what->a2.i) {
    case F_QUITBIRD:
@@ -1507,7 +1474,8 @@ f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struc
  f_pool = tmp_pool;
  f_flags = flags;

  log_reset();
  LOG_BUFFER_INIT(f_buf);

  struct f_val res = interpret(filter->root);

  if (f_old_rta) {
@@ -1546,7 +1514,8 @@ f_eval(struct f_inst *expr, struct linpool *tmp_pool)
  f_rte = NULL;
  f_pool = tmp_pool;

  log_reset();
  LOG_BUFFER_INIT(f_buf);

  return interpret(expr);
}

Loading