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.


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