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.


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