-static void
-lnet_destroy_rc_data(struct lnet_rc_data *rcd)
-{
- LASSERT(list_empty(&rcd->rcd_list));
- /* detached from network */
- LASSERT(LNetMDHandleIsInvalid(rcd->rcd_mdh));
-
- if (rcd->rcd_gateway != NULL) {
- int cpt = rcd->rcd_gateway->lpni_cpt;
-
- lnet_net_lock(cpt);
- lnet_peer_ni_decref_locked(rcd->rcd_gateway);
- lnet_net_unlock(cpt);
- }
-
- if (rcd->rcd_pingbuffer != NULL)
- lnet_ping_buffer_decref(rcd->rcd_pingbuffer);
-
- LIBCFS_FREE(rcd, sizeof(*rcd));
-}
-
-static struct lnet_rc_data *
-lnet_update_rc_data_locked(struct lnet_peer_ni *gateway)
-{
- struct lnet_handle_md mdh;
- struct lnet_rc_data *rcd;
- struct lnet_ping_buffer *pbuf = NULL;
- int nnis = LNET_INTERFACES_MIN;
- int rc;
- int i;
-
- rcd = gateway->lpni_rcd;
- if (rcd) {
- nnis = rcd->rcd_nnis;
- mdh = rcd->rcd_mdh;
- LNetInvalidateMDHandle(&rcd->rcd_mdh);
- pbuf = rcd->rcd_pingbuffer;
- rcd->rcd_pingbuffer = NULL;
- } else {
- LNetInvalidateMDHandle(&mdh);
- }
-
- lnet_net_unlock(gateway->lpni_cpt);
-
- if (rcd) {
- LNetMDUnlink(mdh);
- lnet_ping_buffer_decref(pbuf);
- } else {
- LIBCFS_ALLOC(rcd, sizeof(*rcd));
- if (rcd == NULL)
- goto out;
-
- LNetInvalidateMDHandle(&rcd->rcd_mdh);
- INIT_LIST_HEAD(&rcd->rcd_list);
- rcd->rcd_nnis = nnis;
- }
-
- pbuf = lnet_ping_buffer_alloc(nnis, GFP_NOFS);
- if (pbuf == NULL)
- goto out;
-
- for (i = 0; i < nnis; i++) {
- pbuf->pb_info.pi_ni[i].ns_nid = LNET_NID_ANY;
- pbuf->pb_info.pi_ni[i].ns_status = LNET_NI_STATUS_INVALID;
- }
- rcd->rcd_pingbuffer = pbuf;
-
- LASSERT(!LNetEQHandleIsInvalid(the_lnet.ln_rc_eqh));
- rc = LNetMDBind((struct lnet_md){.start = &pbuf->pb_info,
- .user_ptr = rcd,
- .length = LNET_PING_INFO_SIZE(nnis),
- .threshold = LNET_MD_THRESH_INF,
- .options = LNET_MD_TRUNCATE,
- .eq_handle = the_lnet.ln_rc_eqh},
- LNET_UNLINK,
- &rcd->rcd_mdh);
- if (rc < 0) {
- CERROR("Can't bind MD: %d\n", rc);
- goto out_ping_buffer_decref;
- }
- LASSERT(rc == 0);
-
- lnet_net_lock(gateway->lpni_cpt);
- /* Check if this is still a router. */
- if (!lnet_isrouter(gateway))
- goto out_unlock;
- /* Check if someone else installed router data. */
- if (gateway->lpni_rcd && gateway->lpni_rcd != rcd)
- goto out_unlock;
-
- /* Install and/or update the router data. */
- if (!gateway->lpni_rcd) {
- lnet_peer_ni_addref_locked(gateway);
- rcd->rcd_gateway = gateway;
- gateway->lpni_rcd = rcd;
- }
- gateway->lpni_ping_notsent = 0;
-
- return rcd;
-
-out_unlock:
- lnet_net_unlock(gateway->lpni_cpt);
- rc = LNetMDUnlink(mdh);
- LASSERT(rc == 0);
-out_ping_buffer_decref:
- lnet_ping_buffer_decref(pbuf);
-out:
- if (rcd && rcd != gateway->lpni_rcd)
- lnet_destroy_rc_data(rcd);
- lnet_net_lock(gateway->lpni_cpt);
- return gateway->lpni_rcd;
-}
-
-static int
-lnet_router_check_interval(struct lnet_peer_ni *rtr)
-{
- int secs;
-
- secs = rtr->lpni_alive ? live_router_check_interval :
- dead_router_check_interval;
- if (secs < 0)
- secs = 0;
-
- return secs;
-}
-
-static void
-lnet_ping_router_locked(struct lnet_peer_ni *rtr)
-{
- struct lnet_rc_data *rcd = NULL;
- time64_t now = ktime_get_seconds();
- time64_t secs;
- struct lnet_ni *ni;
-
- lnet_peer_ni_addref_locked(rtr);
-
- if (rtr->lpni_ping_deadline != 0 && /* ping timed out? */
- now > rtr->lpni_ping_deadline)
- lnet_notify_locked(rtr, 1, 0, now);
-
- /* Run any outstanding notifications */
- ni = lnet_get_next_ni_locked(rtr->lpni_net, NULL);
- lnet_ni_notify_locked(ni, rtr);
-
- if (!lnet_isrouter(rtr) ||
- the_lnet.ln_mt_state != LNET_MT_STATE_RUNNING) {
- /* router table changed or router checker is shutting down */
- lnet_peer_ni_decref_locked(rtr);
- return;
- }
-
- rcd = rtr->lpni_rcd;
-
- /*
- * The response to the router checker ping could've timed out and
- * the mdh might've been invalidated, so we need to update it
- * again.
- */
- if (!rcd || rcd->rcd_nnis > rcd->rcd_pingbuffer->pb_nnis ||
- LNetMDHandleIsInvalid(rcd->rcd_mdh))
- rcd = lnet_update_rc_data_locked(rtr);
- if (rcd == NULL)
- return;
-
- secs = lnet_router_check_interval(rtr);
-
- CDEBUG(D_NET,
- "rtr %s %lld: deadline %lld ping_notsent %d alive %d "
- "alive_count %d lpni_ping_timestamp %lld\n",
- libcfs_nid2str(rtr->lpni_nid), secs,
- rtr->lpni_ping_deadline, rtr->lpni_ping_notsent,
- rtr->lpni_alive, rtr->lpni_alive_count, rtr->lpni_ping_timestamp);
-
- if (secs != 0 && !rtr->lpni_ping_notsent &&
- now > rtr->lpni_ping_timestamp + secs) {
- int rc;
- struct lnet_process_id id;
- struct lnet_handle_md mdh;
-
- id.nid = rtr->lpni_nid;
- id.pid = LNET_PID_LUSTRE;
- CDEBUG(D_NET, "Check: %s\n", libcfs_id2str(id));
-
- rtr->lpni_ping_notsent = 1;
- rtr->lpni_ping_timestamp = now;
-
- mdh = rcd->rcd_mdh;
-
- if (rtr->lpni_ping_deadline == 0) {
- rtr->lpni_ping_deadline = ktime_get_seconds() +
- router_ping_timeout;
- }
-
- lnet_net_unlock(rtr->lpni_cpt);
-
- rc = LNetGet(LNET_NID_ANY, mdh, id, LNET_RESERVED_PORTAL,
- LNET_PROTO_PING_MATCHBITS, 0, false);
-
- lnet_net_lock(rtr->lpni_cpt);
- if (rc != 0)
- rtr->lpni_ping_notsent = 0; /* no event pending */
- }
-
- lnet_peer_ni_decref_locked(rtr);
- return;
-}
-