aboutsummaryrefslogtreecommitdiff
path: root/replay/replay-net.c
diff options
context:
space:
mode:
Diffstat (limited to 'replay/replay-net.c')
-rw-r--r--replay/replay-net.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/replay/replay-net.c b/replay/replay-net.c
new file mode 100644
index 0000000000..80b7054156
--- /dev/null
+++ b/replay/replay-net.c
@@ -0,0 +1,102 @@
+/*
+ * replay-net.c
+ *
+ * Copyright (c) 2010-2016 Institute for System Programming
+ * of the Russian Academy of Sciences.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "sysemu/replay.h"
+#include "replay-internal.h"
+#include "sysemu/sysemu.h"
+#include "net/net.h"
+#include "net/filter.h"
+#include "qemu/iov.h"
+
+struct ReplayNetState {
+ NetFilterState *nfs;
+ int id;
+};
+
+typedef struct NetEvent {
+ uint8_t id;
+ uint32_t flags;
+ uint8_t *data;
+ size_t size;
+} NetEvent;
+
+static NetFilterState **network_filters;
+static int network_filters_count;
+
+ReplayNetState *replay_register_net(NetFilterState *nfs)
+{
+ ReplayNetState *rns = g_new0(ReplayNetState, 1);
+ rns->nfs = nfs;
+ rns->id = network_filters_count++;
+ network_filters = g_realloc(network_filters,
+ network_filters_count
+ * sizeof(*network_filters));
+ network_filters[network_filters_count - 1] = nfs;
+ return rns;
+}
+
+void replay_unregister_net(ReplayNetState *rns)
+{
+ network_filters[rns->id] = NULL;
+ g_free(rns);
+}
+
+void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
+ const struct iovec *iov, int iovcnt)
+{
+ NetEvent *event = g_new(NetEvent, 1);
+ event->flags = flags;
+ event->data = g_malloc(iov_size(iov, iovcnt));
+ event->size = iov_size(iov, iovcnt);
+ event->id = rns->id;
+ iov_to_buf(iov, iovcnt, 0, event->data, event->size);
+
+ replay_add_event(REPLAY_ASYNC_EVENT_NET, event, NULL, 0);
+}
+
+void replay_event_net_run(void *opaque)
+{
+ NetEvent *event = opaque;
+ struct iovec iov = {
+ .iov_base = (void *)event->data,
+ .iov_len = event->size
+ };
+
+ assert(event->id < network_filters_count);
+
+ qemu_netfilter_pass_to_next(network_filters[event->id]->netdev,
+ event->flags, &iov, 1, network_filters[event->id]);
+
+ g_free(event->data);
+ g_free(event);
+}
+
+void replay_event_net_save(void *opaque)
+{
+ NetEvent *event = opaque;
+
+ replay_put_byte(event->id);
+ replay_put_dword(event->flags);
+ replay_put_array(event->data, event->size);
+}
+
+void *replay_event_net_load(void)
+{
+ NetEvent *event = g_new(NetEvent, 1);
+
+ event->id = replay_get_byte();
+ event->flags = replay_get_dword();
+ replay_get_array_alloc(&event->data, &event->size);
+
+ return event;
+}