static void vmxnet3_rx_need_csum_calculate(struct NetRxPkt *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 (!net_rx_pkt_has_virt_hdr(pkt)) {

        return;

    }



    vhdr = net_rx_pkt_get_vhdr(pkt);

    if (!VMXNET_FLAG_IS_SET(vhdr->flags, VIRTIO_NET_HDR_F_NEEDS_CSUM)) {

        return;

    }



    net_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:%zu < csum_start(%d) + csum_offset(%d) + 2, "

                  "cannot calculate checksum",

                  pkt_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;

}
