|
@@ -32,6 +32,8 @@ struct rxrpc_abort_buffer {
|
|
__be32 abort_code;
|
|
__be32 abort_code;
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static const char rxrpc_keepalive_string[] = "";
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Arrange for a keepalive ping a certain time after we last transmitted. This
|
|
* Arrange for a keepalive ping a certain time after we last transmitted. This
|
|
* lets the far side know we're still interested in this call and helps keep
|
|
* lets the far side know we're still interested in this call and helps keep
|
|
@@ -122,6 +124,7 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping,
|
|
struct kvec iov[2];
|
|
struct kvec iov[2];
|
|
rxrpc_serial_t serial;
|
|
rxrpc_serial_t serial;
|
|
rxrpc_seq_t hard_ack, top;
|
|
rxrpc_seq_t hard_ack, top;
|
|
|
|
+ ktime_t now;
|
|
size_t len, n;
|
|
size_t len, n;
|
|
int ret;
|
|
int ret;
|
|
u8 reason;
|
|
u8 reason;
|
|
@@ -203,8 +206,10 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping,
|
|
}
|
|
}
|
|
|
|
|
|
ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);
|
|
ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);
|
|
|
|
+ now = ktime_get_real();
|
|
if (ping)
|
|
if (ping)
|
|
- call->ping_time = ktime_get_real();
|
|
|
|
|
|
+ call->ping_time = now;
|
|
|
|
+ conn->params.peer->last_tx_at = ktime_get_real();
|
|
|
|
|
|
if (call->state < RXRPC_CALL_COMPLETE) {
|
|
if (call->state < RXRPC_CALL_COMPLETE) {
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
@@ -288,6 +293,7 @@ int rxrpc_send_abort_packet(struct rxrpc_call *call)
|
|
|
|
|
|
ret = kernel_sendmsg(conn->params.local->socket,
|
|
ret = kernel_sendmsg(conn->params.local->socket,
|
|
&msg, iov, 1, sizeof(pkt));
|
|
&msg, iov, 1, sizeof(pkt));
|
|
|
|
+ conn->params.peer->last_tx_at = ktime_get_real();
|
|
|
|
|
|
rxrpc_put_connection(conn);
|
|
rxrpc_put_connection(conn);
|
|
return ret;
|
|
return ret;
|
|
@@ -378,6 +384,7 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb,
|
|
* message and update the peer record
|
|
* message and update the peer record
|
|
*/
|
|
*/
|
|
ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);
|
|
ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);
|
|
|
|
+ conn->params.peer->last_tx_at = ktime_get_real();
|
|
|
|
|
|
up_read(&conn->params.local->defrag_sem);
|
|
up_read(&conn->params.local->defrag_sem);
|
|
if (ret == -EMSGSIZE)
|
|
if (ret == -EMSGSIZE)
|
|
@@ -429,6 +436,7 @@ send_fragmentable:
|
|
if (ret == 0) {
|
|
if (ret == 0) {
|
|
ret = kernel_sendmsg(conn->params.local->socket, &msg,
|
|
ret = kernel_sendmsg(conn->params.local->socket, &msg,
|
|
iov, 2, len);
|
|
iov, 2, len);
|
|
|
|
+ conn->params.peer->last_tx_at = ktime_get_real();
|
|
|
|
|
|
opt = IP_PMTUDISC_DO;
|
|
opt = IP_PMTUDISC_DO;
|
|
kernel_setsockopt(conn->params.local->socket, SOL_IP,
|
|
kernel_setsockopt(conn->params.local->socket, SOL_IP,
|
|
@@ -446,6 +454,7 @@ send_fragmentable:
|
|
if (ret == 0) {
|
|
if (ret == 0) {
|
|
ret = kernel_sendmsg(conn->params.local->socket, &msg,
|
|
ret = kernel_sendmsg(conn->params.local->socket, &msg,
|
|
iov, 2, len);
|
|
iov, 2, len);
|
|
|
|
+ conn->params.peer->last_tx_at = ktime_get_real();
|
|
|
|
|
|
opt = IPV6_PMTUDISC_DO;
|
|
opt = IPV6_PMTUDISC_DO;
|
|
kernel_setsockopt(conn->params.local->socket,
|
|
kernel_setsockopt(conn->params.local->socket,
|
|
@@ -515,3 +524,51 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
|
|
|
|
|
|
_leave("");
|
|
_leave("");
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Send a VERSION reply to a peer as a keepalive.
|
|
|
|
+ */
|
|
|
|
+void rxrpc_send_keepalive(struct rxrpc_peer *peer)
|
|
|
|
+{
|
|
|
|
+ struct rxrpc_wire_header whdr;
|
|
|
|
+ struct msghdr msg;
|
|
|
|
+ struct kvec iov[2];
|
|
|
|
+ size_t len;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ _enter("");
|
|
|
|
+
|
|
|
|
+ msg.msg_name = &peer->srx.transport;
|
|
|
|
+ msg.msg_namelen = peer->srx.transport_len;
|
|
|
|
+ msg.msg_control = NULL;
|
|
|
|
+ msg.msg_controllen = 0;
|
|
|
|
+ msg.msg_flags = 0;
|
|
|
|
+
|
|
|
|
+ whdr.epoch = htonl(peer->local->rxnet->epoch);
|
|
|
|
+ whdr.cid = 0;
|
|
|
|
+ whdr.callNumber = 0;
|
|
|
|
+ whdr.seq = 0;
|
|
|
|
+ whdr.serial = 0;
|
|
|
|
+ whdr.type = RXRPC_PACKET_TYPE_VERSION; /* Not client-initiated */
|
|
|
|
+ whdr.flags = RXRPC_LAST_PACKET;
|
|
|
|
+ whdr.userStatus = 0;
|
|
|
|
+ whdr.securityIndex = 0;
|
|
|
|
+ whdr._rsvd = 0;
|
|
|
|
+ whdr.serviceId = 0;
|
|
|
|
+
|
|
|
|
+ iov[0].iov_base = &whdr;
|
|
|
|
+ iov[0].iov_len = sizeof(whdr);
|
|
|
|
+ iov[1].iov_base = (char *)rxrpc_keepalive_string;
|
|
|
|
+ iov[1].iov_len = sizeof(rxrpc_keepalive_string);
|
|
|
|
+
|
|
|
|
+ len = iov[0].iov_len + iov[1].iov_len;
|
|
|
|
+
|
|
|
|
+ _proto("Tx VERSION (keepalive)");
|
|
|
|
+
|
|
|
|
+ ret = kernel_sendmsg(peer->local->socket, &msg, iov, 2, len);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ _debug("sendmsg failed: %d", ret);
|
|
|
|
+
|
|
|
|
+ peer->last_tx_at = ktime_get_real();
|
|
|
|
+ _leave("");
|
|
|
|
+}
|