mirror of https://github.com/xqemu/xqemu.git
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1 iQEcBAABAgAGBQJZsfnCAAoJEO8Ells5jWIRF9kH+wTT8+958CsD9hixjGQlPClv g7jY/EyKDe/6568nRDX/TZrGOJjgqYnXyIewyzNjxMp5gptapvTjkgGjhdKU8ZJC Z9RGfYTL30WZDQHZKBdhKpR7BAwRLuzu2kDGpj4c30kQFScjfamhkOyGO8Ej1vW+ bYQkROfSb/jwhgfxHeOwIH50RBfXU6uhr41UeWuGHS9OL8NarTsa6GuPdH4pTxXa aXWZoGPuQAYd0DRuqM8FbxDuSTlaWHFZpQ55eJoRimDfc0JQyrq93si9DjZ3EenT doPF038qjPN4c0MuPLhILOHFD0IL41wol7k3WxT/LSJE7aVnnXzbjd5zbQvgUQE= =SIPv -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging # gpg: Signature made Fri 08 Sep 2017 03:00:34 BST # 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: colo-compare: Update the COLO document to add the IOThread configuration colo-compare: Use IOThread to Check old packet regularly and Process pactkets of the primary qemu-iothread: IOThread supports the GMainContext event loop net/colo-compare.c: Fix comments and scheme net/colo-compare.c: Adjust net queue pop order for performance net/colo-compare.c: Optimize unpredictable tcp options comparison e1000: Rename the SEC symbol to SEQEC net/socket: Improve -net socket error reporting net/net: Convert parse_host_port() to Error net/socket: Convert several helper functions to Error net/socket: Don't treat odd socket type as SOCK_STREAM MAINTAINERS: Update mail address for COLO Proxy net: rtl8139: do not use old_mmio accesses net/rocker: Fix the unusual macro name net/rocker: Convert to realize() net/rocker: Plug memory leak in pci_rocker_init() net/rocker: Remove the dead error handling net/filter-rewriter.c: Fix rewirter checksum bug when use virtio-net Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
74bbfe024d
|
@ -1577,7 +1577,7 @@ F: include/migration/failover.h
|
|||
F: docs/COLO-FT.txt
|
||||
|
||||
COLO Proxy
|
||||
M: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
|
||||
M: Zhang Chen <zhangckid@gmail.com>
|
||||
M: Li Zhijian <lizhijian@cn.fujitsu.com>
|
||||
S: Supported
|
||||
F: docs/colo-proxy.txt
|
||||
|
|
|
@ -170,10 +170,11 @@ Primary(ip:3.3.3.3):
|
|||
-chardev socket,id=compare0-0,host=3.3.3.3,port=9001
|
||||
-chardev socket,id=compare_out,host=3.3.3.3,port=9005,server,nowait
|
||||
-chardev socket,id=compare_out0,host=3.3.3.3,port=9005
|
||||
-object iothread,id=iothread1
|
||||
-object filter-mirror,id=m0,netdev=hn0,queue=tx,outdev=mirror0
|
||||
-object filter-redirector,netdev=hn0,id=redire0,queue=rx,indev=compare_out
|
||||
-object filter-redirector,netdev=hn0,id=redire1,queue=rx,outdev=compare0
|
||||
-object colo-compare,id=comp0,primary_in=compare0-0,secondary_in=compare1,outdev=compare_out0
|
||||
-object colo-compare,id=comp0,primary_in=compare0-0,secondary_in=compare1,outdev=compare_out0,iothread=iothread1
|
||||
|
||||
Secondary(ip:3.3.3.8):
|
||||
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
|
||||
|
|
|
@ -1127,7 +1127,7 @@ static uint32_t (*macreg_readops[])(E1000State *, int) = {
|
|||
getreg(TADV), getreg(ITR), getreg(FCRUC), getreg(IPAV),
|
||||
getreg(WUC), getreg(WUS), getreg(SCC), getreg(ECOL),
|
||||
getreg(MCC), getreg(LATECOL), getreg(COLC), getreg(DC),
|
||||
getreg(TNCRS), getreg(SEC), getreg(CEXTERR), getreg(RLEC),
|
||||
getreg(TNCRS), getreg(SEQEC), getreg(CEXTERR), getreg(RLEC),
|
||||
getreg(XONRXC), getreg(XONTXC), getreg(XOFFRXC), getreg(XOFFTXC),
|
||||
getreg(RFC), getreg(RJC), getreg(RNBC), getreg(TSCTFC),
|
||||
getreg(MGTPRC), getreg(MGTPDC), getreg(MGTPTC), getreg(GORCL),
|
||||
|
@ -1223,7 +1223,7 @@ static const uint8_t mac_reg_access[0x8000] = {
|
|||
[FFLT] = markflag(MAC), [FFMT] = markflag(MAC),
|
||||
[SCC] = markflag(MAC), [FCRUC] = markflag(MAC),
|
||||
[LATECOL] = markflag(MAC), [COLC] = markflag(MAC),
|
||||
[SEC] = markflag(MAC), [CEXTERR] = markflag(MAC),
|
||||
[SEQEC] = markflag(MAC), [CEXTERR] = markflag(MAC),
|
||||
[XONTXC] = markflag(MAC), [XOFFRXC] = markflag(MAC),
|
||||
[RJC] = markflag(MAC), [RNBC] = markflag(MAC),
|
||||
[MGTPDC] = markflag(MAC), [MGTPTC] = markflag(MAC),
|
||||
|
|
|
@ -260,7 +260,7 @@
|
|||
#define E1000_COLC 0x04028 /* Collision Count - R/clr */
|
||||
#define E1000_DC 0x04030 /* Defer Count - R/clr */
|
||||
#define E1000_TNCRS 0x04034 /* TX-No CRS - R/clr */
|
||||
#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */
|
||||
#define E1000_SEQEC 0x04038 /* Sequence Error Count - R/clr */
|
||||
#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */
|
||||
#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */
|
||||
#define E1000_XONRXC 0x04048 /* XON RX Count - R/clr */
|
||||
|
|
|
@ -2855,7 +2855,7 @@ static uint32_t (*e1000e_macreg_readops[])(E1000ECore *, int) = {
|
|||
e1000e_getreg(RDLEN0),
|
||||
e1000e_getreg(RDH1),
|
||||
e1000e_getreg(LATECOL),
|
||||
e1000e_getreg(SEC),
|
||||
e1000e_getreg(SEQEC),
|
||||
e1000e_getreg(XONTXC),
|
||||
e1000e_getreg(WUS),
|
||||
e1000e_getreg(GORCL),
|
||||
|
|
|
@ -40,7 +40,7 @@ enum {
|
|||
defreg(VFTA), defreg(VET), defreg(RDTR), defreg(RADV),
|
||||
defreg(TADV), defreg(ITR), defreg(SCC), defreg(ECOL),
|
||||
defreg(MCC), defreg(LATECOL), defreg(COLC), defreg(DC),
|
||||
defreg(TNCRS), defreg(SEC), defreg(CEXTERR), defreg(RLEC),
|
||||
defreg(TNCRS), defreg(SEQEC), defreg(CEXTERR), defreg(RLEC),
|
||||
defreg(XONRXC), defreg(XONTXC), defreg(XOFFRXC), defreg(XOFFTXC),
|
||||
defreg(FCRUC), defreg(AIT), defreg(TDFH), defreg(TDFT),
|
||||
defreg(TDFHS), defreg(TDFTS), defreg(TDFPC), defreg(WUC),
|
||||
|
|
|
@ -69,10 +69,10 @@ struct rocker {
|
|||
QLIST_ENTRY(rocker) next;
|
||||
};
|
||||
|
||||
#define ROCKER "rocker"
|
||||
#define TYPE_ROCKER "rocker"
|
||||
|
||||
#define to_rocker(obj) \
|
||||
OBJECT_CHECK(Rocker, (obj), ROCKER)
|
||||
#define ROCKER(obj) \
|
||||
OBJECT_CHECK(Rocker, (obj), TYPE_ROCKER)
|
||||
|
||||
static QLIST_HEAD(, rocker) rockers;
|
||||
|
||||
|
@ -239,10 +239,6 @@ static int tx_consume(Rocker *r, DescInfo *info)
|
|||
}
|
||||
iov[iovcnt].iov_len = frag_len;
|
||||
iov[iovcnt].iov_base = g_malloc(frag_len);
|
||||
if (!iov[iovcnt].iov_base) {
|
||||
err = -ROCKER_ENOMEM;
|
||||
goto err_no_mem;
|
||||
}
|
||||
|
||||
pci_dma_read(dev, frag_addr, iov[iovcnt].iov_base,
|
||||
iov[iovcnt].iov_len);
|
||||
|
@ -259,7 +255,6 @@ static int tx_consume(Rocker *r, DescInfo *info)
|
|||
err = fp_port_eg(r->fp_port[port], iov, iovcnt);
|
||||
|
||||
err_too_many_frags:
|
||||
err_no_mem:
|
||||
err_bad_attr:
|
||||
for (i = 0; i < ROCKER_TX_FRAGS_MAX; i++) {
|
||||
g_free(iov[i].iov_base);
|
||||
|
@ -671,10 +666,7 @@ int rx_produce(World *world, uint32_t pport,
|
|||
*/
|
||||
|
||||
data = g_malloc(data_size);
|
||||
if (!data) {
|
||||
err = -ROCKER_ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
iov_to_buf(iov, iovcnt, 0, data, data_size);
|
||||
pci_dma_write(dev, frag_addr, data, data_size);
|
||||
g_free(data);
|
||||
|
@ -719,11 +711,6 @@ static void rocker_test_dma_ctrl(Rocker *r, uint32_t val)
|
|||
|
||||
buf = g_malloc(r->test_dma_size);
|
||||
|
||||
if (!buf) {
|
||||
DPRINTF("test dma buffer alloc failed");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (val) {
|
||||
case ROCKER_TEST_DMA_CTRL_CLEAR:
|
||||
memset(buf, 0, r->test_dma_size);
|
||||
|
@ -1249,20 +1236,18 @@ rollback:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int rocker_msix_init(Rocker *r)
|
||||
static int rocker_msix_init(Rocker *r, Error **errp)
|
||||
{
|
||||
PCIDevice *dev = PCI_DEVICE(r);
|
||||
int err;
|
||||
Error *local_err = NULL;
|
||||
|
||||
err = msix_init(dev, ROCKER_MSIX_VEC_COUNT(r->fp_ports),
|
||||
&r->msix_bar,
|
||||
ROCKER_PCI_MSIX_BAR_IDX, ROCKER_PCI_MSIX_TABLE_OFFSET,
|
||||
&r->msix_bar,
|
||||
ROCKER_PCI_MSIX_BAR_IDX, ROCKER_PCI_MSIX_PBA_OFFSET,
|
||||
0, &local_err);
|
||||
0, errp);
|
||||
if (err) {
|
||||
error_report_err(local_err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -1298,9 +1283,9 @@ static World *rocker_world_type_by_name(Rocker *r, const char *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int pci_rocker_init(PCIDevice *dev)
|
||||
static void pci_rocker_realize(PCIDevice *dev, Error **errp)
|
||||
{
|
||||
Rocker *r = to_rocker(dev);
|
||||
Rocker *r = ROCKER(dev);
|
||||
const MACAddr zero = { .a = { 0, 0, 0, 0, 0, 0 } };
|
||||
const MACAddr dflt = { .a = { 0x52, 0x54, 0x00, 0x12, 0x35, 0x01 } };
|
||||
static int sw_index;
|
||||
|
@ -1310,23 +1295,15 @@ static int pci_rocker_init(PCIDevice *dev)
|
|||
|
||||
r->worlds[ROCKER_WORLD_TYPE_OF_DPA] = of_dpa_world_alloc(r);
|
||||
|
||||
for (i = 0; i < ROCKER_WORLD_TYPE_MAX; i++) {
|
||||
if (!r->worlds[i]) {
|
||||
err = -ENOMEM;
|
||||
goto err_world_alloc;
|
||||
}
|
||||
}
|
||||
|
||||
if (!r->world_name) {
|
||||
r->world_name = g_strdup(world_name(r->worlds[ROCKER_WORLD_TYPE_OF_DPA]));
|
||||
}
|
||||
|
||||
r->world_dflt = rocker_world_type_by_name(r, r->world_name);
|
||||
if (!r->world_dflt) {
|
||||
fprintf(stderr,
|
||||
"rocker: requested world \"%s\" does not exist\n",
|
||||
error_setg(errp,
|
||||
"invalid argument requested world %s does not exist",
|
||||
r->world_name);
|
||||
err = -EINVAL;
|
||||
goto err_world_type_by_name;
|
||||
}
|
||||
|
||||
|
@ -1346,7 +1323,7 @@ static int pci_rocker_init(PCIDevice *dev)
|
|||
|
||||
/* MSI-X init */
|
||||
|
||||
err = rocker_msix_init(r);
|
||||
err = rocker_msix_init(r, errp);
|
||||
if (err) {
|
||||
goto err_msix_init;
|
||||
}
|
||||
|
@ -1354,11 +1331,11 @@ static int pci_rocker_init(PCIDevice *dev)
|
|||
/* validate switch properties */
|
||||
|
||||
if (!r->name) {
|
||||
r->name = g_strdup(ROCKER);
|
||||
r->name = g_strdup(TYPE_ROCKER);
|
||||
}
|
||||
|
||||
if (rocker_find(r->name)) {
|
||||
err = -EEXIST;
|
||||
error_setg(errp, "%s already exists", r->name);
|
||||
goto err_duplicate;
|
||||
}
|
||||
|
||||
|
@ -1372,10 +1349,10 @@ static int pci_rocker_init(PCIDevice *dev)
|
|||
#define ROCKER_IFNAMSIZ 16
|
||||
#define MAX_ROCKER_NAME_LEN (ROCKER_IFNAMSIZ - 1 - 3 - 3)
|
||||
if (strlen(r->name) > MAX_ROCKER_NAME_LEN) {
|
||||
fprintf(stderr,
|
||||
"rocker: name too long; please shorten to at most %d chars\n",
|
||||
error_setg(errp,
|
||||
"name too long; please shorten to at most %d chars",
|
||||
MAX_ROCKER_NAME_LEN);
|
||||
return -EINVAL;
|
||||
goto err_name_too_long;
|
||||
}
|
||||
|
||||
if (memcmp(&r->fp_start_macaddr, &zero, sizeof(zero)) == 0) {
|
||||
|
@ -1393,9 +1370,6 @@ static int pci_rocker_init(PCIDevice *dev)
|
|||
}
|
||||
|
||||
r->rings = g_new(DescRing *, rocker_pci_ring_count(r));
|
||||
if (!r->rings) {
|
||||
goto err_rings_alloc;
|
||||
}
|
||||
|
||||
/* Rings are ordered like this:
|
||||
* - command ring
|
||||
|
@ -1407,14 +1381,9 @@ static int pci_rocker_init(PCIDevice *dev)
|
|||
* .....
|
||||
*/
|
||||
|
||||
err = -ENOMEM;
|
||||
for (i = 0; i < rocker_pci_ring_count(r); i++) {
|
||||
DescRing *ring = desc_ring_alloc(r, i);
|
||||
|
||||
if (!ring) {
|
||||
goto err_ring_alloc;
|
||||
}
|
||||
|
||||
if (i == ROCKER_RING_CMD) {
|
||||
desc_ring_set_consume(ring, cmd_consume, ROCKER_MSIX_VEC_CMD);
|
||||
} else if (i == ROCKER_RING_EVENT) {
|
||||
|
@ -1434,48 +1403,31 @@ static int pci_rocker_init(PCIDevice *dev)
|
|||
fp_port_alloc(r, r->name, &r->fp_start_macaddr,
|
||||
i, &r->fp_ports_peers[i]);
|
||||
|
||||
if (!port) {
|
||||
goto err_port_alloc;
|
||||
}
|
||||
|
||||
r->fp_port[i] = port;
|
||||
fp_port_set_world(port, r->world_dflt);
|
||||
}
|
||||
|
||||
QLIST_INSERT_HEAD(&rockers, r, next);
|
||||
|
||||
return 0;
|
||||
return;
|
||||
|
||||
err_port_alloc:
|
||||
for (--i; i >= 0; i--) {
|
||||
FpPort *port = r->fp_port[i];
|
||||
fp_port_free(port);
|
||||
}
|
||||
i = rocker_pci_ring_count(r);
|
||||
err_ring_alloc:
|
||||
for (--i; i >= 0; i--) {
|
||||
desc_ring_free(r->rings[i]);
|
||||
}
|
||||
g_free(r->rings);
|
||||
err_rings_alloc:
|
||||
err_name_too_long:
|
||||
err_duplicate:
|
||||
rocker_msix_uninit(r);
|
||||
err_msix_init:
|
||||
object_unparent(OBJECT(&r->msix_bar));
|
||||
object_unparent(OBJECT(&r->mmio));
|
||||
err_world_type_by_name:
|
||||
err_world_alloc:
|
||||
for (i = 0; i < ROCKER_WORLD_TYPE_MAX; i++) {
|
||||
if (r->worlds[i]) {
|
||||
world_free(r->worlds[i]);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static void pci_rocker_uninit(PCIDevice *dev)
|
||||
{
|
||||
Rocker *r = to_rocker(dev);
|
||||
Rocker *r = ROCKER(dev);
|
||||
int i;
|
||||
|
||||
QLIST_REMOVE(r, next);
|
||||
|
@ -1508,7 +1460,7 @@ static void pci_rocker_uninit(PCIDevice *dev)
|
|||
|
||||
static void rocker_reset(DeviceState *dev)
|
||||
{
|
||||
Rocker *r = to_rocker(dev);
|
||||
Rocker *r = ROCKER(dev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ROCKER_WORLD_TYPE_MAX; i++) {
|
||||
|
@ -1546,7 +1498,7 @@ static Property rocker_properties[] = {
|
|||
};
|
||||
|
||||
static const VMStateDescription rocker_vmsd = {
|
||||
.name = ROCKER,
|
||||
.name = TYPE_ROCKER,
|
||||
.unmigratable = 1,
|
||||
};
|
||||
|
||||
|
@ -1555,7 +1507,7 @@ static void rocker_class_init(ObjectClass *klass, void *data)
|
|||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = pci_rocker_init;
|
||||
k->realize = pci_rocker_realize;
|
||||
k->exit = pci_rocker_uninit;
|
||||
k->vendor_id = PCI_VENDOR_ID_REDHAT;
|
||||
k->device_id = PCI_DEVICE_ID_REDHAT_ROCKER;
|
||||
|
@ -1569,7 +1521,7 @@ static void rocker_class_init(ObjectClass *klass, void *data)
|
|||
}
|
||||
|
||||
static const TypeInfo rocker_info = {
|
||||
.name = ROCKER,
|
||||
.name = TYPE_ROCKER,
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(Rocker),
|
||||
.class_init = rocker_class_init,
|
||||
|
|
|
@ -65,10 +65,6 @@ char *desc_get_buf(DescInfo *info, bool read_only)
|
|||
info->buf_size = size;
|
||||
}
|
||||
|
||||
if (!info->buf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pci_dma_read(dev, le64_to_cpu(info->desc.buf_addr), info->buf, size);
|
||||
|
||||
return info->buf;
|
||||
|
@ -142,9 +138,6 @@ bool desc_ring_set_size(DescRing *ring, uint32_t size)
|
|||
ring->head = ring->tail = 0;
|
||||
|
||||
ring->info = g_renew(DescInfo, ring->info, size);
|
||||
if (!ring->info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(ring->info, 0, size * sizeof(DescInfo));
|
||||
|
||||
|
@ -345,9 +338,6 @@ DescRing *desc_ring_alloc(Rocker *r, int index)
|
|||
DescRing *ring;
|
||||
|
||||
ring = g_new0(DescRing, 1);
|
||||
if (!ring) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ring->r = r;
|
||||
ring->index = index;
|
||||
|
|
|
@ -226,10 +226,6 @@ FpPort *fp_port_alloc(Rocker *r, char *sw_name,
|
|||
{
|
||||
FpPort *port = g_new0(FpPort, 1);
|
||||
|
||||
if (!port) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
port->r = r;
|
||||
port->index = index;
|
||||
port->pport = index + 1;
|
||||
|
|
|
@ -368,9 +368,6 @@ static OfDpaFlow *of_dpa_flow_alloc(uint64_t cookie)
|
|||
int64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) / 1000;
|
||||
|
||||
flow = g_new0(OfDpaFlow, 1);
|
||||
if (!flow) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
flow->cookie = cookie;
|
||||
flow->mask.tbl_id = 0xffffffff;
|
||||
|
@ -813,10 +810,6 @@ static OfDpaGroup *of_dpa_group_alloc(uint32_t id)
|
|||
{
|
||||
OfDpaGroup *group = g_new0(OfDpaGroup, 1);
|
||||
|
||||
if (!group) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
group->id = id;
|
||||
|
||||
return group;
|
||||
|
@ -1867,9 +1860,6 @@ static int of_dpa_cmd_flow_add(OfDpa *of_dpa, uint64_t cookie,
|
|||
}
|
||||
|
||||
flow = of_dpa_flow_alloc(cookie);
|
||||
if (!flow) {
|
||||
return -ROCKER_ENOMEM;
|
||||
}
|
||||
|
||||
err = of_dpa_cmd_flow_add_mod(of_dpa, flow, flow_tlvs);
|
||||
if (err) {
|
||||
|
@ -2040,17 +2030,10 @@ static int of_dpa_cmd_add_l2_flood(OfDpa *of_dpa, OfDpaGroup *group,
|
|||
rocker_tlv_get_le16(group_tlvs[ROCKER_TLV_OF_DPA_GROUP_COUNT]);
|
||||
|
||||
tlvs = g_new0(RockerTlv *, group->l2_flood.group_count + 1);
|
||||
if (!tlvs) {
|
||||
return -ROCKER_ENOMEM;
|
||||
}
|
||||
|
||||
g_free(group->l2_flood.group_ids);
|
||||
group->l2_flood.group_ids =
|
||||
g_new0(uint32_t, group->l2_flood.group_count);
|
||||
if (!group->l2_flood.group_ids) {
|
||||
err = -ROCKER_ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
rocker_tlv_parse_nested(tlvs, group->l2_flood.group_count,
|
||||
group_tlvs[ROCKER_TLV_OF_DPA_GROUP_IDS]);
|
||||
|
@ -2157,9 +2140,6 @@ static int of_dpa_cmd_group_add(OfDpa *of_dpa, uint32_t group_id,
|
|||
}
|
||||
|
||||
group = of_dpa_group_alloc(group_id);
|
||||
if (!group) {
|
||||
return -ROCKER_ENOMEM;
|
||||
}
|
||||
|
||||
err = of_dpa_cmd_group_do(of_dpa, group_id, group, group_tlvs);
|
||||
if (err) {
|
||||
|
|
|
@ -51,13 +51,11 @@ World *world_alloc(Rocker *r, size_t sizeof_private,
|
|||
{
|
||||
World *w = g_malloc0(sizeof(World) + sizeof_private);
|
||||
|
||||
if (w) {
|
||||
w->r = r;
|
||||
w->type = type;
|
||||
w->ops = ops;
|
||||
if (w->ops->init) {
|
||||
w->ops->init(w);
|
||||
}
|
||||
w->r = r;
|
||||
w->type = type;
|
||||
w->ops = ops;
|
||||
if (w->ops->init) {
|
||||
w->ops->init(w);
|
||||
}
|
||||
|
||||
return w;
|
||||
|
|
|
@ -3132,38 +3132,6 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr)
|
|||
|
||||
/* */
|
||||
|
||||
static void rtl8139_mmio_writeb(void *opaque, hwaddr addr, uint32_t val)
|
||||
{
|
||||
rtl8139_io_writeb(opaque, addr & 0xFF, val);
|
||||
}
|
||||
|
||||
static void rtl8139_mmio_writew(void *opaque, hwaddr addr, uint32_t val)
|
||||
{
|
||||
rtl8139_io_writew(opaque, addr & 0xFF, val);
|
||||
}
|
||||
|
||||
static void rtl8139_mmio_writel(void *opaque, hwaddr addr, uint32_t val)
|
||||
{
|
||||
rtl8139_io_writel(opaque, addr & 0xFF, val);
|
||||
}
|
||||
|
||||
static uint32_t rtl8139_mmio_readb(void *opaque, hwaddr addr)
|
||||
{
|
||||
return rtl8139_io_readb(opaque, addr & 0xFF);
|
||||
}
|
||||
|
||||
static uint32_t rtl8139_mmio_readw(void *opaque, hwaddr addr)
|
||||
{
|
||||
uint32_t val = rtl8139_io_readw(opaque, addr & 0xFF);
|
||||
return val;
|
||||
}
|
||||
|
||||
static uint32_t rtl8139_mmio_readl(void *opaque, hwaddr addr)
|
||||
{
|
||||
uint32_t val = rtl8139_io_readl(opaque, addr & 0xFF);
|
||||
return val;
|
||||
}
|
||||
|
||||
static int rtl8139_post_load(void *opaque, int version_id)
|
||||
{
|
||||
RTL8139State* s = opaque;
|
||||
|
@ -3344,22 +3312,6 @@ static const MemoryRegionOps rtl8139_io_ops = {
|
|||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static const MemoryRegionOps rtl8139_mmio_ops = {
|
||||
.old_mmio = {
|
||||
.read = {
|
||||
rtl8139_mmio_readb,
|
||||
rtl8139_mmio_readw,
|
||||
rtl8139_mmio_readl,
|
||||
},
|
||||
.write = {
|
||||
rtl8139_mmio_writeb,
|
||||
rtl8139_mmio_writew,
|
||||
rtl8139_mmio_writel,
|
||||
},
|
||||
},
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static void rtl8139_timer(void *opaque)
|
||||
{
|
||||
RTL8139State *s = opaque;
|
||||
|
@ -3422,8 +3374,9 @@ static void pci_rtl8139_realize(PCIDevice *dev, Error **errp)
|
|||
|
||||
memory_region_init_io(&s->bar_io, OBJECT(s), &rtl8139_io_ops, s,
|
||||
"rtl8139", 0x100);
|
||||
memory_region_init_io(&s->bar_mem, OBJECT(s), &rtl8139_mmio_ops, s,
|
||||
"rtl8139", 0x100);
|
||||
memory_region_init_alias(&s->bar_mem, OBJECT(s), "rtl8139-mem", &s->bar_io,
|
||||
0, 0x100);
|
||||
|
||||
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->bar_io);
|
||||
pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar_mem);
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@ void socket_listen_cleanup(int fd, Error **errp);
|
|||
int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp);
|
||||
|
||||
/* Old, ipv4 only bits. Don't use for new code. */
|
||||
int parse_host_port(struct sockaddr_in *saddr, const char *str);
|
||||
int parse_host_port(struct sockaddr_in *saddr, const char *str,
|
||||
Error **errp);
|
||||
int socket_init(void);
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,6 +24,9 @@ typedef struct {
|
|||
|
||||
QemuThread thread;
|
||||
AioContext *ctx;
|
||||
GMainContext *worker_context;
|
||||
GMainLoop *main_loop;
|
||||
GOnce once;
|
||||
QemuMutex init_done_lock;
|
||||
QemuCond init_done_cond; /* is thread initialization done? */
|
||||
bool stopping;
|
||||
|
@ -41,5 +44,6 @@ typedef struct {
|
|||
char *iothread_get_id(IOThread *iothread);
|
||||
AioContext *iothread_get_aio_context(IOThread *iothread);
|
||||
void iothread_stop_all(void);
|
||||
GMainContext *iothread_get_g_main_context(IOThread *iothread);
|
||||
|
||||
#endif /* IOTHREAD_H */
|
||||
|
|
45
iothread.c
45
iothread.c
|
@ -57,6 +57,23 @@ static void *iothread_run(void *opaque)
|
|||
|
||||
while (!atomic_read(&iothread->stopping)) {
|
||||
aio_poll(iothread->ctx, true);
|
||||
|
||||
if (atomic_read(&iothread->worker_context)) {
|
||||
GMainLoop *loop;
|
||||
|
||||
g_main_context_push_thread_default(iothread->worker_context);
|
||||
iothread->main_loop =
|
||||
g_main_loop_new(iothread->worker_context, TRUE);
|
||||
loop = iothread->main_loop;
|
||||
|
||||
g_main_loop_run(iothread->main_loop);
|
||||
iothread->main_loop = NULL;
|
||||
g_main_loop_unref(loop);
|
||||
|
||||
g_main_context_pop_thread_default(iothread->worker_context);
|
||||
g_main_context_unref(iothread->worker_context);
|
||||
iothread->worker_context = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
rcu_unregister_thread();
|
||||
|
@ -73,6 +90,9 @@ static int iothread_stop(Object *object, void *opaque)
|
|||
}
|
||||
iothread->stopping = true;
|
||||
aio_notify(iothread->ctx);
|
||||
if (atomic_read(&iothread->main_loop)) {
|
||||
g_main_loop_quit(iothread->main_loop);
|
||||
}
|
||||
qemu_thread_join(&iothread->thread);
|
||||
return 0;
|
||||
}
|
||||
|
@ -125,6 +145,7 @@ static void iothread_complete(UserCreatable *obj, Error **errp)
|
|||
|
||||
qemu_mutex_init(&iothread->init_done_lock);
|
||||
qemu_cond_init(&iothread->init_done_cond);
|
||||
iothread->once = (GOnce) G_ONCE_INIT;
|
||||
|
||||
/* This assumes we are called from a thread with useful CPU affinity for us
|
||||
* to inherit.
|
||||
|
@ -309,3 +330,27 @@ void iothread_stop_all(void)
|
|||
|
||||
object_child_foreach(container, iothread_stop, NULL);
|
||||
}
|
||||
|
||||
static gpointer iothread_g_main_context_init(gpointer opaque)
|
||||
{
|
||||
AioContext *ctx;
|
||||
IOThread *iothread = opaque;
|
||||
GSource *source;
|
||||
|
||||
iothread->worker_context = g_main_context_new();
|
||||
|
||||
ctx = iothread_get_aio_context(iothread);
|
||||
source = aio_get_g_source(ctx);
|
||||
g_source_attach(source, iothread->worker_context);
|
||||
g_source_unref(source);
|
||||
|
||||
aio_notify(iothread->ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GMainContext *iothread_get_g_main_context(IOThread *iothread)
|
||||
{
|
||||
g_once(&iothread->once, iothread_g_main_context_init, iothread);
|
||||
|
||||
return iothread->worker_context;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "qemu/sockets.h"
|
||||
#include "qapi-visit.h"
|
||||
#include "net/colo.h"
|
||||
#include "sysemu/iothread.h"
|
||||
|
||||
#define TYPE_COLO_COMPARE "colo-compare"
|
||||
#define COLO_COMPARE(obj) \
|
||||
|
@ -41,27 +42,27 @@
|
|||
#define REGULAR_PACKET_CHECK_MS 3000
|
||||
|
||||
/*
|
||||
+ CompareState ++
|
||||
| |
|
||||
+---------------+ +---------------+ +---------------+
|
||||
|conn list +--->conn +--------->conn |
|
||||
+---------------+ +---------------+ +---------------+
|
||||
| | | | | |
|
||||
+---------------+ +---v----+ +---v----+ +---v----+ +---v----+
|
||||
|primary | |secondary |primary | |secondary
|
||||
|packet | |packet + |packet | |packet +
|
||||
+--------+ +--------+ +--------+ +--------+
|
||||
| | | |
|
||||
+---v----+ +---v----+ +---v----+ +---v----+
|
||||
|primary | |secondary |primary | |secondary
|
||||
|packet | |packet + |packet | |packet +
|
||||
+--------+ +--------+ +--------+ +--------+
|
||||
| | | |
|
||||
+---v----+ +---v----+ +---v----+ +---v----+
|
||||
|primary | |secondary |primary | |secondary
|
||||
|packet | |packet + |packet | |packet +
|
||||
+--------+ +--------+ +--------+ +--------+
|
||||
*/
|
||||
* + CompareState ++
|
||||
* | |
|
||||
* +---------------+ +---------------+ +---------------+
|
||||
* | conn list + - > conn + ------- > conn + -- > ......
|
||||
* +---------------+ +---------------+ +---------------+
|
||||
* | | | | | |
|
||||
* +---------------+ +---v----+ +---v----+ +---v----+ +---v----+
|
||||
* |primary | |secondary |primary | |secondary
|
||||
* |packet | |packet + |packet | |packet +
|
||||
* +--------+ +--------+ +--------+ +--------+
|
||||
* | | | |
|
||||
* +---v----+ +---v----+ +---v----+ +---v----+
|
||||
* |primary | |secondary |primary | |secondary
|
||||
* |packet | |packet + |packet | |packet +
|
||||
* +--------+ +--------+ +--------+ +--------+
|
||||
* | | | |
|
||||
* +---v----+ +---v----+ +---v----+ +---v----+
|
||||
* |primary | |secondary |primary | |secondary
|
||||
* |packet | |packet + |packet | |packet +
|
||||
* +--------+ +--------+ +--------+ +--------+
|
||||
*/
|
||||
typedef struct CompareState {
|
||||
Object parent;
|
||||
|
||||
|
@ -75,18 +76,17 @@ typedef struct CompareState {
|
|||
SocketReadState sec_rs;
|
||||
bool vnet_hdr;
|
||||
|
||||
/* connection list: the connections belonged to this NIC could be found
|
||||
* in this list.
|
||||
* element type: Connection
|
||||
/*
|
||||
* Record the connection that through the NIC
|
||||
* Element type: Connection
|
||||
*/
|
||||
GQueue conn_list;
|
||||
/* hashtable to save connection */
|
||||
/* Record the connection without repetition */
|
||||
GHashTable *connection_track_table;
|
||||
/* compare thread, a thread for each NIC */
|
||||
QemuThread thread;
|
||||
|
||||
IOThread *iothread;
|
||||
GMainContext *worker_context;
|
||||
GMainLoop *compare_loop;
|
||||
QEMUTimer *packet_check_timer;
|
||||
} CompareState;
|
||||
|
||||
typedef struct CompareClass {
|
||||
|
@ -186,7 +186,10 @@ static int packet_enqueue(CompareState *s, int mode)
|
|||
* return: 0 means packet same
|
||||
* > 0 || < 0 means packet different
|
||||
*/
|
||||
static int colo_packet_compare_common(Packet *ppkt, Packet *spkt, int offset)
|
||||
static int colo_packet_compare_common(Packet *ppkt,
|
||||
Packet *spkt,
|
||||
int poffset,
|
||||
int soffset)
|
||||
{
|
||||
if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
|
||||
char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20];
|
||||
|
@ -201,12 +204,13 @@ static int colo_packet_compare_common(Packet *ppkt, Packet *spkt, int offset)
|
|||
sec_ip_src, sec_ip_dst);
|
||||
}
|
||||
|
||||
offset = ppkt->vnet_hdr_len + offset;
|
||||
poffset = ppkt->vnet_hdr_len + poffset;
|
||||
soffset = ppkt->vnet_hdr_len + soffset;
|
||||
|
||||
if (ppkt->size == spkt->size) {
|
||||
return memcmp(ppkt->data + offset,
|
||||
spkt->data + offset,
|
||||
spkt->size - offset);
|
||||
if (ppkt->size - poffset == spkt->size - soffset) {
|
||||
return memcmp(ppkt->data + poffset,
|
||||
spkt->data + soffset,
|
||||
spkt->size - soffset);
|
||||
} else {
|
||||
trace_colo_compare_main("Net packet size are not the same");
|
||||
return -1;
|
||||
|
@ -263,13 +267,22 @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
|
|||
* so we just need skip this field.
|
||||
*/
|
||||
if (ptcp->th_off > 5) {
|
||||
ptrdiff_t tcp_offset;
|
||||
ptrdiff_t ptcp_offset, stcp_offset;
|
||||
|
||||
tcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data
|
||||
+ (ptcp->th_off * 4) - ppkt->vnet_hdr_len;
|
||||
res = colo_packet_compare_common(ppkt, spkt, tcp_offset);
|
||||
ptcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data
|
||||
+ (ptcp->th_off * 4) - ppkt->vnet_hdr_len;
|
||||
stcp_offset = spkt->transport_header - (uint8_t *)spkt->data
|
||||
+ (stcp->th_off * 4) - spkt->vnet_hdr_len;
|
||||
|
||||
/*
|
||||
* When network is busy, some tcp options(like sack) will unpredictable
|
||||
* occur in primary side or secondary side. it will make packet size
|
||||
* not same, but the two packet's payload is identical. colo just
|
||||
* care about packet payload, so we skip the option field.
|
||||
*/
|
||||
res = colo_packet_compare_common(ppkt, spkt, ptcp_offset, stcp_offset);
|
||||
} else if (ptcp->th_sum == stcp->th_sum) {
|
||||
res = colo_packet_compare_common(ppkt, spkt, ETH_HLEN);
|
||||
res = colo_packet_compare_common(ppkt, spkt, ETH_HLEN, ETH_HLEN);
|
||||
} else {
|
||||
res = -1;
|
||||
}
|
||||
|
@ -330,6 +343,7 @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
|
|||
* the ip payload here.
|
||||
*/
|
||||
ret = colo_packet_compare_common(ppkt, spkt,
|
||||
network_header_length + ETH_HLEN,
|
||||
network_header_length + ETH_HLEN);
|
||||
|
||||
if (ret) {
|
||||
|
@ -367,6 +381,7 @@ static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
|
|||
* the ip payload here.
|
||||
*/
|
||||
if (colo_packet_compare_common(ppkt, spkt,
|
||||
network_header_length + ETH_HLEN,
|
||||
network_header_length + ETH_HLEN)) {
|
||||
trace_colo_compare_icmp_miscompare("primary pkt size",
|
||||
ppkt->size);
|
||||
|
@ -404,7 +419,7 @@ static int colo_packet_compare_other(Packet *spkt, Packet *ppkt)
|
|||
sec_ip_src, sec_ip_dst);
|
||||
}
|
||||
|
||||
return colo_packet_compare_common(ppkt, spkt, 0);
|
||||
return colo_packet_compare_common(ppkt, spkt, 0, 0);
|
||||
}
|
||||
|
||||
static int colo_old_packet_check_one(Packet *pkt, int64_t *check_time)
|
||||
|
@ -430,8 +445,11 @@ static int colo_old_packet_check_one_conn(Connection *conn,
|
|||
(GCompareFunc)colo_old_packet_check_one);
|
||||
|
||||
if (result) {
|
||||
/* do checkpoint will flush old packet */
|
||||
/* TODO: colo_notify_checkpoint();*/
|
||||
/* Do checkpoint will flush old packet */
|
||||
/*
|
||||
* TODO: Notify colo frame to do checkpoint.
|
||||
* colo_compare_inconsistent_notify();
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -469,7 +487,7 @@ static void colo_compare_connection(void *opaque, void *user_data)
|
|||
|
||||
while (!g_queue_is_empty(&conn->primary_list) &&
|
||||
!g_queue_is_empty(&conn->secondary_list)) {
|
||||
pkt = g_queue_pop_tail(&conn->primary_list);
|
||||
pkt = g_queue_pop_head(&conn->primary_list);
|
||||
switch (conn->ip_proto) {
|
||||
case IPPROTO_TCP:
|
||||
result = g_queue_find_custom(&conn->secondary_list,
|
||||
|
@ -507,7 +525,7 @@ static void colo_compare_connection(void *opaque, void *user_data)
|
|||
* until next comparison.
|
||||
*/
|
||||
trace_colo_compare_main("packet different");
|
||||
g_queue_push_tail(&conn->primary_list, pkt);
|
||||
g_queue_push_head(&conn->primary_list, pkt);
|
||||
/* TODO: colo_notify_checkpoint();*/
|
||||
break;
|
||||
}
|
||||
|
@ -597,22 +615,40 @@ static void compare_sec_chr_in(void *opaque, const uint8_t *buf, int size)
|
|||
* Check old packet regularly so it can watch for any packets
|
||||
* that the secondary hasn't produced equivalents of.
|
||||
*/
|
||||
static gboolean check_old_packet_regular(void *opaque)
|
||||
static void check_old_packet_regular(void *opaque)
|
||||
{
|
||||
CompareState *s = opaque;
|
||||
|
||||
/* if have old packet we will notify checkpoint */
|
||||
colo_old_packet_check(s);
|
||||
|
||||
return TRUE;
|
||||
timer_mod(s->packet_check_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
|
||||
REGULAR_PACKET_CHECK_MS);
|
||||
}
|
||||
|
||||
static void *colo_compare_thread(void *opaque)
|
||||
static void colo_compare_timer_init(CompareState *s)
|
||||
{
|
||||
CompareState *s = opaque;
|
||||
GSource *timeout_source;
|
||||
AioContext *ctx = iothread_get_aio_context(s->iothread);
|
||||
|
||||
s->worker_context = g_main_context_new();
|
||||
s->packet_check_timer = aio_timer_new(ctx, QEMU_CLOCK_VIRTUAL,
|
||||
SCALE_MS, check_old_packet_regular,
|
||||
s);
|
||||
timer_mod(s->packet_check_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
|
||||
REGULAR_PACKET_CHECK_MS);
|
||||
}
|
||||
|
||||
static void colo_compare_timer_del(CompareState *s)
|
||||
{
|
||||
if (s->packet_check_timer) {
|
||||
timer_del(s->packet_check_timer);
|
||||
timer_free(s->packet_check_timer);
|
||||
s->packet_check_timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void colo_compare_iothread(CompareState *s)
|
||||
{
|
||||
object_ref(OBJECT(s->iothread));
|
||||
s->worker_context = iothread_get_g_main_context(s->iothread);
|
||||
|
||||
qemu_chr_fe_set_handlers(&s->chr_pri_in, compare_chr_can_read,
|
||||
compare_pri_chr_in, NULL, NULL,
|
||||
|
@ -621,20 +657,7 @@ static void *colo_compare_thread(void *opaque)
|
|||
compare_sec_chr_in, NULL, NULL,
|
||||
s, s->worker_context, true);
|
||||
|
||||
s->compare_loop = g_main_loop_new(s->worker_context, FALSE);
|
||||
|
||||
/* To kick any packets that the secondary doesn't match */
|
||||
timeout_source = g_timeout_source_new(REGULAR_PACKET_CHECK_MS);
|
||||
g_source_set_callback(timeout_source,
|
||||
(GSourceFunc)check_old_packet_regular, s, NULL);
|
||||
g_source_attach(timeout_source, s->worker_context);
|
||||
|
||||
g_main_loop_run(s->compare_loop);
|
||||
|
||||
g_source_unref(timeout_source);
|
||||
g_main_loop_unref(s->compare_loop);
|
||||
g_main_context_unref(s->worker_context);
|
||||
return NULL;
|
||||
colo_compare_timer_init(s);
|
||||
}
|
||||
|
||||
static char *compare_get_pri_indev(Object *obj, Error **errp)
|
||||
|
@ -759,12 +782,10 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
|
|||
{
|
||||
CompareState *s = COLO_COMPARE(uc);
|
||||
Chardev *chr;
|
||||
char thread_name[64];
|
||||
static int compare_id;
|
||||
|
||||
if (!s->pri_indev || !s->sec_indev || !s->outdev) {
|
||||
if (!s->pri_indev || !s->sec_indev || !s->outdev || !s->iothread) {
|
||||
error_setg(errp, "colo compare needs 'primary_in' ,"
|
||||
"'secondary_in','outdev' property set");
|
||||
"'secondary_in','outdev','iothread' property set");
|
||||
return;
|
||||
} else if (!strcmp(s->pri_indev, s->outdev) ||
|
||||
!strcmp(s->sec_indev, s->outdev) ||
|
||||
|
@ -799,12 +820,7 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
|
|||
g_free,
|
||||
connection_destroy);
|
||||
|
||||
sprintf(thread_name, "colo-compare %d", compare_id);
|
||||
qemu_thread_create(&s->thread, thread_name,
|
||||
colo_compare_thread, s,
|
||||
QEMU_THREAD_JOINABLE);
|
||||
compare_id++;
|
||||
|
||||
colo_compare_iothread(s);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -848,6 +864,10 @@ static void colo_compare_init(Object *obj)
|
|||
object_property_add_str(obj, "outdev",
|
||||
compare_get_outdev, compare_set_outdev,
|
||||
NULL);
|
||||
object_property_add_link(obj, "iothread", TYPE_IOTHREAD,
|
||||
(Object **)&s->iothread,
|
||||
object_property_allow_set_link,
|
||||
OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
|
||||
|
||||
s->vnet_hdr = false;
|
||||
object_property_add_bool(obj, "vnet_hdr_support", compare_get_vnet_hdr,
|
||||
|
@ -861,16 +881,21 @@ static void colo_compare_finalize(Object *obj)
|
|||
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);
|
||||
|
||||
g_main_loop_quit(s->compare_loop);
|
||||
qemu_thread_join(&s->thread);
|
||||
|
||||
if (s->iothread) {
|
||||
colo_compare_timer_del(s);
|
||||
}
|
||||
/* Release all unhandled packets after compare thead exited */
|
||||
g_queue_foreach(&s->conn_list, colo_flush_packets, s);
|
||||
|
||||
g_queue_clear(&s->conn_list);
|
||||
|
||||
g_hash_table_destroy(s->connection_track_table);
|
||||
if (s->connection_track_table) {
|
||||
g_hash_table_destroy(s->connection_track_table);
|
||||
}
|
||||
|
||||
if (s->iothread) {
|
||||
object_unref(OBJECT(s->iothread));
|
||||
}
|
||||
g_free(s->pri_indev);
|
||||
g_free(s->sec_indev);
|
||||
g_free(s->outdev);
|
||||
|
|
|
@ -99,7 +99,8 @@ static int handle_primary_tcp_pkt(NetFilterState *nf,
|
|||
/* handle packets to the secondary from the primary */
|
||||
tcp_pkt->th_ack = htonl(ntohl(tcp_pkt->th_ack) + conn->offset);
|
||||
|
||||
net_checksum_calculate((uint8_t *)pkt->data, pkt->size);
|
||||
net_checksum_calculate((uint8_t *)pkt->data + pkt->vnet_hdr_len,
|
||||
pkt->size - pkt->vnet_hdr_len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,7 +139,8 @@ static int handle_secondary_tcp_pkt(NetFilterState *nf,
|
|||
/* handle packets to the primary from the secondary*/
|
||||
tcp_pkt->th_seq = htonl(ntohl(tcp_pkt->th_seq) - conn->offset);
|
||||
|
||||
net_checksum_calculate((uint8_t *)pkt->data, pkt->size);
|
||||
net_checksum_calculate((uint8_t *)pkt->data + pkt->vnet_hdr_len,
|
||||
pkt->size - pkt->vnet_hdr_len);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
22
net/net.c
22
net/net.c
|
@ -100,7 +100,8 @@ static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int parse_host_port(struct sockaddr_in *saddr, const char *str)
|
||||
int parse_host_port(struct sockaddr_in *saddr, const char *str,
|
||||
Error **errp)
|
||||
{
|
||||
char buf[512];
|
||||
struct hostent *he;
|
||||
|
@ -108,24 +109,35 @@ int parse_host_port(struct sockaddr_in *saddr, const char *str)
|
|||
int port;
|
||||
|
||||
p = str;
|
||||
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
|
||||
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
|
||||
error_setg(errp, "host address '%s' doesn't contain ':' "
|
||||
"separating host from port", str);
|
||||
return -1;
|
||||
}
|
||||
saddr->sin_family = AF_INET;
|
||||
if (buf[0] == '\0') {
|
||||
saddr->sin_addr.s_addr = 0;
|
||||
} else {
|
||||
if (qemu_isdigit(buf[0])) {
|
||||
if (!inet_aton(buf, &saddr->sin_addr))
|
||||
if (!inet_aton(buf, &saddr->sin_addr)) {
|
||||
error_setg(errp, "host address '%s' is not a valid "
|
||||
"IPv4 address", buf);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if ((he = gethostbyname(buf)) == NULL)
|
||||
he = gethostbyname(buf);
|
||||
if (he == NULL) {
|
||||
error_setg(errp, "can't resolve host address '%s'", buf);
|
||||
return - 1;
|
||||
}
|
||||
saddr->sin_addr = *(struct in_addr *)he->h_addr;
|
||||
}
|
||||
}
|
||||
port = strtol(p, (char **)&r, 0);
|
||||
if (r == p)
|
||||
if (r == p) {
|
||||
error_setg(errp, "port number '%s' is invalid", p);
|
||||
return -1;
|
||||
}
|
||||
saddr->sin_port = htons(port);
|
||||
return 0;
|
||||
}
|
||||
|
|
156
net/socket.c
156
net/socket.c
|
@ -209,7 +209,9 @@ static void net_socket_send_dgram(void *opaque)
|
|||
}
|
||||
}
|
||||
|
||||
static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr *localaddr)
|
||||
static int net_socket_mcast_create(struct sockaddr_in *mcastaddr,
|
||||
struct in_addr *localaddr,
|
||||
Error **errp)
|
||||
{
|
||||
struct ip_mreq imr;
|
||||
int fd;
|
||||
|
@ -221,16 +223,16 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
|
|||
#endif
|
||||
|
||||
if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) {
|
||||
fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) "
|
||||
"does not contain a multicast address\n",
|
||||
inet_ntoa(mcastaddr->sin_addr),
|
||||
(int)ntohl(mcastaddr->sin_addr.s_addr));
|
||||
error_setg(errp, "specified mcastaddr %s (0x%08x) "
|
||||
"does not contain a multicast address",
|
||||
inet_ntoa(mcastaddr->sin_addr),
|
||||
(int)ntohl(mcastaddr->sin_addr.s_addr));
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
perror("socket(PF_INET, SOCK_DGRAM)");
|
||||
error_setg_errno(errp, errno, "can't create datagram socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -242,13 +244,15 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
|
|||
val = 1;
|
||||
ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
|
||||
if (ret < 0) {
|
||||
perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
|
||||
error_setg_errno(errp, errno,
|
||||
"can't set socket option SO_REUSEADDR");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr));
|
||||
if (ret < 0) {
|
||||
perror("bind");
|
||||
error_setg_errno(errp, errno, "can't bind ip=%s to socket",
|
||||
inet_ntoa(mcastaddr->sin_addr));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -263,7 +267,9 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
|
|||
ret = qemu_setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||
&imr, sizeof(struct ip_mreq));
|
||||
if (ret < 0) {
|
||||
perror("setsockopt(IP_ADD_MEMBERSHIP)");
|
||||
error_setg_errno(errp, errno,
|
||||
"can't add socket to multicast group %s",
|
||||
inet_ntoa(imr.imr_multiaddr));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -272,7 +278,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
|
|||
ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
|
||||
&loop, sizeof(loop));
|
||||
if (ret < 0) {
|
||||
perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
|
||||
error_setg_errno(errp, errno,
|
||||
"can't force multicast message to loopback");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -281,7 +288,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
|
|||
ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
|
||||
localaddr, sizeof(*localaddr));
|
||||
if (ret < 0) {
|
||||
perror("setsockopt(IP_MULTICAST_IF)");
|
||||
error_setg_errno(errp, errno,
|
||||
"can't set the default network send interface");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -321,7 +329,8 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
|
|||
const char *model,
|
||||
const char *name,
|
||||
int fd, int is_connected,
|
||||
const char *mcast)
|
||||
const char *mcast,
|
||||
Error **errp)
|
||||
{
|
||||
struct sockaddr_in saddr;
|
||||
int newfd;
|
||||
|
@ -334,22 +343,17 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
|
|||
*/
|
||||
|
||||
if (is_connected && mcast != NULL) {
|
||||
if (parse_host_port(&saddr, mcast) < 0) {
|
||||
fprintf(stderr,
|
||||
"qemu: error: init_dgram: fd=%d failed parse_host_port()\n",
|
||||
fd);
|
||||
if (parse_host_port(&saddr, mcast, errp) < 0) {
|
||||
goto err;
|
||||
}
|
||||
/* must be bound */
|
||||
if (saddr.sin_addr.s_addr == 0) {
|
||||
fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, "
|
||||
"cannot setup multicast dst addr\n", fd);
|
||||
error_setg(errp, "can't setup multicast destination address");
|
||||
goto err;
|
||||
}
|
||||
/* clone dgram socket */
|
||||
newfd = net_socket_mcast_create(&saddr, NULL);
|
||||
newfd = net_socket_mcast_create(&saddr, NULL, errp);
|
||||
if (newfd < 0) {
|
||||
/* error already reported by net_socket_mcast_create() */
|
||||
goto err;
|
||||
}
|
||||
/* clone newfd to fd, close newfd */
|
||||
|
@ -431,26 +435,27 @@ static NetSocketState *net_socket_fd_init_stream(NetClientState *peer,
|
|||
|
||||
static NetSocketState *net_socket_fd_init(NetClientState *peer,
|
||||
const char *model, const char *name,
|
||||
int fd, int is_connected, const char *mc)
|
||||
int fd, int is_connected,
|
||||
const char *mc, Error **errp)
|
||||
{
|
||||
int so_type = -1, optlen=sizeof(so_type);
|
||||
|
||||
if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type,
|
||||
(socklen_t *)&optlen)< 0) {
|
||||
fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n",
|
||||
fd);
|
||||
error_setg(errp, "can't get socket option SO_TYPE");
|
||||
closesocket(fd);
|
||||
return NULL;
|
||||
}
|
||||
switch(so_type) {
|
||||
case SOCK_DGRAM:
|
||||
return net_socket_fd_init_dgram(peer, model, name, fd, is_connected, mc);
|
||||
return net_socket_fd_init_dgram(peer, model, name, fd, is_connected,
|
||||
mc, errp);
|
||||
case SOCK_STREAM:
|
||||
return net_socket_fd_init_stream(peer, model, name, fd, is_connected);
|
||||
default:
|
||||
/* who knows ... this could be a eg. a pty, do warn and continue as stream */
|
||||
fprintf(stderr, "qemu: warning: socket type=%d for fd=%d is not SOCK_DGRAM or SOCK_STREAM\n", so_type, fd);
|
||||
return net_socket_fd_init_stream(peer, model, name, fd, is_connected);
|
||||
error_report("socket type=%d for fd=%d must be either"
|
||||
" SOCK_DGRAM or SOCK_STREAM", so_type, fd);
|
||||
closesocket(fd);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -484,19 +489,21 @@ static void net_socket_accept(void *opaque)
|
|||
static int net_socket_listen_init(NetClientState *peer,
|
||||
const char *model,
|
||||
const char *name,
|
||||
const char *host_str)
|
||||
const char *host_str,
|
||||
Error **errp)
|
||||
{
|
||||
NetClientState *nc;
|
||||
NetSocketState *s;
|
||||
struct sockaddr_in saddr;
|
||||
int fd, ret;
|
||||
|
||||
if (parse_host_port(&saddr, host_str) < 0)
|
||||
if (parse_host_port(&saddr, host_str, errp) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (fd < 0) {
|
||||
perror("socket");
|
||||
error_setg_errno(errp, errno, "can't create stream socket");
|
||||
return -1;
|
||||
}
|
||||
qemu_set_nonblock(fd);
|
||||
|
@ -505,13 +512,14 @@ static int net_socket_listen_init(NetClientState *peer,
|
|||
|
||||
ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
|
||||
if (ret < 0) {
|
||||
perror("bind");
|
||||
error_setg_errno(errp, errno, "can't bind ip=%s to socket",
|
||||
inet_ntoa(saddr.sin_addr));
|
||||
closesocket(fd);
|
||||
return -1;
|
||||
}
|
||||
ret = listen(fd, 0);
|
||||
if (ret < 0) {
|
||||
perror("listen");
|
||||
error_setg_errno(errp, errno, "can't listen on socket");
|
||||
closesocket(fd);
|
||||
return -1;
|
||||
}
|
||||
|
@ -530,18 +538,20 @@ static int net_socket_listen_init(NetClientState *peer,
|
|||
static int net_socket_connect_init(NetClientState *peer,
|
||||
const char *model,
|
||||
const char *name,
|
||||
const char *host_str)
|
||||
const char *host_str,
|
||||
Error **errp)
|
||||
{
|
||||
NetSocketState *s;
|
||||
int fd, connected, ret;
|
||||
struct sockaddr_in saddr;
|
||||
|
||||
if (parse_host_port(&saddr, host_str) < 0)
|
||||
if (parse_host_port(&saddr, host_str, errp) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (fd < 0) {
|
||||
perror("socket");
|
||||
error_setg_errno(errp, errno, "can't create stream socket");
|
||||
return -1;
|
||||
}
|
||||
qemu_set_nonblock(fd);
|
||||
|
@ -557,7 +567,7 @@ static int net_socket_connect_init(NetClientState *peer,
|
|||
errno == EINVAL) {
|
||||
break;
|
||||
} else {
|
||||
perror("connect");
|
||||
error_setg_errno(errp, errno, "can't connect socket");
|
||||
closesocket(fd);
|
||||
return -1;
|
||||
}
|
||||
|
@ -566,9 +576,11 @@ static int net_socket_connect_init(NetClientState *peer,
|
|||
break;
|
||||
}
|
||||
}
|
||||
s = net_socket_fd_init(peer, model, name, fd, connected, NULL);
|
||||
if (!s)
|
||||
s = net_socket_fd_init(peer, model, name, fd, connected, NULL, errp);
|
||||
if (!s) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(s->nc.info_str, sizeof(s->nc.info_str),
|
||||
"socket: connect to %s:%d",
|
||||
inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
|
||||
|
@ -579,31 +591,38 @@ static int net_socket_mcast_init(NetClientState *peer,
|
|||
const char *model,
|
||||
const char *name,
|
||||
const char *host_str,
|
||||
const char *localaddr_str)
|
||||
const char *localaddr_str,
|
||||
Error **errp)
|
||||
{
|
||||
NetSocketState *s;
|
||||
int fd;
|
||||
struct sockaddr_in saddr;
|
||||
struct in_addr localaddr, *param_localaddr;
|
||||
|
||||
if (parse_host_port(&saddr, host_str) < 0)
|
||||
if (parse_host_port(&saddr, host_str, errp) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (localaddr_str != NULL) {
|
||||
if (inet_aton(localaddr_str, &localaddr) == 0)
|
||||
if (inet_aton(localaddr_str, &localaddr) == 0) {
|
||||
error_setg(errp, "localaddr '%s' is not a valid IPv4 address",
|
||||
localaddr_str);
|
||||
return -1;
|
||||
}
|
||||
param_localaddr = &localaddr;
|
||||
} else {
|
||||
param_localaddr = NULL;
|
||||
}
|
||||
|
||||
fd = net_socket_mcast_create(&saddr, param_localaddr);
|
||||
if (fd < 0)
|
||||
fd = net_socket_mcast_create(&saddr, param_localaddr, errp);
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = net_socket_fd_init(peer, model, name, fd, 0, NULL);
|
||||
if (!s)
|
||||
s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp);
|
||||
if (!s) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->dgram_dst = saddr;
|
||||
|
||||
|
@ -618,40 +637,44 @@ static int net_socket_udp_init(NetClientState *peer,
|
|||
const char *model,
|
||||
const char *name,
|
||||
const char *rhost,
|
||||
const char *lhost)
|
||||
const char *lhost,
|
||||
Error **errp)
|
||||
{
|
||||
NetSocketState *s;
|
||||
int fd, ret;
|
||||
struct sockaddr_in laddr, raddr;
|
||||
|
||||
if (parse_host_port(&laddr, lhost) < 0) {
|
||||
if (parse_host_port(&laddr, lhost, errp) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (parse_host_port(&raddr, rhost) < 0) {
|
||||
if (parse_host_port(&raddr, rhost, errp) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
perror("socket(PF_INET, SOCK_DGRAM)");
|
||||
error_setg_errno(errp, errno, "can't create datagram socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = socket_set_fast_reuse(fd);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, errno,
|
||||
"can't set socket option SO_REUSEADDR");
|
||||
closesocket(fd);
|
||||
return -1;
|
||||
}
|
||||
ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
|
||||
if (ret < 0) {
|
||||
perror("bind");
|
||||
error_setg_errno(errp, errno, "can't bind ip=%s to socket",
|
||||
inet_ntoa(laddr.sin_addr));
|
||||
closesocket(fd);
|
||||
return -1;
|
||||
}
|
||||
qemu_set_nonblock(fd);
|
||||
|
||||
s = net_socket_fd_init(peer, model, name, fd, 0, NULL);
|
||||
s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp);
|
||||
if (!s) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -667,8 +690,6 @@ static int net_socket_udp_init(NetClientState *peer,
|
|||
int net_init_socket(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp)
|
||||
{
|
||||
/* FIXME error_setg(errp, ...) on failure */
|
||||
Error *err = NULL;
|
||||
const NetdevSocketOptions *sock;
|
||||
|
||||
assert(netdev->type == NET_CLIENT_DRIVER_SOCKET);
|
||||
|
@ -676,41 +697,42 @@ int net_init_socket(const Netdev *netdev, const char *name,
|
|||
|
||||
if (sock->has_listen + sock->has_connect + sock->has_mcast +
|
||||
sock->has_udp > 1) {
|
||||
error_report("exactly one of listen=, connect=, mcast= or udp="
|
||||
" is required");
|
||||
error_setg(errp, "exactly one of listen=, connect=, mcast= or udp="
|
||||
" is required");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sock->has_localaddr && !sock->has_mcast && !sock->has_udp) {
|
||||
error_report("localaddr= is only valid with mcast= or udp=");
|
||||
error_setg(errp, "localaddr= is only valid with mcast= or udp=");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sock->has_fd) {
|
||||
int fd;
|
||||
|
||||
fd = monitor_fd_param(cur_mon, sock->fd, &err);
|
||||
fd = monitor_fd_param(cur_mon, sock->fd, errp);
|
||||
if (fd == -1) {
|
||||
error_report_err(err);
|
||||
return -1;
|
||||
}
|
||||
qemu_set_nonblock(fd);
|
||||
if (!net_socket_fd_init(peer, "socket", name, fd, 1, sock->mcast)) {
|
||||
if (!net_socket_fd_init(peer, "socket", name, fd, 1, sock->mcast,
|
||||
errp)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sock->has_listen) {
|
||||
if (net_socket_listen_init(peer, "socket", name, sock->listen) == -1) {
|
||||
if (net_socket_listen_init(peer, "socket", name, sock->listen, errp)
|
||||
< 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sock->has_connect) {
|
||||
if (net_socket_connect_init(peer, "socket", name, sock->connect) ==
|
||||
-1) {
|
||||
if (net_socket_connect_init(peer, "socket", name, sock->connect, errp)
|
||||
< 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -720,7 +742,7 @@ int net_init_socket(const Netdev *netdev, const char *name,
|
|||
/* if sock->localaddr is missing, it has been initialized to "all bits
|
||||
* zero" */
|
||||
if (net_socket_mcast_init(peer, "socket", name, sock->mcast,
|
||||
sock->localaddr) == -1) {
|
||||
sock->localaddr, errp) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -728,11 +750,11 @@ int net_init_socket(const Netdev *netdev, const char *name,
|
|||
|
||||
assert(sock->has_udp);
|
||||
if (!sock->has_localaddr) {
|
||||
error_report("localaddr= is mandatory with udp=");
|
||||
error_setg(errp, "localaddr= is mandatory with udp=");
|
||||
return -1;
|
||||
}
|
||||
if (net_socket_udp_init(peer, "socket", name, sock->udp, sock->localaddr) ==
|
||||
-1) {
|
||||
if (net_socket_udp_init(peer, "socket", name, sock->udp, sock->localaddr,
|
||||
errp) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue