summaryrefslogtreecommitdiff
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)
downloadqemu-eba44e9339fc13c36e24c8c59e2b73ea231b46a1.tar.gz
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;