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.


0b0ee4f4ff9c9bf2ef8c9bdb256fe8579a481597
[palacios.git] / linux_module / palacios-vnet-bridge.c
1 /* 
2    Palacios VNET Host Bridge
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/net.h>
16 #include <linux/string.h>
17 #include <linux/preempt.h>
18 #include <linux/sched.h>
19 #include <asm/msr.h>
20
21 #include <vnet/vnet.h>
22 #include <vnet/vnet_hashtable.h>
23 #include "palacios-vnet.h"
24
25 #define VNET_SERVER_PORT 9000
26
27 struct palacios_vnet_route {
28     struct v3_vnet_route route;
29
30     int idx;
31
32     struct list_head node;
33 };
34
35 typedef enum {UDP, TCP, RAW, NONE} vnet_bridge_proto_t;
36
37 struct vnet_link {
38     uint32_t dst_ip;
39     uint16_t dst_port;
40     
41     struct socket * sock;
42     struct sockaddr_in sock_addr;
43     vnet_bridge_proto_t sock_proto;
44
45     unsigned int pkt_rx, pkt_tx;
46     uint64_t bytes_rx, bytes_tx;
47
48     int idx;
49
50     struct list_head node;
51 };
52
53
54 struct palacios_vnet_state {
55     uint32_t num_routes;
56     uint32_t num_links;
57     uint32_t route_idx;
58     uint32_t link_idx;
59
60     uint8_t status;
61
62     struct list_head route_list;
63     struct list_head link_list;
64
65     struct hashtable *ip2link; /* map IP to its Link */
66
67     spinlock_t lock;
68
69     struct socket * serv_sock;
70     struct sockaddr_in serv_addr;
71     vnet_bridge_proto_t serv_proto;
72
73     /* Socket Receiving Thread */
74     struct task_struct * serv_thread;
75
76     struct proc_dir_entry * vnet_proc_root;
77
78     unsigned int pkt_from_vmm, pkt_to_vmm, pkt_drop_vmm;
79     unsigned int pkt_from_phy, pkt_to_phy, pkt_drop_phy;
80 };
81
82
83 static struct palacios_vnet_state vnet_state;
84
85
86 static inline struct vnet_link * link_by_ip(uint32_t ip) {
87     return (struct vnet_link *)vnet_htable_search(vnet_state.ip2link, (addr_t)&ip);
88 }
89
90 static inline struct vnet_link * link_by_idx(int idx) {
91     struct vnet_link * link = NULL;
92
93     list_for_each_entry(link, &(vnet_state.link_list), node) {
94
95         if (link->idx == idx) {
96             return link;
97         }
98     }
99     return NULL;
100 }
101
102 static inline struct palacios_vnet_route * route_by_idx(int idx) {
103     struct palacios_vnet_route * route = NULL;
104
105     list_for_each_entry(route, &(vnet_state.route_list), node) {
106
107         if (route->idx == idx) {
108             return route;
109         }
110     }
111
112     return NULL;
113 }
114
115
116 static int parse_mac_str(char * str, uint8_t * qual, uint8_t * mac) {
117     char * token;
118
119     printk("Parsing MAC (%s)\n", str);
120         
121     *qual = MAC_NOSET;
122     if(strnicmp("any", str, strlen(str)) == 0){
123         *qual = MAC_ANY;
124         return 0;
125     }else if(strnicmp("none", str, strlen(str)) == 0){
126        *qual = MAC_NONE;
127         return 0;
128     }else{
129         if (strstr(str, "-")) {
130             token = strsep(&str, "-");
131
132             if (strnicmp("not", token, strlen("not")) == 0) {
133                 *qual = MAC_NOT;
134             } else {
135                 printk("Invalid MAC String token (%s)\n", token);
136                 return -1;
137             }
138         }
139
140         if (strstr(str, ":")) {
141             int i = 0;
142
143             if(*qual == MAC_NOSET){
144                 *qual = MAC_ADDR;
145             }
146
147             for (i = 0; i < 6; i++) {
148                 token = strsep(&str, ":");
149                 if (!token) {
150                     printk("Invalid MAC String token (%s)\n", token);
151                     return -1;
152                 }
153                 mac[i] = simple_strtol(token, &token, 16);
154             }
155            printk("MAC: %2x:%2x:%2x:%2x:%2x:%2x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
156                 
157         }else {
158             printk("Invalid MAC String token (%s)\n", token);
159             return -1;
160         }
161                 
162     }
163
164     return 0;
165 }
166
167
168 static int str2mac(char * str, uint8_t * mac){
169     int i = 0;
170     char *hex = NULL;
171         
172     for (i = 0; i < ETH_ALEN; i++) {            
173         hex = strsep(&str, ":");
174         if (!hex) {
175             printk("Invalid MAC String token (%s)\n", str);
176             return -1;
177         }
178         mac[i] = simple_strtol(hex, &hex, 16);
179     }
180         
181     return 0;
182 }
183
184
185 /* Format:
186   * add src-MAC dst-MAC dst-TYPE [dst-ID] src-TYPE [src-ID]
187   *
188   * src-MAC = dst-MAC = not-MAC|any|none|MAC 
189   * dst-TYPE = edge|interface 
190   * src-TYPE = edge|interface|any
191   * dst-ID = src-ID = IP|MAC
192   * MAC=xx:xx:xx:xx:xx:xx
193   * IP = xxx.xxx.xxx.xxx
194   */
195 static int parse_route_str(char * str, struct v3_vnet_route * route) {
196     char * token = NULL;
197     struct vnet_link *link = NULL;
198
199     // src MAC
200     token = strsep(&str, " ");
201     if (!token) {
202         return -1;
203     }
204     parse_mac_str(token, &(route->src_mac_qual), route->src_mac);
205
206     // dst MAC
207     token = strsep(&str, " ");
208     if (!token) {
209         return -1;
210     }
211     parse_mac_str(token, &(route->dst_mac_qual), route->dst_mac);
212
213     // dst LINK type
214     token = strsep(&str, " ");
215     if (!token) {
216         return -1;
217     }
218     printk("dst type =(%s)\n", token);
219     
220     if (strnicmp("interface", token, strlen("interface")) == 0) {
221         route->dst_type = LINK_INTERFACE;
222     } else if (strnicmp("edge", token, strlen("edge")) == 0) {
223         route->dst_type = LINK_EDGE;
224     } else {
225         printk("Invalid Destination Link Type (%s)\n", token);
226         return -1;
227     }
228
229     // dst link
230     token = strsep(&str, " ");
231     if (!token) {
232         return -1;
233     }
234     printk("dst ID=(%s)\n", token);
235
236     // Figure out link here
237     if (route->dst_type == LINK_EDGE) {
238         uint32_t link_ip;
239
240         // Figure out Link Here
241         if (in4_pton(token, strlen(token), (uint8_t *)&(link_ip), '\0', NULL) != 1) {
242             printk("Invalid Dst IP address (%s)\n", token);
243             return -EFAULT;
244         }
245
246         link = link_by_ip(link_ip);
247         if (link != NULL){
248             route->dst_id = link->idx;
249         }else{
250             printk("can not find dst link %s\n", token);
251             return -1;
252         }
253
254         printk("link_ip = %d, link_id = %d\n", link_ip, link->idx);     
255     } else if (route->dst_type == LINK_INTERFACE) {
256         uint8_t mac[ETH_ALEN];
257         
258        if(str2mac(token, mac) == -1){
259            printk("wrong MAC format (%s)\n", token);
260            return -1;
261        }
262            
263         route->dst_id = v3_vnet_find_dev(mac);
264         if (route->dst_id == -1){
265             printk("can not find dst device %s\n", token);
266             return -1;
267         }               
268     } else {
269         printk("Unsupported dst link type\n");
270         return -1;
271     }
272
273     route->src_id = -1;
274     route->src_type = -1;
275
276     // src LINK
277     token = strsep(&str, " ");
278
279     printk("SRC type = %s\n", token);
280
281     if (!token) {
282         return -1;
283     }
284
285     if (strnicmp("interface", token, strlen("interface")) == 0) {
286         route->src_type = LINK_INTERFACE;
287     } else if (strnicmp("edge", token, strlen("edge")) == 0) {
288         route->src_type = LINK_EDGE;
289     } else if (strnicmp("any", token, strlen("any")) == 0) {
290         route->src_type = LINK_ANY;
291     } else {
292         printk("Invalid Src link type (%s)\n", token);
293         return -1;
294     }
295
296
297     if (route->src_type == LINK_ANY) {
298         route->src_id = -1;
299     } else if (route->src_type == LINK_EDGE) {
300         uint32_t src_ip;
301         token = strsep(&str, " ");
302
303         if (!token) {
304             return -1;
305         }
306
307         // Figure out Link Here
308         if (in4_pton(token, strlen(token), (uint8_t *)&(src_ip), '\0', NULL) != 1) {
309             printk("Invalid SRC IP address (%s)\n", token);
310             return -EFAULT;
311         }
312
313         link = link_by_ip(src_ip);
314         if (link != NULL){
315             route->src_id = link->idx;
316         }else{
317             printk("can not find src link %s\n", token);
318             return -1;
319         }
320     } else if(route->src_type == LINK_INTERFACE){
321        uint8_t mac[ETH_ALEN];
322         
323        if(str2mac(token, mac) == -1){
324            printk("wrong MAC format (%s)\n", token);
325            return -1;
326        }
327            
328         route->src_id = v3_vnet_find_dev(mac);
329         if (route->src_id == -1){
330             printk("can not find dst device %s\n", token);
331             return -1;
332         }               
333     } else {
334         printk("Invalid link type\n");
335         return -1;
336     }
337
338     return 0;
339 }
340
341
342
343
344 static void * route_seq_start(struct seq_file * s, loff_t * pos) {
345     struct palacios_vnet_route * route_iter = NULL;
346     loff_t i = 0;
347
348
349     if (*pos >= vnet_state.num_routes) {
350         return NULL;
351     }
352
353     list_for_each_entry(route_iter, &(vnet_state.route_list), node) {
354
355         if (i == *pos) {
356             break;
357         }
358
359         i++;
360     }
361
362     return route_iter;
363 }
364
365
366 static void * link_seq_start(struct seq_file * s, loff_t * pos) {
367     struct vnet_link * link_iter = NULL;
368     loff_t i = 0;
369
370     if (*pos >= vnet_state.num_links) {
371         return NULL;
372     }
373
374     list_for_each_entry(link_iter, &(vnet_state.link_list), node) {
375
376         if (i == *pos) {
377             break;
378         }
379
380         i++;
381     }
382
383     return link_iter;
384 }
385
386
387
388 static void * route_seq_next(struct seq_file * s, void * v, loff_t * pos) {
389     struct palacios_vnet_route * route_iter = NULL;
390
391     route_iter = list_entry(((struct palacios_vnet_route *)v)->node.next, struct palacios_vnet_route, node);
392
393     // Check if the list has looped
394     if (&(route_iter->node) == &(vnet_state.route_list)) {
395         return NULL;
396     }
397
398     *pos += 1;
399
400     return route_iter;
401 }
402
403
404 static void * link_seq_next(struct seq_file * s, void * v, loff_t * pos) {
405     struct vnet_link * link_iter = NULL;
406
407  
408     link_iter = list_entry(((struct vnet_link *)v)->node.next, struct vnet_link, node);
409
410     // Check if the list has looped
411     if (&(link_iter->node) == &(vnet_state.link_list)) {
412         return NULL;
413     }
414
415     *pos += 1;
416
417     return link_iter;
418 }
419
420
421 static void route_seq_stop(struct seq_file * s, void * v) {
422
423     return;
424 }
425
426
427 static void link_seq_stop(struct seq_file * s, void * v) {
428
429     return;
430 }
431
432 static int route_seq_show(struct seq_file * s, void * v) {
433     struct palacios_vnet_route * route_iter = v;
434     struct v3_vnet_route * route = &(route_iter->route);
435
436     seq_printf(s, "%d:\t", route_iter->idx);
437
438     seq_printf(s, "\nSrc:\t");
439     switch (route->src_mac_qual) {
440         case MAC_ANY:
441             seq_printf(s, "any ");
442             break;
443         case MAC_NONE:
444             seq_printf(s, "none ");
445             break;
446         case MAC_NOT:
447             seq_printf(s, "not-%2x:%2x:%2x:%2x:%2x:%2x ", 
448                        route->src_mac[0], route->src_mac[1], route->src_mac[2],
449                        route->src_mac[3], route->src_mac[4], route->src_mac[5]);
450             break;
451         default:
452             seq_printf(s, "%x:%x:%x:%x:%x:%x ", 
453                        route->src_mac[0], route->src_mac[1], route->src_mac[2],
454                        route->src_mac[3], route->src_mac[4], route->src_mac[5]);
455             break;
456     }
457
458     seq_printf(s, "\nDst:\t");
459     switch (route->dst_mac_qual) {
460         case MAC_ANY:
461             seq_printf(s, "any ");
462             break;
463         case MAC_NONE:
464             seq_printf(s, "none ");
465             break;
466         case MAC_NOT:
467             seq_printf(s, "not-%x:%x:%x:%x:%x:%x ", 
468                        route->src_mac[0], route->src_mac[1], route->src_mac[2],
469                        route->src_mac[3], route->src_mac[4], route->src_mac[5]);
470             break;
471         default:
472             seq_printf(s, "%x:%x:%x:%x:%x:%x ", 
473                        route->src_mac[0], route->src_mac[1], route->src_mac[2],
474                        route->src_mac[3], route->src_mac[4], route->src_mac[5]);
475             break;
476     }
477
478     seq_printf(s, "\nDst-Type:\t");
479     switch (route->dst_type) {
480         case LINK_EDGE: {
481             struct vnet_link * link = (struct vnet_link *)link_by_idx(route->dst_id);
482             seq_printf(s, "EDGE %pI4", &link->dst_ip);
483             break;
484         }
485         case LINK_INTERFACE: {
486             seq_printf(s, "INTERFACE ");
487             seq_printf(s, "%d ", route->dst_id);
488             break;
489         }
490         default:
491             seq_printf(s, "Invalid Dst Link Type (%d) ", route->dst_type);
492             break;
493     }
494
495     seq_printf(s, "\nSrc-Type:\t");
496     switch (route->src_type) {
497         case LINK_EDGE: {
498             struct vnet_link * link = (struct vnet_link *)link_by_idx(route->src_id);
499             seq_printf(s, "EDGE %pI4", &link->dst_ip);
500             break;
501         }
502         case LINK_INTERFACE: {
503             seq_printf(s, "INTERFACE %d", route->src_id);
504             break;
505         }
506         case LINK_ANY:
507             seq_printf(s, "ANY");
508             break;
509         default:
510             seq_printf(s, "Invalid Src Link Type (%d) ", route->src_type);
511             break;
512     }
513
514
515     seq_printf(s, "\n");
516
517     return 0;
518 }
519
520
521 static int link_seq_show(struct seq_file * s, void * v) {
522     struct vnet_link * link_iter = v;
523
524     seq_printf(s, "%d:\t%pI4\t%d\n\t\tReceived Pkts: %d, Received Bytes %lld\n\t\tSent Pkts: %d, Sent Bytes: %lld\n\n", 
525                link_iter->idx,
526                &link_iter->dst_ip,
527                link_iter->dst_port,
528                link_iter->pkt_rx,
529                link_iter->bytes_rx,
530                link_iter->pkt_tx,
531                link_iter->bytes_tx);
532
533     return 0;
534 }
535
536
537 static struct seq_operations route_seq_ops = {
538     .start = route_seq_start, 
539     .next = route_seq_next,
540     .stop = route_seq_stop,
541     .show = route_seq_show
542 };
543
544
545 static struct seq_operations link_seq_ops = {
546     .start = link_seq_start,
547     .next = link_seq_next,
548     .stop = link_seq_stop,
549     .show = link_seq_show
550 };
551
552
553 static int route_open(struct inode * inode, struct file * file) {
554     return seq_open(file, &route_seq_ops);
555 }
556
557
558 static int link_open(struct inode * inode, struct file * file) {
559     return seq_open(file, &link_seq_ops);
560 }
561
562 static int inject_route(struct palacios_vnet_route * route) {
563     unsigned long flags;
564
565     v3_vnet_add_route(route->route);
566
567     spin_lock_irqsave(&(vnet_state.lock), flags);
568     list_add(&(route->node), &(vnet_state.route_list));
569     vnet_state.num_routes++;
570     route->idx = vnet_state.route_idx ++;
571     spin_unlock_irqrestore(&(vnet_state.lock), flags);
572
573     printk("Palacios-vnet: One route added to VNET core\n");
574
575     return 0;
576 }
577
578
579 static int delete_route(struct palacios_vnet_route * route) {
580     unsigned long flags;
581
582     //v3_vnet_del_route(route->route);
583
584     spin_lock_irqsave(&(vnet_state.lock), flags);
585     list_del(&(route->node));
586     vnet_state.num_routes --;
587     spin_unlock_irqrestore(&(vnet_state.lock), flags);
588
589     printk("Palacios-vnet: Route %d deleted from VNET\n", route->idx);
590
591     kfree(route);
592
593     return 0;
594 }
595
596 static ssize_t 
597 route_write(struct file * file, 
598             const char * buf, 
599             size_t size, 
600             loff_t * ppos) {
601     char route_buf[256];
602     char * buf_iter = NULL;
603     char * line_str = route_buf;
604     char * token = NULL;
605
606     if (size >= 256) {
607         return -EFAULT;
608     }
609
610     if (copy_from_user(route_buf, buf, size)) {
611         return -EFAULT;
612     }
613
614     route_buf[size] = '\0';
615     printk("Route written: %s\n", route_buf);
616
617     while ((buf_iter = strsep(&line_str, "\r\n"))) {
618
619         token = strsep(&buf_iter, " ");
620         if (!token) {
621             return -EFAULT;
622         }
623         
624         if (strnicmp("ADD", token, strlen("ADD")) == 0) {
625             struct palacios_vnet_route * new_route = NULL;
626             new_route = kmalloc(sizeof(struct palacios_vnet_route), GFP_KERNEL);
627             
628             if (!new_route) {
629                 return -ENOMEM;
630             }
631             
632             memset(new_route, 0, sizeof(struct palacios_vnet_route));
633             
634             if (parse_route_str(buf_iter, &(new_route->route)) == -1) {
635                 kfree(new_route);
636                 return -EFAULT;
637             }
638             
639             if (inject_route(new_route) != 0) {
640                 kfree(new_route);
641                 return -EFAULT;
642             }
643         } else if (strnicmp("DEL", token, strlen("DEL")) == 0) {
644             printk("I should delete the route here\n");
645         } else {
646             printk("Invalid Route command string\n");
647         }
648     }
649
650     return size;
651 }
652
653
654 static void delete_link(struct vnet_link * link){
655     unsigned long flags;
656
657     link->sock->ops->release(link->sock);
658
659     spin_lock_irqsave(&(vnet_state.lock), flags);
660     list_del(&(link->node));
661     vnet_htable_remove(vnet_state.ip2link, (addr_t)&(link->dst_ip), 0);
662     vnet_state.num_links --;
663     spin_unlock_irqrestore(&(vnet_state.lock), flags);
664
665     printk("VNET Bridge: Link deleted, ip 0x%x, port: %d, idx: %d\n", 
666            link->dst_ip, 
667            link->dst_port, 
668            link->idx);
669
670     kfree(link);
671     link = NULL;
672 }
673
674
675 static void deinit_links_list(void){
676     struct vnet_link * link;
677
678     list_for_each_entry(link, &(vnet_state.link_list), node) {
679         delete_link(link);
680     }
681 }
682
683 static void deinit_routes_list(void){
684    struct palacios_vnet_route * route;
685
686    list_for_each_entry(route, &(vnet_state.route_list), node) {
687         delete_route(route);
688    }
689 }
690
691
692
693 static int create_link(struct vnet_link * link) {
694     int err;
695     unsigned long flags;
696     int protocol;
697
698     switch(link->sock_proto){
699         case UDP:
700             protocol = IPPROTO_UDP;
701             break;
702         case TCP:
703             protocol = IPPROTO_TCP;
704             break;
705
706         default:
707            printk("Unsupported VNET Server Protocol\n");
708             return -1;
709     }
710    
711     if ((err = sock_create(AF_INET, SOCK_DGRAM, protocol, &link->sock)) < 0) {
712         printk("Could not create socket for VNET Link, error %d\n", err);
713         return -1;
714     }
715
716     memset(&link->sock_addr, 0, sizeof(struct sockaddr));
717
718     link->sock_addr.sin_family = AF_INET;
719     link->sock_addr.sin_addr.s_addr = link->dst_ip;
720     link->sock_addr.sin_port = htons(link->dst_port);
721
722     if ((err = link->sock->ops->connect(link->sock, (struct sockaddr *)&(link->sock_addr), sizeof(struct sockaddr), 0) < 0)) {
723         printk("Could not connect to remote VNET Server, error %d\n", err);
724         return -1;
725     }
726
727     spin_lock_irqsave(&(vnet_state.lock), flags);
728     list_add(&(link->node), &(vnet_state.link_list));
729     vnet_state.num_links ++;
730     link->idx = vnet_state.link_idx ++;
731     vnet_htable_insert(vnet_state.ip2link, (addr_t)&(link->dst_ip), (addr_t)link);
732     spin_unlock_irqrestore(&(vnet_state.lock), flags);
733
734     printk("VNET Bridge: Link created, ip 0x%x, port: %d, idx: %d, link: %p, protocol: %s\n", 
735            link->dst_ip, 
736            link->dst_port, 
737            link->idx, 
738            link,
739            ((link->sock_proto==UDP)?"UDP":"TCP"));
740
741     return 0;
742 }
743
744
745 /* ADD dst-ip 9000 [udp|tcp] */
746 static ssize_t 
747 link_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
748     char link_buf[256];
749     char * link_iter = NULL;
750     char * line_str = link_buf;
751     char * token = NULL;
752
753     if (size >= 256) {
754         return -EFAULT;
755     }
756
757     if (copy_from_user(link_buf, buf, size)) {
758         return -EFAULT;
759     }
760
761     while ((link_iter = strsep(&line_str, "\r\n"))) {
762         printk("Link written: %s\n", link_buf);
763         
764         token = strsep(&link_iter, " ");
765         
766         if (!token) {
767             return -EFAULT;
768         }
769         
770         if (strnicmp("ADD", token, strlen("ADD")) == 0) {
771             struct vnet_link * new_link = NULL;
772             char * ip_str = NULL;
773             uint32_t ip;
774             
775             ip_str = strsep(&link_iter, " ");
776             
777             if ((!ip_str) || (!link_iter)) {
778                 printk("Missing fields in ADD Link command\n");
779                 return -EFAULT;
780             }
781             
782             if (in4_pton(ip_str, strlen(ip_str), (uint8_t *)&(ip), '\0', NULL) != 1) {
783                 printk("Invalid Dst IP address (%s)\n", ip_str);
784                 return -EFAULT;
785             }
786
787             new_link = kmalloc(sizeof(struct vnet_link), GFP_KERNEL);
788             if (!new_link) {
789                 return -ENOMEM;
790             }
791         
792             memset(new_link, 0, sizeof(struct vnet_link));
793
794             new_link->dst_ip = ip;
795             new_link->dst_port = simple_strtol(link_iter, &link_iter, 10);
796
797             //TODO: Parse UDP|TCP
798             new_link->sock_proto = UDP;
799             
800             if (create_link(new_link) != 0) {
801                 printk("Could not create link\n");
802                 kfree(new_link);
803                 return -EFAULT;
804             }
805
806         } else if (strnicmp("DEL", token, strlen("DEL")) == 0) {
807             printk("Link deletion not supported\n");
808         } else {
809             printk("Invalid Link command string\n");
810         }
811     }
812
813     return size;
814 }
815
816
817 static struct file_operations route_fops = {
818     .owner = THIS_MODULE,
819     .open = route_open, 
820     .read = seq_read,
821     .write = route_write,
822     .llseek = seq_lseek,
823     .release = seq_release
824 };
825
826
827 static struct file_operations link_fops = {
828     .owner = THIS_MODULE,
829     .open = link_open, 
830     .read = seq_read,
831     .write = link_write,
832     .llseek = seq_lseek,
833     .release = seq_release
834 };
835
836
837 static ssize_t 
838 debug_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
839     char link_buf[32];
840     char * link_iter = NULL;
841     char * line_str = link_buf;
842     int level = -1; 
843
844     if (size >= 32) {
845         return -EFAULT;
846     }
847
848     if (copy_from_user(link_buf, buf, size)) {
849         return -EFAULT;
850     }
851
852     link_iter = strsep(&line_str, "\r\n");
853     level = simple_strtol(link_iter, &link_iter, 10);
854
855     printk("Set VNET Debug level to %d\n", level);
856
857     if(level >= 0){
858         net_debug = level;
859     }
860
861     return size;
862 }
863
864
865 static int debug_show(struct seq_file * file, void * v){
866     seq_printf(file, "Current VNET Debug Level: %d\n", net_debug);
867         
868     return 0;
869 }
870
871 static int debug_open(struct inode * inode, struct file * file) {
872     return single_open(file, debug_show, NULL);
873 }
874
875 static struct file_operations debug_fops = {
876     .owner = THIS_MODULE,
877     .open = debug_open, 
878     .read = seq_read,
879     .write = debug_write,
880     .llseek = seq_lseek,
881     .release = seq_release
882 };
883
884 static int stat_show(struct seq_file * file, void * v){
885     struct vnet_stat stats;
886
887     v3_vnet_stat(&stats);
888
889     seq_printf(file, "VNET Core\n");
890     seq_printf(file, "\tReceived Packets: %d\n", stats.rx_pkts);
891     seq_printf(file, "\tReceived Bytes: %lld\n", stats.rx_bytes);
892     seq_printf(file, "\tTransmitted Packets: %d\n", stats.tx_pkts);
893     seq_printf(file, "\tTransmitted Bytes: %lld\n", stats.tx_bytes);
894
895
896     seq_printf(file, "\nVNET Bridge Server\n");
897     seq_printf(file, "\tReceived From VMM: %d\n", vnet_state.pkt_from_vmm);
898     seq_printf(file, "\tSent To VMM: %d\n", vnet_state.pkt_to_vmm);
899     seq_printf(file, "\tDropped From VMM: %d\n", vnet_state.pkt_drop_vmm);
900     seq_printf(file, "\tReceived From Extern Network: %d\n", vnet_state.pkt_from_phy);
901     seq_printf(file, "\tSent To Extern Network: %d\n", vnet_state.pkt_to_phy);
902     seq_printf(file, "\tDropped From Extern Network: %d\n", vnet_state.pkt_drop_phy);
903
904     return 0;
905 }
906
907 static int stat_open(struct inode * inode, struct file * file) {
908     return single_open(file, stat_show, NULL);
909 }
910
911 static struct file_operations stat_fops = {
912     .owner = THIS_MODULE,
913     .open = stat_open, 
914     .read = seq_read,
915     .llseek = seq_lseek,
916     .release = seq_release
917 };
918
919
920 static int init_proc_files(void) {
921     struct proc_dir_entry * route_entry = NULL;
922     struct proc_dir_entry * link_entry = NULL;
923     struct proc_dir_entry * stat_entry = NULL;
924     struct proc_dir_entry * debug_entry = NULL;
925     struct proc_dir_entry * vnet_root = NULL;
926
927     vnet_root = proc_mkdir("vnet", NULL);
928     if (vnet_root == NULL) {
929         return -1;
930     }
931
932     route_entry = create_proc_entry("routes", 0, vnet_root);
933     if (route_entry == NULL) {
934         remove_proc_entry("vnet", NULL);
935         return -1;
936     }
937     route_entry->proc_fops = &route_fops;
938         
939
940     link_entry = create_proc_entry("links", 0, vnet_root);
941     if (link_entry == NULL) {
942         remove_proc_entry("routes", vnet_root);
943         remove_proc_entry("vnet", NULL);
944         return -1;
945     }
946     link_entry->proc_fops = &link_fops;
947         
948
949     stat_entry = create_proc_entry("stats", 0, vnet_root);
950     if(stat_entry == NULL) {
951         remove_proc_entry("links", vnet_root);
952         remove_proc_entry("routes", vnet_root);
953         remove_proc_entry("vnet", NULL);
954         return -1;
955     }
956     stat_entry->proc_fops = &stat_fops;
957
958
959     debug_entry = create_proc_entry("debug", 0, vnet_root);
960     if(debug_entry == NULL) {
961         remove_proc_entry("links", vnet_root);
962         remove_proc_entry("routes", vnet_root);
963         remove_proc_entry("stats", vnet_root);
964         remove_proc_entry("vnet", NULL);
965         return -1;
966     }
967     debug_entry->proc_fops = &debug_fops;
968
969     vnet_state.vnet_proc_root = vnet_root;
970
971     return 0;
972 }
973
974
975 static void destroy_proc_files(void) {
976     struct proc_dir_entry * vnet_root = vnet_state.vnet_proc_root;
977
978     remove_proc_entry("debug", vnet_root);
979     remove_proc_entry("links", vnet_root);
980     remove_proc_entry("routes", vnet_root);
981     remove_proc_entry("stats", vnet_root);
982     remove_proc_entry("vnet", NULL);    
983 }
984
985
986 static int 
987 udp_send(struct socket * sock, 
988          struct sockaddr_in * addr,
989          unsigned char * buf,  int len) {
990     struct msghdr msg;
991     struct iovec iov;
992     mm_segment_t oldfs;
993     int size = 0;
994
995           
996     if (sock->sk == NULL) {
997         return 0;
998     }
999
1000     iov.iov_base = buf;
1001     iov.iov_len = len;
1002
1003     msg.msg_flags = 0;
1004     msg.msg_name = addr;
1005     msg.msg_namelen = sizeof(struct sockaddr_in);
1006     msg.msg_control = NULL;
1007     msg.msg_controllen = 0;
1008     msg.msg_iov = &iov;
1009     msg.msg_iovlen = 1;
1010     msg.msg_control = NULL;
1011
1012     oldfs = get_fs();
1013     set_fs(KERNEL_DS);
1014     size = sock_sendmsg(sock, &msg, len);
1015     set_fs(oldfs);
1016
1017     return size;
1018 }
1019
1020
1021
1022 static int 
1023 udp_recv(struct socket * sock, 
1024          struct sockaddr_in * addr,
1025          unsigned char * buf, int len) {
1026     struct msghdr msg;
1027     struct iovec iov;
1028     mm_segment_t oldfs;
1029     int size = 0;
1030     
1031     if (sock->sk == NULL) {
1032         return 0;
1033     }
1034
1035     iov.iov_base = buf;
1036     iov.iov_len = len;
1037     
1038     msg.msg_flags = 0;
1039     msg.msg_name = addr;
1040     msg.msg_namelen = sizeof(struct sockaddr_in);
1041     msg.msg_control = NULL;
1042     msg.msg_controllen = 0;
1043     msg.msg_iov = &iov;
1044     msg.msg_iovlen = 1;
1045     msg.msg_control = NULL;
1046     
1047     oldfs = get_fs();
1048     set_fs(KERNEL_DS);
1049     size = sock_recvmsg(sock, &msg, len, msg.msg_flags);
1050         
1051     set_fs(oldfs);
1052     
1053     return size;
1054 }
1055
1056 /* send packets to VNET core */
1057 static int 
1058 send_to_palacios(unsigned char * buf, 
1059                  int len,
1060                  int link_id){
1061     struct v3_vnet_pkt pkt;
1062     pkt.size = len;
1063     pkt.src_type = LINK_EDGE;
1064     pkt.src_id = link_id;
1065     memcpy(pkt.header, buf, ETHERNET_HEADER_LEN);
1066     pkt.data = buf;
1067
1068     if(net_debug >= 2){
1069         printk("VNET Lnx Bridge: send pkt to VNET core (size: %d, src_id: %d, src_type: %d)\n", 
1070                         pkt.size,  pkt.src_id, pkt.src_type);
1071         if(net_debug >= 4){
1072             print_hex_dump(NULL, "pkt_data: ", 0, 20, 20, pkt.data, pkt.size, 0);
1073         }
1074     }
1075
1076     vnet_state.pkt_to_vmm ++;
1077
1078     return v3_vnet_send_pkt(&pkt, NULL, 1);
1079 }
1080
1081
1082 /* send packet to extern network */
1083 static int 
1084 bridge_send_pkt(struct v3_vm_info * vm, 
1085                 struct v3_vnet_pkt * pkt, 
1086                 void * private_data) {
1087     struct vnet_link * link;
1088
1089     if(net_debug >= 2){
1090         printk("VNET Lnx Host Bridge: packet received from VNET Core ... pkt size: %d, link: %d\n",
1091                         pkt->size,
1092                         pkt->dst_id);
1093         if(net_debug >= 4){
1094             print_hex_dump(NULL, "pkt_data: ", 0, 20, 20, pkt->data, pkt->size, 0);
1095         }
1096     }
1097
1098     vnet_state.pkt_from_vmm ++;
1099
1100     link = link_by_idx(pkt->dst_id);
1101     if (link != NULL) {
1102         switch(link->sock_proto){
1103             case UDP:
1104                 udp_send(link->sock, &(link->sock_addr), pkt->data, pkt->size);
1105                 vnet_state.pkt_to_phy ++;
1106                 break;
1107             case TCP:
1108                 vnet_state.pkt_to_phy ++;
1109                 break;  
1110
1111             default:
1112                 printk("VNET Server: Invalid Link Protocol\n");
1113                 vnet_state.pkt_drop_vmm ++;
1114         }
1115         link->bytes_tx += pkt->size;
1116         link->pkt_tx ++;
1117     } else {
1118         printk("VNET Bridge Linux Host: wrong dst link, idx: %d, discards the packet\n", pkt->dst_id);
1119         vnet_state.pkt_drop_vmm ++;
1120     }
1121
1122     return 0;
1123 }
1124
1125
1126 static int init_vnet_serv(void) {
1127     int protocol;
1128     int err;
1129
1130     switch(vnet_state.serv_proto){
1131         case UDP:
1132             protocol = IPPROTO_UDP;
1133             break;
1134         case TCP:
1135             protocol = IPPROTO_TCP;
1136             break;
1137
1138         default:
1139            printk("Unsupported VNET Server Protocol\n");
1140             return -1;
1141     }
1142          
1143     if ((err = sock_create(AF_INET, SOCK_DGRAM, protocol, &vnet_state.serv_sock)) < 0) {
1144         printk("Could not create VNET server socket, error: %d\n", err);
1145         return -1;
1146     }
1147
1148     memset(&vnet_state.serv_addr, 0, sizeof(struct sockaddr));
1149
1150     vnet_state.serv_addr.sin_family = AF_INET;
1151     vnet_state.serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
1152     vnet_state.serv_addr.sin_port = htons(VNET_SERVER_PORT);
1153
1154     if ((err = vnet_state.serv_sock->ops->bind(vnet_state.serv_sock, (struct sockaddr *)&(vnet_state.serv_addr), sizeof(struct sockaddr))) < 0) {
1155         printk("Could not bind VNET server socket to port %d, error: %d\n", VNET_SERVER_PORT, err);
1156         return -1;
1157     }
1158
1159     printk("VNET server bind to port: %d\n", VNET_SERVER_PORT);
1160
1161     if(vnet_state.serv_proto == TCP){
1162         if((err = vnet_state.serv_sock->ops->listen(vnet_state.serv_sock, 32)) < 0){
1163             printk("VNET Server error listening on port %d, error %d\n", VNET_SERVER_PORT, err);
1164             return -1;
1165         }
1166     }
1167
1168     return 0;
1169 }
1170
1171 static int vnet_udp_server(void * arg) {
1172     unsigned char * pkt;
1173     struct sockaddr_in pkt_addr;
1174     struct vnet_link * link = NULL;
1175     int len;
1176
1177     printk("Palacios VNET Bridge: UDP receiving server ..... \n");
1178
1179     pkt = kmalloc(MAX_PACKET_LEN, GFP_KERNEL);
1180     while (!kthread_should_stop()) {
1181         
1182         len = udp_recv(vnet_state.serv_sock, &pkt_addr, pkt, MAX_PACKET_LEN); 
1183         if(len < 0) {
1184             printk("Receive error: Could not get packet, error %d\n", len);
1185             continue;
1186         }
1187
1188         link = link_by_ip(pkt_addr.sin_addr.s_addr);
1189         if (link == NULL){
1190             printk("VNET Server: No VNET Link match the src IP\n");
1191             vnet_state.pkt_drop_phy ++;
1192             continue;
1193         }
1194         
1195         vnet_state.pkt_from_phy ++;
1196         link->bytes_rx += len;
1197         link->pkt_rx ++;
1198
1199         send_to_palacios(pkt, len, link->idx);
1200     }
1201
1202     kfree(pkt);
1203
1204     return 0;
1205 }
1206
1207
1208
1209 static int vnet_server(void * arg) {
1210     
1211     if(vnet_state.serv_proto == UDP){
1212         vnet_udp_server(NULL);
1213     }else if(vnet_state.serv_proto == TCP) {
1214         //accept new connection
1215         //use select to receive pkt from physical network
1216         //or create new kthread to handle each connection?
1217     }else {
1218         printk ("VNET Server: Unsupported Protocol\n");
1219         return -1;
1220     }
1221
1222     return 0;
1223 }
1224
1225 static inline unsigned int hash_fn(addr_t hdr_ptr) {    
1226     return vnet_hash_buffer((uint8_t *)hdr_ptr, sizeof(uint32_t));
1227 }
1228
1229 static inline int hash_eq(addr_t key1, addr_t key2) {   
1230     return (memcmp((uint8_t *)key1, (uint8_t *)key2, sizeof(uint32_t)) == 0);
1231 }
1232
1233
1234 int  palacios_init_vnet_bridge(void) {
1235     struct v3_vnet_bridge_ops bridge_ops;
1236
1237
1238     if(vnet_state.status != 0) {
1239         return -1;
1240     }   
1241     vnet_state.status = 1;      
1242         
1243     memset(&vnet_state, 0, sizeof(struct palacios_vnet_state));
1244
1245     INIT_LIST_HEAD(&(vnet_state.link_list));
1246     INIT_LIST_HEAD(&(vnet_state.route_list));
1247     spin_lock_init(&(vnet_state.lock));
1248
1249     init_proc_files();
1250
1251     vnet_state.serv_proto = UDP;
1252
1253     vnet_state.ip2link = vnet_create_htable(10, hash_fn, hash_eq);
1254     if(vnet_state.ip2link == NULL){
1255         printk("Failure to initiate VNET link hashtable\n");
1256         return -1;
1257     }
1258         
1259     if(init_vnet_serv() < 0){
1260         printk("Failure to initiate VNET server\n");
1261         return -1;
1262     }
1263
1264     vnet_state.serv_thread = kthread_run(vnet_server, NULL, "vnet-server");
1265
1266     bridge_ops.input = bridge_send_pkt;
1267     bridge_ops.poll = NULL;
1268         
1269     v3_vnet_add_bridge(NULL, &bridge_ops, HOST_LNX_BRIDGE, NULL);
1270
1271     printk("Palacios VNET Linux Bridge initiated\n");
1272
1273     return 0;
1274 }
1275
1276
1277 void palacios_deinit_vnet_bridge(void){
1278
1279     destroy_proc_files();
1280
1281     //v3_vnet_delete_bridge(NULL, &bridge_ops, HOST_LNX_BRIDGE, NULL);
1282     kthread_stop(vnet_state.serv_thread);
1283     vnet_state.serv_sock->ops->release(vnet_state.serv_sock);
1284
1285     deinit_links_list();
1286     deinit_routes_list();
1287
1288     vnet_free_htable(vnet_state.ip2link, 0, 0);
1289
1290     vnet_state.status = 0;
1291 }
1292
1293