[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-virtual-server
Subject:    [PATCH]add simple unsplicing to tcpsp-0.0.3 with the help of a
From:       "yangrunhua" <yangrunhua () njupt ! edu ! cn>
Date:       2003-10-29 7:14:42
[Download RAW message or body]

Hi all,
	Current tcpsp doesn't seem to have a way to stop forwarding for already spliced TCP \
connections. I wrote this small patch to archive this with the help of a cookie(a \
__u32 number). It is much useful in practice when we want to stop particular spliced \
TCP connections, rather then to rmmod the whole tcpsp module.

diff -urN tcpsp/example/forwarder.c tcpspnew/example/forwarder.c
--- tcpsp/example/forwarder.c	2002-04-24 19:42:07.000000000 +0800
+++ tcpspnew/example/forwarder.c	2003-10-28 17:47:21.000000000 +0800
@@ -40,10 +40,10 @@
 }
 
 
-int tcpsplicing(int fd1, int fd2, int n)
+int tcpsplicing(int fd1, int fd2, int n, __u32 cookie)
 {
 	int sockfd;
-	splice_conn_t sp = {fd1, fd2, n};
+	splice_conn_t sp = {fd1, fd2, n, cookie};
 
 	if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1)
 		return -1;
@@ -109,7 +109,7 @@
 		exit(1);
 	}
 
-	if (tcpsplicing(fd1, fd2, n))
+	if (tcpsplicing(fd1, fd2, n, 1/*cookie*/))
 		printf("tcpsplicing failed\n");
 	else
 		printf("tcpsplicing succeeded\n");
diff -urN tcpsp/tcpsp_conn.c tcpspnew/tcpsp_conn.c
--- tcpsp/tcpsp_conn.c	2003-10-27 00:26:19.000000000 +0800
+++ tcpspnew/tcpsp_conn.c	2003-10-29 14:14:20.000000000 +0800
@@ -46,9 +46,10 @@
 static kmem_cache_t *tcpsp_conn_cachep;
 
 /* tcpsp onnection hash tables */
-#define TCPSP_NTABLES		2
+#define TCPSP_NTABLES		3
 static struct list_head *tcpsp_conn_tab1;
 static struct list_head *tcpsp_conn_tab2;
+static struct list_head *tcpsp_conn_tab3;
 
 static rwlock_t tcpsp_conn_lock = RW_LOCK_UNLOCKED;
 
@@ -68,6 +69,16 @@
 		& TCPSP_CONN_TAB_MASK;
 }
 
+/*
+ *	Returns hash value for tcpsp connection cookie
+ */
+static inline unsigned
+tcpsp_conn_hash_cookie(__u32 cookie)
+{
+	return (cookie^(cookie>>TCPSP_CONN_TAB_BITS))
+		& TCPSP_CONN_TAB_MASK;
+}
+
 
 /*
  *	Hashes tcpsp_conn in tcpsp_conn_tabs by <addr,port>.
@@ -89,6 +100,9 @@
 
 	hash = tcpsp_conn_hash_key(cp->conn[1].laddr, cp->conn[1].lport);
 	list_add(&cp->s_list, &tcpsp_conn_tab2[hash]);
+	
+	hash = tcpsp_conn_hash_cookie(cp->cookie);
+	list_add(&cp->t_list, &tcpsp_conn_tab3[hash]);
 
 	cp->flags |= TCPSP_CONN_F_HASHED;
 	atomic_add(TCPSP_NTABLES, &cp->refcnt);
@@ -111,6 +125,7 @@
 	write_lock(&tcpsp_conn_lock);
 	list_del(&cp->f_list);
 	list_del(&cp->s_list);
+	list_del(&cp->t_list);
 	cp->flags &= ~TCPSP_CONN_F_HASHED;
 	atomic_sub(TCPSP_NTABLES, &cp->refcnt);
 	write_unlock(&tcpsp_conn_lock);
@@ -474,7 +489,7 @@
  *  Create and hash a new tcpsp into the tcpsp_conn_tabs.
  */
 struct tcpsp_conn *
