[ofa-general] [PATCH] sdp: don't do nagle on first packet

Amir Vadai amirv at mellanox.co.il
Mon Jun 22 01:18:45 PDT 2009


Send first packet immediately - even when nagle is on

Signed-off-by: Amir Vadai <amirv at mellanox.co.il>
---
 drivers/infiniband/ulp/sdp/sdp.h       |    5 +++
 drivers/infiniband/ulp/sdp/sdp_bcopy.c |   48 ++++++++++++++++++++++++++++++--
 drivers/infiniband/ulp/sdp/sdp_rx.c    |    6 +++-
 drivers/infiniband/ulp/sdp/sdp_tx.c    |   11 +++++--
 4 files changed, 63 insertions(+), 7 deletions(-)

diff --git a/drivers/infiniband/ulp/sdp/sdp.h b/drivers/infiniband/ulp/sdp/sdp.h
index 57265aa..4bc81e1 100644
--- a/drivers/infiniband/ulp/sdp/sdp.h
+++ b/drivers/infiniband/ulp/sdp/sdp.h
@@ -213,6 +213,7 @@ static inline void sdpstats_hist(u32 *h, u32 val, u32 maxidx, int is_log)
    instead of interrupts (in per-core Tx rings) - should be power of 2 */
 #define SDP_TX_POLL_MODER	16
 #define SDP_TX_POLL_TIMEOUT	(HZ / 4)
+#define SDP_NAGLE_TIMEOUT (HZ / 10) 
 
 #define SDP_RESOLVE_TIMEOUT 1000
 #define SDP_ROUTE_TIMEOUT 1000
@@ -406,6 +407,9 @@ struct sdp_sock {
 	unsigned max_bufs;	/* Initial buffers offered by other side */
 	unsigned min_bufs;	/* Low water mark to wake senders */
 
+	unsigned long nagle_last_unacked; /* mseq of lastest unacked packet */
+	struct timer_list nagle_timer; /* timeout waiting for ack */
+
 	atomic_t               remote_credits;
 #define remote_credits(ssk) (atomic_read(&ssk->remote_credits))
 	int 		  poll_cq;
@@ -552,6 +556,7 @@ int sdp_xmit_poll(struct sdp_sock *ssk, int force);
 void sdp_post_send(struct sdp_sock *ssk, struct sk_buff *skb, u8 mid);
 void _sdp_post_sends(const char *func, int line, struct sdp_sock *ssk, int nonagle);
 #define sdp_post_sends(ssk, nonagle) _sdp_post_sends(__func__, __LINE__, ssk, nonagle)
+void sdp_nagle_timeout(unsigned long data);
 
 /* sdp_rx.c */
 void sdp_rx_ring_init(struct sdp_sock *ssk);
diff --git a/drivers/infiniband/ulp/sdp/sdp_bcopy.c b/drivers/infiniband/ulp/sdp/sdp_bcopy.c
index b98171e..3465035 100644
--- a/drivers/infiniband/ulp/sdp/sdp_bcopy.c
+++ b/drivers/infiniband/ulp/sdp/sdp_bcopy.c
@@ -105,12 +105,54 @@ static inline void update_send_head(struct sock *sk, struct sk_buff *skb)
 
 static inline int sdp_nagle_off(struct sdp_sock *ssk, struct sk_buff *skb)
 {
-	return (ssk->nonagle & TCP_NAGLE_OFF) ||
+	int send_now =
+		 (ssk->nonagle & TCP_NAGLE_OFF) ||
+		!ssk->nagle_last_unacked ||
 		skb->next != (struct sk_buff *)&ssk->isk.sk.sk_write_queue ||
 		skb->len + sizeof(struct sdp_bsdh) >= ssk->xmit_size_goal ||
-		(ring_tail(ssk->tx_ring) == ring_head(ssk->tx_ring) &&
-		 !(ssk->nonagle & TCP_NAGLE_CORK)) ||
 		(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_PSH);
+
+	if (send_now) {
+		unsigned long mseq = ring_head(ssk->tx_ring);
+		ssk->nagle_last_unacked = mseq;
+
+		mod_timer(&ssk->nagle_timer, jiffies + SDP_NAGLE_TIMEOUT);
+		sdp_dbg_data(&ssk->isk.sk, "Starting nagle timer\n");
+	}
+	sdp_dbg_data(&ssk->isk.sk, "send_now = %d last_unacked = %ld\n",
+		send_now, ssk->nagle_last_unacked);
+	
+	return send_now;
+}
+
+void sdp_nagle_timeout(unsigned long data)
+{
+	struct sdp_sock *ssk = (struct sdp_sock *)data;
+	struct sock *sk = &ssk->isk.sk;
+
+	sdp_dbg_data(&ssk->isk.sk, "last_unacked = %ld\n", ssk->nagle_last_unacked);
+
+	if (!ssk->nagle_last_unacked)
+		return;
+
+	/* Only process if the socket is not in use */
+	bh_lock_sock(sk);
+	if (sock_owned_by_user(sk)) {
+		mod_timer(&ssk->nagle_timer, jiffies + SDP_NAGLE_TIMEOUT);
+		sdp_dbg_data(&ssk->isk.sk, "socket is busy - trying later\n");
+		goto out;
+	}
+
+	if (sk->sk_state == TCP_CLOSE)
+		goto out;
+
+	ssk->nagle_last_unacked = 0;
+	sdp_post_sends(ssk, 0);
+
+	if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+		sk_stream_write_space(&ssk->isk.sk);
+out:
+	bh_unlock_sock(sk);
 }
 
 int sdp_post_credits(struct sdp_sock *ssk)
diff --git a/drivers/infiniband/ulp/sdp/sdp_rx.c b/drivers/infiniband/ulp/sdp/sdp_rx.c
index 895ec12..05d8690 100644
--- a/drivers/infiniband/ulp/sdp/sdp_rx.c
+++ b/drivers/infiniband/ulp/sdp/sdp_rx.c
@@ -490,6 +490,7 @@ static struct sk_buff *sdp_process_rx_wc(struct sdp_sock *ssk, struct ib_wc *wc)
 	struct sdp_bsdh *h;
 	struct sock *sk = &ssk->isk.sk;
 	int credits_before;
+	unsigned long mseq_ack;
 	
 	skb = sdp_recv_completion(ssk, wc->wr_id);
 	if (unlikely(!skb))
@@ -536,9 +537,12 @@ static struct sk_buff *sdp_process_rx_wc(struct sdp_sock *ssk, struct ib_wc *wc)
 
 	SDPSTATS_HIST_LINEAR(credits_before_update, tx_credits(ssk));
 
+	mseq_ack = ntohl(h->mseq_ack);
 	credits_before = tx_credits(ssk);
-	atomic_set(&ssk->tx_ring.credits, ntohl(h->mseq_ack) - ring_head(ssk->tx_ring) + 1 +
+	atomic_set(&ssk->tx_ring.credits, mseq_ack - ring_head(ssk->tx_ring) + 1 +
 		ntohs(h->bufs));
+	if (mseq_ack >= ssk->nagle_last_unacked)
+		ssk->nagle_last_unacked = 0;
 
 	sdp_prf(&ssk->isk.sk, skb, "RX %s bufs=%d c before:%d after:%d "
 		"mseq:%d, ack:%d", mid2str(h->mid), ntohs(h->bufs), credits_before, 
diff --git a/drivers/infiniband/ulp/sdp/sdp_tx.c b/drivers/infiniband/ulp/sdp/sdp_tx.c
index 28720b9..a7d16fe 100644
--- a/drivers/infiniband/ulp/sdp/sdp_tx.c
+++ b/drivers/infiniband/ulp/sdp/sdp_tx.c
@@ -68,7 +68,7 @@ void sdp_post_send(struct sdp_sock *ssk, struct sk_buff *skb, u8 mid)
 {
 	struct sdp_buf *tx_req;
 	struct sdp_bsdh *h = (struct sdp_bsdh *)skb_push(skb, sizeof *h);
-	unsigned mseq = ring_head(ssk->tx_ring);
+	unsigned long mseq = ring_head(ssk->tx_ring);
 	int i, rc, frags;
 	u64 addr;
 	struct ib_device *dev;
@@ -78,7 +78,6 @@ void sdp_post_send(struct sdp_sock *ssk, struct sk_buff *skb, u8 mid)
 	struct ib_sge *sge = ibsge;
 	struct ib_send_wr tx_wr = { 0 };
 
-
 	SDPSTATS_COUNTER_MID_INC(post_send, mid);
 	SDPSTATS_HIST(send_size, skb->len);
 
@@ -93,7 +92,7 @@ void sdp_post_send(struct sdp_sock *ssk, struct sk_buff *skb, u8 mid)
 	h->mseq = htonl(mseq);
 	h->mseq_ack = htonl(mseq_ack(ssk));
 
-	sdp_prf(&ssk->isk.sk, skb, "TX: %s bufs: %d mseq:%d ack:%d",
+	sdp_prf(&ssk->isk.sk, skb, "TX: %s bufs: %d mseq:%ld ack:%d",
 			mid2str(mid), ring_posted(ssk->rx_ring), mseq, ntohl(h->mseq_ack));
 
 	SDP_DUMP_PACKET(&ssk->isk.sk, "TX", skb, h);
@@ -405,6 +404,10 @@ int sdp_tx_ring_create(struct sdp_sock *ssk, struct ib_device *device)
 	ssk->tx_ring.timer.data = (unsigned long) ssk;
 	ssk->tx_ring.poll_cnt = 0;
 
+	init_timer(&ssk->nagle_timer);
+	ssk->nagle_timer.function = sdp_nagle_timeout;
+	ssk->nagle_timer.data = (unsigned long) ssk;
+
 	return 0;
 
 err_cq:
@@ -416,6 +419,8 @@ out:
 
 void sdp_tx_ring_destroy(struct sdp_sock *ssk)
 {
+	del_timer(&ssk->nagle_timer);
+
 	if (ssk->tx_ring.buffer) {
 		sdp_tx_ring_purge(ssk);
 
-- 
1.5.3.7




More information about the general mailing list