Commit 0aeac9cb authored by Ondřej Zajíček's avatar Ondřej Zajíček

Merge commit 'origin/bfd'

parents 8931425d 7c9930f9
......@@ -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"
......
......@@ -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 */
......
......@@ -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
......
This diff is collapsed.
......@@ -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)
{
switch(p->kind)
{
if (buf > end)
{
strcpy(buf, " ...");
return;
}
switch(p->kind)
{
case PM_ASN:
buf += bsprintf(buf, " %u", p->val);
break;
case PM_QUESTION:
buf += bsprintf(buf, " ?");
break;
case PM_ASN:
buffer_print(buf, "%u ", p->val);
break;
case PM_ASTERISK:
buf += bsprintf(buf, " *");
break;
case PM_QUESTION:
buffer_puts(buf, "? ");
break;
case PM_ASN_EXPR:
buf += bsprintf(buf, " %u", f_eval_asn((struct f_inst *) p->val));
break;
}
case PM_ASTERISK:
buffer_puts(buf, "* ");
break;
p = p->next;
case PM_ASN_EXPR:
buffer_print(buf, "%u ", f_eval_asn((struct f_inst *) p->val));
break;
}
*buf = 0;
p = p->next;
}
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);
}
......
......@@ -78,12 +78,13 @@ struct f_inst *f_generate_roa_check(struct symbol *sym, struct f_inst *prefix, s
struct f_tree *build_tree(struct f_tree *);
struct f_tree *find_tree(struct f_tree *t, struct f_val val);
int same_tree(struct f_tree *t1, struct f_tree *t2);
void tree_format(struct f_tree *t, buffer *buf);
struct f_trie *f_new_trie(linpool *lp);
void trie_add_prefix(struct f_trie *t, ip_addr px, int plen, int l, int h);
int trie_match_prefix(struct f_trie *t, ip_addr px, int plen);
int trie_same(struct f_trie *t1, struct f_trie *t2);
void trie_print(struct f_trie *t);
void trie_format(struct f_trie *t, buffer *buf);
void fprefix_get_bounds(struct f_prefix *px, int *l, int *h);
......@@ -118,7 +119,8 @@ int i_same(struct f_inst *f1, struct f_inst *f2);
int val_compare(struct f_val v1, struct f_val v2);
int val_same(struct f_val v1, struct f_val v2);
void val_print(struct f_val v);
void val_format(struct f_val v, buffer *buf);
#define F_NOP 0
#define F_NONL 1
......
......@@ -106,7 +106,7 @@ eclist el2;
print "5 = ", p2.len;
print "Delete 3: ", delete(p2, 3);
print "Filter 1-3: ", filter(p2, [1..3]);
pm1 = [= 1 2 * 3 4 5 =];
p2 = prepend( + empty +, 5 );
p2 = prepend( p2, 4 );
......
......@@ -137,3 +137,37 @@ same_tree(struct f_tree *t1, struct f_tree *t2)
return 0;
return 1;
}
static void
tree_node_format(struct f_tree *t, buffer *buf)
{
if (t == NULL)
return;
tree_node_format(t->left, buf);
val_format(t->from, buf);
if (val_compare(t->from, t->to) != 0)
{
buffer_puts(buf, "..");
val_format(t->to, buf);
}
buffer_puts(buf, ", ");
tree_node_format(t->right, buf);
}
void
tree_format(struct f_tree *t, buffer *buf)
{
buffer_puts(buf, "[");
tree_node_format(t, buf);
/* Undo last separator */
if (buf->pos[-1] != '[')
buf->pos -= 2;
buffer_puts(buf, "]");
}
......@@ -265,37 +265,37 @@ trie_same(struct f_trie *t1, struct f_trie *t2)
}
static void
trie_node_print(struct f_trie_node *t, char **sep)
trie_node_format(struct f_trie_node *t, buffer *buf)
{
if (t == NULL)
return;
if (ipa_nonzero(t->accept))
{
logn("%s%I/%d{%I}", *sep, t->addr, t->plen, t->accept);
*sep = ", ";
}
buffer_print(buf, "%I/%d{%I}, ", t->addr, t->plen, t->accept);
trie_node_print(t->c[0], sep);
trie_node_print(t->c[1], sep);
trie_node_format(t->c[0], buf);
trie_node_format(t->c[1], buf);
}
/**
* trie_print
* @t: trie to be printed
* trie_format
* @t: trie to be formatted
* @buf: destination buffer
*
* Prints the trie to the log buffer.
* Prints the trie to the supplied buffer.
*/
void
trie_print(struct f_trie *t)
trie_format(struct f_trie *t, buffer *buf)
{
char *sep = "";
logn("[");
buffer_puts(buf, "[");
if (t->zero)
{
logn("%I/%d", IPA_NONE, 0);
sep = ", ";
}
trie_node_print(&t->root, &sep);
logn("]");
buffer_print(buf, "%I/%d", IPA_NONE, 0);
trie_node_format(&t->root, buf);
/* Undo last separator */
if (buf->pos[-1] != '[')
buf->pos -= 2;
buffer_puts(buf, "]");
}
......@@ -10,6 +10,7 @@
#define _BIRD_BIRDLIB_H_
#include "timer.h"
#include "alloca.h"
/* Ugly structure offset handling macros */
......@@ -19,12 +20,14 @@
/* Utility macros */
#ifdef PARSER
#define _MIN(a,b) (((a)<(b))?(a):(b))
#define _MAX(a,b) (((a)>(b))?(a):(b))
#else
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#ifndef PARSER
#undef MIN
#undef MAX
#define MIN(a,b) _MIN(a,b)
#define MAX(a,b) _MAX(a,b)
#endif
#define ABS(a) ((a)>=0 ? (a) : -(a))
......@@ -40,24 +43,61 @@
#define IP_VERSION 6
#endif
/* Macros for gcc attributes */
#define NORET __attribute__((noreturn))
#define UNUSED __attribute__((unused))
/* Microsecond time */
typedef s64 btime;
#define _S *1000000
#define _MS *1000
#define _US *1
#define TO_S /1000000
#define TO_MS /1000
#define TO_US /1
#ifndef PARSER
#define S _S
#define MS _MS
#define US _US
#endif
/* Logging and dying */
typedef struct buffer {
byte *start;
byte *pos;
byte *end;
} buffer;
#define STACK_BUFFER_INIT(buf,size) \
do { \
buf.start = alloca(size); \
buf.pos = buf.start; \
buf.end = buf.start + size; \
} while(0)
#define LOG_BUFFER_INIT(buf) \
STACK_BUFFER_INIT(buf, LOG_BUFFER_SIZE)
#define LOG_BUFFER_SIZE 1024
struct rate_limit {
bird_clock_t timestamp;
int count;
};
#define log log_msg
void log_reset(void);
void log_commit(int class);
void log_commit(int class, buffer *buf);
void log_msg(char *msg, ...);
void log_rl(struct rate_limit *rl, char *msg, ...);
void logn(char *msg, ...);
void die(char *msg, ...) NORET;
void bug(char *msg, ...) NORET;
......
#define BUFFER(type) struct { type *data; uint used, size; }
#define BUFFER_SIZE(v) ((v).size * sizeof(* (v).data))
#define BUFFER_INIT(v,pool,isize) \
({ \
(v).used = 0; \
(v).size = (isize); \
(v).data = mb_alloc(pool, BUFFER_SIZE(v)); \
})
#define BUFFER_SET(v,nsize) \
({ \
(v).used = (nsize); \
if ((v).used > (v).size) \
buffer_realloc((void **) &((v).data), &((v).size), (v).used, sizeof(* (v).data)); \
})
#define BUFFER_INC(v,step) \
({ \
uint _o = (v).used; \
BUFFER_SET(v, (v).used + (step)); \
(v).data + _o; \
})
#define BUFFER_DEC(v,step) ({ (v).used -= (step); })
#define BUFFER_PUSH(v) (*BUFFER_INC(v,1))
#define BUFFER_POP(v) BUFFER_DEC(v,1)
#define BUFFER_FLUSH(v) ({ (v).used = 0; })
#define HASH(type) struct { type **data; uint count, order; }
#define HASH_TYPE(v) typeof(** (v).data)
#define HASH_SIZE(v) (1 << (v).order)
#define HASH_MASK(v) ((1 << (v).order)-1)
#define HASH_INIT(v,pool,init_order) \
({ \
(v).count = 0; \
(v).order = (init_order); \
(v).data = mb_allocz(pool, HASH_SIZE(v) * sizeof(* (v).data)); \
})
#define HASH_FIND(v,id,key...) \
({ \
uint _h = id##_FN((key)) & HASH_MASK(v); \
HASH_TYPE(v) *_n = (v).data[_h]; \
while (_n && !id##_EQ(id##_KEY(_n), (key))) \
_n = id##_NEXT(_n); \
_n; \
})
#define HASH_INSERT(v,id,node) \
({ \
uint _h = id##_FN(id##_KEY((node))) & HASH_MASK(v); \
HASH_TYPE(v) **_nn = (v).data + _h; \
id##_NEXT(node) = *_nn; \
*_nn = node; \
(v).count++; \
})
#define HASH_DO_REMOVE(v,id,_nn) \
({ \
HASH_TYPE(v) *_n = *_nn; \
if (_n) \
{ \
*_nn = id##_NEXT(_n); \
(v).count--; \
} \
_n; \
})
#define HASH_DELETE(v,id,key...) \
({ \
uint _h = id##_FN((key)) & HASH_MASK(v); \
HASH_TYPE(v) **_nn = (v).data + _h; \
\
while ((*_nn) && !id##_EQ(id##_KEY((*_nn)), (key))) \
_nn = &(id##_NEXT((*_nn))); \
\
HASH_DO_REMOVE(v,id,_nn); \
})
#define HASH_REMOVE(v,id,node) \
({ \
uint _h = id##_FN(id##_KEY((node))) & HASH_MASK(v); \
HASH_TYPE(v) **_nn = (v).data + _h; \
\
while ((*_nn) && (*_nn != (node))) \
_nn = &(id##_NEXT((*_nn))); \
\
HASH_DO_REMOVE(v,id,_nn); \
})
#define HASH_REHASH(v,id,pool,step) \
({ \
HASH_TYPE(v) *_n, *_n2, **_od; \
uint _i, _s; \
\
_s = HASH_SIZE(v); \
_od = (v).data; \
(v).count = 0; \
(v).order += (step); \
(v).data = mb_allocz(pool, HASH_SIZE(v) * sizeof(* (v).data)); \
\
for (_i = 0; _i < _s; _i++) \
for (_n = _od[_i]; _n && (_n2 = id##_NEXT(_n), 1); _n = _n2) \
HASH_INSERT(v, id, _n); \
\
mb_free(_od); \
})
#define HASH_DEFINE_REHASH_FN(id, type) \
static void id##_REHASH_FN(void *v, pool *p, int step) \
{ HASH_REHASH(* (HASH(type) *) v, id, p, step); }
#define HASH_TRY_REHASH_UP(v,id,pool) \
({ \
if (((v).order < id##_REHASH_MAX) && ((v).count > HASH_SIZE(v))) \
id##_REHASH_FN(&v, pool, 1); \
})
#define HASH_TRY_REHASH_DOWN(v,id,pool) \
({ \
if (((v).order > id##_REHASH_MIN) && ((v).count < HASH_SIZE(v)/2)) \
id##_REHASH_FN(&v, pool, -1); \
})
#define HASH_WALK(v,next,n) \
do { \
HASH_TYPE(v) *n; \
uint _i; \
uint _s = HASH_SIZE(v); \
for (_i = 0; _i < _s; _i++) \
for (n = (v).data[_i]; n; n = n->next)
#define HASH_WALK_END } while (0)
#define HASH_WALK_DELSAFE(v,next,n) \
do { \
HASH_TYPE(v) *n, *_next; \
uint _i; \
uint _s = HASH_SIZE(v); \
for (_i = 0; _i < _s; _i++) \
for (n = (v).data[_i]; n && (_next = n->next, 1); n = _next)
#define HASH_WALK_DELSAFE_END } while (0)
/*
* UCW Library -- Universal Heap Macros
*
* (c) 2001 Martin Mares <mj@ucw.cz>
* (c) 2005 Tomas Valla <tom@ucw.cz>
*
* This software may be freely distributed and used according to the terms
* of the GNU Lesser General Public License.
*/
/**
* [[intro]]
* Introduction
* ------------
*
* Binary heap is a simple data structure, which for example supports efficient insertions, deletions
* and access to the minimal inserted item. We define several macros for such operations.
* Note that because of simplicity of heaps, we have decided to define direct macros instead
* of a <<generic:,macro generator>> as for several other data structures in the Libucw.
*
* A heap is represented by a number of elements and by an array of values. Beware that we
* index this array from one, not from zero as do the standard C arrays.
*
* Most macros use these parameters:
*
* - @type - the type of elements
* - @num - a variable (signed or unsigned integer) with the number of elements
* - @heap - a C array of type @type; the heap is stored in `heap[1] .. heap[num]`; `heap[0]` is unused
* - @less - a callback to compare two element values; `less(x, y)` shall return a non-zero value iff @x is lower than @y
* - @swap - a callback to swap two array elements; `swap(heap, i, j, t)` must swap `heap[i]` with `heap[j]` with possible help of temporary variable @t (type @type).
*
* A valid heap must follow these rules:
*
* - `num >= 0`
* - `heap[i] >= heap[i / 2]` for each `i` in `[2, num]`
*
* The first element `heap[1]` is always lower or equal to all other elements.
*
* [[macros]]
* Macros
* ------