Commit 7f9adafc authored by Ondrej Zajicek (work)'s avatar Ondrej Zajicek (work)
Browse files

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

Allows to configure IPv4/IPv6-only or direct/multihop-only BFD protocol
instances.
parent 9f267027
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -1955,6 +1955,7 @@ milliseconds.

<code>
protocol bfd [&lt;name&gt;] {
	accept [ipv4|ipv6] [direct|multihop];
	interface &lt;interface pattern&gt; {
		interval &lt;time&gt;;
		min rx interval &lt;time&gt;;
@@ -1989,6 +1990,14 @@ protocol bfd [&lt;name&gt;] {
</code>

<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>
	Interface definitions allow to specify options for sessions associated
	with such interfaces and also may contain interface specific options.
+29 −5
Original line number Diff line number Diff line
@@ -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);

  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)
+4 −0
Original line number Diff line number Diff line
@@ -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
+19 −1
Original line number Diff line number Diff line
@@ -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 <iface> bfd_neigh_iface
%type <a> 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));