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.


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