qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 2/7] net: Add VLAN client cleanup handler


From: Jan Kiszka
Subject: [Qemu-devel] [PATCH 2/7] net: Add VLAN client cleanup handler
Date: Tue, 14 Apr 2009 19:29:54 +0200
User-agent: StGIT/0.14.2

Do proper VLAN client cleanup via a callback handler. This fixes
resource leakage on host_net_remove and allows a generic net_cleanup
implementation.

Signed-off-by: Jan Kiszka <address@hidden>
---

 hw/e1000.c          |    2 -
 hw/eepro100.c       |    2 -
 hw/etraxfs_eth.c    |    3 +
 hw/mcf_fec.c        |    3 +
 hw/mipsnet.c        |    3 +
 hw/musicpal.c       |    2 -
 hw/ne2000.c         |    4 +
 hw/pcnet.c          |    3 +
 hw/rtl8139.c        |    3 +
 hw/smc91c111.c      |    3 +
 hw/stellaris_enet.c |    3 +
 hw/usb-net.c        |    2 -
 hw/virtio-net.c     |    3 +
 net.c               |  140 +++++++++++++++++++++++++++++----------------------
 net.h               |    4 +
 15 files changed, 106 insertions(+), 74 deletions(-)

diff --git a/hw/e1000.c b/hw/e1000.c
index 1644201..9ce116c 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -1096,7 +1096,7 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn)
     memset(&d->tx, 0, sizeof d->tx);
 
     d->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
-                                 e1000_receive, e1000_can_receive, d);
+                                 e1000_receive, e1000_can_receive, NULL, d);
     d->vc->link_status_changed = e1000_set_link_status;
 
     qemu_format_nic_info_str(d->vc, d->nd->macaddr);
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 0a343df..321bd48 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1751,7 +1751,7 @@ static PCIDevice *nic_init(PCIBus * bus, NICInfo * nd,
     nic_reset(s);
 
     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
-                                 nic_receive, nic_can_receive, s);
+                                 nic_receive, nic_can_receive, NULL, s);
 
     qemu_format_nic_info_str(s->vc, s->macaddr);
 
diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c
index c87e55f..0d5fa9b 100644
--- a/hw/etraxfs_eth.c
+++ b/hw/etraxfs_eth.c
@@ -585,7 +585,8 @@ void *etraxfs_eth_init(NICInfo *nd, CPUState *env,
        cpu_register_physical_memory (base, 0x5c, eth->ethregs);
 
        eth->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
-                                      eth_receive, eth_can_receive, eth);
+                                      eth_receive, eth_can_receive,
+                                      NULL, eth);
        eth->vc->opaque = eth;
        eth->vc->link_status_changed = eth_set_link;
 
diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c
index 413c569..6a42faf 100644
--- a/hw/mcf_fec.c
+++ b/hw/mcf_fec.c
@@ -455,7 +455,8 @@ void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, 
qemu_irq *irq)
     cpu_register_physical_memory(base, 0x400, iomemtype);
 
     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
-                                 mcf_fec_receive, mcf_fec_can_receive, s);
+                                 mcf_fec_receive, mcf_fec_can_receive,
+                                 NULL, s);
     memcpy(s->macaddr, nd->macaddr, 6);
     qemu_format_nic_info_str(s->vc, s->macaddr);
 }
diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index 29bd9b8..81739ac 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -251,7 +251,8 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
     s->nd = nd;
     if (nd && nd->vlan) {
         s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
-                                     mipsnet_receive, mipsnet_can_receive, s);
+                                     mipsnet_receive, mipsnet_can_receive,
+                                     NULL, s);
     } else {
         s->vc = NULL;
     }
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 5de1691..bdff03e 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -755,7 +755,7 @@ static void mv88w8618_eth_init(NICInfo *nd, uint32_t base, 
qemu_irq irq)
     s = qemu_mallocz(sizeof(mv88w8618_eth_state));
     s->irq = irq;
     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
-                                 eth_receive, eth_can_receive, s);
+                                 eth_receive, eth_can_receive, NULL, s);
     iomemtype = cpu_register_io_memory(0, mv88w8618_eth_readfn,
                                        mv88w8618_eth_writefn, s);
     cpu_register_physical_memory(base, MP_ETH_SIZE, iomemtype);
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 24a66bb..02cf5e3 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -742,7 +742,7 @@ void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd)
     ne2000_reset(s);
 
     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
