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.


7f0328c0fd53aac3deb6b9ba6aa6505a309ed914
[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         msg.msg_iov = &iov;
305         msg.msg_iovlen = 1;
306
307         iov.iov_base = (char *)buf;
308         iov.iov_len = (size_t)len;
309
310         oldfs = get_fs();
311         set_fs(KERNEL_DS);
312
313         err = sock_sendmsg(sock->sock, &msg, (size_t)len);
314
315         set_fs(oldfs);
316
317         return err;
318 }
319
320 static int 
321 palacios_recv(
322         const void * sock_ptr,
323         char * buf,
324         const int len
325 )
326 {
327
328         struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
329         struct msghdr msg;
330         mm_segment_t oldfs;
331         struct iovec iov;
332         int err;
333
334         if (sock == NULL) {
335             return -1;
336         }
337
338         msg.msg_flags = 0;
339         msg.msg_name = 0;
340         msg.msg_namelen = 0;
341         msg.msg_control = NULL;
342         msg.msg_controllen = 0;
343         msg.msg_iov = &iov;
344         msg.msg_iovlen = 1;
345
346         iov.iov_base = (void *)&buf[0];
347         iov.iov_len = (size_t)len;
348
349         oldfs = get_fs();
350         set_fs(KERNEL_DS);
351
352         err = sock_recvmsg(sock->sock, &msg, (size_t)len, 0/*MSG_DONTWAIT*/);
353
354         set_fs(oldfs);
355
356         return err;
357 }
358
359 static int 
360 palacios_sendto_ip(
361         const void * sock_ptr,
362         const int ip_addr,
363         const int port,
364         const char * buf,
365         const int len
366 )
367 {
368         struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
369         struct msghdr msg;
370         mm_segment_t oldfs;
371         struct iovec iov;
372         struct sockaddr_in dst;
373         int err = 0;
374
375         if (sock == NULL) {
376             return -1;
377         }
378
379         dst.sin_family = AF_INET;
380         dst.sin_port = htons(port);
381         dst.sin_addr.s_addr = htonl(ip_addr);
382
383         msg.msg_flags = MSG_NOSIGNAL;//0/*MSG_DONTWAIT*/;;
384         msg.msg_name = &dst;
385         msg.msg_namelen = sizeof(struct sockaddr_in);
386         msg.msg_control = NULL;
387         msg.msg_controllen = 0;
388         msg.msg_iov = &iov;
389         msg.msg_iovlen = 1;
390
391         iov.iov_base = (char *)buf;
392         iov.iov_len = (size_t)len;
393
394         oldfs = get_fs();
395         set_fs(KERNEL_DS);
396
397         err = sock_sendmsg(sock->sock, &msg, (size_t)len);
398
399         set_fs(oldfs);
400
401         return err;
402 }
403
404
405 // TODO:
406 static int 
407 palacios_recvfrom_ip(
408         const void * sock_ptr,
409         const int ip_addr,
410         const int port,
411         char * buf,
412         const int len
413 )
414 {
415         struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
416         struct sockaddr_in src;
417         struct msghdr msg;
418         mm_segment_t oldfs;
419         struct iovec iov;
420         int err;
421
422         if (sock == NULL) {
423             return -1;
424         }
425
426         src.sin_family = AF_INET;
427         src.sin_port = htons(port);
428         src.sin_addr.s_addr = htonl(ip_addr);
429
430
431         msg.msg_flags = 0;
432         msg.msg_name = &src;
433         msg.msg_namelen = sizeof(struct sockaddr_in);
434         msg.msg_control = NULL;
435         msg.msg_controllen = 0;
436         msg.msg_iov = &iov;
437         msg.msg_iovlen = 1;
438
439         iov.iov_base = (void *)&buf[0];
440         iov.iov_len = (size_t)len;
441
442         oldfs = get_fs();
443         set_fs(KERNEL_DS);
444
445         err = sock_recvmsg(sock->sock, &msg, (size_t)len, 0/*MSG_DONTWAIT*/);
446
447         set_fs(oldfs);
448
449         return err;
450 }
451
452 static struct v3_socket_hooks palacios_sock_hooks = {
453         .tcp_socket = palacios_tcp_socket,
454         .udp_socket = palacios_udp_socket,
455         .close = palacios_close,
456         .bind = palacios_bind_socket,
457         .listen = palacios_listen,
458         .accept = palacios_accept,
459         .select = palacios_select,
460         .connect_to_ip = palacios_connect_to_ip,
461         .connect_to_host = NULL,
462         .send = palacios_send,
463         .recv = palacios_recv,
464         .sendto_host = NULL,
465         .sendto_ip = palacios_sendto_ip,
466         .recvfrom_host = NULL,
467         .recvfrom_ip = palacios_recvfrom_ip,
468 };
469
470 static int socket_init( void ) {
471         V3_Init_Sockets(&palacios_sock_hooks);
472         INIT_LIST_HEAD(&global_sockets);
473         return 0;
474 }
475
476 static int socket_deinit( void ) {
477     if (!list_empty(&(global_sockets))) {
478         ERROR("Error removing module with open sockets\n");
479     }
480
481     return 0;
482 }
483
484
485 static struct linux_ext socket_ext = {
486     .name = "SOCKET_INTERFACE",
487     .init = socket_init,
488     .deinit = socket_deinit,
489     .guest_init = NULL,
490     .guest_deinit = NULL
491 };
492
493 register_extension(&socket_ext);