summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-03-06 15:13:23 +0000
committerPeter Maydell <peter.maydell@linaro.org>2017-03-06 15:13:23 +0000
commiteba44e9339fc13c36e24c8c59e2b73ea231b46a1 (patch)
tree738208c7e3504fc23aaf4ae80ab549943d5a47f9
parent56b51708e9e22809d2a78f38d0ac84bb3f3fca92 (diff)
parentf0aabd5c4ae11fde704d138e8f06c69e5c902a16 (diff)
downloadfocaccia-qemu-eba44e9339fc13c36e24c8c59e2b73ea231b46a1.tar.gz
focaccia-qemu-eba44e9339fc13c36e24c8c59e2b73ea231b46a1.zip
Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging
# gpg: Signature made Mon 06 Mar 2017 04:15:17 GMT
# gpg:                using RSA key 0xEF04965B398D6211
# gpg: Good signature from "Jason Wang (Jason Wang on RedHat) <jasowang@redhat.com>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 215D 46F4 8246 689E C77F  3562 EF04 965B 398D 6211

* remotes/jasowang/tags/net-pull-request:
  net/filter-mirror: Follow CODING_STYLE
  COLO-compare: Fix icmp and udp compare different packet always dump bug
  COLO-compare: Optimize compare_common and compare_tcp
  COLO-compare: Rename compare function and remove duplicate codes
  filter-rewriter: skip net_checksum_calculate() while offset = 0
  net/colo: fix memory double free error
  vmxnet3: VMStatify rx/tx q_descr and int_state
  vmxnet3: Convert ring values to uint32_t's
  net/colo-compare: Fix memory free error
  colo-compare: Fix removing fds been watched incorrectly in finalization
  char: remove the right fd been watched in qemu_chr_fe_set_handlers()
  colo-compare: kick compare thread to exit after some cleanup in finalization
  colo-compare: use g_timeout_source_new() to process the stale packets
  NetRxPkt: Remove code duplication in net_rx_pkt_pull_data()
  NetRxPkt: Account buffer with ETH header in IOV length
  NetRxPkt: Do not try to pull more data than present
  NetRxPkt: Fix memory corruption on VLAN header stripping
  eth: Extend vlan stripping functions
  net: Remove useless local var pkt

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--chardev/char-fd.c6
-rw-r--r--chardev/char-io.c8
-rw-r--r--chardev/char-io.h2
-rw-r--r--chardev/char-pty.c2
-rw-r--r--chardev/char-socket.c4
-rw-r--r--chardev/char-udp.c6
-rw-r--r--chardev/char.c2
-rw-r--r--hw/net/net_rx_pkt.c41
-rw-r--r--hw/net/vmxnet3.c284
-rw-r--r--include/net/eth.h4
-rw-r--r--net/colo-compare.c189
-rw-r--r--net/colo.c4
-rw-r--r--net/eth.c25
-rw-r--r--net/filter-mirror.c7
-rw-r--r--net/filter-rewriter.c17
15 files changed, 273 insertions, 328 deletions
diff --git a/chardev/char-fd.c b/chardev/char-fd.c
index fb51ab4234..548dd4cdd9 100644
--- a/chardev/char-fd.c
+++ b/chardev/char-fd.c
@@ -58,7 +58,7 @@ static gboolean fd_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
     ret = qio_channel_read(
         chan, (gchar *)buf, len, NULL);
     if (ret == 0) {
-        remove_fd_in_watch(chr);
+        remove_fd_in_watch(chr, NULL);
         qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
         return FALSE;
     }
