Commit 1ec52253 authored by Ondřej Zajíček's avatar Ondřej Zajíček

BFD protocol, ready for release.

Supports OSPF and BGP and also statically configured sessions.
parent 0e175f9f
......@@ -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"
......
......@@ -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=bfd,bgp,ospf,pipe,radv,rip,static
proto_radv=radv
else
ip=ipv4
SUFFIX=""
all_protocols=bfd,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,12 +83,29 @@ 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)
BIRD_CHECK_GCC_OPTION(bird_cv_c_option_fno_strict_overflow, -fno-strict-overflow)
CFLAGS="$CFLAGS -pthread -Wall -Wstrict-prototypes -Wno-parentheses"
CFLAGS="$CFLAGS -Wall -Wstrict-prototypes -Wno-parentheses"
BIRD_ADD_GCC_OPTION(bird_cv_c_option_wno_pointer_sign, -Wno-pointer-sign)
BIRD_ADD_GCC_OPTION(bird_cv_c_option_fno_strict_aliasing, -fno-strict-aliasing)
BIRD_ADD_GCC_OPTION(bird_cv_c_option_fno_strict_overflow, -fno-strict-overflow)
......@@ -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.
......@@ -24,6 +24,8 @@
#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
......
......@@ -276,7 +276,7 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
ip_ntox(va_arg(args, ip_addr), ipbuf);
else {
ip_ntop(va_arg(args, ip_addr), ipbuf);
if (field_width > 0)
if (field_width == 1)
field_width = STD_ADDRESS_P_LENGTH;
}
s = ipbuf;
......
......@@ -681,6 +681,9 @@ proto_build(struct protocol *p)
}
}
/* FIXME: convert this call to some protocol hook */
extern void bfd_init_all(void);
/**
* protos_build - build a protocol list
*
......@@ -718,8 +721,10 @@ protos_build(void)
#ifdef CONFIG_BGP
proto_build(&proto_bgp);
#endif
// XXX
#ifdef CONFIG_BFD
proto_build(&proto_bfd);
bfd_init_all();
#endif
proto_pool = rp_new(&root_pool, "Protocols");
proto_flush_event = ev_new(proto_pool);
......
This diff is collapsed.
......@@ -20,6 +20,7 @@
#include "lib/socket.h"
#include "lib/string.h"
#include "nest/bfd.h"
#include "io.h"
......@@ -33,19 +34,23 @@
#define BFD_DEFAULT_MULTIPLIER 5
struct bfd_iface_config;
struct bfd_config
{
struct proto_config c;
list neigh_list; /* List of struct bfd_neighbor */
list patt_list; /* List of iface configs (struct bfd_iface_config) */
list neigh_list; /* List of configured neighbors (struct bfd_neighbor) */
struct bfd_iface_config *multihop; /* Multihop pseudoiface config */
};
struct bfd_session_config
struct bfd_iface_config
{
struct iface_patt i;
u32 min_rx_int;
u32 min_tx_int;
u32 idle_tx_int;
u8 multiplier;
u8 multihop;
u8 passive;
};
......@@ -55,9 +60,12 @@ struct bfd_neighbor
ip_addr addr;
ip_addr local;
struct iface *iface;
struct bfd_session_config *opts;
struct bfd_session *session;
struct neighbor *neigh;
struct bfd_request *req;
u8 multihop;
u8 active;
};
struct bfd_proto
......@@ -66,6 +74,7 @@ struct bfd_proto
struct birdloop *loop;
pool *tpool;
pthread_spinlock_t lock;
node bfd_node;
slab *session_slab;
HASH(struct bfd_session) session_hash_id;
......@@ -77,25 +86,31 @@ struct bfd_proto
sock *rx_1;
sock *rx_m;
list sock_list;
list iface_list;
};
struct bfd_socket
struct bfd_iface
{
node n;
ip_addr local;
struct iface *iface;
struct bfd_iface_config *cf;
struct bfd_proto *bfd;
sock *sk;
u32 uc;
u8 changed;
};
struct bfd_session
{
node n;
ip_addr addr; /* Address of session */
struct bfd_iface *ifa; /* Iface associated with session */
struct bfd_session *next_id; /* Next in bfd.session_hash_id */
struct bfd_session *next_ip; /* Next in bfd.session_hash_ip */
struct bfd_proto *bfd;
u8 opened;
u8 opened_unused;
u8 passive;
u8 poll_active;
u8 poll_scheduled;
......@@ -123,7 +138,9 @@ struct bfd_session
timer2 *tx_timer; /* Periodic control packet timer */
timer2 *hold_timer; /* Timer for session down detection time */
struct bfd_socket *bsock; /* Socket associated with session */
list request_list; /* List of client requests (struct bfd_request) */
bird_clock_t last_state_change; /* Time of last state change */
u8 notify_running; /* 1 if notify hooks are running */
};
......@@ -168,10 +185,7 @@ void bfd_show_sessions(struct proto *P);
/* packets.c */
void bfd_send_ctl(struct bfd_proto *p, struct bfd_session *s, int final);
sock * bfd_open_rx_sk(struct bfd_proto *p, int multihop);
struct bfd_socket * bfd_get_socket(struct bfd_proto *p, ip_addr local, struct iface *ifa);
void bfd_free_socket(struct bfd_socket *sk);
sock * bfd_open_tx_sk(struct bfd_proto *p, ip_addr local, struct iface *ifa);
#endif /* _BIRD_BFD_H_ */
......@@ -12,20 +12,21 @@ CF_HDR
CF_DEFINES
#define BFD_CFG ((struct bfd_config *) this_proto)
#define BFD_SESSION this_bfd_session
#define BFD_IFACE ((struct bfd_iface_config *) this_ipatt)
#define BFD_NEIGHBOR this_bfd_neighbor
static struct bfd_session_config *this_bfd_session;
static struct bfd_neighbor *this_bfd_neighbor;
extern struct bfd_config *bfd_cf;
CF_DECLS
CF_KEYWORDS(BFD, MIN, IDLE, RX, TX, INTERVAL, MULTIPLIER, MULTIHOP, PASSIVE,
NEIGHBOR, DEV)
CF_KEYWORDS(BFD, MIN, IDLE, RX, TX, INTERVAL, MULTIPLIER, PASSIVE,
INTERFACE, MULTIHOP, NEIGHBOR, DEV, LOCAL)
%type <iface> bfd_neigh_iface
%type <a> bfd_neigh_local
%type <i> bfd_neigh_multihop
CF_GRAMMAR
......@@ -34,12 +35,19 @@ CF_ADDTO(proto, bfd_proto)
bfd_proto_start: proto_start BFD
{
this_proto = proto_config_new(&proto_bfd, sizeof(struct bfd_config), $1);
init_list(&BFD_CFG->patt_list);
init_list(&BFD_CFG->neigh_list);
if (bfd_cf)
cf_error("Only one BFD instance allowed");
bfd_cf = BFD_CFG;
};
bfd_proto_item:
proto_item
| bfd_neighbor
| INTERFACE bfd_iface
| MULTIHOP bfd_multihop
| NEIGHBOR bfd_neighbor
;
bfd_proto_opts:
......@@ -51,38 +59,41 @@ bfd_proto:
bfd_proto_start proto_name '{' bfd_proto_opts '}';
bfd_session_start:
bfd_iface_start:
{
this_bfd_session = cfg_allocz(sizeof(struct bfd_session_config));
this_ipatt = cfg_allocz(sizeof(struct bfd_iface_config));
init_list(&this_ipatt->ipn_list);
BFD_SESSION->min_rx_int = BFD_DEFAULT_MIN_RX_INT;
BFD_SESSION->min_tx_int = BFD_DEFAULT_MIN_TX_INT;
BFD_SESSION->idle_tx_int = BFD_DEFAULT_IDLE_TX_INT;
BFD_SESSION->multiplier = BFD_DEFAULT_MULTIPLIER;
BFD_IFACE->min_rx_int = BFD_DEFAULT_MIN_RX_INT;
BFD_IFACE->min_tx_int = BFD_DEFAULT_MIN_TX_INT;
BFD_IFACE->idle_tx_int = BFD_DEFAULT_IDLE_TX_INT;
BFD_IFACE->multiplier = BFD_DEFAULT_MULTIPLIER;
};
bfd_session_item:
INTERVAL expr_us { BFD_SESSION->min_rx_int = BFD_SESSION->min_tx_int = $2; }
| MIN RX INTERVAL expr_us { BFD_SESSION->min_rx_int = $4; }
| MIN TX INTERVAL expr_us { BFD_SESSION->min_tx_int = $4; }
| IDLE TX INTERVAL expr_us { BFD_SESSION->idle_tx_int = $4; }
| MULTIPLIER expr { BFD_SESSION->multiplier = $2; }
| MULTIHOP bool { BFD_SESSION->multihop = $2; }
| PASSIVE bool { BFD_SESSION->passive = $2; }
bfd_iface_item:
INTERVAL expr_us { BFD_IFACE->min_rx_int = BFD_IFACE->min_tx_int = $2; }
| MIN RX INTERVAL expr_us { BFD_IFACE->min_rx_int = $4; }
| MIN TX INTERVAL expr_us { BFD_IFACE->min_tx_int = $4; }
| IDLE TX INTERVAL expr_us { BFD_IFACE->idle_tx_int = $4; }
| MULTIPLIER expr { BFD_IFACE->multiplier = $2; }
| PASSIVE bool { BFD_IFACE->passive = $2; }
;
bfd_session_opts:
bfd_iface_opts:
/* empty */
| bfd_session_opts bfd_session_item ';'
| bfd_iface_opts bfd_iface_item ';'
;
bfd_session_opt_list:
bfd_iface_opt_list:
/* empty */
| '{' bfd_session_opts '}'
| '{' bfd_iface_opts '}'
;
bfd_session:
bfd_session_start bfd_session_opt_list;
bfd_iface: bfd_iface_start iface_patt_list bfd_iface_opt_list
{ add_tail(&BFD_CFG->patt_list, NODE this_ipatt); };
bfd_multihop: bfd_iface_start bfd_iface_opt_list
{ BFD_CFG->multihop = BFD_IFACE; };
bfd_neigh_iface:
......@@ -96,15 +107,26 @@ bfd_neigh_local:
| LOCAL ipa { $$ = $2; }
;
bfd_neighbor: NEIGHBOR ipa bfd_neigh_iface bfd_neigh_local bfd_session
bfd_neigh_multihop:
/* empty */ { $$ = 0; }
| MULTIHOP bool { $$ = $2; }
;
bfd_neighbor: ipa bfd_neigh_iface bfd_neigh_local bfd_neigh_multihop
{
this_bfd_neighbor = cfg_allocz(sizeof(struct bfd_neighbor));
add_tail(&BFD_CFG->neigh_list, NODE this_bfd_neighbor);
BFD_NEIGHBOR->addr = $2;
BFD_NEIGHBOR->local = $4;
BFD_NEIGHBOR->iface = $3;
BFD_NEIGHBOR->opts = BFD_SESSION;
BFD_NEIGHBOR->addr = $1;
BFD_NEIGHBOR->local = $3;
BFD_NEIGHBOR->iface = $2;
BFD_NEIGHBOR->multihop = $4;
if ($4 && $2)
cf_error("Neighbor cannot set both interface and multihop");
if ($4 && ipa_zero($3))
cf_error("Multihop neighbor requires specified local address");
};
......
......@@ -52,6 +52,9 @@ struct birdloop
};
/*
* Current thread context
*/
static pthread_key_t current_loop_key;
......@@ -74,6 +77,9 @@ birdloop_init_current(void)
}
/*
* Time clock
*/
static void times_update_alt(struct birdloop *loop);
......@@ -163,6 +169,9 @@ current_time(void)
}
/*
* Wakeup code for birdloop
*/
static void
pipe_new(int *pfds)
......@@ -244,6 +253,9 @@ wakeup_kick(struct birdloop *loop)
}
/*
* Events
*/
static inline uint
events_waiting(struct birdloop *loop)
......@@ -279,12 +291,14 @@ ev2_schedule(event *e)
}
/*
* Timers
*/
#define TIMER_LESS(a,b) ((a)->expires < (b)->expires)
#define TIMER_SWAP(heap,a,b,t) (t = heap[a], heap[a] = heap[b], heap[b] = t, \
heap[a]->index = (a), heap[b]->index = (b))
static inline uint timers_count(struct birdloop *loop)
{ return loop->timers.used - 1; }
......@@ -425,6 +439,9 @@ timers_fire(struct birdloop *loop)
}
/*
* Sockets
*/
static void
sockets_init(struct birdloop *loop)
......@@ -494,12 +511,16 @@ sk_stop(sock *s)
static inline uint sk_want_events(sock *s)
{ return (s->rx_hook ? POLLIN : 0) | ((s->ttx != s->tpos) ? POLLOUT : 0); }
/*
FIXME: this should be called from sock code
static void
sockets_update(struct birdloop *loop, sock *s)
{
if (s->index >= 0)
loop->poll_fd.data[s->index].events = sk_want_events(s);
}
*/
static void
sockets_prepare(struct birdloop *loop)
......@@ -594,17 +615,21 @@ sockets_fire(struct birdloop *loop)
}
/*
* Birdloop
*/
static void * birdloop_main(void *arg);
struct birdloop *
birdloop_new(pool *p)
birdloop_new(void)
{
/* FIXME: this init should be elsewhere and thread-safe */
static int init = 0;
if (!init)
{ birdloop_init_current(); init = 1; }
pool *p = rp_new(NULL, "Birdloop root");
struct birdloop *loop = mb_allocz(p, sizeof(struct birdloop));
loop->pool = p;
pthread_mutex_init(&loop->mutex, NULL);
......@@ -640,6 +665,12 @@ birdloop_stop(struct birdloop *loop)
die("pthread_join(): %M", rv);
}
void
birdloop_free(struct birdloop *loop)
{
rfree(loop->pool);
}
void
birdloop_enter(struct birdloop *loop)
......@@ -735,4 +766,3 @@ birdloop_main(void *arg)
}
......@@ -63,6 +63,13 @@ tm2_new_init(pool *p, void (*hook)(struct timer2 *), void *data, uint rec, uint
return t;
}
static inline void
tm2_set_max(timer2 *t, btime when)
{
if (when > t->expires)
tm2_set(t, when);
}
/*
static inline void
tm2_start_max(timer2 *t, btime after)
......@@ -78,9 +85,11 @@ void sk_stop(sock *s);
struct birdloop *birdloop_new(pool *p);
struct birdloop *birdloop_new(void);
void birdloop_start(struct birdloop *loop);
void birdloop_stop(struct birdloop *loop);
void birdloop_free(struct birdloop *loop);
void birdloop_enter(struct birdloop *loop);
void birdloop_leave(struct birdloop *loop);
void birdloop_mask_wakeups(struct birdloop *loop);
......
......@@ -62,7 +62,7 @@ bfd_format_flags(u8 flags, char *buf)
void
bfd_send_ctl(struct bfd_proto *p, struct bfd_session *s, int final)
{
sock *sk = s->bsock->sk;
sock *sk = s->ifa->sk;
struct bfd_ctl_packet *pkt = (struct bfd_ctl_packet *) sk->tbuf;
char fb[8];
......@@ -143,7 +143,7 @@ bfd_rx_hook(sock *sk, int len)
s = bfd_find_session_by_addr(p, sk->faddr);
/* FIXME: better session matching and message */
if (!s || !s->opened)
if (!s)
return 1;
}
......@@ -155,7 +155,7 @@ bfd_rx_hook(sock *sk, int len)
u32 old_tx_int = s->des_min_tx_int;
u32 old_rx_int = s->rem_min_rx_int;
s->rem_id = ntohl(pkt->snd_id);
s->rem_id= ntohl(pkt->snd_id);
s->rem_state = bfd_pkt_get_state(pkt);
s->rem_diag = bfd_pkt_get_diag(pkt);
s->rem_demand_mode = pkt->flags & BFD_FLAG_DEMAND;
......@@ -213,7 +213,7 @@ bfd_open_rx_sk(struct bfd_proto *p, int multihop)
return NULL;
}
static inline sock *
sock *
bfd_open_tx_sk(struct bfd_proto *p, ip_addr local, struct iface *ifa)
{
sock *sk = sk_new(p->tpool);
......@@ -246,32 +246,3 @@ bfd_open_tx_sk(struct bfd_proto *p, ip_addr local, struct iface *ifa)
rfree(sk);
return NULL;
}
struct bfd_socket *
bfd_get_socket(struct bfd_proto *p, ip_addr local, struct iface *ifa)
{
struct bfd_socket *sk;
WALK_LIST(sk, p->sock_list)
if (ipa_equal(sk->sk->saddr, local) && (sk->sk->iface == ifa))
return sk->uc++, sk;
sk = mb_allocz(p->tpool, sizeof(struct bfd_socket));
sk->sk = bfd_open_tx_sk(p, local, ifa);
sk->uc = 1;
add_tail(&p->sock_list, &sk->n);
return sk;
}
void
bfd_free_socket(struct bfd_socket *sk)
{
if (!sk || --sk->uc)
return;
rem_node(&sk->n);
sk_stop(sk->sk);
rfree(sk->sk);
mb_free(sk);
}
......@@ -59,8 +59,9 @@
#include "nest/iface.h"
#include "nest/protocol.h"
#include "nest/route.h"
#include "nest/locks.h"
#include "nest/bfd.h"
#include "nest/cli.h"
#include "nest/locks.h"
#include "conf/conf.h"
#include "lib/socket.h"
#include "lib/resource.h"
......@@ -76,6 +77,7 @@ static void bgp_close(struct bgp_proto *p, int apply_md5);
static void bgp_connect(struct bgp_proto *p);
static void bgp_active(struct bgp_proto *p);
static sock *bgp_setup_listen_sk(ip_addr addr, unsigned port, u32 flags);
static void bgp_update_bfd(struct bgp_proto *p, int use_bfd);
/**
......@@ -153,8 +155,12 @@ bgp_initiate(struct bgp_proto *p)
if (rv < 0)
return;
if (p->cf->bfd)
bgp_update_bfd(p, p->cf->bfd);
if (p->startup_delay)
{
p->start_state = BSS_DELAY;
BGP_TRACE(D_EVENTS, "Startup delayed by %d seconds", p->startup_delay);
bgp_start_timer(p->startup_timer, p->startup_delay);
}
......@@ -765,6 +771,37 @@ bgp_neigh_notify(neighbor *n)
}
}
static void
bgp_bfd_notify(struct bfd_request *req)
{
struct bgp_proto *p = req->data;
int ps = p->p.proto_state;
if (req->down && ((ps == PS_START) || (ps == PS_UP)))
{
BGP_TRACE(D_EVENTS, "BFD session down");
bgp_store_error(p, NULL, BE_MISC, BEM_BFD_DOWN);
if (ps == PS_UP)
bgp_update_startup_delay(p);
bgp_stop(p, 0);
}
}
static void
bgp_update_bfd(struct bgp_proto *p, int use_bfd)
{
if (use_bfd && !p->bfd_req)
p->bfd_req = bfd_request_session(p->p.pool, p->cf->remote_ip, p->source_addr,
p->cf->multihop ? NULL : p->neigh->iface,
bgp_bfd_notify, p);
if (!use_bfd && p->bfd_req)
{
rfree(p->bfd_req);
p->bfd_req = NULL;
}
}
static int
bgp_reload_routes(struct proto *P)
{
......@@ -825,6 +862,7 @@ bgp_start(struct proto *P)
p->outgoing_conn.state = BS_IDLE;
p->incoming_conn.state = BS_IDLE;
p->neigh = NULL;
p->bfd_req = NULL;
rt_lock_table(p->igp_table);
......@@ -992,6 +1030,9 @@ bgp_check_config(struct bgp_config *c)
ipa_has_link_scope(c->source_addr)))
cf_error("Multihop BGP cannot be used with link-local addresses");
if (c->multihop && c->bfd && ipa_zero(c->source_addr))
cf_error("Multihop BGP with BFD requires specified source address");
/* Different default based on rs_client */
if (!c->missing_lladdr)
......@@ -1034,6 +1075,9 @@ bgp_reconfigure(struct proto *P, struct proto_config *C)
|| (old->password && new->password && !strcmp(old->password, new->password)))
&& (get_igp_table(old) == get_igp_table(new));
if (same && (p->start_state > BSS_PREPARE))
bgp_update_bfd(p, new->bfd);
/* We should update our copy of configuration ptr as old configuration will be freed */
if (same)
p->cf = new;
......@@ -1115,7 +1159,7 @@ bgp_store_error(struct bgp_proto *p, struct bgp_conn *c, u8 class, u32 code)
static char *bgp_state_names[] = { "Idle", "Connect", "Active", "OpenSent", "OpenConfirm", "Established", "Close" };
static char *bgp_err_classes[] = { "", "Error: ", "Socket: ", "Received: ", "BGP Error: ", "Automatic shutdown: ", ""};
static char *bgp_misc_errors[] = { "", "Neighbor lost", "Invalid next hop", "Kernel MD5 auth failed", "No listening socket" };
static char *bgp_misc_errors[] = { "", "Neighbor lost", "Invalid next hop", "Kernel MD5 auth failed", "No listening socket", "BFD session down" };
static char *bgp_auto_errors[] = { "", "Route limit exceeded"};
static const char *
......
......@@ -14,6 +14,7 @@
struct linpool;
struct eattr;
struct bfd_request;
struct bgp_config {
struct proto_config c;
......@@ -52,8 +53,10 @@ struct bgp_config {
unsigned error_delay_time_min; /* Time to wait after an error is detected */
unsigned error_delay_time_max;
unsigned disable_after_error; /* Disable the protocol when error is detected */
char *password; /* Password used for MD5 authentication */
struct rtable_config *igp_table; /* Table used for recursive next hop lookups */
int bfd; /* Use BFD for liveness detection */
};
#define MLL_SELF 1
......@@ -99,6 +102,7 @@ struct bgp_proto {
struct bgp_conn incoming_conn; /* Incoming connection we have neither accepted nor rejected yet */
struct object_lock *lock; /* Lock for neighbor connection */
struct neighbor *neigh; /* Neighbor entry corresponding to remote ip, NULL if multihop */
struct bfd_request *bfd_req; /* BFD request, if BFD is used */
ip_addr source_addr; /* Local address used as an advertised next hop */
rtable *igp_table; /* Table used for recursive next hop lookups */
struct event *event; /* Event for respawning and shutting process */
......@@ -287,6 +291,7 @@ void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsi
#define BEM_INVALID_NEXT_HOP 2
#define BEM_INVALID_MD5 3 /* MD5 authentication kernel request failed (possibly not supported) */
#define BEM_NO_SOCKET 4
#define BEM_BFD_DOWN 5
/* Automatic shutdown error codes */
......
......@@ -26,7 +26,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
PREFER, OLDER, MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH,
INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
SECONDARY)
SECONDARY, BFD)
CF_GRAMMAR
......@@ -110,6 +110,7 @@ bgp_proto:
| bgp_proto SECONDARY bool ';' { BGP_CFG->secondary = $3; }
| bgp_proto IGP TABLE rtable ';' { BGP_CFG->igp_table = $4; }
| bgp_proto TTL SECURITY bool ';' { BGP_CFG->ttl_security = $4; }
| bgp_proto BFD bool ';' { BGP_CFG->bfd = $3; cf_check_bfd($3); }
;
CF_ADDTO(dynamic_attr, BGP_ORIGIN
......
......@@ -309,6 +309,7 @@ ospf_iface_item:
| TX PRIORITY expr { OSPF_PATT->tx_priority = $3; }
| TTL SECURITY bool { OSPF_PATT->ttl_security = $3; }
| TTL SECURITY TX ONLY { OSPF_PATT->ttl_security = 2; }
| BFD bool { OSPF_PATT->bfd = $2; cf_check_bfd($2); }
| password_list
;
......