aboutsummaryrefslogtreecommitdiffstats
path: root/emulators/qemu
diff options
context:
space:
mode:
authornox <nox@FreeBSD.org>2010-02-05 04:27:30 +0800
committernox <nox@FreeBSD.org>2010-02-05 04:27:30 +0800
commitbbc4cafc7951d764d3220fb98f971ace1309a697 (patch)
treeb0b2993e50073297ef4facd08a2a66136cd0be1f /emulators/qemu
parentab15a1ddedac3747c0c96ee52d0361d344abb12b (diff)
downloadfreebsd-ports-gnome-bbc4cafc7951d764d3220fb98f971ace1309a697.tar.gz
freebsd-ports-gnome-bbc4cafc7951d764d3220fb98f971ace1309a697.tar.zst
freebsd-ports-gnome-bbc4cafc7951d764d3220fb98f971ace1309a697.zip
- Welcome usable qemu pcap networking! :)
1. Fix packet delays. [1] 2. Truncate oversize packets according to host interface's MTU to avoid e.g. Linux guests panic'ing. Note: This is only necessary as a stopgap measure for cases like host inferfaces using TSO (it still causes retransmissions), the better workaround is to disable the feature on the host interface while using qemu's pcap code. - Add note about pcap to pkg-message.s - Bump PORTREVISIONs. Submitted by: jkim [1]
Diffstat (limited to 'emulators/qemu')
-rw-r--r--emulators/qemu/Makefile1
-rw-r--r--emulators/qemu/files/pcap-patch143
-rw-r--r--emulators/qemu/pkg-message7
3 files changed, 98 insertions, 53 deletions
diff --git a/emulators/qemu/Makefile b/emulators/qemu/Makefile
index 5fac48c23701..1e5f983ce338 100644
--- a/emulators/qemu/Makefile
+++ b/emulators/qemu/Makefile
@@ -7,6 +7,7 @@
PORTNAME= qemu
PORTVERSION= 0.11.1
+PORTREVISION= 1
CATEGORIES= emulators
MASTER_SITES= ${MASTER_SITE_SAVANNAH} \
http://bellard.org/qemu/
diff --git a/emulators/qemu/files/pcap-patch b/emulators/qemu/files/pcap-patch
index 0351d0c23f9b..55b51cc66e8a 100644
--- a/emulators/qemu/files/pcap-patch
+++ b/emulators/qemu/files/pcap-patch
@@ -1,6 +1,6 @@
---- Makefile.target.orig 2008-07-18 15:18:11.000000000 -0400
-+++ Makefile.target 2008-07-18 15:23:11.000000000 -0400
-@@ -619,6 +619,13 @@
+--- Makefile.target.orig 2010-01-29 14:39:26.000000000 -0500
++++ Makefile.target 2010-01-29 14:39:28.000000000 -0500
+@@ -616,6 +616,13 @@ ifdef CONFIG_COREAUDIO
COCOA_LIBS+=-framework CoreAudio
endif
endif
@@ -14,8 +14,9 @@
ifdef CONFIG_SLIRP
CPPFLAGS+=-I$(SRC_PATH)/slirp
endif
-Index: configure
-@@ -203,6 +203,9 @@
+--- configure.orig 2010-01-29 14:39:26.000000000 -0500
++++ configure 2010-01-29 14:39:27.000000000 -0500
+@@ -203,6 +203,9 @@ sdl="yes"
sdl_x11="no"
xen="yes"
pkgversion=""
@@ -25,7 +26,7 @@ Index: configure
# OS specific
if check_define __linux__ ; then
-@@ -428,6 +431,8 @@
+@@ -428,6 +431,8 @@ for opt do
;;
--disable-vnc-sasl) vnc_sasl="no"
;;
@@ -34,7 +35,7 @@ Index: configure
--disable-slirp) slirp="no"
;;
--disable-vde) vde="no"
-@@ -925,6 +930,48 @@
+@@ -925,6 +930,48 @@ EOF
fi
##########################################
@@ -83,7 +84,7 @@ Index: configure
# VNC TLS detection
if test "$vnc_tls" = "yes" ; then
cat > $TMPC <<EOF
-@@ -1436,6 +1484,7 @@
+@@ -1436,6 +1483,7 @@ if test "$vnc_sasl" = "yes" ; then
echo " SASL CFLAGS $vnc_sasl_cflags"
echo " SASL LIBS $vnc_sasl_libs"
fi
@@ -91,7 +92,7 @@ Index: configure
if test -n "$sparc_cpu"; then
echo "Target Sparc Arch $sparc_cpu"
fi
-@@ -1589,6 +1638,16 @@
+@@ -1589,6 +1637,16 @@ fi
if test $profiler = "yes" ; then
echo "#define CONFIG_PROFILER 1" >> $config_host_h
fi
@@ -109,7 +110,7 @@ Index: configure
echo "CONFIG_SLIRP=y" >> $config_host_mak
echo "#define CONFIG_SLIRP 1" >> $config_host_h
Index: net.c
-@@ -688,6 +688,166 @@
+@@ -688,6 +688,201 @@ static void config_error(Monitor *mon, c
va_end(ap);
}
@@ -123,6 +124,7 @@ Index: net.c
+typedef struct PCAPState {
+ VLANClientState *vc;
+ pcap_t *handle;
++ int max_eth_frame_size;
+} PCAPState;
+
+static ssize_t pcap_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
@@ -136,14 +138,29 @@ Index: net.c
+{
+ VLANClientState *vc = (VLANClientState *)user;
+
-+ qemu_send_packet(vc, pdata, phdr->len);
++ int len = phdr->len;
++#ifdef __FreeBSD__
++ PCAPState *s = vc->opaque;
++ int max_eth_frame_size = s->max_eth_frame_size;
++
++ if (len > max_eth_frame_size) {
++ fprintf(stderr,
++ "pcap_send: packet size > %d (%d), truncating\n",
++ max_eth_frame_size, len);
++ len = max_eth_frame_size;
++ }
++#endif
++ qemu_send_packet(vc, pdata, len);
+}
+
+static void pcap_send(void *opaque)
+{
+ PCAPState *s = (PCAPState *)opaque;
+
-+ pcap_dispatch(s->handle, 1, (pcap_handler)&pcap_callback, (u_char *)s->vc);
++ for (;;) {
++ if (pcap_dispatch(s->handle, 0, (pcap_handler)&pcap_callback, (u_char *)s->vc) >= 0)
++ break;
++ }
+}
+
+static void pcap_cleanup(VLANClientState *vc)
@@ -165,43 +182,62 @@ Index: net.c
+
+ s = qemu_mallocz(sizeof(PCAPState));
+ if (!s)
-+ return -1;
++ return -1;
+
+ if (ifname == NULL && (ifname = pcap_lookupdev(errbuf)) == NULL) {
-+ fprintf(stderr, "qemu: pcap_lookupdev: %s\n", errbuf);
-+ goto fail;
++ fprintf(stderr, "qemu: pcap_lookupdev: %s\n", errbuf);
++ goto fail;
+ }
+
++#ifdef __FreeBSD__
++ /*
++ * We want to avoid passing oversize packets to the guest, which
++ * at least on FreeBSD can happen if the host interface uses tso
++ * (seen with an em(4) in this case) - so find out the host
++ * interface's mtu and assume the guest is configured the same.
++ */
++ s->max_eth_frame_size = 1514;
++ i = socket(AF_INET, SOCK_DGRAM, 0);
++ if (i >= 0) {
++ struct ifreq ifr;
++
++ (void) memset(&ifr, 0, sizeof(ifr));
++ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
++ if (ioctl(i, SIOCGIFMTU, &ifr) != -1)
++ s->max_eth_frame_size = ifr.ifr_mtu + 14;
++ close(i);
++ }
++#endif
+#if defined(HAVE_PCAP_CREATE) || defined(_WIN32)
+ /*
+ * Create pcap handle for the device, set promiscuous mode and activate.
+ */
+ s->handle = (void *)pcap_create(ifname, errbuf);
+ if (!s->handle) {
-+ fprintf(stderr, "qemu: pcap_create: %s\n", errbuf);
-+ goto fail;
++ fprintf(stderr, "qemu: pcap_create: %s\n", errbuf);
++ goto fail;
+ }
+ if (pcap_set_promisc(s->handle, 1) != 0) {
-+ pcap_perror(s->handle, "qemu: pcap_set_promisc:");
-+ goto fail;
++ pcap_perror(s->handle, "qemu: pcap_set_promisc:");
++ goto fail;
+ }
+ if (pcap_activate(s->handle) != 0) {
-+ pcap_perror(s->handle, "qemu: pcap_activate:");
-+ goto fail;
++ pcap_perror(s->handle, "qemu: pcap_activate:");
++ goto fail;
+ }
+#else
+ /* Attempt to connect device. */
+ s->handle = (void *)pcap_open_live(ifname, 65535, 1, 0, errbuf);
+ if (!s->handle) {
-+ fprintf(stderr, "qemu: pcap_open_live: %s\n", errbuf);
-+ goto fail;
++ fprintf(stderr, "qemu: pcap_open_live: %s\n", errbuf);
++ goto fail;
+ }
+#endif
+
+ /* Set non-blocking mode. */
+ if (pcap_setnonblock(s->handle, 1, errbuf) < 0) {
-+ fprintf(stderr, "qemu: pcap_setnonblock: %s\n", errbuf);
-+ goto fail;
++ fprintf(stderr, "qemu: pcap_setnonblock: %s\n", errbuf);
++ goto fail;
+ }
+
+#if defined(_WIN32)
@@ -209,8 +245,8 @@ Index: net.c
+ * Tell the kernel that the packet has to be seen immediately.
+ */
+ if (pcap_setmintocopy(s->handle, 0) < 0) {
-+ fprintf(stderr, "qemu: pcap failed to set immediate mode\n");
-+ goto fail;
++ fprintf(stderr, "qemu: pcap failed to set immediate mode\n");
++ goto fail;
+ }
+#else /* !_WIN32 */
+#if defined(HAVE_BPF)
@@ -219,11 +255,11 @@ Index: net.c
+ * Tell the kernel that the packet has to be seen immediately.
+ */
+ {
-+ unsigned int one = 1;
-+ if (ioctl(pcap_fileno(s->handle), BIOCIMMEDIATE, &one) < 0) {
-+ fprintf(stderr, "qemu: pcap failed to set immediate mode\n");
-+ goto fail;
-+ }
++ unsigned int one = 1;
++ if (ioctl(pcap_fileno(s->handle), BIOCIMMEDIATE, &one) < 0) {
++ fprintf(stderr, "qemu: pcap failed to set immediate mode\n");
++ goto fail;
++ }
+ }
+#endif /* BIOCIMMEDIATE */
+
@@ -233,11 +269,11 @@ Index: net.c
+ * This is necessary to connect host and guest.
+ */
+ {
-+ unsigned int one = 1;
-+ if (ioctl(pcap_fileno(s->handle), BIOCFEEDBACK, &one) < 0) {
-+ fprintf(stderr, "qemu: pcap failed to set feedback mode\n");
-+ goto fail;
-+ }
++ unsigned int one = 1;
++ if (ioctl(pcap_fileno(s->handle), BIOCFEEDBACK, &one) < 0) {
++ fprintf(stderr, "qemu: pcap failed to set feedback mode\n");
++ goto fail;
++ }
+ }
+#endif /* BIOCFEEDBACK */
+#endif /* HAVE_BPF */
@@ -248,14 +284,14 @@ Index: net.c
+
+#if defined(_WIN32)
+ if ((h = pcap_getevent(s->handle)) == NULL) {
-+ fprintf(stderr, "qemu: pcap_getevent failed\n");
-+ goto fail;
++ fprintf(stderr, "qemu: pcap_getevent failed\n");
++ goto fail;
+ }
+ qemu_add_wait_object(h, pcap_send, s);
+#else /* !_WIN32 */
+ if ((i = pcap_get_selectable_fd(s->handle)) < 0) {
-+ fprintf(stderr, "qemu: pcap_get_selectable_fd failed\n");
-+ goto fail;
++ fprintf(stderr, "qemu: pcap_get_selectable_fd failed\n");
++ goto fail;
+ }
+ qemu_set_fd_handler(i, pcap_send, NULL, s);
+#endif /* _WIN32 */
@@ -264,9 +300,9 @@ Index: net.c
+
+fail:
+ if (s) {
-+ if (s->handle)
-+ pcap_close(s->handle);
-+ qemu_free(s);
++ if (s->handle)
++ pcap_close(s->handle);
++ qemu_free(s);
+ }
+
+ return -1;
@@ -276,25 +312,26 @@ Index: net.c
#if defined(CONFIG_SLIRP)
/* slirp network adapter */
-@@ -2598,6 +2758,16 @@
+@@ -2596,6 +2791,16 @@ int net_client_init(Monitor *mon, const
are wanted */
ret = 0;
} else
+#ifdef CONFIG_PCAP
+ if (!strcmp(device, "pcap")) {
-+ char ifname[64];
-+ vlan->nb_host_devs++;
-+ if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0)
-+ ret = net_pcap_init(vlan, device, name, NULL);
-+ else
-+ ret = net_pcap_init(vlan, device, name, ifname);
++ char ifname[64];
++ vlan->nb_host_devs++;
++ if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0)
++ ret = net_pcap_init(vlan, device, name, NULL);
++ else
++ ret = net_pcap_init(vlan, device, name, ifname);
+ } else
+#endif
#ifdef CONFIG_SLIRP
if (!strcmp(device, "user")) {
static const char * const slirp_params[] = {
-Index: qemu-options.hx
-@@ -782,6 +782,10 @@
+--- qemu-options.hx.orig 2009-12-02 15:27:02.000000000 -0500
++++ qemu-options.hx 2010-01-29 14:39:27.000000000 -0500
+@@ -782,6 +782,10 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
" connect the user mode network stack to VLAN 'n', configure its\n"
" DHCP server and enabled optional services\n"
#endif
diff --git a/emulators/qemu/pkg-message b/emulators/qemu/pkg-message
index 5a1393ea7b77..6e35e73f7698 100644
--- a/emulators/qemu/pkg-message
+++ b/emulators/qemu/pkg-message
@@ -145,6 +145,13 @@ if a guest cannot eject it itself.)
- The default configuration location (qemu-ifup script etc.) has been
changed from /etc to PREFIX/etc (usually /usr/local/etc). Move your
files accordingly.
+- The pcap code (-net nic... -net pcap,ifname=...) should work properly
+now, with only one exception: Advanced features like TSO used on the host
+interface can cause oversize packets which now do get truncated to avoid
+confusing/panicing guests but of course still will cause retransmissions.
+So if you see slow throughput and `pcap_send: packet size > ..., truncating'
+messages on qemu's tty try disabling TSO etc on the host interface at least
+while using pcap.
- kqemu still works in the 0.11 branch, but is disabled by default now
so you'll have to pass -enable-kqemu (or -kernel-kqemu as with the
previous versions) if you want to use it.