191b10270SAsias He #include "kvm/mutex.h" 291b10270SAsias He #include "kvm/uip.h" 391b10270SAsias He 491b10270SAsias He #include <linux/virtio_net.h> 591b10270SAsias He #include <linux/kernel.h> 691b10270SAsias He #include <linux/list.h> 791b10270SAsias He 8*0c847458SAsias He int uip_tx(struct iovec *iov, u16 out, struct uip_info *info) 9*0c847458SAsias He { 10*0c847458SAsias He struct virtio_net_hdr *vnet; 11*0c847458SAsias He struct uip_tx_arg arg; 12*0c847458SAsias He int eth_len, vnet_len; 13*0c847458SAsias He struct uip_eth *eth; 14*0c847458SAsias He u8 *buf = NULL; 15*0c847458SAsias He u16 proto; 16*0c847458SAsias He int i; 17*0c847458SAsias He 18*0c847458SAsias He /* 19*0c847458SAsias He * Buffer from guest to device 20*0c847458SAsias He */ 21*0c847458SAsias He vnet_len = iov[0].iov_len; 22*0c847458SAsias He vnet = iov[0].iov_base; 23*0c847458SAsias He 24*0c847458SAsias He eth_len = iov[1].iov_len; 25*0c847458SAsias He eth = iov[1].iov_base; 26*0c847458SAsias He 27*0c847458SAsias He /* 28*0c847458SAsias He * In case, ethernet frame is in more than one iov entry. 29*0c847458SAsias He * Copy iov buffer into one linear buffer. 30*0c847458SAsias He */ 31*0c847458SAsias He if (out > 2) { 32*0c847458SAsias He eth_len = 0; 33*0c847458SAsias He for (i = 1; i < out; i++) 34*0c847458SAsias He eth_len += iov[i].iov_len; 35*0c847458SAsias He 36*0c847458SAsias He buf = malloc(eth_len); 37*0c847458SAsias He if (!buf) 38*0c847458SAsias He return -1; 39*0c847458SAsias He 40*0c847458SAsias He eth = (struct uip_eth *)buf; 41*0c847458SAsias He for (i = 1; i < out; i++) { 42*0c847458SAsias He memcpy(buf, iov[i].iov_base, iov[i].iov_len); 43*0c847458SAsias He buf += iov[i].iov_len; 44*0c847458SAsias He } 45*0c847458SAsias He } 46*0c847458SAsias He 47*0c847458SAsias He memset(&arg, 0, sizeof(arg)); 48*0c847458SAsias He 49*0c847458SAsias He arg.vnet_len = vnet_len; 50*0c847458SAsias He arg.eth_len = eth_len; 51*0c847458SAsias He arg.info = info; 52*0c847458SAsias He arg.vnet = vnet; 53*0c847458SAsias He arg.eth = eth; 54*0c847458SAsias He 55*0c847458SAsias He /* 56*0c847458SAsias He * Check package type 57*0c847458SAsias He */ 58*0c847458SAsias He proto = ntohs(eth->type); 59*0c847458SAsias He 60*0c847458SAsias He switch (proto) { 61*0c847458SAsias He case UIP_ETH_P_ARP: 62*0c847458SAsias He uip_tx_do_arp(&arg); 63*0c847458SAsias He break; 64*0c847458SAsias He case UIP_ETH_P_IP: 65*0c847458SAsias He uip_tx_do_ipv4(&arg); 66*0c847458SAsias He break; 67*0c847458SAsias He default: 68*0c847458SAsias He break; 69*0c847458SAsias He } 70*0c847458SAsias He 71*0c847458SAsias He if (out > 2 && buf) 72*0c847458SAsias He free(eth); 73*0c847458SAsias He 74*0c847458SAsias He return vnet_len + eth_len; 75*0c847458SAsias He } 76*0c847458SAsias He 7791b10270SAsias He int uip_init(struct uip_info *info) 7891b10270SAsias He { 7991b10270SAsias He struct list_head *udp_socket_head; 8091b10270SAsias He struct list_head *tcp_socket_head; 8191b10270SAsias He struct list_head *buf_head; 8291b10270SAsias He struct uip_buf *buf; 8391b10270SAsias He int buf_nr; 8491b10270SAsias He int i; 8591b10270SAsias He 8691b10270SAsias He udp_socket_head = &info->udp_socket_head; 8791b10270SAsias He tcp_socket_head = &info->tcp_socket_head; 8891b10270SAsias He buf_head = &info->buf_head; 8991b10270SAsias He buf_nr = info->buf_nr; 9091b10270SAsias He 9191b10270SAsias He INIT_LIST_HEAD(udp_socket_head); 9291b10270SAsias He INIT_LIST_HEAD(tcp_socket_head); 9391b10270SAsias He INIT_LIST_HEAD(buf_head); 9491b10270SAsias He 9591b10270SAsias He pthread_mutex_init(&info->udp_socket_lock, NULL); 9691b10270SAsias He pthread_mutex_init(&info->tcp_socket_lock, NULL); 9791b10270SAsias He pthread_mutex_init(&info->buf_lock, NULL); 9891b10270SAsias He 9991b10270SAsias He pthread_cond_init(&info->buf_used_cond, NULL); 10091b10270SAsias He pthread_cond_init(&info->buf_free_cond, NULL); 10191b10270SAsias He 10291b10270SAsias He 10391b10270SAsias He for (i = 0; i < buf_nr; i++) { 10491b10270SAsias He buf = malloc(sizeof(*buf)); 10591b10270SAsias He memset(buf, 0, sizeof(*buf)); 10691b10270SAsias He 10791b10270SAsias He buf->status = UIP_BUF_STATUS_FREE; 10891b10270SAsias He buf->info = info; 10991b10270SAsias He buf->id = i; 11091b10270SAsias He list_add_tail(&buf->list, buf_head); 11191b10270SAsias He } 11291b10270SAsias He 11391b10270SAsias He list_for_each_entry(buf, buf_head, list) { 11491b10270SAsias He buf->vnet = malloc(sizeof(struct virtio_net_hdr)); 11591b10270SAsias He buf->vnet_len = sizeof(struct virtio_net_hdr); 11691b10270SAsias He buf->eth = malloc(1024*64 + sizeof(struct uip_pseudo_hdr)); 11791b10270SAsias He buf->eth_len = 1024*64 + sizeof(struct uip_pseudo_hdr); 11891b10270SAsias He 11991b10270SAsias He memset(buf->vnet, 0, buf->vnet_len); 12091b10270SAsias He memset(buf->eth, 0, buf->eth_len); 12191b10270SAsias He } 12291b10270SAsias He 12391b10270SAsias He info->buf_free_nr = buf_nr; 12491b10270SAsias He info->buf_used_nr = 0; 12591b10270SAsias He 12691b10270SAsias He return 0; 12791b10270SAsias He } 128