mirror of https://github.com/xemu-project/xemu.git
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1 iQEcBAABAgAGBQJYbwc1AAoJEO8Ells5jWIR1Y0IAKtI6HKo075VCtHJG/NilwAI bhOSirja8oa0w8sLaWe706bwCAWCjQJpNQID8CDWpDxaNinLn7tPC4gFzTxcvWqV A+BGvtyncniZywBBWUM6XkIXc0yPw7t/UZ1cobkx1RB5oDtagW3vgWnigqk+iiE3 fq0M9Q7utFQV0L08TShhY2cOV6PZJV7usUNA/ev8gzpjMwjQEYUboMkMNt853pHA GDzTFTrOIV3+fI8olERpHUrszL3AKLFiMI+XdyOIB8fhe41hnnDf3BLZF2x0t0KY yHPvRpb8i6YeGOif2CzWetbWW/6nj291z8PfgmNkb09pAqTyqQ2gJp+9Bib6YIo= =aP1M -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging # gpg: Signature made Fri 06 Jan 2017 02:55:49 GMT # gpg: using RSA key 0xEF04965B398D6211 # gpg: Good signature from "Jason Wang (Jason Wang on RedHat) <jasowang@redhat.com>" # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 215D 46F4 8246 689E C77F 3562 EF04 965B 398D 6211 * remotes/jasowang/tags/net-pull-request: fsl_etsec: Fix Tx BD ring wrapping handling rtl8139: correctly handle PHY reset record/replay: add network support Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
a01b1e9a00
|
@ -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.
|
||||
|
|
|
@ -358,25 +358,24 @@ void etsec_walk_tx_ring(eTSEC *etsec, int ring_nbr)
|
|||
/* Save flags before BD update */
|
||||
bd_flags = bd.flags;
|
||||
|
||||
if (bd_flags & BD_TX_READY) {
|
||||
process_tx_bd(etsec, &bd);
|
||||
|
||||
/* Write back BD after update */
|
||||
write_buffer_descriptor(etsec, bd_addr, &bd);
|
||||
if (!(bd_flags & BD_TX_READY)) {
|
||||
break;
|
||||
}
|
||||
|
||||
process_tx_bd(etsec, &bd);
|
||||
/* Write back BD after update */
|
||||
write_buffer_descriptor(etsec, bd_addr, &bd);
|
||||
|
||||
/* Wrap or next BD */
|
||||
if (bd_flags & BD_WRAP) {
|
||||
bd_addr = ring_base;
|
||||
} else {
|
||||
bd_addr += sizeof(eTSEC_rxtx_bd);
|
||||
}
|
||||
} while (TRUE);
|
||||
|
||||
} while (bd_addr != ring_base);
|
||||
|
||||
bd_addr = ring_base;
|
||||
|
||||
/* Save the Buffer Descriptor Pointers to current bd */
|
||||
/* Save the Buffer Descriptor Pointers to last bd that was not
|
||||
* succesfully closed */
|
||||
etsec->regs[TBPTR0 + ring_nbr].value = bd_addr;
|
||||
|
||||
/* Set transmit halt THLTx */
|
||||
|
|
|
@ -1205,6 +1205,20 @@ static void rtl8139_reset_rxring(RTL8139State *s, uint32_t bufferSize)
|
|||
s->RxBufAddr = 0;
|
||||
}
|
||||
|
||||
static void rtl8139_reset_phy(RTL8139State *s)
|
||||
{
|
||||
s->BasicModeStatus = 0x7809;
|
||||
s->BasicModeStatus |= 0x0020; /* autonegotiation completed */
|
||||
/* preserve link state */
|
||||
s->BasicModeStatus |= qemu_get_queue(s->nic)->link_down ? 0 : 0x04;
|
||||
|
||||
s->NWayAdvert = 0x05e1; /* all modes, full duplex */
|
||||
s->NWayLPAR = 0x05e1; /* all modes, full duplex */
|
||||
s->NWayExpansion = 0x0001; /* autonegotiation supported */
|
||||
|
||||
s->CSCR = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD;
|
||||
}
|
||||
|
||||
static void rtl8139_reset(DeviceState *d)
|
||||
{
|
||||
RTL8139State *s = RTL8139(d);
|
||||
|
@ -1256,25 +1270,14 @@ static void rtl8139_reset(DeviceState *d)
|
|||
s->Config3 = 0x1; /* fast back-to-back compatible */
|
||||
s->Config5 = 0x0;
|
||||
|
||||
s->CSCR = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD;
|
||||
|
||||
s->CpCmd = 0x0; /* reset C+ mode */
|
||||
s->cplus_enabled = 0;
|
||||
|
||||
|
||||
// s->BasicModeCtrl = 0x3100; // 100Mbps, full duplex, autonegotiation
|
||||
// s->BasicModeCtrl = 0x2100; // 100Mbps, full duplex
|
||||
s->BasicModeCtrl = 0x1000; // autonegotiation
|
||||
|
||||
s->BasicModeStatus = 0x7809;
|
||||
//s->BasicModeStatus |= 0x0040; /* UTP medium */
|
||||
s->BasicModeStatus |= 0x0020; /* autonegotiation completed */
|
||||
/* preserve link state */
|
||||
s->BasicModeStatus |= qemu_get_queue(s->nic)->link_down ? 0 : 0x04;
|
||||
|
||||
s->NWayAdvert = 0x05e1; /* all modes, full duplex */
|
||||
s->NWayLPAR = 0x05e1; /* all modes, full duplex */
|
||||
s->NWayExpansion = 0x0001; /* autonegotiation supported */
|
||||
rtl8139_reset_phy(s);
|
||||
|
||||
/* also reset timer and disable timer interrupt */
|
||||
s->TCTR = 0;
|
||||
|
@ -1469,7 +1472,7 @@ static void rtl8139_BasicModeCtrl_write(RTL8139State *s, uint32_t val)
|
|||
DPRINTF("BasicModeCtrl register write(w) val=0x%04x\n", val);
|
||||
|
||||
/* mask unwritable bits */
|
||||
uint32_t mask = 0x4cff;
|
||||
uint32_t mask = 0xccff;
|
||||
|
||||
if (1 || !rtl8139_config_writable(s))
|
||||
{
|
||||
|
@ -1479,6 +1482,11 @@ static void rtl8139_BasicModeCtrl_write(RTL8139State *s, uint32_t val)
|
|||
mask |= 0x0100;
|
||||
}
|
||||
|
||||
if (val & 0x8000) {
|
||||
/* Reset PHY */
|
||||
rtl8139_reset_phy(s);
|
||||
}
|
||||
|
||||
val = SET_MASKED(val, mask, s->BasicModeCtrl);
|
||||
|
||||
s->BasicModeCtrl = val;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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);
|
|
@ -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
|
||||
|
|
|
@ -54,6 +54,9 @@ static void replay_run_event(Event *event)
|
|||
case REPLAY_ASYNC_EVENT_BLOCK:
|
||||
aio_bh_call(event->opaque);
|
||||
break;
|
||||
case REPLAY_ASYNC_EVENT_NET:
|
||||
replay_event_net_run(event->opaque);
|
||||
break;
|
||||
default:
|
||||
error_report("Replay: invalid async event ID (%d) in the queue",
|
||||
event->event_kind);
|
||||
|
@ -189,6 +192,9 @@ static void replay_save_event(Event *event, int checkpoint)
|
|||
case REPLAY_ASYNC_EVENT_BLOCK:
|
||||
replay_put_qword(event->id);
|
||||
break;
|
||||
case REPLAY_ASYNC_EVENT_NET:
|
||||
replay_event_net_save(event->opaque);
|
||||
break;
|
||||
default:
|
||||
error_report("Unknown ID %" PRId64 " of replay event", event->id);
|
||||
exit(1);
|
||||
|
@ -252,6 +258,11 @@ static Event *replay_read_event(int checkpoint)
|
|||
read_id = replay_get_qword();
|
||||
}
|
||||
break;
|
||||
case REPLAY_ASYNC_EVENT_NET:
|
||||
event = g_malloc0(sizeof(Event));
|
||||
event->event_kind = read_event_kind;
|
||||
event->opaque = replay_event_net_load();
|
||||
return event;
|
||||
default:
|
||||
error_report("Unknown ID %d of replay event", read_event_kind);
|
||||
exit(1);
|
||||
|
|
|
@ -50,6 +50,7 @@ enum ReplayAsyncEventKind {
|
|||
REPLAY_ASYNC_EVENT_INPUT_SYNC,
|
||||
REPLAY_ASYNC_EVENT_CHAR_READ,
|
||||
REPLAY_ASYNC_EVENT_BLOCK,
|
||||
REPLAY_ASYNC_EVENT_NET,
|
||||
REPLAY_ASYNC_COUNT
|
||||
};
|
||||
|
||||
|
@ -161,6 +162,15 @@ void replay_event_char_read_save(void *opaque);
|
|||
/*! Reads char event read from the file. */
|
||||
void *replay_event_char_read_load(void);
|
||||
|
||||
/* Network devices */
|
||||
|
||||
/*! Called to run network event. */
|
||||
void replay_event_net_run(void *opaque);
|
||||
/*! Writes network event to the file. */
|
||||
void replay_event_net_save(void *opaque);
|
||||
/*! Reads network from the file. */
|
||||
void *replay_event_net_load(void);
|
||||
|
||||
/* VMState-related functions */
|
||||
|
||||
/* Registers replay VMState.
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
/* Current version of the replay mechanism.
|
||||
Increase it when file format changes. */
|
||||
#define REPLAY_VERSION 0xe02004
|
||||
#define REPLAY_VERSION 0xe02005
|
||||
/* Size of replay log header */
|
||||
#define HEADER_SIZE (sizeof(uint32_t) + sizeof(uint64_t))
|
||||
|
||||
|
|
3
vl.c
3
vl.c
|
@ -2859,7 +2859,8 @@ static bool object_create_initial(const char *type)
|
|||
g_str_equal(type, "filter-mirror") ||
|
||||
g_str_equal(type, "filter-redirector") ||
|
||||
g_str_equal(type, "colo-compare") ||
|
||||
g_str_equal(type, "filter-rewriter")) {
|
||||
g_str_equal(type, "filter-rewriter") ||
|
||||
g_str_equal(type, "filter-replay")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue