Close TCP connections for RDMA clients

This commit is contained in:
Vitaliy Filippov
2026-05-01 22:13:29 +00:00
parent e7f30c4939
commit f8de201625
6 changed files with 81 additions and 22 deletions
+32 -10
View File
@@ -191,9 +191,12 @@ void osd_messenger_t::init()
{ {
auto cl = cl_it->second; auto cl = cl_it->second;
cl_it++; cl_it++;
if (!cl->osd_num && !cl->in_osd_num || cl->peer_state != PEER_CONNECTED && cl->peer_state != PEER_RDMA) if (!cl->osd_num && !cl->in_osd_num ||
cl->peer_state == PEER_CONNECTING ||
cl->peer_state == PEER_RDMA_CONNECTING_IN ||
cl->peer_state == PEER_STOPPED)
{ {
// Do not run keepalive on regular clients // Do not run keepalive on regular and unconnected clients
continue; continue;
} }
if (cl->ping_time_remaining > 0) if (cl->ping_time_remaining > 0)
@@ -222,7 +225,7 @@ void osd_messenger_t::init()
.opcode = OSD_OP_PING, .opcode = OSD_OP_PING,
}, },
}; };
op->callback = [this, cl](osd_op_t *op) op->callback = [this](osd_op_t *op)
{ {
auto cl_it = clients.find(op->client_id); auto cl_it = clients.find(op->client_id);
if (cl_it == clients.end()) if (cl_it == clients.end())
@@ -231,14 +234,15 @@ void osd_messenger_t::init()
delete op; delete op;
return; return;
} }
uint64_t fail_client_id = (op->reply.hdr.retval != 0 ? op->client_id : 0); auto cl = cl_it->second;
auto fail_osd_num = cl->in_osd_num ? cl->in_osd_num : cl->osd_num; bool failed = (op->reply.hdr.retval != 0);
cl->ping_time_remaining = 0; cl->ping_time_remaining = 0;
delete op; delete op;
if (fail_client_id) if (failed)
{ {
fprintf(stderr, "Ping failed for OSD %ju (client %ju), disconnecting peer\n", fail_osd_num, fail_client_id); auto fail_osd_num = cl->in_osd_num ? cl->in_osd_num : cl->osd_num;
stop_client(fail_client_id); fprintf(stderr, "Ping failed for OSD %ju (client %ju), disconnecting peer\n", fail_osd_num, cl->client_id);
stop_client(cl->client_id);
} }
}; };
cl->ping_time_remaining = osd_ping_timeout; cl->ping_time_remaining = osd_ping_timeout;
@@ -608,6 +612,17 @@ void osd_messenger_t::handle_peer_epoll(int peer_fd, int epoll_events)
if (epoll_events & EPOLLRDHUP) if (epoll_events & EPOLLRDHUP)
{ {
// Stop client // Stop client
if (cl->rdma_close_tcp && (cl->peer_state == PEER_RDMA ||
cl->peer_state == PEER_RDMA_CONNECTING_IN ||
cl->peer_state == PEER_RDMA_CONNECTING_OUT))
{
// It's allowed to stop the TCP socket during RDMA transition
tfd->set_fd_handler(cl->peer_fd, false, NULL);
clients_by_fd.erase(cl->peer_fd);
close(cl->peer_fd);
cl->peer_fd = -1;
return;
}
if (log_level > 0) if (log_level > 0)
{ {
fprintf(stderr, "[OSD %ju] client %ju disconnected\n", this->osd_num, cl->client_id); fprintf(stderr, "[OSD %ju] client %ju disconnected\n", this->osd_num, cl->client_id);
@@ -687,7 +702,10 @@ void osd_messenger_t::check_peer_config(osd_client_t *cl)
// Inform that we're OSD <osd_num> // Inform that we're OSD <osd_num>
payload["osd_num"] = osd_num; payload["osd_num"] = osd_num;
} }
auto features = json11::Json::object{ { "check_sequencing", true } }; auto features = json11::Json::object{
{ "check_sequencing", true },
{ "rdma_close_tcp", true },
};
if (use_proto_checksums) if (use_proto_checksums)
{ {
features["proto_checksums"] = use_proto_checksums; features["proto_checksums"] = use_proto_checksums;
@@ -781,6 +799,10 @@ void osd_messenger_t::check_peer_config(osd_client_t *cl)
cl->proto_csum_status = MSGR_CSUM_PAYLOAD; cl->proto_csum_status = MSGR_CSUM_PAYLOAD;
} }
#ifdef WITH_RDMA #ifdef WITH_RDMA
if (config["features"]["rdma_close_tcp"].bool_value())
{
cl->rdma_close_tcp = true;
}
if (!use_rdmacm && cl->rdma_conn && config["rdma_address"].is_string()) if (!use_rdmacm && cl->rdma_conn && config["rdma_address"].is_string())
{ {
msgr_rdma_address_t addr; msgr_rdma_address_t addr;
@@ -805,7 +827,7 @@ void osd_messenger_t::check_peer_config(osd_client_t *cl)
{ {
fprintf(stderr, "Connected to OSD %ju using RDMA\n", cl->osd_num); fprintf(stderr, "Connected to OSD %ju using RDMA\n", cl->osd_num);
} }
cl->peer_state = PEER_RDMA; cl->peer_state = (cl->rdma_close_tcp ? PEER_RDMA_CONNECTING_OUT : PEER_RDMA);
// Add the initial receive request // Add the initial receive request
init_recv_rdma(cl); init_recv_rdma(cl);
} }
+5 -3
View File
@@ -35,9 +35,10 @@
#define PEER_CONNECTING 1 #define PEER_CONNECTING 1
#define PEER_CONNECTED 2 #define PEER_CONNECTED 2
#define PEER_RDMA_CONNECTING 3 #define PEER_RDMA_CONNECTING_IN 3
#define PEER_RDMA 4 #define PEER_RDMA_CONNECTING_OUT 4
#define PEER_STOPPED 5 #define PEER_RDMA 5
#define PEER_STOPPED 6
#define MSGR_CSUM_PAYLOAD 1 #define MSGR_CSUM_PAYLOAD 1
#define MSGR_CSUM_FULL 2 #define MSGR_CSUM_FULL 2
@@ -126,6 +127,7 @@ struct osd_client_t
std::vector<int> recv_flags; std::vector<int> recv_flags;
uint64_t read_op_id = 1; uint64_t read_op_id = 1;
bool check_sequencing = false; bool check_sequencing = false;
bool rdma_close_tcp = false;
bool enable_pg_locks = false; bool enable_pg_locks = false;
op_aes_xts_decrypt_t *xts_dec_ctx = NULL; op_aes_xts_decrypt_t *xts_dec_ctx = NULL;
size_t read_op_inline_decrypt_pos = 0; size_t read_op_inline_decrypt_pos = 0;
+19 -2
View File
@@ -541,7 +541,7 @@ bool osd_messenger_t::connect_rdma(uint64_t client_id, std::string rdma_address,
{ {
// Remember connection, but switch to RDMA only after sending the configuration response // Remember connection, but switch to RDMA only after sending the configuration response
cl->rdma_conn = rdma_conn; cl->rdma_conn = rdma_conn;
cl->peer_state = PEER_RDMA_CONNECTING; cl->peer_state = PEER_RDMA_CONNECTING_IN;
return true; return true;
} }
} }
@@ -700,7 +700,7 @@ void osd_messenger_t::handle_rdma_events(msgr_rdma_context_t *rdma_context)
auto rc = cl->rdma_conn; auto rc = cl->rdma_conn;
if (wc[i].status != IBV_WC_SUCCESS) if (wc[i].status != IBV_WC_SUCCESS)
{ {
fprintf(stderr, "RDMA work request failed for client %ju", client_id); fprintf(stderr, "RDMA work request (%s) failed for client %ju", is_send ? "send" : "recv", client_id);
if (cl->osd_num) if (cl->osd_num)
{ {
fprintf(stderr, " (OSD %ju)", cl->osd_num); fprintf(stderr, " (OSD %ju)", cl->osd_num);
@@ -711,6 +711,23 @@ void osd_messenger_t::handle_rdma_events(msgr_rdma_context_t *rdma_context)
} }
if (!is_send) if (!is_send)
{ {
if (cl->peer_state == PEER_RDMA_CONNECTING_OUT)
{
// First message received over RDMA - TCP socket can be closed now
if (log_level > 0)
{
fprintf(stderr, "Successfully connected with client %ju using RDMA\n", cl->client_id);
}
cl->peer_state = PEER_RDMA;
if (cl->peer_fd >= 0 && cl->rdma_close_tcp)
{
// TCP socket is not needed anymore
tfd->set_fd_handler(cl->peer_fd, false, NULL);
clients_by_fd.erase(cl->peer_fd);
close(cl->peer_fd);
cl->peer_fd = -1;
}
}
rc->cur_recv--; rc->cur_recv--;
if (!handle_read_buffer(cl, rc->recv_buffers[rc->next_recv_buf], wc[i].byte_len)) if (!handle_read_buffer(cl, rc->recv_buffers[rc->next_recv_buf], wc[i].byte_len))
{ {
+6 -1
View File
@@ -396,6 +396,10 @@ public:
} }
}; };
#ifdef WITH_RDMA
#include "msgr_rdma.h"
#endif
void osd_messenger_t::read_requests() void osd_messenger_t::read_requests()
{ {
for (int i = 0; i < read_ready_clients.size(); i++) for (int i = 0; i < read_ready_clients.size(); i++)
@@ -403,7 +407,8 @@ void osd_messenger_t::read_requests()
uint64_t client_id = read_ready_clients[i]; uint64_t client_id = read_ready_clients[i];
auto cl_it = clients.find(client_id); auto cl_it = clients.find(client_id);
if (cl_it == clients.end() || !cl_it->second || cl_it->second->read_msg.msg_iovlen || if (cl_it == clients.end() || !cl_it->second || cl_it->second->read_msg.msg_iovlen ||
cl_it->second->peer_state != PEER_CONNECTED) cl_it->second->peer_state == PEER_CONNECTING ||
cl_it->second->peer_state == PEER_STOPPED)
{ {
continue; continue;
} }
+12 -6
View File
@@ -487,7 +487,7 @@ void osd_messenger_t::outbox_push(osd_op_t *cur_op)
} }
cl->write_ops.push_back(cur_op); cl->write_ops.push_back(cur_op);
#ifdef WITH_RDMA #ifdef WITH_RDMA
if (cl->peer_state == PEER_RDMA) if (cl->peer_state == PEER_RDMA || cl->peer_state == PEER_RDMA_CONNECTING_OUT)
{ {
try_send_rdma(cl); try_send_rdma(cl);
return; return;
@@ -826,14 +826,20 @@ void osd_messenger_t::handle_send(int result, bool prev, bool more, osd_client_t
cl->proto_csum_status = cl->proto_csum_status & (~MSGR_CSUM_NEG); cl->proto_csum_status = cl->proto_csum_status & (~MSGR_CSUM_NEG);
} }
#ifdef WITH_RDMA #ifdef WITH_RDMA
if (cl->rdma_conn && !cl->write_op && !cl->write_ops.size() && cl->peer_state == PEER_RDMA_CONNECTING) if (cl->rdma_conn && cl->peer_state == PEER_RDMA_CONNECTING_IN && !cl->write_op && !cl->write_ops.size())
{ {
// FIXME: Ignore pings during RDMA state transition if (cl->rdma_close_tcp)
if (log_level > 0)
{ {
fprintf(stderr, "Successfully connected with client %ju using RDMA\n", cl->client_id); cl->peer_state = PEER_RDMA_CONNECTING_OUT;
}
else
{
if (log_level > 0)
{
fprintf(stderr, "Successfully connected with client %ju using RDMA\n", cl->client_id);
}
cl->peer_state = PEER_RDMA;
} }
cl->peer_state = PEER_RDMA;
// Add the initial receive request // Add the initial receive request
init_recv_rdma(cl); init_recv_rdma(cl);
} }
+7
View File
@@ -373,6 +373,13 @@ void osd_t::exec_show_config(osd_op_t *cur_op)
cl->read_op_id = cur_op->req.hdr.id + 1; cl->read_op_id = cur_op->req.hdr.id + 1;
} }
auto features = json11::Json::object{ { "pg_locks", true } }; auto features = json11::Json::object{ { "pg_locks", true } };
#ifdef WITH_RDMA
if (msgr.is_rdma_enabled() && req_json["features"]["rdma_close_tcp"].bool_value())
{
cl->rdma_close_tcp = true;
features["rdma_close_tcp"] = true;
}
#endif
if (msgr.use_proto_checksums) if (msgr.use_proto_checksums)
{ {
auto peer_csums = req_json["features"]["proto_checksums"].uint64_value(); auto peer_csums = req_json["features"]["proto_checksums"].uint64_value();