]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm tools: Introduce uip_rx() for uip
authorAsias He <asias.hejun@gmail.com>
Wed, 29 Jun 2011 08:47:28 +0000 (16:47 +0800)
committerPekka Enberg <penberg@kernel.org>
Thu, 30 Jun 2011 07:42:45 +0000 (10:42 +0300)
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>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
tools/kvm/include/kvm/uip.h
tools/kvm/uip/core.c

index 38ad386a8d623bc2f352ec51f80345df15d2e14c..18849d2fb7c5f85ffdcd16232e571fde8cd2c2da 100644 (file)
@@ -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);
index 3a3754675ae82cf91e2d345f7ca8679b5caf8a28..7a4b824cd3db67034ab627e22b884ea017909db7 100644 (file)
@@ -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;