From: Asias He Date: Wed, 29 Jun 2011 08:47:28 +0000 (+0800) Subject: kvm tools: Introduce uip_rx() for uip X-Git-Tag: next-20110824~3^2~164 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=f699f9d556d337b5b84d3409d12b39b551c651ef;p=karo-tx-linux.git kvm tools: Introduce uip_rx() for uip 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 Signed-off-by: Pekka Enberg --- diff --git a/tools/kvm/include/kvm/uip.h b/tools/kvm/include/kvm/uip.h index 38ad386a8d62..18849d2fb7c5 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 3a3754675ae8..7a4b824cd3db 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;