rxrpc: Add re-sent Tx annotation

Add a Tx-phase annotation for packet buffers to indicate that a buffer has
already been retransmitted.  This will be used by future congestion
management.  Re-retransmissions of a packet don't affect the congestion
window managment in the same way as initial retransmissions.

Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
David Howells 2016-09-22 00:29:32 +01:00
parent 5a924b8951
commit f07373ead4
3 changed files with 32 additions and 12 deletions

View File

@ -505,6 +505,8 @@ struct rxrpc_call {
#define RXRPC_TX_ANNO_UNACK 1 #define RXRPC_TX_ANNO_UNACK 1
#define RXRPC_TX_ANNO_NAK 2 #define RXRPC_TX_ANNO_NAK 2
#define RXRPC_TX_ANNO_RETRANS 3 #define RXRPC_TX_ANNO_RETRANS 3
#define RXRPC_TX_ANNO_MASK 0x03
#define RXRPC_TX_ANNO_RESENT 0x04
#define RXRPC_RX_ANNO_JUMBO 0x3f /* Jumbo subpacket number + 1 if not zero */ #define RXRPC_RX_ANNO_JUMBO 0x3f /* Jumbo subpacket number + 1 if not zero */
#define RXRPC_RX_ANNO_JLAST 0x40 /* Set if last element of a jumbo packet */ #define RXRPC_RX_ANNO_JLAST 0x40 /* Set if last element of a jumbo packet */
#define RXRPC_RX_ANNO_VERIFIED 0x80 /* Set if verified and decrypted */ #define RXRPC_RX_ANNO_VERIFIED 0x80 /* Set if verified and decrypted */

View File

@ -144,7 +144,7 @@ static void rxrpc_resend(struct rxrpc_call *call)
rxrpc_seq_t cursor, seq, top; rxrpc_seq_t cursor, seq, top;
unsigned long resend_at, now; unsigned long resend_at, now;
int ix; int ix;
u8 annotation; u8 annotation, anno_type;
_enter("{%d,%d}", call->tx_hard_ack, call->tx_top); _enter("{%d,%d}", call->tx_hard_ack, call->tx_top);
@ -165,14 +165,16 @@ static void rxrpc_resend(struct rxrpc_call *call)
for (seq = cursor + 1; before_eq(seq, top); seq++) { for (seq = cursor + 1; before_eq(seq, top); seq++) {
ix = seq & RXRPC_RXTX_BUFF_MASK; ix = seq & RXRPC_RXTX_BUFF_MASK;
annotation = call->rxtx_annotations[ix]; annotation = call->rxtx_annotations[ix];
if (annotation == RXRPC_TX_ANNO_ACK) anno_type = annotation & RXRPC_TX_ANNO_MASK;
annotation &= ~RXRPC_TX_ANNO_MASK;
if (anno_type == RXRPC_TX_ANNO_ACK)
continue; continue;
skb = call->rxtx_buffer[ix]; skb = call->rxtx_buffer[ix];
rxrpc_see_skb(skb, rxrpc_skb_tx_seen); rxrpc_see_skb(skb, rxrpc_skb_tx_seen);
sp = rxrpc_skb(skb); sp = rxrpc_skb(skb);
if (annotation == RXRPC_TX_ANNO_UNACK) { if (anno_type == RXRPC_TX_ANNO_UNACK) {
if (time_after(sp->resend_at, now)) { if (time_after(sp->resend_at, now)) {
if (time_before(sp->resend_at, resend_at)) if (time_before(sp->resend_at, resend_at))
resend_at = sp->resend_at; resend_at = sp->resend_at;
@ -181,7 +183,7 @@ static void rxrpc_resend(struct rxrpc_call *call)
} }
/* Okay, we need to retransmit a packet. */ /* Okay, we need to retransmit a packet. */
call->rxtx_annotations[ix] = RXRPC_TX_ANNO_RETRANS; call->rxtx_annotations[ix] = RXRPC_TX_ANNO_RETRANS | annotation;
} }
call->resend_at = resend_at; call->resend_at = resend_at;
@ -194,7 +196,8 @@ static void rxrpc_resend(struct rxrpc_call *call)
for (seq = cursor + 1; before_eq(seq, top); seq++) { for (seq = cursor + 1; before_eq(seq, top); seq++) {
ix = seq & RXRPC_RXTX_BUFF_MASK; ix = seq & RXRPC_RXTX_BUFF_MASK;
annotation = call->rxtx_annotations[ix]; annotation = call->rxtx_annotations[ix];
if (annotation != RXRPC_TX_ANNO_RETRANS) anno_type = annotation & RXRPC_TX_ANNO_MASK;
if (anno_type != RXRPC_TX_ANNO_RETRANS)
continue; continue;
skb = call->rxtx_buffer[ix]; skb = call->rxtx_buffer[ix];
@ -220,10 +223,17 @@ static void rxrpc_resend(struct rxrpc_call *call)
* received and the packet might have been hard-ACK'd (in which * received and the packet might have been hard-ACK'd (in which
* case it will no longer be in the buffer). * case it will no longer be in the buffer).
*/ */
if (after(seq, call->tx_hard_ack) && if (after(seq, call->tx_hard_ack)) {
(call->rxtx_annotations[ix] == RXRPC_TX_ANNO_RETRANS || annotation = call->rxtx_annotations[ix];
call->rxtx_annotations[ix] == RXRPC_TX_ANNO_NAK)) anno_type = annotation & RXRPC_TX_ANNO_MASK;
call->rxtx_annotations[ix] = RXRPC_TX_ANNO_UNACK; if (anno_type == RXRPC_TX_ANNO_RETRANS ||
anno_type == RXRPC_TX_ANNO_NAK) {
annotation &= ~RXRPC_TX_ANNO_MASK;
annotation |= RXRPC_TX_ANNO_UNACK;
}
annotation |= RXRPC_TX_ANNO_RESENT;
call->rxtx_annotations[ix] = annotation;
}
if (after(call->tx_hard_ack, seq)) if (after(call->tx_hard_ack, seq))
seq = call->tx_hard_ack; seq = call->tx_hard_ack;

View File

@ -388,17 +388,25 @@ static void rxrpc_input_soft_acks(struct rxrpc_call *call, u8 *acks,
{ {
bool resend = false; bool resend = false;
int ix; int ix;
u8 annotation, anno_type;
for (; nr_acks > 0; nr_acks--, seq++) { for (; nr_acks > 0; nr_acks--, seq++) {
ix = seq & RXRPC_RXTX_BUFF_MASK; ix = seq & RXRPC_RXTX_BUFF_MASK;
annotation = call->rxtx_annotations[ix];
anno_type = annotation & RXRPC_TX_ANNO_MASK;
annotation &= ~RXRPC_TX_ANNO_MASK;
switch (*acks++) { switch (*acks++) {
case RXRPC_ACK_TYPE_ACK: case RXRPC_ACK_TYPE_ACK:
call->rxtx_annotations[ix] = RXRPC_TX_ANNO_ACK; if (anno_type == RXRPC_TX_ANNO_ACK)
continue;
call->rxtx_annotations[ix] =
RXRPC_TX_ANNO_ACK | annotation;
break; break;
case RXRPC_ACK_TYPE_NACK: case RXRPC_ACK_TYPE_NACK:
if (call->rxtx_annotations[ix] == RXRPC_TX_ANNO_NAK) if (anno_type == RXRPC_TX_ANNO_NAK)
continue; continue;
call->rxtx_annotations[ix] = RXRPC_TX_ANNO_NAK; call->rxtx_annotations[ix] =
RXRPC_TX_ANNO_NAK | annotation;
resend = true; resend = true;
break; break;
default: default: