2 * Palacios Socket Interface Implementation
7 #include <interfaces/vmm_socket.h>
9 #include <linux/spinlock.h>
10 #include <asm/uaccess.h>
11 #include <linux/inet.h>
12 #include <linux/kthread.h>
13 #include <linux/netdevice.h>
16 #include <linux/string.h>
17 #include <linux/preempt.h>
18 #include <linux/sched.h>
19 #include <linux/list.h>
22 #include "linux-exts.h"
25 struct palacios_socket {
28 struct v3_guest * guest;
29 struct list_head sock_node;
32 static struct list_head global_sockets;
35 // currently just the list of created sockets
36 struct vm_socket_state {
37 struct list_head socket_list;
41 //ignore the arguments given here currently
43 palacios_tcp_socket(const int bufsize, const int nodelay,
44 const int nonblocking, void * private_data) {
45 struct v3_guest * guest = (struct v3_guest *)private_data;
46 struct palacios_socket * sock = NULL;
47 struct vm_socket_state * vm_state = NULL;
51 vm_state = get_vm_ext_data(guest, "SOCKET_INTERFACE");
53 if (vm_state == NULL) {
54 ERROR("ERROR: Could not locate vm socket state for extension SOCKET_INTERFACE\n");
60 sock = palacios_alloc(sizeof(struct palacios_socket));
63 ERROR("Cannot allocate TCP socket\n");
67 memset(sock, 0, sizeof(struct palacios_socket));
69 err = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &(sock->sock));
72 ERROR("Cannot create TCP socket\n");
80 list_add(&(sock->sock_node), &global_sockets);
82 list_add(&(sock->sock_node), &(vm_state->socket_list));
88 //ignore the arguments given here currently
92 const int nonblocking,
96 struct v3_guest * guest = (struct v3_guest *)private_data;
97 struct palacios_socket * sock = NULL;
98 struct vm_socket_state * vm_state = NULL;
102 vm_state = get_vm_ext_data(guest, "SOCKET_INTERFACE");
104 if (vm_state == NULL) {
105 ERROR("ERROR: Could not locate vm socket state for extension SOCKET_INTERFACE\n");
111 sock = palacios_alloc(sizeof(struct palacios_socket));
113 ERROR("Cannot allocate UDP socket\n");
117 memset(sock, 0, sizeof(struct palacios_socket));
119 err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &(sock->sock)) ;
122 ERROR("Cannot create UDP socket\n");
131 list_add(&(sock->sock_node), &global_sockets);
133 list_add(&(sock->sock_node), &(vm_state->socket_list));
141 palacios_close(void * sock_ptr)
143 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
146 sock->sock->ops->release(sock->sock);
148 list_del(&(sock->sock_node));
154 palacios_bind_socket(
155 const void * sock_ptr,
159 struct sockaddr_in addr;
160 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
166 addr.sin_family = AF_INET;
167 addr.sin_port = htons(port);
168 addr.sin_addr.s_addr = INADDR_ANY;
170 return sock->sock->ops->bind(sock->sock, (struct sockaddr *)&addr, sizeof(addr));
175 const void * sock_ptr,
179 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
185 return sock->sock->ops->listen(sock->sock, backlog);
188 static void * palacios_accept(const void * sock_ptr, unsigned int * remote_ip, unsigned int * port) {
190 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
191 struct palacios_socket * newsock = NULL;
192 struct vm_socket_state * vm_state = NULL;
199 if (sock->guest != NULL) {
200 vm_state = get_vm_ext_data(sock->guest, "SOCKET_INTERFACE");
202 if (vm_state == NULL) {
203 ERROR("Could not locate vm socket state for extension SOCKET_INTERFACE\n");
209 newsock = palacios_alloc(sizeof(struct palacios_socket));
212 ERROR("Cannot allocate new socket on accept\n");
216 err = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &(newsock->sock));
219 ERROR("Cannot create new socket on accept\n");
220 palacios_free(newsock);
224 newsock->sock->type = sock->sock->type;
225 newsock->sock->ops = sock->sock->ops;
227 err = newsock->sock->ops->accept(sock->sock, newsock->sock, 0);
230 ERROR("Cannot accept\n");
231 palacios_free(newsock);
235 //TODO: How do we get ip & port?
238 newsock->guest = sock->guest;
240 if (sock->guest == NULL) {
241 list_add(&(newsock->sock_node), &global_sockets);
243 list_add(&(newsock->sock_node), &(vm_state->socket_list));
251 struct v3_sock_set * rset,
252 struct v3_sock_set * wset,
253 struct v3_sock_set * eset,
254 struct v3_timeval tv)
262 palacios_connect_to_ip(
263 const void * sock_ptr,
268 struct sockaddr_in client;
269 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
275 client.sin_family = AF_INET;
276 client.sin_port = htons(port);
277 client.sin_addr.s_addr = htonl(hostip);
279 return sock->sock->ops->connect(sock->sock, (struct sockaddr *)&client, sizeof(client), 0);
284 const void * sock_ptr,
289 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
299 msg.msg_flags = MSG_NOSIGNAL;//0/*MSG_DONTWAIT*/;;
302 msg.msg_control = NULL;
303 msg.msg_controllen = 0;
307 iov.iov_base = (char *)buf;
308 iov.iov_len = (size_t)len;
313 err = sock_sendmsg(sock->sock, &msg, (size_t)len);
322 const void * sock_ptr,
328 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
341 msg.msg_control = NULL;
342 msg.msg_controllen = 0;
346 iov.iov_base = (void *)&buf[0];
347 iov.iov_len = (size_t)len;
352 err = sock_recvmsg(sock->sock, &msg, (size_t)len, 0/*MSG_DONTWAIT*/);
361 const void * sock_ptr,
368 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
372 struct sockaddr_in dst;
379 dst.sin_family = AF_INET;
380 dst.sin_port = htons(port);
381 dst.sin_addr.s_addr = htonl(ip_addr);
383 msg.msg_flags = MSG_NOSIGNAL;//0/*MSG_DONTWAIT*/;;
385 msg.msg_namelen = sizeof(struct sockaddr_in);
386 msg.msg_control = NULL;
387 msg.msg_controllen = 0;
391 iov.iov_base = (char *)buf;
392 iov.iov_len = (size_t)len;
397 err = sock_sendmsg(sock->sock, &msg, (size_t)len);
407 palacios_recvfrom_ip(
408 const void * sock_ptr,
415 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
416 struct sockaddr_in src;
426 src.sin_family = AF_INET;
427 src.sin_port = htons(port);
428 src.sin_addr.s_addr = htonl(ip_addr);
433 msg.msg_namelen = sizeof(struct sockaddr_in);
434 msg.msg_control = NULL;
435 msg.msg_controllen = 0;
439 iov.iov_base = (void *)&buf[0];
440 iov.iov_len = (size_t)len;
445 err = sock_recvmsg(sock->sock, &msg, (size_t)len, 0/*MSG_DONTWAIT*/);
452 static struct v3_socket_hooks palacios_sock_hooks = {
453 .tcp_socket = palacios_tcp_socket,
454 .udp_socket = palacios_udp_socket,
455 .close = palacios_close,
456 .bind = palacios_bind_socket,
457 .listen = palacios_listen,
458 .accept = palacios_accept,
459 .select = palacios_select,
460 .connect_to_ip = palacios_connect_to_ip,
461 .connect_to_host = NULL,
462 .send = palacios_send,
463 .recv = palacios_recv,
465 .sendto_ip = palacios_sendto_ip,
466 .recvfrom_host = NULL,
467 .recvfrom_ip = palacios_recvfrom_ip,
470 static int socket_init( void ) {
471 V3_Init_Sockets(&palacios_sock_hooks);
472 INIT_LIST_HEAD(&global_sockets);
476 static int socket_deinit( void ) {
477 if (!list_empty(&(global_sockets))) {
478 ERROR("Error removing module with open sockets\n");
485 static struct linux_ext socket_ext = {
486 .name = "SOCKET_INTERFACE",
488 .deinit = socket_deinit,
493 register_extension(&socket_ext);