@@ -89,7 +89,7 @@ static void fd_chr_update_read_handler(Chardev *chr,
 {
     FDChardev *s = FD_CHARDEV(chr);
 
-    remove_fd_in_watch(chr);
+    remove_fd_in_watch(chr, NULL);
     if (s->ioc_in) {
         chr->fd_in_tag = io_add_watch_poll(chr, s->ioc_in,
                                            fd_chr_read_poll,
@@ -103,7 +103,7 @@ static void char_fd_finalize(Object *obj)
     Chardev *chr = CHARDEV(obj);
     FDChardev *s = FD_CHARDEV(obj);
 
-    remove_fd_in_watch(chr);
+    remove_fd_in_watch(chr, NULL);
     if (s->ioc_in) {
         object_unref(OBJECT(s->ioc_in));
     }
diff --git a/chardev/char-io.c b/chardev/char-io.c
index 7dfc3f22ba..b4bb094ea3 100644
--- a/chardev/char-io.c
+++ b/chardev/char-io.c
@@ -127,14 +127,14 @@ guint io_add_watch_poll(Chardev *chr,
     return tag;
 }
 
-static void io_remove_watch_poll(guint tag)
+static void io_remove_watch_poll(guint tag, GMainContext *context)
 {
     GSource *source;
     IOWatchPoll *iwp;
 
     g_return_if_fail(tag > 0);
 
-    source = g_main_context_find_source_by_id(NULL, tag);
+    source = g_main_context_find_source_by_id(context, tag);
     g_return_if_fail(source != NULL);
 
     iwp = io_watch_poll_from_source(source);
@@ -146,10 +146,10 @@ static void io_remove_watch_poll(guint tag)
     g_source_destroy(&iwp->parent);
 }
 
-void remove_fd_in_watch(Chardev *chr)
+void remove_fd_in_watch(Chardev *chr, GMainContext *context)
 {
     if (chr->fd_in_tag) {
-        io_remove_watch_poll(chr->fd_in_tag);
+        io_remove_watch_poll(chr->fd_in_tag, context);
         chr->fd_in_tag = 0;
     }
 }
diff --git a/chardev/char-io.h b/chardev/char-io.h
index d7ae5f1585..842be56bda 100644
--- a/chardev/char-io.h
+++ b/chardev/char-io.h
@@ -36,7 +36,7 @@ guint io_add_watch_poll(Chardev *chr,
                         gpointer user_data,
                         GMainContext *context);
 
-void remove_fd_in_watch(Chardev *chr);
+void remove_fd_in_watch(Chardev *chr, GMainContext *context);
 
 int io_channel_send(QIOChannel *ioc, const void *buf, size_t len);
 
diff --git a/chardev/char-pty.c b/chardev/char-pty.c
index ecf2c7a5c4..a6337be8aa 100644
--- a/chardev/char-pty.c
+++ b/chardev/char-pty.c
@@ -199,7 +199,7 @@ static void pty_chr_state(Chardev *chr, int connected)
             g_source_remove(s->open_tag);
             s->open_tag = 0;
         }
-        remove_fd_in_watch(chr);
+        remove_fd_in_watch(chr, NULL);
         s->connected = 0;
         /* (re-)connect poll interval for idle guests: once per second.
          * We check more frequently in case the guests sends data to
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 865c52762e..d7e92e1bd3 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -328,7 +328,7 @@ static void tcp_chr_free_connection(Chardev *chr)
     }
 
     tcp_set_msgfds(chr, NULL, 0);
-    remove_fd_in_watch(chr);
+    remove_fd_in_watch(chr, NULL);
     object_unref(OBJECT(s->sioc));
     s->sioc = NULL;
     object_unref(OBJECT(s->ioc));
@@ -498,7 +498,7 @@ static void tcp_chr_update_read_handler(Chardev *chr,
         return;
     }
 
-    remove_fd_in_watch(chr);
+    remove_fd_in_watch(chr, NULL);
     if (s->ioc) {
         chr->fd_in_tag = io_add_watch_poll(chr, s->ioc,
                                            tcp_chr_read_poll,
diff --git a/chardev/char-udp.c b/chardev/char-udp.c
index 2c6c7ddd73..804bd22efa 100644
--- a/chardev/char-udp.c
+++ b/chardev/char-udp.c
@@ -81,7 +81,7 @@ static gboolean udp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
     ret = qio_channel_read(
         s->ioc, (char *)s->buf, sizeof(s->buf), NULL);
     if (ret <= 0) {
-        remove_fd_in_watch(chr);
+        remove_fd_in_watch(chr, NULL);
         return FALSE;
     }
     s->bufcnt = ret;
@@ -101,7 +101,7 @@ static void udp_chr_update_read_handler(Chardev *chr,
 {
     UdpChardev *s = UDP_CHARDEV(chr);
 
-    remove_fd_in_watch(chr);
+    remove_fd_in_watch(chr, NULL);
     if (s->ioc) {
         chr->fd_in_tag = io_add_watch_poll(chr, s->ioc,
                                            udp_chr_read_poll,
@@ -115,7 +115,7 @@ static void char_udp_finalize(Object *obj)
     Chardev *chr = CHARDEV(obj);
     UdpChardev *s = UDP_CHARDEV(obj);
 
-    remove_fd_in_watch(chr);
+    remove_fd_in_watch(chr, NULL);
     if (s->ioc) {
         object_unref(OBJECT(s->ioc));
     }
diff --git a/chardev/char.c b/chardev/char.c
index 54cd5f4081..3df116350b 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -560,7 +560,7 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
     cc = CHARDEV_GET_CLASS(s);
     if (!opaque && !fd_can_read && !fd_read && !fd_event) {
         fe_open = 0;
-        remove_fd_in_watch(s);
+        remove_fd_in_watch(s, context);
     } else {
         fe_open = 1;
     }
diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c
index 1019b50c18..cef1c2e0d1 100644
--- a/hw/net/net_rx_pkt.c
+++ b/hw/net/net_rx_pkt.c
@@ -23,13 +23,13 @@
 
 struct NetRxPkt {
     struct virtio_net_hdr virt_hdr;
-    uint8_t ehdr_buf[sizeof(struct eth_header)];
+    uint8_t ehdr_buf[sizeof(struct eth_header) + sizeof(struct vlan_header)];
     struct iovec *vec;
     uint16_t vec_len_total;
     uint16_t vec_len;
     uint32_t tot_len;
     uint16_t tci;
-    bool vlan_stripped;
+    size_t ehdr_buf_len;
     bool has_virt_hdr;
     eth_pkt_types_e packet_type;
 
@@ -88,21 +88,21 @@ net_rx_pkt_pull_data(struct NetRxPkt *pkt,
                         const struct iovec *iov, int iovcnt,
                         size_t ploff)
 {
-    if (pkt->vlan_stripped) {
+    uint32_t pllen = iov_size(iov, iovcnt) - ploff;
+
+    if (pkt->ehdr_buf_len) {
         net_rx_pkt_iovec_realloc(pkt, iovcnt + 1);
 
         pkt->vec[0].iov_base = pkt->ehdr_buf;
-        pkt->vec[0].iov_len = sizeof(pkt->ehdr_buf);
-
-        pkt->tot_len =
-            iov_size(iov, iovcnt) - ploff + sizeof(struct eth_header);
+        pkt->vec[0].iov_len = pkt->ehdr_buf_len;
 
+        pkt->tot_len = pllen + pkt->ehdr_buf_len;
         pkt->vec_len = iov_copy(pkt->vec + 1, pkt->vec_len_total - 1,
-                                iov, iovcnt, ploff, pkt->tot_len);
+                                iov, iovcnt, ploff, pllen) + 1;
     } else {
         net_rx_pkt_iovec_realloc(pkt, iovcnt);
 
-        pkt->tot_len = iov_size(iov, iovcnt) - ploff;
+        pkt->tot_len = pllen;
         pkt->vec_len = iov_copy(pkt->vec, pkt->vec_len_total,
                                 iov, iovcnt, ploff, pkt->tot_len);
     }
@@ -123,11 +123,12 @@ void net_rx_pkt_attach_iovec(struct NetRxPkt *pkt,
     uint16_t tci = 0;
     uint16_t ploff = iovoff;
     assert(pkt);
-    pkt->vlan_stripped = false;
 
     if (strip_vlan) {
-        pkt->vlan_stripped = eth_strip_vlan(iov, iovcnt, iovoff, pkt->ehdr_buf,
-                                            &ploff, &tci);
+        pkt->ehdr_buf_len = eth_strip_vlan(iov, iovcnt, iovoff, pkt->ehdr_buf,
+                                           &ploff, &tci);
+    } else {
+        pkt->ehdr_buf_len = 0;
     }
 
     pkt->tci = tci;
@@ -143,12 +144,13 @@ void net_rx_pkt_attach_iovec_ex(struct NetRxPkt *pkt,
     uint16_t tci = 0;
     uint16_t ploff = iovoff;
     assert(pkt);
-    pkt->vlan_stripped = false;
 
     if (strip_vlan) {
-        pkt->vlan_stripped = eth_strip_vlan_ex(iov, iovcnt, iovoff, vet,
-                                               pkt->ehdr_buf,
-                                               &ploff, &tci);
+        pkt->ehdr_buf_len = eth_strip_vlan_ex(iov, iovcnt, iovoff, vet,
+                                              pkt->ehdr_buf,
+                                              &ploff, &tci);
+    } else {
+        pkt->ehdr_buf_len = 0;
     }
 
     pkt->tci = tci;
@@ -159,11 +161,10 @@ void net_rx_pkt_attach_iovec_ex(struct NetRxPkt *pkt,
 void net_rx_pkt_dump(struct NetRxPkt *pkt)
 {
 #ifdef NET_RX_PKT_DEBUG
-    NetRxPkt *pkt = (NetRxPkt *)pkt;
     assert(pkt);
 
-    printf("RX PKT: tot_len: %d, vlan_stripped: %d, vlan_tag: %d\n",
-              pkt->tot_len, pkt->vlan_stripped, pkt->tci);
+    printf("RX PKT: tot_len: %d, ehdr_buf_len: %lu, vlan_tag: %d\n",
+              pkt->tot_len, pkt->ehdr_buf_len, pkt->tci);
 #endif
 }
 
@@ -426,7 +427,7 @@ bool net_rx_pkt_is_vlan_stripped(struct NetRxPkt *pkt)
 {
     assert(pkt);
 
-    return pkt->vlan_stripped;
+    return pkt->ehdr_buf_len ? true : false;
 }
 
 bool net_rx_pkt_has_virt_hdr(struct NetRxPkt *pkt)
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index e13a798b3b..8b1fab24fd 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -141,17 +141,17 @@ typedef struct VMXNET3Class {
 /* Cyclic ring abstraction */
 typedef struct {
     hwaddr pa;
-    size_t size;
-    size_t cell_size;
-    size_t next;
+    uint32_t size;
+    uint32_t cell_size;
+    uint32_t next;
     uint8_t gen;
 } Vmxnet3Ring;
 
 static inline void vmxnet3_ring_init(PCIDevice *d,
 				     Vmxnet3Ring *ring,
                                      hwaddr pa,
-                                     size_t size,
-                                     size_t cell_size,
+                                     uint32_t size,
+                                     uint32_t cell_size,
                                      bool zero_region)
 {
     ring->pa = pa;
@@ -166,7 +166,7 @@ static inline void vmxnet3_ring_init(PCIDevice *d,
 }
 
 #define VMXNET3_RING_DUMP(macro, ring_name, ridx, r)                         \
-    macro("%s#%d: base %" PRIx64 " size %zu cell_size %zu gen %d next %zu",  \
+    macro("%s#%d: base %" PRIx64 " size %u cell_size %u gen %d next %u",  \
           (ring_name), (ridx),                                               \
           (r)->pa, (r)->size, (r)->cell_size, (r)->gen, (r)->next)
 
@@ -2403,155 +2403,87 @@ static const VMStateDescription vmxstate_vmxnet3_mcast_list = {
     }
 };
 
-static void vmxnet3_get_ring_from_file(QEMUFile *f, Vmxnet3Ring *r)
-{
-    r->pa = qemu_get_be64(f);
-    r->size = qemu_get_be32(f);
-    r->cell_size = qemu_get_be32(f);
-    r->next = qemu_get_be32(f);
-    r->gen = qemu_get_byte(f);
-}
-
-static void vmxnet3_put_ring_to_file(QEMUFile *f, Vmxnet3Ring *r)
-{
-    qemu_put_be64(f, r->pa);
-    qemu_put_be32(f, r->size);
-    qemu_put_be32(f, r->cell_size);
-    qemu_put_be32(f, r->next);
-    qemu_put_byte(f, r->gen);
-}
-
-static void vmxnet3_get_tx_stats_from_file(QEMUFile *f,
-    struct UPT1_TxStats *tx_stat)
-{
-    tx_stat->TSOPktsTxOK = qemu_get_be64(f);
-    tx_stat->TSOBytesTxOK = qemu_get_be64(f);
-    tx_stat->ucastPktsTxOK = qemu_get_be64(f);
-    tx_stat->ucastBytesTxOK = qemu_get_be64(f);
-    tx_stat->mcastPktsTxOK = qemu_get_be64(f);
-    tx_stat->mcastBytesTxOK = qemu_get_be64(f);
-    tx_stat->bcastPktsTxOK = qemu_get_be64(f);
-    tx_stat->bcastBytesTxOK = qemu_get_be64(f);
-    tx_stat->pktsTxError = qemu_get_be64(f);
-    tx_stat->pktsTxDiscard = qemu_get_be64(f);
-}
-
-static void vmxnet3_put_tx_stats_to_file(QEMUFile *f,
-    struct UPT1_TxStats *tx_stat)
-{
-    qemu_put_be64(f, tx_stat->TSOPktsTxOK);
-    qemu_put_be64(f, tx_stat->TSOBytesTxOK);
-    qemu_put_be64(f, tx_stat->ucastPktsTxOK);
-    qemu_put_be64(f, tx_stat->ucastBytesTxOK);
-    qemu_put_be64(f, tx_stat->mcastPktsTxOK);
-    qemu_put_be64(f, tx_stat->mcastBytesTxOK);
-    qemu_put_be64(f, tx_stat->bcastPktsTxOK);
-    qemu_put_be64(f, tx_stat->bcastBytesTxOK);
-    qemu_put_be64(f, tx_stat->pktsTxError);
-    qemu_put_be64(f, tx_stat->pktsTxDiscard);
-}
-
-static int vmxnet3_get_txq_descr(QEMUFile *f, void *pv, size_t size,
-    VMStateField *field)
-{
-    Vmxnet3TxqDescr *r = pv;
-
-    vmxnet3_get_ring_from_file(f, &r->tx_ring);
-    vmxnet3_get_ring_from_file(f, &r->comp_ring);
-    r->intr_idx = qemu_get_byte(f);
-    r->tx_stats_pa = qemu_get_be64(f);
-
-    vmxnet3_get_tx_stats_from_file(f, &r->txq_stats);
-
-    return 0;
-}
-
-static int vmxnet3_put_txq_descr(QEMUFile *f, void *pv, size_t size,
-                                 VMStateField *field, QJSON *vmdesc)
-{
-    Vmxnet3TxqDescr *r = pv;
-
-    vmxnet3_put_ring_to_file(f, &r->tx_ring);
-    vmxnet3_put_ring_to_file(f, &r->comp_ring);
-    qemu_put_byte(f, r->intr_idx);
-    qemu_put_be64(f, r->tx_stats_pa);
-    vmxnet3_put_tx_stats_to_file(f, &r->txq_stats);
-
-    return 0;
-}
-
-static const VMStateInfo txq_descr_info = {
-    .name = "txq_descr",
-    .get = vmxnet3_get_txq_descr,
-    .put = vmxnet3_put_txq_descr
+static const VMStateDescription vmstate_vmxnet3_ring = {
+    .name = "vmxnet3-ring",
+    .version_id = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64(pa, Vmxnet3Ring),
+        VMSTATE_UINT32(size, Vmxnet3Ring),
+        VMSTATE_UINT32(cell_size, Vmxnet3Ring),
+        VMSTATE_UINT32(next, Vmxnet3Ring),
+        VMSTATE_UINT8(gen, Vmxnet3Ring),
+        VMSTATE_END_OF_LIST()
+    }
 };
 
-static void vmxnet3_get_rx_stats_from_file(QEMUFile *f,
-    struct UPT1_RxStats *rx_stat)
-{
-    rx_stat->LROPktsRxOK = qemu_get_be64(f);
-    rx_stat->LROBytesRxOK = qemu_get_be64(f);
-    rx_stat->ucastPktsRxOK = qemu_get_be64(f);
-    rx_stat->ucastBytesRxOK = qemu_get_be64(f);
-    rx_stat->mcastPktsRxOK = qemu_get_be64(f);
-    rx_stat->mcastBytesRxOK = qemu_get_be64(f);
-    rx_stat->bcastPktsRxOK = qemu_get_be64(f);
-    rx_stat->bcastBytesRxOK = qemu_get_be64(f);
-    rx_stat->pktsRxOutOfBuf = qemu_get_be64(f);
-    rx_stat->pktsRxError = qemu_get_be64(f);
-}
-
-static void vmxnet3_put_rx_stats_to_file(QEMUFile *f,
-    struct UPT1_RxStats *rx_stat)
-{
-    qemu_put_be64(f, rx_stat->LROPktsRxOK);
-    qemu_put_be64(f, rx_stat->LROBytesRxOK);
-    qemu_put_be64(f, rx_stat->ucastPktsRxOK);
-    qemu_put_be64(f, rx_stat->ucastBytesRxOK);
-    qemu_put_be64(f, rx_stat->mcastPktsRxOK);
-    qemu_put_be64(f, rx_stat->mcastBytesRxOK);
-    qemu_put_be64(f, rx_stat->bcastPktsRxOK);
-    qemu_put_be64(f, rx_stat->bcastBytesRxOK);
-    qemu_put_be64(f, rx_stat->pktsRxOutOfBuf);
-    qemu_put_be64(f, rx_stat->pktsRxError);
-}
-
-static int vmxnet3_get_rxq_descr(QEMUFile *f, void *pv, size_t size,
-    VMStateField *field)
-{
-    Vmxnet3RxqDescr *r = pv;
-    int i;
-
-    for (i = 0; i < VMXNET3_RX_RINGS_PER_QUEUE; i++) {
-        vmxnet3_get_ring_from_file(f, &r->rx_ring[i]);
+static const VMStateDescription vmstate_vmxnet3_tx_stats = {
+    .name = "vmxnet3-tx-stats",
+    .version_id = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64(TSOPktsTxOK, struct UPT1_TxStats),
+        VMSTATE_UINT64(TSOBytesTxOK, struct UPT1_TxStats),
+        VMSTATE_UINT64(ucastPktsTxOK, struct UPT1_TxStats),
+        VMSTATE_UINT64(ucastBytesTxOK, struct UPT1_TxStats),
+        VMSTATE_UINT64(mcastPktsTxOK, struct UPT1_TxStats),
+        VMSTATE_UINT64(mcastBytesTxOK, struct UPT1_TxStats),
+        VMSTATE_UINT64(bcastPktsTxOK, struct UPT1_TxStats),
+        VMSTATE_UINT64(bcastBytesTxOK, struct UPT1_TxStats),
+        VMSTATE_UINT64(pktsTxError, struct UPT1_TxStats),
+        VMSTATE_UINT64(pktsTxDiscard, struct UPT1_TxStats),
+        VMSTATE_END_OF_LIST()
     }
+};
 
-    vmxnet3_get_ring_from_file(f, &r->comp_ring);
-    r->intr_idx = qemu_get_byte(f);
-    r->rx_stats_pa = qemu_get_be64(f);
-
-    vmxnet3_get_rx_stats_from_file(f, &r->rxq_stats);
-
-    return 0;
-}
-
-static int vmxnet3_put_rxq_descr(QEMUFile *f, void *pv, size_t size,
-                                 VMStateField *field, QJSON *vmdesc)
-{
-    Vmxnet3RxqDescr *r = pv;
-    int i;
-
-    for (i = 0; i < VMXNET3_RX_RINGS_PER_QUEUE; i++) {
-        vmxnet3_put_ring_to_file(f, &r->rx_ring[i]);
+static const VMStateDescription vmstate_vmxnet3_txq_descr = {
+    .name = "vmxnet3-txq-descr",
+    .version_id = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT(tx_ring, Vmxnet3TxqDescr, 0, vmstate_vmxnet3_ring,
+                       Vmxnet3Ring),
+        VMSTATE_STRUCT(comp_ring, Vmxnet3TxqDescr, 0, vmstate_vmxnet3_ring,
+                       Vmxnet3Ring),
+        VMSTATE_UINT8(intr_idx, Vmxnet3TxqDescr),
+        VMSTATE_UINT64(tx_stats_pa, Vmxnet3TxqDescr),
+        VMSTATE_STRUCT(txq_stats, Vmxnet3TxqDescr, 0, vmstate_vmxnet3_tx_stats,
+                       struct UPT1_TxStats),
+        VMSTATE_END_OF_LIST()
     }
+};
 
-    vmxnet3_put_ring_to_file(f, &r->comp_ring);
-    qemu_put_byte(f, r->intr_idx);
-    qemu_put_be64(f, r->rx_stats_pa);
-    vmxnet3_put_rx_stats_to_file(f, &r->rxq_stats);
+static const VMStateDescription vmstate_vmxnet3_rx_stats = {
+    .name = "vmxnet3-rx-stats",
+    .version_id = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64(LROPktsRxOK, struct UPT1_RxStats),
+        VMSTATE_UINT64(LROBytesRxOK, struct UPT1_RxStats),
+        VMSTATE_UINT64(ucastPktsRxOK, struct UPT1_RxStats),
+        VMSTATE_UINT64(ucastBytesRxOK, struct UPT1_RxStats),
+        VMSTATE_UINT64(mcastPktsRxOK, struct UPT1_RxStats),
+        VMSTATE_UINT64(mcastBytesRxOK, struct UPT1_RxStats),
+        VMSTATE_UINT64(bcastPktsRxOK, struct UPT1_RxStats),
+        VMSTATE_UINT64(bcastBytesRxOK, struct UPT1_RxStats),
+        VMSTATE_UINT64(pktsRxOutOfBuf, struct UPT1_RxStats),
+        VMSTATE_UINT64(pktsRxError, struct UPT1_RxStats),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
-    return 0;
-}
+static const VMStateDescription vmstate_vmxnet3_rxq_descr = {
+    .name = "vmxnet3-rxq-descr",
+    .version_id = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT_ARRAY(rx_ring, Vmxnet3RxqDescr,
+                             VMXNET3_RX_RINGS_PER_QUEUE, 0,
+                             vmstate_vmxnet3_ring, Vmxnet3Ring),
+        VMSTATE_STRUCT(comp_ring, Vmxnet3RxqDescr, 0, vmstate_vmxnet3_ring,
+                       Vmxnet3Ring),
+        VMSTATE_UINT8(intr_idx, Vmxnet3RxqDescr),
+        VMSTATE_UINT64(rx_stats_pa, Vmxnet3RxqDescr),
+        VMSTATE_STRUCT(rxq_stats, Vmxnet3RxqDescr, 0, vmstate_vmxnet3_rx_stats,
+                       struct UPT1_RxStats),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static int vmxnet3_post_load(void *opaque, int version_id)
 {
@@ -2577,40 +2509,15 @@ static int vmxnet3_post_load(void *opaque, int version_id)
     return 0;
 }
 
-static const VMStateInfo rxq_descr_info = {
-    .name = "rxq_descr",
-    .get = vmxnet3_get_rxq_descr,
-    .put = vmxnet3_put_rxq_descr
-};
-
-static int vmxnet3_get_int_state(QEMUFile *f, void *pv, size_t size,
-    VMStateField *field)
-{
-    Vmxnet3IntState *r = pv;
-
-    r->is_masked = qemu_get_byte(f);
-    r->is_pending = qemu_get_byte(f);
-    r->is_asserted = qemu_get_byte(f);
-
-    return 0;
-}
-
-static int vmxnet3_put_int_state(QEMUFile *f, void *pv, size_t size,
-                                 VMStateField *field, QJSON *vmdesc)
-{
-    Vmxnet3IntState *r = pv;
-
-    qemu_put_byte(f, r->is_masked);
-    qemu_put_byte(f, r->is_pending);
-    qemu_put_byte(f, r->is_asserted);
-
-    return 0;
-}
-
-static const VMStateInfo int_state_info = {
-    .name = "int_state",
-    .get = vmxnet3_get_int_state,
-    .put = vmxnet3_put_int_state
+static const VMStateDescription vmstate_vmxnet3_int_state = {
+    .name = "vmxnet3-int-state",
+    .version_id = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_BOOL(is_masked, Vmxnet3IntState),
+        VMSTATE_BOOL(is_pending, Vmxnet3IntState),
+        VMSTATE_BOOL(is_asserted, Vmxnet3IntState),
+        VMSTATE_END_OF_LIST()
+    }
 };
 
 static bool vmxnet3_vmstate_need_pcie_device(void *opaque)
@@ -2667,14 +2574,15 @@ static const VMStateDescription vmstate_vmxnet3 = {
             VMSTATE_UINT64(drv_shmem, VMXNET3State),
             VMSTATE_UINT64(temp_shared_guest_driver_memory, VMXNET3State),
 
-            VMSTATE_ARRAY(txq_descr, VMXNET3State,
-                VMXNET3_DEVICE_MAX_TX_QUEUES, 0, txq_descr_info,
+            VMSTATE_STRUCT_ARRAY(txq_descr, VMXNET3State,
+                VMXNET3_DEVICE_MAX_TX_QUEUES, 0, vmstate_vmxnet3_txq_descr,
                 Vmxnet3TxqDescr),
-            VMSTATE_ARRAY(rxq_descr, VMXNET3State,
-                VMXNET3_DEVICE_MAX_RX_QUEUES, 0, rxq_descr_info,
+            VMSTATE_STRUCT_ARRAY(rxq_descr, VMXNET3State,
+                VMXNET3_DEVICE_MAX_RX_QUEUES, 0, vmstate_vmxnet3_rxq_descr,
                 Vmxnet3RxqDescr),
-            VMSTATE_ARRAY(interrupt_states, VMXNET3State, VMXNET3_MAX_INTRS,
-                0, int_state_info, Vmxnet3IntState),
+            VMSTATE_STRUCT_ARRAY(interrupt_states, VMXNET3State,
+                VMXNET3_MAX_INTRS, 0, vmstate_vmxnet3_int_state,
+                Vmxnet3IntState),
 
             VMSTATE_END_OF_LIST()
     },
diff --git a/include/net/eth.h b/include/net/eth.h
index 2013175857..afeb45be34 100644
--- a/include/net/eth.h
+++ b/include/net/eth.h
@@ -331,12 +331,12 @@ eth_get_pkt_tci(const void *p)
     }
 }
 
-bool
+size_t
 eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
                uint8_t *new_ehdr_buf,
                uint16_t *payload_offset, uint16_t *tci);
 
-bool
+size_t
 eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
                   uint16_t vet, uint8_t *new_ehdr_buf,
                   uint16_t *payload_offset, uint16_t *tci);
diff --git a/net/colo-compare.c b/net/colo-compare.c
index 162fd6a570..282727b28a 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -83,9 +83,9 @@ typedef struct CompareState {
     GHashTable *connection_track_table;
     /* 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;
+
+    GMainContext *worker_context;
+    GMainLoop *compare_loop;
 } CompareState;
 
 typedef struct CompareClass {
@@ -180,7 +180,7 @@ static int packet_enqueue(CompareState *s, int mode)
  * return:    0  means packet same
  *            > 0 || < 0 means packet different
  */
-static int colo_packet_compare(Packet *ppkt, Packet *spkt)
+static int colo_packet_compare_common(Packet *ppkt, Packet *spkt, int offset)
 {
     trace_colo_compare_ip_info(ppkt->size, inet_ntoa(ppkt->ip->ip_src),
                                inet_ntoa(ppkt->ip->ip_dst), spkt->size,
@@ -188,8 +188,10 @@ static int colo_packet_compare(Packet *ppkt, Packet *spkt)
                                inet_ntoa(spkt->ip->ip_dst));
 
     if (ppkt->size == spkt->size) {
-        return memcmp(ppkt->data, spkt->data, spkt->size);
+        return memcmp(ppkt->data + offset, spkt->data + offset,
+                      spkt->size - offset);
     } else {
+        trace_colo_compare_main("Net packet size are not the same");
         return -1;
     }
 }
@@ -205,12 +207,6 @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
     int res;
 
     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;
@@ -229,8 +225,11 @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
         spkt->ip->ip_sum = ppkt->ip->ip_sum;
     }
 
-    res = memcmp(ppkt->data + ETH_HLEN, spkt->data + ETH_HLEN,
-                (spkt->size - ETH_HLEN));
+    if (ptcp->th_sum == stcp->th_sum) {
+        res = colo_packet_compare_common(ppkt, spkt, ETH_HLEN);
+    } else {
+        res = -1;
+    }
 
     if (res != 0 && trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) {
         trace_colo_compare_pkt_info_src(inet_ntoa(ppkt->ip->ip_src),
@@ -261,15 +260,32 @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
 static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
 {
     int ret;
+    int network_header_length = ppkt->ip->ip_hl * 4;
 
     trace_colo_compare_main("compare udp");
-    ret = colo_packet_compare(ppkt, spkt);
+
+    /*
+     * Because of ppkt and spkt are both in the same connection,
+     * The ppkt's src ip, dst ip, src port, dst port, ip_proto all are
+     * same with spkt. In addition, IP header's Identification is a random
+     * field, we can handle it in IP fragmentation function later.
+     * COLO just concern the response net packet payload from primary guest
+     * and secondary guest are same or not, So we ignored all IP header include
+     * other field like TOS,TTL,IP Checksum. we only need to compare
+     * the ip payload here.
+     */
+    ret = colo_packet_compare_common(ppkt, spkt,
+                                     network_header_length + ETH_HLEN);
 
     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);
+        if (trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) {
+            qemu_hexdump((char *)ppkt->data, stderr, "colo-compare pri pkt",
+                         ppkt->size);
+            qemu_hexdump((char *)spkt->data, stderr, "colo-compare sec pkt",
+                         spkt->size);
+        }
     }
 
     return ret;
@@ -281,24 +297,32 @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
  */
 static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
 {
-    int network_length;
+    int network_header_length = ppkt->ip->ip_hl * 4;
 
     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)) {
+    /*
+     * Because of ppkt and spkt are both in the same connection,
+     * The ppkt's src ip, dst ip, src port, dst port, ip_proto all are
+     * same with spkt. In addition, IP header's Identification is a random
+     * field, we can handle it in IP fragmentation function later.
+     * COLO just concern the response net packet payload from primary guest
+     * and secondary guest are same or not, So we ignored all IP header include
+     * other field like TOS,TTL,IP Checksum. we only need to compare
+     * the ip payload here.
+     */
+    if (colo_packet_compare_common(ppkt, spkt,
+                                   network_header_length + ETH_HLEN)) {
         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);
+        if (trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) {
+            qemu_hexdump((char *)ppkt->data, stderr, "colo-compare pri pkt",
+                         ppkt->size);
+            qemu_hexdump((char *)spkt->data, stderr, "colo-compare sec pkt",
+                         spkt->size);
+        }
         return -1;
     } else {
         return 0;
@@ -316,7 +340,7 @@ static int colo_packet_compare_other(Packet *spkt, Packet *ppkt)
                                inet_ntoa(ppkt->ip->ip_dst), spkt->size,
                                inet_ntoa(spkt->ip->ip_src),
                                inet_ntoa(spkt->ip->ip_dst));
-    return colo_packet_compare(ppkt, spkt);
+    return colo_packet_compare_common(ppkt, spkt, 0);
 }
 
 static int colo_old_packet_check_one(Packet *pkt, int64_t *check_time)
@@ -374,9 +398,7 @@ static void colo_compare_connection(void *opaque, void *user_data)
 
     while (!g_queue_is_empty(&conn->primary_list) &&
            !g_queue_is_empty(&conn->secondary_list)) {
-        qemu_mutex_lock(&s->timer_check_lock);
         pkt = g_queue_pop_tail(&conn->primary_list);
-        qemu_mutex_unlock(&s->timer_check_lock);
         switch (conn->ip_proto) {
         case IPPROTO_TCP:
             result = g_queue_find_custom(&conn->secondary_list,
@@ -411,9 +433,7 @@ static void colo_compare_connection(void *opaque, void *user_data)
              * 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;
         }
@@ -486,25 +506,45 @@ static void compare_sec_chr_in(void *opaque, const uint8_t *buf, int size)
     }
 }
 
+/*
+ * Check old packet regularly so it can watch for any packets
+ * that the secondary hasn't produced equivalents of.
+ */
+static gboolean check_old_packet_regular(void *opaque)
+{
+    CompareState *s = opaque;
+
+    /* if have old packet we will notify checkpoint */
+    colo_old_packet_check(s);
+
+    return TRUE;
+}
+
 static void *colo_compare_thread(void *opaque)
 {
-    GMainContext *worker_context;
-    GMainLoop *compare_loop;
     CompareState *s = opaque;
+    GSource *timeout_source;
 
-    worker_context = g_main_context_new();
+    s->worker_context = g_main_context_new();
 
     qemu_chr_fe_set_handlers(&s->chr_pri_in, compare_chr_can_read,
-                             compare_pri_chr_in, NULL, s, worker_context, true);
+                          compare_pri_chr_in, NULL, s, s->worker_context, true);
     qemu_chr_fe_set_handlers(&s->chr_sec_in, compare_chr_can_read,
-                             compare_sec_chr_in, NULL, s, worker_context, true);
+                          compare_sec_chr_in, NULL, s, s->worker_context, true);
+
+    s->compare_loop = g_main_loop_new(s->worker_context, FALSE);
 
-    compare_loop = g_main_loop_new(worker_context, FALSE);
+    /* To kick any packets that the secondary doesn't match */
+    timeout_source = g_timeout_source_new(REGULAR_PACKET_CHECK_MS);
+    g_source_set_callback(timeout_source,
+                          (GSourceFunc)check_old_packet_regular, s, NULL);
+    g_source_attach(timeout_source, s->worker_context);
 
-    g_main_loop_run(compare_loop);
+    g_main_loop_run(s->compare_loop);
 
-    g_main_loop_unref(compare_loop);
-    g_main_context_unref(worker_context);
+    g_source_unref(timeout_source);
+    g_main_loop_unref(s->compare_loop);
+    g_main_context_unref(s->worker_context);
     return NULL;
 }
 
@@ -604,26 +644,6 @@ static int find_and_check_chardev(Chardev **chr,
 }
 
 /*
- * 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);
-}
-
-/*
  * Called from the main thread on the primary
  * to setup colo-compare.
  */
@@ -665,7 +685,6 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
     net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize);
 
     g_queue_init(&s->conn_list);