-tcpsp_conn_new(struct socket *sock1, struct socket *sock2, int n)
+tcpsp_conn_new(struct socket *sock1, struct socket *sock2, int n, __u32 cookie)
 {
 	struct tcp_opt *tp1, *tp2;
 	struct tcpsp_conn *cp;
@@ -500,6 +515,8 @@
 	fill_conn_tuple(&cp->conn[1], sock2->sk);
 
 	cp->conn[1].splice_iss += n;
+	
+	cp->cookie = cookie;
 
 	atomic_inc(&tcpsp_conn_count);
 
@@ -546,7 +563,7 @@
 	pos = 128;
 	if (pos > offset) {
 		len += sprintf(buffer+len, "%-127s\n",
-			       "FromIP   FPrt ToIP     TPrt LocalIP  LPrt DestIP   DPrt State       \
Expires"); +			       "FromIP   FPrt ToIP     TPrt LocalIP  LPrt DestIP   DPrt State  \
Expires Cookie  ");  }
 
 	for(idx = 0; idx < TCPSP_CONN_TAB_SIZE; idx++) {
@@ -563,7 +580,7 @@
 			if (pos <= offset)
 				continue;
 			sprintf(temp,
-				"%08X %04X %08X %04X %08X %04X %08X %04X %-11s %7lu",
+				"%08X %04X %08X %04X %08X %04X %08X %04X %-11s %7lu %08X",
 				ntohl(cp->conn[0].raddr),
 				ntohs(cp->conn[0].rport),
 				ntohl(cp->conn[0].laddr),
@@ -573,7 +590,8 @@
 				ntohl(cp->conn[1].raddr),
 				ntohs(cp->conn[1].rport),
 				tcpsp_state_name(cp->state),
-				cp->timer.expires-jiffies);
+				cp->timer.expires-jiffies,
+				cp->cookie);
 			len += sprintf(buffer+len, "%-127s\n", temp);
 			if (pos >= offset+length) {
 				read_unlock_bh(&tcpsp_conn_lock);
@@ -630,6 +648,41 @@
 	}
 }
 
+/*
+ *      Delete the connection entry matches the cookie in the tcpsp_conn_tab
+ */
+int tcpsp_conn_del(__u32 cookie)
+{
+	int idx;
+	struct tcpsp_conn *cp;
+	struct list_head *e, *nxt;
+
+  	idx = tcpsp_conn_hash_cookie(cookie);
+	/*
+	 *  Lock is actually needed in this loop.
+	 */
+	write_lock(&tcpsp_conn_lock);
+
+	list_for_each_safe (e, nxt, &tcpsp_conn_tab3[idx]) {
+		cp = list_entry(e, struct tcpsp_conn, t_list);
+		write_unlock(&tcpsp_conn_lock);
+		TCPSP_DBG(4, "del splicing connection\n");
+		if (cp->cookie == cookie){
+			if (del_timer(&cp->timer))
+				tcpsp_conn_expire_now(cp);
+			goto out_found;
+		}
+
+		write_lock(&tcpsp_conn_lock);
+	}
+	write_unlock(&tcpsp_conn_lock);
+	
+	return -EINVAL;
+
+  out_found:
+	return 0;
+}
+
 
 int tcpsp_conn_init(void)
 {
@@ -647,6 +700,13 @@
 		vfree(tcpsp_conn_tab1);
 		return -ENOMEM;
 	}
+	
+	if (!(tcpsp_conn_tab3 =
+	      vmalloc(TCPSP_CONN_TAB_SIZE * sizeof(struct list_head)))) {
+		vfree(tcpsp_conn_tab2);
+		vfree(tcpsp_conn_tab1);
+		return -ENOMEM;
+	}
 
 	/* Allocate tcpsp_conn slab cache */
 	tcpsp_conn_cachep = kmem_cache_create("tcpsp_conn",
@@ -655,6 +715,7 @@
 	if (!tcpsp_conn_cachep) {
 		vfree(tcpsp_conn_tab1);
 		vfree(tcpsp_conn_tab2);
+		vfree(tcpsp_conn_tab3);
 		return -ENOMEM;
 	}
 
@@ -668,6 +729,7 @@
 	for (idx = 0; idx < TCPSP_CONN_TAB_SIZE; idx++) {
 		INIT_LIST_HEAD(&tcpsp_conn_tab1[idx]);
 		INIT_LIST_HEAD(&tcpsp_conn_tab2[idx]);
+		INIT_LIST_HEAD(&tcpsp_conn_tab3[idx]);
 	}
 
 	proc_net_create("tcpsp_conn", 0, tcpsp_conn_getinfo);
@@ -685,4 +747,5 @@
 	proc_net_remove("tcpsp_conn");
 	vfree(tcpsp_conn_tab1);
 	vfree(tcpsp_conn_tab2);
+	vfree(tcpsp_conn_tab3);
 }
