2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2010, Lei Xia <lxia@northwestern.edu>
11 * Copyright (c) 2010, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * This is free software. You are permitted to use, redistribute,
15 * and modify it under the terms of the GNU General Public License
16 * Version 2 (GPLv2). The accompanying COPYING file contains the
17 * full text of the license.
20 * Palacios Socket Interface Implementation
23 #include <interfaces/vmm_socket.h>
25 #include <linux/spinlock.h>
26 #include <asm/uaccess.h>
27 #include <linux/inet.h>
28 #include <linux/kthread.h>
29 #include <linux/netdevice.h>
32 #include <linux/string.h>
33 #include <linux/preempt.h>
34 #include <linux/sched.h>
35 #include <linux/list.h>
38 #include "linux-exts.h"
41 struct palacios_socket {
44 struct v3_guest * guest;
45 struct list_head sock_node;
48 static struct list_head global_sockets;
51 // currently just the list of created sockets
52 struct vm_socket_state {
53 struct list_head socket_list;
57 //ignore the arguments given here currently
59 palacios_tcp_socket(const int bufsize, const int nodelay,
60 const int nonblocking, void * private_data) {
61 struct v3_guest * guest = (struct v3_guest *)private_data;
62 struct palacios_socket * sock = NULL;
63 struct vm_socket_state * vm_state = NULL;
67 vm_state = get_vm_ext_data(guest, "SOCKET_INTERFACE");
69 if (vm_state == NULL) {
70 printk("ERROR: Could not locate vm socket state for extension SOCKET_INTERFACE\n");
76 sock = kmalloc(sizeof(struct palacios_socket), GFP_KERNEL);
77 memset(sock, 0, sizeof(struct palacios_socket));
79 err = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &(sock->sock));
89 list_add(&(sock->sock_node), &global_sockets);
91 list_add(&(sock->sock_node), &(vm_state->socket_list));
97 //ignore the arguments given here currently
101 const int nonblocking,
105 struct v3_guest * guest = (struct v3_guest *)private_data;
106 struct palacios_socket * sock = NULL;
107 struct vm_socket_state * vm_state = NULL;
111 vm_state = get_vm_ext_data(guest, "SOCKET_INTERFACE");
113 if (vm_state == NULL) {
114 printk("ERROR: Could not locate vm socket state for extension SOCKET_INTERFACE\n");
120 sock = kmalloc(sizeof(struct palacios_socket), GFP_KERNEL);
121 memset(sock, 0, sizeof(struct palacios_socket));
123 err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &(sock->sock)) ;
134 list_add(&(sock->sock_node), &global_sockets);
136 list_add(&(sock->sock_node), &(vm_state->socket_list));
144 palacios_close(void * sock_ptr)
146 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
149 sock->sock->ops->release(sock->sock);
151 list_del(&(sock->sock_node));
157 palacios_bind_socket(
158 const void * sock_ptr,
162 struct sockaddr_in addr;
163 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
169 addr.sin_family = AF_INET;
170 addr.sin_port = htons(port);
171 addr.sin_addr.s_addr = INADDR_ANY;
173 return sock->sock->ops->bind(sock->sock, (struct sockaddr *)&addr, sizeof(addr));
178 const void * sock_ptr,
182 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
188 return sock->sock->ops->listen(sock->sock, backlog);
191 static void * palacios_accept(const void * sock_ptr, unsigned int * remote_ip, unsigned int * port) {
193 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
194 struct palacios_socket * newsock = NULL;
195 struct vm_socket_state * vm_state = NULL;
202 if (sock->guest != NULL) {
203 vm_state = get_vm_ext_data(sock->guest, "SOCKET_INTERFACE");
205 if (vm_state == NULL) {
206 printk("ERROR: Could not locate vm socket state for extension SOCKET_INTERFACE\n");
212 newsock = kmalloc(sizeof(struct palacios_socket), GFP_KERNEL);
214 err = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &(newsock->sock));
221 newsock->sock->type = sock->sock->type;
222 newsock->sock->ops = sock->sock->ops;
224 err = newsock->sock->ops->accept(sock->sock, newsock->sock, 0);
231 //TODO: How do we get ip & port?
234 newsock->guest = sock->guest;
236 if (sock->guest == NULL) {
237 list_add(&(newsock->sock_node), &global_sockets);
239 list_add(&(newsock->sock_node), &(vm_state->socket_list));
247 struct v3_sock_set * rset,
248 struct v3_sock_set * wset,
249 struct v3_sock_set * eset,
250 struct v3_timeval tv)
258 palacios_connect_to_ip(
259 const void * sock_ptr,
264 struct sockaddr_in client;
265 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
271 client.sin_family = AF_INET;
272 client.sin_port = htons(port);
273 client.sin_addr.s_addr = htonl(hostip);
275 return sock->sock->ops->connect(sock->sock, (struct sockaddr *)&client, sizeof(client), 0);
280 const void * sock_ptr,
285 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
295 msg.msg_flags = MSG_NOSIGNAL;//0/*MSG_DONTWAIT*/;;
298 msg.msg_control = NULL;
299 msg.msg_controllen = 0;
303 iov.iov_base = (char *)buf;
304 iov.iov_len = (size_t)len;
309 err = sock_sendmsg(sock->sock, &msg, (size_t)len);
318 const void * sock_ptr,
324 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
337 msg.msg_control = NULL;
338 msg.msg_controllen = 0;
342 iov.iov_base = (void *)&buf[0];
343 iov.iov_len = (size_t)len;
348 err = sock_recvmsg(sock->sock, &msg, (size_t)len, 0/*MSG_DONTWAIT*/);
357 const void * sock_ptr,
364 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
368 struct sockaddr_in dst;
375 dst.sin_family = AF_INET;
376 dst.sin_port = htons(port);
377 dst.sin_addr.s_addr = htonl(ip_addr);
379 msg.msg_flags = MSG_NOSIGNAL;//0/*MSG_DONTWAIT*/;;
381 msg.msg_namelen = sizeof(struct sockaddr_in);
382 msg.msg_control = NULL;
383 msg.msg_controllen = 0;
387 iov.iov_base = (char *)buf;
388 iov.iov_len = (size_t)len;
393 err = sock_sendmsg(sock->sock, &msg, (size_t)len);
403 palacios_recvfrom_ip(
404 const void * sock_ptr,
411 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
412 struct sockaddr_in src;
423 src.sin_family = AF_INET;
424 src.sin_port = htons(port);
425 src.sin_addr.s_addr = htonl(ip_addr);
431 msg.msg_namelen = sizeof(struct sockaddr_in);
432 msg.msg_control = NULL;
433 msg.msg_controllen = 0;
437 iov.iov_base = (void *)&buf[0];
438 iov.iov_len = (size_t)len;
443 err = sock_recvmsg(sock->sock, &msg, (size_t)len, 0/*MSG_DONTWAIT*/);
450 static struct v3_socket_hooks palacios_sock_hooks = {
451 .tcp_socket = palacios_tcp_socket,
452 .udp_socket = palacios_udp_socket,
453 .close = palacios_close,
454 .bind = palacios_bind_socket,
455 .listen = palacios_listen,
456 .accept = palacios_accept,
457 .select = palacios_select,
458 .connect_to_ip = palacios_connect_to_ip,
459 .connect_to_host = NULL,
460 .send = palacios_send,
461 .recv = palacios_recv,
463 .sendto_ip = palacios_sendto_ip,
464 .recvfrom_host = NULL,
465 .recvfrom_ip = palacios_recvfrom_ip,
468 static int socket_init( void ) {
469 V3_Init_Sockets(&palacios_sock_hooks);
470 INIT_LIST_HEAD(&global_sockets);
474 static int socket_deinit( void ) {
475 if (!list_empty(&(global_sockets))) {
476 printk("Error removing module with open sockets\n");
483 static struct linux_ext socket_ext = {
484 .name = "SOCKET_INTERFACE",
486 .deinit = socket_deinit,
491 register_extension(&socket_ext);