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