Commit 646c5478 authored by Pavel Dovgalyuk's avatar Pavel Dovgalyuk Committed by Jason Wang
Browse files

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: default avatarPavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
Signed-off-by: default avatarJason Wang <jasowang@redhat.com>
parent e92fbc75
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -195,3 +195,17 @@ Queue is flushed at checkpoints and information about processed requests
is recorded to the log. In replay phase the queue is matched with
events read from the log. Therefore block devices requests are processed
deterministically.

Network devices
---------------

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.
+12 −0
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ enum ReplayCheckpoint {
};
typedef enum ReplayCheckpoint ReplayCheckpoint;

typedef struct ReplayNetState ReplayNetState;

extern ReplayMode replay_mode;

/* Replay process control functions */
@@ -137,4 +139,14 @@ void replay_char_read_all_save_error(int res);
/*! Writes character read_all execution result into the replay log. */
void replay_char_read_all_save_buf(uint8_t *buf, int offset);

/* Network */

/*! Registers replay network filter attached to some backend. */
ReplayNetState *replay_register_net(NetFilterState *nfs);
/*! Unregisters replay network filter. */
void replay_unregister_net(ReplayNetState *rns);
/*! Called to write network packet to the replay log. */
void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
                             const struct iovec *iov, int iovcnt);

#endif
+1 −0
Original line number Diff line number Diff line
@@ -19,3 +19,4 @@ common-obj-y += filter-mirror.o
common-obj-y += colo-compare.o
common-obj-y += colo.o
common-obj-y += filter-rewriter.o
common-obj-y += filter-replay.o

net/filter-replay.c

0 → 100644
+92 −0
Original line number Diff line number Diff line
/*
 * filter-replay.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 "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/timer.h"
#include "qapi/visitor.h"
#include "net/filter.h"
#include "sysemu/replay.h"

#define TYPE_FILTER_REPLAY "filter-replay"

#define FILTER_REPLAY(obj) \
    OBJECT_CHECK(NetFilterReplayState, (obj), TYPE_FILTER_REPLAY)

struct NetFilterReplayState {
    NetFilterState nfs;
    ReplayNetState *rns;
};
typedef struct NetFilterReplayState NetFilterReplayState;

static ssize_t filter_replay_receive_iov(NetFilterState *nf,
                                         NetClientState *sndr,
                                         unsigned flags,
                                         const struct iovec *iov,
                                         int iovcnt, NetPacketSent *sent_cb)
{
    NetFilterReplayState *nfrs = FILTER_REPLAY(nf);
    switch (replay_mode) {
    case REPLAY_MODE_RECORD:
        if (nf->netdev == sndr) {
            replay_net_packet_event(nfrs->rns, flags, iov, iovcnt);
            return iov_size(iov, iovcnt);
        }
        return 0;
    case REPLAY_MODE_PLAY:
        /* Drop all packets in replay mode.
           Packets from the log will be injected by the replay module. */
        return iov_size(iov, iovcnt);
    default:
        /* Pass all the packets. */
        return 0;
    }
}

static void filter_replay_instance_init(Object *obj)
{
    NetFilterReplayState *nfrs = FILTER_REPLAY(obj);
    nfrs->rns = replay_register_net(&nfrs->nfs);
}

static void filter_replay_instance_finalize(Object *obj)
{
    NetFilterReplayState *nfrs = FILTER_REPLAY(obj);
    replay_unregister_net(nfrs->rns);
}

static void filter_replay_class_init(ObjectClass *oc, void *data)
{
    NetFilterClass *nfc = NETFILTER_CLASS(oc);

    nfc->receive_iov = filter_replay_receive_iov;
}

static const TypeInfo filter_replay_info = {
    .name = TYPE_FILTER_REPLAY,
    .parent = TYPE_NETFILTER,
    .class_init = filter_replay_class_init,
    .instance_init = filter_replay_instance_init,
    .instance_finalize = filter_replay_instance_finalize,
    .instance_size = sizeof(NetFilterReplayState),
};

static void filter_replay_register_types(void)
{
    type_register_static(&filter_replay_info);
}

type_init(filter_replay_register_types);
+1 −0
Original line number Diff line number Diff line
@@ -5,3 +5,4 @@ common-obj-y += replay-time.o
common-obj-y += replay-input.o
common-obj-y += replay-char.o
common-obj-y += replay-snapshot.o
common-obj-y += replay-net.o
Loading