-    qemu_mutex_init(&s->timer_check_lock);
 
     s->connection_track_table = g_hash_table_new_full(connection_key_hash,
                                                       connection_key_equal,
@@ -678,15 +697,26 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
                        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);
-
     return;
 }
 
+static void colo_flush_packets(void *opaque, void *user_data)
+{
+    CompareState *s = user_data;
+    Connection *conn = opaque;
+    Packet *pkt = NULL;
+
+    while (!g_queue_is_empty(&conn->primary_list)) {
+        pkt = g_queue_pop_head(&conn->primary_list);
+        compare_chr_send(&s->chr_out, pkt->data, pkt->size);
+        packet_destroy(pkt, NULL);
+    }
+    while (!g_queue_is_empty(&conn->secondary_list)) {
+        pkt = g_queue_pop_head(&conn->secondary_list);
+        packet_destroy(pkt, NULL);
+    }
+}
+
 static void colo_compare_class_init(ObjectClass *oc, void *data)
 {
     UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
@@ -711,24 +741,21 @@ static void colo_compare_finalize(Object *obj)
 {
     CompareState *s = COLO_COMPARE(obj);
 
-    qemu_chr_fe_deinit(&s->chr_pri_in);
-    qemu_chr_fe_deinit(&s->chr_sec_in);
+    qemu_chr_fe_set_handlers(&s->chr_pri_in, NULL, NULL, NULL, NULL,
+                             s->worker_context, true);
+    qemu_chr_fe_set_handlers(&s->chr_sec_in, NULL, NULL, NULL, NULL,
+                             s->worker_context, true);
     qemu_chr_fe_deinit(&s->chr_out);
 
-    g_queue_free(&s->conn_list);
-
-    if (qemu_thread_is_self(&s->thread)) {
-        /* compare connection */
-        g_queue_foreach(&s->conn_list, colo_compare_connection, s);
-        qemu_thread_join(&s->thread);
-    }
+    g_main_loop_quit(s->compare_loop);
+    qemu_thread_join(&s->thread);
 
-    if (s->timer) {
-        timer_del(s->timer);
-    }
+    /* Release all unhandled packets after compare thead exited */
+    g_queue_foreach(&s->conn_list, colo_flush_packets, s);
 
-    qemu_mutex_destroy(&s->timer_check_lock);
+    g_queue_clear(&s->conn_list);
 
+    g_hash_table_destroy(s->connection_track_table);
     g_free(s->pri_indev);
     g_free(s->sec_indev);
     g_free(s->outdev);
diff --git a/net/colo.c b/net/colo.c
index 6a6eacd2dc..8cc166bc22 100644
--- a/net/colo.c
+++ b/net/colo.c
@@ -147,9 +147,9 @@ void connection_destroy(void *opaque)
     Connection *conn = opaque;
 
     g_queue_foreach(&conn->primary_list, packet_destroy, NULL);
-    g_queue_free(&conn->primary_list);
+    g_queue_clear(&conn->primary_list);
     g_queue_foreach(&conn->secondary_list, packet_destroy, NULL);
-    g_queue_free(&conn->secondary_list);
+    g_queue_clear(&conn->secondary_list);
     g_slice_free(Connection, conn);
 }
 
diff --git a/net/eth.c b/net/eth.c
index df81efb676..5b9ba26a56 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -232,7 +232,7 @@ void eth_get_protocols(const struct iovec *iov, int iovcnt,
     }
 }
 
