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.


Fix a bug in vnet when removing a route entry
[palacios.git] / linux_module / palacios-vnet-ctrl.c
1 /* 
2    Palacios VNET Control Module
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 vnet_route_iter {
28     struct v3_vnet_route route;
29     uint32_t idx;
30
31     struct list_head node;
32 };
33
34
35 struct vnet_link_iter {
36     uint32_t dst_ip;
37     uint16_t dst_port;
38     vnet_brg_proto_t proto;
39     uint32_t idx;
40
41     struct list_head node;
42 };
43
44
45 struct vnet_ctrl_state {
46     uint8_t status;
47
48     uint32_t num_links;
49     uint32_t num_routes;
50         
51     struct list_head route_list;
52     struct list_head link_iter_list;
53
54     spinlock_t lock;
55
56     struct proc_dir_entry * vnet_proc_root;
57 };
58
59
60 static struct vnet_ctrl_state vnet_ctrl_s;
61
62
63 static int parse_mac_str(char * str, uint8_t * qual, uint8_t * mac) {
64     char * token;
65
66     printk("Parsing MAC (%s)\n", str);
67         
68     *qual = MAC_NOSET;
69     if(strnicmp("any", str, strlen(str)) == 0){
70         *qual = MAC_ANY;
71         return 0;
72     }else if(strnicmp("none", str, strlen(str)) == 0){
73        *qual = MAC_NONE;
74         return 0;
75     }else{
76         if (strstr(str, "-")) {
77             token = strsep(&str, "-");
78
79             if (strnicmp("not", token, strlen("not")) == 0) {
80                 *qual = MAC_NOT;
81             } else {
82                 printk("Invalid MAC String token (%s)\n", token);
83                 return -1;
84             }
85         }
86
87         if (strstr(str, ":")) {
88             int i = 0;
89
90             if(*qual == MAC_NOSET){
91                 *qual = MAC_ADDR;
92             }
93
94             for (i = 0; i < 6; i++) {
95                 token = strsep(&str, ":");
96                 if (!token) {
97                     printk("Invalid MAC String token (%s)\n", token);
98                     return -1;
99                 }
100                 mac[i] = simple_strtol(token, &token, 16);
101             }
102            printk("MAC: %2x:%2x:%2x:%2x:%2x:%2x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
103                 
104         }else {
105             printk("Invalid MAC String token (%s)\n", token);
106             return -1;
107         }
108                 
109     }
110
111     return 0;
112 }
113
114
115 static int str2mac(char * str, uint8_t * mac){
116     int i = 0;
117     char *hex = NULL;
118         
119     for (i = 0; i < ETH_ALEN; i++) {            
120         hex = strsep(&str, ":");
121         if (!hex) {
122             printk("Invalid MAC String token (%s)\n", str);
123             return -1;
124         }
125         mac[i] = simple_strtol(hex, &hex, 16);
126     }
127         
128     return 0;
129 }
130
131
132 static inline struct vnet_link_iter * link_by_ip(uint32_t ip) {
133     struct vnet_link_iter * link = NULL;
134
135     list_for_each_entry(link, &(vnet_ctrl_s.link_iter_list), node) {
136
137         if (link->dst_ip == ip) {
138             return link;
139         }
140     }
141         
142     return NULL;
143 }
144
145 static inline struct vnet_link_iter * link_by_idx(int idx) {
146     struct vnet_link_iter * link = NULL;
147
148     list_for_each_entry(link, &(vnet_ctrl_s.link_iter_list), node) {
149         if (link->idx == idx) {
150             return link;
151         }
152     }
153         
154     return NULL;
155 }
156
157
158 static int parse_route_str(char * str, struct v3_vnet_route * route) {
159     char * token = NULL;
160     struct vnet_link_iter * link = NULL;
161
162     // src MAC
163     token = strsep(&str, " ");
164     if (!token) {
165         return -1;
166     }
167     parse_mac_str(token, &(route->src_mac_qual), route->src_mac);
168
169     // dst MAC
170     token = strsep(&str, " ");
171     if (!token) {
172         return -1;
173     }
174     parse_mac_str(token, &(route->dst_mac_qual), route->dst_mac);
175
176     // dst LINK type
177     token = strsep(&str, " ");
178     if (!token) {
179         return -1;
180     }
181     printk("dst type =(%s)\n", token);
182     
183     if (strnicmp("interface", token, strlen("interface")) == 0) {
184         route->dst_type = LINK_INTERFACE;
185     } else if (strnicmp("edge", token, strlen("edge")) == 0) {
186         route->dst_type = LINK_EDGE;
187     } else {
188         printk("Invalid Destination Link Type (%s)\n", token);
189         return -1;
190     }
191
192     // dst link
193     token = strsep(&str, " ");
194     if (!token) {
195         return -1;
196     }
197     printk("dst ID=(%s)\n", token);
198
199     // Figure out link here
200     if (route->dst_type == LINK_EDGE) {
201         uint32_t link_ip;
202
203         // Figure out Link Here
204         if (in4_pton(token, strlen(token), (uint8_t *)&(link_ip), '\0', NULL) != 1) {
205             printk("Invalid Dst IP address (%s)\n", token);
206             return -EFAULT;
207         }
208
209         link = link_by_ip(link_ip);
210         if (link != NULL){
211             route->dst_id = link->idx;
212         }else{
213             printk("can not find dst link %s\n", token);
214             return -1;
215         }
216
217         printk("link_ip = %d, link_id = %d\n", link_ip, link->idx);     
218     } else if (route->dst_type == LINK_INTERFACE) {
219         uint8_t mac[ETH_ALEN];
220         
221        if(str2mac(token, mac) == -1){
222            printk("wrong MAC format (%s)\n", token);
223            return -1;
224        }
225            
226         route->dst_id = v3_vnet_find_dev(mac);
227         if (route->dst_id == -1){
228             printk("can not find dst device %s\n", token);
229             return -1;
230         }               
231     } else {
232         printk("Unsupported dst link type\n");
233         return -1;
234     }
235
236     route->src_id = -1;
237     route->src_type = -1;
238
239     // src LINK
240     token = strsep(&str, " ");
241
242     printk("SRC type = %s\n", token);
243
244     if (!token) {
245         return -1;
246     }
247
248     if (strnicmp("interface", token, strlen("interface")) == 0) {
249         route->src_type = LINK_INTERFACE;
250     } else if (strnicmp("edge", token, strlen("edge")) == 0) {
251         route->src_type = LINK_EDGE;
252     } else if (strnicmp("any", token, strlen("any")) == 0) {
253         route->src_type = LINK_ANY;
254     } else {
255         printk("Invalid Src link type (%s)\n", token);
256         return -1;
257     }
258
259
260     if (route->src_type == LINK_ANY) {
261         route->src_id = -1;
262     } else if (route->src_type == LINK_EDGE) {
263         uint32_t src_ip;
264         token = strsep(&str, " ");
265
266         if (!token) {
267             return -1;
268         }
269
270         // Figure out Link Here
271         if (in4_pton(token, strlen(token), (uint8_t *)&(src_ip), '\0', NULL) != 1) {
272             printk("Invalid SRC IP address (%s)\n", token);
273             return -EFAULT;
274         }
275
276         link = link_by_ip(src_ip);
277         if (link != NULL){
278             route->src_id = link->idx;
279         }else{
280             printk("can not find src link %s\n", token);
281             return -1;
282         }
283     } else if(route->src_type == LINK_INTERFACE){
284        uint8_t mac[ETH_ALEN];
285         
286        if(str2mac(token, mac) == -1){
287            printk("wrong MAC format (%s)\n", token);
288            return -1;
289        }
290            
291         route->src_id = v3_vnet_find_dev(mac);
292         if (route->src_id == -1){
293             printk("can not find dst device %s\n", token);
294             return -1;
295         }               
296     } else {
297         printk("Invalid link type\n");
298         return -1;
299     }
300
301     return 0;
302 }
303
304
305 static void * route_seq_start(struct seq_file * s, loff_t * pos) {
306     struct vnet_route_iter * route_iter = NULL;
307     loff_t i = 0;
308
309     if (*pos >= vnet_ctrl_s.num_routes) {
310         return NULL;
311     }
312
313     list_for_each_entry(route_iter, &(vnet_ctrl_s.route_list), node) {
314         if (i == *pos) {
315             break;
316         }
317
318         i++;
319     }
320
321     return route_iter;
322 }
323
324
325 static void * route_seq_next(struct seq_file * s, void * v, loff_t * pos) {
326     struct vnet_route_iter * route_iter = NULL;
327
328     route_iter = list_entry(((struct vnet_route_iter *)v)->node.next, struct vnet_route_iter, node);
329
330     // Check if the list has looped
331     if (&(route_iter->node) == &(vnet_ctrl_s.route_list)) {
332         return NULL;
333     }
334
335     *pos += 1;
336
337     return route_iter;
338 }
339
340 static void route_seq_stop(struct seq_file * s, void * v) {
341
342     return;
343 }
344
345 static void * link_seq_start(struct seq_file * s, loff_t * pos) {
346     struct vnet_link_iter * link_iter = NULL;
347     loff_t i = 0;
348
349     if (*pos >= vnet_ctrl_s.num_links) {
350         return NULL;
351     }
352
353     list_for_each_entry(link_iter, &(vnet_ctrl_s.link_iter_list), node) {
354         if (i == *pos) {
355             break;
356         }
357
358         i++;
359     }
360
361     return link_iter;
362 }
363
364 static int route_seq_show(struct seq_file * s, void * v) {
365     struct vnet_route_iter * route_iter = v;
366     struct v3_vnet_route * route = &(route_iter->route);
367
368     seq_printf(s, "%d:\t", route_iter->idx);
369
370     seq_printf(s, "\nSrc:\t");
371     switch (route->src_mac_qual) {
372         case MAC_ANY:
373             seq_printf(s, "any ");
374             break;
375         case MAC_NONE:
376             seq_printf(s, "none ");
377             break;
378         case MAC_NOT:
379             seq_printf(s, "not-%2x:%2x:%2x:%2x:%2x:%2x ", 
380                        route->src_mac[0], route->src_mac[1], route->src_mac[2],
381                        route->src_mac[3], route->src_mac[4], route->src_mac[5]);
382             break;
383         default:
384             seq_printf(s, "%x:%x:%x:%x:%x:%x ", 
385                        route->src_mac[0], route->src_mac[1], route->src_mac[2],
386                        route->src_mac[3], route->src_mac[4], route->src_mac[5]);
387             break;
388     }
389
390     seq_printf(s, "\nDst:\t");
391     switch (route->dst_mac_qual) {
392         case MAC_ANY:
393             seq_printf(s, "any ");
394             break;
395         case MAC_NONE:
396             seq_printf(s, "none ");
397             break;
398         case MAC_NOT:
399             seq_printf(s, "not-%x:%x:%x:%x:%x:%x ", 
400                        route->src_mac[0], route->src_mac[1], route->src_mac[2],
401                        route->src_mac[3], route->src_mac[4], route->src_mac[5]);
402             break;
403         default:
404             seq_printf(s, "%x:%x:%x:%x:%x:%x ", 
405                        route->src_mac[0], route->src_mac[1], route->src_mac[2],
406                        route->src_mac[3], route->src_mac[4], route->src_mac[5]);
407             break;
408     }
409
410     seq_printf(s, "\nDst-Type:\t");
411     switch (route->dst_type) {
412         case LINK_EDGE: {
413             struct vnet_link_iter * link = (struct vnet_link_iter *)link_by_idx(route->dst_id);
414             seq_printf(s, "EDGE %pI4", &link->dst_ip);
415             break;
416         }
417         case LINK_INTERFACE: {
418             seq_printf(s, "INTERFACE ");
419             seq_printf(s, "%d ", route->dst_id);
420             break;
421         }
422         default:
423             seq_printf(s, "Invalid Dst Link Type (%d) ", route->dst_type);
424             break;
425     }
426
427     seq_printf(s, "\nSrc-Type:\t");
428     switch (route->src_type) {
429         case LINK_EDGE: {
430             struct vnet_link_iter * link = (struct vnet_link_iter *)link_by_idx(route->src_id);
431             seq_printf(s, "EDGE %pI4", &link->dst_ip);
432             break;
433         }
434         case LINK_INTERFACE: {
435             seq_printf(s, "INTERFACE %d", route->src_id);
436             break;
437         }
438         case LINK_ANY:
439             seq_printf(s, "ANY");
440             break;
441         default:
442             seq_printf(s, "Invalid Src Link Type (%d) ", route->src_type);
443             break;
444     }
445
446     seq_printf(s, "\n");
447
448     return 0;
449 }
450
451 static void * link_seq_next(struct seq_file * s, void * v, loff_t * pos) {
452     struct vnet_link_iter * link_iter = NULL;
453
454     link_iter = list_entry(((struct vnet_link_iter *)v)->node.next, struct vnet_link_iter, node);
455
456     // Check if the list has looped
457     if (&(link_iter->node) == &(vnet_ctrl_s.link_iter_list)) {
458         return NULL;
459     }
460
461     *pos += 1;
462
463     return link_iter;
464 }
465
466 static void link_seq_stop(struct seq_file * s, void * v) {
467
468     return;
469 }
470
471 static int link_seq_show(struct seq_file * s, void * v) {
472     struct vnet_link_iter * link_iter = v;
473     struct nic_statistics stats;
474
475     vnet_brg_link_stats(link_iter->idx, &stats);
476
477     seq_printf(s, "%d:\t%pI4\t%d\n\t\tReceived Pkts: %lld, Received Bytes %lld\n\t\tSent Pkts: %lld, Sent Bytes: %lld\n\n", 
478                link_iter->idx,
479                &link_iter->dst_ip,
480                link_iter->dst_port,
481                stats.rx_pkts,
482                stats.rx_bytes,
483                stats.tx_pkts,
484                stats.tx_bytes);
485
486     return 0;
487 }
488
489
490 static struct seq_operations route_seq_ops = {
491     .start = route_seq_start, 
492     .next = route_seq_next,
493     .stop = route_seq_stop,
494     .show = route_seq_show
495 };
496
497
498 static struct seq_operations link_seq_ops = {
499     .start = link_seq_start,
500     .next = link_seq_next,
501     .stop = link_seq_stop,
502     .show = link_seq_show
503 };
504
505
506 static int route_open(struct inode * inode, struct file * file) {
507     return seq_open(file, &route_seq_ops);
508 }
509
510
511 static int link_open(struct inode * inode, struct file * file) {
512     return seq_open(file, &link_seq_ops);
513 }
514
515
516
517 static int inject_route(struct vnet_route_iter * route) {
518     unsigned long flags;
519     
520     route->idx = v3_vnet_add_route(route->route);
521
522     spin_lock_irqsave(&(vnet_ctrl_s.lock), flags);
523     list_add(&(route->node), &(vnet_ctrl_s.route_list));
524     vnet_ctrl_s.num_routes ++;
525     spin_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
526
527     printk("VNET Control: One route added to VNET core\n");
528
529     return 0;
530 }
531
532
533 static void delete_route(struct vnet_route_iter * route) {
534     unsigned long flags;
535
536     v3_vnet_del_route(route->idx);
537
538     spin_lock_irqsave(&(vnet_ctrl_s.lock), flags);
539     list_del(&(route->node));
540     vnet_ctrl_s.num_routes --;
541     spin_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
542
543     printk("VNET Control: Route %d deleted from VNET\n", route->idx);
544
545     kfree(route);
546     route = NULL;
547 }
548
549
550 /* Format:
551   * add src-MAC dst-MAC dst-TYPE [dst-ID] src-TYPE [src-ID]
552   *
553   * src-MAC = dst-MAC = not-MAC|any|none|MAC 
554   * dst-TYPE = edge|interface 
555   * src-TYPE = edge|interface|any
556   * dst-ID = src-ID = IP|MAC
557   * MAC=xx:xx:xx:xx:xx:xx
558   * IP = xxx.xxx.xxx.xxx
559   *
560   *
561   * del route-idx
562   *
563   */
564 static ssize_t 
565 route_write(struct file * file, 
566             const char * buf, 
567             size_t size, 
568             loff_t * ppos) {
569     char route_buf[256];
570     char * buf_iter = NULL;
571     char * line_str = route_buf;
572     char * token = NULL;
573
574     if (size >= 256) {
575         return -EFAULT;
576     }
577
578     if (copy_from_user(route_buf, buf, size)) {
579         return -EFAULT;
580     }
581
582     route_buf[size] = '\0';
583     printk("Route written: %s\n", route_buf);
584
585     while ((buf_iter = strsep(&line_str, "\r\n"))) {
586
587         token = strsep(&buf_iter, " ");
588         if (!token) {
589             return -EFAULT;
590         }
591         
592         if (strnicmp("ADD", token, strlen("ADD")) == 0) {
593             struct vnet_route_iter * new_route = NULL;
594             new_route = kmalloc(sizeof(struct vnet_route_iter), GFP_KERNEL);
595             
596             if (!new_route) {
597                 return -ENOMEM;
598             }
599             
600             memset(new_route, 0, sizeof(struct vnet_route_iter));
601             
602             if (parse_route_str(buf_iter, &(new_route->route)) == -1) {
603                 kfree(new_route);
604                 return -EFAULT;
605             }
606             
607             if (inject_route(new_route) != 0) {
608                 kfree(new_route);
609                 return -EFAULT;
610             }
611         } else if (strnicmp("DEL", token, strlen("DEL")) == 0) {
612             char * idx_str = NULL;
613             uint32_t d_idx;
614             struct vnet_route_iter * route = NULL;
615
616             idx_str = strsep(&buf_iter, " ");
617             
618             if (!idx_str) {
619                 printk("Missing route idx in DEL Route command\n");
620                 return -EFAULT;
621             }
622
623             d_idx = simple_strtoul(idx_str, &idx_str, 10);
624
625             printk("VNET: deleting route %d\n", d_idx);
626
627             list_for_each_entry(route, &(vnet_ctrl_s.route_list), node) {
628                 if (route->idx == d_idx) {
629                     delete_route(route);
630                     break;
631                 }
632             }
633         } else {
634             printk("Invalid Route command string\n");
635         }
636     }
637
638     return size;
639 }
640
641
642 static void delete_link(struct vnet_link_iter * link){
643     unsigned long flags;
644
645     vnet_brg_delete_link(link->idx);
646
647     spin_lock_irqsave(&(vnet_ctrl_s.lock), flags);
648     list_del(&(link->node));
649     vnet_ctrl_s.num_links --;
650     spin_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
651
652     kfree(link);
653     link = NULL;
654 }
655
656
657 static void deinit_links_list(void){
658     struct vnet_link_iter * link;
659
660     list_for_each_entry(link, &(vnet_ctrl_s.link_iter_list), node) {
661         delete_link(link);
662     }
663 }
664
665 static void deinit_routes_list(void){
666    struct vnet_route_iter * route;
667
668    list_for_each_entry(route, &(vnet_ctrl_s.route_list), node) {
669         delete_route(route);
670    }
671 }
672
673 /* ADD dst-ip 9000 [udp|tcp] */
674 /* DEL link-idx */
675 static ssize_t 
676 link_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
677     char link_buf[256];
678     char * link_iter = NULL;
679     char * line_str = link_buf;
680     char * token = NULL;
681
682     if (size >= 256) {
683         return -EFAULT;
684     }
685
686     if (copy_from_user(link_buf, buf, size)) {
687         return -EFAULT;
688     }
689
690     while ((link_iter = strsep(&line_str, "\r\n"))) {
691         printk("Link written: %s\n", link_buf);
692         
693         token = strsep(&link_iter, " ");
694         
695         if (!token) {
696             return -EFAULT;
697         }
698         
699         if (strnicmp("ADD", token, strlen("ADD")) == 0) {
700             struct vnet_link_iter * link = NULL;
701             char * ip_str = NULL;
702             uint32_t d_ip;
703             uint16_t d_port;
704             vnet_brg_proto_t d_proto;
705             int link_idx;
706             unsigned long flags;
707             
708             ip_str = strsep(&link_iter, " ");
709             
710             if ((!ip_str) || (!link_iter)) {
711                 printk("Missing fields in ADD Link command\n");
712                 return -EFAULT;
713             }
714             
715             if (in4_pton(ip_str, strlen(ip_str), (uint8_t *)&(d_ip), '\0', NULL) != 1) {
716                 printk("Invalid Dst IP address (%s)\n", ip_str);
717                 return -EFAULT;
718             }
719
720             d_port = simple_strtol(link_iter, &link_iter, 10);
721             d_proto = UDP;
722
723             link_idx = vnet_brg_add_link(d_ip, d_port, d_proto);
724             if(link_idx < 0){
725                 printk("VNET Control: Failed to create link\n");
726                 return -EFAULT;
727             }
728
729             link = kmalloc(sizeof(struct vnet_link_iter), GFP_KERNEL);
730             memset(link, 0, sizeof(struct vnet_link_iter));
731
732             link->dst_ip = d_ip;
733             link->dst_port = d_port;
734             link->proto = d_proto;
735             link->idx = link_idx;
736
737             spin_lock_irqsave(&(vnet_ctrl_s.lock), flags);
738             list_add(&(link->node), &(vnet_ctrl_s.link_iter_list));
739             vnet_ctrl_s.num_links ++;
740             spin_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
741         } else if (strnicmp("DEL", token, strlen("DEL")) == 0) {
742             char * idx_str = NULL;
743             uint32_t d_idx;
744             
745             idx_str = strsep(&link_iter, " ");
746             
747             if (!idx_str) {
748                 printk("Missing link idx in DEL Link command\n");
749                 return -EFAULT;
750             }
751
752             d_idx = simple_strtoul(idx_str, &idx_str, 10);
753
754             vnet_brg_delete_link(d_idx);
755                 
756             printk("VNET Control: One link deleted\n");         
757         } else {
758             printk("Invalid Link command string\n");
759         }
760     }
761
762     return size;
763 }
764
765
766 static struct file_operations route_fops = {
767     .owner = THIS_MODULE,
768     .open = route_open, 
769     .read = seq_read,
770     .write = route_write,
771     .llseek = seq_lseek,
772     .release = seq_release
773 };
774
775
776 static struct file_operations link_fops = {
777     .owner = THIS_MODULE,
778     .open = link_open, 
779     .read = seq_read,
780     .write = link_write,
781     .llseek = seq_lseek,
782     .release = seq_release
783 };
784
785
786 static ssize_t 
787 debug_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
788     char in_buf[32];
789     char * in_iter = NULL;
790     char * line_str = in_buf;
791     int level = -1; 
792
793     if (size >= 32) {
794         return -EFAULT;
795     }
796
797     if (copy_from_user(in_buf, buf, size)) {
798         return -EFAULT;
799     }
800
801     in_iter = strsep(&line_str, "\r\n");
802     level = simple_strtol(in_iter, &in_iter, 10);
803
804     printk("VNET Control: Set VNET Debug level to %d\n", level);
805
806     if(level >= 0){
807         net_debug = level;
808     }
809
810     return size;
811 }
812
813
814 static int debug_show(struct seq_file * file, void * v){
815     seq_printf(file, "Current NET Debug Level: %d\n", net_debug);
816         
817     return 0;
818 }
819
820 static int debug_open(struct inode * inode, struct file * file) {
821     return single_open(file, debug_show, NULL);
822 }
823
824 static struct file_operations debug_fops = {
825     .owner = THIS_MODULE,
826     .open = debug_open, 
827     .read = seq_read,
828     .write = debug_write,
829     .llseek = seq_lseek,
830     .release = seq_release
831 };
832
833 static int stat_show(struct seq_file * file, void * v){
834     struct vnet_stat stats;
835     struct vnet_brg_stats brg_stats;
836
837     v3_vnet_stat(&stats);
838
839     seq_printf(file, "VNET Core\n");
840     seq_printf(file, "\tReceived Packets: %d\n", stats.rx_pkts);
841     seq_printf(file, "\tReceived Bytes: %lld\n", stats.rx_bytes);
842     seq_printf(file, "\tTransmitted Packets: %d\n", stats.tx_pkts);
843     seq_printf(file, "\tTransmitted Bytes: %lld\n", stats.tx_bytes);
844
845     vnet_brg_stats(&brg_stats);
846    
847     seq_printf(file, "\nVNET Bridge Server\n");
848     seq_printf(file, "\tReceived From VMM: %lld\n", brg_stats.pkt_from_vmm);
849     seq_printf(file, "\tSent To VMM: %lld\n", brg_stats.pkt_to_vmm);
850     seq_printf(file, "\tDropped From VMM: %lld\n", brg_stats.pkt_drop_vmm);
851     seq_printf(file, "\tReceived From Extern Network: %lld\n", brg_stats.pkt_from_phy);
852     seq_printf(file, "\tSent To Extern Network: %lld\n", brg_stats.pkt_to_phy);
853     seq_printf(file, "\tDropped From Extern Network: %lld\n", brg_stats.pkt_drop_phy);
854
855     return 0;
856 }
857
858 static int stat_open(struct inode * inode, struct file * file) {
859     return single_open(file, stat_show, NULL);
860 }
861
862 static struct file_operations stat_fops = {
863     .owner = THIS_MODULE,
864     .open = stat_open, 
865     .read = seq_read,
866     .llseek = seq_lseek,
867     .release = seq_release
868 };
869
870
871 static int init_proc_files(void) {
872     struct proc_dir_entry * route_entry = NULL;
873     struct proc_dir_entry * link_entry = NULL;
874     struct proc_dir_entry * stat_entry = NULL;
875     struct proc_dir_entry * debug_entry = NULL;
876     struct proc_dir_entry * vnet_root = NULL;
877
878     vnet_root = proc_mkdir("vnet", NULL);
879     if (vnet_root == NULL) {
880         return -1;
881     }
882
883     route_entry = create_proc_entry("routes", 0, vnet_root);
884     if (route_entry == NULL) {
885         remove_proc_entry("vnet", NULL);
886         return -1;
887     }
888     route_entry->proc_fops = &route_fops;
889         
890
891     link_entry = create_proc_entry("links", 0, vnet_root);
892     if (link_entry == NULL) {
893         remove_proc_entry("routes", vnet_root);
894         remove_proc_entry("vnet", NULL);
895         return -1;
896     }
897     link_entry->proc_fops = &link_fops;
898         
899
900     stat_entry = create_proc_entry("stats", 0, vnet_root);
901     if(stat_entry == NULL) {
902         remove_proc_entry("links", vnet_root);
903         remove_proc_entry("routes", vnet_root);
904         remove_proc_entry("vnet", NULL);
905         return -1;
906     }
907     stat_entry->proc_fops = &stat_fops;
908
909
910     debug_entry = create_proc_entry("debug", 0, vnet_root);
911     if(debug_entry == NULL) {
912         remove_proc_entry("links", vnet_root);
913         remove_proc_entry("routes", vnet_root);
914         remove_proc_entry("stats", vnet_root);
915         remove_proc_entry("vnet", NULL);
916         return -1;
917     }
918     debug_entry->proc_fops = &debug_fops;
919
920     vnet_ctrl_s.vnet_proc_root = vnet_root;
921
922     return 0;
923 }
924
925
926 static void destroy_proc_files(void) {
927     struct proc_dir_entry * vnet_root = vnet_ctrl_s.vnet_proc_root;
928
929     remove_proc_entry("debug", vnet_root);
930     remove_proc_entry("links", vnet_root);
931     remove_proc_entry("routes", vnet_root);
932     remove_proc_entry("stats", vnet_root);
933     remove_proc_entry("vnet", NULL);    
934 }
935
936
937 int vnet_ctrl_init(void) {
938     if(vnet_ctrl_s.status != 0) {
939         return -1;
940     }   
941     vnet_ctrl_s.status = 1;     
942         
943     memset(&vnet_ctrl_s, 0, sizeof(struct vnet_ctrl_state));
944
945     INIT_LIST_HEAD(&(vnet_ctrl_s.link_iter_list));
946     INIT_LIST_HEAD(&(vnet_ctrl_s.route_list));
947     spin_lock_init(&(vnet_ctrl_s.lock));
948
949     init_proc_files();
950         
951     printk("VNET Linux control module initiated\n");
952
953     return 0;
954 }
955
956
957 void vnet_ctrl_deinit(void){
958     destroy_proc_files();
959
960     deinit_links_list();
961     deinit_routes_list();
962
963     vnet_ctrl_s.status = 0;
964 }
965
966