xref: /kvmtool/net/uip/buf.c (revision d3476f7d3bb7cee0b620cf207c168cb4f5b5c41e)
126570aafSAsias He #include "kvm/uip.h"
226570aafSAsias He 
326570aafSAsias He #include <linux/kernel.h>
426570aafSAsias He #include <linux/list.h>
526570aafSAsias He 
uip_buf_get_used(struct uip_info * info)626570aafSAsias He struct uip_buf *uip_buf_get_used(struct uip_info *info)
726570aafSAsias He {
826570aafSAsias He 	struct uip_buf *buf;
926570aafSAsias He 	bool found = false;
1026570aafSAsias He 
1126570aafSAsias He 	mutex_lock(&info->buf_lock);
1226570aafSAsias He 
1326570aafSAsias He 	while (!(info->buf_used_nr > 0))
14*d3476f7dSSasha Levin 		pthread_cond_wait(&info->buf_used_cond, &info->buf_lock.mutex);
1526570aafSAsias He 
1626570aafSAsias He 	list_for_each_entry(buf, &info->buf_head, list) {
1726570aafSAsias He 		if (buf->status == UIP_BUF_STATUS_USED) {
1826570aafSAsias He 			/*
1926570aafSAsias He 			 * Set status to INUSE immediately to prevent
2026570aafSAsias He 			 * someone from using this buf until we free it
2126570aafSAsias He 			 */
2226570aafSAsias He 			buf->status = UIP_BUF_STATUS_INUSE;
2326570aafSAsias He 			info->buf_used_nr--;
2426570aafSAsias He 			found = true;
2526570aafSAsias He 			break;
2626570aafSAsias He 		}
2726570aafSAsias He 	}
2826570aafSAsias He 
2926570aafSAsias He 	mutex_unlock(&info->buf_lock);
3026570aafSAsias He 
3126570aafSAsias He 	return found ? buf : NULL;
3226570aafSAsias He }
3326570aafSAsias He 
uip_buf_get_free(struct uip_info * info)3426570aafSAsias He struct uip_buf *uip_buf_get_free(struct uip_info *info)
3526570aafSAsias He {
3626570aafSAsias He 	struct uip_buf *buf;
3726570aafSAsias He 	bool found = false;
3826570aafSAsias He 
3926570aafSAsias He 	mutex_lock(&info->buf_lock);
4026570aafSAsias He 
4126570aafSAsias He 	while (!(info->buf_free_nr > 0))
42*d3476f7dSSasha Levin 		pthread_cond_wait(&info->buf_free_cond, &info->buf_lock.mutex);
4326570aafSAsias He 
4426570aafSAsias He 	list_for_each_entry(buf, &info->buf_head, list) {
4526570aafSAsias He 		if (buf->status == UIP_BUF_STATUS_FREE) {
4626570aafSAsias He 			/*
4726570aafSAsias He 			 * Set status to INUSE immediately to prevent
4826570aafSAsias He 			 * someone from using this buf until we free it
4926570aafSAsias He 			 */
5026570aafSAsias He 			buf->status = UIP_BUF_STATUS_INUSE;
5126570aafSAsias He 			info->buf_free_nr--;
5226570aafSAsias He 			found = true;
5326570aafSAsias He 			break;
5426570aafSAsias He 		}
5526570aafSAsias He 	}
5626570aafSAsias He 
5726570aafSAsias He 	mutex_unlock(&info->buf_lock);
5826570aafSAsias He 
5926570aafSAsias He 	return found ? buf : NULL;
6026570aafSAsias He }
6126570aafSAsias He 
uip_buf_set_used(struct uip_info * info,struct uip_buf * buf)6226570aafSAsias He struct uip_buf *uip_buf_set_used(struct uip_info *info, struct uip_buf *buf)
6326570aafSAsias He {
6426570aafSAsias He 	mutex_lock(&info->buf_lock);
6526570aafSAsias He 
6626570aafSAsias He 	buf->status = UIP_BUF_STATUS_USED;
6726570aafSAsias He 	info->buf_used_nr++;
6826570aafSAsias He 	pthread_cond_signal(&info->buf_used_cond);
6926570aafSAsias He 
7026570aafSAsias He 	mutex_unlock(&info->buf_lock);
7126570aafSAsias He 
7226570aafSAsias He 	return buf;
7326570aafSAsias He }
7426570aafSAsias He 
uip_buf_set_free(struct uip_info * info,struct uip_buf * buf)7526570aafSAsias He struct uip_buf *uip_buf_set_free(struct uip_info *info, struct uip_buf *buf)
7626570aafSAsias He {
7726570aafSAsias He 	mutex_lock(&info->buf_lock);
7826570aafSAsias He 
7926570aafSAsias He 	buf->status = UIP_BUF_STATUS_FREE;
8026570aafSAsias He 	info->buf_free_nr++;
8126570aafSAsias He 	pthread_cond_signal(&info->buf_free_cond);
8226570aafSAsias He 
8326570aafSAsias He 	mutex_unlock(&info->buf_lock);
8426570aafSAsias He 
8526570aafSAsias He 	return buf;
8626570aafSAsias He }
8726570aafSAsias He 
uip_buf_clone(struct uip_tx_arg * arg)8826570aafSAsias He struct uip_buf *uip_buf_clone(struct uip_tx_arg *arg)
8926570aafSAsias He {
9026570aafSAsias He 	struct uip_buf *buf;
9126570aafSAsias He 	struct uip_eth *eth2;
9226570aafSAsias He 	struct uip_info *info;
9326570aafSAsias He 
9426570aafSAsias He 	info = arg->info;
9526570aafSAsias He 
9626570aafSAsias He 	/*
9726570aafSAsias He 	 * Get buffer from device to guest
9826570aafSAsias He 	 */
9926570aafSAsias He 	buf = uip_buf_get_free(info);
10026570aafSAsias He 
10126570aafSAsias He 	/*
10226570aafSAsias He 	 * Clone buffer
10326570aafSAsias He 	 */
10426570aafSAsias He 	memcpy(buf->vnet, arg->vnet, arg->vnet_len);
10526570aafSAsias He 	memcpy(buf->eth, arg->eth, arg->eth_len);
10626570aafSAsias He 	buf->vnet_len	= arg->vnet_len;
10726570aafSAsias He 	buf->eth_len	= arg->eth_len;
10826570aafSAsias He 
10926570aafSAsias He 	eth2		= (struct uip_eth *)buf->eth;
11026570aafSAsias He 	eth2->src	= info->host_mac;
11126570aafSAsias He 	eth2->dst	= arg->eth->src;
11226570aafSAsias He 
11326570aafSAsias He 	return buf;
11426570aafSAsias He }
115