-bool
+size_t
 eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
                uint8_t *new_ehdr_buf,
                uint16_t *payload_offset, uint16_t *tci)
@@ -244,7 +244,7 @@ eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
                                new_ehdr, sizeof(*new_ehdr));
 
     if (copied < sizeof(*new_ehdr)) {
-        return false;
+        return 0;
     }
 
     switch (be16_to_cpu(new_ehdr->h_proto)) {
@@ -254,7 +254,7 @@ eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
                             &vlan_hdr, sizeof(vlan_hdr));
 
         if (copied < sizeof(vlan_hdr)) {
-            return false;
+            return 0;
         }
 
         new_ehdr->h_proto = vlan_hdr.h_proto;
@@ -268,18 +268,21 @@ eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
                                 PKT_GET_VLAN_HDR(new_ehdr), sizeof(vlan_hdr));
 
             if (copied < sizeof(vlan_hdr)) {
-                return false;
+                return 0;
             }
 
             *payload_offset += sizeof(vlan_hdr);
+
+            return sizeof(struct eth_header) + sizeof(struct vlan_header);
+        } else {
+            return sizeof(struct eth_header);
         }
-        return true;
     default:
-        return false;
+        return 0;
     }
 }
 
-bool
+size_t
 eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
                   uint16_t vet, uint8_t *new_ehdr_buf,
                   uint16_t *payload_offset, uint16_t *tci)
