On Thu, 24 Dec 2020 09:09:18 +0800 Zhang Chen wrote: > From: Zhang Chen > > Currently, we just use guest's TCP/UDP source port as the key > to bypass certain network traffic. > > Signed-off-by: Zhang Chen > --- > net/colo-compare.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++ > net/colo-compare.h | 2 ++ > net/net.c | 27 +++++++++++++++++++++++++ > 3 files changed, 78 insertions(+) > > diff --git a/net/colo-compare.c b/net/colo-compare.c > index 337025b44f..11a32caa9b 100644 > --- a/net/colo-compare.c > +++ b/net/colo-compare.c > @@ -46,6 +46,9 @@ static QTAILQ_HEAD(, CompareState) net_compares = > static NotifierList colo_compare_notifiers = > NOTIFIER_LIST_INITIALIZER(colo_compare_notifiers); > > +static QLIST_HEAD(, PassthroughEntry) passthroughlist = > + QLIST_HEAD_INITIALIZER(passthroughlist); > + Hi, I think this should be per colo-compare instance e.g. inside 'struct CompareState'. > #define COMPARE_READ_LEN_MAX NET_BUFSIZE > #define MAX_QUEUE_SIZE 1024 > > @@ -103,6 +106,12 @@ typedef struct SendEntry { > uint8_t *buf; > } SendEntry; > > +typedef struct PassthroughEntry { > + bool is_tcp; > + uint16_t port; > + QLIST_ENTRY(PassthroughEntry) node; > +} PassthroughEntry; > + > struct CompareState { > Object parent; > > @@ -247,6 +256,7 @@ static int packet_enqueue(CompareState *s, int mode, Connection **con) > ConnectionKey key; > Packet *pkt = NULL; > Connection *conn; > + PassthroughEntry *bypass, *next; > int ret; > > if (mode == PRIMARY_IN) { > @@ -264,8 +274,23 @@ static int packet_enqueue(CompareState *s, int mode, Connection **con) > pkt = NULL; > return -1; > } > + > fill_connection_key(pkt, &key); > > + /* Check COLO passthrough connenction */ > + if (!QLIST_EMPTY(&passthroughlist)) { > + QLIST_FOREACH_SAFE(bypass, &passthroughlist, node, next) { > + if (((key.ip_proto == IPPROTO_TCP) && bypass->is_tcp) || > + ((key.ip_proto == IPPROTO_UDP) && !bypass->is_tcp)) { > + if (bypass->port == key.src_port) { > + packet_destroy(pkt, NULL); > + pkt = NULL; > + return -1; > + } > + } > + } > + } > + > conn = connection_get(s->connection_track_table, > &key, > &s->conn_list); > @@ -1373,6 +1398,30 @@ static void colo_flush_packets(void *opaque, void *user_data) > } > } > > +void colo_compare_passthrough_add(bool is_tcp, const uint16_t port) > +{ > + PassthroughEntry *bypass = NULL; > + > + bypass = g_new0(PassthroughEntry, 1); > + bypass->is_tcp = is_tcp; > + bypass->port = port; > + QLIST_INSERT_HEAD(&passthroughlist, bypass, node); > +} > + > +void colo_compare_passthrough_del(bool is_tcp, const uint16_t port) > +{ > + PassthroughEntry *bypass = NULL, *next = NULL; > + > + if (!QLIST_EMPTY(&passthroughlist)) { > + QLIST_FOREACH_SAFE(bypass, &passthroughlist, node, next) { > + if ((bypass->is_tcp == is_tcp) && (bypass->port == port)) { > + QLIST_REMOVE(bypass, node); > + g_free(bypass); > + } > + } > + } > +} > + > static void colo_compare_class_init(ObjectClass *oc, void *data) > { > UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); > diff --git a/net/colo-compare.h b/net/colo-compare.h > index 22ddd512e2..1fa026c85e 100644 > --- a/net/colo-compare.h > +++ b/net/colo-compare.h > @@ -20,5 +20,7 @@ > void colo_notify_compares_event(void *opaque, int event, Error **errp); > void colo_compare_register_notifier(Notifier *notify); > void colo_compare_unregister_notifier(Notifier *notify); > +void colo_compare_passthrough_add(bool is_tcp, const uint16_t port); > +void colo_compare_passthrough_del(bool is_tcp, const uint16_t port); > > #endif /* QEMU_COLO_COMPARE_H */ > diff --git a/net/net.c b/net/net.c > index eac7a92618..1f303e8309 100644 > --- a/net/net.c > +++ b/net/net.c > @@ -55,6 +55,7 @@ > #include "sysemu/sysemu.h" > #include "net/filter.h" > #include "qapi/string-output-visitor.h" > +#include "net/colo-compare.h" > > /* Net bridge is currently not supported for W32. */ > #if !defined(_WIN32) > @@ -1155,12 +1156,38 @@ void qmp_colo_passthrough_add(const char *prot, const uint32_t port, > Error **errp) > { > /* Setup passthrough connection */ > + if (port > 65536) { > + error_setg(errp, "COLO pass through get wrong port"); > + return; > + } > + > + if (!strcmp(prot, "tcp") || !strcmp(prot, "TCP")) { > + colo_compare_passthrough_add(true, (uint16_t)port); > + } else if (!strcmp(prot, "udp") || !strcmp(prot, "UDP")) { > + colo_compare_passthrough_add(false, (uint16_t)port); > + } else { > + error_setg(errp, "COLO pass through just support tcp or udp protocol"); > + return; > + } > } > > void qmp_colo_passthrough_del(const char *prot, const uint32_t port, > Error **errp) > { > /* Delete passthrough connection */ > + if (port > 65536) { > + error_setg(errp, "COLO pass through get wrong port"); > + return; > + } > + > + if (!strcmp(prot, "tcp") || !strcmp(prot, "TCP")) { > + colo_compare_passthrough_del(true, (uint16_t)port); > + } else if (!strcmp(prot, "udp") || !strcmp(prot, "UDP")) { > + colo_compare_passthrough_del(false, (uint16_t)port); > + } else { > + error_setg(errp, "COLO pass through just support tcp or udp protocol"); > + return; > + } > } > > static void netfilter_print_info(Monitor *mon, NetFilterState *nf) --