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.


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