Commit a778cd56 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging



# gpg: Signature made Mon 17 Jul 2017 13:17:17 BST
# 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 a trusted signature!
# gpg:          There is no indication 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:
  virtio-net: fix offload ctrl endian
  virtion-net: Prefer is_power_of_2()
  docs/colo-proxy.txt: Update colo-proxy usage of net driver with vnet_header
  net/filter-rewriter.c: Make filter-rewriter support vnet_hdr_len
  net/colo-compare.c: Add vnet packet's tcp/udp/icmp compare
  net/colo.c: Add vnet packet parse feature in colo-proxy
  net/colo-compare.c: Make colo-compare support vnet_hdr_len
  net/colo-compare.c: Introduce parameter for compare_chr_send()
  net/colo.c: Make vnet_hdr_len as packet property
  net/filter-mirror.c: Add new option to enable vnet support for filter-redirector
  net/filter-mirror.c: Make filter mirror support vnet support.
  net/filter-mirror.c: Introduce parameter for filter_send()
  net/net.c: Add vnet_hdr support in SocketReadState
  net: Add vnet_hdr_len arguments in NetClientState

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 5a477a78 189ae6bb
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -182,6 +182,32 @@ Secondary(ip:3.3.3.8):
-chardev socket,id=red1,host=3.3.3.3,port=9004
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
-object filter-rewriter,id=f3,netdev=hn0,queue=all

If you want to use virtio-net-pci or other driver with vnet_header:

Primary(ip:3.3.3.3):
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait
-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait
-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait
-chardev socket,id=compare0-0,host=3.3.3.3,port=9001
-chardev socket,id=compare_out,host=3.3.3.3,port=9005,server,nowait
-chardev socket,id=compare_out0,host=3.3.3.3,port=9005
-object filter-mirror,id=m0,netdev=hn0,queue=tx,outdev=mirror0,vnet_hdr_support
-object filter-redirector,netdev=hn0,id=redire0,queue=rx,indev=compare_out,vnet_hdr_support
-object filter-redirector,netdev=hn0,id=redire1,queue=rx,outdev=compare0,vnet_hdr_support
-object colo-compare,id=comp0,primary_in=compare0-0,secondary_in=compare1,outdev=compare_out0,vnet_hdr_support

Secondary(ip:3.3.3.8):
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
-device e1000,netdev=hn0,mac=52:a4:00:12:78:66
-chardev socket,id=red0,host=3.3.3.3,port=9003
-chardev socket,id=red1,host=3.3.3.3,port=9004
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0,vnet_hdr_support
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1,vnet_hdr_support
-object filter-rewriter,id=f3,netdev=hn0,queue=all,vnet_hdr_support

Note:
  a.COLO-proxy must work with COLO-frame and Block-replication.
+3 −1
Original line number Diff line number Diff line
@@ -758,6 +758,8 @@ static int virtio_net_handle_offloads(VirtIONet *n, uint8_t cmd,
    if (cmd == VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET) {
        uint64_t supported_offloads;

        offloads = virtio_ldq_p(vdev, &offloads);

        if (!n->has_vnet_hdr) {
            return VIRTIO_NET_ERR;
        }
@@ -1942,7 +1944,7 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
     */
    if (n->net_conf.rx_queue_size < VIRTIO_NET_RX_QUEUE_MIN_SIZE ||
        n->net_conf.rx_queue_size > VIRTQUEUE_MAX_SIZE ||
        (n->net_conf.rx_queue_size & (n->net_conf.rx_queue_size - 1))) {
        !is_power_of_2(n->net_conf.rx_queue_size)) {
        error_setg(errp, "Invalid rx_queue_size (= %" PRIu16 "), "
                   "must be a power of 2 between %d and %d.",
                   n->net_conf.rx_queue_size, VIRTIO_NET_RX_QUEUE_MIN_SIZE,
+8 −2
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ struct NetClientState {
    unsigned int queue_index;
    unsigned rxfilter_notify_enabled:1;
    int vring_enable;
    int vnet_hdr_len;
    QTAILQ_HEAD(NetFilterHead, NetFilterState) filters;
};

@@ -111,9 +112,13 @@ typedef struct NICState {
} NICState;

struct SocketReadState {
    int state; /* 0 = getting length, 1 = getting data */
    /* 0 = getting length, 1 = getting vnet header length, 2 = getting data */
    int state;
    /* This flag decide whether to read the vnet_hdr_len field */
    bool vnet_hdr;
    uint32_t index;
    uint32_t packet_len;
    uint32_t vnet_hdr_len;
    uint8_t buf[NET_BUFSIZE];
    SocketReadStateFinalize *finalize;
};
@@ -176,7 +181,8 @@ ssize_t qemu_deliver_packet_iov(NetClientState *sender,
void print_net_client(Monitor *mon, NetClientState *nc);
void hmp_info_network(Monitor *mon, const QDict *qdict);
void net_socket_rs_init(SocketReadState *rs,
                        SocketReadStateFinalize *finalize);
                        SocketReadStateFinalize *finalize,
                        bool vnet_hdr);

/* NIC info */

+69 −15
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ typedef struct CompareState {
    CharBackend chr_out;
    SocketReadState pri_rs;
    SocketReadState sec_rs;
    bool vnet_hdr;

    /* connection list: the connections belonged to this NIC could be found
     * in this list.
@@ -97,9 +98,10 @@ enum {
    SECONDARY_IN,
};

static int compare_chr_send(CharBackend *out,
static int compare_chr_send(CompareState *s,
                            const uint8_t *buf,
                            uint32_t size);
                            uint32_t size,
                            uint32_t vnet_hdr_len);

static gint seq_sorter(Packet *a, Packet *b, gpointer data)
{
@@ -121,9 +123,13 @@ static int packet_enqueue(CompareState *s, int mode)
    Connection *conn;

    if (mode == PRIMARY_IN) {
        pkt = packet_new(s->pri_rs.buf, s->pri_rs.packet_len);
        pkt = packet_new(s->pri_rs.buf,
                         s->pri_rs.packet_len,
                         s->pri_rs.vnet_hdr_len);
    } else {
        pkt = packet_new(s->sec_rs.buf, s->sec_rs.packet_len);
        pkt = packet_new(s->sec_rs.buf,
                         s->sec_rs.packet_len,
                         s->sec_rs.vnet_hdr_len);
    }

    if (parse_packet_early(pkt)) {
@@ -195,8 +201,11 @@ static int colo_packet_compare_common(Packet *ppkt, Packet *spkt, int offset)
                                   sec_ip_src, sec_ip_dst);
    }

    offset = ppkt->vnet_hdr_len + offset;

    if (ppkt->size == spkt->size) {
        return memcmp(ppkt->data + offset, spkt->data + offset,
        return memcmp(ppkt->data + offset,
                      spkt->data + offset,
                      spkt->size - offset);
    } else {
        trace_colo_compare_main("Net packet size are not the same");
@@ -255,8 +264,9 @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
     */
    if (ptcp->th_off > 5) {
        ptrdiff_t tcp_offset;

        tcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data
                     + (ptcp->th_off * 4);
                     + (ptcp->th_off * 4) - ppkt->vnet_hdr_len;
        res = colo_packet_compare_common(ppkt, spkt, tcp_offset);
    } else if (ptcp->th_sum == stcp->th_sum) {
        res = colo_packet_compare_common(ppkt, spkt, ETH_HLEN);
@@ -479,7 +489,10 @@ static void colo_compare_connection(void *opaque, void *user_data)
        }

        if (result) {
            ret = compare_chr_send(&s->chr_out, pkt->data, pkt->size);
            ret = compare_chr_send(s,
                                   pkt->data,
                                   pkt->size,
                                   pkt->vnet_hdr_len);
            if (ret < 0) {
                error_report("colo_send_primary_packet failed");
            }
@@ -500,9 +513,10 @@ static void colo_compare_connection(void *opaque, void *user_data)
    }
}

static int compare_chr_send(CharBackend *out,
static int compare_chr_send(CompareState *s,
                            const uint8_t *buf,
                            uint32_t size)
                            uint32_t size,
                            uint32_t vnet_hdr_len)
{
    int ret = 0;
    uint32_t len = htonl(size);
@@ -511,12 +525,24 @@ static int compare_chr_send(CharBackend *out,
        return 0;
    }

    ret = qemu_chr_fe_write_all(out, (uint8_t *)&len, sizeof(len));
    ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
    if (ret != sizeof(len)) {
        goto err;
    }

    if (s->vnet_hdr) {
        /*
         * We send vnet header len make other module(like filter-redirector)
         * know how to parse net packet correctly.
         */
        len = htonl(vnet_hdr_len);
        ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
        if (ret != sizeof(len)) {
            goto err;
        }
    }

    ret = qemu_chr_fe_write_all(out, (uint8_t *)buf, size);
    ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size);
    if (ret != size) {
        goto err;
    }
@@ -655,13 +681,32 @@ static void compare_set_outdev(Object *obj, const char *value, Error **errp)
    s->outdev = g_strdup(value);
}

static bool compare_get_vnet_hdr(Object *obj, Error **errp)
{
    CompareState *s = COLO_COMPARE(obj);

    return s->vnet_hdr;
}

static void compare_set_vnet_hdr(Object *obj,
                                 bool value,
                                 Error **errp)
{
    CompareState *s = COLO_COMPARE(obj);

    s->vnet_hdr = value;
}

static void compare_pri_rs_finalize(SocketReadState *pri_rs)
{
    CompareState *s = container_of(pri_rs, CompareState, pri_rs);

    if (packet_enqueue(s, PRIMARY_IN)) {
        trace_colo_compare_main("primary: unsupported packet in");
        compare_chr_send(&s->chr_out, pri_rs->buf, pri_rs->packet_len);
        compare_chr_send(s,
                         pri_rs->buf,
                         pri_rs->packet_len,
                         pri_rs->vnet_hdr_len);
    } else {
        /* compare connection */
        g_queue_foreach(&s->conn_list, colo_compare_connection, s);
@@ -743,8 +788,8 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
        return;
    }

    net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize);
    net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize);
    net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize, s->vnet_hdr);
    net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize, s->vnet_hdr);

    g_queue_init(&s->conn_list);

