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 #include <interfaces/vmm_socket.h>
22 #include <linux/spinlock.h>
23 #include <asm/uaccess.h>
24 #include <linux/inet.h>
25 #include <linux/kthread.h>
26 #include <linux/netdevice.h>
29 #include <linux/string.h>
30 #include <linux/preempt.h>
31 #include <linux/sched.h>
32 #include <linux/list.h>
35 #include "linux-exts.h"
38 struct palacios_socket {
41 struct v3_guest * guest;
42 struct list_head sock_node;
45 static struct list_head global_sockets;
48 // currently just the list of created sockets
49 struct vm_socket_state {
50 struct list_head socket_list;
54 //ignore the arguments given here currently
56 palacios_tcp_socket(const int bufsize, const int nodelay,
57 const int nonblocking, void * private_data) {
58 struct v3_guest * guest = (struct v3_guest *)private_data;
59 struct palacios_socket * sock = NULL;
60 struct vm_socket_state * vm_state = NULL;
64 vm_state = get_vm_ext_data(guest, "SOCKET_INTERFACE");
66 if (vm_state == NULL) {
67 printk("ERROR: Could not locate vm socket state for extension SOCKET_INTERFACE\n");
73 sock = kmalloc(sizeof(struct palacios_socket), GFP_KERNEL);
74 memset(sock, 0, sizeof(struct palacios_socket));
76 err = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &(sock->sock));
86 list_add(&(sock->sock_node), &global_sockets);
88 list_add(&(sock->sock_node), &(vm_state->socket_list));
94 //ignore the arguments given here currently
98 const int nonblocking,
102 struct v3_guest * guest = (struct v3_guest *)private_data;
103 struct palacios_socket * sock = NULL;
104 struct vm_socket_state * vm_state = NULL;
108 vm_state = get_vm_ext_data(guest, "SOCKET_INTERFACE");
110 if (vm_state == NULL) {
111 printk("ERROR: Could not locate vm socket state for extension SOCKET_INTERFACE\n");
117 sock = kmalloc(sizeof(struct palacios_socket), GFP_KERNEL);
118 memset(sock, 0, sizeof(struct palacios_socket));
120 err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &(sock->sock)) ;
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 printk("ERROR: Could not locate vm socket state for extension SOCKET_INTERFACE\n");
209 newsock = kmalloc(sizeof(struct palacios_socket), GFP_KERNEL);
211 err = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &(newsock->sock));
218 newsock->sock->type = sock->sock->type;
219 newsock->sock->ops = sock->sock->ops;
221 err = newsock->sock->ops->accept(sock->sock, newsock->sock, 0);
228 //TODO: How do we get ip & port?
231 newsock->guest = sock->guest;
233 if (sock->guest == NULL) {
234 list_add(&(newsock->sock_node), &global_sockets);
236 list_add(&(newsock->sock_node), &(vm_state->socket_list));
244 struct v3_sock_set * rset,
245 struct v3_sock_set * wset,
246 struct v3_sock_set * eset,
247 struct v3_timeval tv)
255 palacios_connect_to_ip(
256 const void * sock_ptr,
261 struct sockaddr_in client;
262 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
268 client.sin_family = AF_INET;
269 client.sin_port = htons(port);
270 client.sin_addr.s_addr = htonl(hostip);
272 return sock->sock->ops->connect(sock->sock, (struct sockaddr *)&client, sizeof(client), 0);
277 const void * sock_ptr,
282 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
292 msg.msg_flags = MSG_NOSIGNAL;//0/*MSG_DONTWAIT*/;;
295 msg.msg_control = NULL;
296 msg.msg_controllen = 0;
300 iov.iov_base = (char *)buf;
301 iov.iov_len = (size_t)len;
306 err = sock_sendmsg(sock->sock, &msg, (size_t)len);
315 const void * sock_ptr,
321 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
334 msg.msg_control = NULL;
335 msg.msg_controllen = 0;
339 iov.iov_base = (void *)&buf[0];
340 iov.iov_len = (size_t)len;
345 err = sock_recvmsg(sock->sock, &msg, (size_t)len, 0/*MSG_DONTWAIT*/);
354 const void * sock_ptr,
361 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
365 struct sockaddr_in dst;
372 dst.sin_family = AF_INET;
373 dst.sin_port = htons(port);
374 dst.sin_addr.s_addr = htonl(ip_addr);
376 msg.msg_flags = MSG_NOSIGNAL;//0/*MSG_DONTWAIT*/;;
378 msg.msg_namelen = sizeof(struct sockaddr_in);
379 msg.msg_control = NULL;
380 msg.msg_controllen = 0;
384 iov.iov_base = (char *)buf;
385 iov.iov_len = (size_t)len;
390 err = sock_sendmsg(sock->sock, &msg, (size_t)len);
400 palacios_recvfrom_ip(
401 const void * sock_ptr,
408 struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
409 struct sockaddr_in src;
420 src.sin_family = AF_INET;
421 src.sin_port = htons(port);
422 src.sin_addr.s_addr = htonl(ip_addr);
428 msg.msg_namelen = sizeof(struct sockaddr_in);
429 msg.msg_control = NULL;
430 msg.msg_controllen = 0;
434 iov.iov_base = (void *)&buf[0];
435 iov.iov_len = (size_t)len;
440 err = sock_recvmsg(sock->sock, &msg, (size_t)len, 0/*MSG_DONTWAIT*/);
447 static struct v3_socket_hooks palacios_sock_hooks = {
448 .tcp_socket = palacios_tcp_socket,
449 .udp_socket = palacios_udp_socket,
450 .close = palacios_close,
451 .bind = palacios_bind_socket,
452 .listen = palacios_listen,
453 .accept = palacios_accept,
454 .select = palacios_select,
455 .connect_to_ip = palacios_connect_to_ip,
456 .connect_to_host = NULL,
457 .send = palacios_send,
458 .recv = palacios_recv,
460 .sendto_ip = palacios_sendto_ip,
461 .recvfrom_host = NULL,
462 .recvfrom_ip = palacios_recvfrom_ip,
465 static int socket_init( void ) {
466 V3_Init_Sockets(&palacios_sock_hooks);
467 INIT_LIST_HEAD(&global_sockets);
471 static int socket_deinit( void ) {
472 if (!list_empty(&(global_sockets))) {
473 printk("Error removing module with open sockets\n");
478 static struct linux_ext socket_ext = {
479 .name "SOCKET_INTERFACE",
481 .deinit = socket_deinit,
486 register_extension(&socket_ext);