Пример #1
0
static void virtio_net_tx_lazy(struct vmm_netport *port, void *arg, int budget)
{
	u16 head = 0;
	u32 iov_cnt = 0, pkt_len = 0, total_len = 0;
	struct virtio_net_dev *ndev = arg;
	struct virtio_device *dev = ndev->vdev;
	struct virtio_queue *vq = &ndev->vqs[VIRTIO_NET_TX_QUEUE];
	struct virtio_iovec *iov = ndev->tx_iov;
	struct vmm_mbuf *mb;

	while ((budget > 0) && virtio_queue_available(vq)) {
		head = virtio_queue_get_iovec(vq, iov, &iov_cnt, &total_len);

		/* iov[0] is offload info */
		pkt_len = total_len - iov[0].len;

		if (pkt_len <= VIRTIO_NET_MTU) {
			MGETHDR(mb, 0, 0);
			MEXTMALLOC(mb, pkt_len, M_WAIT);
			virtio_iovec_to_buf_read(dev, 
						 &iov[1], iov_cnt - 1,
						 M_BUFADDR(mb), pkt_len);
			mb->m_len = mb->m_pktlen = pkt_len;
			vmm_port2switch_xfer_mbuf(ndev->port, mb);
		}

		virtio_queue_set_used_elem(vq, head, total_len);

		budget--;
	}

	if (virtio_queue_should_signal(vq)) {
		dev->tra->notify(dev, VIRTIO_NET_TX_QUEUE);
	}
}
Пример #2
0
static err_t lwip_netstack_output(struct netif *netif, struct pbuf *p)
{
	struct vmm_mbuf *mbuf, *mbuf_head, *mbuf_cur;
	struct pbuf *q;
	struct lwip_netstack *lns = netif->state;

	if (!p || !p->payload || !p->len) {
		return ERR_OK;
	}

	if (p->tot_len > MAX_FRAME_LEN) {
		/* Frame too long, drop it */
		return ERR_MEM;
	}

	/* Increase reference to the pbuf as we reuse the same buffers */
	pbuf_ref(p);

	/* Create the first mbuf in the chain */
	MGETHDR(mbuf_head, 0, 0);
	MEXTADD(mbuf_head, p->payload, p->len, lwip_netstack_mbuf_free, p);
	mbuf_cur = mbuf_head;

	/* Create next mbufs in chain from the pbuf chain */
	q = p->next;
	while (q != NULL) {
		MGET(mbuf, 0, M_EXT_DONTFREE);
		MEXTADD(mbuf, q->payload, q->len, NULL, NULL);
		mbuf_cur->m_next = mbuf;
		mbuf_cur = mbuf;
		q = q->next;
	}

	/* Setup mbuf len */
	mbuf_head->m_len = mbuf_head->m_pktlen = p->tot_len;

	/* Send mbuf to the netswitch */
	vmm_port2switch_xfer_mbuf(lns->port, mbuf_head);

	/* Return success */
	return ERR_OK;
}