-                                 ne2000_receive, ne2000_can_receive, s);
+                                 ne2000_receive, ne2000_can_receive, NULL, s);
 
     qemu_format_nic_info_str(s->vc, s->macaddr);
 
@@ -802,7 +802,7 @@ PCIDevice *pci_ne2000_init(PCIBus *bus, NICInfo *nd, int 
devfn)
     memcpy(s->macaddr, nd->macaddr, 6);
     ne2000_reset(s);
     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
-                                 ne2000_receive, ne2000_can_receive, s);
+                                 ne2000_receive, ne2000_can_receive, NULL, s);
 
     qemu_format_nic_info_str(s->vc, s->macaddr);
 
diff --git a/hw/pcnet.c b/hw/pcnet.c
index be68f28..ff1d1c3 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -1937,7 +1937,8 @@ static void pcnet_common_init(PCNetState *d, NICInfo *nd)
 
     if (nd && nd->vlan) {
         d->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
-                                     pcnet_receive, pcnet_can_receive, d);
+                                     pcnet_receive, pcnet_can_receive,
+                                     NULL, d);
 
         qemu_format_nic_info_str(d->vc, d->nd->macaddr);
     } else {
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 9fa69db..a2b28bb 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3450,7 +3450,8 @@ PCIDevice *pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int 
devfn)
     memcpy(s->macaddr, nd->macaddr, 6);
     rtl8139_reset(s);
     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
-                                 rtl8139_receive, rtl8139_can_receive, s);
+                                 rtl8139_receive, rtl8139_can_receive,
+                                 NULL, s);
 
     qemu_format_nic_info_str(s->vc, s->macaddr);
 
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index f5b29a7..f20c9b3 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -707,7 +707,8 @@ void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq 
irq)
     smc91c111_reset(s);
 
     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
-                                 smc91c111_receive, smc91c111_can_receive, s);
+                                 smc91c111_receive, smc91c111_can_receive,
+                                 NULL, s);
     qemu_format_nic_info_str(s->vc, s->macaddr);
     /* ??? Save/restore.  */
 }
diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c
index 88c5620..3035734 100644
--- a/hw/stellaris_enet.c
+++ b/hw/stellaris_enet.c
@@ -400,7 +400,8 @@ void stellaris_enet_init(NICInfo *nd, uint32_t base, 
qemu_irq irq)
 
     if (nd->vlan) {
         s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
-                                     stellaris_enet_receive, 
stellaris_enet_can_receive, s);
+                                     stellaris_enet_receive,
+                                     stellaris_enet_can_receive, NULL, s);
         qemu_format_nic_info_str(s->vc, s->macaddr);
     }
 
diff --git a/hw/usb-net.c b/hw/usb-net.c
index 863c25f..2fd5112 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1452,7 +1452,7 @@ USBDevice *usb_net_init(NICInfo *nd)
     pstrcpy(s->dev.devname, sizeof(s->dev.devname),
                     "QEMU USB Network Interface");
     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
-                    usbnet_receive, usbnet_can_receive, s);
+                                 usbnet_receive, usbnet_can_receive, NULL, s);
 
     qemu_format_nic_info_str(s->vc, s->mac);
 
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 88ec1ac..bf15d39 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -603,7 +603,8 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int 
devfn)
     memcpy(n->mac, nd->macaddr, ETH_ALEN);
     n->status = VIRTIO_NET_S_LINK_UP;
     n->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
-                                 virtio_net_receive, virtio_net_can_receive, 
n);
+                                 virtio_net_receive, virtio_net_can_receive,
+                                 NULL, n);
     n->vc->link_status_changed = virtio_net_set_link_status;
 
     qemu_format_nic_info_str(n->vc, n->mac);
diff --git a/net.c b/net.c
index c7e4a0b..36c0509 100644
--- a/net.c
+++ b/net.c
@@ -333,6 +333,7 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan,
                                       const char *name,
                                       IOReadHandler *fd_read,
                                       IOCanRWHandler *fd_can_read,
