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.


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