LVS
lvs-users
Google
 
Web LinuxVirtualServer.org

[PATCH]simple unsplicing to tcpsp-0.0.3 with the help of unique cookie

To: <lvs-users@xxxxxxxxxxxxxxxxxxxxxx>
Subject: [PATCH]simple unsplicing to tcpsp-0.0.3 with the help of unique cookie
From: "yangrunhua" <yangrunhua@xxxxxxxxxxxx>
Date: Thu, 30 Oct 2003 15:16:17 +0800
Hi all,
        Compared to my last patch to tcpsp-0.0.3, it refuses to call 
tcpsp_conn_new for duplicated cookies, and return -EINVAL, so it will make that 
cookie unique.
        I recommend this new patch rather than the one I posted yesterday.
        From my last letter: "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 than 
to rmmod the whole tcpsp module."
        Any feedback is welcome!

        Runhua Yang(yangrunhua@xxxxxxxxxxxx)


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-29 00:33:51.000000000 +0800
@@ -19,6 +19,7 @@
 #include <sys/poll.h>
 #include <netdb.h>
 #include <popt.h>
+#include <time.h>
 
 #include "tcpsp.h"
 
@@ -40,10 +41,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 +110,7 @@
                exit(1);
        }
 
-       if (tcpsplicing(fd1, fd2, n))
+       if (tcpsplicing(fd1, fd2, n, (__u32)time(NULL)/*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-30 15:02:12.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,53 @@
        }
 }
 
+/*
+ *      Find the connection entry matches the cookie in the tcpsp_conn_tab,
+ *      and return it without locking
+ */
+struct tcpsp_conn * tcpsp_conn_find(__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.
+        */
+       read_lock(&tcpsp_conn_lock);
+
+       list_for_each_safe (e, nxt, &tcpsp_conn_tab3[idx]) {
+               cp = list_entry(e, struct tcpsp_conn, t_list);
+               read_unlock(&tcpsp_conn_lock);
+               if (cp->cookie == cookie){
+                       return cp;
+               }
+
+               read_lock(&tcpsp_conn_lock);
+       }
+       read_unlock(&tcpsp_conn_lock);
+       
+       return NULL;
+}
+
+/*
+ *      Delete the connection entry matches the cookie in the tcpsp_conn_tab
+ */
+int tcpsp_conn_del(__u32 cookie)
+{
+       struct tcpsp_conn *cp = tcpsp_conn_find(cookie);
+       
+       if (cp == NULL) return -EINVAL;
+       
+       TCPSP_DBG(4, "del splicing connection\n");
+       
+       if (del_timer(&cp->timer)){
+               tcpsp_conn_expire_now(cp);
+       }
+       
+       return 0;
+}
 
 int tcpsp_conn_init(void)
 {
@@ -647,6 +712,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 +727,7 @@
        if (!tcpsp_conn_cachep) {
                vfree(tcpsp_conn_tab1);
                vfree(tcpsp_conn_tab2);
+               vfree(tcpsp_conn_tab3);
                return -ENOMEM;
        }
 
@@ -668,6 +741,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 +759,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-30 14:14:40.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;
@@ -179,12 +179,18 @@
                goto out;
        if (!(sock2 = sockfd_lookup(fd2, &err)))
                goto out_put_sock1;
+               
+       if ((cp = tcpsp_conn_find(cookie))){
+               err = -EINVAL;
+               goto out_put_sock2;
+       }
 
-       if (!(cp = tcpsp_conn_new(sock1, sock2, n)))
+       if (!(cp = tcpsp_conn_new(sock1, sock2, n, cookie)))
                err = -ENOMEM;
        else
                tcpsp_conn_put(cp);
 
+  out_put_sock2:
        sockfd_put(sock2);
   out_put_sock1:
        sockfd_put(sock1);
@@ -192,6 +198,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 +228,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-30 14:16:16.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,9 @@
 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);
+extern struct tcpsp_conn * tcpsp_conn_find(__u32 cookie);
 #define tcpsp_conn_expire_now(cp)  cp->timer.function((unsigned long)cp)
 
 extern const char * tcpsp_state_name(int state);

<Prev in Thread] Current Thread [Next in Thread>
  • [PATCH]simple unsplicing to tcpsp-0.0.3 with the help of unique cookie, yangrunhua <=