Example #1
0
/*
 * Called from the compare thread on the primary
 * for compare icmp packet
 */
static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
{
    int network_header_length = ppkt->ip->ip_hl * 4;

    trace_colo_compare_main("compare icmp");

    /*
     * 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,
                                   network_header_length + ETH_HLEN)) {
        trace_colo_compare_icmp_miscompare("primary pkt size",
                                           ppkt->size);
        trace_colo_compare_icmp_miscompare("Secondary pkt size",
                                           spkt->size);
        if (trace_event_get_state_backends(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;
    }
}
Example #2
0
static ssize_t etsec_receive(NetClientState *nc,
                             const uint8_t  *buf,
                             size_t          size)
{
    eTSEC *etsec = qemu_get_nic_opaque(nc);

#if defined(HEX_DUMP)
    fprintf(stderr, "%s receive size:%d\n", etsec->nic->nc.name, size);
    qemu_hexdump(buf, stderr, "", size);
#endif
    etsec_rx_ring_write(etsec, buf, size);
    return size;
}
Example #3
0
void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt,
                 FILE *fp, const char *prefix, size_t limit)
{
    int v;
    size_t size = 0;
    char *buf;

    for (v = 0; v < iov_cnt; v++) {
        size += iov[v].iov_len;
    }
    size = size > limit ? limit : size;
    buf = g_malloc(size);
    iov_to_buf(iov, iov_cnt, 0, buf, size);
    qemu_hexdump(buf, fp, prefix, size);
    g_free(buf);
}
Example #4
0
static ssize_t etsec_receive(NetClientState *nc,
                             const uint8_t  *buf,
                             size_t          size)
{
    ssize_t ret;
    eTSEC *etsec = qemu_get_nic_opaque(nc);

#if defined(HEX_DUMP)
    fprintf(stderr, "%s receive size:%d\n", etsec->nic->nc.name, size);
    qemu_hexdump(buf, stderr, "", size);
#endif
    /* Flush is unnecessary as are already in receiving path */
    etsec->need_flush = false;
    ret = etsec_rx_ring_write(etsec, buf, size);
    if (ret == 0) {
        /* The packet will be queued, let's flush it when buffer is available
         * again. */
        etsec->need_flush = true;
    }
    return ret;
}
Example #5
0
/*
 * 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;

    trace_colo_compare_main("compare tcp");

    ptcp = (struct tcphdr *)ppkt->transport_header;
    stcp = (struct tcphdr *)spkt->transport_header;

    /*
     * 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 different
     * anyway, and it should recover at the TCP level.
     * An alternative would be to get both the primary and secondary to rewrite
     * somehow; but that would need some sync traffic to sync the state
     */
    if (ntohs(ppkt->ip->ip_off) & IP_DF) {
        spkt->ip->ip_id = ppkt->ip->ip_id;
        /* and the sum will be different if the IDs were different */
        spkt->ip->ip_sum = ppkt->ip->ip_sum;
    }

    /*
     * Check tcp header length for tcp option field.
     * th_off > 5 means this tcp packet have options field.
     * The tcp options maybe always different.
     * for example:
     * From RFC 7323.
     * TCP Timestamps option (TSopt):
     * Kind: 8
     *
     * Length: 10 bytes
     *
     *    +-------+-------+---------------------+---------------------+
     *    |Kind=8 |  10   |   TS Value (TSval)  |TS Echo Reply (TSecr)|
     *    +-------+-------+---------------------+---------------------+
     *       1       1              4                     4
     *
     * In this case the primary guest's timestamp always different with
     * the secondary guest's timestamp. COLO just focus on payload,
     * so we just need skip this field.
     */
    if (ptcp->th_off > 5) {
        ptrdiff_t ptcp_offset, stcp_offset;

        ptcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data
                      + (ptcp->th_off * 4) - ppkt->vnet_hdr_len;
        stcp_offset = spkt->transport_header - (uint8_t *)spkt->data
                      + (stcp->th_off * 4) - spkt->vnet_hdr_len;

        /*
         * When network is busy, some tcp options(like sack) will unpredictable
         * occur in primary side or secondary side. it will make packet size
         * not same, but the two packet's payload is identical. colo just
         * care about packet payload, so we skip the option field.
         */
        res = colo_packet_compare_common(ppkt, spkt, ptcp_offset, stcp_offset);
    } else if (ptcp->th_sum == stcp->th_sum) {
        res = colo_packet_compare_common(ppkt, spkt, ETH_HLEN, ETH_HLEN);
    } else {
        res = -1;
    }

    if (res != 0 &&
        trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
        char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20];

        strcpy(pri_ip_src, inet_ntoa(ppkt->ip->ip_src));
        strcpy(pri_ip_dst, inet_ntoa(ppkt->ip->ip_dst));
        strcpy(sec_ip_src, inet_ntoa(spkt->ip->ip_src));
        strcpy(sec_ip_dst, inet_ntoa(spkt->ip->ip_dst));

        trace_colo_compare_ip_info(ppkt->size, pri_ip_src,
                                   pri_ip_dst, spkt->size,
                                   sec_ip_src, sec_ip_dst);

        trace_colo_compare_tcp_info("pri tcp packet",
                                    ntohl(ptcp->th_seq),
                                    ntohl(ptcp->th_ack),
                                    res, ptcp->th_flags,
                                    ppkt->size);

        trace_colo_compare_tcp_info("sec tcp packet",
                                    ntohl(stcp->th_seq),
                                    ntohl(stcp->th_ack),
                                    res, stcp->th_flags,
                                    spkt->size);

        qemu_hexdump((char *)ppkt->data, stderr,
                     "colo-compare ppkt", ppkt->size);
        qemu_hexdump((char *)spkt->data, stderr,
                     "colo-compare spkt", spkt->size);
    }

    return res;
}