Hi,

Testing bfd against frr on linux, their bfd implementation sends polls
as soon as the session is up even if the session timers haven't
changed from what it was advertising while it was in the down state.
Currently openbsd bfd doesn't respond to polls, so this diff adds that
support. tcpdump output during session setup (.9 is openbsd):

14:56:31.225339 10.10.20.9.58974 > 10.10.20.10.bfd-control: [udp sum ok] BFD v1 
length 24 state down flags [] diag none my-discrim 3396727743 your-discrim 0 
mintx 1000000 minrx 1000000 minecho 0 multiplier 3 [to s 0xc0] (ttl 255, id 
48014, len 52)
14:56:31.533645 10.10.20.10.49143 > 10.10.20.9.bfd-control: [udp sum ok] BFD v1 
length 24 state init flags [] diag neighbor-down my-discrim 2 your-discrim 
3396727743 mintx 1500000 minrx 1500000 minecho 50000 mul tiplier 3 (DF) [tos 
0xc0] (ttl 255, id 36838, len 52)
14:56:32.022601 10.10.20.9.58974 > 10.10.20.10.bfd-control: [udp sum ok] BFD v1 
length 24 state up flags [] diag none my-discrim 3396727743 your-discrim 2 
mintx 1000000 minrx 1500000 minecho 0 multiplier 3 [tos 0xc0] (ttl 255, id 
21474, len 52)
14:56:32.023134 10.10.20.10.49143 > 10.10.20.9.bfd-control: [udp sum ok] BFD v1 
length 24 state up flags [P] diag none my-discrim 2 your-discrim 3396727743 
mintx 1500000 minrx 1500000 minecho 50000 multiplier 3 (DF) [tos 0xc0] (ttl 
255, id 36952, len 52)
14:56:32.023207 10.10.20.9.58974 > 10.10.20.10.bfd-control: [udp sum ok] BFD v1 
length 24 state up flags [F] diag none my-discrim 3396727743 your-discrim 2 
mintx 1500000 minrx 1500000 minecho 0 multiplier 3 [tos 0xc0] (ttl 255, id 
23805, len 52)
14:56:32.997091 10.10.20.10.49143 > 10.10.20.9.bfd-control: [udp sum ok] BFD v1 
length 24 state up flags [] diag none my-discrim 2 your-discrim 3396727743 
mintx 1500000 minrx 1500000 minecho 50000 multiplier 3 ( DF) [tos 0xc0] (ttl 
255, id 36991, len 52)

I also added some handling for generating polls and receiving finals while
in there, but there isn't any code to actually start our own poll
sequence just yet.

I only have frr and openbsd peers to test with - if anybody has
something else hooked up would be good to check what they do.

Mitchell


diff --git sys/net/bfd.c sys/net/bfd.c
index 42995531a8a..2ae287a15bb 100644
--- sys/net/bfd.c
+++ sys/net/bfd.c
@@ -741,6 +741,8 @@ bfd_reset(struct bfd_config *bfd)
 
        bfd->bc_mode = BFD_MODE_ASYNC;
        bfd->bc_state = BFD_STATE_DOWN;
+       bfd->bc_poll_seq = 0;
+       bfd->bc_poll_rcvd = 0;
 
        /* rfc5880 6.8.18 */
        bfd->bc_neighbor->bn_lstate = BFD_STATE_DOWN;
@@ -825,7 +827,10 @@ bfd_input(struct bfd_config *bfd, struct mbuf *m)
        bfd->bc_neighbor->bn_rdiscr = ntohl(peer->bfd_my_discriminator);
        bfd->bc_neighbor->bn_rstate = state;
        bfd->bc_neighbor->bn_rdemand = (flags & BFD_FLAG_D);
-       bfd->bc_poll = (flags & BFD_FLAG_F);
+
+       if (flags & BFD_FLAG_F && bfd->bc_poll_seq) {
+               bfd->bc_poll_seq = 0;
+       }
 
        /* Local change to the algorithm, we don't accept below 50ms */
        if (ntohl(peer->bfd_required_min_rx_interval) < BFD_MINIMUM)
@@ -891,6 +896,12 @@ bfd_input(struct bfd_config *bfd, struct mbuf *m)
 
        bfd->bc_error = 0;
 
+       /* Reply to poll if we aren't down */
+       if (flags & BFD_FLAG_P && bfd->bc_state > BFD_STATE_DOWN) {
+               bfd->bc_poll_rcvd = 1;
+               bfd_send_control(bfd);
+       }
+
  discard:
        bfd->bc_neighbor->bn_rdiag = diag;
        m_free(m);
@@ -979,6 +990,13 @@ bfd_send_control(void *x)
 
        h->bfd_ver_diag = ((BFD_VERSION << 5) | (bfd->bc_neighbor->bn_ldiag));
        h->bfd_sta_flags = (bfd->bc_state << 6);
+       /* Can't send a poll and a final in the same packet. */
+       if (bfd->bc_poll_rcvd) {
+               h->bfd_sta_flags |= BFD_FLAG_F;
+               bfd->bc_poll_rcvd = 0;
+       } else if (bfd->bc_poll_seq) {
+               h->bfd_sta_flags |= BFD_FLAG_P;
+       }
        h->bfd_detect_multi = bfd->bc_neighbor->bn_mult;
        h->bfd_length = BFD_HDRLEN;
        h->bfd_my_discriminator = htonl(bfd->bc_neighbor->bn_ldiscr);
diff --git sys/net/bfd.h sys/net/bfd.h
index 3e8da45086f..8ee372faa5d 100644
--- sys/net/bfd.h
+++ sys/net/bfd.h
@@ -143,7 +143,8 @@ struct bfd_config {
        time_t                   bc_lastuptime;
        unsigned int             bc_laststate;
        unsigned int             bc_state;
-       unsigned int             bc_poll;
+       unsigned int             bc_poll_seq;
+       unsigned int             bc_poll_rcvd;
        unsigned int             bc_error;
        uint32_t                 bc_minrx;
        uint32_t                 bc_mintx;

Reply via email to