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.


add missed file
[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             
615             idx_str = strsep(&buf_iter, " ");
616             
617             if (!idx_str) {
618                 printk("Missing route idx in DEL Route command\n");
619                 return -EFAULT;
620             }
621
622             d_idx = simple_strtoul(idx_str, &idx_str, 10);
623
624             v3_vnet_del_route(d_idx);
625                 
626             printk("VNET Control: One route deleted\n");                
627
628         } else {
629             printk("Invalid Route command string\n");
630         }
631     }
632
633     return size;
634 }
635
636
637 static void delete_link(struct vnet_link_iter * link){
638     unsigned long flags;
639
640     vnet_brg_delete_link(link->idx);
641
642     spin_lock_irqsave(&(vnet_ctrl_s.lock), flags);
643     list_del(&(link->node));
644     vnet_ctrl_s.num_links --;
645     spin_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
646
647     kfree(link);
648     link = NULL;
649 }
650
651
652 static void deinit_links_list(void){
653     struct vnet_link_iter * link;
654
655     list_for_each_entry(link, &(vnet_ctrl_s.link_iter_list), node) {
656         delete_link(link);
657     }
658 }
659
660 static void deinit_routes_list(void){
661    struct vnet_route_iter * route;
662
663    list_for_each_entry(route, &(vnet_ctrl_s.route_list), node) {
664         delete_route(route);
665    }
666 }
667
668 /* ADD dst-ip 9000 [udp|tcp] */
669 /* DEL link-idx */
670 static ssize_t 
671 link_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
672     char link_buf[256];
673     char * link_iter = NULL;
674     char * line_str = link_buf;
675     char * token = NULL;
676
677     if (size >= 256) {
678         return -EFAULT;
679     }
680
681     if (copy_from_user(link_buf, buf, size)) {
682         return -EFAULT;
683     }
684
685     while ((link_iter = strsep(&line_str, "\r\n"))) {
686         printk("Link written: %s\n", link_buf);
687         
688         token = strsep(&link_iter, " ");
689         
690         if (!token) {
691             return -EFAULT;
692         }
693         
694         if (strnicmp("ADD", token, strlen("ADD")) == 0) {
695             struct vnet_link_iter * link = NULL;
696             char * ip_str = NULL;
697             uint32_t d_ip;
698             uint16_t d_port;
699             vnet_brg_proto_t d_proto;
700             int link_idx;
701             unsigned long flags;
702             
703             ip_str = strsep(&link_iter, " ");
704             
705             if ((!ip_str) || (!link_iter)) {
706                 printk("Missing fields in ADD Link command\n");
707                 return -EFAULT;
708             }
709             
710             if (in4_pton(ip_str, strlen(ip_str), (uint8_t *)&(d_ip), '\0', NULL) != 1) {
711                 printk("Invalid Dst IP address (%s)\n", ip_str);
712                 return -EFAULT;
713             }
714
715             d_port = simple_strtol(link_iter, &link_iter, 10);
716             d_proto = UDP;
717
718             link_idx = vnet_brg_add_link(d_ip, d_port, d_proto);
719             if(link_idx < 0){
720                 printk("VNET Control: Failed to create link\n");
721                 return -EFAULT;
722             }
723
724             link = kmalloc(sizeof(struct vnet_link_iter), GFP_KERNEL);
725             memset(link, 0, sizeof(struct vnet_link_iter));
726
727             link->dst_ip = d_ip;
728             link->dst_port = d_port;
729             link->proto = d_proto;
730             link->idx = link_idx;
731
732             spin_lock_irqsave(&(vnet_ctrl_s.lock), flags);
733             list_add(&(link->node), &(vnet_ctrl_s.link_iter_list));
734             vnet_ctrl_s.num_links ++;
735             spin_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
736         } else if (strnicmp("DEL", token, strlen("DEL")) == 0) {
737             char * idx_str = NULL;
738             uint32_t d_idx;
739             
740             idx_str = strsep(&link_iter, " ");
741             
742             if (!idx_str) {
743                 printk("Missing link idx in DEL Link command\n");
744                 return -EFAULT;
745             }
746
747             d_idx = simple_strtoul(idx_str, &idx_str, 10);
748
749             vnet_brg_delete_link(d_idx);
750                 
751             printk("VNET Control: One link deleted\n");         
752         } else {
753             printk("Invalid Link command string\n");
754         }
755     }
756
757     return size;
758 }
759
760
761 static struct file_operations route_fops = {
762     .owner = THIS_MODULE,
763     .open = route_open, 
764     .read = seq_read,
765     .write = route_write,
766     .llseek = seq_lseek,
767     .release = seq_release
768 };
769
770
771 static struct file_operations link_fops = {
772     .owner = THIS_MODULE,
773     .open = link_open, 
774     .read = seq_read,
775     .write = link_write,
776     .llseek = seq_lseek,
777     .release = seq_release
778 };
779
780
781 static ssize_t 
782 debug_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
783     char in_buf[32];
784     char * in_iter = NULL;
785     char * line_str = in_buf;
786     int level = -1; 
787
788     if (size >= 32) {
789         return -EFAULT;
790     }
791
792     if (copy_from_user(in_buf, buf, size)) {
793         return -EFAULT;
794     }
795
796     in_iter = strsep(&line_str, "\r\n");
797     level = simple_strtol(in_iter, &in_iter, 10);
798
799     printk("VNET Control: Set VNET Debug level to %d\n", level);
800
801     if(level >= 0){
802         net_debug = level;
803     }
804
805     return size;
806 }
807
808
809 static int debug_show(struct seq_file * file, void * v){
810     seq_printf(file, "Current NET Debug Level: %d\n", net_debug);
811         
812     return 0;
813 }
814
815 static int debug_open(struct inode * inode, struct file * file) {
816     return single_open(file, debug_show, NULL);
817 }
818
819 static struct file_operations debug_fops = {
820     .owner = THIS_MODULE,
821     .open = debug_open, 
822     .read = seq_read,
823     .write = debug_write,
824     .llseek = seq_lseek,
825     .release = seq_release
826 };
827
828 static int stat_show(struct seq_file * file, void * v){
829     struct vnet_stat stats;
830     struct vnet_brg_stats brg_stats;
831
832     v3_vnet_stat(&stats);
833
834     seq_printf(file, "VNET Core\n");
835     seq_printf(file, "\tReceived Packets: %d\n", stats.rx_pkts);
836     seq_printf(file, "\tReceived Bytes: %lld\n", stats.rx_bytes);
837     seq_printf(file, "\tTransmitted Packets: %d\n", stats.tx_pkts);
838     seq_printf(file, "\tTransmitted Bytes: %lld\n", stats.tx_bytes);
839
840     vnet_brg_stats(&brg_stats);
841    
842     seq_printf(file, "\nVNET Bridge Server\n");
843     seq_printf(file, "\tReceived From VMM: %lld\n", brg_stats.pkt_from_vmm);
844     seq_printf(file, "\tSent To VMM: %lld\n", brg_stats.pkt_to_vmm);
845     seq_printf(file, "\tDropped From VMM: %lld\n", brg_stats.pkt_drop_vmm);
846     seq_printf(file, "\tReceived From Extern Network: %lld\n", brg_stats.pkt_from_phy);
847     seq_printf(file, "\tSent To Extern Network: %lld\n", brg_stats.pkt_to_phy);
848     seq_printf(file, "\tDropped From Extern Network: %lld\n", brg_stats.pkt_drop_phy);
849
850     return 0;
851 }
852
853 static int stat_open(struct inode * inode, struct file * file) {
854     return single_open(file, stat_show, NULL);
855 }
856
857 static struct file_operations stat_fops = {
858     .owner = THIS_MODULE,
859     .open = stat_open, 
860     .read = seq_read,
861     .llseek = seq_lseek,
862     .release = seq_release
863 };
864
865
866 static int init_proc_files(void) {
867     struct proc_dir_entry * route_entry = NULL;
868     struct proc_dir_entry * link_entry = NULL;
869     struct proc_dir_entry * stat_entry = NULL;
870     struct proc_dir_entry * debug_entry = NULL;
871     struct proc_dir_entry * vnet_root = NULL;
872
873     vnet_root = proc_mkdir("vnet", NULL);
874     if (vnet_root == NULL) {
875         return -1;
876     }
877
878     route_entry = create_proc_entry("routes", 0, vnet_root);
879     if (route_entry == NULL) {
880         remove_proc_entry("vnet", NULL);
881         return -1;
882     }
883     route_entry->proc_fops = &route_fops;
884         
885
886     link_entry = create_proc_entry("links", 0, vnet_root);
887     if (link_entry == NULL) {
888         remove_proc_entry("routes", vnet_root);
889         remove_proc_entry("vnet", NULL);
890         return -1;
891     }
892     link_entry->proc_fops = &link_fops;
893         
894
895     stat_entry = create_proc_entry("stats", 0, vnet_root);
896     if(stat_entry == NULL) {
897         remove_proc_entry("links", vnet_root);
898         remove_proc_entry("routes", vnet_root);
899         remove_proc_entry("vnet", NULL);
900         return -1;
901     }
902     stat_entry->proc_fops = &stat_fops;
903
904
905     debug_entry = create_proc_entry("debug", 0, vnet_root);
906     if(debug_entry == NULL) {
907         remove_proc_entry("links", vnet_root);
908         remove_proc_entry("routes", vnet_root);
909         remove_proc_entry("stats", vnet_root);
910         remove_proc_entry("vnet", NULL);
911         return -1;
912     }
913     debug_entry->proc_fops = &debug_fops;
914
915     vnet_ctrl_s.vnet_proc_root = vnet_root;
916
917     return 0;
918 }
919
920
921 static void destroy_proc_files(void) {
922     struct proc_dir_entry * vnet_root = vnet_ctrl_s.vnet_proc_root;
923
924     remove_proc_entry("debug", vnet_root);
925     remove_proc_entry("links", vnet_root);
926     remove_proc_entry("routes", vnet_root);
927     remove_proc_entry("stats", vnet_root);
928     remove_proc_entry("vnet", NULL);    
929 }
930
931
932 int vnet_ctrl_init(void) {
933     if(vnet_ctrl_s.status != 0) {
934         return -1;
935     }   
936     vnet_ctrl_s.status = 1;     
937         
938     memset(&vnet_ctrl_s, 0, sizeof(struct vnet_ctrl_state));
939
940     INIT_LIST_HEAD(&(vnet_ctrl_s.link_iter_list));
941     INIT_LIST_HEAD(&(vnet_ctrl_s.route_list));
942     spin_lock_init(&(vnet_ctrl_s.lock));
943
944     init_proc_files();
945         
946     printk("VNET Linux control module initiated\n");
947
948     return 0;
949 }
950
951
952 void vnet_ctrl_deinit(void){
953     destroy_proc_files();
954
955     deinit_links_list();
956     deinit_routes_list();
957
958     vnet_ctrl_s.status = 0;
959 }
960
961