diff mbox

[v2,23/31] kvm tools: Introduce uip_rx() for uip

Message ID 1309423279-3093-24-git-send-email-asias.hejun@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Asias He June 30, 2011, 8:41 a.m. UTC
This patch implement rx interface for uip. uip_rx() can be called in
virtio_net_rx_thread().

It is a consumer of the ethernet used buffer. It sleeps until there is
used buffer avaiable and copy ethernet data into virtio iov buffers
which provided by virtio_net_rx_thread().

Signed-off-by: Asias He <asias.hejun@gmail.com>
---
 tools/kvm/include/kvm/uip.h |    1 +
 tools/kvm/uip/core.c        |   61 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+), 0 deletions(-)
diff mbox

Patch

diff --git a/tools/kvm/include/kvm/uip.h b/tools/kvm/include/kvm/uip.h
index 38ad386..18849d2 100644
--- a/tools/kvm/include/kvm/uip.h
+++ b/tools/kvm/include/kvm/uip.h
@@ -269,6 +269,7 @@  static inline u16 uip_eth_hdrlen(struct uip_eth *eth)
 }
 
 int uip_tx(struct iovec *iov, u16 out, struct uip_info *info);
+int uip_rx(struct iovec *iov, u16 in, struct uip_info *info);
 int uip_init(struct uip_info *info);
 
 int uip_tx_do_ipv4_icmp(struct uip_tx_arg *arg);
diff --git a/tools/kvm/uip/core.c b/tools/kvm/uip/core.c
index 3a37546..7a4b824 100644
--- a/tools/kvm/uip/core.c
+++ b/tools/kvm/uip/core.c
@@ -74,6 +74,67 @@  int uip_tx(struct iovec *iov, u16 out, struct uip_info *info)
 	return vnet_len + eth_len;
 }
 
+int uip_rx(struct iovec *iov, u16 in, struct uip_info *info)
+{
+	struct virtio_net_hdr *vnet;
+	struct uip_eth *eth;
+	struct uip_buf *buf;
+	int vnet_len;
+	int eth_len;
+	char *p;
+	int len;
+	int cnt;
+	int i;
+
+	/*
+	 * Sleep until there is a buffer for guest
+	 */
+	buf = uip_buf_get_used(info);
+
+	/*
+	 * Fill device to guest buffer, vnet hdr fisrt
+	 */
+	vnet_len = iov[0].iov_len;
+	vnet = iov[0].iov_base;
+	if (buf->vnet_len > vnet_len) {
+		len = -1;
+		goto out;
+	}
+	memcpy(vnet, buf->vnet, buf->vnet_len);
+
+	/*
+	 * Then, the real eth data
+	 * Note: Be sure buf->eth_len is not bigger than the buffer len that guest provides
+	 */
+	cnt = buf->eth_len;
+	p = buf->eth;
+	for (i = 1; i < in; i++) {
+		eth_len = iov[i].iov_len;
+		eth = iov[i].iov_base;
+		if (cnt > eth_len) {
+			memcpy(eth, p, eth_len);
+			cnt -= eth_len;
+			p += eth_len;
+		} else {
+			memcpy(eth, p, cnt);
+			cnt -= cnt;
+			break;
+		}
+	}
+
+	if (cnt) {
+		pr_warning("uip_rx error");
+		len = -1;
+		goto out;
+	}
+
+	len = buf->vnet_len + buf->eth_len;
+
+out:
+	uip_buf_set_free(info, buf);
+	return len;
+}
+
 int uip_init(struct uip_info *info)
 {
 	struct list_head *udp_socket_head;