xref: /kvmtool/net/uip/buf.c (revision d3476f7d3bb7cee0b620cf207c168cb4f5b5c41e)
1 #include "kvm/uip.h"
2 
3 #include <linux/kernel.h>
4 #include <linux/list.h>
5 
uip_buf_get_used(struct uip_info * info)6 struct uip_buf *uip_buf_get_used(struct uip_info *info)
7 {
8 	struct uip_buf *buf;
9 	bool found = false;
10 
11 	mutex_lock(&info->buf_lock);
12 
13 	while (!(info->buf_used_nr > 0))
14 		pthread_cond_wait(&info->buf_used_cond, &info->buf_lock.mutex);
15 
16 	list_for_each_entry(buf, &info->buf_head, list) {
17 		if (buf->status == UIP_BUF_STATUS_USED) {
18 			/*
19 			 * Set status to INUSE immediately to prevent
20 			 * someone from using this buf until we free it
21 			 */
22 			buf->status = UIP_BUF_STATUS_INUSE;
23 			info->buf_used_nr--;
24 			found = true;
25 			break;
26 		}
27 	}
28 
29 	mutex_unlock(&info->buf_lock);
30 
31 	return found ? buf : NULL;
32 }
33 
uip_buf_get_free(struct uip_info * info)34 struct uip_buf *uip_buf_get_free(struct uip_info *info)
35 {
36 	struct uip_buf *buf;
37 	bool found = false;
38 
39 	mutex_lock(&info->buf_lock);
40 
41 	while (!(info->buf_free_nr > 0))
42 		pthread_cond_wait(&info->buf_free_cond, &info->buf_lock.mutex);
43 
44 	list_for_each_entry(buf, &info->buf_head, list) {
45 		if (buf->status == UIP_BUF_STATUS_FREE) {
46 			/*
47 			 * Set status to INUSE immediately to prevent
48 			 * someone from using this buf until we free it
49 			 */
50 			buf->status = UIP_BUF_STATUS_INUSE;
51 			info->buf_free_nr--;
52 			found = true;
53 			break;
54 		}
55 	}
56 
57 	mutex_unlock(&info->buf_lock);
58 
59 	return found ? buf : NULL;
60 }
61 
uip_buf_set_used(struct uip_info * info,struct uip_buf * buf)62 struct uip_buf *uip_buf_set_used(struct uip_info *info, struct uip_buf *buf)
63 {
64 	mutex_lock(&info->buf_lock);
65 
66 	buf->status = UIP_BUF_STATUS_USED;
67 	info->buf_used_nr++;
68 	pthread_cond_signal(&info->buf_used_cond);
69 
70 	mutex_unlock(&info->buf_lock);
71 
72 	return buf;
73 }
74 
uip_buf_set_free(struct uip_info * info,struct uip_buf * buf)75 struct uip_buf *uip_buf_set_free(struct uip_info *info, struct uip_buf *buf)
76 {
77 	mutex_lock(&info->buf_lock);
78 
79 	buf->status = UIP_BUF_STATUS_FREE;
80 	info->buf_free_nr++;
81 	pthread_cond_signal(&info->buf_free_cond);
82 
83 	mutex_unlock(&info->buf_lock);
84 
85 	return buf;
86 }
87 
uip_buf_clone(struct uip_tx_arg * arg)88 struct uip_buf *uip_buf_clone(struct uip_tx_arg *arg)
89 {
90 	struct uip_buf *buf;
91 	struct uip_eth *eth2;
92 	struct uip_info *info;
93 
94 	info = arg->info;
95 
96 	/*
97 	 * Get buffer from device to guest
98 	 */
99 	buf = uip_buf_get_free(info);
100 
101 	/*
102 	 * Clone buffer
103 	 */
104 	memcpy(buf->vnet, arg->vnet, arg->vnet_len);
105 	memcpy(buf->eth, arg->eth, arg->eth_len);
106 	buf->vnet_len	= arg->vnet_len;
107 	buf->eth_len	= arg->eth_len;
108 
109 	eth2		= (struct uip_eth *)buf->eth;
110 	eth2->src	= info->host_mac;
111 	eth2->dst	= arg->eth->src;
112 
113 	return buf;
114 }
115