diff --git a/doc/bird.sgml b/doc/bird.sgml
index 8548c9c6..b965da87 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -1955,6 +1955,7 @@ milliseconds.
protocol bfd [<name>] {
+ accept [ipv4|ipv6] [direct|multihop];
interface <interface pattern> {
interval <time>;
min rx interval <time>;
@@ -1989,6 +1990,14 @@ protocol bfd [<name>] {
+ accept [ipv4|ipv6] [direct|multihop]
+ A BFD protocol instance accepts (by default) all BFD session requests
+ (with regard to VRF restrictions, see above). This option controls
+ whether IPv4 / IPv6 and direct / multihop session requests are accepted
+ (and which listening sockets are opened). It can be used, for example,
+ to configure separate BFD protocol instances for IPv4 and for IPv6
+ sessions.
+
interface
Interface definitions allow to specify options for sessions associated
with such interfaces and also may contain interface specific options.
diff --git a/proto/bfd/bfd.c b/proto/bfd/bfd.c
index a3e6d01c..b4c53754 100644
--- a/proto/bfd/bfd.c
+++ b/proto/bfd/bfd.c
@@ -624,9 +624,17 @@ bfd_request_notify(struct bfd_request *req, u8 state, u8 diag)
static int
bfd_add_request(struct bfd_proto *p, struct bfd_request *req)
{
+ struct bfd_config *cf = (struct bfd_config *) (p->p.cf);
+
if (p->p.vrf_set && (p->p.vrf != req->vrf))
return 0;
+ if (ipa_is_ip4(req->addr) ? !cf->accept_ipv4 : !cf->accept_ipv6)
+ return 0;
+
+ if (req->iface ? !cf->accept_direct : !cf->accept_multihop)
+ return 0;
+
struct bfd_session *s = bfd_find_session_by_addr(p, req->addr);
u8 state, diag;
@@ -986,10 +994,19 @@ bfd_start(struct proto *P)
add_tail(&bfd_proto_list, &p->bfd_node);
birdloop_enter(p->loop);
- p->rx4_1 = bfd_open_rx_sk(p, 0, SK_IPV4);
- p->rx4_m = bfd_open_rx_sk(p, 1, SK_IPV4);
- p->rx6_1 = bfd_open_rx_sk(p, 0, SK_IPV6);
- p->rx6_m = bfd_open_rx_sk(p, 1, SK_IPV6);
+
+ if (cf->accept_ipv4 && cf->accept_direct)
+ p->rx4_1 = bfd_open_rx_sk(p, 0, SK_IPV4);
+
+ if (cf->accept_ipv4 && cf->accept_multihop)
+ p->rx4_m = bfd_open_rx_sk(p, 1, SK_IPV4);
+
+ if (cf->accept_ipv6 && cf->accept_direct)
+ p->rx6_1 = bfd_open_rx_sk(p, 0, SK_IPV6);
+
+ if (cf->accept_ipv6 && cf->accept_multihop)
+ p->rx6_m = bfd_open_rx_sk(p, 1, SK_IPV6);
+
birdloop_leave(p->loop);
bfd_take_requests(p);
@@ -1034,10 +1051,17 @@ static int
bfd_reconfigure(struct proto *P, struct proto_config *c)
{
struct bfd_proto *p = (struct bfd_proto *) P;
- // struct bfd_config *old = (struct bfd_config *) (P->cf);
+ struct bfd_config *old = (struct bfd_config *) (P->cf);
struct bfd_config *new = (struct bfd_config *) c;
struct bfd_iface *ifa;
+ /* TODO: Improve accept reconfiguration */
+ if ((new->accept_ipv4 != old->accept_ipv4) ||
+ (new->accept_ipv6 != old->accept_ipv6) ||
+ (new->accept_direct != old->accept_direct) ||
+ (new->accept_multihop != old->accept_multihop))
+ return 0;
+
birdloop_mask_wakeups(p->loop);
WALK_LIST(ifa, p->iface_list)
diff --git a/proto/bfd/bfd.h b/proto/bfd/bfd.h
index bc4fe969..5c2054cc 100644
--- a/proto/bfd/bfd.h
+++ b/proto/bfd/bfd.h
@@ -43,6 +43,10 @@ struct bfd_config
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 */
+ u8 accept_ipv4;
+ u8 accept_ipv6;
+ u8 accept_direct;
+ u8 accept_multihop;
};
struct bfd_iface_config
diff --git a/proto/bfd/config.Y b/proto/bfd/config.Y
index ed416f25..84d12306 100644
--- a/proto/bfd/config.Y
+++ b/proto/bfd/config.Y
@@ -23,7 +23,7 @@ CF_DECLS
CF_KEYWORDS(BFD, MIN, IDLE, RX, TX, INTERVAL, MULTIPLIER, PASSIVE,
INTERFACE, MULTIHOP, NEIGHBOR, DEV, LOCAL, AUTHENTICATION,
- NONE, SIMPLE, METICULOUS, KEYED, MD5, SHA1)
+ NONE, SIMPLE, METICULOUS, KEYED, MD5, SHA1, IPV4, IPV6, DIRECT)
%type bfd_neigh_iface
%type bfd_neigh_local
@@ -38,10 +38,13 @@ bfd_proto_start: proto_start BFD
this_proto = proto_config_new(&proto_bfd, $1);
init_list(&BFD_CFG->patt_list);
init_list(&BFD_CFG->neigh_list);
+ BFD_CFG->accept_ipv4 = BFD_CFG->accept_ipv6 = 1;
+ BFD_CFG->accept_direct = BFD_CFG->accept_multihop = 1;
};
bfd_proto_item:
proto_item
+ | ACCEPT bfd_accept
| INTERFACE bfd_iface
| MULTIHOP bfd_multihop
| NEIGHBOR bfd_neighbor
@@ -56,6 +59,21 @@ bfd_proto:
bfd_proto_start proto_name '{' bfd_proto_opts '}';
+bfd_accept_item:
+ IPV4 { BFD_CFG->accept_ipv4 = 1; BFD_CFG->accept_ipv6 = 0; }
+ | IPV6 { BFD_CFG->accept_ipv4 = 0; BFD_CFG->accept_ipv6 = 1; }
+ | DIRECT { BFD_CFG->accept_direct = 1; BFD_CFG->accept_multihop = 0; }
+ | MULTIHOP { BFD_CFG->accept_direct = 0; BFD_CFG->accept_multihop = 1; }
+ ;
+
+bfd_accept:
+ {
+ BFD_CFG->accept_ipv4 = BFD_CFG->accept_ipv6 = 1;
+ BFD_CFG->accept_direct = BFD_CFG->accept_multihop = 1;
+ }
+ | bfd_accept bfd_accept_item
+
+
bfd_iface_start:
{
this_ipatt = cfg_allocz(sizeof(struct bfd_iface_config));