mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-16 02:14:58 +00:00
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
|
Say Y here to inject packet loss by discarding some received and some
|
||||||
transmitted packets.
|
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
|
config AF_RXRPC_DEBUG
|
||||||
bool "RxRPC dynamic debugging"
|
bool "RxRPC dynamic debugging"
|
||||||
|
@ -285,6 +285,9 @@ struct rxrpc_local {
|
|||||||
struct completion io_thread_ready; /* Indication that the I/O thread started */
|
struct completion io_thread_ready; /* Indication that the I/O thread started */
|
||||||
struct rxrpc_sock *service; /* Service(s) listening on this endpoint */
|
struct rxrpc_sock *service; /* Service(s) listening on this endpoint */
|
||||||
struct rw_semaphore defrag_sem; /* control re-enablement of IP DF bit */
|
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 sk_buff_head rx_queue; /* Received packets */
|
||||||
struct list_head conn_attend_q; /* Conns requiring immediate attention */
|
struct list_head conn_attend_q; /* Conns requiring immediate attention */
|
||||||
struct list_head call_attend_q; /* Calls 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_window_size;
|
||||||
extern unsigned int rxrpc_rx_mtu;
|
extern unsigned int rxrpc_rx_mtu;
|
||||||
extern unsigned int rxrpc_rx_jumbo_max;
|
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
|
* 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)
|
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);
|
struct rxrpc_local *local = rcu_dereference_sk_user_data(udp_sk);
|
||||||
|
|
||||||
if (unlikely(!local)) {
|
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;
|
skb->mark = RXRPC_SKB_MARK_PACKET;
|
||||||
rxrpc_new_skb(skb, rxrpc_skb_new_encap_rcv);
|
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);
|
rxrpc_wake_up_io_thread(local);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -407,6 +417,9 @@ int rxrpc_io_thread(void *data)
|
|||||||
struct rxrpc_local *local = data;
|
struct rxrpc_local *local = data;
|
||||||
struct rxrpc_call *call;
|
struct rxrpc_call *call;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
|
||||||
|
ktime_t now;
|
||||||
|
#endif
|
||||||
bool should_stop;
|
bool should_stop;
|
||||||
|
|
||||||
complete(&local->io_thread_ready);
|
complete(&local->io_thread_ready);
|
||||||
@ -481,6 +494,17 @@ int rxrpc_io_thread(void *data)
|
|||||||
continue;
|
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)) {
|
if (!skb_queue_empty(&local->rx_queue)) {
|
||||||
spin_lock_irq(&local->rx_queue.lock);
|
spin_lock_irq(&local->rx_queue.lock);
|
||||||
skb_queue_splice_tail_init(&local->rx_queue, &rx_queue);
|
skb_queue_splice_tail_init(&local->rx_queue, &rx_queue);
|
||||||
@ -502,6 +526,28 @@ int rxrpc_io_thread(void *data)
|
|||||||
|
|
||||||
if (should_stop)
|
if (should_stop)
|
||||||
break;
|
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();
|
schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,6 +110,9 @@ static struct rxrpc_local *rxrpc_alloc_local(struct net *net,
|
|||||||
INIT_HLIST_NODE(&local->link);
|
INIT_HLIST_NODE(&local->link);
|
||||||
init_rwsem(&local->defrag_sem);
|
init_rwsem(&local->defrag_sem);
|
||||||
init_completion(&local->io_thread_ready);
|
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);
|
skb_queue_head_init(&local->rx_queue);
|
||||||
INIT_LIST_HEAD(&local->conn_attend_q);
|
INIT_LIST_HEAD(&local->conn_attend_q);
|
||||||
INIT_LIST_HEAD(&local->call_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
|
/* At this point, there should be no more packets coming in to the
|
||||||
* local endpoint.
|
* 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_queue(&local->rx_queue);
|
||||||
rxrpc_purge_client_connections(local);
|
rxrpc_purge_client_connections(local);
|
||||||
}
|
}
|
||||||
|
@ -53,3 +53,10 @@ unsigned int rxrpc_rx_mtu = 5692;
|
|||||||
* sender that we're willing to handle.
|
* sender that we're willing to handle.
|
||||||
*/
|
*/
|
||||||
unsigned int rxrpc_rx_jumbo_max = 4;
|
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 int n_max_acks = 255;
|
||||||
static const unsigned long one_jiffy = 1;
|
static const unsigned long one_jiffy = 1;
|
||||||
static const unsigned long max_jiffies = MAX_JIFFY_OFFSET;
|
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.
|
* RxRPC operating parameters.
|
||||||
@ -63,6 +66,19 @@ static struct ctl_table rxrpc_sysctl_table[] = {
|
|||||||
.extra2 = (void *)&max_jiffies,
|
.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 */
|
/* Non-time values */
|
||||||
{
|
{
|
||||||
.procname = "reap_client_conns",
|
.procname = "reap_client_conns",
|
||||||
@ -109,7 +125,6 @@ static struct ctl_table rxrpc_sysctl_table[] = {
|
|||||||
.extra1 = (void *)SYSCTL_ONE,
|
.extra1 = (void *)SYSCTL_ONE,
|
||||||
.extra2 = (void *)&four,
|
.extra2 = (void *)&four,
|
||||||
},
|
},
|
||||||
|
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user