BFD: Option to specify which class of BFD sessions are accepted

Allows to configure IPv4/IPv6-only or direct/multihop-only BFD protocol
instances.
This commit is contained in:
Ondrej Zajicek (work) 2020-01-28 18:07:25 +01:00
parent 9f2670277c
commit 7f9adafc10
4 changed files with 61 additions and 6 deletions

View file

@ -1955,6 +1955,7 @@ milliseconds.
<code> <code>
protocol bfd [&lt;name&gt;] { protocol bfd [&lt;name&gt;] {
accept [ipv4|ipv6] [direct|multihop];
interface &lt;interface pattern&gt; { interface &lt;interface pattern&gt; {
interval &lt;time&gt;; interval &lt;time&gt;;
min rx interval &lt;time&gt;; min rx interval &lt;time&gt;;
@ -1989,6 +1990,14 @@ protocol bfd [&lt;name&gt;] {
</code> </code>
<descrip> <descrip>
<tag><label id="bfd-accept">accept [ipv4|ipv6] [direct|multihop]</tag>
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.
<tag><label id="bfd-iface">interface <m/pattern/ [, <m/.../] { <m/options/ }</tag> <tag><label id="bfd-iface">interface <m/pattern/ [, <m/.../] { <m/options/ }</tag>
Interface definitions allow to specify options for sessions associated Interface definitions allow to specify options for sessions associated
with such interfaces and also may contain interface specific options. with such interfaces and also may contain interface specific options.

View file

@ -624,9 +624,17 @@ bfd_request_notify(struct bfd_request *req, u8 state, u8 diag)
static int static int
bfd_add_request(struct bfd_proto *p, struct bfd_request *req) 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)) if (p->p.vrf_set && (p->p.vrf != req->vrf))
return 0; 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); struct bfd_session *s = bfd_find_session_by_addr(p, req->addr);
u8 state, diag; u8 state, diag;
@ -986,10 +994,19 @@ bfd_start(struct proto *P)
add_tail(&bfd_proto_list, &p->bfd_node); add_tail(&bfd_proto_list, &p->bfd_node);
birdloop_enter(p->loop); 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); if (cf->accept_ipv4 && cf->accept_direct)
p->rx6_1 = bfd_open_rx_sk(p, 0, SK_IPV6); p->rx4_1 = bfd_open_rx_sk(p, 0, SK_IPV4);
p->rx6_m = bfd_open_rx_sk(p, 1, SK_IPV6);
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); birdloop_leave(p->loop);
bfd_take_requests(p); bfd_take_requests(p);
@ -1034,10 +1051,17 @@ static int
bfd_reconfigure(struct proto *P, struct proto_config *c) bfd_reconfigure(struct proto *P, struct proto_config *c)
{ {
struct bfd_proto *p = (struct bfd_proto *) P; 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_config *new = (struct bfd_config *) c;
struct bfd_iface *ifa; 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); birdloop_mask_wakeups(p->loop);
WALK_LIST(ifa, p->iface_list) WALK_LIST(ifa, p->iface_list)

View file

@ -43,6 +43,10 @@ struct bfd_config
list patt_list; /* List of iface configs (struct bfd_iface_config) */ list patt_list; /* List of iface configs (struct bfd_iface_config) */
list neigh_list; /* List of configured neighbors (struct bfd_neighbor) */ list neigh_list; /* List of configured neighbors (struct bfd_neighbor) */
struct bfd_iface_config *multihop; /* Multihop pseudoiface config */ struct bfd_iface_config *multihop; /* Multihop pseudoiface config */
u8 accept_ipv4;
u8 accept_ipv6;
u8 accept_direct;
u8 accept_multihop;
}; };
struct bfd_iface_config struct bfd_iface_config

View file

@ -23,7 +23,7 @@ CF_DECLS
CF_KEYWORDS(BFD, MIN, IDLE, RX, TX, INTERVAL, MULTIPLIER, PASSIVE, CF_KEYWORDS(BFD, MIN, IDLE, RX, TX, INTERVAL, MULTIPLIER, PASSIVE,
INTERFACE, MULTIHOP, NEIGHBOR, DEV, LOCAL, AUTHENTICATION, INTERFACE, MULTIHOP, NEIGHBOR, DEV, LOCAL, AUTHENTICATION,
NONE, SIMPLE, METICULOUS, KEYED, MD5, SHA1) NONE, SIMPLE, METICULOUS, KEYED, MD5, SHA1, IPV4, IPV6, DIRECT)
%type <iface> bfd_neigh_iface %type <iface> bfd_neigh_iface
%type <a> bfd_neigh_local %type <a> bfd_neigh_local
@ -38,10 +38,13 @@ bfd_proto_start: proto_start BFD
this_proto = proto_config_new(&proto_bfd, $1); this_proto = proto_config_new(&proto_bfd, $1);
init_list(&BFD_CFG->patt_list); init_list(&BFD_CFG->patt_list);
init_list(&BFD_CFG->neigh_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: bfd_proto_item:
proto_item proto_item
| ACCEPT bfd_accept
| INTERFACE bfd_iface | INTERFACE bfd_iface
| MULTIHOP bfd_multihop | MULTIHOP bfd_multihop
| NEIGHBOR bfd_neighbor | NEIGHBOR bfd_neighbor
@ -56,6 +59,21 @@ bfd_proto:
bfd_proto_start proto_name '{' bfd_proto_opts '}'; 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: bfd_iface_start:
{ {
this_ipatt = cfg_allocz(sizeof(struct bfd_iface_config)); this_ipatt = cfg_allocz(sizeof(struct bfd_iface_config));