Skip to content

Commit

Permalink
rxrpc: Fix generation of serial numbers to skip zero
Browse files Browse the repository at this point in the history
[ Upstream commit f310414 ]

In the Rx protocol, every packet generated is marked with a per-connection
monotonically increasing serial number.  This number can be referenced in
an ACK packet generated in response to an incoming packet - thereby
allowing the sender to use this for RTT determination, amongst other
things.

However, if the reference field in the ACK is zero, it doesn't refer to any
incoming packet (it could be a ping to find out if a packet got lost, for
example) - so we shouldn't generate zero serial numbers.

Fix the generation of serial numbers to retry if it comes up with a zero.

Furthermore, since the serial numbers are only ever allocated within the
I/O thread this connection is bound to, there's no need for atomics so
remove that too.

Fixes: 17926a7 ("[AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both")
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Eric Dumazet <edumazet@google.com>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
dhowells authored and gregkh committed Feb 16, 2024
1 parent 4adeeff commit edc8201
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 9 deletions.
16 changes: 15 additions & 1 deletion net/rxrpc/ar-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ struct rxrpc_connection {
enum rxrpc_call_completion completion; /* Completion condition */
s32 abort_code; /* Abort code of connection abort */
int debug_id; /* debug ID for printks */
atomic_t serial; /* packet serial number counter */
rxrpc_serial_t tx_serial; /* Outgoing packet serial number counter */
unsigned int hi_serial; /* highest serial number received */
u32 service_id; /* Service ID, possibly upgraded */
u32 security_level; /* Security level selected */
Expand Down Expand Up @@ -819,6 +819,20 @@ static inline bool rxrpc_sending_to_client(const struct rxrpc_txbuf *txb)

#include <trace/events/rxrpc.h>

/*
* Allocate the next serial number on a connection. 0 must be skipped.
*/
static inline rxrpc_serial_t rxrpc_get_next_serial(struct rxrpc_connection *conn)
{
rxrpc_serial_t serial;

serial = conn->tx_serial;
if (serial == 0)
serial = 1;
conn->tx_serial = serial + 1;
return serial;
}

/*
* af_rxrpc.c
*/
Expand Down
2 changes: 1 addition & 1 deletion net/rxrpc/conn_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
iov[2].iov_base = &ack_info;
iov[2].iov_len = sizeof(ack_info);

serial = atomic_inc_return(&conn->serial);
serial = rxrpc_get_next_serial(conn);

pkt.whdr.epoch = htonl(conn->proto.epoch);
pkt.whdr.cid = htonl(conn->proto.cid | channel);
Expand Down
8 changes: 4 additions & 4 deletions net/rxrpc/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
iov[0].iov_len = sizeof(txb->wire) + sizeof(txb->ack) + n;
len = iov[0].iov_len;

serial = atomic_inc_return(&conn->serial);
serial = rxrpc_get_next_serial(conn);
txb->wire.serial = htonl(serial);
trace_rxrpc_tx_ack(call->debug_id, serial,
ntohl(txb->ack.firstPacket),
Expand Down Expand Up @@ -302,7 +302,7 @@ int rxrpc_send_abort_packet(struct rxrpc_call *call)
iov[0].iov_base = &pkt;
iov[0].iov_len = sizeof(pkt);

serial = atomic_inc_return(&conn->serial);
serial = rxrpc_get_next_serial(conn);
pkt.whdr.serial = htonl(serial);

iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, sizeof(pkt));
Expand Down Expand Up @@ -334,7 +334,7 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
_enter("%x,{%d}", txb->seq, txb->len);

/* Each transmission of a Tx packet needs a new serial number */
serial = atomic_inc_return(&conn->serial);
serial = rxrpc_get_next_serial(conn);
txb->wire.serial = htonl(serial);

if (test_bit(RXRPC_CONN_PROBING_FOR_UPGRADE, &conn->flags) &&
Expand Down Expand Up @@ -558,7 +558,7 @@ void rxrpc_send_conn_abort(struct rxrpc_connection *conn)

len = iov[0].iov_len + iov[1].iov_len;

serial = atomic_inc_return(&conn->serial);
serial = rxrpc_get_next_serial(conn);
whdr.serial = htonl(serial);

iov_iter_kvec(&msg.msg_iter, WRITE, iov, 2, len);
Expand Down
2 changes: 1 addition & 1 deletion net/rxrpc/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v)
atomic_read(&conn->active),
state,
key_serial(conn->key),
atomic_read(&conn->serial),
conn->tx_serial,
conn->hi_serial,
conn->channels[0].call_id,
conn->channels[1].call_id,
Expand Down
4 changes: 2 additions & 2 deletions net/rxrpc/rxkad.c
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ static int rxkad_issue_challenge(struct rxrpc_connection *conn)

len = iov[0].iov_len + iov[1].iov_len;

serial = atomic_inc_return(&conn->serial);
serial = rxrpc_get_next_serial(conn);
whdr.serial = htonl(serial);

ret = kernel_sendmsg(conn->local->socket, &msg, iov, 2, len);
Expand Down Expand Up @@ -721,7 +721,7 @@ static int rxkad_send_response(struct rxrpc_connection *conn,

len = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len;

serial = atomic_inc_return(&conn->serial);
serial = rxrpc_get_next_serial(conn);
whdr.serial = htonl(serial);

rxrpc_local_dont_fragment(conn->local, false);
Expand Down

0 comments on commit edc8201

Please sign in to comment.