[PATCH net-next 4/9] rxrpc: Send pings to get RTT data [ver #2]

2016-09-22 Thread David Howells
Send a PING ACK packet to the peer when we get a new incoming call from a
peer we don't have a record for.  The PING RESPONSE ACK packet will tell us
the following about the peer:

 (1) its receive window size

 (2) its MTU sizes

 (3) its support for jumbo DATA packets

 (4) if it supports slow start (similar to RFC 5681)

 (5) an estimate of the RTT

This is necessary because the peer won't normally send us an ACK until it
gets to the Rx phase and we send it a packet, but we would like to know
some of this information before we start sending packets.

A pair of tracepoints are added so that RTT determination can be observed.

Signed-off-by: David Howells 
---

 net/rxrpc/ar-internal.h |7 +--
 net/rxrpc/input.c   |   48 ++-
 net/rxrpc/misc.c|   11 ++-
 net/rxrpc/output.c  |   22 ++
 4 files changed, 80 insertions(+), 8 deletions(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 79c671e552c3..8b47f468eb9d 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -403,6 +403,7 @@ enum rxrpc_call_flag {
RXRPC_CALL_EXPOSED, /* The call was exposed to the world */
RXRPC_CALL_RX_LAST, /* Received the last packet (at 
rxtx_top) */
RXRPC_CALL_TX_LAST, /* Last packet in Tx buffer (at 
rxtx_top) */
+   RXRPC_CALL_PINGING, /* Ping in process */
 };
 
 /*
@@ -487,6 +488,8 @@ struct rxrpc_call {
u32 call_id;/* call ID on connection  */
u32 cid;/* connection ID plus channel 
index */
int debug_id;   /* debug ID for printks */
+   unsigned short  rx_pkt_offset;  /* Current recvmsg packet 
offset */
+   unsigned short  rx_pkt_len; /* Current recvmsg packet len */
 
/* Rx/Tx circular buffer, depending on phase.
 *
@@ -530,8 +533,8 @@ struct rxrpc_call {
u16 ackr_skew;  /* skew on packet being ACK'd */
rxrpc_serial_t  ackr_serial;/* serial of packet being ACK'd 
*/
rxrpc_seq_t ackr_prev_seq;  /* previous sequence number 
received */
-   unsigned short  rx_pkt_offset;  /* Current recvmsg packet 
offset */
-   unsigned short  rx_pkt_len; /* Current recvmsg packet len */
+   rxrpc_serial_t  ackr_ping;  /* Last ping sent */
+   ktime_t ackr_ping_time; /* Time last ping sent */
 
/* transmission-phase ACK management */
rxrpc_serial_t  acks_latest;/* serial number of latest ACK 
received */
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index aa261df9fc9e..a0a5bd108c9e 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -37,6 +37,19 @@ static void rxrpc_proto_abort(const char *why,
 }
 
 /*
+ * Ping the other end to fill our RTT cache and to retrieve the rwind
+ * and MTU parameters.
+ */
+static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb,
+   int skew)
+{
+   struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+
+   rxrpc_propose_ACK(call, RXRPC_ACK_PING, skew, sp->hdr.serial,
+ true, true);
+}
+
+/*
  * Apply a hard ACK by advancing the Tx window.
  */
 static void rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to)
@@ -343,6 +356,32 @@ ack:
 }
 
 /*
+ * Process a ping response.
+ */
+static void rxrpc_input_ping_response(struct rxrpc_call *call,
+ ktime_t resp_time,
+ rxrpc_serial_t orig_serial,
+ rxrpc_serial_t ack_serial)
+{
+   rxrpc_serial_t ping_serial;
+   ktime_t ping_time;
+
+   ping_time = call->ackr_ping_time;
+   smp_rmb();
+   ping_serial = call->ackr_ping;
+
+   if (!test_bit(RXRPC_CALL_PINGING, >flags) ||
+   before(orig_serial, ping_serial))
+   return;
+   clear_bit(RXRPC_CALL_PINGING, >flags);
+   if (after(orig_serial, ping_serial))
+   return;
+
+   rxrpc_peer_add_rtt(call, rxrpc_rtt_rx_ping_response,
+  orig_serial, ack_serial, ping_time, resp_time);
+}
+
+/*
  * Process the extra information that may be appended to an ACK packet
  */
 static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb,
@@ -438,6 +477,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct 
sk_buff *skb,
struct rxrpc_ackinfo info;
u8 acks[RXRPC_MAXACKS];
} buf;
+   rxrpc_serial_t acked_serial;
rxrpc_seq_t first_soft_ack, hard_ack;
int nr_acks, offset;
 
@@ -449,6 +489,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct 
sk_buff *skb,
}
sp->offset += sizeof(buf.ack);
 
+   acked_serial = 

[PATCH net-next 4/9] rxrpc: Send pings to get RTT data [ver #2]

2016-09-22 Thread David Howells
Send a PING ACK packet to the peer when we get a new incoming call from a
peer we don't have a record for.  The PING RESPONSE ACK packet will tell us
the following about the peer:

 (1) its receive window size

 (2) its MTU sizes

 (3) its support for jumbo DATA packets

 (4) if it supports slow start (similar to RFC 5681)

 (5) an estimate of the RTT

This is necessary because the peer won't normally send us an ACK until it
gets to the Rx phase and we send it a packet, but we would like to know
some of this information before we start sending packets.

A pair of tracepoints are added so that RTT determination can be observed.

Signed-off-by: David Howells 
---

 net/rxrpc/ar-internal.h |7 +--
 net/rxrpc/input.c   |   48 ++-
 net/rxrpc/misc.c|   11 ++-
 net/rxrpc/output.c  |   22 ++
 4 files changed, 80 insertions(+), 8 deletions(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 79c671e552c3..8b47f468eb9d 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -403,6 +403,7 @@ enum rxrpc_call_flag {
RXRPC_CALL_EXPOSED, /* The call was exposed to the world */
RXRPC_CALL_RX_LAST, /* Received the last packet (at 
rxtx_top) */
RXRPC_CALL_TX_LAST, /* Last packet in Tx buffer (at 
rxtx_top) */
+   RXRPC_CALL_PINGING, /* Ping in process */
 };
 
 /*
@@ -487,6 +488,8 @@ struct rxrpc_call {
u32 call_id;/* call ID on connection  */
u32 cid;/* connection ID plus channel 
index */
int debug_id;   /* debug ID for printks */
+   unsigned short  rx_pkt_offset;  /* Current recvmsg packet 
offset */
+   unsigned short  rx_pkt_len; /* Current recvmsg packet len */
 
/* Rx/Tx circular buffer, depending on phase.
 *
@@ -530,8 +533,8 @@ struct rxrpc_call {
u16 ackr_skew;  /* skew on packet being ACK'd */
rxrpc_serial_t  ackr_serial;/* serial of packet being ACK'd 
*/
rxrpc_seq_t ackr_prev_seq;  /* previous sequence number 
received */
-   unsigned short  rx_pkt_offset;  /* Current recvmsg packet 
offset */
-   unsigned short  rx_pkt_len; /* Current recvmsg packet len */
+   rxrpc_serial_t  ackr_ping;  /* Last ping sent */
+   ktime_t ackr_ping_time; /* Time last ping sent */
 
/* transmission-phase ACK management */
rxrpc_serial_t  acks_latest;/* serial number of latest ACK 
received */
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index aa261df9fc9e..a0a5bd108c9e 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -37,6 +37,19 @@ static void rxrpc_proto_abort(const char *why,
 }
 
 /*
+ * Ping the other end to fill our RTT cache and to retrieve the rwind
+ * and MTU parameters.
+ */
+static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb,
+   int skew)
+{
+   struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+
+   rxrpc_propose_ACK(call, RXRPC_ACK_PING, skew, sp->hdr.serial,
+ true, true);
+}
+
+/*
  * Apply a hard ACK by advancing the Tx window.
  */
 static void rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to)
@@ -343,6 +356,32 @@ ack:
 }
 
 /*
+ * Process a ping response.
+ */
+static void rxrpc_input_ping_response(struct rxrpc_call *call,
+ ktime_t resp_time,
+ rxrpc_serial_t orig_serial,
+ rxrpc_serial_t ack_serial)
+{
+   rxrpc_serial_t ping_serial;
+   ktime_t ping_time;
+
+   ping_time = call->ackr_ping_time;
+   smp_rmb();
+   ping_serial = call->ackr_ping;
+
+   if (!test_bit(RXRPC_CALL_PINGING, >flags) ||
+   before(orig_serial, ping_serial))
+   return;
+   clear_bit(RXRPC_CALL_PINGING, >flags);
+   if (after(orig_serial, ping_serial))
+   return;
+
+   rxrpc_peer_add_rtt(call, rxrpc_rtt_rx_ping_response,
+  orig_serial, ack_serial, ping_time, resp_time);
+}
+
+/*
  * Process the extra information that may be appended to an ACK packet
  */
 static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb,
@@ -438,6 +477,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct 
sk_buff *skb,
struct rxrpc_ackinfo info;
u8 acks[RXRPC_MAXACKS];
} buf;
+   rxrpc_serial_t acked_serial;
rxrpc_seq_t first_soft_ack, hard_ack;
int nr_acks, offset;
 
@@ -449,6 +489,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct 
sk_buff *skb,
}
sp->offset += sizeof(buf.ack);
 
+   acked_serial = ntohl(buf.ack.serial);

