qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 8/9] slirp: Move tcb socket to iohandler


From: Fam Zheng
Subject: [Qemu-devel] [PATCH 8/9] slirp: Move tcb socket to iohandler
Date: Wed, 10 Jun 2015 16:59:50 +0800

This change is a replicate of the previous two, just the calculation of polled
events is more delicate, and both read and write are polled.

Signed-off-by: Fam Zheng <address@hidden>
---
 slirp/slirp.c | 310 ++++++++++++++++++++++++++--------------------------------
 1 file changed, 140 insertions(+), 170 deletions(-)

diff --git a/slirp/slirp.c b/slirp/slirp.c
index a031240..4cfa190 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -286,6 +286,143 @@ static void slirp_update_timeout(uint32_t *timeout)
     *timeout = t;
 }
 
+static void slirp_tcb_read_oob(void *opaque)
+{
+    struct socket *so = opaque;
+    sorecvoob(so);
+}
+
+static void slirp_tcb_read(void *opaque)
+{
+    int ret;
+    struct socket *so = opaque;
+
+    if (so->so_state & SS_NOFDREF) {
+        return;
+    }
+    /*
+     * Check for incoming connections
+     */
+    if (so->so_state & SS_FACCEPTCONN) {
+        tcp_connect(so);
+    } else {
+        ret = soread(so);
+
+        /* Output it if we read something */
+        if (ret > 0) {
+            tcp_output(sototcpcb(so));
+        }
+    }
+}
+
+static void slirp_tcb_write(void *opaque)
+{
+    int ret;
+    struct socket *so = opaque;
+
+    if (so->so_state & SS_NOFDREF) {
+        return;
+    }
+    /*
+     * Check for non-blocking, still-connecting sockets
+     */
+    if (so->so_state & SS_ISFCONNECTING) {
+        /* Connected */
+        so->so_state &= ~SS_ISFCONNECTING;
+
+        ret = send(so->s, (const void *) &ret, 0, 0);
+        if (ret < 0) {
+            /* XXXXX Must fix, zero bytes is a NOP */
+            if (errno == EAGAIN || errno == EWOULDBLOCK ||
+                errno == EINPROGRESS || errno == ENOTCONN) {
+                return;
+            }
+
+            /* else failed */
+            so->so_state &= SS_PERSISTENT_MASK;
+            so->so_state |= SS_NOFDREF;
+        }
+        /* else so->so_state &= ~SS_ISFCONNECTING; */
+
+        /*
+         * Continue tcp_input
+         */
+        tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
+        /* continue; */
+    } else {
+        sowrite(so);
+    }
+    /*
+     * XXXXX If we wrote something (a lot), there
+     * could be a need for a window update.
+     * In the worst case, the remote will send
+     * a window probe to get things going again
+     */
+}
+
+static bool slirp_poll_update_tcb(struct socket *so)
+{
+    int events = 0;
+    Slirp *slirp = so->slirp;
+
+    /*
+     * See if we need a tcp_fasttimo
+     */
+    if (slirp->time_fasttimo == 0 &&
+        so->so_tcpcb->t_flags & TF_DELACK) {
+        slirp->time_fasttimo = curtime; /* Flag when want a fasttimo */
+    }
+
+    /*
+     * NOFDREF can include still connecting to local-host,
+     * newly socreated() sockets etc. Don't want to select these.
+     */
+    if (so->so_state & SS_NOFDREF || so->s == -1) {
+        so->poll_events = 0;
+        qemu_set_fd_handler(so->s, NULL, NULL, NULL);
+        return false;
+    }
+
+    if (so->so_state & SS_FACCEPTCONN) {
+        /*
+         * Set for reading sockets which are accepting
+         */
+        events = G_IO_IN;
+    } else if (so->so_state & SS_ISFCONNECTING) {
+        /*
+         * Set for writing sockets which are connecting
+         */
+        events = G_IO_OUT;
+    }
+
+    /*
+     * Set for writing if we are connected, can send more, and
+     * we have something to send
+     */
+    if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
+        events |= G_IO_OUT;
+    }
+
+    /*
+     * Set for reading (and urgent data) if we are connected, can
+     * receive more, and we have room for it XXX /2 ?
+     */
+    if (CONN_CANFRCV(so) &&
+        (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
+        events |= G_IO_IN | G_IO_PRI;
+    }
+
+    if (events != so->poll_events) {
+        so->poll_events = events;
+        qemu_set_fd_handler_pri(so->s,
+                                events & G_IO_IN ? slirp_tcb_read : NULL,
+                                events & G_IO_OUT ? slirp_tcb_write : NULL,
+                                events & G_IO_PRI ? slirp_tcb_read_oob : NULL,
+                                so);
+    }
+    return false;
+}
+
 static void slirp_udb_read(void *opaque)
 {
     struct socket *so = opaque;
@@ -301,8 +438,8 @@ static bool slirp_poll_update_udb(struct socket *so)
      */
     if (so->so_expire) {
         if (so->so_expire <= curtime) {
+            qemu_set_fd_handler(so->s, NULL, NULL, NULL);
             udp_detach(so);
-            qemu_set_fd_handler(so->s, NULL, NULL, NULL);
             return ret;
         } else {
             ret = true;
@@ -339,8 +476,8 @@ static bool slirp_poll_update_icmp(struct socket *so)
      */
     if (so->so_expire) {
         if (so->so_expire <= curtime) {
+            qemu_set_fd_handler(so->s, NULL, NULL, NULL);
             icmp_detach(so);
-            qemu_set_fd_handler(so->s, NULL, NULL, NULL);
             return ret;
         } else {
             ret = true; /* Let socket expire */
@@ -385,79 +522,8 @@ void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout)
 
         for (so = slirp->tcb.so_next; so != &slirp->tcb;
                 so = so_next) {
-            int events = 0;
-
             so_next = so->so_next;
-
-            so->pollfds_idx = -1;
-
-            /*
-             * See if we need a tcp_fasttimo
-             */
-            if (slirp->time_fasttimo == 0 &&
-                so->so_tcpcb->t_flags & TF_DELACK) {
-                slirp->time_fasttimo = curtime; /* Flag when want a fasttimo */
-            }
-
-            /*
-             * NOFDREF can include still connecting to local-host,
-             * newly socreated() sockets etc. Don't want to select these.
-             */
-            if (so->so_state & SS_NOFDREF || so->s == -1) {
-                continue;
-            }
-
-            /*
-             * Set for reading sockets which are accepting
-             */
-            if (so->so_state & SS_FACCEPTCONN) {
-                GPollFD pfd = {
-                    .fd = so->s,
-                    .events = G_IO_IN | G_IO_HUP | G_IO_ERR,
-                };
-                so->pollfds_idx = pollfds->len;
-                g_array_append_val(pollfds, pfd);
-                continue;
-            }
-
-            /*
-             * Set for writing sockets which are connecting
-             */
-            if (so->so_state & SS_ISFCONNECTING) {
-                GPollFD pfd = {
-                    .fd = so->s,
-                    .events = G_IO_OUT | G_IO_ERR,
-                };
-                so->pollfds_idx = pollfds->len;
-                g_array_append_val(pollfds, pfd);
-                continue;
-            }
-
-            /*
-             * Set for writing if we are connected, can send more, and
-             * we have something to send
-             */
-            if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
-                events |= G_IO_OUT | G_IO_ERR;
-            }
-
-            /*
-             * Set for reading (and urgent data) if we are connected, can
-             * receive more, and we have room for it XXX /2 ?
-             */
-            if (CONN_CANFRCV(so) &&
-                (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
-                events |= G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI;
-            }
-
-            if (events) {
-                GPollFD pfd = {
-                    .fd = so->s,
-                    .events = events,
-                };
-                so->pollfds_idx = pollfds->len;
-                g_array_append_val(pollfds, pfd);
-            }
+            slirp->do_slowtimo |= slirp_poll_update_tcb(so);
         }
 
         /*
@@ -484,8 +550,6 @@ void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout)
 void slirp_pollfds_poll(GArray *pollfds, int select_error)
 {
     Slirp *slirp;
-    struct socket *so, *so_next;
-    int ret;
 
     if (QTAILQ_EMPTY(&slirp_instances)) {
         return;
@@ -509,100 +573,6 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error)
             slirp->last_slowtimo = curtime;
         }
 
-        /*
-         * Check sockets
-         */
-        if (!select_error) {
-            /*
-             * Check TCP sockets
-             */
-            for (so = slirp->tcb.so_next; so != &slirp->tcb;
-                    so = so_next) {
-                int revents;
-
-                so_next = so->so_next;
-
-                revents = 0;
-                if (so->pollfds_idx != -1) {
-                    revents = g_array_index(pollfds, GPollFD,
-                                            so->pollfds_idx).revents;
-                }
-
-                if (so->so_state & SS_NOFDREF || so->s == -1) {
-                    continue;
-                }
-
-                /*
-                 * Check for URG data
-                 * This will soread as well, so no need to
-                 * test for G_IO_IN below if this succeeds
-                 */
-                if (revents & G_IO_PRI) {
-                    sorecvoob(so);
-                }
-                /*
-                 * Check sockets for reading
-                 */
-                else if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) {
-                    /*
-                     * Check for incoming connections
-                     */
-                    if (so->so_state & SS_FACCEPTCONN) {
-                        tcp_connect(so);
-                        continue;
-                    } /* else */
-                    ret = soread(so);
-
-                    /* Output it if we read something */
-                    if (ret > 0) {
-                        tcp_output(sototcpcb(so));
-                    }
-                }
-
-                /*
-                 * Check sockets for writing
-                 */
-                if (!(so->so_state & SS_NOFDREF) &&
-                        (revents & (G_IO_OUT | G_IO_ERR))) {
-                    /*
-                     * Check for non-blocking, still-connecting sockets
-                     */
-                    if (so->so_state & SS_ISFCONNECTING) {
-                        /* Connected */
-                        so->so_state &= ~SS_ISFCONNECTING;
-
-                        ret = send(so->s, (const void *) &ret, 0, 0);
-                        if (ret < 0) {
-                            /* XXXXX Must fix, zero bytes is a NOP */
-                            if (errno == EAGAIN || errno == EWOULDBLOCK ||
-                                errno == EINPROGRESS || errno == ENOTCONN) {
-                                continue;
-                            }
-
-                            /* else failed */
-                            so->so_state &= SS_PERSISTENT_MASK;
-                            so->so_state |= SS_NOFDREF;
-                        }
-                        /* else so->so_state &= ~SS_ISFCONNECTING; */
-
-                        /*
-                         * Continue tcp_input
-                         */
-                        tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
-                        /* continue; */
-                    } else {
-                        ret = sowrite(so);
-                    }
-                    /*
-                     * XXXXX If we wrote something (a lot), there
-                     * could be a need for a window update.
-                     * In the worst case, the remote will send
-                     * a window probe to get things going again
-                     */
-                }
-            }
-        }
-
         if_start(slirp);
     }
 }
-- 
2.4.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]