@@ -37,4 +37,6 @@ COLOMode get_colo_mode(void);
void colo_do_failover(MigrationState *s);
bool colo_shutdown(void);
+void colo_add_buffer_filter(const char *netdev_id, void *opaque);
+
#endif
@@ -22,6 +22,8 @@
#define NETFILTER_CLASS(klass) \
OBJECT_CLASS_CHECK(NetFilterClass, (klass), TYPE_NETFILTER)
+#define TYPE_FILTER_BUFFER "filter-buffer"
+
typedef void (FilterSetup) (NetFilterState *nf, Error **errp);
typedef void (FilterCleanup) (NetFilterState *nf);
/*
@@ -13,6 +13,7 @@
#include <migration/colo.h>
#include "trace.h"
+#include <net/net.h>
typedef struct {
bool colo_requested;
@@ -58,6 +59,10 @@ static const VMStateDescription colo_state = {
void colo_info_init(void)
{
vmstate_register(NULL, 0, &colo_state, &colo_info);
+ /* FIXME: Remove this after COLO switch to use colo-proxy */
+ if (colo_supported()) {
+ netdev_init_add_handler(colo_add_buffer_filter, NULL);
+ }
}
bool migration_incoming_enable_colo(void)
@@ -18,12 +18,23 @@
#include "qemu/error-report.h"
#include "migration/failover.h"
#include "qapi-event.h"
+#include "net/net.h"
+#include "net/filter.h"
+#include "net/vhost_net.h"
static bool vmstate_loading;
/* colo buffer */
#define COLO_BUFFER_BASE_SIZE (4 * 1024 * 1024)
+typedef struct COLOListNode {
+ void *opaque;
+ QLIST_ENTRY(COLOListNode) node;
+} COLOListNode;
+
+static QLIST_HEAD(, COLOListNode) COLOBufferFilters =
+ QLIST_HEAD_INITIALIZER(COLOBufferFilters);
+
bool colo_supported(void)
{
return true;
@@ -382,6 +393,44 @@ static int colo_prepare_before_save(MigrationState *s)
return ret;
}
+void colo_add_buffer_filter(const char *netdev_id, void *opaque)
+{
+ NetFilterState *nf;
+ char filter_name[128];
+ Object *filter;
+ COLOListNode *filternode;
+ NetClientState *nc = qemu_find_netdev(netdev_id);
+
+ /* FIXME: Not support multiple queues */
+ if (!nc || nc->queue_index > 1) {
+ return;
+ }
+
+ /* Not support vhost-net */
+ if (get_vhost_net(nc)) {
+ return;
+ }
+
+ snprintf(filter_name, sizeof(filter_name),
+ "%scolo", netdev_id);
+
+ filter = object_new_with_props(TYPE_FILTER_BUFFER,
+ object_get_objects_root(),
+ filter_name, NULL,
+ "netdev", netdev_id,
+ "status", "disable",
+ NULL);
+ if (!filter) {
+ return;
+ }
+ nf = NETFILTER(filter);
+ /* Only buffer the packets that sent out by VM */
+ nf->direction = NET_FILTER_DIRECTION_RX;
+ filternode = g_new0(COLOListNode, 1);
+ filternode->opaque = nf;
+ QLIST_INSERT_HEAD(&COLOBufferFilters, filternode, node);
+}
+
static void colo_process_checkpoint(MigrationState *s)
{
QEMUSizedBuffer *buffer = NULL;
@@ -16,8 +16,6 @@
#include "qapi-visit.h"
#include "qom/object.h"
-#define TYPE_FILTER_BUFFER "filter-buffer"
-
#define FILTER_BUFFER(obj) \
OBJECT_CHECK(FilterBufferState, (obj), TYPE_FILTER_BUFFER)
@@ -48,3 +48,7 @@ bool colo_shutdown(void)
{
return false;
}
+
+void colo_add_buffer_filter(const char *netdev_id, void *opaque)
+{
+}
For COLO periodic mode, it need to buffer packets that sent by VM, and we will not release these packets until finish a checkpoint. Here, we add each netdev a buffer-filter that will be controlled by COLO. It is disabled by default, and the packets will not pass through these filters. If users don't enable COLO while configure qemu, these buffer-filters will not be added. Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com> Cc: Jason Wang <jasowang@redhat.com> Cc: Yang Hongyang <hongyang.yang@easystack.cn> --- v15: - call object_new_with_props() directly to add filter in colo_add_buffer_filter. (Jason's suggestion) v14: - New patch --- include/migration/colo.h | 2 ++ include/net/filter.h | 2 ++ migration/colo-comm.c | 5 +++++ migration/colo.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ net/filter-buffer.c | 2 -- stubs/migration-colo.c | 4 ++++ 6 files changed, 62 insertions(+), 2 deletions(-)