[PATCH net-next 4/9] rxrpc: Send pings to get RTT data

2016-09-21 Thread David Howells
Send a PING ACK packet to the peer when we get a new incoming call from a
peer we don't have a record for.  The PING RESPONSE ACK packet will tell us
the following about the peer:

 (1) its receive window size

 (2) its MTU sizes

 (3) its support for jumbo DATA packets

 (4) if it supports slow start (similar to RFC 5681)

 (5) an estimate of the RTT

This is necessary because the peer won't normally send us an ACK until it
gets to the Rx phase and we send it a packet, but we would like to know
some of this information before we start sending packets.

A pair of tracepoints are added so that RTT determination can be observed.

Signed-off-by: David Howells 
---

 net/rxrpc/ar-internal.h |7 +--
 net/rxrpc/input.c   |   48 ++-
 net/rxrpc/misc.c|   11 ++-
 net/rxrpc/output.c  |   22 ++
 4 files changed, 80 insertions(+), 8 deletions(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 79c671e552c3..8b47f468eb9d 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -403,6 +403,7 @@ enum rxrpc_call_flag {
RXRPC_CALL_EXPOSED, /* The call was exposed to the world */
RXRPC_CALL_RX_LAST, /* Received the last packet (at 
rxtx_top) */
RXRPC_CALL_TX_LAST, /* Last packet in Tx buffer (at 
rxtx_top) */
+   RXRPC_CALL_PINGING, /* Ping in process */
 };
 
 /*
@@ -487,6 +488,8 @@ struct rxrpc_call {
u32 call_id;/* call ID on connection  */
u32 cid;/* connection ID plus channel 
index */
int debug_id;   /* debug ID for printks */
+   unsigned short  rx_pkt_offset;  /* Current recvmsg packet 
offset */
+   unsigned short  rx_pkt_len; /* Current recvmsg packet len */
 
/* Rx/Tx circular buffer, depending on phase.
 *
@@ -530,8 +533,8 @@ struct rxrpc_call {
u16 ackr_skew;  /* skew on packet being ACK'd */
rxrpc_serial_t  ackr_serial;/* serial of packet being ACK'd 
*/
rxrpc_seq_t ackr_prev_seq;  /* previous sequence number 
received */
-   unsigned short  rx_pkt_offset;  /* Current recvmsg packet 
offset */
-   unsigned short  rx_pkt_len; /* Current recvmsg packet len */
+   rxrpc_serial_t  ackr_ping;  /* Last ping sent */
+   ktime_t ackr_ping_time; /* Time last ping sent */
 
/* transmission-phase ACK management */
rxrpc_serial_t  acks_latest;/* serial number of latest ACK 
received */
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index aa261df9fc9e..a0a5bd108c9e 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -37,6 +37,19 @@ static void rxrpc_proto_abort(const char *why,
 }
 
 /*
+ * Ping the other end to fill our RTT cache and to retrieve the rwind
+ * and MTU parameters.
+ */
+static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb,
+   int skew)
+{
+   struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+
+   rxrpc_propose_ACK(call, RXRPC_ACK_PING, skew, sp->hdr.serial,
+ true, true);
+}
+
+/*
  * Apply a hard ACK by advancing the Tx window.
  */
 static void rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to)
@@ -343,6 +356,32 @@ ack:
 }
 
 /*
+ * Process a ping response.
+ */
+static void rxrpc_input_ping_response(struct rxrpc_call *call,
+ ktime_t resp_time,
+ rxrpc_serial_t orig_serial,
+ rxrpc_serial_t ack_serial)
+{
+   rxrpc_serial_t ping_serial;
+   ktime_t ping_time;
+
+   ping_time = call->ackr_ping_time;
+   smp_rmb();
+   ping_serial = call->ackr_ping;
+
+   if (!test_bit(RXRPC_CALL_PINGING, >flags) ||
+   before(orig_serial, ping_serial))
+   return;
+   clear_bit(RXRPC_CALL_PINGING, >flags);
+   if (after(orig_serial, ping_serial))
+   return;
+
+   rxrpc_peer_add_rtt(call, rxrpc_rtt_rx_ping_response,
+  orig_serial, ack_serial, ping_time, resp_time);
+}
+
+/*
  * Process the extra information that may be appended to an ACK packet
  */
 static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb,
@@ -438,6 +477,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct 
sk_buff *skb,
struct rxrpc_ackinfo info;
u8 acks[RXRPC_MAXACKS];
} buf;
+   rxrpc_serial_t acked_serial;
rxrpc_seq_t first_soft_ack, hard_ack;
int nr_acks, offset;
 
@@ -449,6 +489,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct 
sk_buff *skb,
}
sp->offset += sizeof(buf.ack);
 
+   acked_serial = 

