Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging

# gpg: Signature made Thu 18 Jun 2020 14:16:22 BST
# gpg:                using RSA key EF04965B398D6211
# gpg: Good signature from "Jason Wang (Jason Wang on RedHat) <jasowang@redhat.com>" [marginal]
# 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: (33 commits)
  net: Drop the NetLegacy structure, always use Netdev instead
  net: Drop the legacy "name" parameter from the -net option
  hw/net/e1000e: Do not abort() on invalid PSRCTL register value
  colo-compare: Fix memory leak in packet_enqueue()
  net/colo-compare.c: Correct ordering in complete and finalize
  net/colo-compare.c: Check that colo-compare is active
  net/colo-compare.c: Only hexdump packets if tracing is enabled
  net/colo-compare.c: Fix deadlock in compare_chr_send
  chardev/char.c: Use qemu_co_sleep_ns if in coroutine
  net/colo-compare.c: Create event_bh with the right AioContext
  net: use peer when purging queue in qemu_flush_or_purge_queue_packets()
  net: cadence_gem: Fix RX address filtering
  net: cadence_gem: TX_LAST bit should be set by guest
  net: cadence_gem: Update the reset value for interrupt mask register
  net: cadnece_gem: Update irq_read_clear field of designcfg_debug1 reg
  net: cadence_gem: Add support for jumbo frames
  net: cadence_gem: Fix up code style
  net: cadence_gem: Move tx/rx packet buffert to CadenceGEMState
  net: cadence_gem: Set ISR according to queue in use
  net: cadence_gem: Define access permission for interrupt registers
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2020-06-18 16:52:10 +01:00
19 changed files with 909 additions and 453 deletions
+6 -1
View File
@@ -38,6 +38,7 @@
#include "qemu/module.h"
#include "qemu/option.h"
#include "qemu/id.h"
#include "qemu/coroutine.h"
#include "chardev/char-mux.h"
@@ -119,7 +120,11 @@ static int qemu_chr_write_buffer(Chardev *s,
retry:
res = cc->chr_write(s, buf + *offset, len - *offset);
if (res < 0 && errno == EAGAIN && write_all) {
g_usleep(100);
if (qemu_in_coroutine()) {
qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, 100000);
} else {
g_usleep(100);
}
goto retry;
}
+9 -6
View File
@@ -47,12 +47,6 @@ The 'file' driver for drives is no longer appropriate for character or host
devices and will only accept regular files (S_IFREG). The correct driver
for these file types is 'host_cdrom' or 'host_device' as appropriate.
``-net ...,name=``\ *name* (since 3.1)
''''''''''''''''''''''''''''''''''''''
The ``name`` parameter of the ``-net`` option is a synonym
for the ``id`` parameter, which should now be used instead.
``-smp`` (invalid topologies) (since 3.1)
'''''''''''''''''''''''''''''''''''''''''
@@ -441,6 +435,15 @@ What follows is a record of recently removed, formerly deprecated
features that serves as a record for users who have encountered
trouble after a recent upgrade.
System emulator command line arguments
--------------------------------------
``-net ...,name=``\ *name* (removed in 5.1)
'''''''''''''''''''''''''''''''''''''''''''
The ``name`` parameter of the ``-net`` option was a synonym
for the ``id`` parameter, which should now be used instead.
QEMU Machine Protocol (QMP) commands
------------------------------------
+1
View File
@@ -41,6 +41,7 @@ obj-$(CONFIG_MILKYMIST) += milkymist-minimac2.o
obj-$(CONFIG_PSERIES) += spapr_llan.o
obj-$(CONFIG_XILINX_ETHLITE) += xilinx_ethlite.o
common-obj-$(CONFIG_VIRTIO_NET) += net_rx_pkt.o
obj-$(CONFIG_VIRTIO_NET) += virtio-net.o
common-obj-$(call land,$(CONFIG_VIRTIO_NET),$(CONFIG_VHOST_NET)) += vhost_net.o
common-obj-$(call lnot,$(call land,$(CONFIG_VIRTIO_NET),$(CONFIG_VHOST_NET))) += vhost_net-stub.o
+256 -196
View File
File diff suppressed because it is too large Load Diff
+7 -3
View File
@@ -34,9 +34,9 @@
*/
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "net/net.h"
#include "net/tap.h"
#include "hw/hw.h"
#include "hw/pci/msi.h"
#include "hw/pci/msix.h"
#include "sysemu/runstate.h"
@@ -2816,11 +2816,15 @@ e1000e_set_psrctl(E1000ECore *core, int index, uint32_t val)
if (core->mac[RCTL] & E1000_RCTL_DTYP_MASK) {
if ((val & E1000_PSRCTL_BSIZE0_MASK) == 0) {
hw_error("e1000e: PSRCTL.BSIZE0 cannot be zero");
qemu_log_mask(LOG_GUEST_ERROR,
"e1000e: PSRCTL.BSIZE0 cannot be zero");
return;
}
if ((val & E1000_PSRCTL_BSIZE1_MASK) == 0) {
hw_error("e1000e: PSRCTL.BSIZE1 cannot be zero");
qemu_log_mask(LOG_GUEST_ERROR,
"e1000e: PSRCTL.BSIZE1 cannot be zero");
return;
}
}
+3
View File
@@ -381,6 +381,9 @@ virtio_net_announce_notify(void) ""
virtio_net_announce_timer(int round) "%d"
virtio_net_handle_announce(int round) "%d"
virtio_net_post_load_device(void)
virtio_net_rss_disable(void)
virtio_net_rss_error(const char *msg, uint32_t value) "%s, value 0x%08x"
virtio_net_rss_enable(uint32_t p1, uint16_t p2, uint8_t p3) "hashes 0x%x, table of %d, key of %d"
# tulip.c
tulip_reg_write(uint64_t addr, const char *name, int size, uint64_t val) "addr 0x%02"PRIx64" (%s) size %d value 0x%08"PRIx64
+6 -6
View File
@@ -171,9 +171,6 @@ static void tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc)
len = s->rx_frame_len;
}
if (s->rx_frame_len + len > sizeof(s->rx_frame)) {
return;
}
pci_dma_write(&s->dev, desc->buf_addr1, s->rx_frame +
(s->rx_frame_size - s->rx_frame_len), len);
s->rx_frame_len -= len;
@@ -186,9 +183,6 @@ static void tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc)
len = s->rx_frame_len;
}
if (s->rx_frame_len + len > sizeof(s->rx_frame)) {
return;
}
pci_dma_write(&s->dev, desc->buf_addr2, s->rx_frame +
(s->rx_frame_size - s->rx_frame_len), len);
s->rx_frame_len -= len;
@@ -584,6 +578,9 @@ static int tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc)
int len2 = (desc->control >> TDES1_BUF2_SIZE_SHIFT) & TDES1_BUF2_SIZE_MASK;
if (s->tx_frame_len + len1 > sizeof(s->tx_frame)) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: descriptor overflow (ofs: %u, len:%d, size:%zu)\n",
__func__, s->tx_frame_len, len1, sizeof(s->tx_frame));
return -1;
}
if (len1) {
@@ -593,6 +590,9 @@ static int tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc)
}
if (s->tx_frame_len + len2 > sizeof(s->tx_frame)) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: descriptor overflow (ofs: %u, len:%d, size:%zu)\n",
__func__, s->tx_frame_len, len2, sizeof(s->tx_frame));
return -1;
}
if (len2) {
+1 -1
View File
@@ -211,7 +211,7 @@
#define RDES0_RF BIT(11)
#define RDES0_DT_SHIFT 12
#define RDES0_DT_MASK 3
#define RDES0_LE BIT(14)
#define RDES0_DE BIT(14)
#define RDES0_ES BIT(15)
#define RDES0_FL_SHIFT 16
#define RDES0_FL_MASK 0x3fff
+349 -40
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -40,6 +40,9 @@
#define MAX_TYPE1_SCREENERS 16
#define MAX_TYPE2_SCREENERS 16
#define MAX_JUMBO_FRAME_SIZE_MASK 0x3FFF
#define MAX_FRAME_SIZE MAX_JUMBO_FRAME_SIZE_MASK
typedef struct CadenceGEMState {
/*< private >*/
SysBusDevice parent_obj;
@@ -57,6 +60,7 @@ typedef struct CadenceGEMState {
uint8_t num_type1_screeners;
uint8_t num_type2_screeners;
uint32_t revision;
uint16_t jumbo_max_len;
/* GEM registers backing store */
uint32_t regs[CADENCE_GEM_MAXREG];
@@ -80,6 +84,8 @@ typedef struct CadenceGEMState {
uint8_t can_rx_state; /* Debug only */
uint8_t tx_packet[MAX_FRAME_SIZE];
uint8_t rx_packet[MAX_FRAME_SIZE];
uint32_t rx_desc[MAX_PRIORITY_QUEUES][DESC_MAX_NUM_WORDS];
bool sar_active[4];
+16
View File
@@ -126,6 +126,20 @@ typedef struct VirtioNetRscChain {
/* Maximum packet size we can receive from tap device: header + 64k */
#define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 * KiB))
#define VIRTIO_NET_RSS_MAX_KEY_SIZE 40
#define VIRTIO_NET_RSS_MAX_TABLE_LEN 128
typedef struct VirtioNetRssData {
bool enabled;
bool redirect;
bool populate_hash;
uint32_t hash_types;
uint8_t key[VIRTIO_NET_RSS_MAX_KEY_SIZE];
uint16_t indirections_len;
uint16_t *indirections_table;
uint16_t default_queue;
} VirtioNetRssData;
typedef struct VirtIONetQueue {
VirtQueue *rx_vq;
VirtQueue *tx_vq;
@@ -199,6 +213,8 @@ struct VirtIONet {
bool failover;
DeviceListener primary_listener;
Notifier migration_state;
VirtioNetRssData rss_data;
struct NetRxPkt *rx_pkt;
};
void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
+10
View File
@@ -432,6 +432,16 @@ extern const VMStateInfo vmstate_info_qlist;
.offset = vmstate_offset_pointer(_state, _field, _type), \
}
#define VMSTATE_VARRAY_UINT16_ALLOC(_field, _state, _field_num, _version, _info, _type) {\
.name = (stringify(_field)), \
.version_id = (_version), \
.num_offset = vmstate_offset_value(_state, _field_num, uint16_t),\
.info = &(_info), \
.size = sizeof(_type), \
.flags = VMS_VARRAY_UINT16 | VMS_POINTER | VMS_ALLOC, \
.offset = vmstate_offset_pointer(_state, _field, _type), \
}
#define VMSTATE_VARRAY_UINT16_UNSAFE(_field, _state, _field_num, _version, _info, _type) {\
.name = (stringify(_field)), \
.version_id = (_version), \
+213 -76
View File
@@ -32,6 +32,9 @@
#include "migration/migration.h"
#include "util.h"
#include "block/aio-wait.h"
#include "qemu/coroutine.h"
#define TYPE_COLO_COMPARE "colo-compare"
#define COLO_COMPARE(obj) \
OBJECT_CHECK(CompareState, (obj), TYPE_COLO_COMPARE)
@@ -51,6 +54,8 @@ static NotifierList colo_compare_notifiers =
#define REGULAR_PACKET_CHECK_MS 3000
#define DEFAULT_TIME_OUT_MS 3000
static QemuMutex colo_compare_mutex;
static bool colo_compare_active;
static QemuMutex event_mtx;
static QemuCond event_complete_cond;
static int event_unhandled_count;
@@ -77,6 +82,23 @@ static int event_unhandled_count;
* |packet | |packet + |packet | |packet +
* +--------+ +--------+ +--------+ +--------+
*/
typedef struct SendCo {
Coroutine *co;
struct CompareState *s;
CharBackend *chr;
GQueue send_list;
bool notify_remote_frame;
bool done;
int ret;
} SendCo;
typedef struct SendEntry {
uint32_t size;
uint32_t vnet_hdr_len;
uint8_t *buf;
} SendEntry;
typedef struct CompareState {
Object parent;
@@ -91,6 +113,8 @@ typedef struct CompareState {
SocketReadState pri_rs;
SocketReadState sec_rs;
SocketReadState notify_rs;
SendCo out_sendco;
SendCo notify_sendco;
bool vnet_hdr;
uint32_t compare_timeout;
uint32_t expired_scan_cycle;
@@ -122,12 +146,17 @@ enum {
SECONDARY_IN,
};
static const char *colo_mode[] = {
[PRIMARY_IN] = "primary",
[SECONDARY_IN] = "secondary",
};
static int compare_chr_send(CompareState *s,
const uint8_t *buf,
uint8_t *buf,
uint32_t size,
uint32_t vnet_hdr_len,
bool notify_remote_frame);
bool notify_remote_frame,
bool zero_copy);
static bool packet_matches_str(const char *str,
const uint8_t *buf,
@@ -145,7 +174,7 @@ static void notify_remote_frame(CompareState *s)
char msg[] = "DO_CHECKPOINT";
int ret = 0;
ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true);
ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true, false);
if (ret < 0) {
error_report("Notify Xen COLO-frame failed");
}
@@ -217,6 +246,7 @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
ConnectionKey key;
Packet *pkt = NULL;
Connection *conn;
int ret;
if (mode == PRIMARY_IN) {
pkt = packet_new(s->pri_rs.buf,
@@ -245,16 +275,18 @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
}
if (mode == PRIMARY_IN) {
if (!colo_insert_packet(&conn->primary_list, pkt, &conn->pack)) {
error_report("colo compare primary queue size too big,"
"drop packet");
}
ret = colo_insert_packet(&conn->primary_list, pkt, &conn->pack);
} else {
if (!colo_insert_packet(&conn->secondary_list, pkt, &conn->sack)) {
error_report("colo compare secondary queue size too big,"
"drop packet");
}
ret = colo_insert_packet(&conn->secondary_list, pkt, &conn->sack);
}
if (!ret) {
trace_colo_compare_drop_packet(colo_mode[mode],
"queue size too big, drop packet");
packet_destroy(pkt, NULL);
pkt = NULL;
}
*con = conn;
return 0;
@@ -272,12 +304,13 @@ static void colo_release_primary_pkt(CompareState *s, Packet *pkt)
pkt->data,
pkt->size,
pkt->vnet_hdr_len,
false);
false,
true);
if (ret < 0) {
error_report("colo send primary packet failed");
}
trace_colo_compare_main("packet same and release packet");
packet_destroy(pkt, NULL);
packet_destroy_partial(pkt, NULL);
}
/*
@@ -459,10 +492,12 @@ sec:
g_queue_push_head(&conn->primary_list, ppkt);
g_queue_push_head(&conn->secondary_list, spkt);
qemu_hexdump((char *)ppkt->data, stderr,
"colo-compare ppkt", ppkt->size);
qemu_hexdump((char *)spkt->data, stderr,
"colo-compare spkt", spkt->size);
if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
qemu_hexdump((char *)ppkt->data, stderr,
"colo-compare ppkt", ppkt->size);
qemu_hexdump((char *)spkt->data, stderr,
"colo-compare spkt", spkt->size);
}
colo_compare_inconsistency_notify(s);
}
@@ -699,65 +734,115 @@ static void colo_compare_connection(void *opaque, void *user_data)
}
}
static void coroutine_fn _compare_chr_send(void *opaque)
{
SendCo *sendco = opaque;
CompareState *s = sendco->s;
int ret = 0;
while (!g_queue_is_empty(&sendco->send_list)) {
SendEntry *entry = g_queue_pop_tail(&sendco->send_list);
uint32_t len = htonl(entry->size);
ret = qemu_chr_fe_write_all(sendco->chr, (uint8_t *)&len, sizeof(len));
if (ret != sizeof(len)) {
g_free(entry->buf);
g_slice_free(SendEntry, entry);
goto err;
}
if (!sendco->notify_remote_frame && s->vnet_hdr) {
/*
* We send vnet header len make other module(like filter-redirector)
* know how to parse net packet correctly.
*/
len = htonl(entry->vnet_hdr_len);
ret = qemu_chr_fe_write_all(sendco->chr,
(uint8_t *)&len,
sizeof(len));
if (ret != sizeof(len)) {
g_free(entry->buf);
g_slice_free(SendEntry, entry);
goto err;
}
}
ret = qemu_chr_fe_write_all(sendco->chr,
(uint8_t *)entry->buf,
entry->size);
if (ret != entry->size) {
g_free(entry->buf);
g_slice_free(SendEntry, entry);
goto err;
}
g_free(entry->buf);
g_slice_free(SendEntry, entry);
}
sendco->ret = 0;
goto out;
err:
while (!g_queue_is_empty(&sendco->send_list)) {
SendEntry *entry = g_queue_pop_tail(&sendco->send_list);
g_free(entry->buf);
g_slice_free(SendEntry, entry);
}
sendco->ret = ret < 0 ? ret : -EIO;
out:
sendco->co = NULL;
sendco->done = true;
aio_wait_kick();
}
static int compare_chr_send(CompareState *s,
const uint8_t *buf,
uint8_t *buf,
uint32_t size,
uint32_t vnet_hdr_len,
bool notify_remote_frame)
bool notify_remote_frame,
bool zero_copy)
{
int ret = 0;
uint32_t len = htonl(size);
SendCo *sendco;
SendEntry *entry;
if (notify_remote_frame) {
sendco = &s->notify_sendco;
} else {
sendco = &s->out_sendco;
}
if (!size) {
return 0;
}
if (notify_remote_frame) {
ret = qemu_chr_fe_write_all(&s->chr_notify_dev,
(uint8_t *)&len,
sizeof(len));
entry = g_slice_new(SendEntry);
entry->size = size;
entry->vnet_hdr_len = vnet_hdr_len;
if (zero_copy) {
entry->buf = buf;
} else {
ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
entry->buf = g_malloc(size);
memcpy(entry->buf, buf, size);
}
g_queue_push_head(&sendco->send_list, entry);
if (ret != sizeof(len)) {
goto err;
}
if (s->vnet_hdr) {
/*
* We send vnet header len make other module(like filter-redirector)
* know how to parse net packet correctly.
*/
len = htonl(vnet_hdr_len);
if (!notify_remote_frame) {
ret = qemu_chr_fe_write_all(&s->chr_out,
(uint8_t *)&len,
sizeof(len));
}
if (ret != sizeof(len)) {
goto err;
if (sendco->done) {
sendco->co = qemu_coroutine_create(_compare_chr_send, sendco);
sendco->done = false;
qemu_coroutine_enter(sendco->co);
if (sendco->done) {
/* report early errors */
return sendco->ret;
}
}
if (notify_remote_frame) {
ret = qemu_chr_fe_write_all(&s->chr_notify_dev,
(uint8_t *)buf,
size);
} else {
ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size);
}
if (ret != size) {
goto err;
}
/* assume success */
return 0;
err:
return ret < 0 ? ret : -EIO;
}
static int compare_chr_can_read(void *opaque)
@@ -830,6 +915,12 @@ static void check_old_packet_regular(void *opaque)
void colo_notify_compares_event(void *opaque, int event, Error **errp)
{
CompareState *s;
qemu_mutex_lock(&colo_compare_mutex);
if (!colo_compare_active) {
qemu_mutex_unlock(&colo_compare_mutex);
return;
}
qemu_mutex_lock(&event_mtx);
QTAILQ_FOREACH(s, &net_compares, next) {
@@ -843,6 +934,7 @@ void colo_notify_compares_event(void *opaque, int event, Error **errp)
}
qemu_mutex_unlock(&event_mtx);
qemu_mutex_unlock(&colo_compare_mutex);
}
static void colo_compare_timer_init(CompareState *s)
@@ -890,6 +982,7 @@ static void colo_compare_handle_event(void *opaque)
static void colo_compare_iothread(CompareState *s)
{
AioContext *ctx = iothread_get_aio_context(s->iothread);
object_ref(OBJECT(s->iothread));
s->worker_context = iothread_get_g_main_context(s->iothread);
@@ -906,7 +999,7 @@ static void colo_compare_iothread(CompareState *s)
}
colo_compare_timer_init(s);
s->event_bh = qemu_bh_new(colo_compare_handle_event, s);
s->event_bh = aio_bh_new(ctx, colo_compare_handle_event, s);
}
static char *compare_get_pri_indev(Object *obj, Error **errp)
@@ -1062,6 +1155,7 @@ static void compare_pri_rs_finalize(SocketReadState *pri_rs)
pri_rs->buf,
pri_rs->packet_len,
pri_rs->vnet_hdr_len,
false,
false);
} else {
/* compare packet in the specified connection */
@@ -1092,7 +1186,7 @@ static void compare_notify_rs_finalize(SocketReadState *notify_rs)
if (packet_matches_str("COLO_USERSPACE_PROXY_INIT",
notify_rs->buf,
notify_rs->packet_len)) {
ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true);
ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true, false);
if (ret < 0) {
error_report("Notify Xen COLO-frame INIT failed");
}
@@ -1196,19 +1290,38 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
s->vnet_hdr);
}
QTAILQ_INSERT_TAIL(&net_compares, s, next);
s->out_sendco.s = s;
s->out_sendco.chr = &s->chr_out;
s->out_sendco.notify_remote_frame = false;
s->out_sendco.done = true;
g_queue_init(&s->out_sendco.send_list);
if (s->notify_dev) {
s->notify_sendco.s = s;
s->notify_sendco.chr = &s->chr_notify_dev;
s->notify_sendco.notify_remote_frame = true;
s->notify_sendco.done = true;
g_queue_init(&s->notify_sendco.send_list);
}
g_queue_init(&s->conn_list);
qemu_mutex_init(&event_mtx);
qemu_cond_init(&event_complete_cond);
s->connection_track_table = g_hash_table_new_full(connection_key_hash,
connection_key_equal,
g_free,
connection_destroy);
colo_compare_iothread(s);
qemu_mutex_lock(&colo_compare_mutex);
if (!colo_compare_active) {
qemu_mutex_init(&event_mtx);
qemu_cond_init(&event_complete_cond);
colo_compare_active = true;
}
QTAILQ_INSERT_TAIL(&net_compares, s, next);
qemu_mutex_unlock(&colo_compare_mutex);
return;
}
@@ -1224,8 +1337,9 @@ static void colo_flush_packets(void *opaque, void *user_data)
pkt->data,
pkt->size,
pkt->vnet_hdr_len,
false);
packet_destroy(pkt, NULL);
false,
true);
packet_destroy_partial(pkt, NULL);
}
while (!g_queue_is_empty(&conn->secondary_list)) {
pkt = g_queue_pop_head(&conn->secondary_list);
@@ -1276,6 +1390,20 @@ static void colo_compare_finalize(Object *obj)
CompareState *s = COLO_COMPARE(obj);
CompareState *tmp = NULL;
qemu_mutex_lock(&colo_compare_mutex);
QTAILQ_FOREACH(tmp, &net_compares, next) {
if (tmp == s) {
QTAILQ_REMOVE(&net_compares, s, next);
break;
}
}
if (QTAILQ_EMPTY(&net_compares)) {
colo_compare_active = false;
qemu_mutex_destroy(&event_mtx);
qemu_cond_destroy(&event_complete_cond);
}
qemu_mutex_unlock(&colo_compare_mutex);
qemu_chr_fe_deinit(&s->chr_pri_in, false);
qemu_chr_fe_deinit(&s->chr_sec_in, false);
qemu_chr_fe_deinit(&s->chr_out, false);
@@ -1289,17 +1417,23 @@ static void colo_compare_finalize(Object *obj)
qemu_bh_delete(s->event_bh);
QTAILQ_FOREACH(tmp, &net_compares, next) {
if (tmp == s) {
QTAILQ_REMOVE(&net_compares, s, next);
break;
}
AioContext *ctx = iothread_get_aio_context(s->iothread);
aio_context_acquire(ctx);
AIO_WAIT_WHILE(ctx, !s->out_sendco.done);
if (s->notify_dev) {
AIO_WAIT_WHILE(ctx, !s->notify_sendco.done);
}
aio_context_release(ctx);
/* Release all unhandled packets after compare thead exited */
g_queue_foreach(&s->conn_list, colo_flush_packets, s);
AIO_WAIT_WHILE(NULL, !s->out_sendco.done);
g_queue_clear(&s->conn_list);
g_queue_clear(&s->out_sendco.send_list);
if (s->notify_dev) {
g_queue_clear(&s->notify_sendco.send_list);
}
if (s->connection_track_table) {
g_hash_table_destroy(s->connection_track_table);
@@ -1309,15 +1443,18 @@ static void colo_compare_finalize(Object *obj)
object_unref(OBJECT(s->iothread));
}
qemu_mutex_destroy(&event_mtx);
qemu_cond_destroy(&event_complete_cond);
g_free(s->pri_indev);
g_free(s->sec_indev);
g_free(s->outdev);
g_free(s->notify_dev);
}
static void __attribute__((__constructor__)) colo_compare_init_globals(void)
{
colo_compare_active = false;
qemu_mutex_init(&colo_compare_mutex);
}
static const TypeInfo colo_compare_info = {
.name = TYPE_COLO_COMPARE,
.parent = TYPE_OBJECT,
+7
View File
@@ -185,6 +185,13 @@ void packet_destroy(void *opaque, void *user_data)
g_slice_free(Packet, pkt);
}
void packet_destroy_partial(void *opaque, void *user_data)
{
Packet *pkt = opaque;
g_slice_free(Packet, pkt);
}
/*
* Clear hashtable, stop this hash growing really huge
*/
+1
View File
@@ -102,5 +102,6 @@ bool connection_has_tracked(GHashTable *connection_track_table,
void connection_hashtable_reset(GHashTable *connection_track_table);
Packet *packet_new(const void *data, int size, int vnet_hdr_len);
void packet_destroy(void *opaque, void *user_data);
void packet_destroy_partial(void *opaque, void *user_data);
#endif /* NET_COLO_H */
+15 -74
View File
@@ -610,7 +610,7 @@ void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge)
qemu_notify_event();
} else if (purge) {
/* Unable to empty the queue, purge remaining packets */
qemu_net_queue_purge(nc->incoming_queue, nc);
qemu_net_queue_purge(nc->incoming_queue, nc->peer);
}
}
@@ -965,17 +965,11 @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
};
static int net_client_init1(const void *object, bool is_netdev, Error **errp)
static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp)
{
Netdev legacy = {0};
const Netdev *netdev;
const char *name;
NetClientState *peer = NULL;
if (is_netdev) {
netdev = object;
name = netdev->id;
if (netdev->type == NET_CLIENT_DRIVER_NIC ||
!net_client_init_fun[netdev->type]) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
@@ -983,62 +977,11 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
return -1;
}
} else {
const NetLegacy *net = object;
const NetLegacyOptions *opts = net->opts;
legacy.id = net->id;
netdev = &legacy;
/* missing optional values have been initialized to "all bits zero" */
name = net->has_id ? net->id : net->name;
if (net->has_name) {
warn_report("The 'name' parameter is deprecated, use 'id' instead");
}
/* Map the old options to the new flat type */
switch (opts->type) {
case NET_LEGACY_OPTIONS_TYPE_NONE:
if (netdev->type == NET_CLIENT_DRIVER_NONE) {
return 0; /* nothing to do */
case NET_LEGACY_OPTIONS_TYPE_NIC:
legacy.type = NET_CLIENT_DRIVER_NIC;
legacy.u.nic = opts->u.nic;
break;
case NET_LEGACY_OPTIONS_TYPE_USER:
legacy.type = NET_CLIENT_DRIVER_USER;
legacy.u.user = opts->u.user;
break;
case NET_LEGACY_OPTIONS_TYPE_TAP:
legacy.type = NET_CLIENT_DRIVER_TAP;
legacy.u.tap = opts->u.tap;
break;
case NET_LEGACY_OPTIONS_TYPE_L2TPV3:
legacy.type = NET_CLIENT_DRIVER_L2TPV3;
legacy.u.l2tpv3 = opts->u.l2tpv3;
break;
case NET_LEGACY_OPTIONS_TYPE_SOCKET:
legacy.type = NET_CLIENT_DRIVER_SOCKET;
legacy.u.socket = opts->u.socket;
break;
case NET_LEGACY_OPTIONS_TYPE_VDE:
legacy.type = NET_CLIENT_DRIVER_VDE;
legacy.u.vde = opts->u.vde;
break;
case NET_LEGACY_OPTIONS_TYPE_BRIDGE:
legacy.type = NET_CLIENT_DRIVER_BRIDGE;
legacy.u.bridge = opts->u.bridge;
break;
case NET_LEGACY_OPTIONS_TYPE_NETMAP:
legacy.type = NET_CLIENT_DRIVER_NETMAP;
legacy.u.netmap = opts->u.netmap;
break;
case NET_LEGACY_OPTIONS_TYPE_VHOST_USER:
legacy.type = NET_CLIENT_DRIVER_VHOST_USER;
legacy.u.vhost_user = opts->u.vhost_user;
break;
default:
abort();
}
if (!net_client_init_fun[netdev->type]) {
if (netdev->type == NET_CLIENT_DRIVER_HUBPORT ||
!net_client_init_fun[netdev->type]) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
"a net backend type (maybe it is not compiled "
"into this binary)");
@@ -1047,12 +990,12 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
/* Do not add to a hub if it's a nic with a netdev= parameter. */
if (netdev->type != NET_CLIENT_DRIVER_NIC ||
!opts->u.nic.has_netdev) {
!netdev->u.nic.has_netdev) {
peer = net_hub_add_port(0, NULL, NULL);
}
}
if (net_client_init_fun[netdev->type](netdev, name, peer, errp) < 0) {
if (net_client_init_fun[netdev->type](netdev, netdev->id, peer, errp) < 0) {
/* FIXME drop when all init functions store an Error */
if (errp && !*errp) {
error_setg(errp, QERR_DEVICE_INIT_FAILED,
@@ -1108,7 +1051,7 @@ static void show_netdevs(void)
static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
{
gchar **substrings = NULL;
void *object = NULL;
Netdev *object = NULL;
Error *err = NULL;
int ret = -1;
Visitor *v = opts_visitor_new(opts);
@@ -1151,21 +1094,19 @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
}
}
if (is_netdev) {
visit_type_Netdev(v, NULL, (Netdev **)&object, &err);
} else {
visit_type_NetLegacy(v, NULL, (NetLegacy **)&object, &err);
/* Create an ID for -net if the user did not specify one */
if (!is_netdev && !qemu_opts_id(opts)) {
static int idx;
qemu_opts_set_id(opts, g_strdup_printf("__org.qemu.net%i", idx++));
}
visit_type_Netdev(v, NULL, &object, &err);
if (!err) {
ret = net_client_init1(object, is_netdev, &err);
}
if (is_netdev) {
qapi_free_Netdev(object);
} else {
qapi_free_NetLegacy(object);
}
qapi_free_Netdev(object);
out:
error_propagate(errp, err);
+2 -1
View File
@@ -254,7 +254,8 @@ static void tap_set_vnet_hdr_len(NetClientState *nc, int len)
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
assert(len == sizeof(struct virtio_net_hdr_mrg_rxbuf) ||
len == sizeof(struct virtio_net_hdr));
len == sizeof(struct virtio_net_hdr) ||
len == sizeof(struct virtio_net_hdr_v1_hash));
tap_fd_set_vnet_hdr_len(s->fd, len);
s->host_vnet_hdr_len = len;
+1
View File
@@ -12,6 +12,7 @@ colo_proxy_main(const char *chr) ": %s"
# colo-compare.c
colo_compare_main(const char *chr) ": %s"
colo_compare_drop_packet(const char *queue, const char *chr) ": %s: %s"
colo_compare_udp_miscompare(const char *sta, int size) ": %s = %d"
colo_compare_icmp_miscompare(const char *sta, int size) ": %s = %d"
colo_compare_ip_info(int psize, const char *sta, const char *stb, int ssize, const char *stc, const char *std) "ppkt size = %d, ip_src = %s, ip_dst = %s, spkt size = %d, ip_src = %s, ip_dst = %s"
-49
View File
@@ -467,55 +467,6 @@
'netmap': 'NetdevNetmapOptions',
'vhost-user': 'NetdevVhostUserOptions' } }
##
# @NetLegacy:
#
# Captures the configuration of a network device; legacy.
#
# @id: identifier for monitor commands
#
# @name: identifier for monitor commands, ignored if @id is present
#
# @opts: device type specific properties (legacy)
#
# Since: 1.2
##
{ 'struct': 'NetLegacy',
'data': {
'*id': 'str',
'*name': 'str',
'opts': 'NetLegacyOptions' } }
##
# @NetLegacyOptionsType:
#
# Since: 1.2
##
{ 'enum': 'NetLegacyOptionsType',
'data': ['none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde',
'bridge', 'netmap', 'vhost-user'] }
##
# @NetLegacyOptions:
#
# Like Netdev, but for use only by the legacy command line options
#
# Since: 1.2
##
{ 'union': 'NetLegacyOptions',
'base': { 'type': 'NetLegacyOptionsType' },
'discriminator': 'type',
'data': {
'nic': 'NetLegacyNicOptions',
'user': 'NetdevUserOptions',
'tap': 'NetdevTapOptions',
'l2tpv3': 'NetdevL2TPv3Options',
'socket': 'NetdevSocketOptions',
'vde': 'NetdevVdeOptions',
'bridge': 'NetdevBridgeOptions',
'netmap': 'NetdevNetmapOptions',
'vhost-user': 'NetdevVhostUserOptions' } }
##
# @NetFilterDirection:
#