#include "qemu/osdep.h"
#include "clients.h"
#include "qapi/error.h"
-#include "qemu-common.h"
#include "qemu/error-report.h"
#include "qemu/iov.h"
-#include "qemu/log.h"
+#include "qemu/module.h"
#include "qemu/timer.h"
#include "qapi/visitor.h"
#include "net/filter.h"
+#include "qom/object.h"
+#include "sysemu/rtc.h"
typedef struct DumpState {
int64_t start_ts;
uint32_t len;
};
-static ssize_t dump_receive_iov(DumpState *s, const struct iovec *iov, int cnt)
+static ssize_t dump_receive_iov(DumpState *s, const struct iovec *iov, int cnt,
+ int offset)
{
struct pcap_sf_pkthdr hdr;
int64_t ts;
int caplen;
- size_t size = iov_size(iov, cnt);
- struct iovec dumpiov[cnt + 1];
+ size_t size = iov_size(iov, cnt) - offset;
+ g_autofree struct iovec *dumpiov = g_new(struct iovec, cnt + 1);
/* Early return in case of previous error. */
if (s->fd < 0) {
dumpiov[0].iov_base = &hdr;
dumpiov[0].iov_len = sizeof(hdr);
- cnt = iov_copy(&dumpiov[1], cnt, iov, cnt, 0, caplen);
+ cnt = iov_copy(&dumpiov[1], cnt, iov, cnt, offset, caplen);
if (writev(s->fd, dumpiov, cnt + 1) != sizeof(hdr) + caplen) {
error_report("network dump write error - stopping dump");
fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0644);
if (fd < 0) {
- error_setg_errno(errp, errno, "-net dump: can't open %s", filename);
+ error_setg_errno(errp, errno, "net dump: can't open %s", filename);
return -1;
}
hdr.linktype = 1;
if (write(fd, &hdr, sizeof(hdr)) < sizeof(hdr)) {
- error_setg_errno(errp, errno, "-net dump write error");
+ error_setg_errno(errp, errno, "net dump write error");
close(fd);
return -1;
}
return 0;
}
-/* Dumping via VLAN netclient */
-
-struct DumpNetClient {
- NetClientState nc;
- DumpState ds;
-};
-typedef struct DumpNetClient DumpNetClient;
-
-static ssize_t dumpclient_receive(NetClientState *nc, const uint8_t *buf,
- size_t size)
-{
- DumpNetClient *dc = DO_UPCAST(DumpNetClient, nc, nc);
- struct iovec iov = {
- .iov_base = (void *)buf,
- .iov_len = size
- };
-
- return dump_receive_iov(&dc->ds, &iov, 1);
-}
-
-static ssize_t dumpclient_receive_iov(NetClientState *nc,
- const struct iovec *iov, int cnt)
-{
- DumpNetClient *dc = DO_UPCAST(DumpNetClient, nc, nc);
-
- return dump_receive_iov(&dc->ds, iov, cnt);
-}
-
-static void dumpclient_cleanup(NetClientState *nc)
-{
- DumpNetClient *dc = DO_UPCAST(DumpNetClient, nc, nc);
-
- dump_cleanup(&dc->ds);
-}
-
-static NetClientInfo net_dump_info = {
- .type = NET_CLIENT_DRIVER_DUMP,
- .size = sizeof(DumpNetClient),
- .receive = dumpclient_receive,
- .receive_iov = dumpclient_receive_iov,
- .cleanup = dumpclient_cleanup,
-};
-
-int net_init_dump(const Netdev *netdev, const char *name,
- NetClientState *peer, Error **errp)
-{
- int len, rc;
- const char *file;
- char def_file[128];
- const NetdevDumpOptions *dump;
- NetClientState *nc;
- DumpNetClient *dnc;
-
- assert(netdev->type == NET_CLIENT_DRIVER_DUMP);
- dump = &netdev->u.dump;
-
- assert(peer);
-
- if (dump->has_file) {
- file = dump->file;
- } else {
- int id;
- int ret;
-
- ret = net_hub_id_for_client(peer, &id);
- assert(ret == 0); /* peer must be on a hub */
-
- snprintf(def_file, sizeof(def_file), "qemu-vlan%d.pcap", id);
- file = def_file;
- }
-
- if (dump->has_len) {
- if (dump->len > INT_MAX) {
- error_setg(errp, "invalid length: %"PRIu64, dump->len);
- return -1;
- }
- len = dump->len;
- } else {
- len = 65536;
- }
-
- nc = qemu_new_net_client(&net_dump_info, peer, "dump", name);
- snprintf(nc->info_str, sizeof(nc->info_str),
- "dump to %s (len=%d)", file, len);
-
- dnc = DO_UPCAST(DumpNetClient, nc, nc);
- rc = net_dump_state_init(&dnc->ds, file, len, errp);
- if (rc) {
- qemu_del_net_client(nc);
- }
- return rc;
-}
-
-/* Dumping via filter */
-
#define TYPE_FILTER_DUMP "filter-dump"
-#define FILTER_DUMP(obj) \
- OBJECT_CHECK(NetFilterDumpState, (obj), TYPE_FILTER_DUMP)
+OBJECT_DECLARE_SIMPLE_TYPE(NetFilterDumpState, FILTER_DUMP)
struct NetFilterDumpState {
NetFilterState nfs;
char *filename;
uint32_t maxlen;
};
-typedef struct NetFilterDumpState NetFilterDumpState;
static ssize_t filter_dump_receive_iov(NetFilterState *nf, NetClientState *sndr,
unsigned flags, const struct iovec *iov,
int iovcnt, NetPacketSent *sent_cb)
{
NetFilterDumpState *nfds = FILTER_DUMP(nf);
+ int offset = qemu_get_using_vnet_hdr(nf->netdev) ?
+ qemu_get_vnet_hdr_len(nf->netdev) : 0;
- dump_receive_iov(&nfds->ds, iov, iovcnt);
+ dump_receive_iov(&nfds->ds, iov, iovcnt, offset);
return 0;
}
void *opaque, Error **errp)
{
NetFilterDumpState *nfds = FILTER_DUMP(obj);
- Error *local_err = NULL;
uint32_t value;
- visit_type_uint32(v, name, &value, &local_err);
- if (local_err) {
- goto out;
+ if (!visit_type_uint32(v, name, &value, errp)) {
+ return;
}
if (value == 0) {
- error_setg(&local_err, "Property '%s.%s' doesn't take value '%u'",
+ error_setg(errp, "Property '%s.%s' doesn't take value '%u'",
object_get_typename(obj), name, value);
- goto out;
+ return;
}
nfds->maxlen = value;
-
-out:
- error_propagate(errp, local_err);
}
static char *file_dump_get_filename(Object *obj, Error **errp)
NetFilterDumpState *nfds = FILTER_DUMP(obj);
nfds->maxlen = 65536;
-
- object_property_add(obj, "maxlen", "int", filter_dump_get_maxlen,
- filter_dump_set_maxlen, NULL, NULL, NULL);
- object_property_add_str(obj, "file", file_dump_get_filename,
- file_dump_set_filename, NULL);
}
static void filter_dump_instance_finalize(Object *obj)
{
NetFilterClass *nfc = NETFILTER_CLASS(oc);
+ object_class_property_add(oc, "maxlen", "uint32", filter_dump_get_maxlen,
+ filter_dump_set_maxlen, NULL, NULL);
+ object_class_property_add_str(oc, "file", file_dump_get_filename,
+ file_dump_set_filename);
+
nfc->setup = filter_dump_setup;
nfc->cleanup = filter_dump_cleanup;
nfc->receive_iov = filter_dump_receive_iov;