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.


Linux kernel compatability enhancements (through 3.19)
[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             ERROR("ERROR: Could not locate vm socket state for extension SOCKET_INTERFACE\n");
55             return NULL;
56         }
57     }
58
59
60     sock = palacios_alloc(sizeof(struct palacios_socket));
61     
62     if (!sock) { 
63         ERROR("Cannot allocate TCP socket\n");
64         return NULL;
65     }
66
67     memset(sock, 0, sizeof(struct palacios_socket));
68
69     err = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &(sock->sock));
70
71     if (err < 0) {
72         ERROR("Cannot create TCP socket\n");
73         palacios_free(sock);
74         return NULL;
75     }
76        
77     sock->guest = guest;
78     
79     if (guest == NULL) {
80         list_add(&(sock->sock_node), &global_sockets);
81     } else {
82         list_add(&(sock->sock_node), &(vm_state->socket_list));
83     }
84     
85     return sock;
86 }
87
88 //ignore the arguments given here currently
89 static void *
90 palacios_udp_socket(
91         const int bufsize,
92         const int nonblocking,
93         void * private_data
94 )
95 {
96     struct v3_guest * guest = (struct v3_guest *)private_data;
97     struct palacios_socket * sock = NULL;
98     struct vm_socket_state * vm_state = NULL;
99     int err;
100
101     if (guest != NULL) {
102         vm_state = get_vm_ext_data(guest, "SOCKET_INTERFACE");
103         
104         if (vm_state == NULL) {
105             ERROR("ERROR: Could not locate vm socket state for extension SOCKET_INTERFACE\n");
106             return NULL;
107         }
108     }
109
110
111     sock = palacios_alloc(sizeof(struct palacios_socket));
112     if (!sock) { 
113         ERROR("Cannot allocate UDP socket\n");
114         return NULL;
115     }
116
117     memset(sock, 0, sizeof(struct palacios_socket));
118
119     err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &(sock->sock)) ;
120         
121     if (err < 0){
122         ERROR("Cannot create UDP socket\n");
123         palacios_free(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         palacios_free(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             ERROR("Could not locate vm socket state for extension SOCKET_INTERFACE\n");
204             return NULL;
205         }
206     }
207
208
209     newsock = palacios_alloc(sizeof(struct palacios_socket));
210
211     if (!newsock) { 
212         ERROR("Cannot allocate new socket on accept\n");
213         return NULL;
214     }
215
216     err = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &(newsock->sock));
217
218     if (err < 0) {
219         ERROR("Cannot create new socket on accept\n");
220         palacios_free(newsock);
221         return NULL;
222     }
223
224     newsock->sock->type = sock->sock->type;
225     newsock->sock->ops = sock->sock->ops;
226
227     err = newsock->sock->ops->accept(sock->sock, newsock->sock, 0);
228
229     if (err < 0){
230         ERROR("Cannot accept\n");
231         palacios_free(newsock);
232         return NULL;
233     }
234
235     //TODO: How do we get ip & port?
236
237         
238     newsock->guest = sock->guest;
239     
240     if (sock->guest == NULL) {
241         list_add(&(newsock->sock_node), &global_sockets);
242     } else {
243         list_add(&(newsock->sock_node), &(vm_state->socket_list));
244     }
245
246     return newsock;
247 }
248
249 static int 
250 palacios_select(
251         struct v3_sock_set * rset,
252         struct v3_sock_set * wset,
253         struct v3_sock_set * eset,
254         struct v3_timeval tv)
255 {
256         //TODO:
257
258         return 0;
259 }
260
261 static int 
262 palacios_connect_to_ip(
263         const void * sock_ptr,
264         const int hostip,
265         const int port
266 )
267 {
268         struct sockaddr_in client;
269         struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
270
271         if (sock == NULL) {
272             return -1;
273         }
274
275         client.sin_family = AF_INET;
276         client.sin_port = htons(port);
277         client.sin_addr.s_addr = htonl(hostip);
278
279         return sock->sock->ops->connect(sock->sock, (struct sockaddr *)&client, sizeof(client), 0);
280 }
281
282 static int 
283 palacios_send(
284         const void * sock_ptr,
285         const char * buf,
286         const int len
287 )
288 {
289         struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
290         struct msghdr msg;
291         mm_segment_t oldfs;
292         struct iovec iov;
293         int err = 0;
294
295         if (sock == NULL) {
296             return -1;
297         }
298
299         msg.msg_flags = MSG_NOSIGNAL;//0/*MSG_DONTWAIT*/;;
300         msg.msg_name = 0;
301         msg.msg_namelen = 0;
302         msg.msg_control = NULL;
303         msg.msg_controllen = 0;
304 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
305         msg.msg_iov = &iov;
306         msg.msg_iovlen = 1;
307 #else
308         iov_iter_init(&(msg.msg_iter),WRITE,&iov,1,0);
309 #endif
310
311         iov.iov_base = (char *)buf;
312         iov.iov_len = (size_t)len;
313
314         oldfs = get_fs();
315         set_fs(KERNEL_DS);
316
317         err = sock_sendmsg(sock->sock, &msg, (size_t)len);
318
319         set_fs(oldfs);
320
321         return err;
322 }
323
324 static int 
325 palacios_recv(
326         const void * sock_ptr,
327         char * buf,
328         const int len
329 )
330 {
331
332         struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
333         struct msghdr msg;
334         mm_segment_t oldfs;
335         struct iovec iov;
336         int err;
337
338         if (sock == NULL) {
339             return -1;
340         }
341
342         msg.msg_flags = 0;
343         msg.msg_name = 0;
344         msg.msg_namelen = 0;
345         msg.msg_control = NULL;
346         msg.msg_controllen = 0;
347 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
348         msg.msg_iov = &iov;
349         msg.msg_iovlen = 1;
350 #else
351         iov_iter_init(&(msg.msg_iter),READ,&iov,1,0);
352 #endif
353
354         iov.iov_base = (void *)&buf[0];
355         iov.iov_len = (size_t)len;
356
357         oldfs = get_fs();
358         set_fs(KERNEL_DS);
359
360         err = sock_recvmsg(sock->sock, &msg, (size_t)len, 0/*MSG_DONTWAIT*/);
361
362         set_fs(oldfs);
363
364         return err;
365 }
366
367 static int 
368 palacios_sendto_ip(
369         const void * sock_ptr,
370         const int ip_addr,
371         const int port,
372         const char * buf,
373         const int len
374 )
375 {
376         struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
377         struct msghdr msg;
378         mm_segment_t oldfs;
379         struct iovec iov;
380         struct sockaddr_in dst;
381         int err = 0;
382
383         if (sock == NULL) {
384             return -1;
385         }
386
387         dst.sin_family = AF_INET;
388         dst.sin_port = htons(port);
389         dst.sin_addr.s_addr = htonl(ip_addr);
390
391         msg.msg_flags = MSG_NOSIGNAL;//0/*MSG_DONTWAIT*/;;
392         msg.msg_name = &dst;
393         msg.msg_namelen = sizeof(struct sockaddr_in);
394         msg.msg_control = NULL;
395         msg.msg_controllen = 0;
396 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
397         msg.msg_iov = &iov;
398         msg.msg_iovlen = 1;
399 #else
400         iov_iter_init(&(msg.msg_iter),WRITE,&iov,1,0);
401 #endif
402
403         iov.iov_base = (char *)buf;
404         iov.iov_len = (size_t)len;
405
406         oldfs = get_fs();
407         set_fs(KERNEL_DS);
408
409         err = sock_sendmsg(sock->sock, &msg, (size_t)len);
410
411         set_fs(oldfs);
412
413         return err;
414 }
415
416
417 // TODO:
418 static int 
419 palacios_recvfrom_ip(
420         const void * sock_ptr,
421         const int ip_addr,
422         const int port,
423         char * buf,
424         const int len
425 )
426 {
427         struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
428         struct sockaddr_in src;
429         struct msghdr msg;
430         mm_segment_t oldfs;
431         struct iovec iov;
432         int err;
433
434         if (sock == NULL) {
435             return -1;
436         }
437
438         src.sin_family = AF_INET;
439         src.sin_port = htons(port);
440         src.sin_addr.s_addr = htonl(ip_addr);
441
442
443         msg.msg_flags = 0;
444         msg.msg_name = &src;
445         msg.msg_namelen = sizeof(struct sockaddr_in);
446         msg.msg_control = NULL;
447         msg.msg_controllen = 0;
448 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
449         msg.msg_iov = &iov;
450         msg.msg_iovlen = 1;
451 #else
452         iov_iter_init(&(msg.msg_iter),READ,&iov,1,0);
453 #endif
454
455         iov.iov_base = (void *)&buf[0];
456         iov.iov_len = (size_t)len;
457
458         oldfs = get_fs();
459         set_fs(KERNEL_DS);
460
461         err = sock_recvmsg(sock->sock, &msg, (size_t)len, 0/*MSG_DONTWAIT*/);
462
463         set_fs(oldfs);
464
465         return err;
466 }
467
468 static struct v3_socket_hooks palacios_sock_hooks = {
469         .tcp_socket = palacios_tcp_socket,
470         .udp_socket = palacios_udp_socket,
471         .close = palacios_close,
472         .bind = palacios_bind_socket,
473         .listen = palacios_listen,
474         .accept = palacios_accept,
475         .select = palacios_select,
476         .connect_to_ip = palacios_connect_to_ip,
477         .connect_to_host = NULL,
478         .send = palacios_send,
479         .recv = palacios_recv,
480         .sendto_host = NULL,
481         .sendto_ip = palacios_sendto_ip,
482         .recvfrom_host = NULL,
483         .recvfrom_ip = palacios_recvfrom_ip,
484 };
485
486 static int socket_init( void ) {
487         V3_Init_Sockets(&palacios_sock_hooks);
488         INIT_LIST_HEAD(&global_sockets);
489         return 0;
490 }
491
492 static int socket_deinit( void ) {
493     if (!list_empty(&(global_sockets))) {
494         ERROR("Error removing module with open sockets\n");
495     }
496
497     return 0;
498 }
499
500
501 static struct linux_ext socket_ext = {
502     .name = "SOCKET_INTERFACE",
503     .init = socket_init,
504     .deinit = socket_deinit,
505     .guest_init = NULL,
506     .guest_deinit = NULL
507 };
508
509 register_extension(&socket_ext);