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