Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


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