+                                      VLANClientCleanupHandler *cleanup,
                                       void *opaque)
 {
     VLANClientState *vc, **pvc;
@@ -344,6 +345,7 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan,
         vc->name = assign_name(vc, model);
     vc->fd_read = fd_read;
     vc->fd_can_read = fd_can_read;
+    vc->cleanup = cleanup;
     vc->opaque = opaque;
     vc->vlan = vlan;
 
@@ -362,6 +364,9 @@ void qemu_del_vlan_client(VLANClientState *vc)
     while (*pvc != NULL)
         if (*pvc == vc) {
             *pvc = vc->next;
+            if (vc->cleanup) {
+                vc->cleanup(vc->opaque);
+            }
             free(vc->name);
             free(vc->model);
             free(vc);
@@ -521,7 +526,7 @@ static int net_slirp_init(VLANState *vlan, const char 
*model, const char *name)
         slirp_init(slirp_restrict, slirp_ip);
     }
     slirp_vc = qemu_new_vlan_client(vlan, model, name,
-                                    slirp_receive, NULL, NULL);
+                                    slirp_receive, NULL, NULL, NULL);
     slirp_vc->info_str[0] = '\0';
     return 0;
 }
@@ -752,6 +757,51 @@ static void tap_send(void *opaque)
 
 /* fd support */
 
+static int launch_script(const char *setup_script, const char *ifname, int fd)
+{
+    int pid, status, open_max, i;
+    char *args[3];
+    char **parg;
+
+    /* try to launch network script */
+    pid = fork();
+    if (pid < 0)
+        return -1;
+    if (pid == 0) {
+        open_max = sysconf(_SC_OPEN_MAX);
+        for (i = 0; i < open_max; i++) {
+            if (i != STDIN_FILENO && i != STDOUT_FILENO &&
+                i != STDERR_FILENO && i != fd) {
+                close(i);
+            }
+        }
+        parg = args;
+        *parg++ = (char *)setup_script;
+        *parg++ = (char *)ifname;
+        *parg++ = NULL;
+        execv(setup_script, args);
+        _exit(1);
+    }
+    while (waitpid(pid, &status, 0) != pid);
+    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+        fprintf(stderr, "%s: could not launch network script\n",
+                setup_script);
+        return -1;
+    }
+    return 0;
+}
+
+static void net_tap_cleanup(void *opaque)
+{
+    TAPState *s = opaque;
+
+    if (s->down_script[0]) {
+        launch_script(s->down_script, s->down_script_arg, s->fd);
+    }
+    close(s->fd);
+    qemu_free(s);
+}
+
 static TAPState *net_tap_fd_init(VLANState *vlan,
                                  const char *model,
                                  const char *name,
@@ -761,7 +811,8 @@ static TAPState *net_tap_fd_init(VLANState *vlan,
 
     s = qemu_mallocz(sizeof(TAPState));
     s->fd = fd;
-    s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive, NULL, s);
+    s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive, NULL,
+                                 net_tap_cleanup, s);
 #ifdef HAVE_IOVEC
     s->vc->fd_readv = tap_receive_iov;
 #endif
@@ -960,42 +1011,6 @@ static int tap_open(char *ifname, int ifname_size)
 }
 #endif
 
-static int launch_script(const char *setup_script, const char *ifname, int fd)
-{
-    int pid, status;
-    char *args[3];
-    char **parg;
-
-        /* try to launch network script */
-        pid = fork();
-        if (pid >= 0) {
-            if (pid == 0) {
-                int open_max = sysconf (_SC_OPEN_MAX), i;
-                for (i = 0; i < open_max; i++)
-                    if (i != STDIN_FILENO &&
-                        i != STDOUT_FILENO &&
-                        i != STDERR_FILENO &&
-                        i != fd)
-                        close(i);
-
-                parg = args;
-                *parg++ = (char *)setup_script;
-                *parg++ = (char *)ifname;
-                *parg++ = NULL;
-                execv(setup_script, args);
-                _exit(1);
-            }
-            while (waitpid(pid, &status, 0) != pid);
-            if (!WIFEXITED(status) ||
-                WEXITSTATUS(status) != 0) {
-                fprintf(stderr, "%s: could not launch network script\n",
-                        setup_script);
-                return -1;
-            }
-        }
-    return 0;
-}
-
 static int net_tap_init(VLANState *vlan, const char *model,
                         const char *name, const char *ifname1,
                         const char *setup_script, const char *down_script)
