From cae1cc2a5f0fb8cf8f2997c75d85955f4d3fc017 Mon Sep 17 00:00:00 2001 From: Asias He Date: Wed, 29 Jun 2011 16:47:27 +0800 Subject: [PATCH] kvm tools: Introduce uip_tx() for uip This patch implement tx interface for uip. uip_tx() can be called in virtio_net_tx_thread(). It dispatches ethernet frame to ARP or IP handling code. Signed-off-by: Asias He Signed-off-by: Pekka Enberg --- tools/kvm/include/kvm/uip.h | 2 ++ tools/kvm/uip/core.c | 69 +++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/tools/kvm/include/kvm/uip.h b/tools/kvm/include/kvm/uip.h index c300de09c4b6..38ad386a8d62 100644 --- a/tools/kvm/include/kvm/uip.h +++ b/tools/kvm/include/kvm/uip.h @@ -12,6 +12,7 @@ #define UIP_BUF_STATUS_USED 2 #define UIP_ETH_P_IP 0X0800 +#define UIP_ETH_P_ARP 0X0806 #define UIP_IP_VER_4 0X40 #define UIP_IP_HDR_LEN 0X05 @@ -267,6 +268,7 @@ static inline u16 uip_eth_hdrlen(struct uip_eth *eth) return sizeof(*eth); } +int uip_tx(struct iovec *iov, u16 out, 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 58eba6bec43c..3a3754675ae8 100644 --- a/tools/kvm/uip/core.c +++ b/tools/kvm/uip/core.c @@ -5,6 +5,75 @@ #include #include +int uip_tx(struct iovec *iov, u16 out, struct uip_info *info) +{ + struct virtio_net_hdr *vnet; + struct uip_tx_arg arg; + int eth_len, vnet_len; + struct uip_eth *eth; + u8 *buf = NULL; + u16 proto; + int i; + + /* + * Buffer from guest to device + */ + vnet_len = iov[0].iov_len; + vnet = iov[0].iov_base; + + eth_len = iov[1].iov_len; + eth = iov[1].iov_base; + + /* + * In case, ethernet frame is in more than one iov entry. + * Copy iov buffer into one linear buffer. + */ + if (out > 2) { + eth_len = 0; + for (i = 1; i < out; i++) + eth_len += iov[i].iov_len; + + buf = malloc(eth_len); + if (!buf) + return -1; + + eth = (struct uip_eth *)buf; + for (i = 1; i < out; i++) { + memcpy(buf, iov[i].iov_base, iov[i].iov_len); + buf += iov[i].iov_len; + } + } + + memset(&arg, 0, sizeof(arg)); + + arg.vnet_len = vnet_len; + arg.eth_len = eth_len; + arg.info = info; + arg.vnet = vnet; + arg.eth = eth; + + /* + * Check package type + */ + proto = ntohs(eth->type); + + switch (proto) { + case UIP_ETH_P_ARP: + uip_tx_do_arp(&arg); + break; + case UIP_ETH_P_IP: + uip_tx_do_ipv4(&arg); + break; + default: + break; + } + + if (out > 2 && buf) + free(eth); + + return vnet_len + eth_len; +} + int uip_init(struct uip_info *info) { struct list_head *udp_socket_head; -- 2.39.5