LVS
lvs-users
Google
 
Web LinuxVirtualServer.org

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

To: <lvs-users@xxxxxxxxxxxxxxxxxxxxxx>
Subject: [PATCH]add simple unsplicing to tcpsp-0.0.3 with the help of a cookie
From: "yangrunhua" <yangrunhua@xxxxxxxxxxxx>
Date: Wed, 29 Oct 2003 15:14:42 +0800
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);

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