static ssize_t vnic_receive_iov(VLANClientState *ncp, const struct iovec *iov, int iovcnt) { int ret, fvec, i; size_t total; VNICState *vsp = DO_UPCAST(VNICState, vns_nc, ncp); assert(iovcnt <= FRAMEIO_NVECS_MAX); /* * Copy the iovcs to our write frameio. Also, check if any of these is * valid dhcp and handle it immediately. */ for (i = 0, fvec = 0; i < iovcnt; i++, iov++) { if (vsp->vns_ds.vnds_enabled && is_dhcp_request(iov->iov_base, iov->iov_len)) { /* * Basically drop the packet because we can't send a * reply at this time. It's unfortunate, but we don't * really have the proper infrastructure to do something * else with this at this time. */ if (!vnic_can_send(vsp)) continue; ret = create_dhcp_response(iov->iov_base, iov->iov_len, &vsp->vns_ds); /* This failed, drop it and continue */ if (ret == 0) continue; ret = qemu_send_packet_async(&vsp->vns_nc, vsp->vns_ds.vnds_buf, ret, vnic_send_completed); /* * qemu has told us that it can't receive any more data * at this time for the guest (host->guest traffic) so * turn off our read poll until we get that the send has * completed. */ if (ret == 0) vnic_read_poll(vsp, 0); continue; } vsp->vns_wfio->fio_vecs[fvec].fv_buf = iov->iov_base; vsp->vns_wfio->fio_vecs[fvec].fv_buflen = iov->iov_len; fvec++; } vsp->vns_wfio->fio_nvecs = fvec; do { ret = vnd_frameio_write(vsp->vns_hdl, vsp->vns_wfio); } while (ret == -1 && errno == EINTR); if (ret == -1 && errno == EAGAIN) { vnic_write_poll(vsp, 1); return (0); } total = 0; for (i = 0; i < vsp->vns_wfio->fio_nvecs; i++) { if (vsp->vns_wfio->fio_vecs[i].fv_actlen == 0 && vsp->vns_wfio->fio_vecs[i].fv_buflen == 0) break; total += vsp->vns_wfio->fio_vecs[i].fv_actlen; } return (total); }
static ssize_t vnic_receive_iov(VLANClientState *ncp, const struct iovec *iov, int iovcnt) { int ret, i; size_t total, altsize; VNICState *vsp = DO_UPCAST(VNICState, vns_nc, ncp); for (total = 0, i = 0; i < iovcnt; i++) { total += (iov + i)->iov_len; } if (vsp->vns_ds.vnds_enabled && is_dhcp_requestv(iov, iovcnt)) { /* * Basically drop the packet because we can't send a * reply at this time. It's unfortunate, but we don't * really have the proper infrastructure to do something * else with this at this time. */ if (!vnic_can_send(vsp)) return (total); ret = create_dhcp_responsev(iov, iovcnt, &vsp->vns_ds); /* This failed, drop it and continue */ if (ret == 0) return (total); ret = qemu_send_packet_async(&vsp->vns_nc, vsp->vns_ds.vnds_buf, ret, vnic_send_completed); /* * qemu has told us that it can't receive any more data * at this time for the guest (host->guest traffic) so * turn off our read poll until we get that the send has * completed. */ if (ret == 0) vnic_read_poll(vsp, 0); return (total); } /* * Copy the iovcs to our write frameio. Be on the lookout for someone * giving us more vectors than we support in frameio. In that case, * let's go ahead and just simply concat the rest. */ for (i = 0; i < MIN(iovcnt, FRAMEIO_NVECS_MAX - 1); i++, iov++) { vsp->vns_wfio->fio_vecs[i].fv_buf = iov->iov_base; vsp->vns_wfio->fio_vecs[i].fv_buflen = iov->iov_len; } altsize = 0; for (i = MIN(iovcnt, FRAMEIO_NVECS_MAX - 1); i != iovcnt; i++, iov++) { /* * The packet is too large. We're goin to silently drop it... */ if (altsize + iov->iov_len > VNIC_BUFSIZE) return (total); bcopy(iov->iov_base, vsp->vns_txbuf + altsize, iov->iov_len); altsize += iov->iov_len; } if (altsize != 0) { vsp->vns_wfio->fio_vecs[FRAMEIO_NVECS_MAX-1].fv_buf = vsp->vns_txbuf; vsp->vns_wfio->fio_vecs[FRAMEIO_NVECS_MAX-1].fv_buflen = altsize; } vsp->vns_wfio->fio_nvecs = MIN(iovcnt, FRAMEIO_NVECS_MAX); vsp->vns_wfio->fio_nvpf = MIN(iovcnt, FRAMEIO_NVECS_MAX); do { ret = vnd_frameio_write(vsp->vns_hdl, vsp->vns_wfio); } while (ret == -1 && errno == EINTR); if (ret == -1 && errno == EAGAIN) { vnic_write_poll(vsp, 1); return (0); } else if (ret == -1) { abort(); } total = 0; for (i = 0; i < vsp->vns_wfio->fio_nvecs; i++) { if (vsp->vns_wfio->fio_vecs[i].fv_actlen == 0 && vsp->vns_wfio->fio_vecs[i].fv_buflen == 0) break; total += vsp->vns_wfio->fio_vecs[i].fv_actlen; } return (total); }