Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 31a1b989 authored by David Howells's avatar David Howells
Browse files

rxrpc: Generate a summary of the ACK state for later use



Generate a summary of the Tx buffer packet state when an ACK is received
for use in a later patch that does congestion management.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent df0562a7
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -540,6 +540,20 @@ struct rxrpc_call {

	/* transmission-phase ACK management */
	rxrpc_serial_t		acks_latest;	/* serial number of latest ACK received */
	rxrpc_seq_t		acks_lowest_nak; /* Lowest NACK in the buffer (or ==tx_hard_ack) */
};

/*
 * Summary of a new ACK and the changes it made.
 */
struct rxrpc_ack_summary {
	u8			ack_reason;
	u8			nr_acks;		/* Number of ACKs in packet */
	u8			nr_nacks;		/* Number of NACKs in packet */
	u8			nr_new_acks;		/* Number of new ACKs in packet */
	u8			nr_new_nacks;		/* Number of new NACKs in packet */
	u8			nr_rot_new_acks;	/* Number of rotated new ACKs */
	bool			new_low_nack;		/* T if new low NACK found */
};

enum rxrpc_skb_trace {
+34 −11
Original line number Diff line number Diff line
@@ -56,12 +56,20 @@ static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb,
/*
 * Apply a hard ACK by advancing the Tx window.
 */
static void rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to)
static void rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
				   struct rxrpc_ack_summary *summary)
{
	struct sk_buff *skb, *list = NULL;
	int ix;
	u8 annotation;

	if (call->acks_lowest_nak == call->tx_hard_ack) {
		call->acks_lowest_nak = to;
	} else if (before_eq(call->acks_lowest_nak, to)) {
		summary->new_low_nack = true;
		call->acks_lowest_nak = to;
	}

	spin_lock(&call->lock);

	while (before(call->tx_hard_ack, to)) {
@@ -77,6 +85,8 @@ static void rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to)

		if (annotation & RXRPC_TX_ANNO_LAST)
			set_bit(RXRPC_CALL_TX_LAST, &call->flags);
		if ((annotation & RXRPC_TX_ANNO_MASK) != RXRPC_TX_ANNO_ACK)
			summary->nr_rot_new_acks++;
	}

	spin_unlock(&call->lock);
@@ -147,6 +157,7 @@ static bool rxrpc_end_tx_phase(struct rxrpc_call *call, bool reply_begun,
 */
static bool rxrpc_receiving_reply(struct rxrpc_call *call)
{
	struct rxrpc_ack_summary summary = { 0 };
	rxrpc_seq_t top = READ_ONCE(call->tx_top);

	if (call->ackr_reason) {
@@ -159,7 +170,7 @@ static bool rxrpc_receiving_reply(struct rxrpc_call *call)
	}

	if (!test_bit(RXRPC_CALL_TX_LAST, &call->flags))
		rxrpc_rotate_tx_window(call, top);
		rxrpc_rotate_tx_window(call, top, &summary);
	if (!test_bit(RXRPC_CALL_TX_LAST, &call->flags)) {
		rxrpc_proto_abort("TXL", call, top);
		return false;
@@ -508,7 +519,8 @@ static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb,
 * the time the ACK was sent.
 */
static void rxrpc_input_soft_acks(struct rxrpc_call *call, u8 *acks,
				  rxrpc_seq_t seq, int nr_acks)
				  rxrpc_seq_t seq, int nr_acks,
				  struct rxrpc_ack_summary *summary)
{
	bool resend = false;
	int ix;
@@ -521,14 +533,23 @@ static void rxrpc_input_soft_acks(struct rxrpc_call *call, u8 *acks,
		annotation &= ~RXRPC_TX_ANNO_MASK;
		switch (*acks++) {
		case RXRPC_ACK_TYPE_ACK:
			summary->nr_acks++;
			if (anno_type == RXRPC_TX_ANNO_ACK)
				continue;
			summary->nr_new_acks++;
			call->rxtx_annotations[ix] =
				RXRPC_TX_ANNO_ACK | annotation;
			break;
		case RXRPC_ACK_TYPE_NACK:
			if (!summary->nr_nacks &&
			    call->acks_lowest_nak != seq) {
				call->acks_lowest_nak = seq;
				summary->new_low_nack = true;
			}
			summary->nr_nacks++;
			if (anno_type == RXRPC_TX_ANNO_NAK)
				continue;
			summary->nr_new_nacks++;
			if (anno_type == RXRPC_TX_ANNO_RETRANS)
				continue;
			call->rxtx_annotations[ix] =
@@ -558,7 +579,7 @@ static void rxrpc_input_soft_acks(struct rxrpc_call *call, u8 *acks,
static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
			    u16 skew)
{
	u8 ack_reason;
	struct rxrpc_ack_summary summary = { 0 };
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
	union {
		struct rxrpc_ackpacket ack;
@@ -581,10 +602,10 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
	first_soft_ack = ntohl(buf.ack.firstPacket);
	hard_ack = first_soft_ack - 1;
	nr_acks = buf.ack.nAcks;
	ack_reason = (buf.ack.reason < RXRPC_ACK__INVALID ?
	summary.ack_reason = (buf.ack.reason < RXRPC_ACK__INVALID ?
			      buf.ack.reason : RXRPC_ACK__INVALID);

	trace_rxrpc_rx_ack(call, first_soft_ack, ack_reason, nr_acks);
	trace_rxrpc_rx_ack(call, first_soft_ack, summary.ack_reason, nr_acks);

	_proto("Rx ACK %%%u { m=%hu f=#%u p=#%u s=%%%u r=%s n=%u }",
	       sp->hdr.serial,
@@ -592,7 +613,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
	       first_soft_ack,
	       ntohl(buf.ack.previousPacket),
	       acked_serial,
	       rxrpc_ack_names[ack_reason],
	       rxrpc_ack_names[summary.ack_reason],
	       buf.ack.nAcks);

	if (buf.ack.reason == RXRPC_ACK_PING_RESPONSE)
@@ -649,12 +670,13 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
		return rxrpc_proto_abort("AKN", call, 0);

	if (after(hard_ack, call->tx_hard_ack))
		rxrpc_rotate_tx_window(call, hard_ack);
		rxrpc_rotate_tx_window(call, hard_ack, &summary);

	if (nr_acks > 0) {
		if (skb_copy_bits(skb, sp->offset, buf.acks, nr_acks) < 0)
			return rxrpc_proto_abort("XSA", call, 0);
		rxrpc_input_soft_acks(call, buf.acks, first_soft_ack, nr_acks);
		rxrpc_input_soft_acks(call, buf.acks, first_soft_ack, nr_acks,
				      &summary);
	}

	if (test_bit(RXRPC_CALL_TX_LAST, &call->flags)) {
@@ -669,11 +691,12 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
 */
static void rxrpc_input_ackall(struct rxrpc_call *call, struct sk_buff *skb)
{
	struct rxrpc_ack_summary summary = { 0 };
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);

	_proto("Rx ACKALL %%%u", sp->hdr.serial);

	rxrpc_rotate_tx_window(call, call->tx_top);
	rxrpc_rotate_tx_window(call, call->tx_top, &summary);
	if (test_bit(RXRPC_CALL_TX_LAST, &call->flags))
		rxrpc_end_tx_phase(call, false, "ETL");
}