@@ -42,6 +42,36 @@ static QTAILQ_HEAD(, VLANClientState) non_vlan_clients;
int default_net = 1;
+static void pcap_dump(NetClientDump *net_client_dump, const uint8_t *buf, size_t size)
+{
+ struct pcap_sf_pkthdr hdr;
+ int64_t ts;
+ int caplen;
+
+ if (!net_client_dump) {
+ return;
+ }
+
+ /* Early return in case of previous error. */
+ if (net_client_dump->fd < 0) {
+ return;
+ }
+
+ ts = muldiv64(qemu_get_clock(vm_clock), 1000000, get_ticks_per_sec());
+ caplen = size > net_client_dump->pcap_caplen ? net_client_dump->pcap_caplen : size;
+
+ hdr.ts.tv_sec = ts / 1000000;
+ hdr.ts.tv_usec = ts % 1000000;
+ hdr.caplen = caplen;
+ hdr.len = size;
+ if (write(net_client_dump->fd, &hdr, sizeof(hdr)) != sizeof(hdr) ||
+ write(net_client_dump->fd, buf, caplen) != caplen) {
+ error_report("Error writing pcap dump, closing descriptor.");
+ close(net_client_dump->fd);
+ net_client_dump->fd = -1;
+ }
+}
+
/***********************************************************/
/* network device redirectors */
@@ -495,6 +525,7 @@ static ssize_t qemu_send_packet_async_with_flags(VLANClientState *sender,
NetPacketSent *sent_cb)
{
NetQueue *queue;
+ NetClientDump *dump;
#ifdef DEBUG_NET
printf("qemu_send_packet_async:\n");
@@ -507,6 +538,14 @@ static ssize_t qemu_send_packet_async_with_flags(VLANClientState *sender,
if (sender->peer) {
queue = sender->peer->send_queue;
+ if (sender->dump || sender->peer->dump) {
+ if (sender->dump) {
+ dump = sender->dump;
+ } else {
+ dump = sender->peer->dump;
+ }
+ pcap_dump(dump, buf, size);
+ }
} else {
queue = sender->vlan->send_queue;
}
@@ -621,6 +660,8 @@ ssize_t qemu_sendv_packet_async(VLANClientState *sender,
NetPacketSent *sent_cb)
{
NetQueue *queue;
+ NetClientDump *dump;
+ int i;
if (sender->link_down || (!sender->peer && !sender->vlan)) {
return calc_iov_length(iov, iovcnt);
@@ -628,6 +669,17 @@ ssize_t qemu_sendv_packet_async(VLANClientState *sender,
if (sender->peer) {
queue = sender->peer->send_queue;
+ if (sender->dump || sender->peer->dump) {
+ if (sender->dump) {
+ dump = sender->dump;
+ } else {
+ dump = sender->peer->dump;
+ }
+ /* XXX handle vnet_hdr headers or dump will be corrupt */
+ for (i = 0; i < iovcnt; i++) {
+ pcap_dump(dump, (const uint8_t*)iov[i].iov_base, iov[i].iov_len);
+ }
+ }
} else {
queue = sender->vlan->send_queue;
}
@@ -1347,6 +1399,44 @@ static int net_init_netdev(QemuOpts *opts, void *dummy)
return net_client_init(NULL, opts, 1);
}
+NetClientDump *net_client_create_dump(const char *filename, int len) {
+ NetClientDump *net_client_dump;
+ struct pcap_file_hdr hdr;
+ int fd;
+
+ fd = open(filename, O_CREAT | O_WRONLY | O_BINARY, 0644);
+ if (fd < 0) {
+ error_report("Cannot create dump file: %s", filename);
+ return NULL;
+ }
+
+ if (!len) {
+ len = 65536;
+ }
+
+ hdr.magic = PCAP_MAGIC;
+ hdr.version_major = 2;
+ hdr.version_minor = 4;
+ hdr.thiszone = 0;
+ hdr.sigfigs = 0;
+ hdr.snaplen = len;
+ hdr.linktype = 1;
+
+ if (write(fd, &hdr, sizeof(hdr)) < sizeof(hdr)) {
+ error_report("Error writing dump file error: %s", strerror(errno));
+ close(fd);
+ return NULL;
+ }
+
+ net_client_dump = qemu_malloc(sizeof(NetClientDump));
+ net_client_dump->fd = fd;
+ net_client_dump->pcap_caplen = len;
+ pstrcpy(net_client_dump->filename, sizeof(char[128]), filename);
+
+ return net_client_dump;
+
+}
+
int net_init_clients(void)
{
if (default_net) {
@@ -55,6 +55,12 @@ typedef struct NetClientInfo {
NetPoll *poll;
} NetClientInfo;
+struct NetClientDump {
+ int fd;
+ int pcap_caplen;
+ char filename[128];
+};
+
struct VLANClientState {
NetClientInfo *info;
int link_down;
@@ -66,6 +72,7 @@ struct VLANClientState {
char *name;
char info_str[256];
unsigned receive_disabled : 1;
+ NetClientDump *dump;
};
typedef struct NICState {
@@ -81,6 +88,7 @@ struct VLANState {
NetQueue *send_queue;
};
+NetClientDump *net_client_create_dump(const char *filename, int len);
VLANState *qemu_find_vlan(int id, int allocate);
VLANClientState *qemu_find_netdev(const char *id);
VLANClientState *qemu_new_net_client(NetClientInfo *info,
@@ -212,6 +212,7 @@ typedef struct CharDriverState CharDriverState;
typedef struct MACAddr MACAddr;
typedef struct VLANState VLANState;
typedef struct VLANClientState VLANClientState;
+typedef struct NetClientDump NetClientDump;
typedef struct i2c_bus i2c_bus;
typedef struct i2c_slave i2c_slave;
typedef struct SMBusDevice SMBusDevice;
Signed-off-by: Miguel Di Ciurcio Filho <miguel.filho@gmail.com> --- net.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ net.h | 8 +++++ qemu-common.h | 1 + 3 files changed, 99 insertions(+), 0 deletions(-)