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 / palacios-vnet-brg.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) 2011, Lei Xia <lxia@northwestern.edu>
11  * Copyright (c) 2011, 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 /* Palacios VNET Host Bridge */
20
21 #include <linux/spinlock.h>
22 #include <linux/seq_file.h>
23 #include <linux/proc_fs.h>
24 #include <asm/uaccess.h>
25 #include <linux/inet.h>
26 #include <linux/kthread.h>
27
28 #include <linux/netdevice.h>
29 #include <linux/ip.h>
30 #include <linux/in.h>
31 #include <linux/net.h>
32 #include <linux/string.h>
33 #include <linux/preempt.h>
34 #include <linux/sched.h>
35 #include <asm/msr.h>
36
37 #include <vnet/vnet.h>
38 #include <vnet/vnet_hashtable.h>
39 #include "palacios-vnet.h"
40
41 #define VNET_SERVER_PORT 9000
42
43 struct vnet_link {
44     uint32_t dst_ip;
45     uint16_t dst_port;
46     
47     struct socket * sock;
48     struct sockaddr_in sock_addr;
49     vnet_brg_proto_t sock_proto;
50
51     struct nic_statistics stats;
52
53     uint32_t idx;
54
55     struct list_head node;
56 };
57
58
59 struct vnet_brg_state {
60     uint8_t status;
61
62     uint32_t num_links;
63     uint32_t link_idx;
64     struct list_head link_list;
65     struct hashtable *ip2link;
66
67     spinlock_t lock;
68
69     struct socket * serv_sock;
70     struct sockaddr_in serv_addr;
71     vnet_brg_proto_t serv_proto;
72         
73     struct task_struct * serv_thread;
74
75     void * brg_data; /* private data from vnet_core */
76
77     struct vnet_brg_stats stats;
78 };
79
80
81 static struct vnet_brg_state vnet_brg_s;
82
83
84 int vnet_brg_stats(struct vnet_brg_stats * stats){
85     memcpy(stats, &(vnet_brg_s.stats), sizeof(*stats));
86
87     return 0;
88 }
89
90 static inline struct vnet_link * _link_by_ip(uint32_t ip) {
91     return (struct vnet_link *)vnet_htable_search(vnet_brg_s.ip2link, (addr_t)&ip);
92 }
93
94 static inline struct vnet_link * _link_by_idx(int idx) {
95     struct vnet_link * link = NULL;
96
97     list_for_each_entry(link, &(vnet_brg_s.link_list), node) {
98                 
99         if (link->idx == idx) {
100             return link;
101         }
102     }
103     return NULL;
104 }
105
106
107 static void _delete_link(struct vnet_link * link){
108     unsigned long flags;
109
110     link->sock->ops->release(link->sock);
111
112     spin_lock_irqsave(&(vnet_brg_s.lock), flags);
113     list_del(&(link->node));
114     vnet_htable_remove(vnet_brg_s.ip2link, (addr_t)&(link->dst_ip), 0);
115     vnet_brg_s.num_links --;
116     spin_unlock_irqrestore(&(vnet_brg_s.lock), flags);
117
118     printk("VNET Bridge: Link deleted, ip 0x%x, port: %d, idx: %d\n", 
119            link->dst_ip, 
120            link->dst_port, 
121            link->idx);
122
123     kfree(link);
124     link = NULL;
125 }
126
127 void vnet_brg_delete_link(uint32_t idx){
128     struct vnet_link * link = _link_by_idx(idx);
129
130     if(link){
131         _delete_link(link);
132     }
133 }
134
135 static void deinit_links_list(void){
136     struct vnet_link * link;
137
138     list_for_each_entry(link, &(vnet_brg_s.link_list), node) {
139         _delete_link(link);
140     }
141 }
142
143 static uint32_t _create_link(struct vnet_link * link) {
144     int err;
145     unsigned long flags;
146     int protocol;
147
148     switch(link->sock_proto){
149         case UDP:
150             protocol = IPPROTO_UDP;
151             break;
152         case TCP:
153             protocol = IPPROTO_TCP;
154             break;
155
156         default:
157            printk("Unsupported VNET Server Protocol\n");
158             return -1;
159     }
160    
161     if ((err = sock_create(AF_INET, SOCK_DGRAM, protocol, &link->sock)) < 0) {
162         printk("Could not create socket for VNET Link, error %d\n", err);
163         return -1;
164     }
165
166     memset(&link->sock_addr, 0, sizeof(struct sockaddr));
167
168     link->sock_addr.sin_family = AF_INET;
169     link->sock_addr.sin_addr.s_addr = link->dst_ip;
170     link->sock_addr.sin_port = htons(link->dst_port);
171
172     if ((err = link->sock->ops->connect(link->sock, (struct sockaddr *)&(link->sock_addr), sizeof(struct sockaddr), 0) < 0)) {
173         printk("Could not connect to remote VNET Server, error %d\n", err);
174         return -1;
175     }
176
177     spin_lock_irqsave(&(vnet_brg_s.lock), flags);
178     list_add(&(link->node), &(vnet_brg_s.link_list));
179     vnet_brg_s.num_links ++;
180     link->idx = ++ vnet_brg_s.link_idx;
181     vnet_htable_insert(vnet_brg_s.ip2link, (addr_t)&(link->dst_ip), (addr_t)link);
182     spin_unlock_irqrestore(&(vnet_brg_s.lock), flags);
183
184     printk("VNET Bridge: Link created, ip 0x%x, port: %d, idx: %d, link: %p, protocol: %s\n", 
185            link->dst_ip, 
186            link->dst_port, 
187            link->idx, 
188            link,
189            ((link->sock_proto==UDP)?"UDP":"TCP"));
190
191     return link->idx;
192 }
193
194
195 uint32_t vnet_brg_add_link(uint32_t ip, uint16_t port, vnet_brg_proto_t proto){
196      struct vnet_link * new_link = NULL;
197      uint32_t idx;
198
199      new_link = kmalloc(sizeof(struct vnet_link), GFP_KERNEL);
200      if (!new_link) {
201         return -1;
202      }
203      memset(new_link, 0, sizeof(struct vnet_link));
204
205      new_link->dst_ip = ip;
206      new_link->dst_port = port;
207      new_link->sock_proto = proto;
208
209      idx = _create_link(new_link);
210      if (idx < 0) {
211         printk("Could not create link\n");
212         kfree(new_link);
213         return -1;
214      }
215
216      return idx;
217 }
218
219
220 int vnet_brg_link_stats(uint32_t link_idx, struct nic_statistics * stats){
221      struct vnet_link * link;
222
223      link = _link_by_idx(link_idx);
224      if(!link){
225          return -1;
226      }
227
228      memcpy(stats, &(link->stats), sizeof(*stats));
229
230      return 0;
231 }
232      
233
234 static int 
235 _udp_send(struct socket * sock, 
236          struct sockaddr_in * addr,
237          unsigned char * buf,  int len) {
238     struct msghdr msg;
239     struct iovec iov;
240     mm_segment_t oldfs;
241     int size = 0;
242
243           
244     if (sock->sk == NULL) {
245         return 0;
246     }
247
248     iov.iov_base = buf;
249     iov.iov_len = len;
250
251     msg.msg_flags = 0;
252     msg.msg_name = addr;
253     msg.msg_namelen = sizeof(struct sockaddr_in);
254     msg.msg_control = NULL;
255     msg.msg_controllen = 0;
256     msg.msg_iov = &iov;
257     msg.msg_iovlen = 1;
258     msg.msg_control = NULL;
259
260     oldfs = get_fs();
261     set_fs(KERNEL_DS);
262     size = sock_sendmsg(sock, &msg, len);
263     set_fs(oldfs);
264
265     return size;
266 }
267
268
269
270 static int 
271 _udp_recv(struct socket * sock, 
272          struct sockaddr_in * addr,
273          unsigned char * buf, int len) {
274     struct msghdr msg;
275     struct iovec iov;
276     mm_segment_t oldfs;
277     int size = 0;
278     
279     if (sock->sk == NULL) {
280         return 0;
281     }
282
283     iov.iov_base = buf;
284     iov.iov_len = len;
285     
286     msg.msg_flags = 0;
287     msg.msg_name = addr;
288     msg.msg_namelen = sizeof(struct sockaddr_in);
289     msg.msg_control = NULL;
290     msg.msg_controllen = 0;
291     msg.msg_iov = &iov;
292     msg.msg_iovlen = 1;
293     msg.msg_control = NULL;
294     
295     oldfs = get_fs();
296     set_fs(KERNEL_DS);
297     size = sock_recvmsg(sock, &msg, len, msg.msg_flags);
298         
299     set_fs(oldfs);
300     
301     return size;
302 }
303
304 /* send packets to VNET core */
305 static int 
306 send_to_palacios(unsigned char * buf, 
307                  int len,
308                  int link_id){
309     struct v3_vnet_pkt pkt;
310     pkt.size = len;
311     pkt.src_type = LINK_EDGE;
312     pkt.src_id = link_id;
313     memcpy(pkt.header, buf, ETHERNET_HEADER_LEN);
314     pkt.data = buf;
315
316     if(net_debug >= 2){
317         printk("VNET Lnx Bridge: send pkt to VNET core (size: %d, src_id: %d, src_type: %d)\n", 
318                         pkt.size,  pkt.src_id, pkt.src_type);
319         if(net_debug >= 4){
320             print_hex_dump(NULL, "pkt_data: ", 0, 20, 20, pkt.data, pkt.size, 0);
321         }
322     }
323
324     vnet_brg_s.stats.pkt_to_vmm ++;
325
326     return v3_vnet_send_pkt(&pkt, NULL, 1);
327 }
328
329
330 /* send packet to extern network */
331 static int 
332 bridge_send_pkt(struct v3_vm_info * vm, 
333                 struct v3_vnet_pkt * pkt, 
334                 void * private_data) {
335     struct vnet_link * link;
336
337     if(net_debug >= 2){
338         printk("VNET Lnx Host Bridge: packet received from VNET Core ... pkt size: %d, link: %d\n",
339                         pkt->size,
340                         pkt->dst_id);
341         if(net_debug >= 4){
342             print_hex_dump(NULL, "pkt_data: ", 0, 20, 20, pkt->data, pkt->size, 0);
343         }
344     }
345
346     vnet_brg_s.stats.pkt_from_vmm ++;
347
348     link = _link_by_idx(pkt->dst_id);
349     if (link != NULL) {
350         switch(link->sock_proto){
351             case UDP:
352                 _udp_send(link->sock, &(link->sock_addr), pkt->data, pkt->size);
353                 vnet_brg_s.stats.pkt_to_phy ++;
354                 break;
355             case TCP:
356                 vnet_brg_s.stats.pkt_to_phy ++;
357                 break;  
358
359             default:
360                 printk("VNET Server: Invalid Link Protocol\n");
361                 vnet_brg_s.stats.pkt_drop_vmm ++;
362         }
363         link->stats.tx_bytes += pkt->size;
364         link->stats.tx_pkts ++;
365     } else {
366         printk("VNET Bridge Linux Host: wrong dst link, idx: %d, discards the packet\n", pkt->dst_id);
367         vnet_brg_s.stats.pkt_drop_vmm ++;
368     }
369
370     return 0;
371 }
372
373
374 static int init_vnet_serv(void) {
375     int protocol;
376     int err;
377
378     switch(vnet_brg_s.serv_proto){
379         case UDP:
380             protocol = IPPROTO_UDP;
381             break;
382         case TCP:
383             protocol = IPPROTO_TCP;
384             break;
385
386         default:
387            printk("Unsupported VNET Server Protocol\n");
388             return -1;
389     }
390          
391     if ((err = sock_create(AF_INET, SOCK_DGRAM, protocol, &vnet_brg_s.serv_sock)) < 0) {
392         printk("Could not create VNET server socket, error: %d\n", err);
393         return -1;
394     }
395
396     memset(&vnet_brg_s.serv_addr, 0, sizeof(struct sockaddr));
397
398     vnet_brg_s.serv_addr.sin_family = AF_INET;
399     vnet_brg_s.serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
400     vnet_brg_s.serv_addr.sin_port = htons(VNET_SERVER_PORT);
401
402     if ((err = vnet_brg_s.serv_sock->ops->bind(vnet_brg_s.serv_sock, (struct sockaddr *)&(vnet_brg_s.serv_addr), sizeof(struct sockaddr))) < 0) {
403         printk("Could not bind VNET server socket to port %d, error: %d\n", VNET_SERVER_PORT, err);
404         return -1;
405     }
406
407     printk("VNET server bind to port: %d\n", VNET_SERVER_PORT);
408
409     if(vnet_brg_s.serv_proto == TCP){
410         if((err = vnet_brg_s.serv_sock->ops->listen(vnet_brg_s.serv_sock, 32)) < 0){
411             printk("VNET Server error listening on port %d, error %d\n", VNET_SERVER_PORT, err);
412             return -1;
413         }
414     }
415
416     return 0;
417 }
418
419 static int _udp_server(void * arg) {
420     unsigned char * pkt;
421     struct sockaddr_in pkt_addr;
422     struct vnet_link * link = NULL;
423     int len;
424
425     printk("Palacios VNET Bridge: UDP receiving server ..... \n");
426
427     pkt = kmalloc(MAX_PACKET_LEN, GFP_KERNEL);
428     while (!kthread_should_stop()) {
429         
430         len = _udp_recv(vnet_brg_s.serv_sock, &pkt_addr, pkt, MAX_PACKET_LEN); 
431         if(len < 0) {
432             printk("Receive error: Could not get packet, error %d\n", len);
433             continue;
434         }
435
436         link = _link_by_ip(pkt_addr.sin_addr.s_addr);
437         if (link == NULL){
438             printk("VNET Server: No VNET Link match the src IP\n");
439             vnet_brg_s.stats.pkt_drop_phy ++;
440             continue;
441         }
442         
443         vnet_brg_s.stats.pkt_from_phy ++;
444         link->stats.rx_bytes += len;
445         link->stats.rx_pkts ++;
446
447         send_to_palacios(pkt, len, link->idx);
448     }
449
450     kfree(pkt);
451
452     return 0;
453 }
454
455
456 static int _rx_server(void * arg) {
457     
458     if(vnet_brg_s.serv_proto == UDP){
459         _udp_server(NULL);
460     }else if(vnet_brg_s.serv_proto == TCP) {
461         //accept new connection
462         //use select to receive pkt from physical network
463         //or create new kthread to handle each connection?
464     }else {
465         printk ("VNET Server: Unsupported Protocol\n");
466         return -1;
467     }
468
469     return 0;
470 }
471
472 static inline unsigned int hash_fn(addr_t hdr_ptr) {    
473     return vnet_hash_buffer((uint8_t *)hdr_ptr, sizeof(uint32_t));
474 }
475
476 static inline int hash_eq(addr_t key1, addr_t key2) {   
477     return (memcmp((uint8_t *)key1, (uint8_t *)key2, sizeof(uint32_t)) == 0);
478 }
479
480
481 int vnet_bridge_init(void) {
482     struct v3_vnet_bridge_ops bridge_ops;
483
484     if(vnet_brg_s.status != 0) {
485         return -1;
486     }   
487     vnet_brg_s.status = 1;      
488         
489     memset(&vnet_brg_s, 0, sizeof(struct vnet_brg_state));
490
491     INIT_LIST_HEAD(&(vnet_brg_s.link_list));
492     spin_lock_init(&(vnet_brg_s.lock));
493
494     vnet_brg_s.serv_proto = UDP;
495
496     vnet_brg_s.ip2link = vnet_create_htable(10, hash_fn, hash_eq);
497     if(vnet_brg_s.ip2link == NULL){
498         printk("Failure to initiate VNET link hashtable\n");
499         return -1;
500     }
501         
502     if(init_vnet_serv() < 0){
503         printk("Failure to initiate VNET server\n");
504         return -1;
505     }
506
507     vnet_brg_s.serv_thread = kthread_run(_rx_server, NULL, "vnet-server");
508
509     bridge_ops.input = bridge_send_pkt;
510     bridge_ops.poll = NULL;
511         
512     if( v3_vnet_add_bridge(NULL, &bridge_ops, HOST_LNX_BRIDGE, NULL) < 0){
513         printk("VNET LNX Bridge: Fails to register bridge to VNET core");
514     }
515
516     printk("VNET Linux Bridge initiated\n");
517
518     return 0;
519 }
520
521
522 void vnet_bridge_deinit(void){
523
524     v3_vnet_del_bridge(HOST_LNX_BRIDGE);
525
526     kthread_stop(vnet_brg_s.serv_thread);
527     vnet_brg_s.serv_sock->ops->release(vnet_brg_s.serv_sock);
528
529     deinit_links_list();
530
531     vnet_free_htable(vnet_brg_s.ip2link, 0, 0);
532
533     vnet_brg_s.status = 0;
534 }
535
536