[Top][All Lists]
[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);
- [Qemu-devel] [PATCH 0/7] Various small networking improvements, Jan Kiszka, 2009/04/14
- [Qemu-devel] [PATCH 4/7] net: Prevent multiple slirp instances, Jan Kiszka, 2009/04/14
- [Qemu-devel] [PATCH 1/7] net: Fix -net socket,listen, Jan Kiszka, 2009/04/14
- [Qemu-devel] [PATCH 2/7] net: Add VLAN client cleanup handler,
Jan Kiszka <=
- [Qemu-devel] Re: [PATCH 2/7] net: Add VLAN client cleanup handler, Jan Kiszka, 2009/04/15
- [Qemu-devel] Re: [PATCH 2/7] net: Add VLAN client cleanup handler, Mark McLoughlin, 2009/04/15
- [Qemu-devel] Re: [PATCH 2/7] net: Add VLAN client cleanup handler, Jan Kiszka, 2009/04/15
[Qemu-devel] [PATCH 3/7] net: Check device passed to host_net_remove, Jan Kiszka, 2009/04/14