diff -urN tcpsp/tcpsp_ctl.c tcpspnew/tcpsp_ctl.c
--- tcpsp/tcpsp_ctl.c	2003-10-27 00:26:19.000000000 +0800
+++ tcpspnew/tcpsp_ctl.c	2003-10-29 11:22:22.000000000 +0800
@@ -169,7 +169,7 @@
 }
 
 
-int sys_tcpsplicing(int fd1, int fd2, int n)
+int sys_tcpsplicing(int fd1, int fd2, int n, __u32 cookie)
 {
 	struct socket *sock1, *sock2;
 	struct tcpsp_conn *cp;
@@ -180,7 +180,7 @@
 	if (!(sock2 = sockfd_lookup(fd2, &err)))
 		goto out_put_sock1;
 
-	if (!(cp = tcpsp_conn_new(sock1, sock2, n)))
+	if (!(cp = tcpsp_conn_new(sock1, sock2, n, cookie)))
 		err = -ENOMEM;
 	else
 		tcpsp_conn_put(cp);
@@ -192,6 +192,11 @@
 	return err;
 }
 
+int sys_tcpunsplicing(__u32 cookie)
+{
+	return tcpsp_conn_del(cookie);
+}
+
 
 /* this interface is ugly, will be changed to system call */
 static int
@@ -217,7 +222,10 @@
 
 	switch (cmd) {
 	case TCPSP_SO_SET_ADD:
-		ret = sys_tcpsplicing(sp.s1, sp.s2, sp.n);
+		ret = sys_tcpsplicing(sp.s1, sp.s2, sp.n, sp.cookie);
+		break;
+	case TCPSP_SO_SET_DEL:
+		ret = sys_tcpunsplicing(sp.cookie);
 		break;
 	default:
 		ret = -EINVAL;
diff -urN tcpsp/tcpsp.h tcpspnew/tcpsp.h
--- tcpsp/tcpsp.h	2002-05-20 11:22:42.000000000 +0800
+++ tcpspnew/tcpsp.h	2003-10-29 11:21:40.000000000 +0800
@@ -24,7 +24,8 @@
 
 #define TCPSP_SO_SET_NONE	TCPSP_BASE_CTL	        /* just peek */
 #define TCPSP_SO_SET_ADD	(TCPSP_BASE_CTL+1)
-#define TCPSP_SO_SET_MAX	TCPSP_SO_SET_ADD
+#define TCPSP_SO_SET_DEL	(TCPSP_BASE_CTL+2)
+#define TCPSP_SO_SET_MAX	TCPSP_SO_SET_DEL
 
 #define TCPSP_SO_GET_VERSION	TCPSP_BASE_CTL
 #define TCPSP_SO_GET_INFO	(TCPSP_BASE_CTL+1)
@@ -39,6 +40,8 @@
 
 	/* the number of bytes written to s2 */
 	int n;
+	
+	__u32 cookie;
 } splice_conn_t;
 
 
@@ -177,6 +180,7 @@
 struct tcpsp_conn {
 	struct list_head        f_list;		/* first hash table */
 	struct list_head        s_list;		/* second hash table */
+	struct list_head        t_list;         /* third hash table */
 
 	atomic_t                refcnt;		/* reference count */
 
@@ -197,6 +201,9 @@
 
 	/* packet transmitter */
 	int (*packet_xmit)(struct sk_buff *skb);
+	
+	/* cookie */
+	__u32                   cookie;         /* cookie */
 };
 
 
@@ -232,7 +239,8 @@
 extern void tcpsp_conn_put(struct tcpsp_conn *cp);
 
 extern struct tcpsp_conn *
-tcpsp_conn_new(struct socket *sock1, struct socket *sock2, int n);
+tcpsp_conn_new(struct socket *sock1, struct socket *sock2, int n, __u32 cookie);
+extern int tcpsp_conn_del(__u32 cookie);
 #define tcpsp_conn_expire_now(cp)  cp->timer.function((unsigned long)cp)
 
 extern const char * tcpsp_state_name(int state);

_______________________________________________
LinuxVirtualServer.org mailing list - lvs-users@LinuxVirtualServer.org
Send requests to lvs-users-request@LinuxVirtualServer.org
or go to http://www.in-addr.de/mailman/listinfo/lvs-users


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic