Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


ported socket interface to extension framework
[palacios.releases.git] / linux_module / palacios-socket.c
1 /*
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.
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2010, Lei Xia <lxia@northwestern.edu>
11  * Copyright (c) 2010, The V3VEE Project <http://www.v3vee.org>
12  * All rights reserved.
13  *
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.
18  */
19
20 #include <interfaces/vmm_socket.h>
21
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>
27 #include <linux/ip.h>
28 #include <linux/in.h>
29 #include <linux/string.h>
30 #include <linux/preempt.h>
31 #include <linux/sched.h>
32 #include <linux/list.h>
33
34 #include "palacios.h"
35 #include "linux-exts.h"
36
37
38 struct palacios_socket {
39     struct socket * sock;
40     
41     struct v3_guest * guest;
42     struct list_head sock_node;
43 };
44
45 static struct list_head global_sockets;
46
47
48 // currently just the list of created sockets
49 struct vm_socket_state {
50     struct list_head socket_list;
51 };
52
53
54 //ignore the arguments given here currently
55 static void * 
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;
61     int err;
62
63     if (guest != NULL) {
64         vm_state = get_vm_ext_data(guest, "SOCKET_INTERFACE");
65         
66         if (vm_state == NULL) {
67             printk("ERROR: Could not locate vm socket state for extension SOCKET_INTERFACE\n");
68             return NULL;
69         }
70     }
71
72
73     sock = kmalloc(sizeof(struct palacios_socket), GFP_KERNEL);
74     memset(sock, 0, sizeof(struct palacios_socket));
75
76     err = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &(sock->sock));
77
78     if (err < 0) {
79         kfree(sock);
80         return NULL;
81     }
82        
83     sock->guest = guest;
84     
85     if (guest == NULL) {
86         list_add(&(sock->sock_node), &global_sockets);
87     } else {
88         list_add(&(sock->sock_node), &(vm_state->socket_list));
89     }
90     
91     return sock;
92 }
93
94 //ignore the arguments given here currently
95 static void *
96 palacios_udp_socket(
97         const int bufsize,
98         const int nonblocking,
99         void * private_data
100 )
101 {
102     struct v3_guest * guest = (struct v3_guest *)private_data;
103     struct palacios_socket * sock = NULL;
104     struct vm_socket_state * vm_state = NULL;
105     int err;
106
107     if (guest != NULL) {
108         vm_state = get_vm_ext_data(guest, "SOCKET_INTERFACE");
109         
110         if (vm_state == NULL) {
111             printk("ERROR: Could not locate vm socket state for extension SOCKET_INTERFACE\n");
112             return NULL;
113         }
114     }
115
116
117     sock = kmalloc(sizeof(struct palacios_socket), GFP_KERNEL);
118     memset(sock, 0, sizeof(struct palacios_socket));
119
120     err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &(sock->sock)) ;
121         
122     if (err < 0){
123         kfree(sock);
124         return NULL;
125     }
126     
127     
128     sock->guest = guest;
129     
130     if (guest == NULL) {
131         list_add(&(sock->sock_node), &global_sockets);
132     } else {
133         list_add(&(sock->sock_node), &(vm_state->socket_list));
134     }
135
136     return sock;
137 }
138
139
140 static void 
141 palacios_close(void * sock_ptr)
142 {
143     struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
144
145     if (sock != NULL) {
146         sock->sock->ops->release(sock->sock);
147         
148         list_del(&(sock->sock_node));
149         kfree(sock);
150     }
151 }
152
153 static int 
154 palacios_bind_socket(
155         const void * sock_ptr,
156         const int port
157 )
158 {
159         struct sockaddr_in addr;
160         struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
161
162         if (sock == NULL) {
163             return -1;
164         }
165
166         addr.sin_family = AF_INET;
167         addr.sin_port = htons(port);
168         addr.sin_addr.s_addr = INADDR_ANY;
169
170         return sock->sock->ops->bind(sock->sock, (struct sockaddr *)&addr, sizeof(addr));
171 }
172
173 static int 
174 palacios_listen(
175         const void * sock_ptr,
176         int backlog
177 )
178 {
179         struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
180
181         if (sock == NULL) {
182             return -1;
183         }
184
185         return sock->sock->ops->listen(sock->sock, backlog);
186 }
187
188 static void * palacios_accept(const void * sock_ptr, unsigned int * remote_ip, unsigned int * port) {
189
190     struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
191     struct palacios_socket * newsock = NULL;
192     struct vm_socket_state * vm_state = NULL;
193     int err;
194
195     if (sock == NULL) {
196         return NULL;
197     }
198     
199     if (sock->guest != NULL) {
200         vm_state = get_vm_ext_data(sock->guest, "SOCKET_INTERFACE");
201         
202         if (vm_state == NULL) {
203             printk("ERROR: Could not locate vm socket state for extension SOCKET_INTERFACE\n");
204             return NULL;
205         }
206     }
207
208
209     newsock = kmalloc(sizeof(struct palacios_socket), GFP_KERNEL);
210
211     err = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &(newsock->sock));
212
213     if (err < 0) {
214         kfree(newsock);
215         return NULL;
216     }
217
218     newsock->sock->type = sock->sock->type;
219     newsock->sock->ops = sock->sock->ops;
220
221     err = newsock->sock->ops->accept(sock->sock, newsock->sock, 0);
222
223     if (err < 0){
224         kfree(newsock);
225         return NULL;
226     }
227
228     //TODO: How do we get ip & port?
229
230         
231     newsock->guest = sock->guest;
232     
233     if (sock->guest == NULL) {
234         list_add(&(newsock->sock_node), &global_sockets);
235     } else {
236         list_add(&(newsock->sock_node), &(vm_state->socket_list));
237     }
238
239     return newsock;
240 }
241
242 static int 
243 palacios_select(
244         struct v3_sock_set * rset,
245         struct v3_sock_set * wset,
246         struct v3_sock_set * eset,
247         struct v3_timeval tv)
248 {
249         //TODO:
250
251         return 0;
252 }
253
254 static int 
255 palacios_connect_to_ip(
256         const void * sock_ptr,
257         const int hostip,
258         const int port
259 )
260 {
261         struct sockaddr_in client;
262         struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
263
264         if (sock == NULL) {
265             return -1;
266         }
267
268         client.sin_family = AF_INET;
269         client.sin_port = htons(port);
270         client.sin_addr.s_addr = htonl(hostip);
271
272         return sock->sock->ops->connect(sock->sock, (struct sockaddr *)&client, sizeof(client), 0);
273 }
274
275 static int 
276 palacios_send(
277         const void * sock_ptr,
278         const char * buf,
279         const int len
280 )
281 {
282         struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
283         struct msghdr msg;
284         mm_segment_t oldfs;
285         struct iovec iov;
286         int err = 0;
287
288         if (sock == NULL) {
289             return -1;
290         }
291
292         msg.msg_flags = MSG_NOSIGNAL;//0/*MSG_DONTWAIT*/;;
293         msg.msg_name = 0;
294         msg.msg_namelen = 0;
295         msg.msg_control = NULL;
296         msg.msg_controllen = 0;
297         msg.msg_iov = &iov;
298         msg.msg_iovlen = 1;
299
300         iov.iov_base = (char *)buf;
301         iov.iov_len = (size_t)len;
302
303         oldfs = get_fs();
304         set_fs(KERNEL_DS);
305
306         err = sock_sendmsg(sock->sock, &msg, (size_t)len);
307
308         set_fs(oldfs);
309
310         return err;
311 }
312
313 static int 
314 palacios_recv(
315         const void * sock_ptr,
316         char * buf,
317         const int len
318 )
319 {
320
321         struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
322         struct msghdr msg;
323         mm_segment_t oldfs;
324         struct iovec iov;
325         int err;
326
327         if (sock == NULL) {
328             return -1;
329         }
330
331         msg.msg_flags = 0;
332         msg.msg_name = 0;
333         msg.msg_namelen = 0;
334         msg.msg_control = NULL;
335         msg.msg_controllen = 0;
336         msg.msg_iov = &iov;
337         msg.msg_iovlen = 1;
338
339         iov.iov_base = (void *)&buf[0];
340         iov.iov_len = (size_t)len;
341
342         oldfs = get_fs();
343         set_fs(KERNEL_DS);
344
345         err = sock_recvmsg(sock->sock, &msg, (size_t)len, 0/*MSG_DONTWAIT*/);
346
347         set_fs(oldfs);
348
349         return err;
350 }
351
352 static int 
353 palacios_sendto_ip(
354         const void * sock_ptr,
355         const int ip_addr,
356         const int port,
357         const char * buf,
358         const int len
359 )
360 {
361         struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
362         struct msghdr msg;
363         mm_segment_t oldfs;
364         struct iovec iov;
365         struct sockaddr_in dst;
366         int err = 0;
367
368         if (sock == NULL) {
369             return -1;
370         }
371
372         dst.sin_family = AF_INET;
373         dst.sin_port = htons(port);
374         dst.sin_addr.s_addr = htonl(ip_addr);
375
376         msg.msg_flags = MSG_NOSIGNAL;//0/*MSG_DONTWAIT*/;;
377         msg.msg_name = &dst;
378         msg.msg_namelen = sizeof(struct sockaddr_in);
379         msg.msg_control = NULL;
380         msg.msg_controllen = 0;
381         msg.msg_iov = &iov;
382         msg.msg_iovlen = 1;
383
384         iov.iov_base = (char *)buf;
385         iov.iov_len = (size_t)len;
386
387         oldfs = get_fs();
388         set_fs(KERNEL_DS);
389
390         err = sock_sendmsg(sock->sock, &msg, (size_t)len);
391
392         set_fs(oldfs);
393
394         return err;
395 }
396
397
398 // TODO:
399 static int 
400 palacios_recvfrom_ip(
401         const void * sock_ptr,
402         const int ip_addr,
403         const int port,
404         char * buf,
405         const int len
406 )
407 {
408         struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
409         struct sockaddr_in src;
410         int alen;
411         struct msghdr msg;
412         mm_segment_t oldfs;
413         struct iovec iov;
414         int err;
415
416         if (sock == NULL) {
417             return -1;
418         }
419
420         src.sin_family = AF_INET;
421         src.sin_port = htons(port);
422         src.sin_addr.s_addr = htonl(ip_addr);
423         alen = sizeof(src);
424
425
426         msg.msg_flags = 0;
427         msg.msg_name = &src;
428         msg.msg_namelen = sizeof(struct sockaddr_in);
429         msg.msg_control = NULL;
430         msg.msg_controllen = 0;
431         msg.msg_iov = &iov;
432         msg.msg_iovlen = 1;
433
434         iov.iov_base = (void *)&buf[0];
435         iov.iov_len = (size_t)len;
436
437         oldfs = get_fs();
438         set_fs(KERNEL_DS);
439
440         err = sock_recvmsg(sock->sock, &msg, (size_t)len, 0/*MSG_DONTWAIT*/);
441
442         set_fs(oldfs);
443
444         return err;
445 }
446
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,
459         .sendto_host = NULL,
460         .sendto_ip = palacios_sendto_ip,
461         .recvfrom_host = NULL,
462         .recvfrom_ip = palacios_recvfrom_ip,
463 };
464
465 static int socket_init( void ) {
466         V3_Init_Sockets(&palacios_sock_hooks);
467         INIT_LIST_HEAD(&global_sockets);
468         return 0;
469 }
470
471 static int socket_deinit( void ) {
472     if (!list_empty(&(global_sockets))) {
473         printk("Error removing module with open sockets\n");
474     }
475 }
476
477
478 static struct linux_ext socket_ext = {
479     .name "SOCKET_INTERFACE",
480     .init = socket_init,
481     .deinit = socket_deinit,
482     .guest_init = NULL,
483     .guest_deinit = NULL
484 };
485
486 register_extension(&socket_ext);