rxrpc: Correctly initialise, limit and transmit call->rx_winsize
authorDavid Howells <dhowells@redhat.com>
Tue, 13 Sep 2016 21:36:22 +0000 (22:36 +0100)
committerDavid Howells <dhowells@redhat.com>
Tue, 13 Sep 2016 21:38:45 +0000 (22:38 +0100)
call->rx_winsize should be initialised to the sysctl setting and the sysctl
setting should be limited to the maximum we want to permit.  Further, we
need to place this in the ACK info instead of the sysctl setting.

Furthermore, discard the idea of accepting the subpackets of a jumbo packet
that lie beyond the receive window when the first packet of the jumbo is
within the window.  Just discard the excess subpackets instead.  This
allows the receive window to be opened up right to the buffer size less one
for the dead slot.

Signed-off-by: David Howells <dhowells@redhat.com>
net/rxrpc/ar-internal.h
net/rxrpc/call_object.c
net/rxrpc/input.c
net/rxrpc/misc.c
net/rxrpc/output.c
net/rxrpc/sysctl.c

index 47c74a581a0fc8a2c886ead48466aac293adfaba..e78c40b37db554e3bb9712be92c1255426dd8590 100644 (file)
@@ -498,6 +498,7 @@ struct rxrpc_call {
         */
 #define RXRPC_RXTX_BUFF_SIZE   64
 #define RXRPC_RXTX_BUFF_MASK   (RXRPC_RXTX_BUFF_SIZE - 1)
+#define RXRPC_INIT_RX_WINDOW_SIZE 32
        struct sk_buff          **rxtx_buffer;
        u8                      *rxtx_annotations;
 #define RXRPC_TX_ANNO_ACK      0
@@ -518,7 +519,7 @@ struct rxrpc_call {
        rxrpc_seq_t             rx_expect_next; /* Expected next packet sequence number */
        u8                      rx_winsize;     /* Size of Rx window */
        u8                      tx_winsize;     /* Maximum size of Tx window */
-       u8                      nr_jumbo_dup;   /* Number of jumbo duplicates */
+       u8                      nr_jumbo_bad;   /* Number of jumbo dups/exceeds-windows */
 
        /* receive-phase ACK management */
        u8                      ackr_reason;    /* reason to ACK */
index 9aa1c4b535632fb4c1cc36a8626716a199a156f4..22f9b0d1a138b4c01ea4d76964e9583aee04ace3 100644 (file)
@@ -152,7 +152,7 @@ struct rxrpc_call *rxrpc_alloc_call(gfp_t gfp)
        memset(&call->sock_node, 0xed, sizeof(call->sock_node));
 
        /* Leave space in the ring to handle a maxed-out jumbo packet */
-       call->rx_winsize = RXRPC_RXTX_BUFF_SIZE - 1 - 46;
+       call->rx_winsize = rxrpc_rx_window_size;
        call->tx_winsize = 16;
        call->rx_expect_next = 1;
        return call;
index 8e529afcd6c1131800bd8404ccd38dc845e68869..75af0bd316c75ad71122c8a3092796297c9837df 100644 (file)
@@ -164,7 +164,7 @@ protocol_error:
  * (that information is encoded in the ACK packet).
  */
 static void rxrpc_input_dup_data(struct rxrpc_call *call, rxrpc_seq_t seq,
-                                u8 annotation, bool *_jumbo_dup)
+                                u8 annotation, bool *_jumbo_bad)
 {
        /* Discard normal packets that are duplicates. */
        if (annotation == 0)
@@ -174,9 +174,9 @@ static void rxrpc_input_dup_data(struct rxrpc_call *call, rxrpc_seq_t seq,
         * more partially duplicate jumbo packets, we refuse to take any more
         * jumbos for this call.
         */
-       if (!*_jumbo_dup) {
-               call->nr_jumbo_dup++;
-               *_jumbo_dup = true;
+       if (!*_jumbo_bad) {
+               call->nr_jumbo_bad++;
+               *_jumbo_bad = true;
        }
 }
 
@@ -191,7 +191,7 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb,
        unsigned int ix;
        rxrpc_serial_t serial = sp->hdr.serial, ack_serial = 0;
        rxrpc_seq_t seq = sp->hdr.seq, hard_ack;
-       bool immediate_ack = false, jumbo_dup = false, queued;
+       bool immediate_ack = false, jumbo_bad = false, queued;
        u16 len;
        u8 ack = 0, flags, annotation = 0;
 
@@ -222,7 +222,7 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb,
 
        flags = sp->hdr.flags;
        if (flags & RXRPC_JUMBO_PACKET) {
-               if (call->nr_jumbo_dup > 3) {
+               if (call->nr_jumbo_bad > 3) {
                        ack = RXRPC_ACK_NOSPACE;
                        ack_serial = serial;
                        goto ack;
@@ -259,7 +259,7 @@ next_subpacket:
        }
 
        if (call->rxtx_buffer[ix]) {
-               rxrpc_input_dup_data(call, seq, annotation, &jumbo_dup);
+               rxrpc_input_dup_data(call, seq, annotation, &jumbo_bad);
                if (ack != RXRPC_ACK_DUPLICATE) {
                        ack = RXRPC_ACK_DUPLICATE;
                        ack_serial = serial;
@@ -304,6 +304,15 @@ skip:
                annotation++;
                if (flags & RXRPC_JUMBO_PACKET)
                        annotation |= RXRPC_RX_ANNO_JLAST;
+               if (after(seq, hard_ack + call->rx_winsize)) {
+                       ack = RXRPC_ACK_EXCEEDS_WINDOW;
+                       ack_serial = serial;
+                       if (!jumbo_bad) {
+                               call->nr_jumbo_bad++;
+                               jumbo_bad = true;
+                       }
+                       goto ack;
+               }
 
                _proto("Rx DATA Jumbo %%%u", serial);
                goto next_subpacket;
index fd096f742e4b1d653710327420421345797457a0..8b910780f1acf5d616b0e9004a8cc9bfd2487381 100644 (file)
@@ -50,7 +50,10 @@ unsigned int rxrpc_idle_ack_delay = 0.5 * HZ;
  * limit is hit, we should generate an EXCEEDS_WINDOW ACK and discard further
  * packets.
  */
-unsigned int rxrpc_rx_window_size = RXRPC_RXTX_BUFF_SIZE - 46;
+unsigned int rxrpc_rx_window_size = RXRPC_INIT_RX_WINDOW_SIZE;
+#if (RXRPC_RXTX_BUFF_SIZE - 1) < RXRPC_INIT_RX_WINDOW_SIZE
+#error Need to reduce RXRPC_INIT_RX_WINDOW_SIZE
+#endif
 
 /*
  * Maximum Rx MTU size.  This indicates to the sender the size of jumbo packet
index 719a4c23f09d0c8516ae8da83b6c78f1b262c2c9..90c7722d5779910f432831041d4f31ba249aa879 100644 (file)
@@ -71,10 +71,10 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_call *call,
 
        mtu = call->conn->params.peer->if_mtu;
        mtu -= call->conn->params.peer->hdrsize;
-       jmax = (call->nr_jumbo_dup > 3) ? 1 : rxrpc_rx_jumbo_max;
+       jmax = (call->nr_jumbo_bad > 3) ? 1 : rxrpc_rx_jumbo_max;
        pkt->ackinfo.rxMTU      = htonl(rxrpc_rx_mtu);
        pkt->ackinfo.maxMTU     = htonl(mtu);
-       pkt->ackinfo.rwind      = htonl(rxrpc_rx_window_size);
+       pkt->ackinfo.rwind      = htonl(call->rx_winsize);
        pkt->ackinfo.jumbo_max  = htonl(jmax);
 
        *ackp++ = 0;
index b7ca8cf13c849b5a7f0b7509683bb8db4a171c9c..a03c61c672f5433eb5a76952566fcf073babfc0a 100644 (file)
@@ -20,7 +20,7 @@ static const unsigned int one = 1;
 static const unsigned int four = 4;
 static const unsigned int thirtytwo = 32;
 static const unsigned int n_65535 = 65535;
-static const unsigned int n_max_acks = RXRPC_MAXACKS;
+static const unsigned int n_max_acks = RXRPC_RXTX_BUFF_SIZE - 1;
 
 /*
  * RxRPC operating parameters.