Commit af094824 authored by David Howells's avatar David Howells
Browse files

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: default avatarDavid Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
parent 223f5901
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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"
+6 −0
Original line number Diff line number Diff line
@@ -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
+47 −1
Original line number Diff line number Diff line
@@ -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();
	}

+6 −0
Original line number Diff line number Diff line
@@ -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);
}
+7 −0
Original line number Diff line number Diff line
@@ -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
Loading