mirror of
https://git.FreeBSD.org/ports.git
synced 2024-12-26 05:02:18 +00:00
- 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]
This commit is contained in:
parent
b3743b6bd3
commit
47de8e10d8
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=249241
@ -7,6 +7,7 @@
|
||||
|
||||
PORTNAME= qemu
|
||||
PORTVERSION= 0.12.2
|
||||
PORTREVISION= 1
|
||||
CATEGORIES= emulators
|
||||
MASTER_SITES= ${MASTER_SITE_SAVANNAH}:release \
|
||||
${MASTER_SITE_LOCAL}:snapshot \
|
||||
|
@ -1,4 +1,5 @@
|
||||
Index: configure
|
||||
--- configure.orig 2010-01-29 14:36:00.000000000 -0500
|
||||
+++ configure 2010-01-29 14:36:00.000000000 -0500
|
||||
@@ -257,6 +257,9 @@ pkgversion=""
|
||||
check_utests="no"
|
||||
user_pie="no"
|
||||
@ -84,7 +85,8 @@ Index: configure
|
||||
if test "$slirp" = "yes" ; then
|
||||
echo "CONFIG_SLIRP=y" >> $config_host_mak
|
||||
QEMU_CFLAGS="-I\$(SRC_PATH)/slirp $QEMU_CFLAGS"
|
||||
Index: net.h
|
||||
--- net.h.orig 2010-01-29 14:36:00.000000000 -0500
|
||||
+++ net.h 2010-01-29 14:36:00.000000000 -0500
|
||||
@@ -33,7 +33,8 @@ typedef enum {
|
||||
NET_CLIENT_TYPE_TAP,
|
||||
NET_CLIENT_TYPE_SOCKET,
|
||||
@ -96,16 +98,19 @@ Index: net.h
|
||||
|
||||
typedef int (NetCanReceive)(VLANClientState *);
|
||||
Index: net.c
|
||||
@@ -36,6 +36,8 @@
|
||||
@@ -36,6 +36,11 @@
|
||||
#include "qemu-common.h"
|
||||
#include "qemu_socket.h"
|
||||
|
||||
+#include <sys/ioctl.h>
|
||||
+#ifdef __FreeBSD__
|
||||
+#include <net/if.h>
|
||||
+#endif
|
||||
+
|
||||
static QTAILQ_HEAD(, VLANState) vlans;
|
||||
static QTAILQ_HEAD(, VLANClientState) non_vlan_clients;
|
||||
|
||||
@@ -820,6 +822,212 @@ static int net_init_nic(QemuOpts *opts,
|
||||
@@ -820,6 +825,228 @@ static int net_init_nic(QemuOpts *opts,
|
||||
return idx;
|
||||
}
|
||||
|
||||
@ -119,6 +124,7 @@ Index: net.c
|
||||
+typedef struct PCAPState {
|
||||
+ VLANClientState nc;
|
||||
+ pcap_t *handle;
|
||||
+ int max_eth_frame_size;
|
||||
+} PCAPState;
|
||||
+
|
||||
+static ssize_t pcap_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
|
||||
@ -128,27 +134,33 @@ Index: net.c
|
||||
+ return pcap_inject(s->handle, (u_char*)buf, size);
|
||||
+}
|
||||
+
|
||||
+#define MAX_ETH_FRAME_SIZE 1514
|
||||
+
|
||||
+static void pcap_callback(u_char *user, struct pcap_pkthdr *phdr, u_char *pdata)
|
||||
+{
|
||||
+ VLANClientState *vc = (VLANClientState *)user;
|
||||
+ int len = phdr->len;
|
||||
+ VLANClientState *nc = (VLANClientState *)user;
|
||||
+
|
||||
+ if (len > MAX_ETH_FRAME_SIZE) {
|
||||
+ int len = phdr->len;
|
||||
+#ifdef __FreeBSD__
|
||||
+ PCAPState *s = DO_UPCAST(PCAPState, nc, nc);
|
||||
+ 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;
|
||||
+ max_eth_frame_size, len);
|
||||
+ len = max_eth_frame_size;
|
||||
+ }
|
||||
+ qemu_send_packet(vc, pdata, len);
|
||||
+#endif
|
||||
+ qemu_send_packet(nc, pdata, len);
|
||||
+}
|
||||
+
|
||||
+static void pcap_send(void *opaque)
|
||||
+{
|
||||
+ PCAPState *s = (PCAPState *)opaque;
|
||||
+
|
||||
+ pcap_dispatch(s->handle, 1, (pcap_handler)&pcap_callback, (u_char *)&s->nc);
|
||||
+ for (;;) {
|
||||
+ if (pcap_dispatch(s->handle, 0, (pcap_handler)&pcap_callback, (u_char *)&s->nc) >= 0)
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void pcap_cleanup(VLANClientState *nc)
|
||||
@ -162,10 +174,6 @@ Index: net.c
|
||||
+ .type = NET_CLIENT_TYPE_PCAP,
|
||||
+ .size = sizeof(PCAPState),
|
||||
+ .receive = pcap_receive,
|
||||
+#if 0
|
||||
+ .receive_raw = tap_receive_raw,
|
||||
+ .receive_iov = tap_receive_iov,
|
||||
+#endif
|
||||
+ .cleanup = pcap_cleanup,
|
||||
+};
|
||||
+
|
||||
@ -181,52 +189,65 @@ Index: net.c
|
||||
+
|
||||
+ s = qemu_mallocz(sizeof(PCAPState));
|
||||
+ nc = qemu_new_net_client(&net_pcap_info, vlan, NULL, model, name);
|
||||
+#if 0
|
||||
+ nc = qemu_new_vlan_client(NET_CLIENT_TYPE_PCAP,
|
||||
+ vlan, NULL, model, name, NULL,
|
||||
+ pcap_receive, NULL, NULL,
|
||||
+ pcap_cleanup, s);
|
||||
+#endif
|
||||
+
|
||||
+ s = DO_UPCAST(PCAPState, nc, nc);
|
||||
+ if (!s)
|
||||
+ return -1;
|
||||
+ return -1;
|
||||
+
|
||||
+ if (ifname == NULL && (ifname = pcap_lookupdev(errbuf)) == NULL) {
|
||||
+ fprintf(stderr, "qemu: pcap_create: %s\n", errbuf);
|
||||
+ goto fail;
|
||||
+ fprintf(stderr, "qemu: pcap_create: %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(CONFIG_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)
|
||||
@ -234,8 +255,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(CONFIG_BPF)
|
||||
@ -244,11 +265,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 */
|
||||
+
|
||||
@ -258,11 +279,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 /* CONFIG_BPF */
|
||||
@ -272,14 +293,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 */
|
||||
@ -288,9 +309,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;
|
||||
@ -318,7 +339,7 @@ Index: net.c
|
||||
#define NET_COMMON_PARAMS_DESC \
|
||||
{ \
|
||||
.name = "type", \
|
||||
@@ -980,6 +1188,20 @@ static struct {
|
||||
@@ -980,6 +1207,20 @@ static struct {
|
||||
#endif /* _WIN32 */
|
||||
{ /* end of list */ }
|
||||
},
|
||||
@ -339,9 +360,9 @@ Index: net.c
|
||||
}, {
|
||||
.type = "socket",
|
||||
.init = net_init_socket,
|
||||
--- qemu-options.hx.orig 2009-08-28 16:46:21.000000000 -0400
|
||||
+++ qemu-options.hx 2009-09-02 16:20:14.000000000 -0400
|
||||
@@ -783,6 +783,10 @@
|
||||
--- qemu-options.hx.orig 2010-01-14 17:18:00.000000000 -0500
|
||||
+++ qemu-options.hx 2010-01-29 14:36:00.000000000 -0500
|
||||
@@ -799,6 +799,10 @@ DEF("smb", HAS_ARG, QEMU_OPTION_smb, "")
|
||||
DEF("net", HAS_ARG, QEMU_OPTION_net,
|
||||
"-net nic[,vlan=n][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n"
|
||||
" create a new Network Interface Card and connect it to VLAN 'n'\n"
|
||||
|
@ -122,6 +122,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 is no longer supported in qemu upstream after the 0.11 branch
|
||||
was created, which means also not in this version. (Linux has moved
|
||||
on to kvm now for qemu(-like) virtualization needs, so if you want qemu
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
PORTNAME= qemu
|
||||
PORTVERSION= 0.11.1
|
||||
PORTREVISION= 1
|
||||
CATEGORIES= emulators
|
||||
MASTER_SITES= ${MASTER_SITE_SAVANNAH} \
|
||||
http://bellard.org/qemu/
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user