From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41634) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bLRdo-0004fN-Fw for qemu-devel@nongnu.org; Fri, 08 Jul 2016 05:00:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bLRdj-0003AU-Uh for qemu-devel@nongnu.org; Fri, 08 Jul 2016 05:00:08 -0400 Received: from mx1.redhat.com ([209.132.183.28]:42356) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bLRdj-0003AM-Ls for qemu-devel@nongnu.org; Fri, 08 Jul 2016 05:00:03 -0400 References: <1466681677-30487-1-git-send-email-zhangchen.fnst@cn.fujitsu.com> <1466681677-30487-5-git-send-email-zhangchen.fnst@cn.fujitsu.com> From: Jason Wang Message-ID: <577F6B8D.2050309@redhat.com> Date: Fri, 8 Jul 2016 16:59:57 +0800 MIME-Version: 1.0 In-Reply-To: <1466681677-30487-5-git-send-email-zhangchen.fnst@cn.fujitsu.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [RFC PATCH V5 4/4] colo-compare: add TCP, UDP, ICMP packet comparison List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Zhang Chen , qemu devel Cc: Li Zhijian , "eddie . dong" , "Dr . David Alan Gilbert" , zhanghailiang On 2016=E5=B9=B406=E6=9C=8823=E6=97=A5 19:34, Zhang Chen wrote: > Signed-off-by: Zhang Chen > Signed-off-by: Li Zhijian > Signed-off-by: Wen Congyang > --- > net/colo-compare.c | 171 ++++++++++++++++++++++++++++++++++++++++++++= +++++++-- > trace-events | 6 ++ > 2 files changed, 173 insertions(+), 4 deletions(-) Commit log please. > diff --git a/net/colo-compare.c b/net/colo-compare.c > index 928d729..addf704 100644 > --- a/net/colo-compare.c > +++ b/net/colo-compare.c > @@ -18,6 +18,7 @@ > #include "qapi/qmp/qerror.h" > #include "qapi/error.h" > #include "net/net.h" > +#include "net/eth.h" > #include "net/vhost_net.h" > #include "qom/object_interfaces.h" > #include "qemu/iov.h" > @@ -180,9 +181,155 @@ static int colo_packet_compare(Packet *ppkt, Pack= et *spkt) > } > } > =20 > -static int colo_packet_compare_all(Packet *spkt, Packet *ppkt) > +/* > + * 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) > +{ > + struct tcphdr *ptcp, *stcp; > + int res; > + char *sdebug, *ddebug; > + > + trace_colo_compare_main("compare tcp"); > + if (ppkt->size !=3D spkt->size) { > + if (trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) { > + trace_colo_compare_main("pkt size not same"); > + } > + return -1; > + } > + > + ptcp =3D (struct tcphdr *)ppkt->transport_layer; > + stcp =3D (struct tcphdr *)spkt->transport_layer; > + > + if (ptcp->th_seq !=3D stcp->th_seq) { > + if (trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) { > + trace_colo_compare_main("pkt tcp seq not same"); > + } > + return -1; > + } > + > + /* > + * 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 d= ifferent > + * anyway, and it should recover at the TCP level. > + * An alternative would be to get both the primary and secondary t= o rewrite > + * somehow; but that would need some sync traffic to sync the stat= e > + */ > + if (ntohs(ppkt->ip->ip_off) & IP_DF) { > + spkt->ip->ip_id =3D ppkt->ip->ip_id; > + /* and the sum will be different if the IDs were different */ > + spkt->ip->ip_sum =3D ppkt->ip->ip_sum; > + } I was considering, can we do some trick in rewriter instead of here? > + > + res =3D memcmp(ppkt->data + ETH_HLEN, spkt->data + ETH_HLEN, > + (spkt->size - ETH_HLEN)); > + > + if (res !=3D 0 && trace_event_get_state(TRACE_COLO_COMPARE_MISCOMP= ARE)) { > + sdebug =3D strdup(inet_ntoa(ppkt->ip->ip_src)); > + ddebug =3D strdup(inet_ntoa(ppkt->ip->ip_dst)); > + fprintf(stderr, "%s: src/dst: %s/%s p: seq/ack=3D%u/%u" > + " s: seq/ack=3D%u/%u res=3D%d flags=3D%x/%x\n", __func__, > + sdebug, ddebug, > + ntohl(ptcp->th_seq), ntohl(ptcp->th_ack), > + ntohl(stcp->th_seq), ntohl(stcp->th_ack), > + res, ptcp->th_flags, stcp->th_flags); > + > + trace_colo_compare_tcp_miscompare("Primary len", ppkt->size); > + qemu_hexdump((char *)ppkt->data, stderr, "colo-compare", ppkt-= >size); > + trace_colo_compare_tcp_miscompare("Secondary len", 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 =3D colo_packet_compare(ppkt, spkt); > + > + if (ret) { > + trace_colo_compare_udp_miscompare("primary pkt size", ppkt->si= ze); > + 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; > + struct icmp *icmp_ppkt, *icmp_spkt; > + > + trace_colo_compare_main("compare icmp"); > + network_length =3D ppkt->ip->ip_hl * 4; > + if (ppkt->size !=3D spkt->size || > + ppkt->size < network_length + ETH_HLEN) { > + trace_colo_compare_icmp_miscompare_size(ppkt->size, spkt->size= ); > + return -1; > + } > + icmp_ppkt =3D (struct icmp *)(ppkt->data + network_length + ETH_HL= EN); > + icmp_spkt =3D (struct icmp *)(spkt->data + network_length + ETH_HL= EN); > + > + if ((icmp_ppkt->icmp_type =3D=3D icmp_spkt->icmp_type) && > + (icmp_ppkt->icmp_code =3D=3D icmp_spkt->icmp_code)) { > + if (icmp_ppkt->icmp_type =3D=3D ICMP_REDIRECT) { > + if (icmp_ppkt->icmp_gwaddr.s_addr !=3D > + icmp_spkt->icmp_gwaddr.s_addr) { > + trace_colo_compare_main("icmp_gwaddr.s_addr not same")= ; > + trace_colo_compare_icmp_miscompare_addr("ppkt s_addr", > + inet_ntoa(icmp_ppkt->icmp_gwaddr)); > + trace_colo_compare_icmp_miscompare_addr("spkt s_addr", > + inet_ntoa(icmp_spkt->icmp_gwaddr)); > + return -1; > + } > + } else if ((icmp_ppkt->icmp_type =3D=3D ICMP_UNREACH) && > + (icmp_ppkt->icmp_type =3D=3D ICMP_UNREACH_NEEDFRAG)= ) { > + if (icmp_ppkt->icmp_nextmtu !=3D icmp_spkt->icmp_nextmtu) = { > + trace_colo_compare_main("icmp_nextmtu not same"); > + trace_colo_compare_icmp_miscompare_mtu("ppkt nextmtu", > + icmp_ppkt->icmp_nextmtu); > + trace_colo_compare_icmp_miscompare_mtu("spkt nextmtu", > + icmp_spkt->icmp_nextmtu); > + return -1; > + } > + } > + } else { > + return -1; > + } Why only compare part of icmp packet? > + > + 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 all"); > + 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)); > return colo_packet_compare(ppkt, spkt); > } > =20 > @@ -221,8 +368,24 @@ 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)) { > pkt =3D g_queue_pop_tail(&conn->primary_list); > - result =3D g_queue_find_custom(&conn->secondary_list, > - pkt, (GCompareFunc)colo_packet_compare_a= ll); > + switch (conn->ip_proto) { > + case IPPROTO_TCP: > + result =3D g_queue_find_custom(&conn->secondary_list, > + pkt, (GCompareFunc)colo_packet_compare_tcp); > + break; > + case IPPROTO_UDP: > + result =3D g_queue_find_custom(&conn->secondary_list, > + pkt, (GCompareFunc)colo_packet_compare_udp); > + break; > + case IPPROTO_ICMP: > + result =3D g_queue_find_custom(&conn->secondary_list, > + pkt, (GCompareFunc)colo_packet_compare_icmp); > + break; > + default: > + result =3D g_queue_find_custom(&conn->secondary_list, > + pkt, (GCompareFunc)colo_packet_compare_other); > + break; > + } > =20 > if (result) { > ret =3D compare_chr_send(s->chr_out, pkt->data, pkt->size= ); > diff --git a/trace-events b/trace-events > index 1537e91..6686cdf 100644 > --- a/trace-events > +++ b/trace-events > @@ -1919,5 +1919,11 @@ aspeed_vic_write(uint64_t offset, unsigned size,= uint32_t data) "To 0x%" PRIx64 > =20 > # net/colo-compare.c > colo_compare_main(const char *chr) ": %s" > +colo_compare_tcp_miscompare(const char *sta, int size) ": %s =3D %d" > +colo_compare_udp_miscompare(const char *sta, int size) ": %s =3D %d" > +colo_compare_icmp_miscompare_size(int psize, int ssize) ":ppkt size =3D= %d spkt size =3D %d" > +colo_compare_icmp_miscompare_addr(const char *sta, const char *stb) ":= %s %s" > +colo_compare_icmp_miscompare_mtu(const char *sta, int size) ": %s %d" > colo_compare_ip_info(int psize, const char *sta, const char *stb, int= ssize, const char *stc, const char *std) "ppkt size =3D %d, ip_src =3D %= s, ip_dst =3D %s, spkt size =3D %d, ip_src =3D %s, ip_dst =3D %s" > colo_old_packet_check_found(int64_t old_time) "%" PRId64 > +colo_compare_miscompare(void) ""