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.


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