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 VNET Linux backend code to Linux_module directory
[palacios.git] / linux_module / palacios-vnet.c
1 /* 
2    Palacios VNET interface
3    (c) Lei Xia, 2010
4  */
5 #include <linux/spinlock.h>
6 #include <linux/seq_file.h>
7 #include <linux/proc_fs.h>
8 #include <asm/uaccess.h>
9 #include <linux/inet.h>
10 #include <linux/kthread.h>
11
12 #include <linux/netdevice.h>
13 #include <linux/ip.h>
14 #include <linux/in.h>
15 #include <linux/string.h>
16 #include <linux/preempt.h>
17 #include <linux/sched.h>
18 #include <asm/msr.h>
19
20 #include <palacios/vmm_vnet.h>
21 #include "palacios-vnet.h"
22
23 //#define DEBUG_VNET_BRIGE
24
25 #define VNET_UDP_PORT 9000
26
27 struct palacios_vnet_route {
28     struct v3_vnet_route route;
29
30     int route_idx;
31
32     struct list_head node;
33 };
34
35
36 struct vnet_link {
37     uint32_t dst_ip;
38     uint16_t dst_port;
39     
40     struct socket * sock;
41     struct sockaddr_in sock_addr;
42
43     int link_idx;
44
45     struct list_head node;
46 };
47
48 struct palacios_vnet_state {
49     uint32_t num_routes;
50     uint32_t num_links; 
51
52     struct list_head route_list;
53     struct list_head link_list;
54
55     struct socket * serv_sock;
56     struct sockaddr_in serv_addr;
57
58     /* The thread recving pkts from sockets. */
59     struct task_struct * serv_thread;
60     spinlock_t lock;
61
62     unsigned long pkt_sent, pkt_recv, pkt_drop, pkt_udp_recv, pkt_udp_send;
63 };
64
65
66 static struct palacios_vnet_state vnet_state;
67
68
69 struct vnet_link * link_by_ip(uint32_t ip) {
70     struct vnet_link * link = NULL;
71
72     list_for_each_entry(link, &(vnet_state.link_list), node) {
73
74         if (link->dst_ip == ip) {
75             return link;
76         }
77     }
78
79     return NULL;
80 }
81
82 struct vnet_link * link_by_idx(int idx) {
83     struct vnet_link * link = NULL;
84
85     list_for_each_entry(link, &(vnet_state.link_list), node) {
86
87         if (link->link_idx == idx) {
88             return link;
89         }
90     }
91     return NULL;
92 }
93
94 struct palacios_vnet_route * route_by_idx(int idx) {
95     struct palacios_vnet_route * route = NULL;
96
97     list_for_each_entry(route, &(vnet_state.route_list), node) {
98
99         if (route->route_idx == idx) {
100             return route;
101         }
102     }
103
104     return NULL;
105 }
106
107
108 static int parse_mac_str(char * str, uint8_t * qual, uint8_t * mac) {
109     char * token;
110
111     printk("Parsing MAC (%s)\n", str);
112         
113     *qual = MAC_NOSET;
114     if(strnicmp("any", str, strlen(str)) == 0){
115         *qual = MAC_ANY;
116         return 0;
117     }else if(strnicmp("none", str, strlen(str)) == 0){
118        *qual = MAC_NONE;
119         return 0;
120     }else{
121         if (strstr(str, "-")) {
122             token = strsep(&str, "-");
123
124             if (strnicmp("not", token, strlen("not")) == 0) {
125                 *qual = MAC_NOT;
126             } else {
127                 printk("Invalid MAC String token (%s)\n", token);
128                 return -1;
129             }
130         }
131
132         if (strstr(str, ":")) {
133             int i = 0;
134
135             if(*qual == MAC_NOSET){
136                 *qual = MAC_ADDR;
137             }
138
139             for (i = 0; i < 6; i++) {
140                 token = strsep(&str, ":");
141                 if (!token) {
142                     printk("Invalid MAC String token (%s)\n", token);
143                     return -1;
144                 }
145                 mac[i] = simple_strtol(token, &token, 16);
146             }
147            printk("MAC: %2x:%2x:%2x:%2x:%2x:%2x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
148                 
149         }else {
150             printk("Invalid MAC String token (%s)\n", token);
151             return -1;
152         }
153                 
154     }
155
156     return 0;
157 }
158
159
160 static int str2mac(char * str, uint8_t * mac){
161     int i = 0;
162     char *hex = NULL;
163         
164     for (i = 0; i < ETH_ALEN; i++) {            
165         hex = strsep(&str, ":");
166         if (!hex) {
167             printk("Invalid MAC String token (%s)\n", str);
168             return -1;
169         }
170         mac[i] = simple_strtol(hex, &hex, 16);
171     }
172         
173     return 0;
174 }
175
176
177 /* Format:
178   * add src-MAC dst-MAC dst-TYPE [dst-ID] src-TYPE [src-ID]
179   *
180   * src-MAC = dst-MAC = not-MAC|any|none|MAC 
181   * dst-TYPE = edge|interface 
182   * src-TYPE = edge|interface|any
183   * dst-ID = src-ID = IP|MAC
184   * MAC=xx:xx:xx:xx:xx:xx
185   * IP = xxx.xxx.xxx.xxx
186   */
187 static int parse_route_str(char * str, struct v3_vnet_route * route) {
188     char * token = NULL;
189     struct vnet_link *link = NULL;
190
191     // src MAC
192     token = strsep(&str, " ");
193     if (!token) {
194         return -1;
195     }
196     parse_mac_str(token, &(route->src_mac_qual), route->src_mac);
197
198     // dst MAC
199     token = strsep(&str, " ");
200     if (!token) {
201         return -1;
202     }
203     parse_mac_str(token, &(route->dst_mac_qual), route->dst_mac);
204
205     // dst LINK type
206     token = strsep(&str, " ");
207     if (!token) {
208         return -1;
209     }
210     printk("dst type =(%s)\n", token);
211     
212     if (strnicmp("interface", token, strlen("interface")) == 0) {
213         route->dst_type = LINK_INTERFACE;
214     } else if (strnicmp("edge", token, strlen("edge")) == 0) {
215         route->dst_type = LINK_EDGE;
216     } else {
217         printk("Invalid Destination Link Type (%s)\n", token);
218         return -1;
219     }
220
221     // dst link
222     token = strsep(&str, " ");
223     if (!token) {
224         return -1;
225     }
226     printk("dst link ID=(%s)\n", token);
227
228     // Figure out link here
229     if (route->dst_type == LINK_EDGE) {
230         uint32_t link_ip;
231
232         // Figure out Link Here
233         if (in4_pton(token, strlen(token), (uint8_t *)&(link_ip), '\0', NULL) != 1) {
234             printk("Invalid Dst IP address (%s)\n", token);
235             return -EFAULT;
236         }
237
238         link = link_by_ip(link_ip);
239         if (link != NULL){
240             route->dst_id = link->link_idx;
241         }else{
242             printk("can not find dst link %s\n", token);
243             return -1;
244         }
245
246         printk("link_ip = %d, link_id = %d\n", link_ip, link->link_idx);        
247     } else if (route->dst_type == LINK_INTERFACE) {
248         uint8_t mac[ETH_ALEN];
249         
250        if(str2mac(token, mac) == -1){
251            printk("wrong MAC format (%s)\n", token);
252            return -1;
253        }
254            
255         route->dst_id = v3_vnet_find_dev(mac);
256         if (route->dst_id == -1){
257             printk("can not find dst device %s\n", token);
258             return -1;
259         }               
260     } else {
261         printk("Unsupported dst link type\n");
262         return -1;
263     }
264
265     route->src_id = -1;
266     route->src_type = -1;
267
268     // src LINK
269     token = strsep(&str, " ");
270
271     printk("SRC type = %s\n", token);
272
273     if (!token) {
274         return -1;
275     }
276
277     if (strnicmp("interface", token, strlen("interface")) == 0) {
278         route->src_type = LINK_INTERFACE;
279     } else if (strnicmp("edge", token, strlen("edge")) == 0) {
280         route->src_type = LINK_EDGE;
281     } else if (strnicmp("any", token, strlen("any")) == 0) {
282         route->src_type = LINK_ANY;
283     } else {
284         printk("Invalid Src link type (%s)\n", token);
285         return -1;
286     }
287
288
289     if (route->src_type == LINK_ANY) {
290         route->src_id = -1;
291     } else if (route->src_type == LINK_EDGE) {
292         uint32_t src_ip;
293         token = strsep(&str, " ");
294
295         if (!token) {
296             return -1;
297         }
298
299         // Figure out Link Here
300         if (in4_pton(token, strlen(token), (uint8_t *)&(src_ip), '\0', NULL) != 1) {
301             printk("Invalid SRC IP address (%s)\n", token);
302             return -EFAULT;
303         }
304
305         link = link_by_ip(src_ip);
306         if (link != NULL){
307             route->src_id = link->link_idx;
308         }else{
309             printk("can not find src link %s\n", token);
310             return -1;
311         }
312     } else if(route->src_type == LINK_INTERFACE){
313        uint8_t mac[ETH_ALEN];
314         
315        if(str2mac(token, mac) == -1){
316            printk("wrong MAC format (%s)\n", token);
317            return -1;
318        }
319            
320         route->src_id = v3_vnet_find_dev(mac);
321         if (route->src_id == -1){
322             printk("can not find dst device %s\n", token);
323             return -1;
324         }               
325     } else {
326         printk("Invalid link type\n");
327         return -1;
328     }
329
330     return 0;
331 }
332
333
334
335
336 static void * route_seq_start(struct seq_file * s, loff_t * pos) {
337     struct palacios_vnet_route * route_iter = NULL;
338     loff_t i = 0;
339
340
341     if (*pos >= vnet_state.num_routes) {
342         return NULL;
343     }
344
345     list_for_each_entry(route_iter, &(vnet_state.route_list), node) {
346
347         if (i == *pos) {
348             break;
349         }
350
351         i++;
352     }
353
354     return route_iter;
355 }
356
357
358 static void * link_seq_start(struct seq_file * s, loff_t * pos) {
359     struct vnet_link * link_iter = NULL;
360     loff_t i = 0;
361
362     if (*pos >= vnet_state.num_links) {
363         return NULL;
364     }
365
366     list_for_each_entry(link_iter, &(vnet_state.link_list), node) {
367
368         if (i == *pos) {
369             break;
370         }
371
372         i++;
373     }
374
375     return link_iter;
376 }
377
378
379
380 static void * route_seq_next(struct seq_file * s, void * v, loff_t * pos) {
381     struct palacios_vnet_route * route_iter = NULL;
382
383     route_iter = list_entry(((struct palacios_vnet_route *)v)->node.next, struct palacios_vnet_route, node);
384
385     // Check if the list has looped
386     if (&(route_iter->node) == &(vnet_state.route_list)) {
387         return NULL;
388     }
389
390     *pos += 1;
391
392     return route_iter;
393 }
394
395
396 static void * link_seq_next(struct seq_file * s, void * v, loff_t * pos) {
397     struct vnet_link * link_iter = NULL;
398
399  
400     link_iter = list_entry(((struct vnet_link *)v)->node.next, struct vnet_link, node);
401
402     // Check if the list has looped
403     if (&(link_iter->node) == &(vnet_state.link_list)) {
404         return NULL;
405     }
406
407     *pos += 1;
408
409     return link_iter;
410 }
411
412
413 static void route_seq_stop(struct seq_file * s, void * v) {
414     printk("route_seq_stop\n");
415
416     return;
417 }
418
419
420 static void link_seq_stop(struct seq_file * s, void * v) {
421     printk("link_seq_stop\n");
422
423     return;
424 }
425
426 static int route_seq_show(struct seq_file * s, void * v) {
427     struct palacios_vnet_route * route_iter = v;
428     struct v3_vnet_route * route = &(route_iter->route);
429
430     seq_printf(s, "%d:\t", route_iter->route_idx);
431
432     seq_printf(s, "\nSrc:\t");
433     switch (route->src_mac_qual) {
434         case MAC_ANY:
435             seq_printf(s, "any ");
436             break;
437         case MAC_NONE:
438             seq_printf(s, "none ");
439             break;
440         case MAC_NOT:
441             seq_printf(s, "not-%2x:%2x:%2x:%2x:%2x:%2x ", 
442                        route->src_mac[0], route->src_mac[1], route->src_mac[2],
443                        route->src_mac[3], route->src_mac[4], route->src_mac[5]);
444             break;
445         default:
446             seq_printf(s, "%x:%x:%x:%x:%x:%x ", 
447                        route->src_mac[0], route->src_mac[1], route->src_mac[2],
448                        route->src_mac[3], route->src_mac[4], route->src_mac[5]);
449             break;
450     }
451
452     seq_printf(s, "\nDst:\t");
453     switch (route->dst_mac_qual) {
454         case MAC_ANY:
455             seq_printf(s, "any ");
456             break;
457         case MAC_NONE:
458             seq_printf(s, "none ");
459             break;
460         case MAC_NOT:
461             seq_printf(s, "not-%x:%x:%x:%x:%x:%x ", 
462                        route->src_mac[0], route->src_mac[1], route->src_mac[2],
463                        route->src_mac[3], route->src_mac[4], route->src_mac[5]);
464             break;
465         default:
466             seq_printf(s, "%x:%x:%x:%x:%x:%x ", 
467                        route->src_mac[0], route->src_mac[1], route->src_mac[2],
468                        route->src_mac[3], route->src_mac[4], route->src_mac[5]);
469             break;
470     }
471
472     seq_printf(s, "\nDst-Type:\t");
473     switch (route->dst_type) {
474         case LINK_EDGE: {
475             struct vnet_link * link = (struct vnet_link *)link_by_idx(route->dst_id);
476             seq_printf(s, "EDGE %pI4", &link->dst_ip);
477             break;
478         }
479         case LINK_INTERFACE: {
480             seq_printf(s, "INTERFACE ");
481             seq_printf(s, "%d ", route->dst_id);
482             break;
483         }
484         default:
485             seq_printf(s, "Invalid Dst Link Type (%d) ", route->dst_type);
486             break;
487     }
488
489     seq_printf(s, "\nSrc-Type:\t");
490     switch (route->src_type) {
491         case LINK_EDGE: {
492             struct vnet_link * link = (struct vnet_link *)link_by_idx(route->src_id);
493             seq_printf(s, "EDGE %pI4", &link->dst_ip);
494             break;
495         }
496         case LINK_INTERFACE: {
497             seq_printf(s, "INTERFACE %d", route->src_id);
498             break;
499         }
500         case LINK_ANY:
501             seq_printf(s, "ANY");
502             break;
503         default:
504             seq_printf(s, "Invalid Src Link Type (%d) ", route->src_type);
505             break;
506     }
507
508
509     seq_printf(s, "\n");
510
511     return 0;
512 }
513
514
515 static int link_seq_show(struct seq_file * s, void * v) {
516     struct vnet_link * link_iter = v;
517
518     seq_printf(s, "%d:\t%pI4\t%d\n", 
519                link_iter->link_idx,
520                &link_iter->dst_ip,
521                link_iter->dst_port);
522
523     return 0;
524 }
525
526
527 static struct seq_operations route_seq_ops = {
528     .start = route_seq_start, 
529     .next = route_seq_next,
530     .stop = route_seq_stop,
531     .show = route_seq_show
532 };
533
534
535 static struct seq_operations link_seq_ops = {
536     .start = link_seq_start,
537     .next = link_seq_next,
538     .stop = link_seq_stop,
539     .show = link_seq_show
540 };
541
542
543 static int route_open(struct inode * inode, struct file * file) {
544     return seq_open(file, &route_seq_ops);
545 }
546
547
548 static int link_open(struct inode * inode, struct file * file) {
549     return seq_open(file, &link_seq_ops);
550 }
551
552 static int inject_route(struct palacios_vnet_route * route) {
553     unsigned long flags;
554
555     v3_vnet_add_route(route->route);
556
557     spin_lock_irqsave(&(vnet_state.lock), flags);
558     list_add(&(route->node), &(vnet_state.route_list));
559     route->route_idx = vnet_state.num_routes++;
560     spin_unlock_irqrestore(&(vnet_state.lock), flags);
561
562     printk("Palacios-vnet: One route added to VNET core\n");
563
564     return 0;
565 }
566
567 static ssize_t 
568 route_write(struct file * file, 
569             const char * buf, 
570             size_t size, 
571             loff_t * ppos) {
572     char route_buf[256];
573     char * buf_iter = NULL;
574     char * line_str = route_buf;
575     char * token = NULL;
576
577     if (size >= 256) {
578         return -EFAULT;
579     }
580
581     if (copy_from_user(route_buf, buf, size)) {
582         return -EFAULT;
583     }
584
585     printk("Route written: %s\n", route_buf);
586
587     while ((buf_iter = strsep(&line_str, "\r\n"))) {
588
589         token = strsep(&buf_iter, " ");
590         if (!token) {
591             return -EFAULT;
592         }
593         
594         if (strnicmp("ADD", token, strlen("ADD")) == 0) {
595             struct palacios_vnet_route * new_route = NULL;
596             new_route = kmalloc(sizeof(struct palacios_vnet_route), GFP_KERNEL);
597             
598             if (!new_route) {
599                 return -ENOMEM;
600             }
601             
602             memset(new_route, 0, sizeof(struct palacios_vnet_route));
603             
604             if (parse_route_str(buf_iter, &(new_route->route)) == -1) {
605                 kfree(new_route);
606                 return -EFAULT;
607             }
608             
609             if (inject_route(new_route) != 0) {
610                 return -EFAULT;
611             }
612         } else if (strnicmp("DEL", token, strlen("DEL")) == 0) {
613             printk("I should delete the route here\n");
614         } else {
615             printk("Invalid Route command string\n");
616         }
617     }
618
619     return size;
620 }
621
622
623 static int create_link(struct vnet_link * link) {
624     int err;
625     unsigned long flags;
626
627     if ( (err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &link->sock)) < 0) {
628         printk("Could not create socket\n");
629         return -1;
630     }
631
632     memset(&link->sock_addr, 0, sizeof(struct sockaddr));
633
634     link->sock_addr.sin_family = AF_INET;
635     link->sock_addr.sin_addr.s_addr = link->dst_ip;
636     link->sock_addr.sin_port = htons(link->dst_port);
637
638     if ((err = link->sock->ops->connect(link->sock, (struct sockaddr *)&(link->sock_addr), sizeof(struct sockaddr), 0) < 0)) {
639         printk("Could not connect to remote host\n");
640         return -1;
641     }
642
643     // We use the file pointer because we are in the kernel
644     // This is only used to assigned File Descriptors for user space, so it is available here
645     // link->sock->file = link;
646
647     spin_lock_irqsave(&(vnet_state.lock), flags);
648     list_add(&(link->node), &(vnet_state.link_list));
649     link->link_idx = vnet_state.num_links++;
650     spin_unlock_irqrestore(&(vnet_state.lock), flags);
651
652     printk("VNET Bridge: Link created, ip %d, port: %d, idx: %d, link: %p\n", 
653            link->dst_ip, 
654            link->dst_port, 
655            link->link_idx, 
656            link);
657
658     return 0;
659 }
660
661
662 /* ADD dst-ip 9000 */
663 static ssize_t 
664 link_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
665     char link_buf[256];
666     char * link_iter = NULL;
667     char * line_str = link_buf;
668     char * token = NULL;
669
670     if (size >= 256) {
671         return -EFAULT;
672     }
673
674     if (copy_from_user(link_buf, buf, size)) {
675         return -EFAULT;
676     }
677
678     while ((link_iter = strsep(&line_str, "\r\n"))) {
679         printk("Link written: %s\n", link_buf);
680         
681         token = strsep(&link_iter, " ");
682         
683         if (!token) {
684             return -EFAULT;
685         }
686         
687         if (strnicmp("ADD", token, strlen("ADD")) == 0) {
688             struct vnet_link * new_link = NULL;
689             char * ip_str = NULL;
690             uint32_t ip;
691             
692             ip_str = strsep(&link_iter, " ");
693             
694             if ((!ip_str) || (!link_iter)) {
695                 printk("Missing fields in ADD Link command\n");
696                 return -EFAULT;
697             }
698             
699             if (in4_pton(ip_str, strlen(ip_str), (uint8_t *)&(ip), '\0', NULL) != 1) {
700                 printk("Invalid Dst IP address (%s)\n", ip_str);
701                 return -EFAULT;
702             }
703
704             new_link = kmalloc(sizeof(struct vnet_link), GFP_KERNEL);
705
706             if (!new_link) {
707                 return -ENOMEM;
708             }
709
710             memset(new_link, 0, sizeof(struct vnet_link));
711
712             new_link->dst_ip = ip;
713             new_link->dst_port = simple_strtol(link_iter, &link_iter, 10);
714             
715             if (create_link(new_link) != 0) {
716                 printk("Could not create link\n");
717                 kfree(new_link);
718                 return -EFAULT;
719             }
720
721         } else if (strnicmp("DEL", token, strlen("DEL")) == 0) {
722             printk("Link deletion not supported\n");
723         } else {
724             printk("Invalid Link command string\n");
725         }
726     }
727
728     return size;
729 }
730
731
732 static struct file_operations route_fops = {
733     .owner = THIS_MODULE,
734     .open = route_open, 
735     .read = seq_read,
736     .write = route_write,
737     .llseek = seq_lseek,
738     .release = seq_release
739 };
740
741
742 static struct file_operations link_fops = {
743     .owner = THIS_MODULE,
744     .open = link_open, 
745     .read = seq_read,
746     .write = link_write,
747     .llseek = seq_lseek,
748     .release = seq_release
749 };
750
751
752 static int init_proc_files(void) {
753     struct proc_dir_entry * route_entry = NULL;
754     struct proc_dir_entry * link_entry = NULL;
755     struct proc_dir_entry * vnet_root = NULL;
756
757
758     vnet_root = proc_mkdir("vnet", NULL);
759     if (vnet_root == NULL) {
760         return -1;
761     }
762
763     route_entry = create_proc_entry("routes", 0, vnet_root);
764
765     if (route_entry == NULL) {
766         remove_proc_entry("vnet", NULL);
767         return -1;
768     }
769
770     route_entry->proc_fops = &route_fops;
771
772
773     link_entry = create_proc_entry("links", 0, vnet_root);
774
775     if (link_entry == NULL) {
776         remove_proc_entry("routes", vnet_root);
777         remove_proc_entry("vnet", NULL);
778         return -1;
779     }
780
781     link_entry->proc_fops = &link_fops;
782
783     return 0;
784
785 }
786
787
788
789 static int 
790 udp_send(struct socket * sock, 
791          struct sockaddr_in * addr,
792          unsigned char * buf,  int len) {
793     struct msghdr msg;
794     struct iovec iov;
795     mm_segment_t oldfs;
796     int size = 0;
797
798           
799     if (sock->sk == NULL) {
800         return 0;
801     }
802
803     iov.iov_base = buf;
804     iov.iov_len = len;
805
806     msg.msg_flags = 0;
807     msg.msg_name = addr;
808     msg.msg_namelen = sizeof(struct sockaddr_in);
809     msg.msg_control = NULL;
810     msg.msg_controllen = 0;
811     msg.msg_iov = &iov;
812     msg.msg_iovlen = 1;
813     msg.msg_control = NULL;
814
815     oldfs = get_fs();
816     set_fs(KERNEL_DS);
817     size = sock_sendmsg(sock, &msg, len);
818     set_fs(oldfs);
819
820     return size;
821 }
822
823
824
825 static int 
826 udp_recv(struct socket * sock, 
827          struct sockaddr_in * addr,
828          unsigned char * buf, int len) {
829     struct msghdr msg;
830     struct iovec iov;
831     mm_segment_t oldfs;
832     int size = 0;
833     
834     if (sock->sk == NULL) {
835         return 0;
836     }
837
838     iov.iov_base = buf;
839     iov.iov_len = len;
840     
841     msg.msg_flags = 0;
842     msg.msg_name = addr;
843     msg.msg_namelen = sizeof(struct sockaddr_in);
844     msg.msg_control = NULL;
845     msg.msg_controllen = 0;
846     msg.msg_iov = &iov;
847     msg.msg_iovlen = 1;
848     msg.msg_control = NULL;
849     
850     oldfs = get_fs();
851     set_fs(KERNEL_DS);
852     size = sock_recvmsg(sock, &msg, len, msg.msg_flags);
853         
854     set_fs(oldfs);
855     
856     return size;
857 }
858
859 //send packets from Network to VNET core
860 static int 
861 send_to_palacios(unsigned char * buf, 
862                  int len,
863                  int link_id){
864     struct v3_vnet_pkt pkt;
865     pkt.size = len;
866     pkt.src_type = LINK_EDGE;
867     pkt.src_id = link_id;
868     memcpy(pkt.header, buf, ETHERNET_HEADER_LEN);
869     pkt.data = buf;
870
871 #ifdef CONFIG_PALACIOS_VNET_DEBUG
872     {
873         printk("VNET Lnx Bridge: send pkt to VNET core (size: %d, src_id: %d, src_type: %d)\n", 
874                         pkt.size,  pkt.src_id, pkt.src_type);
875
876         print_hex_dump(NULL, "pkt_data: ", 0, 20, 20, pkt.data, pkt.size, 0);
877     }
878 #endif
879
880     return v3_vnet_send_pkt(&pkt, NULL);;
881 }
882
883
884 //send packet from VNET core to Network
885 static int 
886 bridge_send_pkt(struct v3_vm_info * vm, 
887                 struct v3_vnet_pkt * pkt, 
888                 void * private_data) {
889     struct vnet_link * link;
890
891     #ifdef CONFIG_PALACIOS_VNET_DEBUG
892            {
893                 printk("VNET Lnx Host Bridge: packet received from VNET Core ... len: %d, pkt size: %d, link: %d\n",
894                         len,
895                         pkt->size,
896                         pkt->dst_id);
897
898                 print_hex_dump(NULL, "pkt_data: ", 0, 20, 20, pkt->data, pkt->size, 0);
899            }
900     #endif
901
902     vnet_state.pkt_recv ++;
903
904     link = link_by_idx(pkt->dst_id);
905     if (link != NULL) {
906         udp_send(link->sock, &(link->sock_addr), pkt->data, pkt->size);
907         vnet_state.pkt_udp_send ++;
908     } else {
909         printk("VNET Bridge Linux Host: wrong dst link, idx: %d, discards the packet\n", pkt->dst_id);
910         vnet_state.pkt_drop ++;
911     }
912
913     return 0;
914 }
915
916
917 static void 
918 poll_pkt(struct v3_vm_info * vm, 
919          void * private_data) {
920
921
922 }
923
924
925
926 static int init_vnet_serv(void) {
927      
928     if (sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &vnet_state.serv_sock) < 0) {
929         printk("Could not create socket\n");
930         return -1;
931     }
932
933     memset(&vnet_state.serv_addr, 0, sizeof(struct sockaddr));
934
935     vnet_state.serv_addr.sin_family = AF_INET;
936     vnet_state.serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
937     vnet_state.serv_addr.sin_port = htons(VNET_UDP_PORT);
938
939     if (vnet_state.serv_sock->ops->bind(vnet_state.serv_sock, (struct sockaddr *)&(vnet_state.serv_addr), sizeof(struct sockaddr)) < 0) {
940         printk("Could not bind VNET server socket to port %d\n", VNET_UDP_PORT);
941         return -1;
942     }
943
944     printk("VNET server bind to port: %d\n", VNET_UDP_PORT);
945
946     return 0;
947 }
948
949 static int vnet_server(void * arg) {
950     unsigned char pkt[ETHERNET_PACKET_LEN];
951     struct sockaddr_in pkt_addr;
952     struct vnet_link *link = NULL;
953     int len;
954     int link_id;
955
956     printk("Palacios VNET Bridge: UDP receiving server ..... \n");
957
958     while (!kthread_should_stop()) {
959         
960         len = udp_recv(vnet_state.serv_sock, &pkt_addr, pkt, ETHERNET_PACKET_LEN); 
961         if(len < 0) {
962             printk("Receive error: Could not get packet, error %d\n", len);
963             continue;
964         }
965
966         link = link_by_ip(ntohl(pkt_addr.sin_addr.s_addr));
967         if (link != NULL){
968             link_id= link->link_idx;
969         }
970         else { 
971             link_id= 0;
972         }
973         
974         vnet_state.pkt_udp_recv ++;
975
976         send_to_palacios(pkt, len, link_id);
977     }
978
979     return 0;
980 }
981
982
983 int  palacios_init_vnet(void) {
984     struct v3_vnet_bridge_ops bridge_ops;
985         
986     memset(&vnet_state, 0, sizeof(struct palacios_vnet_state));
987
988     INIT_LIST_HEAD(&(vnet_state.link_list));
989     INIT_LIST_HEAD(&(vnet_state.route_list));
990     spin_lock_init(&(vnet_state.lock));
991
992     init_proc_files();
993     if(init_vnet_serv() < 0){
994         printk("Failure to initiate VNET server\n");
995         return -1;
996     }
997
998     vnet_state.serv_thread = kthread_run(vnet_server, NULL, "vnet-server");
999
1000     //kthread_run(profiling, NULL, "Profiling");
1001
1002     bridge_ops.input = bridge_send_pkt;
1003     bridge_ops.poll = poll_pkt;
1004         
1005     v3_vnet_add_bridge(NULL, &bridge_ops, HOST_LNX_BRIDGE, NULL);
1006
1007     printk("Palacios VNET Linux Bridge initiated\n");
1008
1009     return 0;
1010 }
1011