rxrpc: Allow a delay to be injected into packet reception
If CONFIG_AF_RXRPC_DEBUG_RX_DELAY=y, then a delay is injected between packets and errors being received and them being made available to the processing code, thereby allowing the RTT to be artificially increased. Signed-off-by: David Howells <dhowells@redhat.com> cc: Marc Dionne <marc.dionne@auristor.com> cc: linux-afs@lists.infradead.org
This commit is contained in:
parent
223f59016f
commit
af094824f2
|
@ -36,6 +36,15 @@ config AF_RXRPC_INJECT_LOSS
|
|||
Say Y here to inject packet loss by discarding some received and some
|
||||
transmitted packets.
|
||||
|
||||
config AF_RXRPC_INJECT_RX_DELAY
|
||||
bool "Inject delay into packet reception"
|
||||
depends on SYSCTL
|
||||
help
|
||||
Say Y here to inject a delay into packet reception, allowing an
|
||||
extended RTT time to be modelled. The delay can be configured using
|
||||
/proc/sys/net/rxrpc/rxrpc_inject_rx_delay, setting a number of
|
||||
milliseconds up to 0.5s (note that the granularity is actually in
|
||||
jiffies).
|
||||
|
||||
config AF_RXRPC_DEBUG
|
||||
bool "RxRPC dynamic debugging"
|
||||
|
|
|
@ -285,6 +285,9 @@ struct rxrpc_local {
|
|||
struct completion io_thread_ready; /* Indication that the I/O thread started */
|
||||
struct rxrpc_sock *service; /* Service(s) listening on this endpoint */
|
||||
struct rw_semaphore defrag_sem; /* control re-enablement of IP DF bit */
|
||||
#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
|
||||
struct sk_buff_head rx_delay_queue; /* Delay injection queue */
|
||||
#endif
|
||||
struct sk_buff_head rx_queue; /* Received packets */
|
||||
struct list_head conn_attend_q; /* Conns requiring immediate attention */
|
||||
struct list_head call_attend_q; /* Calls requiring immediate attention */
|
||||
|
@ -1109,6 +1112,9 @@ extern unsigned long rxrpc_idle_ack_delay;
|
|||
extern unsigned int rxrpc_rx_window_size;
|
||||
extern unsigned int rxrpc_rx_mtu;
|
||||
extern unsigned int rxrpc_rx_jumbo_max;
|
||||
#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
|
||||
extern unsigned long rxrpc_inject_rx_delay;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* net_ns.c
|
||||
|
|
|
@ -25,6 +25,7 @@ static int rxrpc_input_packet_on_conn(struct rxrpc_connection *conn,
|
|||
*/
|
||||
int rxrpc_encap_rcv(struct sock *udp_sk, struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff_head *rx_queue;
|
||||
struct rxrpc_local *local = rcu_dereference_sk_user_data(udp_sk);
|
||||
|
||||
if (unlikely(!local)) {
|
||||
|
@ -36,7 +37,16 @@ int rxrpc_encap_rcv(struct sock *udp_sk, struct sk_buff *skb)
|
|||
|
||||
skb->mark = RXRPC_SKB_MARK_PACKET;
|
||||
rxrpc_new_skb(skb, rxrpc_skb_new_encap_rcv);
|
||||
skb_queue_tail(&local->rx_queue, skb);
|
||||
rx_queue = &local->rx_queue;
|
||||
#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
|
||||
if (rxrpc_inject_rx_delay ||
|
||||
!skb_queue_empty(&local->rx_delay_queue)) {
|
||||
skb->tstamp = ktime_add_ms(skb->tstamp, rxrpc_inject_rx_delay);
|
||||
rx_queue = &local->rx_delay_queue;
|
||||
}
|
||||
#endif
|
||||
|
||||
skb_queue_tail(rx_queue, skb);
|
||||
rxrpc_wake_up_io_thread(local);
|
||||
return 0;
|
||||
}
|
||||
|
@ -407,6 +417,9 @@ int rxrpc_io_thread(void *data)
|
|||
struct rxrpc_local *local = data;
|
||||
struct rxrpc_call *call;
|
||||
struct sk_buff *skb;
|
||||
#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
|
||||
ktime_t now;
|
||||
#endif
|
||||
bool should_stop;
|
||||
|
||||
complete(&local->io_thread_ready);
|
||||
|
@ -481,6 +494,17 @@ int rxrpc_io_thread(void *data)
|
|||
continue;
|
||||
}
|
||||
|
||||
/* Inject a delay into packets if requested. */
|
||||
#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
|
||||
now = ktime_get_real();
|
||||
while ((skb = skb_peek(&local->rx_delay_queue))) {
|
||||
if (ktime_before(now, skb->tstamp))
|
||||
break;
|
||||
skb = skb_dequeue(&local->rx_delay_queue);
|
||||
skb_queue_tail(&local->rx_queue, skb);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!skb_queue_empty(&local->rx_queue)) {
|
||||
spin_lock_irq(&local->rx_queue.lock);
|
||||
skb_queue_splice_tail_init(&local->rx_queue, &rx_queue);
|
||||
|
@ -502,6 +526,28 @@ int rxrpc_io_thread(void *data)
|
|||
|
||||
if (should_stop)
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
|
||||
skb = skb_peek(&local->rx_delay_queue);
|
||||
if (skb) {
|
||||
unsigned long timeout;
|
||||
ktime_t tstamp = skb->tstamp;
|
||||
ktime_t now = ktime_get_real();
|
||||
s64 delay_ns = ktime_to_ns(ktime_sub(tstamp, now));
|
||||
|
||||
if (delay_ns <= 0) {
|
||||
__set_current_state(TASK_RUNNING);
|
||||
continue;
|
||||
}
|
||||
|
||||
timeout = nsecs_to_jiffies(delay_ns);
|
||||
timeout = max(timeout, 1UL);
|
||||
schedule_timeout(timeout);
|
||||
__set_current_state(TASK_RUNNING);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
schedule();
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,9 @@ static struct rxrpc_local *rxrpc_alloc_local(struct net *net,
|
|||
INIT_HLIST_NODE(&local->link);
|
||||
init_rwsem(&local->defrag_sem);
|
||||
init_completion(&local->io_thread_ready);
|
||||
#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
|
||||
skb_queue_head_init(&local->rx_delay_queue);
|
||||
#endif
|
||||
skb_queue_head_init(&local->rx_queue);
|
||||
INIT_LIST_HEAD(&local->conn_attend_q);
|
||||
INIT_LIST_HEAD(&local->call_attend_q);
|
||||
|
@ -434,6 +437,9 @@ void rxrpc_destroy_local(struct rxrpc_local *local)
|
|||
/* At this point, there should be no more packets coming in to the
|
||||
* local endpoint.
|
||||
*/
|
||||
#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
|
||||
rxrpc_purge_queue(&local->rx_delay_queue);
|
||||
#endif
|
||||
rxrpc_purge_queue(&local->rx_queue);
|
||||
rxrpc_purge_client_connections(local);
|
||||
}
|
||||
|
|
|
@ -53,3 +53,10 @@ unsigned int rxrpc_rx_mtu = 5692;
|
|||
* sender that we're willing to handle.
|
||||
*/
|
||||
unsigned int rxrpc_rx_jumbo_max = 4;
|
||||
|
||||
#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
|
||||
/*
|
||||
* The delay to inject into packet reception.
|
||||
*/
|
||||
unsigned long rxrpc_inject_rx_delay;
|
||||
#endif
|
||||
|
|
|
@ -17,6 +17,9 @@ static const unsigned int n_65535 = 65535;
|
|||
static const unsigned int n_max_acks = 255;
|
||||
static const unsigned long one_jiffy = 1;
|
||||
static const unsigned long max_jiffies = MAX_JIFFY_OFFSET;
|
||||
#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
|
||||
static const unsigned long max_500 = 500;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* RxRPC operating parameters.
|
||||
|
@ -63,6 +66,19 @@ static struct ctl_table rxrpc_sysctl_table[] = {
|
|||
.extra2 = (void *)&max_jiffies,
|
||||
},
|
||||
|
||||
/* Values used in milliseconds */
|
||||
#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
|
||||
{
|
||||
.procname = "inject_rx_delay",
|
||||
.data = &rxrpc_inject_rx_delay,
|
||||
.maxlen = sizeof(unsigned long),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_doulongvec_minmax,
|
||||
.extra1 = (void *)SYSCTL_LONG_ZERO,
|
||||
.extra2 = (void *)&max_500,
|
||||
},
|
||||
#endif
|
||||
|
||||
/* Non-time values */
|
||||
{
|
||||
.procname = "reap_client_conns",
|
||||
|
@ -109,7 +125,6 @@ static struct ctl_table rxrpc_sysctl_table[] = {
|
|||
.extra1 = (void *)SYSCTL_ONE,
|
||||
.extra2 = (void *)&four,
|
||||
},
|
||||
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue