[RFC][PATCH 4/5] I/OAT DMA support and TCP acceleration

From: Chris Leech
Date: Wed Dec 21 2005 - 00:18:40 EST


Structure changes for TCP recv offload to I/OAT

Adds an async_wait_queue and some additional fields to tcp_sock, a
copied_early flag to sb_buff and a dma_cookie_t to tcp_skb_cb

Renames cleanup_rbuf to tcp_cleanup_rbuf and makes it non-static so we
can call it from tcp_input.c

---
include/linux/skbuff.h | 5 +++--
include/linux/tcp.h | 9 +++++++++
include/net/tcp.h | 10 ++++++++++
net/core/skbuff.c | 1 +
net/ipv4/tcp.c | 11 ++++++-----
net/ipv4/tcp_ipv4.c | 4 ++++
net/ipv4/tcp_minisocks.c | 1 +
net/ipv6/tcp_ipv6.c | 1 +
8 files changed, 35 insertions(+), 7 deletions(-)
diff -urp a/include/linux/skbuff.h b/include/linux/skbuff.h
--- a/include/linux/skbuff.h 2005-12-21 12:05:09.000000000 -0800
+++ b/include/linux/skbuff.h 2005-12-21 12:10:14.000000000 -0800
@@ -248,7 +248,7 @@ struct sk_buff {
* want to keep them across layers you have to do a skb_clone()
* first. This is owned by whoever has the skb queued ATM.
*/
- char cb[40];
+ char cb[44];

unsigned int len,
data_len,
@@ -261,7 +261,8 @@ struct sk_buff {
nohdr:1,
nfctinfo:3;
__u8 pkt_type:3,
- fclone:2;
+ fclone:2,
+ copied_early:1;
__be16 protocol;

void (*destructor)(struct sk_buff *skb);
diff -urp a/include/linux/tcp.h b/include/linux/tcp.h
--- a/include/linux/tcp.h 2005-12-21 12:05:09.000000000 -0800
+++ b/include/linux/tcp.h 2005-12-21 12:10:14.000000000 -0800
@@ -18,6 +18,7 @@
#define _LINUX_TCP_H

#include <linux/types.h>
+#include <linux/dmaengine.h>
#include <asm/byteorder.h>

struct tcphdr {
@@ -249,6 +250,13 @@ struct tcp_sock {
struct iovec *iov;
int memory;
int len;
+
+ /* members for async copy */
+ int wakeup;
+ struct dma_chan *dma_chan;
+ int bytes_early_copied;
+ struct dma_locked_list *locked_list;
+ dma_cookie_t dma_cookie;
} ucopy;

__u32 snd_wl1; /* Sequence for window update */
@@ -294,6 +302,7 @@ struct tcp_sock {
__u32 snd_cwnd_stamp;

struct sk_buff_head out_of_order_queue; /* Out of order segments go here */
+ struct sk_buff_head async_wait_queue; /* DMA unfinished segments go here */

struct tcp_func *af_specific; /* Operations which are AF_INET{4,6} specific */

diff -urp a/include/net/tcp.h b/include/net/tcp.h
--- a/include/net/tcp.h 2005-12-21 12:05:09.000000000 -0800
+++ b/include/net/tcp.h 2005-12-21 12:10:14.000000000 -0800
@@ -563,6 +563,9 @@ extern u32 __tcp_select_window(struct so
* 40 bytes on 64-bit machines, if this grows please adjust
* skbuff.h:skbuff->cb[xxx] size appropriately.
*/
+
+#include <linux/dmaengine.h>
+
struct tcp_skb_cb {
union {
struct inet_skb_parm h4;
@@ -602,6 +605,7 @@ struct tcp_skb_cb {

__u16 urg_ptr; /* Valid w/URG flags is set. */
__u32 ack_seq; /* Sequence number ACK'd */
+ dma_cookie_t dma_cookie; /* async copy token */
};

#define TCP_SKB_CB(__skb) ((struct tcp_skb_cb *)&((__skb)->cb[0]))
@@ -867,8 +871,14 @@ static __inline__ void tcp_prequeue_init
{
tp->ucopy.task = NULL;
tp->ucopy.len = 0;
+ tp->ucopy.wakeup = 0;
tp->ucopy.memory = 0;
skb_queue_head_init(&tp->ucopy.prequeue);
+
+ tp->ucopy.dma_chan = NULL;
+ tp->ucopy.bytes_early_copied = 0;
+ tp->ucopy.locked_list = NULL;
+ tp->ucopy.dma_cookie = 0;
}

/* Packet is added to VJ-style prequeue for processing in process
diff -urp a/net/core/skbuff.c b/net/core/skbuff.c
--- a/net/core/skbuff.c 2005-12-21 12:05:09.000000000 -0800
+++ b/net/core/skbuff.c 2005-12-21 12:10:14.000000000 -0800
@@ -400,6 +400,7 @@ struct sk_buff *skb_clone(struct sk_buff
C(local_df);
n->cloned = 1;
n->nohdr = 0;
+ C(copied_early);
C(pkt_type);
C(ip_summed);
C(priority);
diff -urp a/net/ipv4/tcp.c b/net/ipv4/tcp.c
--- a/net/ipv4/tcp.c 2005-12-21 12:05:09.000000000 -0800
+++ b/net/ipv4/tcp.c 2005-12-21 12:10:27.000000000 -0800
@@ -936,7 +936,7 @@ static int tcp_recv_urg(struct sock *sk,
* calculation of whether or not we must ACK for the sake of
* a window update.
*/
-static void cleanup_rbuf(struct sock *sk, int copied)
+void tcp_cleanup_rbuf(struct sock *sk, int copied)
{
struct tcp_sock *tp = tcp_sk(sk);
int time_to_ack = 0;
@@ -1085,7 +1085,7 @@ int tcp_read_sock(struct sock *sk, read_

/* Clean up data we have read: This will do ACK frames. */
if (copied)
- cleanup_rbuf(sk, copied);
+ tcp_cleanup_rbuf(sk, copied);
return copied;
}

@@ -1219,7 +1219,7 @@ int tcp_recvmsg(struct kiocb *iocb, stru
}
}

- cleanup_rbuf(sk, copied);
+ tcp_cleanup_rbuf(sk, copied);

if (!sysctl_tcp_low_latency && tp->ucopy.task == user_recv) {
/* Install new reader */
@@ -1390,7 +1390,7 @@ skip_copy:
*/

/* Clean up data we have read: This will do ACK frames. */
- cleanup_rbuf(sk, copied);
+ tcp_cleanup_rbuf(sk, copied);

TCP_CHECK_TIMER(sk);
release_sock(sk);
@@ -1652,6 +1652,7 @@ int tcp_disconnect(struct sock *sk, int
__skb_queue_purge(&sk->sk_receive_queue);
sk_stream_writequeue_purge(sk);
__skb_queue_purge(&tp->out_of_order_queue);
+ __skb_queue_purge(&tp->async_wait_queue);

inet->dport = 0;

@@ -1855,7 +1856,7 @@ int tcp_setsockopt(struct sock *sk, int
(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT) &&
inet_csk_ack_scheduled(sk)) {
icsk->icsk_ack.pending |= ICSK_ACK_PUSHED;
- cleanup_rbuf(sk, 1);
+ tcp_cleanup_rbuf(sk, 1);
if (!(val & 1))
icsk->icsk_ack.pingpong = 1;
}
diff -urp a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
--- a/net/ipv4/tcp_ipv4.c 2005-12-14 15:50:41.000000000 -0800
+++ b/net/ipv4/tcp_ipv4.c 2005-12-21 12:10:27.000000000 -0800
@@ -1414,6 +1414,7 @@ static int tcp_v4_init_sock(struct sock
struct tcp_sock *tp = tcp_sk(sk);

skb_queue_head_init(&tp->out_of_order_queue);
+ skb_queue_head_init(&tp->async_wait_queue);
tcp_init_xmit_timers(sk);
tcp_prequeue_init(tp);

@@ -1466,6 +1467,9 @@ int tcp_v4_destroy_sock(struct sock *sk)
/* Cleans up our, hopefully empty, out_of_order_queue. */
__skb_queue_purge(&tp->out_of_order_queue);

+ /* Cleans up our async_wait_queue */
+ __skb_queue_purge(&tp->async_wait_queue);
+
/* Clean prequeue, it must be empty really */
__skb_queue_purge(&tp->ucopy.prequeue);

diff -urp a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
--- a/net/ipv4/tcp_minisocks.c 2005-12-14 15:50:41.000000000 -0800
+++ b/net/ipv4/tcp_minisocks.c 2005-12-21 12:10:27.000000000 -0800
@@ -389,6 +389,7 @@ struct sock *tcp_create_openreq_child(st
tcp_set_ca_state(newsk, TCP_CA_Open);
tcp_init_xmit_timers(newsk);
skb_queue_head_init(&newtp->out_of_order_queue);
+ skb_queue_head_init(&newtp->async_wait_queue);
newtp->rcv_wup = treq->rcv_isn + 1;
newtp->write_seq = treq->snt_isn + 1;
newtp->pushed_seq = newtp->write_seq;
diff -urp a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
--- a/net/ipv6/tcp_ipv6.c 2005-12-14 15:50:41.000000000 -0800
+++ b/net/ipv6/tcp_ipv6.c 2005-12-21 12:10:27.000000000 -0800
@@ -1863,6 +1863,7 @@ static int tcp_v6_init_sock(struct sock
struct tcp_sock *tp = tcp_sk(sk);

skb_queue_head_init(&tp->out_of_order_queue);
+ skb_queue_head_init(&tp->async_wait_queue);
tcp_init_xmit_timers(sk);
tcp_prequeue_init(tp);


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/