@@ -1064,6 +1079,14 @@ static void vde_from_qemu(void *opaque, const uint8_t 
*buf, int size)
     }
 }
 
+static void net_vde_cleanup(void *opaque)
+{
+    VDEState *s = opaque;
+
+    vde_close(s->fd);
+    qemu_free(s);
+}
+
 static int net_vde_init(VLANState *vlan, const char *model,
                         const char *name, const char *sock,
                         int port, const char *group, int mode)
@@ -1084,7 +1107,8 @@ static int net_vde_init(VLANState *vlan, const char 
*model,
         free(s);
         return -1;
     }
-    s->vc = qemu_new_vlan_client(vlan, model, name, vde_from_qemu, NULL, s);
+    s->vc = qemu_new_vlan_client(vlan, model, name, vde_from_qemu, NULL,
+                                 net_vde_cleanup, s);
     qemu_set_fd_handler(vde_datafd(s->vde), vde_to_qemu, NULL, s);
     snprintf(s->vc->info_str, sizeof(s->vc->info_str), "sock=%s,fd=%d",
              sock, vde_datafd(s->vde));
@@ -1269,6 +1293,14 @@ fail:
     return -1;
 }
 
+static void net_socket_cleanup(void *opaque)
+{
+    NetSocketState *s = opaque;
+
+    close(s->fd);
+    qemu_free(s);
+}
+
 static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
                                                 const char *model,
                                                 const char *name,
@@ -1313,7 +1345,8 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState 
*vlan,
     s = qemu_mallocz(sizeof(NetSocketState));
     s->fd = fd;
 
-    s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive_dgram, 
NULL, s);
+    s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive_dgram,
+                                 NULL, net_socket_cleanup, s);
     qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s);
 
     /* mcast: save bound address as dst */
@@ -1340,8 +1373,8 @@ static NetSocketState 
*net_socket_fd_init_stream(VLANState *vlan,
     NetSocketState *s;
     s = qemu_mallocz(sizeof(NetSocketState));
     s->fd = fd;
-    s->vc = qemu_new_vlan_client(vlan, model, name,
-                                 net_socket_receive, NULL, s);
+    s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive,
+                                 NULL, net_socket_cleanup, s);
     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
              "socket: fd=%d", fd);
     if (is_connected) {
@@ -1903,29 +1936,16 @@ done:
 
 void net_cleanup(void)
 {
-#if !defined(_WIN32)
     VLANState *vlan;
+    VLANClientState *vc;
 
-    /* close network clients */
-    for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
-        VLANClientState *vc;
-
-        for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
-            if (vc->fd_read == tap_receive) {
-                TAPState *s = vc->opaque;
-
-                if (s->down_script[0])
-                    launch_script(s->down_script, s->down_script_arg, s->fd);
-            }
-#if defined(CONFIG_VDE)
-            if (vc->fd_read == vde_from_qemu) {
-                VDEState *s = vc->opaque;
-                vde_close(s->vde);
+    for (vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
+        for (vc = vlan->first_client; vc != NULL; vc = vc->next) {
+            if (vc->cleanup) {
+                vc->cleanup(vc->opaque);
             }
-#endif
         }
     }
-#endif
 }
 
 void net_client_check(void)
diff --git a/net.h b/net.h
index 1a51be7..571305b 100644
--- a/net.h
+++ b/net.h
@@ -11,7 +11,10 @@ typedef struct VLANClientState VLANClientState;
 
 typedef void (LinkStatusChanged)(VLANClientState *);
 
+typedef void (VLANClientCleanupHandler)(void *);
+
 struct VLANClientState {
+    VLANClientCleanupHandler *cleanup;
     IOReadHandler *fd_read;
     IOReadvHandler *fd_readv;
     /* Packets may still be sent if this returns zero.  It's used to
@@ -40,6 +43,7 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan,
                                       const char *name,
                                       IOReadHandler *fd_read,
                                       IOCanRWHandler *fd_can_read,
+                                      VLANClientCleanupHandler *cleanup,
                                       void *opaque);
 void qemu_del_vlan_client(VLANClientState *vc);
 VLANClientState *qemu_find_vlan_client(VLANState *vlan, void *opaque);





reply via email to

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