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

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



# gpg: Signature made Mon Jul 20 18:25:14 2015 BST using RSA key ID 81AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>"

* remotes/stefanha/tags/net-pull-request:
  net: Flush queued packets when guest resumes
  lan9118: Drop lan9118_can_receive
  etraxfs_eth: Drop eth_can_receive
  musicpal: Drop eth_can_receive
  net/vmxnet3: Fix RX TCP/UDP checksum on partially summed packets
  net/vmxnet3: Refactor 'vmxnet_rx_pkt_attach_data'
  socket: pass correct size in net_socket_send()

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 13566fe3 625de449
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -187,11 +187,6 @@ static void eth_rx_desc_get(uint32_t addr, mv88w8618_rx_desc *desc)
    le32_to_cpus(&desc->next);
}

static int eth_can_receive(NetClientState *nc)
{
    return 1;
}

static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size)
{
    mv88w8618_eth_state *s = qemu_get_nic_opaque(nc);
@@ -381,7 +376,6 @@ static void eth_cleanup(NetClientState *nc)
static NetClientInfo net_mv88w8618_info = {
    .type = NET_CLIENT_OPTIONS_KIND_NIC,
    .size = sizeof(NICState),
    .can_receive = eth_can_receive,
    .receive = eth_receive,
    .cleanup = eth_cleanup,
};
+0 −6
Original line number Diff line number Diff line
@@ -520,11 +520,6 @@ static int eth_match_groupaddr(ETRAXFSEthState *eth, const unsigned char *sa)
    return match;
}

static int eth_can_receive(NetClientState *nc)
{
    return 1;
}

static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size)
{
    unsigned char sa_bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@@ -584,7 +579,6 @@ static const MemoryRegionOps eth_ops = {
static NetClientInfo net_etraxfs_info = {
    .type = NET_CLIENT_OPTIONS_KIND_NIC,
    .size = sizeof(NICState),
    .can_receive = eth_can_receive,
    .receive = eth_receive,
    .link_status_changed = eth_set_link,
};
+0 −6
Original line number Diff line number Diff line
@@ -461,11 +461,6 @@ static void lan9118_reset(DeviceState *d)
    lan9118_reload_eeprom(s);
}

static int lan9118_can_receive(NetClientState *nc)
{
    return 1;
}

static void rx_fifo_push(lan9118_state *s, uint32_t val)
{
    int fifo_pos;
@@ -1312,7 +1307,6 @@ static const MemoryRegionOps lan9118_16bit_mem_ops = {
static NetClientInfo net_lan9118_info = {
    .type = NET_CLIENT_OPTIONS_KIND_NIC,
    .size = sizeof(NICState),
    .can_receive = lan9118_can_receive,
    .receive = lan9118_receive,
    .link_status_changed = lan9118_set_link,
};
+59 −0
Original line number Diff line number Diff line
@@ -885,6 +885,63 @@ vmxnet3_get_next_rx_descr(VMXNET3State *s, bool is_head,
    }
}

/* In case packet was csum offloaded (either NEEDS_CSUM or DATA_VALID),
 * the implementation always passes an RxCompDesc with a "Checksum
 * calculated and found correct" to the OS (cnc=0 and tuc=1, see
 * vmxnet3_rx_update_descr). This emulates the observed ESXi behavior.
 *
 * Therefore, if packet has the NEEDS_CSUM set, we must calculate
 * and place a fully computed checksum into the tcp/udp header.
 * Otherwise, the OS driver will receive a checksum-correct indication
 * (CHECKSUM_UNNECESSARY), but with the actual tcp/udp checksum field
 * having just the pseudo header csum value.
 *
 * While this is not a problem if packet is destined for local delivery,
 * in the case the host OS performs forwarding, it will forward an
 * incorrectly checksummed packet.
 */
static void vmxnet3_rx_need_csum_calculate(struct VmxnetRxPkt *pkt,
                                           const void *pkt_data,
                                           size_t pkt_len)
{
    struct virtio_net_hdr *vhdr;
    bool isip4, isip6, istcp, isudp;
    uint8_t *data;
    int len;

    if (!vmxnet_rx_pkt_has_virt_hdr(pkt)) {
        return;
    }

    vhdr = vmxnet_rx_pkt_get_vhdr(pkt);
    if (!VMXNET_FLAG_IS_SET(vhdr->flags, VIRTIO_NET_HDR_F_NEEDS_CSUM)) {
        return;
    }

    vmxnet_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp);
    if (!(isip4 || isip6) || !(istcp || isudp)) {
        return;
    }

    vmxnet3_dump_virt_hdr(vhdr);

    /* Validate packet len: csum_start + scum_offset + length of csum field */
    if (pkt_len < (vhdr->csum_start + vhdr->csum_offset + 2)) {
        VMW_PKPRN("packet len:%d < csum_start(%d) + csum_offset(%d) + 2, "
                  "cannot calculate checksum",
                  len, vhdr->csum_start, vhdr->csum_offset);
        return;
    }

    data = (uint8_t *)pkt_data + vhdr->csum_start;
    len = pkt_len - vhdr->csum_start;
    /* Put the checksum obtained into the packet */
    stw_be_p(data + vhdr->csum_offset, net_raw_checksum(data, len));

    vhdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM;
    vhdr->flags |= VIRTIO_NET_HDR_F_DATA_VALID;
}

static void vmxnet3_rx_update_descr(struct VmxnetRxPkt *pkt,
    struct Vmxnet3_RxCompDesc *rxcd)
{
@@ -1897,6 +1954,8 @@ vmxnet3_receive(NetClientState *nc, const uint8_t *buf, size_t size)
        get_eth_packet_type(PKT_GET_ETH_HDR(buf)));

    if (vmxnet3_rx_filter_may_indicate(s, buf, size)) {
        vmxnet_rx_pkt_set_protocols(s->rx_pkt, buf, size);
        vmxnet3_rx_need_csum_calculate(s->rx_pkt, buf, size);
        vmxnet_rx_pkt_attach_data(s->rx_pkt, buf, size, s->rx_vlan_stripping);
        bytes_indicated = vmxnet3_indicate_packet(s) ? size : -1;
        if (bytes_indicated < size) {
+9 −3
Original line number Diff line number Diff line
@@ -92,9 +92,6 @@ void vmxnet_rx_pkt_attach_data(struct VmxnetRxPkt *pkt, const void *data,
    }

    pkt->tci = tci;

    eth_get_protocols(data, len, &pkt->isip4, &pkt->isip6,
        &pkt->isudp, &pkt->istcp);
}

void vmxnet_rx_pkt_dump(struct VmxnetRxPkt *pkt)
@@ -131,6 +128,15 @@ size_t vmxnet_rx_pkt_get_total_len(struct VmxnetRxPkt *pkt)
    return pkt->tot_len;
}

void vmxnet_rx_pkt_set_protocols(struct VmxnetRxPkt *pkt, const void *data,
                                 size_t len)
{
    assert(pkt);

    eth_get_protocols(data, len, &pkt->isip4, &pkt->isip6,
        &pkt->isudp, &pkt->istcp);
}

void vmxnet_rx_pkt_get_protocols(struct VmxnetRxPkt *pkt,
                                 bool *isip4, bool *isip6,
                                 bool *isudp, bool *istcp)
Loading