4 #include <linux/virtio_net.h>
5 #include <linux/kernel.h>
6 #include <linux/list.h>
8 int uip_tx(struct iovec
*iov
, u16 out
, struct uip_info
*info
)
10 struct virtio_net_hdr
*vnet
;
11 struct uip_tx_arg arg
;
12 int eth_len
, vnet_len
;
19 * Buffer from guest to device
21 vnet_len
= iov
[0].iov_len
;
22 vnet
= iov
[0].iov_base
;
24 eth_len
= iov
[1].iov_len
;
25 eth
= iov
[1].iov_base
;
28 * In case, ethernet frame is in more than one iov entry.
29 * Copy iov buffer into one linear buffer.
33 for (i
= 1; i
< out
; i
++)
34 eth_len
+= iov
[i
].iov_len
;
36 buf
= malloc(eth_len
);
40 eth
= (struct uip_eth
*)buf
;
41 for (i
= 1; i
< out
; i
++) {
42 memcpy(buf
, iov
[i
].iov_base
, iov
[i
].iov_len
);
43 buf
+= iov
[i
].iov_len
;
47 memset(&arg
, 0, sizeof(arg
));
49 arg
.vnet_len
= vnet_len
;
50 arg
.eth_len
= eth_len
;
58 proto
= ntohs(eth
->type
);
74 return vnet_len
+ eth_len
;
77 int uip_rx(struct iovec
*iov
, u16 in
, struct uip_info
*info
)
79 struct virtio_net_hdr
*vnet
;
90 * Sleep until there is a buffer for guest
92 buf
= uip_buf_get_used(info
);
95 * Fill device to guest buffer, vnet hdr fisrt
97 vnet_len
= iov
[0].iov_len
;
98 vnet
= iov
[0].iov_base
;
99 if (buf
->vnet_len
> vnet_len
) {
103 memcpy(vnet
, buf
->vnet
, buf
->vnet_len
);
106 * Then, the real eth data
107 * Note: Be sure buf->eth_len is not bigger than the buffer len that guest provides
111 for (i
= 1; i
< in
; i
++) {
112 eth_len
= iov
[i
].iov_len
;
113 eth
= iov
[i
].iov_base
;
115 memcpy(eth
, p
, eth_len
);
126 pr_warning("uip_rx error");
131 len
= buf
->vnet_len
+ buf
->eth_len
;
134 uip_buf_set_free(info
, buf
);
138 int uip_init(struct uip_info
*info
)
140 struct list_head
*udp_socket_head
;
141 struct list_head
*tcp_socket_head
;
142 struct list_head
*buf_head
;
147 udp_socket_head
= &info
->udp_socket_head
;
148 tcp_socket_head
= &info
->tcp_socket_head
;
149 buf_head
= &info
->buf_head
;
150 buf_nr
= info
->buf_nr
;
152 INIT_LIST_HEAD(udp_socket_head
);
153 INIT_LIST_HEAD(tcp_socket_head
);
154 INIT_LIST_HEAD(buf_head
);
156 pthread_mutex_init(&info
->udp_socket_lock
, NULL
);
157 pthread_mutex_init(&info
->tcp_socket_lock
, NULL
);
158 pthread_mutex_init(&info
->buf_lock
, NULL
);
160 pthread_cond_init(&info
->buf_used_cond
, NULL
);
161 pthread_cond_init(&info
->buf_free_cond
, NULL
);
164 for (i
= 0; i
< buf_nr
; i
++) {
165 buf
= malloc(sizeof(*buf
));
166 memset(buf
, 0, sizeof(*buf
));
168 buf
->status
= UIP_BUF_STATUS_FREE
;
171 list_add_tail(&buf
->list
, buf_head
);
174 list_for_each_entry(buf
, buf_head
, list
) {
175 buf
->vnet
= malloc(sizeof(struct virtio_net_hdr
));
176 buf
->vnet_len
= sizeof(struct virtio_net_hdr
);
177 buf
->eth
= malloc(1024*64 + sizeof(struct uip_pseudo_hdr
));
178 buf
->eth_len
= 1024*64 + sizeof(struct uip_pseudo_hdr
);
180 memset(buf
->vnet
, 0, buf
->vnet_len
);
181 memset(buf
->eth
, 0, buf
->eth_len
);
184 info
->buf_free_nr
= buf_nr
;
185 info
->buf_used_nr
= 0;
187 uip_dhcp_get_dns(info
);