@@ -291,7 +294,7 @@ eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
                                new_ehdr, sizeof(*new_ehdr));
 
     if (copied < sizeof(*new_ehdr)) {
-        return false;
+        return 0;
     }
 
     if (be16_to_cpu(new_ehdr->h_proto) == vet) {
@@ -299,17 +302,17 @@ eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
                             &vlan_hdr, sizeof(vlan_hdr));
 
         if (copied < sizeof(vlan_hdr)) {
-            return false;
+            return 0;
         }
 
         new_ehdr->h_proto = vlan_hdr.h_proto;
 
         *tci = be16_to_cpu(vlan_hdr.h_tci);
         *payload_offset = iovoff + sizeof(*new_ehdr) + sizeof(vlan_hdr);
-        return true;
+        return sizeof(struct eth_header);
     }
 
-    return false;
+    return 0;
 }
 
 void
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
index aa0aa98fa5..72fa7c2b6c 100644
--- a/net/filter-mirror.c
+++ b/net/filter-mirror.c
@@ -49,7 +49,7 @@ static int filter_mirror_send(CharBackend *chr_out,
 {
     int ret = 0;
     ssize_t size = 0;
-    uint32_t len =  0;
+    uint32_t len = 0;
     char *buf;
 
     size = iov_size(iov, iovcnt);
@@ -77,8 +77,9 @@ err:
     return ret < 0 ? ret : -EIO;
 }
 
-static void
-redirector_to_filter(NetFilterState *nf, const uint8_t *buf, int len)
+static void redirector_to_filter(NetFilterState *nf,
+                                 const uint8_t *buf,
+                                 int len)
 {
     struct iovec iov = {
         .iov_base = (void *)buf,
diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
index c4ab91cdee..afa06e8919 100644
--- a/net/filter-rewriter.c
+++ b/net/filter-rewriter.c
@@ -93,10 +93,12 @@ static int handle_primary_tcp_pkt(NetFilterState *nf,
             conn->offset -= (ntohl(tcp_pkt->th_ack) - 1);
             conn->syn_flag = 0;
         }
-        /* handle packets to the secondary from the primary */
-        tcp_pkt->th_ack = htonl(ntohl(tcp_pkt->th_ack) + conn->offset);
+        if (conn->offset) {
+            /* handle packets to the secondary from the primary */
+            tcp_pkt->th_ack = htonl(ntohl(tcp_pkt->th_ack) + conn->offset);
 
-        net_checksum_calculate((uint8_t *)pkt->data, pkt->size);
+            net_checksum_calculate((uint8_t *)pkt->data, pkt->size);
+        }
     }
 
     return 0;
@@ -129,10 +131,13 @@ static int handle_secondary_tcp_pkt(NetFilterState *nf,
     }
 
     if ((tcp_pkt->th_flags & (TH_ACK | TH_SYN)) == TH_ACK) {
-        /* handle packets to the primary from the secondary*/
-        tcp_pkt->th_seq = htonl(ntohl(tcp_pkt->th_seq) - conn->offset);
+        /* Only need to adjust seq while offset is Non-zero */
+        if (conn->offset) {
+            /* handle packets to the primary from the secondary*/
+            tcp_pkt->th_seq = htonl(ntohl(tcp_pkt->th_seq) - conn->offset);
 
-        net_checksum_calculate((uint8_t *)pkt->data, pkt->size);
+            net_checksum_calculate((uint8_t *)pkt->data, pkt->size);
+        }
     }
 
     return 0;