colo-compare: introduce colo compare initialization
This a COLO net ascii figure:
Primary qemu Secondary qemu
+--------------------------------------------------------------+ +----------------------------------------------------------------+
| +----------------------------------------------------------+ | | +-----------------------------------------------------------+ |
| | | | | | | |
| | guest | | | | guest | |
| | | | | | | |
| +-------^--------------------------+-----------------------+ | | +---------------------+--------+----------------------------+ |
| | | | | ^ | |
| | | | | | | |
| | +------------------------------------------------------+ | | | |
|netfilter| | | | | | netfilter | | |
| +----------+ +----------------------------+ | | | +-----------------------------------------------------------+ |
| | | | | | out | | | | | | filter excute order | |
| | | | +-----------------------------+ | | | | | | +-------------------> | |
| | | | | | | | | | | | | | TCP | |
| | +-----+--+-+ +-----v----+ +-----v----+ |pri +----+----+sec| | | | +------------+ +---+----+---v+rewriter++ +------------+ | |
| | | | | | | | |in | |in | | | | | | | | | | | | |
| | | filter | | filter | | filter +------> colo <------+ +--------> filter +--> adjust | adjust +--> filter | | |
| | | mirror | |redirector| |redirector| | | compare | | | | | | redirector | | ack | seq | | redirector | | |
| | | | | | | | | | | | | | | | | | | | | | | |
| | +----^-----+ +----+-----+ +----------+ | +---------+ | | | | +------------+ +--------+--------------+ +---+--------+ | |
| | | tx | rx rx | | | | | tx all | rx | |
| | | | | | | | +-----------------------------------------------------------+ |
| | | +--------------+ | | | | | |
| | | filter excute order | | | | | | |
| | | +----------------> | | | +--------------------------------------------------------+ |
| +-----------------------------------------+ | | |
| | | | | |
+--------------------------------------------------------------+ +----------------------------------------------------------------+
|guest receive | guest send
| |
+--------+----------------------------v------------------------+
| | NOTE: filter direction is rx/tx/all
| tap | rx:receive packets sent to the netdev
| | tx:receive packets sent by the netdev
+--------------------------------------------------------------+
In COLO-compare, we do packet comparing job.
Packets coming from the primary char indev will be sent to outdev.
Packets coming from the secondary char dev will be dropped after comparing.
colo-comapre need two input chardev and one output chardev:
primary_in=chardev1-id (source: primary send packet)
secondary_in=chardev2-id (source: secondary send packet)
outdev=chardev3-id
usage:
primary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait
-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait
-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait
-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 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
secondary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
-device e1000,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=red0,host=3.3.3.3,port=9003
-chardev socket,id=red1,host=3.3.3.3,port=9004
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2016-09-27 05:22:26 +03:00
|
|
|
/*
|
|
|
|
* COarse-grain LOck-stepping Virtual Machines for Non-stop Service (COLO)
|
|
|
|
* (a.k.a. Fault Tolerance or Continuous Replication)
|
|
|
|
*
|
|
|
|
* Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
|
|
|
|
* Copyright (c) 2016 FUJITSU LIMITED
|
|
|
|
* Copyright (c) 2016 Intel Corporation
|
|
|
|
*
|
|
|
|
* Author: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
|
|
|
|
*
|
|
|
|
* 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"
|
2016-09-27 05:22:27 +03:00
|
|
|
#include "trace.h"
|
colo-compare: introduce colo compare initialization
This a COLO net ascii figure:
Primary qemu Secondary qemu
+--------------------------------------------------------------+ +----------------------------------------------------------------+
| +----------------------------------------------------------+ | | +-----------------------------------------------------------+ |
| | | | | | | |
| | guest | | | | guest | |
| | | | | | | |
| +-------^--------------------------+-----------------------+ | | +---------------------+--------+----------------------------+ |
| | | | | ^ | |
| | | | | | | |
| | +------------------------------------------------------+ | | | |
|netfilter| | | | | | netfilter | | |
| +----------+ +----------------------------+ | | | +-----------------------------------------------------------+ |
| | | | | | out | | | | | | filter excute order | |
| | | | +-----------------------------+ | | | | | | +-------------------> | |
| | | | | | | | | | | | | | TCP | |
| | +-----+--+-+ +-----v----+ +-----v----+ |pri +----+----+sec| | | | +------------+ +---+----+---v+rewriter++ +------------+ | |
| | | | | | | | |in | |in | | | | | | | | | | | | |
| | | filter | | filter | | filter +------> colo <------+ +--------> filter +--> adjust | adjust +--> filter | | |
| | | mirror | |redirector| |redirector| | | compare | | | | | | redirector | | ack | seq | | redirector | | |
| | | | | | | | | | | | | | | | | | | | | | | |
| | +----^-----+ +----+-----+ +----------+ | +---------+ | | | | +------------+ +--------+--------------+ +---+--------+ | |
| | | tx | rx rx | | | | | tx all | rx | |
| | | | | | | | +-----------------------------------------------------------+ |
| | | +--------------+ | | | | | |
| | | filter excute order | | | | | | |
| | | +----------------> | | | +--------------------------------------------------------+ |
| +-----------------------------------------+ | | |
| | | | | |
+--------------------------------------------------------------+ +----------------------------------------------------------------+
|guest receive | guest send
| |
+--------+----------------------------v------------------------+
| | NOTE: filter direction is rx/tx/all
| tap | rx:receive packets sent to the netdev
| | tx:receive packets sent by the netdev
+--------------------------------------------------------------+
In COLO-compare, we do packet comparing job.
Packets coming from the primary char indev will be sent to outdev.
Packets coming from the secondary char dev will be dropped after comparing.
colo-comapre need two input chardev and one output chardev:
primary_in=chardev1-id (source: primary send packet)
secondary_in=chardev2-id (source: secondary send packet)
outdev=chardev3-id
usage:
primary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait
-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait
-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait
-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 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
secondary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
-device e1000,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=red0,host=3.3.3.3,port=9003
-chardev socket,id=red1,host=3.3.3.3,port=9004
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2016-09-27 05:22:26 +03:00
|
|
|
#include "qemu-common.h"
|
|
|
|
#include "qapi/qmp/qerror.h"
|
|
|
|
#include "qapi/error.h"
|
|
|
|
#include "net/net.h"
|
2016-09-27 05:22:31 +03:00
|
|
|
#include "net/eth.h"
|
colo-compare: introduce colo compare initialization
This a COLO net ascii figure:
Primary qemu Secondary qemu
+--------------------------------------------------------------+ +----------------------------------------------------------------+
| +----------------------------------------------------------+ | | +-----------------------------------------------------------+ |
| | | | | | | |
| | guest | | | | guest | |
| | | | | | | |
| +-------^--------------------------+-----------------------+ | | +---------------------+--------+----------------------------+ |
| | | | | ^ | |
| | | | | | | |
| | +------------------------------------------------------+ | | | |
|netfilter| | | | | | netfilter | | |
| +----------+ +----------------------------+ | | | +-----------------------------------------------------------+ |
| | | | | | out | | | | | | filter excute order | |
| | | | +-----------------------------+ | | | | | | +-------------------> | |
| | | | | | | | | | | | | | TCP | |
| | +-----+--+-+ +-----v----+ +-----v----+ |pri +----+----+sec| | | | +------------+ +---+----+---v+rewriter++ +------------+ | |
| | | | | | | | |in | |in | | | | | | | | | | | | |
| | | filter | | filter | | filter +------> colo <------+ +--------> filter +--> adjust | adjust +--> filter | | |
| | | mirror | |redirector| |redirector| | | compare | | | | | | redirector | | ack | seq | | redirector | | |
| | | | | | | | | | | | | | | | | | | | | | | |
| | +----^-----+ +----+-----+ +----------+ | +---------+ | | | | +------------+ +--------+--------------+ +---+--------+ | |
| | | tx | rx rx | | | | | tx all | rx | |
| | | | | | | | +-----------------------------------------------------------+ |
| | | +--------------+ | | | | | |
| | | filter excute order | | | | | | |
| | | +----------------> | | | +--------------------------------------------------------+ |
| +-----------------------------------------+ | | |
| | | | | |
+--------------------------------------------------------------+ +----------------------------------------------------------------+
|guest receive | guest send
| |
+--------+----------------------------v------------------------+
| | NOTE: filter direction is rx/tx/all
| tap | rx:receive packets sent to the netdev
| | tx:receive packets sent by the netdev
+--------------------------------------------------------------+
In COLO-compare, we do packet comparing job.
Packets coming from the primary char indev will be sent to outdev.
Packets coming from the secondary char dev will be dropped after comparing.
colo-comapre need two input chardev and one output chardev:
primary_in=chardev1-id (source: primary send packet)
secondary_in=chardev2-id (source: secondary send packet)
outdev=chardev3-id
usage:
primary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait
-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait
-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait
-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 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
secondary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
-device e1000,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=red0,host=3.3.3.3,port=9003
-chardev socket,id=red1,host=3.3.3.3,port=9004
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2016-09-27 05:22:26 +03:00
|
|
|
#include "qom/object_interfaces.h"
|
|
|
|
#include "qemu/iov.h"
|
|
|
|
#include "qom/object.h"
|
|
|
|
#include "qemu/typedefs.h"
|
|
|
|
#include "net/queue.h"
|
|
|
|
#include "sysemu/char.h"
|
|
|
|
#include "qemu/sockets.h"
|
|
|
|
#include "qapi-visit.h"
|
2016-09-27 05:22:27 +03:00
|
|
|
#include "net/colo.h"
|
colo-compare: introduce colo compare initialization
This a COLO net ascii figure:
Primary qemu Secondary qemu
+--------------------------------------------------------------+ +----------------------------------------------------------------+
| +----------------------------------------------------------+ | | +-----------------------------------------------------------+ |
| | | | | | | |
| | guest | | | | guest | |
| | | | | | | |
| +-------^--------------------------+-----------------------+ | | +---------------------+--------+----------------------------+ |
| | | | | ^ | |
| | | | | | | |
| | +------------------------------------------------------+ | | | |
|netfilter| | | | | | netfilter | | |
| +----------+ +----------------------------+ | | | +-----------------------------------------------------------+ |
| | | | | | out | | | | | | filter excute order | |
| | | | +-----------------------------+ | | | | | | +-------------------> | |
| | | | | | | | | | | | | | TCP | |
| | +-----+--+-+ +-----v----+ +-----v----+ |pri +----+----+sec| | | | +------------+ +---+----+---v+rewriter++ +------------+ | |
| | | | | | | | |in | |in | | | | | | | | | | | | |
| | | filter | | filter | | filter +------> colo <------+ +--------> filter +--> adjust | adjust +--> filter | | |
| | | mirror | |redirector| |redirector| | | compare | | | | | | redirector | | ack | seq | | redirector | | |
| | | | | | | | | | | | | | | | | | | | | | | |
| | +----^-----+ +----+-----+ +----------+ | +---------+ | | | | +------------+ +--------+--------------+ +---+--------+ | |
| | | tx | rx rx | | | | | tx all | rx | |
| | | | | | | | +-----------------------------------------------------------+ |
| | | +--------------+ | | | | | |
| | | filter excute order | | | | | | |
| | | +----------------> | | | +--------------------------------------------------------+ |
| +-----------------------------------------+ | | |
| | | | | |
+--------------------------------------------------------------+ +----------------------------------------------------------------+
|guest receive | guest send
| |
+--------+----------------------------v------------------------+
| | NOTE: filter direction is rx/tx/all
| tap | rx:receive packets sent to the netdev
| | tx:receive packets sent by the netdev
+--------------------------------------------------------------+
In COLO-compare, we do packet comparing job.
Packets coming from the primary char indev will be sent to outdev.
Packets coming from the secondary char dev will be dropped after comparing.
colo-comapre need two input chardev and one output chardev:
primary_in=chardev1-id (source: primary send packet)
secondary_in=chardev2-id (source: secondary send packet)
outdev=chardev3-id
usage:
primary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait
-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait
-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait
-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 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
secondary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
-device e1000,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=red0,host=3.3.3.3,port=9003
-chardev socket,id=red1,host=3.3.3.3,port=9004
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2016-09-27 05:22:26 +03:00
|
|
|
|
|
|
|
#define TYPE_COLO_COMPARE "colo-compare"
|
|
|
|
#define COLO_COMPARE(obj) \
|
|
|
|
OBJECT_CHECK(CompareState, (obj), TYPE_COLO_COMPARE)
|
|
|
|
|
2016-09-27 05:22:30 +03:00
|
|
|
#define COMPARE_READ_LEN_MAX NET_BUFSIZE
|
2016-09-27 05:22:29 +03:00
|
|
|
#define MAX_QUEUE_SIZE 1024
|
|
|
|
|
2016-09-27 05:22:30 +03:00
|
|
|
/* TODO: Should be configurable */
|
|
|
|
#define REGULAR_PACKET_CHECK_MS 3000
|
|
|
|
|
2016-09-27 05:22:27 +03:00
|
|
|
/*
|
|
|
|
+ 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 +
|
|
|
|
+--------+ +--------+ +--------+ +--------+
|
|
|
|
*/
|
colo-compare: introduce colo compare initialization
This a COLO net ascii figure:
Primary qemu Secondary qemu
+--------------------------------------------------------------+ +----------------------------------------------------------------+
| +----------------------------------------------------------+ | | +-----------------------------------------------------------+ |
| | | | | | | |
| | guest | | | | guest | |
| | | | | | | |
| +-------^--------------------------+-----------------------+ | | +---------------------+--------+----------------------------+ |
| | | | | ^ | |
| | | | | | | |
| | +------------------------------------------------------+ | | | |
|netfilter| | | | | | netfilter | | |
| +----------+ +----------------------------+ | | | +-----------------------------------------------------------+ |
| | | | | | out | | | | | | filter excute order | |
| | | | +-----------------------------+ | | | | | | +-------------------> | |
| | | | | | | | | | | | | | TCP | |
| | +-----+--+-+ +-----v----+ +-----v----+ |pri +----+----+sec| | | | +------------+ +---+----+---v+rewriter++ +------------+ | |
| | | | | | | | |in | |in | | | | | | | | | | | | |
| | | filter | | filter | | filter +------> colo <------+ +--------> filter +--> adjust | adjust +--> filter | | |
| | | mirror | |redirector| |redirector| | | compare | | | | | | redirector | | ack | seq | | redirector | | |
| | | | | | | | | | | | | | | | | | | | | | | |
| | +----^-----+ +----+-----+ +----------+ | +---------+ | | | | +------------+ +--------+--------------+ +---+--------+ | |
| | | tx | rx rx | | | | | tx all | rx | |
| | | | | | | | +-----------------------------------------------------------+ |
| | | +--------------+ | | | | | |
| | | filter excute order | | | | | | |
| | | +----------------> | | | +--------------------------------------------------------+ |
| +-----------------------------------------+ | | |
| | | | | |
+--------------------------------------------------------------+ +----------------------------------------------------------------+
|guest receive | guest send
| |
+--------+----------------------------v------------------------+
| | NOTE: filter direction is rx/tx/all
| tap | rx:receive packets sent to the netdev
| | tx:receive packets sent by the netdev
+--------------------------------------------------------------+
In COLO-compare, we do packet comparing job.
Packets coming from the primary char indev will be sent to outdev.
Packets coming from the secondary char dev will be dropped after comparing.
colo-comapre need two input chardev and one output chardev:
primary_in=chardev1-id (source: primary send packet)
secondary_in=chardev2-id (source: secondary send packet)
outdev=chardev3-id
usage:
primary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait
-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait
-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait
-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 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
secondary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
-device e1000,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=red0,host=3.3.3.3,port=9003
-chardev socket,id=red1,host=3.3.3.3,port=9004
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2016-09-27 05:22:26 +03:00
|
|
|
typedef struct CompareState {
|
|
|
|
Object parent;
|
|
|
|
|
|
|
|
char *pri_indev;
|
|
|
|
char *sec_indev;
|
|
|
|
char *outdev;
|
|
|
|
CharDriverState *chr_pri_in;
|
|
|
|
CharDriverState *chr_sec_in;
|
|
|
|
CharDriverState *chr_out;
|
|
|
|
SocketReadState pri_rs;
|
|
|
|
SocketReadState sec_rs;
|
2016-09-27 05:22:27 +03:00
|
|
|
|
2016-09-27 05:22:29 +03:00
|
|
|
/* connection list: the connections belonged to this NIC could be found
|
|
|
|
* in this list.
|
|
|
|
* element type: Connection
|
|
|
|
*/
|
|
|
|
GQueue conn_list;
|
2016-09-27 05:22:27 +03:00
|
|
|
/* hashtable to save connection */
|
|
|
|
GHashTable *connection_track_table;
|
2016-09-27 05:22:30 +03:00
|
|
|
/* compare thread, a thread for each NIC */
|
|
|
|
QemuThread thread;
|
|
|
|
/* Timer used on the primary to find packets that are never matched */
|
|
|
|
QEMUTimer *timer;
|
|
|
|
QemuMutex timer_check_lock;
|
colo-compare: introduce colo compare initialization
This a COLO net ascii figure:
Primary qemu Secondary qemu
+--------------------------------------------------------------+ +----------------------------------------------------------------+
| +----------------------------------------------------------+ | | +-----------------------------------------------------------+ |
| | | | | | | |
| | guest | | | | guest | |
| | | | | | | |
| +-------^--------------------------+-----------------------+ | | +---------------------+--------+----------------------------+ |
| | | | | ^ | |
| | | | | | | |
| | +------------------------------------------------------+ | | | |
|netfilter| | | | | | netfilter | | |
| +----------+ +----------------------------+ | | | +-----------------------------------------------------------+ |
| | | | | | out | | | | | | filter excute order | |
| | | | +-----------------------------+ | | | | | | +-------------------> | |
| | | | | | | | | | | | | | TCP | |
| | +-----+--+-+ +-----v----+ +-----v----+ |pri +----+----+sec| | | | +------------+ +---+----+---v+rewriter++ +------------+ | |
| | | | | | | | |in | |in | | | | | | | | | | | | |
| | | filter | | filter | | filter +------> colo <------+ +--------> filter +--> adjust | adjust +--> filter | | |
| | | mirror | |redirector| |redirector| | | compare | | | | | | redirector | | ack | seq | | redirector | | |
| | | | | | | | | | | | | | | | | | | | | | | |
| | +----^-----+ +----+-----+ +----------+ | +---------+ | | | | +------------+ +--------+--------------+ +---+--------+ | |
| | | tx | rx rx | | | | | tx all | rx | |
| | | | | | | | +-----------------------------------------------------------+ |
| | | +--------------+ | | | | | |
| | | filter excute order | | | | | | |
| | | +----------------> | | | +--------------------------------------------------------+ |
| +-----------------------------------------+ | | |
| | | | | |
+--------------------------------------------------------------+ +----------------------------------------------------------------+
|guest receive | guest send
| |
+--------+----------------------------v------------------------+
| | NOTE: filter direction is rx/tx/all
| tap | rx:receive packets sent to the netdev
| | tx:receive packets sent by the netdev
+--------------------------------------------------------------+
In COLO-compare, we do packet comparing job.
Packets coming from the primary char indev will be sent to outdev.
Packets coming from the secondary char dev will be dropped after comparing.
colo-comapre need two input chardev and one output chardev:
primary_in=chardev1-id (source: primary send packet)
secondary_in=chardev2-id (source: secondary send packet)
outdev=chardev3-id
usage:
primary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait
-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait
-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait
-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 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
secondary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
-device e1000,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=red0,host=3.3.3.3,port=9003
-chardev socket,id=red1,host=3.3.3.3,port=9004
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2016-09-27 05:22:26 +03:00
|
|
|
} CompareState;
|
|
|
|
|
|
|
|
typedef struct CompareClass {
|
|
|
|
ObjectClass parent_class;
|
|
|
|
} CompareClass;
|
|
|
|
|
|
|
|
typedef struct CompareChardevProps {
|
|
|
|
bool is_socket;
|
|
|
|
} CompareChardevProps;
|
|
|
|
|
2016-09-27 05:22:27 +03:00
|
|
|
enum {
|
|
|
|
PRIMARY_IN = 0,
|
|
|
|
SECONDARY_IN,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int compare_chr_send(CharDriverState *out,
|
|
|
|
const uint8_t *buf,
|
|
|
|
uint32_t size);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return 0 on success, if return -1 means the pkt
|
|
|
|
* is unsupported(arp and ipv6) and will be sent later
|
|
|
|
*/
|
|
|
|
static int packet_enqueue(CompareState *s, int mode)
|
|
|
|
{
|
2016-09-27 05:22:29 +03:00
|
|
|
ConnectionKey key;
|
2016-09-27 05:22:27 +03:00
|
|
|
Packet *pkt = NULL;
|
2016-09-27 05:22:29 +03:00
|
|
|
Connection *conn;
|
2016-09-27 05:22:27 +03:00
|
|
|
|
|
|
|
if (mode == PRIMARY_IN) {
|
|
|
|
pkt = packet_new(s->pri_rs.buf, s->pri_rs.packet_len);
|
|
|
|
} else {
|
|
|
|
pkt = packet_new(s->sec_rs.buf, s->sec_rs.packet_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parse_packet_early(pkt)) {
|
|
|
|
packet_destroy(pkt, NULL);
|
|
|
|
pkt = NULL;
|
|
|
|
return -1;
|
|
|
|
}
|
2016-09-27 05:22:29 +03:00
|
|
|
fill_connection_key(pkt, &key);
|
2016-09-27 05:22:27 +03:00
|
|
|
|
2016-09-27 05:22:29 +03:00
|
|
|
conn = connection_get(s->connection_track_table,
|
|
|
|
&key,
|
|
|
|
&s->conn_list);
|
2016-09-27 05:22:27 +03:00
|
|
|
|
2016-09-27 05:22:29 +03:00
|
|
|
if (!conn->processing) {
|
|
|
|
g_queue_push_tail(&s->conn_list, conn);
|
|
|
|
conn->processing = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mode == PRIMARY_IN) {
|
|
|
|
if (g_queue_get_length(&conn->primary_list) <=
|
|
|
|
MAX_QUEUE_SIZE) {
|
|
|
|
g_queue_push_tail(&conn->primary_list, pkt);
|
|
|
|
} else {
|
|
|
|
error_report("colo compare primary queue size too big,"
|
|
|
|
"drop packet");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (g_queue_get_length(&conn->secondary_list) <=
|
|
|
|
MAX_QUEUE_SIZE) {
|
|
|
|
g_queue_push_tail(&conn->secondary_list, pkt);
|
|
|
|
} else {
|
|
|
|
error_report("colo compare secondary queue size too big,"
|
|
|
|
"drop packet");
|
|
|
|
}
|
|
|
|
}
|
2016-09-27 05:22:27 +03:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-27 05:22:30 +03:00
|
|
|
/*
|
|
|
|
* The IP packets sent by primary and secondary
|
|
|
|
* will be compared in here
|
|
|
|
* TODO support ip fragment, Out-Of-Order
|
|
|
|
* return: 0 means packet same
|
|
|
|
* > 0 || < 0 means packet different
|
|
|
|
*/
|
|
|
|
static int colo_packet_compare(Packet *ppkt, Packet *spkt)
|
|
|
|
{
|
|
|
|
trace_colo_compare_ip_info(ppkt->size, inet_ntoa(ppkt->ip->ip_src),
|
|
|
|
inet_ntoa(ppkt->ip->ip_dst), spkt->size,
|
|
|
|
inet_ntoa(spkt->ip->ip_src),
|
|
|
|
inet_ntoa(spkt->ip->ip_dst));
|
|
|
|
|
|
|
|
if (ppkt->size == spkt->size) {
|
|
|
|
return memcmp(ppkt->data, spkt->data, spkt->size);
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-27 05:22:31 +03:00
|
|
|
/*
|
|
|
|
* Called from the compare thread on the primary
|
|
|
|
* for compare tcp packet
|
|
|
|
* compare_tcp copied from Dr. David Alan Gilbert's branch
|
|
|
|
*/
|
|
|
|
static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
|
2016-09-27 05:22:30 +03:00
|
|
|
{
|
2016-09-27 05:22:31 +03:00
|
|
|
struct tcphdr *ptcp, *stcp;
|
|
|
|
int res;
|
|
|
|
char *sdebug, *ddebug;
|
|
|
|
|
|
|
|
trace_colo_compare_main("compare tcp");
|
|
|
|
if (ppkt->size != spkt->size) {
|
|
|
|
if (trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) {
|
|
|
|
trace_colo_compare_main("pkt size not same");
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptcp = (struct tcphdr *)ppkt->transport_header;
|
|
|
|
stcp = (struct tcphdr *)spkt->transport_header;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The 'identification' field in the IP header is *very* random
|
|
|
|
* it almost never matches. Fudge this by ignoring differences in
|
|
|
|
* unfragmented packets; they'll normally sort themselves out if different
|
|
|
|
* anyway, and it should recover at the TCP level.
|
|
|
|
* An alternative would be to get both the primary and secondary to rewrite
|
|
|
|
* somehow; but that would need some sync traffic to sync the state
|
|
|
|
*/
|
|
|
|
if (ntohs(ppkt->ip->ip_off) & IP_DF) {
|
|
|
|
spkt->ip->ip_id = ppkt->ip->ip_id;
|
|
|
|
/* and the sum will be different if the IDs were different */
|
|
|
|
spkt->ip->ip_sum = ppkt->ip->ip_sum;
|
|
|
|
}
|
|
|
|
|
|
|
|
res = memcmp(ppkt->data + ETH_HLEN, spkt->data + ETH_HLEN,
|
|
|
|
(spkt->size - ETH_HLEN));
|
|
|
|
|
|
|
|
if (res != 0 && trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) {
|
|
|
|
sdebug = strdup(inet_ntoa(ppkt->ip->ip_src));
|
|
|
|
ddebug = strdup(inet_ntoa(ppkt->ip->ip_dst));
|
|
|
|
fprintf(stderr, "%s: src/dst: %s/%s p: seq/ack=%u/%u"
|
|
|
|
" s: seq/ack=%u/%u res=%d flags=%x/%x\n",
|
|
|
|
__func__, sdebug, ddebug,
|
|
|
|
(unsigned int)ntohl(ptcp->th_seq),
|
|
|
|
(unsigned int)ntohl(ptcp->th_ack),
|
|
|
|
(unsigned int)ntohl(stcp->th_seq),
|
|
|
|
(unsigned int)ntohl(stcp->th_ack),
|
|
|
|
res, ptcp->th_flags, stcp->th_flags);
|
|
|
|
|
|
|
|
fprintf(stderr, "Primary len = %d\n", ppkt->size);
|
|
|
|
qemu_hexdump((char *)ppkt->data, stderr, "colo-compare", ppkt->size);
|
|
|
|
fprintf(stderr, "Secondary len = %d\n", spkt->size);
|
|
|
|
qemu_hexdump((char *)spkt->data, stderr, "colo-compare", spkt->size);
|
|
|
|
|
|
|
|
g_free(sdebug);
|
|
|
|
g_free(ddebug);
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Called from the compare thread on the primary
|
|
|
|
* for compare udp packet
|
|
|
|
*/
|
|
|
|
static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
trace_colo_compare_main("compare udp");
|
|
|
|
ret = colo_packet_compare(ppkt, spkt);
|
|
|
|
|
|
|
|
if (ret) {
|
|
|
|
trace_colo_compare_udp_miscompare("primary pkt size", ppkt->size);
|
|
|
|
qemu_hexdump((char *)ppkt->data, stderr, "colo-compare", ppkt->size);
|
|
|
|
trace_colo_compare_udp_miscompare("Secondary pkt size", spkt->size);
|
|
|
|
qemu_hexdump((char *)spkt->data, stderr, "colo-compare", spkt->size);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Called from the compare thread on the primary
|
|
|
|
* for compare icmp packet
|
|
|
|
*/
|
|
|
|
static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
|
|
|
|
{
|
|
|
|
int network_length;
|
|
|
|
|
|
|
|
trace_colo_compare_main("compare icmp");
|
|
|
|
network_length = ppkt->ip->ip_hl * 4;
|
|
|
|
if (ppkt->size != spkt->size ||
|
|
|
|
ppkt->size < network_length + ETH_HLEN) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (colo_packet_compare(ppkt, spkt)) {
|
|
|
|
trace_colo_compare_icmp_miscompare("primary pkt size",
|
|
|
|
ppkt->size);
|
|
|
|
qemu_hexdump((char *)ppkt->data, stderr, "colo-compare",
|
|
|
|
ppkt->size);
|
|
|
|
trace_colo_compare_icmp_miscompare("Secondary pkt size",
|
|
|
|
spkt->size);
|
|
|
|
qemu_hexdump((char *)spkt->data, stderr, "colo-compare",
|
|
|
|
spkt->size);
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Called from the compare thread on the primary
|
|
|
|
* for compare other packet
|
|
|
|
*/
|
|
|
|
static int colo_packet_compare_other(Packet *spkt, Packet *ppkt)
|
|
|
|
{
|
|
|
|
trace_colo_compare_main("compare other");
|
|
|
|
trace_colo_compare_ip_info(ppkt->size, inet_ntoa(ppkt->ip->ip_src),
|
|
|
|
inet_ntoa(ppkt->ip->ip_dst), spkt->size,
|
|
|
|
inet_ntoa(spkt->ip->ip_src),
|
|
|
|
inet_ntoa(spkt->ip->ip_dst));
|
2016-09-27 05:22:30 +03:00
|
|
|
return colo_packet_compare(ppkt, spkt);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int colo_old_packet_check_one(Packet *pkt, int64_t *check_time)
|
|
|
|
{
|
|
|
|
int64_t now = qemu_clock_get_ms(QEMU_CLOCK_HOST);
|
|
|
|
|
|
|
|
if ((now - pkt->creation_ms) > (*check_time)) {
|
|
|
|
trace_colo_old_packet_check_found(pkt->creation_ms);
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void colo_old_packet_check_one_conn(void *opaque,
|
|
|
|
void *user_data)
|
|
|
|
{
|
|
|
|
Connection *conn = opaque;
|
|
|
|
GList *result = NULL;
|
|
|
|
int64_t check_time = REGULAR_PACKET_CHECK_MS;
|
|
|
|
|
|
|
|
result = g_queue_find_custom(&conn->primary_list,
|
|
|
|
&check_time,
|
|
|
|
(GCompareFunc)colo_old_packet_check_one);
|
|
|
|
|
|
|
|
if (result) {
|
|
|
|
/* do checkpoint will flush old packet */
|
|
|
|
/* TODO: colo_notify_checkpoint();*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Look for old packets that the secondary hasn't matched,
|
|
|
|
* if we have some then we have to checkpoint to wake
|
|
|
|
* the secondary up.
|
|
|
|
*/
|
|
|
|
static void colo_old_packet_check(void *opaque)
|
|
|
|
{
|
|
|
|
CompareState *s = opaque;
|
|
|
|
|
|
|
|
g_queue_foreach(&s->conn_list, colo_old_packet_check_one_conn, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Called from the compare thread on the primary
|
|
|
|
* for compare connection
|
|
|
|
*/
|
|
|
|
static void colo_compare_connection(void *opaque, void *user_data)
|
|
|
|
{
|
|
|
|
CompareState *s = user_data;
|
|
|
|
Connection *conn = opaque;
|
|
|
|
Packet *pkt = NULL;
|
|
|
|
GList *result = NULL;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
while (!g_queue_is_empty(&conn->primary_list) &&
|
|
|
|
!g_queue_is_empty(&conn->secondary_list)) {
|
|
|
|
qemu_mutex_lock(&s->timer_check_lock);
|
|
|
|
pkt = g_queue_pop_tail(&conn->primary_list);
|
|
|
|
qemu_mutex_unlock(&s->timer_check_lock);
|
2016-09-27 05:22:31 +03:00
|
|
|
switch (conn->ip_proto) {
|
|
|
|
case IPPROTO_TCP:
|
|
|
|
result = g_queue_find_custom(&conn->secondary_list,
|
|
|
|
pkt, (GCompareFunc)colo_packet_compare_tcp);
|
|
|
|
break;
|
|
|
|
case IPPROTO_UDP:
|
|
|
|
result = g_queue_find_custom(&conn->secondary_list,
|
|
|
|
pkt, (GCompareFunc)colo_packet_compare_udp);
|
|
|
|
break;
|
|
|
|
case IPPROTO_ICMP:
|
|
|
|
result = g_queue_find_custom(&conn->secondary_list,
|
|
|
|
pkt, (GCompareFunc)colo_packet_compare_icmp);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
result = g_queue_find_custom(&conn->secondary_list,
|
|
|
|
pkt, (GCompareFunc)colo_packet_compare_other);
|
|
|
|
break;
|
|
|
|
}
|
2016-09-27 05:22:30 +03:00
|
|
|
|
|
|
|
if (result) {
|
|
|
|
ret = compare_chr_send(s->chr_out, pkt->data, pkt->size);
|
|
|
|
if (ret < 0) {
|
|
|
|
error_report("colo_send_primary_packet failed");
|
|
|
|
}
|
|
|
|
trace_colo_compare_main("packet same and release packet");
|
|
|
|
g_queue_remove(&conn->secondary_list, result->data);
|
|
|
|
packet_destroy(pkt, NULL);
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* If one packet arrive late, the secondary_list or
|
|
|
|
* primary_list will be empty, so we can't compare it
|
|
|
|
* until next comparison.
|
|
|
|
*/
|
|
|
|
trace_colo_compare_main("packet different");
|
|
|
|
qemu_mutex_lock(&s->timer_check_lock);
|
|
|
|
g_queue_push_tail(&conn->primary_list, pkt);
|
|
|
|
qemu_mutex_unlock(&s->timer_check_lock);
|
|
|
|
/* TODO: colo_notify_checkpoint();*/
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-27 05:22:27 +03:00
|
|
|
static int compare_chr_send(CharDriverState *out,
|
|
|
|
const uint8_t *buf,
|
|
|
|
uint32_t size)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
uint32_t len = htonl(size);
|
|
|
|
|
|
|
|
if (!size) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = qemu_chr_fe_write_all(out, (uint8_t *)&len, sizeof(len));
|
|
|
|
if (ret != sizeof(len)) {
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = qemu_chr_fe_write_all(out, (uint8_t *)buf, size);
|
|
|
|
if (ret != size) {
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
return ret < 0 ? ret : -EIO;
|
|
|
|
}
|
|
|
|
|
2016-09-27 05:22:30 +03:00
|
|
|
static int compare_chr_can_read(void *opaque)
|
|
|
|
{
|
|
|
|
return COMPARE_READ_LEN_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Called from the main thread on the primary for packets
|
|
|
|
* arriving over the socket from the primary.
|
|
|
|
*/
|
|
|
|
static void compare_pri_chr_in(void *opaque, const uint8_t *buf, int size)
|
|
|
|
{
|
|
|
|
CompareState *s = COLO_COMPARE(opaque);
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = net_fill_rstate(&s->pri_rs, buf, size);
|
|
|
|
if (ret == -1) {
|
|
|
|
qemu_chr_add_handlers(s->chr_pri_in, NULL, NULL, NULL, NULL);
|
|
|
|
error_report("colo-compare primary_in error");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Called from the main thread on the primary for packets
|
|
|
|
* arriving over the socket from the secondary.
|
|
|
|
*/
|
|
|
|
static void compare_sec_chr_in(void *opaque, const uint8_t *buf, int size)
|
|
|
|
{
|
|
|
|
CompareState *s = COLO_COMPARE(opaque);
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = net_fill_rstate(&s->sec_rs, buf, size);
|
|
|
|
if (ret == -1) {
|
|
|
|
qemu_chr_add_handlers(s->chr_sec_in, NULL, NULL, NULL, NULL);
|
|
|
|
error_report("colo-compare secondary_in error");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *colo_compare_thread(void *opaque)
|
|
|
|
{
|
|
|
|
GMainContext *worker_context;
|
|
|
|
GMainLoop *compare_loop;
|
|
|
|
CompareState *s = opaque;
|
|
|
|
|
|
|
|
worker_context = g_main_context_new();
|
|
|
|
|
|
|
|
qemu_chr_add_handlers_full(s->chr_pri_in, compare_chr_can_read,
|
|
|
|
compare_pri_chr_in, NULL, s, worker_context);
|
|
|
|
qemu_chr_add_handlers_full(s->chr_sec_in, compare_chr_can_read,
|
|
|
|
compare_sec_chr_in, NULL, s, worker_context);
|
|
|
|
|
|
|
|
compare_loop = g_main_loop_new(worker_context, FALSE);
|
|
|
|
|
|
|
|
g_main_loop_run(compare_loop);
|
|
|
|
|
|
|
|
g_main_loop_unref(compare_loop);
|
|
|
|
g_main_context_unref(worker_context);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
colo-compare: introduce colo compare initialization
This a COLO net ascii figure:
Primary qemu Secondary qemu
+--------------------------------------------------------------+ +----------------------------------------------------------------+
| +----------------------------------------------------------+ | | +-----------------------------------------------------------+ |
| | | | | | | |
| | guest | | | | guest | |
| | | | | | | |
| +-------^--------------------------+-----------------------+ | | +---------------------+--------+----------------------------+ |
| | | | | ^ | |
| | | | | | | |
| | +------------------------------------------------------+ | | | |
|netfilter| | | | | | netfilter | | |
| +----------+ +----------------------------+ | | | +-----------------------------------------------------------+ |
| | | | | | out | | | | | | filter excute order | |
| | | | +-----------------------------+ | | | | | | +-------------------> | |
| | | | | | | | | | | | | | TCP | |
| | +-----+--+-+ +-----v----+ +-----v----+ |pri +----+----+sec| | | | +------------+ +---+----+---v+rewriter++ +------------+ | |
| | | | | | | | |in | |in | | | | | | | | | | | | |
| | | filter | | filter | | filter +------> colo <------+ +--------> filter +--> adjust | adjust +--> filter | | |
| | | mirror | |redirector| |redirector| | | compare | | | | | | redirector | | ack | seq | | redirector | | |
| | | | | | | | | | | | | | | | | | | | | | | |
| | +----^-----+ +----+-----+ +----------+ | +---------+ | | | | +------------+ +--------+--------------+ +---+--------+ | |
| | | tx | rx rx | | | | | tx all | rx | |
| | | | | | | | +-----------------------------------------------------------+ |
| | | +--------------+ | | | | | |
| | | filter excute order | | | | | | |
| | | +----------------> | | | +--------------------------------------------------------+ |
| +-----------------------------------------+ | | |
| | | | | |
+--------------------------------------------------------------+ +----------------------------------------------------------------+
|guest receive | guest send
| |
+--------+----------------------------v------------------------+
| | NOTE: filter direction is rx/tx/all
| tap | rx:receive packets sent to the netdev
| | tx:receive packets sent by the netdev
+--------------------------------------------------------------+
In COLO-compare, we do packet comparing job.
Packets coming from the primary char indev will be sent to outdev.
Packets coming from the secondary char dev will be dropped after comparing.
colo-comapre need two input chardev and one output chardev:
primary_in=chardev1-id (source: primary send packet)
secondary_in=chardev2-id (source: secondary send packet)
outdev=chardev3-id
usage:
primary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait
-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait
-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait
-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 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
secondary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
-device e1000,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=red0,host=3.3.3.3,port=9003
-chardev socket,id=red1,host=3.3.3.3,port=9004
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2016-09-27 05:22:26 +03:00
|
|
|
static char *compare_get_pri_indev(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
CompareState *s = COLO_COMPARE(obj);
|
|
|
|
|
|
|
|
return g_strdup(s->pri_indev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void compare_set_pri_indev(Object *obj, const char *value, Error **errp)
|
|
|
|
{
|
|
|
|
CompareState *s = COLO_COMPARE(obj);
|
|
|
|
|
|
|
|
g_free(s->pri_indev);
|
|
|
|
s->pri_indev = g_strdup(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *compare_get_sec_indev(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
CompareState *s = COLO_COMPARE(obj);
|
|
|
|
|
|
|
|
return g_strdup(s->sec_indev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void compare_set_sec_indev(Object *obj, const char *value, Error **errp)
|
|
|
|
{
|
|
|
|
CompareState *s = COLO_COMPARE(obj);
|
|
|
|
|
|
|
|
g_free(s->sec_indev);
|
|
|
|
s->sec_indev = g_strdup(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *compare_get_outdev(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
CompareState *s = COLO_COMPARE(obj);
|
|
|
|
|
|
|
|
return g_strdup(s->outdev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void compare_set_outdev(Object *obj, const char *value, Error **errp)
|
|
|
|
{
|
|
|
|
CompareState *s = COLO_COMPARE(obj);
|
|
|
|
|
|
|
|
g_free(s->outdev);
|
|
|
|
s->outdev = g_strdup(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void compare_pri_rs_finalize(SocketReadState *pri_rs)
|
|
|
|
{
|
2016-09-27 05:22:27 +03:00
|
|
|
CompareState *s = container_of(pri_rs, CompareState, pri_rs);
|
|
|
|
|
|
|
|
if (packet_enqueue(s, PRIMARY_IN)) {
|
|
|
|
trace_colo_compare_main("primary: unsupported packet in");
|
|
|
|
compare_chr_send(s->chr_out, pri_rs->buf, pri_rs->packet_len);
|
2016-09-27 05:22:30 +03:00
|
|
|
} else {
|
|
|
|
/* compare connection */
|
|
|
|
g_queue_foreach(&s->conn_list, colo_compare_connection, s);
|
2016-09-27 05:22:27 +03:00
|
|
|
}
|
colo-compare: introduce colo compare initialization
This a COLO net ascii figure:
Primary qemu Secondary qemu
+--------------------------------------------------------------+ +----------------------------------------------------------------+
| +----------------------------------------------------------+ | | +-----------------------------------------------------------+ |
| | | | | | | |
| | guest | | | | guest | |
| | | | | | | |
| +-------^--------------------------+-----------------------+ | | +---------------------+--------+----------------------------+ |
| | | | | ^ | |
| | | | | | | |
| | +------------------------------------------------------+ | | | |
|netfilter| | | | | | netfilter | | |
| +----------+ +----------------------------+ | | | +-----------------------------------------------------------+ |
| | | | | | out | | | | | | filter excute order | |
| | | | +-----------------------------+ | | | | | | +-------------------> | |
| | | | | | | | | | | | | | TCP | |
| | +-----+--+-+ +-----v----+ +-----v----+ |pri +----+----+sec| | | | +------------+ +---+----+---v+rewriter++ +------------+ | |
| | | | | | | | |in | |in | | | | | | | | | | | | |
| | | filter | | filter | | filter +------> colo <------+ +--------> filter +--> adjust | adjust +--> filter | | |
| | | mirror | |redirector| |redirector| | | compare | | | | | | redirector | | ack | seq | | redirector | | |
| | | | | | | | | | | | | | | | | | | | | | | |
| | +----^-----+ +----+-----+ +----------+ | +---------+ | | | | +------------+ +--------+--------------+ +---+--------+ | |
| | | tx | rx rx | | | | | tx all | rx | |
| | | | | | | | +-----------------------------------------------------------+ |
| | | +--------------+ | | | | | |
| | | filter excute order | | | | | | |
| | | +----------------> | | | +--------------------------------------------------------+ |
| +-----------------------------------------+ | | |
| | | | | |
+--------------------------------------------------------------+ +----------------------------------------------------------------+
|guest receive | guest send
| |
+--------+----------------------------v------------------------+
| | NOTE: filter direction is rx/tx/all
| tap | rx:receive packets sent to the netdev
| | tx:receive packets sent by the netdev
+--------------------------------------------------------------+
In COLO-compare, we do packet comparing job.
Packets coming from the primary char indev will be sent to outdev.
Packets coming from the secondary char dev will be dropped after comparing.
colo-comapre need two input chardev and one output chardev:
primary_in=chardev1-id (source: primary send packet)
secondary_in=chardev2-id (source: secondary send packet)
outdev=chardev3-id
usage:
primary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait
-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait
-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait
-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 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
secondary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
-device e1000,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=red0,host=3.3.3.3,port=9003
-chardev socket,id=red1,host=3.3.3.3,port=9004
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2016-09-27 05:22:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void compare_sec_rs_finalize(SocketReadState *sec_rs)
|
|
|
|
{
|
2016-09-27 05:22:27 +03:00
|
|
|
CompareState *s = container_of(sec_rs, CompareState, sec_rs);
|
|
|
|
|
|
|
|
if (packet_enqueue(s, SECONDARY_IN)) {
|
|
|
|
trace_colo_compare_main("secondary: unsupported packet in");
|
2016-09-27 05:22:30 +03:00
|
|
|
} else {
|
|
|
|
/* compare connection */
|
|
|
|
g_queue_foreach(&s->conn_list, colo_compare_connection, s);
|
2016-09-27 05:22:27 +03:00
|
|
|
}
|
colo-compare: introduce colo compare initialization
This a COLO net ascii figure:
Primary qemu Secondary qemu
+--------------------------------------------------------------+ +----------------------------------------------------------------+
| +----------------------------------------------------------+ | | +-----------------------------------------------------------+ |
| | | | | | | |
| | guest | | | | guest | |
| | | | | | | |
| +-------^--------------------------+-----------------------+ | | +---------------------+--------+----------------------------+ |
| | | | | ^ | |
| | | | | | | |
| | +------------------------------------------------------+ | | | |
|netfilter| | | | | | netfilter | | |
| +----------+ +----------------------------+ | | | +-----------------------------------------------------------+ |
| | | | | | out | | | | | | filter excute order | |
| | | | +-----------------------------+ | | | | | | +-------------------> | |
| | | | | | | | | | | | | | TCP | |
| | +-----+--+-+ +-----v----+ +-----v----+ |pri +----+----+sec| | | | +------------+ +---+----+---v+rewriter++ +------------+ | |
| | | | | | | | |in | |in | | | | | | | | | | | | |
| | | filter | | filter | | filter +------> colo <------+ +--------> filter +--> adjust | adjust +--> filter | | |
| | | mirror | |redirector| |redirector| | | compare | | | | | | redirector | | ack | seq | | redirector | | |
| | | | | | | | | | | | | | | | | | | | | | | |
| | +----^-----+ +----+-----+ +----------+ | +---------+ | | | | +------------+ +--------+--------------+ +---+--------+ | |
| | | tx | rx rx | | | | | tx all | rx | |
| | | | | | | | +-----------------------------------------------------------+ |
| | | +--------------+ | | | | | |
| | | filter excute order | | | | | | |
| | | +----------------> | | | +--------------------------------------------------------+ |
| +-----------------------------------------+ | | |
| | | | | |
+--------------------------------------------------------------+ +----------------------------------------------------------------+
|guest receive | guest send
| |
+--------+----------------------------v------------------------+
| | NOTE: filter direction is rx/tx/all
| tap | rx:receive packets sent to the netdev
| | tx:receive packets sent by the netdev
+--------------------------------------------------------------+
In COLO-compare, we do packet comparing job.
Packets coming from the primary char indev will be sent to outdev.
Packets coming from the secondary char dev will be dropped after comparing.
colo-comapre need two input chardev and one output chardev:
primary_in=chardev1-id (source: primary send packet)
secondary_in=chardev2-id (source: secondary send packet)
outdev=chardev3-id
usage:
primary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait
-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait
-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait
-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 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
secondary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
-device e1000,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=red0,host=3.3.3.3,port=9003
-chardev socket,id=red1,host=3.3.3.3,port=9004
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2016-09-27 05:22:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return 0 is success.
|
|
|
|
* Return 1 is failed.
|
|
|
|
*/
|
|
|
|
static int find_and_check_chardev(CharDriverState **chr,
|
|
|
|
char *chr_name,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
CompareChardevProps props;
|
|
|
|
|
|
|
|
*chr = qemu_chr_find(chr_name);
|
|
|
|
if (*chr == NULL) {
|
|
|
|
error_setg(errp, "Device '%s' not found",
|
|
|
|
chr_name);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&props, 0, sizeof(props));
|
|
|
|
|
net: don't poke at chardev internal QemuOpts
The vhost-user & colo code is poking at the QemuOpts instance
in the CharDriverState struct, not realizing that it is valid
for this to be NULL. e.g. the following crash shows a codepath
where it will be NULL:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x000055baf6ab4adc in qemu_opt_foreach (opts=0x0, func=0x55baf696b650 <net_vhost_chardev_opts>, opaque=0x7ffc51368c00, errp=0x7ffc51368e48) at util/qemu-option.c:617
617 QTAILQ_FOREACH(opt, &opts->head, next) {
[Current thread is 1 (Thread 0x7f1d4970bb40 (LWP 6603))]
(gdb) bt
#0 0x000055baf6ab4adc in qemu_opt_foreach (opts=0x0, func=0x55baf696b650 <net_vhost_chardev_opts>, opaque=0x7ffc51368c00, errp=0x7ffc51368e48) at util/qemu-option.c:617
#1 0x000055baf696b7da in net_vhost_parse_chardev (opts=0x55baf8ff9260, errp=0x7ffc51368e48) at net/vhost-user.c:314
#2 0x000055baf696b985 in net_init_vhost_user (netdev=0x55baf8ff9250, name=0x55baf879d270 "hostnet2", peer=0x0, errp=0x7ffc51368e48) at net/vhost-user.c:360
#3 0x000055baf6960216 in net_client_init1 (object=0x55baf8ff9250, is_netdev=true, errp=0x7ffc51368e48) at net/net.c:1051
#4 0x000055baf6960518 in net_client_init (opts=0x55baf776e7e0, is_netdev=true, errp=0x7ffc51368f00) at net/net.c:1108
#5 0x000055baf696083f in netdev_add (opts=0x55baf776e7e0, errp=0x7ffc51368f00) at net/net.c:1186
#6 0x000055baf69608c7 in qmp_netdev_add (qdict=0x55baf7afaf60, ret=0x7ffc51368f50, errp=0x7ffc51368f48) at net/net.c:1205
#7 0x000055baf6622135 in handle_qmp_command (parser=0x55baf77fb590, tokens=0x7f1d24011960) at /path/to/qemu.git/monitor.c:3978
#8 0x000055baf6a9d099 in json_message_process_token (lexer=0x55baf77fb598, input=0x55baf75acd20, type=JSON_RCURLY, x=113, y=19) at qobject/json-streamer.c:105
#9 0x000055baf6abf7aa in json_lexer_feed_char (lexer=0x55baf77fb598, ch=125 '}', flush=false) at qobject/json-lexer.c:319
#10 0x000055baf6abf8f2 in json_lexer_feed (lexer=0x55baf77fb598, buffer=0x7ffc51369170 "}R\204\367\272U", size=1) at qobject/json-lexer.c:369
#11 0x000055baf6a9d13c in json_message_parser_feed (parser=0x55baf77fb590, buffer=0x7ffc51369170 "}R\204\367\272U", size=1) at qobject/json-streamer.c:124
#12 0x000055baf66221f7 in monitor_qmp_read (opaque=0x55baf77fb530, buf=0x7ffc51369170 "}R\204\367\272U", size=1) at /path/to/qemu.git/monitor.c:3994
#13 0x000055baf6757014 in qemu_chr_be_write_impl (s=0x55baf7610a40, buf=0x7ffc51369170 "}R\204\367\272U", len=1) at qemu-char.c:387
#14 0x000055baf6757076 in qemu_chr_be_write (s=0x55baf7610a40, buf=0x7ffc51369170 "}R\204\367\272U", len=1) at qemu-char.c:399
#15 0x000055baf675b3b0 in tcp_chr_read (chan=0x55baf90244b0, cond=G_IO_IN, opaque=0x55baf7610a40) at qemu-char.c:2927
#16 0x000055baf6a5d655 in qio_channel_fd_source_dispatch (source=0x55baf7610df0, callback=0x55baf675b25a <tcp_chr_read>, user_data=0x55baf7610a40) at io/channel-watch.c:84
#17 0x00007f1d3e80cbbd in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0
#18 0x000055baf69d3720 in glib_pollfds_poll () at main-loop.c:213
#19 0x000055baf69d37fd in os_host_main_loop_wait (timeout=126000000) at main-loop.c:258
#20 0x000055baf69d38ad in main_loop_wait (nonblocking=0) at main-loop.c:506
#21 0x000055baf676587b in main_loop () at vl.c:1908
#22 0x000055baf676d3bf in main (argc=101, argv=0x7ffc5136a6c8, envp=0x7ffc5136a9f8) at vl.c:4604
(gdb) p opts
$1 = (QemuOpts *) 0x0
The crash occurred when attaching vhost-user net via QMP:
{
"execute": "chardev-add",
"arguments": {
"id": "charnet2",
"backend": {
"type": "socket",
"data": {
"addr": {
"type": "unix",
"data": {
"path": "/var/run/openvswitch/vhost-user1"
}
},
"wait": false,
"server": false
}
}
},
"id": "libvirt-19"
}
{
"return": {
},
"id": "libvirt-19"
}
{
"execute": "netdev_add",
"arguments": {
"type": "vhost-user",
"chardev": "charnet2",
"id": "hostnet2"
},
"id": "libvirt-20"
}
Code using chardevs should not be poking at the internals of the
CharDriverState struct. What vhost-user wants is a chardev that is
operating as reconnectable network service, along with the ability
to do FD passing over the connection. The colo code simply wants
a network service. Add a feature concept to the char drivers so
that chardev users can query the actual features they wish to have
supported. The QemuOpts member is removed to prevent future mistakes
in this area.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2016-10-07 15:18:34 +03:00
|
|
|
if (!qemu_chr_has_feature(*chr, QEMU_CHAR_FEATURE_RECONNECTABLE)) {
|
|
|
|
error_setg(errp, "chardev \"%s\" is not reconnectable",
|
colo-compare: introduce colo compare initialization
This a COLO net ascii figure:
Primary qemu Secondary qemu
+--------------------------------------------------------------+ +----------------------------------------------------------------+
| +----------------------------------------------------------+ | | +-----------------------------------------------------------+ |
| | | | | | | |
| | guest | | | | guest | |
| | | | | | | |
| +-------^--------------------------+-----------------------+ | | +---------------------+--------+----------------------------+ |
| | | | | ^ | |
| | | | | | | |
| | +------------------------------------------------------+ | | | |
|netfilter| | | | | | netfilter | | |
| +----------+ +----------------------------+ | | | +-----------------------------------------------------------+ |
| | | | | | out | | | | | | filter excute order | |
| | | | +-----------------------------+ | | | | | | +-------------------> | |
| | | | | | | | | | | | | | TCP | |
| | +-----+--+-+ +-----v----+ +-----v----+ |pri +----+----+sec| | | | +------------+ +---+----+---v+rewriter++ +------------+ | |
| | | | | | | | |in | |in | | | | | | | | | | | | |
| | | filter | | filter | | filter +------> colo <------+ +--------> filter +--> adjust | adjust +--> filter | | |
| | | mirror | |redirector| |redirector| | | compare | | | | | | redirector | | ack | seq | | redirector | | |
| | | | | | | | | | | | | | | | | | | | | | | |
| | +----^-----+ +----+-----+ +----------+ | +---------+ | | | | +------------+ +--------+--------------+ +---+--------+ | |
| | | tx | rx rx | | | | | tx all | rx | |
| | | | | | | | +-----------------------------------------------------------+ |
| | | +--------------+ | | | | | |
| | | filter excute order | | | | | | |
| | | +----------------> | | | +--------------------------------------------------------+ |
| +-----------------------------------------+ | | |
| | | | | |
+--------------------------------------------------------------+ +----------------------------------------------------------------+
|guest receive | guest send
| |
+--------+----------------------------v------------------------+
| | NOTE: filter direction is rx/tx/all
| tap | rx:receive packets sent to the netdev
| | tx:receive packets sent by the netdev
+--------------------------------------------------------------+
In COLO-compare, we do packet comparing job.
Packets coming from the primary char indev will be sent to outdev.
Packets coming from the secondary char dev will be dropped after comparing.
colo-comapre need two input chardev and one output chardev:
primary_in=chardev1-id (source: primary send packet)
secondary_in=chardev2-id (source: secondary send packet)
outdev=chardev3-id
usage:
primary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait
-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait
-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait
-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 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
secondary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
-device e1000,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=red0,host=3.3.3.3,port=9003
-chardev socket,id=red1,host=3.3.3.3,port=9004
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2016-09-27 05:22:26 +03:00
|
|
|
chr_name);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-27 05:22:30 +03:00
|
|
|
/*
|
|
|
|
* Check old packet regularly so it can watch for any packets
|
|
|
|
* that the secondary hasn't produced equivalents of.
|
|
|
|
*/
|
|
|
|
static void check_old_packet_regular(void *opaque)
|
|
|
|
{
|
|
|
|
CompareState *s = opaque;
|
|
|
|
|
|
|
|
timer_mod(s->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
|
|
|
|
REGULAR_PACKET_CHECK_MS);
|
|
|
|
/* if have old packet we will notify checkpoint */
|
|
|
|
/*
|
|
|
|
* TODO: Make timer handler run in compare thread
|
|
|
|
* like qemu_chr_add_handlers_full.
|
|
|
|
*/
|
|
|
|
qemu_mutex_lock(&s->timer_check_lock);
|
|
|
|
colo_old_packet_check(s);
|
|
|
|
qemu_mutex_unlock(&s->timer_check_lock);
|
|
|
|
}
|
|
|
|
|
colo-compare: introduce colo compare initialization
This a COLO net ascii figure:
Primary qemu Secondary qemu
+--------------------------------------------------------------+ +----------------------------------------------------------------+
| +----------------------------------------------------------+ | | +-----------------------------------------------------------+ |
| | | | | | | |
| | guest | | | | guest | |
| | | | | | | |
| +-------^--------------------------+-----------------------+ | | +---------------------+--------+----------------------------+ |
| | | | | ^ | |
| | | | | | | |
| | +------------------------------------------------------+ | | | |
|netfilter| | | | | | netfilter | | |
| +----------+ +----------------------------+ | | | +-----------------------------------------------------------+ |
| | | | | | out | | | | | | filter excute order | |
| | | | +-----------------------------+ | | | | | | +-------------------> | |
| | | | | | | | | | | | | | TCP | |
| | +-----+--+-+ +-----v----+ +-----v----+ |pri +----+----+sec| | | | +------------+ +---+----+---v+rewriter++ +------------+ | |
| | | | | | | | |in | |in | | | | | | | | | | | | |
| | | filter | | filter | | filter +------> colo <------+ +--------> filter +--> adjust | adjust +--> filter | | |
| | | mirror | |redirector| |redirector| | | compare | | | | | | redirector | | ack | seq | | redirector | | |
| | | | | | | | | | | | | | | | | | | | | | | |
| | +----^-----+ +----+-----+ +----------+ | +---------+ | | | | +------------+ +--------+--------------+ +---+--------+ | |
| | | tx | rx rx | | | | | tx all | rx | |
| | | | | | | | +-----------------------------------------------------------+ |
| | | +--------------+ | | | | | |
| | | filter excute order | | | | | | |
| | | +----------------> | | | +--------------------------------------------------------+ |
| +-----------------------------------------+ | | |
| | | | | |
+--------------------------------------------------------------+ +----------------------------------------------------------------+
|guest receive | guest send
| |
+--------+----------------------------v------------------------+
| | NOTE: filter direction is rx/tx/all
| tap | rx:receive packets sent to the netdev
| | tx:receive packets sent by the netdev
+--------------------------------------------------------------+
In COLO-compare, we do packet comparing job.
Packets coming from the primary char indev will be sent to outdev.
Packets coming from the secondary char dev will be dropped after comparing.
colo-comapre need two input chardev and one output chardev:
primary_in=chardev1-id (source: primary send packet)
secondary_in=chardev2-id (source: secondary send packet)
outdev=chardev3-id
usage:
primary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait
-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait
-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait
-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 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
secondary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
-device e1000,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=red0,host=3.3.3.3,port=9003
-chardev socket,id=red1,host=3.3.3.3,port=9004
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2016-09-27 05:22:26 +03:00
|
|
|
/*
|
|
|
|
* Called from the main thread on the primary
|
|
|
|
* to setup colo-compare.
|
|
|
|
*/
|
|
|
|
static void colo_compare_complete(UserCreatable *uc, Error **errp)
|
|
|
|
{
|
|
|
|
CompareState *s = COLO_COMPARE(uc);
|
2016-09-27 05:22:30 +03:00
|
|
|
char thread_name[64];
|
|
|
|
static int compare_id;
|
colo-compare: introduce colo compare initialization
This a COLO net ascii figure:
Primary qemu Secondary qemu
+--------------------------------------------------------------+ +----------------------------------------------------------------+
| +----------------------------------------------------------+ | | +-----------------------------------------------------------+ |
| | | | | | | |
| | guest | | | | guest | |
| | | | | | | |
| +-------^--------------------------+-----------------------+ | | +---------------------+--------+----------------------------+ |
| | | | | ^ | |
| | | | | | | |
| | +------------------------------------------------------+ | | | |
|netfilter| | | | | | netfilter | | |
| +----------+ +----------------------------+ | | | +-----------------------------------------------------------+ |
| | | | | | out | | | | | | filter excute order | |
| | | | +-----------------------------+ | | | | | | +-------------------> | |
| | | | | | | | | | | | | | TCP | |
| | +-----+--+-+ +-----v----+ +-----v----+ |pri +----+----+sec| | | | +------------+ +---+----+---v+rewriter++ +------------+ | |
| | | | | | | | |in | |in | | | | | | | | | | | | |
| | | filter | | filter | | filter +------> colo <------+ +--------> filter +--> adjust | adjust +--> filter | | |
| | | mirror | |redirector| |redirector| | | compare | | | | | | redirector | | ack | seq | | redirector | | |
| | | | | | | | | | | | | | | | | | | | | | | |
| | +----^-----+ +----+-----+ +----------+ | +---------+ | | | | +------------+ +--------+--------------+ +---+--------+ | |
| | | tx | rx rx | | | | | tx all | rx | |
| | | | | | | | +-----------------------------------------------------------+ |
| | | +--------------+ | | | | | |
| | | filter excute order | | | | | | |
| | | +----------------> | | | +--------------------------------------------------------+ |
| +-----------------------------------------+ | | |
| | | | | |
+--------------------------------------------------------------+ +----------------------------------------------------------------+
|guest receive | guest send
| |
+--------+----------------------------v------------------------+
| | NOTE: filter direction is rx/tx/all
| tap | rx:receive packets sent to the netdev
| | tx:receive packets sent by the netdev
+--------------------------------------------------------------+
In COLO-compare, we do packet comparing job.
Packets coming from the primary char indev will be sent to outdev.
Packets coming from the secondary char dev will be dropped after comparing.
colo-comapre need two input chardev and one output chardev:
primary_in=chardev1-id (source: primary send packet)
secondary_in=chardev2-id (source: secondary send packet)
outdev=chardev3-id
usage:
primary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait
-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait
-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait
-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 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
secondary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
-device e1000,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=red0,host=3.3.3.3,port=9003
-chardev socket,id=red1,host=3.3.3.3,port=9004
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2016-09-27 05:22:26 +03:00
|
|
|
|
|
|
|
if (!s->pri_indev || !s->sec_indev || !s->outdev) {
|
|
|
|
error_setg(errp, "colo compare needs 'primary_in' ,"
|
|
|
|
"'secondary_in','outdev' property set");
|
|
|
|
return;
|
|
|
|
} else if (!strcmp(s->pri_indev, s->outdev) ||
|
|
|
|
!strcmp(s->sec_indev, s->outdev) ||
|
|
|
|
!strcmp(s->pri_indev, s->sec_indev)) {
|
|
|
|
error_setg(errp, "'indev' and 'outdev' could not be same "
|
|
|
|
"for compare module");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (find_and_check_chardev(&s->chr_pri_in, s->pri_indev, errp)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (find_and_check_chardev(&s->chr_sec_in, s->sec_indev, errp)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (find_and_check_chardev(&s->chr_out, s->outdev, errp)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
qemu_chr_fe_claim_no_fail(s->chr_pri_in);
|
|
|
|
|
|
|
|
qemu_chr_fe_claim_no_fail(s->chr_sec_in);
|
|
|
|
|
|
|
|
qemu_chr_fe_claim_no_fail(s->chr_out);
|
|
|
|
|
|
|
|
net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize);
|
|
|
|
net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize);
|
|
|
|
|
2016-09-27 05:22:29 +03:00
|
|
|
g_queue_init(&s->conn_list);
|
2016-09-27 05:22:30 +03:00
|
|
|
qemu_mutex_init(&s->timer_check_lock);
|
2016-09-27 05:22:29 +03:00
|
|
|
|
|
|
|
s->connection_track_table = g_hash_table_new_full(connection_key_hash,
|
|
|
|
connection_key_equal,
|
|
|
|
g_free,
|
|
|
|
connection_destroy);
|
2016-09-27 05:22:27 +03:00
|
|
|
|
2016-09-27 05:22:30 +03:00
|
|
|
sprintf(thread_name, "colo-compare %d", compare_id);
|
|
|
|
qemu_thread_create(&s->thread, thread_name,
|
|
|
|
colo_compare_thread, s,
|
|
|
|
QEMU_THREAD_JOINABLE);
|
|
|
|
compare_id++;
|
|
|
|
|
|
|
|
/* A regular timer to kick any packets that the secondary doesn't match */
|
|
|
|
s->timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, /* Only when guest runs */
|
|
|
|
check_old_packet_regular, s);
|
|
|
|
timer_mod(s->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
|
|
|
|
REGULAR_PACKET_CHECK_MS);
|
|
|
|
|
colo-compare: introduce colo compare initialization
This a COLO net ascii figure:
Primary qemu Secondary qemu
+--------------------------------------------------------------+ +----------------------------------------------------------------+
| +----------------------------------------------------------+ | | +-----------------------------------------------------------+ |
| | | | | | | |
| | guest | | | | guest | |
| | | | | | | |
| +-------^--------------------------+-----------------------+ | | +---------------------+--------+----------------------------+ |
| | | | | ^ | |
| | | | | | | |
| | +------------------------------------------------------+ | | | |
|netfilter| | | | | | netfilter | | |
| +----------+ +----------------------------+ | | | +-----------------------------------------------------------+ |
| | | | | | out | | | | | | filter excute order | |
| | | | +-----------------------------+ | | | | | | +-------------------> | |
| | | | | | | | | | | | | | TCP | |
| | +-----+--+-+ +-----v----+ +-----v----+ |pri +----+----+sec| | | | +------------+ +---+----+---v+rewriter++ +------------+ | |
| | | | | | | | |in | |in | | | | | | | | | | | | |
| | | filter | | filter | | filter +------> colo <------+ +--------> filter +--> adjust | adjust +--> filter | | |
| | | mirror | |redirector| |redirector| | | compare | | | | | | redirector | | ack | seq | | redirector | | |
| | | | | | | | | | | | | | | | | | | | | | | |
| | +----^-----+ +----+-----+ +----------+ | +---------+ | | | | +------------+ +--------+--------------+ +---+--------+ | |
| | | tx | rx rx | | | | | tx all | rx | |
| | | | | | | | +-----------------------------------------------------------+ |
| | | +--------------+ | | | | | |
| | | filter excute order | | | | | | |
| | | +----------------> | | | +--------------------------------------------------------+ |
| +-----------------------------------------+ | | |
| | | | | |
+--------------------------------------------------------------+ +----------------------------------------------------------------+
|guest receive | guest send
| |
+--------+----------------------------v------------------------+
| | NOTE: filter direction is rx/tx/all
| tap | rx:receive packets sent to the netdev
| | tx:receive packets sent by the netdev
+--------------------------------------------------------------+
In COLO-compare, we do packet comparing job.
Packets coming from the primary char indev will be sent to outdev.
Packets coming from the secondary char dev will be dropped after comparing.
colo-comapre need two input chardev and one output chardev:
primary_in=chardev1-id (source: primary send packet)
secondary_in=chardev2-id (source: secondary send packet)
outdev=chardev3-id
usage:
primary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait
-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait
-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait
-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 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
secondary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
-device e1000,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=red0,host=3.3.3.3,port=9003
-chardev socket,id=red1,host=3.3.3.3,port=9004
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2016-09-27 05:22:26 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void colo_compare_class_init(ObjectClass *oc, void *data)
|
|
|
|
{
|
|
|
|
UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
|
|
|
|
|
|
|
|
ucc->complete = colo_compare_complete;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void colo_compare_init(Object *obj)
|
|
|
|
{
|
|
|
|
object_property_add_str(obj, "primary_in",
|
|
|
|
compare_get_pri_indev, compare_set_pri_indev,
|
|
|
|
NULL);
|
|
|
|
object_property_add_str(obj, "secondary_in",
|
|
|
|
compare_get_sec_indev, compare_set_sec_indev,
|
|
|
|
NULL);
|
|
|
|
object_property_add_str(obj, "outdev",
|
|
|
|
compare_get_outdev, compare_set_outdev,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void colo_compare_finalize(Object *obj)
|
|
|
|
{
|
|
|
|
CompareState *s = COLO_COMPARE(obj);
|
|
|
|
|
|
|
|
if (s->chr_pri_in) {
|
|
|
|
qemu_chr_add_handlers(s->chr_pri_in, NULL, NULL, NULL, NULL);
|
|
|
|
qemu_chr_fe_release(s->chr_pri_in);
|
|
|
|
}
|
|
|
|
if (s->chr_sec_in) {
|
|
|
|
qemu_chr_add_handlers(s->chr_sec_in, NULL, NULL, NULL, NULL);
|
|
|
|
qemu_chr_fe_release(s->chr_sec_in);
|
|
|
|
}
|
|
|
|
if (s->chr_out) {
|
|
|
|
qemu_chr_fe_release(s->chr_out);
|
|
|
|
}
|
|
|
|
|
2016-09-27 05:22:29 +03:00
|
|
|
g_queue_free(&s->conn_list);
|
|
|
|
|
2016-09-27 05:22:30 +03:00
|
|
|
if (qemu_thread_is_self(&s->thread)) {
|
|
|
|
/* compare connection */
|
|
|
|
g_queue_foreach(&s->conn_list, colo_compare_connection, s);
|
|
|
|
qemu_thread_join(&s->thread);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s->timer) {
|
|
|
|
timer_del(s->timer);
|
|
|
|
}
|
|
|
|
|
|
|
|
qemu_mutex_destroy(&s->timer_check_lock);
|
|
|
|
|
colo-compare: introduce colo compare initialization
This a COLO net ascii figure:
Primary qemu Secondary qemu
+--------------------------------------------------------------+ +----------------------------------------------------------------+
| +----------------------------------------------------------+ | | +-----------------------------------------------------------+ |
| | | | | | | |
| | guest | | | | guest | |
| | | | | | | |
| +-------^--------------------------+-----------------------+ | | +---------------------+--------+----------------------------+ |
| | | | | ^ | |
| | | | | | | |
| | +------------------------------------------------------+ | | | |
|netfilter| | | | | | netfilter | | |
| +----------+ +----------------------------+ | | | +-----------------------------------------------------------+ |
| | | | | | out | | | | | | filter excute order | |
| | | | +-----------------------------+ | | | | | | +-------------------> | |
| | | | | | | | | | | | | | TCP | |
| | +-----+--+-+ +-----v----+ +-----v----+ |pri +----+----+sec| | | | +------------+ +---+----+---v+rewriter++ +------------+ | |
| | | | | | | | |in | |in | | | | | | | | | | | | |
| | | filter | | filter | | filter +------> colo <------+ +--------> filter +--> adjust | adjust +--> filter | | |
| | | mirror | |redirector| |redirector| | | compare | | | | | | redirector | | ack | seq | | redirector | | |
| | | | | | | | | | | | | | | | | | | | | | | |
| | +----^-----+ +----+-----+ +----------+ | +---------+ | | | | +------------+ +--------+--------------+ +---+--------+ | |
| | | tx | rx rx | | | | | tx all | rx | |
| | | | | | | | +-----------------------------------------------------------+ |
| | | +--------------+ | | | | | |
| | | filter excute order | | | | | | |
| | | +----------------> | | | +--------------------------------------------------------+ |
| +-----------------------------------------+ | | |
| | | | | |
+--------------------------------------------------------------+ +----------------------------------------------------------------+
|guest receive | guest send
| |
+--------+----------------------------v------------------------+
| | NOTE: filter direction is rx/tx/all
| tap | rx:receive packets sent to the netdev
| | tx:receive packets sent by the netdev
+--------------------------------------------------------------+
In COLO-compare, we do packet comparing job.
Packets coming from the primary char indev will be sent to outdev.
Packets coming from the secondary char dev will be dropped after comparing.
colo-comapre need two input chardev and one output chardev:
primary_in=chardev1-id (source: primary send packet)
secondary_in=chardev2-id (source: secondary send packet)
outdev=chardev3-id
usage:
primary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait
-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait
-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait
-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 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
secondary:
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
-device e1000,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=red0,host=3.3.3.3,port=9003
-chardev socket,id=red1,host=3.3.3.3,port=9004
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2016-09-27 05:22:26 +03:00
|
|
|
g_free(s->pri_indev);
|
|
|
|
g_free(s->sec_indev);
|
|
|
|
g_free(s->outdev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const TypeInfo colo_compare_info = {
|
|
|
|
.name = TYPE_COLO_COMPARE,
|
|
|
|
.parent = TYPE_OBJECT,
|
|
|
|
.instance_size = sizeof(CompareState),
|
|
|
|
.instance_init = colo_compare_init,
|
|
|
|
.instance_finalize = colo_compare_finalize,
|
|
|
|
.class_size = sizeof(CompareClass),
|
|
|
|
.class_init = colo_compare_class_init,
|
|
|
|
.interfaces = (InterfaceInfo[]) {
|
|
|
|
{ TYPE_USER_CREATABLE },
|
|
|
|
{ }
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static void register_types(void)
|
|
|
|
{
|
|
|
|
type_register_static(&colo_compare_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
type_init(register_types);
|