return fr_rb_find(inst->peers, &(fr_client_t) { .ipaddr = *ipaddr, .proto = IPPROTO_UDP });
}
+/** Set the event list for a new socket
+ *
+ * @param[in] li the listener
+ * @param[in] el the event list
+ * @param[in] nr context from the network side
+ */
+static void mod_event_list_set(fr_listen_t *li, fr_event_list_t *el, UNUSED void *nr)
+{
+ proto_bfd_udp_t *inst = talloc_get_type_abort(li->app_io_instance, proto_bfd_udp_t);
+ proto_bfd_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_bfd_udp_thread_t);
+ fr_rb_iter_inorder_t iter;
+ proto_bfd_peer_t *peer;
+
+ inst->el = el;
+
+ /*
+ * Walk over the list of peers, associating them with this listener.
+ */
+ for (peer = fr_rb_iter_init_inorder(&iter, inst->peers);
+ peer != NULL;
+ peer = fr_rb_iter_next_inorder(&iter)) {
+ if (peer->inst != inst) continue;
+
+ bfd_session_start(peer, el, thread->sockfd);
+ }
+}
+
+
fr_app_io_t proto_bfd_udp = {
.common = {
.magic = MODULE_MAGIC_INIT,
.write = mod_write,
.fd_set = mod_fd_set,
.network_get = mod_network_get,
+ .event_list_set = mod_event_list_set,
.client_find = mod_client_find,
.get_name = mod_name,
};
}
#endif
-//static int bfd_start_packets(proto_bfd_peer_t *session);
-static int bfd_start_control(proto_bfd_peer_t *session);
+static void bfd_start_packets(proto_bfd_peer_t *session);
+static void bfd_start_control(proto_bfd_peer_t *session);
static int bfd_stop_control(proto_bfd_peer_t *session);
//static int bfd_process(proto_bfd_peer_t *session, bfd_packet_t *bfd);
static void bfd_set_timeout(proto_bfd_peer_t *session, fr_time_t when);
-static int bfd_start_packets(proto_bfd_peer_t *session);
-
static const char *bfd_state[] = {
"admin-down",
"down",
/*
* Start sending packets.
*/
-static int bfd_start_packets(proto_bfd_peer_t *session)
+static void bfd_start_packets(proto_bfd_peer_t *session)
{
uint64_t interval, base;
uint64_t jitter;
bfd_send_packet, session) < 0) {
fr_assert("Failed to insert event" == NULL);
}
-
- return 0;
}
/*
* Start polling for the peer.
*/
-static int bfd_start_poll(proto_bfd_peer_t *session)
+static void bfd_start_poll(proto_bfd_peer_t *session)
{
- if (session->doing_poll) return 0;
+ if (session->doing_poll) return;
/*
* Already sending packets. Reset the timers and set the
* Send POLL packets, even if we're not sending CONTROL
* packets.
*/
- return bfd_start_packets(session);
+ bfd_start_packets(session);
}
/*
return 1;
}
-static int bfd_start_control(proto_bfd_peer_t *session)
+static void bfd_start_control(proto_bfd_peer_t *session)
{
/*
* @todo - change our discriminator?
/*
* We don't expect to see remote packets, so don't do anything.
*/
- if (fr_time_delta_unwrap(session->remote_min_rx_interval) == 0) return 0;
+ if (fr_time_delta_unwrap(session->remote_min_rx_interval) == 0) return;
- if ((session->remote_disc == 0) && session->passive) return 0;
+ /*
+ * @todo - support passive. From 6.1:
+ *
+ * A system may take either an Active role or a Passive role in session
+ * initialization. A system taking the Active role MUST send BFD
+ * Control packets for a particular session, regardless of whether it
+ * has received any BFD packets for that session. A system taking the
+ * Passive role MUST NOT begin sending BFD packets for a particular
+ * session until it has received a BFD packet for that session, and thus
+ * has learned the remote system's discriminator value.
+ */
+ if ((session->remote_disc == 0) && session->passive) return;
/*
* We were asked to go "up" when we were alread "up"
session->client.shortname);
fr_assert(0 == 1);
bfd_stop_control(session);
- return 0;
+ return;
}
bfd_set_timeout(session, session->last_recv);
- if (session->ev_packet) return 0;
+ if (session->ev_packet) return;
+
/*
* Start sending packets.
*/
- return bfd_start_packets(session);
+ bfd_start_packets(session);
}
session->local_disc = fr_rand();
session->remote_disc = 0;
session->local_diag = BFD_DIAG_NONE;
- session->remote_min_rx_interval = fr_time_delta_wrap(0);
+ session->remote_min_rx_interval = fr_time_delta_wrap(1);
session->remote_demand_mode = false;
session->recv_auth_seq = 0;
session->xmit_auth_seq = fr_rand();
return 0;
}
+
+void bfd_session_start(proto_bfd_peer_t *session, fr_event_list_t *el, int sockfd)
+{
+ DEBUG("Starting BFD for %s", session->client.shortname);
+
+ fr_assert(!session->el);
+
+ session->el = el;
+ session->sockfd = sockfd;
+
+ bfd_start_control(session);
+}