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.


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