qemu/replay/replay-net.c
Pavel Dovgalyuk 646c5478c0 record/replay: add network support
This patch adds support of recording and replaying network packets in
irount rr mode.

Record and replay for network interactions is performed with the network filter.
Each backend must have its own instance of the replay filter as follows:
 -netdev user,id=net1 -device rtl8139,netdev=net1
 -object filter-replay,id=replay,netdev=net1

Replay network filter is used to record and replay network packets. While
recording the virtual machine this filter puts all packets coming from
the outer world into the log. In replay mode packets from the log are
injected into the network device. All interactions with network backend
in replay mode are disabled.

v5 changes:
 - using iov_to_buf function instead of loop

Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2017-01-06 10:38:00 +08:00

102 lines
2.5 KiB
C

/*
* 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;
}