@@ -770,7 +815,10 @@ static void colo_flush_packets(void *opaque, void *user_data)

    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);
        compare_chr_send(s,
                         pkt->data,
                         pkt->size,
                         pkt->vnet_hdr_len);
        packet_destroy(pkt, NULL);
    }
    while (!g_queue_is_empty(&conn->secondary_list)) {
@@ -788,6 +836,8 @@ static void colo_compare_class_init(ObjectClass *oc, void *data)

static void colo_compare_init(Object *obj)
{
    CompareState *s = COLO_COMPARE(obj);

    object_property_add_str(obj, "primary_in",
                            compare_get_pri_indev, compare_set_pri_indev,
                            NULL);
@@ -797,6 +847,10 @@ static void colo_compare_init(Object *obj)
    object_property_add_str(obj, "outdev",
                            compare_get_outdev, compare_set_outdev,
                            NULL);

    s->vnet_hdr = false;
    object_property_add_bool(obj, "vnet_hdr_support", compare_get_vnet_hdr,
                             compare_set_vnet_hdr, NULL);
}

static void colo_compare_finalize(Object *obj)
+5 −4
Original line number Diff line number Diff line
@@ -43,11 +43,11 @@ int parse_packet_early(Packet *pkt)
{
    int network_length;
    static const uint8_t vlan[] = {0x81, 0x00};
    uint8_t *data = pkt->data;
    uint8_t *data = pkt->data + pkt->vnet_hdr_len;
    uint16_t l3_proto;
    ssize_t l2hdr_len = eth_get_l2_hdr_length(data);

    if (pkt->size < ETH_HLEN) {
    if (pkt->size < ETH_HLEN + pkt->vnet_hdr_len) {
        trace_colo_proxy_main("pkt->size < ETH_HLEN");
        return 1;
    }
@@ -73,7 +73,7 @@ int parse_packet_early(Packet *pkt)
    }

    network_length = pkt->ip->ip_hl * 4;
    if (pkt->size < l2hdr_len + network_length) {
    if (pkt->size < l2hdr_len + network_length + pkt->vnet_hdr_len) {
        trace_colo_proxy_main("pkt->size < network_header + network_length");
        return 1;
    }
@@ -153,13 +153,14 @@ void connection_destroy(void *opaque)
    g_slice_free(Connection, conn);
}

Packet *packet_new(const void *data, int size)
Packet *packet_new(const void *data, int size, int vnet_hdr_len)
{
    Packet *pkt = g_slice_new(Packet);

    pkt->data = g_memdup(data, size);
    pkt->size = size;
    pkt->creation_ms = qemu_clock_get_ms(QEMU_CLOCK_HOST);
    pkt->vnet_hdr_len = vnet_hdr_len;

    return pkt;
}
Loading