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 <asias.hejun@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
This commit is contained in:
Asias He
2015-06-01 16:39:45 +01:00
committed by Will Deacon
parent 91b10270c4
commit 0c84745800
2 changed files with 71 additions and 0 deletions
+2
View File
@@ -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);
+69
View File
@@ -5,6 +5,75 @@
#include <linux/kernel.h>
#include <linux/list.h>
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;