[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [Patch] Add -net dump option
From: |
Tristan Gingold |
Subject: |
[Qemu-devel] [Patch] Add -net dump option |
Date: |
Thu, 5 Mar 2009 11:10:18 +0100 |
User-agent: |
Mutt/1.4.2.3i |
Hi,
latest version of the patch inlined.
Signed-off-by: Tristan Gingold <address@hidden>
Thanks,
Tristan.
Index: vl.c
===================================================================
--- vl.c (revision 6685)
+++ vl.c (working copy)
@@ -3987,6 +3987,8 @@
" Use group 'groupname' and mode 'octalmode' to
change default\n"
" ownership and permissions for communication
port.\n"
#endif
+ "-net dump[,vlan=n][,file=f][,len=n]\n"
+ " dump traffic on vlan 'n' to file 'f' (max n bytes
per packet)\n"
"-net none use it alone to have zero network devices; if no
-net option\n"
" is provided, the default is '-net nic -net user'\n"
#ifdef CONFIG_SLIRP
Index: net.c
===================================================================
--- net.c (revision 6685)
+++ net.c (working copy)
@@ -27,6 +27,7 @@
#include "sysemu.h"
#include "qemu-timer.h"
#include "qemu-char.h"
+#include "qemu-log.h"
#include "audio/audio.h"
#include <unistd.h>
@@ -324,14 +325,14 @@
return strdup(buf);
}
-VLANClientState *qemu_new_vlan_client(VLANState *vlan,
- const char *model,
- const char *name,
- IOReadHandler *fd_read,
- IOCanRWHandler *fd_can_read,
- void *opaque)
+static VLANClientState *qemu_new_vlan_client_common(VLANState *vlan,
+ const char *model,
+ const char *name,
+ IOReadHandler *fd_read,
+ IOCanRWHandler *fd_can_read,
+ void *opaque)
{
- VLANClientState *vc, **pvc;
+ VLANClientState *vc;
vc = qemu_mallocz(sizeof(VLANClientState));
vc->model = strdup(model);
if (name)
@@ -343,14 +344,58 @@
vc->opaque = opaque;
vc->vlan = vlan;
- vc->next = NULL;
+ return vc;
+}
+
+VLANClientState *qemu_new_vlan_client(VLANState *vlan,
+ const char *model,
+ const char *name,
+ IOReadHandler *fd_read,
+ IOCanRWHandler *fd_can_read,
+ void *opaque)
+{
+ VLANClientState *vc, **pvc;
+
+ vc = qemu_new_vlan_client_common(vlan, model, name, fd_read, fd_can_read,
+ opaque);
+ /* Append but before last_client. */
pvc = &vlan->first_client;
- while (*pvc != NULL)
+ while (*pvc != NULL) {
+ if ((*pvc)->last_client) {
+ vc->next = *pvc;
+ break;
+ }
pvc = &(*pvc)->next;
+ }
*pvc = vc;
return vc;
}
+static VLANClientState *qemu_new_vlan_client_tail(VLANState *vlan,
+ const char *model,
+ const char *name,
+ IOReadHandler *fd_read,
+ IOCanRWHandler *fd_can_read,
+ void *opaque)
+{
+ VLANClientState *vc, **pvc;
+
+ vc = qemu_new_vlan_client_common(vlan, model, name, fd_read, fd_can_read,
+ opaque);
+ vc->last_client = 1;
+ pvc = &vlan->first_client;
+ while (*pvc != NULL) {
+ if ((*pvc)->last_client) {
+ fprintf(stderr, "Multiple vlan last client (%s and %s)\n",
+ (*pvc)->name, name);
+ exit(1);
+ }
+ pvc = &(*pvc)->next;
+ }
+ *pvc = vc;
+ return vc;
+}
+
void qemu_del_vlan_client(VLANClientState *vc)
{
VLANClientState **pvc = &vc->vlan->first_client;
@@ -516,8 +561,8 @@
slirp_inited = 1;
slirp_init(slirp_restrict, slirp_ip);
}
- slirp_vc = qemu_new_vlan_client(vlan, model, name,
- slirp_receive, NULL, NULL);
+ slirp_vc = qemu_new_vlan_client_tail(vlan, model, name,
+ slirp_receive, NULL, NULL);
slirp_vc->info_str[0] = '\0';
return 0;
}
@@ -1088,6 +1133,91 @@
}
#endif
+typedef struct DumpState {
+ VLANClientState *tcpdump_vc;
+ FILE *tcpdump_file;
+ int tcpdump_caplen;
+} DumpState;
+
+#define TCPDUMP_MAGIC 0xa1b2c3d4
+
+struct pcap_file_hdr {
+ uint32_t magic;
+ uint16_t version_major;
+ uint16_t version_minor;
+ int32_t thiszone;
+ uint32_t sigfigs;
+ uint32_t snaplen;
+ uint32_t linktype;
+};
+
+struct pcap_sf_pkthdr {
+ struct {
+ int32_t tv_sec;
+ int32_t tv_usec;
+ } ts;
+ uint32_t caplen;
+ uint32_t len;
+};
+
+static void tcpdump_receive(void *opaque, const uint8_t *buf, int size)
+{
+ DumpState *ds = (DumpState *)opaque;
+ struct pcap_sf_pkthdr hdr;
+ int64_t ts;
+ int caplen;
+
+ /* Early return in case of previous error. */
+ if (ds->tcpdump_file == NULL)
+ return;
+
+ ts = muldiv64 (qemu_get_clock(vm_clock),1000000, ticks_per_sec);
+ caplen = size > ds->tcpdump_caplen ? ds->tcpdump_caplen : size;
+
+ hdr.ts.tv_sec = ts / 1000000000LL;
+ hdr.ts.tv_usec = ts % 1000000;
+ hdr.caplen = caplen;
+ hdr.len = size;
+ if (fwrite(&hdr, sizeof(hdr), 1, ds->tcpdump_file) != 1
+ || fwrite(buf, caplen, 1, ds->tcpdump_file) != 1) {
+ qemu_log("-net dump write error - stop dump\n");
+ fclose(ds->tcpdump_file);
+ ds->tcpdump_file = NULL;
+ }
+}
+
+static int net_tcpdump_init(VLANState *vlan, const char *device,
+ const char *name, const char *filename, int len)
+{
+ struct pcap_file_hdr hdr;
+ DumpState *ds;
+
+ ds = qemu_malloc (sizeof (DumpState));
+ ds->tcpdump_file = fopen(filename, "wb");
+ if (!ds->tcpdump_file) {
+ fprintf(stderr, "-net dump: can't open %s\n", filename);
+ exit(1);
+ }
+
+ ds->tcpdump_caplen = len;
+
+ hdr.magic = TCPDUMP_MAGIC;
+ hdr.version_major = 2;
+ hdr.version_minor = 4;
+ hdr.thiszone = 0;
+ hdr.sigfigs = 0;
+ hdr.snaplen = ds->tcpdump_caplen;
+ hdr.linktype = 1;
+
+ fwrite(&hdr, sizeof(hdr), 1, ds->tcpdump_file);
+
+ ds->tcpdump_vc = qemu_new_vlan_client(vlan, device, name,
+ tcpdump_receive, NULL, ds);
+ snprintf(ds->tcpdump_vc->info_str, sizeof(ds->tcpdump_vc->info_str),
+ "tcpdump to %s (len=%d)", filename, len);
+ return 0;
+}
+
/* network connection */
typedef struct NetSocketState {
VLANClientState *vc;
@@ -1762,6 +1892,20 @@
ret = net_vde_init(vlan, device, name, vde_sock, vde_port, vde_group,
vde_mode);
} else
#endif
+ if (!strcmp(device, "dump")) {
+ int len = 64;
+ if (get_param_value(buf, sizeof(buf), "len", p) > 0) {
+ len = strtol(buf, NULL, 0);
+ }
+
+ if (!get_param_value(buf, sizeof(buf), "file", p)) {
+ if (vlan_id == 0)
+ strcpy(buf, "qemu.tcpdump");
+ else
+ snprintf(buf, sizeof(buf), "qemu-vlan%d.tcpdump", vlan_id);
+ }
+ ret = net_tcpdump_init(vlan, device, name, buf, len);
+ } else
{
fprintf(stderr, "Unknown network device: %s\n", device);
if (name)
Index: net.h
===================================================================
--- net.h (revision 6685)
+++ net.h (working copy)
@@ -19,6 +19,9 @@
IOCanRWHandler *fd_can_read;
LinkStatusChanged *link_status_changed;
int link_down;
+ /* If set this client must be the last in the VLAN (currently set only
+ by slirp). */
+ int last_client;
void *opaque;
struct VLANClientState *next;
struct VLANState *vlan;
Index: qemu-doc.texi
===================================================================
--- qemu-doc.texi (revision 6685)
+++ qemu-doc.texi (working copy)
@@ -742,6 +742,11 @@
qemu linux.img -net nic -net vde,sock=/tmp/myswitch
@end example
address@hidden -net dump[,address@hidden,address@hidden,address@hidden
+Dump network traffic on VLAN @var{n} to file @var{file} (@file{qemu.tcpdump} by
+default). At most @var{len} bytes (64 by default) by packet are stored. The
+dump can be analyzed with tools such as tcpdump.
+
@item -net none
Indicate that no network devices should be configured. It is used to
override the default configuration (@option{-net nic -net user}) which
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [Patch] Add -net dump option,
Tristan Gingold <=