[PATCH net-next 4/9] rxrpc: Send pings to get RTT data

2016-09-21 Thread David Howells
Send a PING ACK packet to the peer when we get a new incoming call from a
peer we don't have a record for.  The PING RESPONSE ACK packet will tell us
the following about the peer:

 (1) its receive window size

 (2) its MTU sizes

 (3) its support for jumbo DATA packets

 (4) if it supports slow start (similar to RFC 5681)

 (5) an estimate of the RTT

This is necessary because the peer won't normally send us an ACK until it
gets to the Rx phase and we send it a packet, but we would like to know
some of this information before we start sending packets.

A pair of tracepoints are added so that RTT determination can be observed.

Signed-off-by: David Howells 
---

 net/rxrpc/ar-internal.h |7 +--
 net/rxrpc/input.c   |   48 ++-
 net/rxrpc/misc.c|   11 ++-
 net/rxrpc/output.c  |   22 ++
 4 files changed, 80 insertions(+), 8 deletions(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 79c671e552c3..8b47f468eb9d 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -403,6 +403,7 @@ enum rxrpc_call_flag {
RXRPC_CALL_EXPOSED, /* The call was exposed to the world */
RXRPC_CALL_RX_LAST, /* Received the last packet (at 
rxtx_top) */
RXRPC_CALL_TX_LAST, /* Last packet in Tx buffer (at 
rxtx_top) */
+   RXRPC_CALL_PINGING, /* Ping in process */
 };
 
 /*
@@ -487,6 +488,8 @@ struct rxrpc_call {
u32 call_id;/* call ID on connection  */
u32 cid;/* connection ID plus channel 
index */
int debug_id;   /* debug ID for printks */
+   unsigned short  rx_pkt_offset;  /* Current recvmsg packet 
offset */
+   unsigned short  rx_pkt_len; /* Current recvmsg packet len */
 
/* Rx/Tx circular buffer, depending on phase.
 *
@@ -530,8 +533,8 @@ struct rxrpc_call {
u16 ackr_skew;  /* skew on packet being ACK'd */
rxrpc_serial_t  ackr_serial;/* serial of packet being ACK'd 
*/
rxrpc_seq_t ackr_prev_seq;  /* previous sequence number 
received */
-   unsigned short  rx_pkt_offset;  /* Current recvmsg packet 
offset */
-   unsigned short  rx_pkt_len; /* Current recvmsg packet len */
+   rxrpc_serial_t  ackr_ping;  /* Last ping sent */
+   ktime_t ackr_ping_time; /* Time last ping sent */
 
/* transmission-phase ACK management */
rxrpc_serial_t  acks_latest;/* serial number of latest ACK 
received */
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index aa261df9fc9e..a0a5bd108c9e 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -37,6 +37,19 @@ static void rxrpc_proto_abort(const char *why,
 }
 
 /*
+ * Ping the other end to fill our RTT cache and to retrieve the rwind
+ * and MTU parameters.
+ */
+static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb,
+   int skew)
+{
+   struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+
+   rxrpc_propose_ACK(call, RXRPC_ACK_PING, skew, sp->hdr.serial,
+ true, true);
+}
+
+/*
  * Apply a hard ACK by advancing the Tx window.
  */
 static void rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to)
@@ -343,6 +356,32 @@ ack:
 }
 
 /*
+ * Process a ping response.
+ */
+static void rxrpc_input_ping_response(struct rxrpc_call *call,
+ ktime_t resp_time,
+ rxrpc_serial_t orig_serial,
+ rxrpc_serial_t ack_serial)
+{
+   rxrpc_serial_t ping_serial;
+   ktime_t ping_time;
+
+   ping_time = call->ackr_ping_time;
+   smp_rmb();
+   ping_serial = call->ackr_ping;
+
+   if (!test_bit(RXRPC_CALL_PINGING, >flags) ||
+   before(orig_serial, ping_serial))
+   return;
+   clear_bit(RXRPC_CALL_PINGING, >flags);
+   if (after(orig_serial, ping_serial))
+   return;
+
+   rxrpc_peer_add_rtt(call, rxrpc_rtt_rx_ping_response,
+  orig_serial, ack_serial, ping_time, resp_time);
+}
+
+/*
  * Process the extra information that may be appended to an ACK packet
  */
 static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb,
@@ -438,6 +477,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct 
sk_buff *skb,
struct rxrpc_ackinfo info;
u8 acks[RXRPC_MAXACKS];
} buf;
+   rxrpc_serial_t acked_serial;
rxrpc_seq_t first_soft_ack, hard_ack;
int nr_acks, offset;
 
@@ -449,6 +489,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct 
sk_buff *skb,
}
sp->offset += sizeof(buf.ack);
 
+   acked_serial = ntohl(buf.ack.serial);