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.


86ec1296ad75a24f269ab8779518faec5fb4a4a5
[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     palacios_spinlock_lock_irqsave(&(vnet_ctrl_s.lock), flags);
548     list_add(&(route->node), &(vnet_ctrl_s.route_list));
549     vnet_ctrl_s.num_routes ++;
550     palacios_spinlock_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     palacios_spinlock_lock_irqsave(&(vnet_ctrl_s.lock), flags);
564     list_del(&(route->node));
565     vnet_ctrl_s.num_routes --;
566     palacios_spinlock_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     palacios_spinlock_lock_irqsave(&(vnet_ctrl_s.lock), flags);
676     list_del(&(link->node));
677     vnet_ctrl_s.num_links --;
678     palacios_spinlock_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     link_buf[size] = '\0';
719     INFO("Link written: %s\n", link_buf);
720
721     while ((link_iter = skip_lines(&line_str))) {
722         
723         token = skip_blank(&link_iter);
724         if (!token) {
725             return -EFAULT;
726         }
727         
728         if (strnicmp("ADD", token, strlen("ADD")) == 0) {
729             struct vnet_link_iter * link = NULL;
730             char * ip_str = NULL;
731             uint32_t d_ip;
732             uint16_t d_port;
733             vnet_brg_proto_t d_proto;
734             int link_idx;
735             unsigned long flags;
736             
737             ip_str = skip_blank(&link_iter);
738             
739             if ((!ip_str) || (!link_iter)) {
740                 WARNING("Missing fields in ADD Link command\n");
741                 return -EFAULT;
742             }
743             
744             if (in4_pton(ip_str, strlen(ip_str), (uint8_t *)&(d_ip), '\0', NULL) != 1) {
745                 WARNING("Invalid Dst IP address (%s)\n", ip_str);
746                 return -EFAULT;
747             }
748
749             d_port = simple_strtol(link_iter, &link_iter, 10);
750             d_proto = UDP;
751
752             link_idx = vnet_brg_add_link(d_ip, d_port, d_proto);
753             if(link_idx < 0){
754                 WARNING("VNET Control: Failed to create link\n");
755                 return -EFAULT;
756             }
757
758             link = palacios_alloc(sizeof(struct vnet_link_iter));
759             if (!link) {
760                 WARNING("VNET Control: Cannot allocate link\n");
761                 return -EFAULT;
762             }
763
764             memset(link, 0, sizeof(struct vnet_link_iter));
765
766             link->dst_ip = d_ip;
767             link->dst_port = d_port;
768             link->proto = d_proto;
769             link->idx = link_idx;
770
771             palacios_spinlock_lock_irqsave(&(vnet_ctrl_s.lock), flags);
772             list_add(&(link->node), &(vnet_ctrl_s.link_iter_list));
773             vnet_ctrl_s.num_links ++;
774             palacios_spinlock_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
775         } else if (strnicmp("DEL", token, strlen("DEL")) == 0) {
776             char * idx_str = NULL;
777             uint32_t d_idx;
778             struct vnet_link_iter * link = NULL;
779             
780             idx_str = skip_blank(&link_iter);
781             
782             if (!idx_str) {
783                 WARNING("Missing link idx in DEL Link command\n");
784                 return -EFAULT;
785             }
786
787             d_idx = simple_strtoul(idx_str, &idx_str, 10);
788
789             INFO("VNET: deleting link %d\n", d_idx);
790
791             list_for_each_entry(link, &(vnet_ctrl_s.link_iter_list), node) {
792                 if (link->idx == d_idx) {
793                     delete_link(link);
794                     break;
795                 }
796             }
797
798             DEBUG("VNET Control: One link deleted\n");          
799
800         } else {
801             WARNING("Invalid Link command string\n");
802         }
803     }
804
805     return size;
806 }
807
808
809 static struct file_operations route_fops = {
810     .owner = THIS_MODULE,
811     .open = route_open, 
812     .read = seq_read,
813     .write = route_write,
814     .llseek = seq_lseek,
815     .release = seq_release
816 };
817
818
819 static struct file_operations link_fops = {
820     .owner = THIS_MODULE,
821     .open = link_open, 
822     .read = seq_read,
823     .write = link_write,
824     .llseek = seq_lseek,
825     .release = seq_release
826 };
827
828
829 static ssize_t 
830 debug_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
831     char in_buf[32];
832     char * in_iter = NULL;
833     char * line_str = in_buf;
834     int level = -1; 
835
836     if (size >= 32) {
837         return -EFAULT;
838     }
839
840     if (copy_from_user(in_buf, buf, size)) {
841         return -EFAULT;
842     }
843
844     in_iter = skip_lines(&line_str);
845     level = simple_strtol(in_iter, &in_iter, 10);
846
847     DEBUG("VNET Control: Set VNET Debug level to %d\n", level);
848
849     if(level >= 0){
850         net_debug = level;
851     }
852
853     return size;
854 }
855
856
857 static int debug_show(struct seq_file * file, void * v){
858     seq_printf(file, "Current NET Debug Level: %d\n", net_debug);
859         
860     return 0;
861 }
862
863 static int debug_open(struct inode * inode, struct file * file) {
864     return single_open(file, debug_show, NULL);
865 }
866
867 static struct file_operations debug_fops = {
868     .owner = THIS_MODULE,
869     .open = debug_open, 
870     .read = seq_read,
871     .write = debug_write,
872     .llseek = seq_lseek,
873     .release = seq_release
874 };
875
876 static int stat_show(struct seq_file * file, void * v){
877     struct vnet_stat stats;
878     struct vnet_brg_stats brg_stats;
879
880     v3_vnet_stat(&stats);
881
882     seq_printf(file, "VNET Core\n");
883     seq_printf(file, "\tReceived Packets: %d\n", stats.rx_pkts);
884     seq_printf(file, "\tReceived Bytes: %lld\n", stats.rx_bytes);
885     seq_printf(file, "\tTransmitted Packets: %d\n", stats.tx_pkts);
886     seq_printf(file, "\tTransmitted Bytes: %lld\n", stats.tx_bytes);
887
888     vnet_brg_stats(&brg_stats);
889    
890     seq_printf(file, "\nVNET Bridge Server\n");
891     seq_printf(file, "\tReceived From VMM: %lld\n", brg_stats.pkt_from_vmm);
892     seq_printf(file, "\tSent To VMM: %lld\n", brg_stats.pkt_to_vmm);
893     seq_printf(file, "\tDropped From VMM: %lld\n", brg_stats.pkt_drop_vmm);
894     seq_printf(file, "\tReceived From Extern Network: %lld\n", brg_stats.pkt_from_phy);
895     seq_printf(file, "\tSent To Extern Network: %lld\n", brg_stats.pkt_to_phy);
896     seq_printf(file, "\tDropped From Extern Network: %lld\n", brg_stats.pkt_drop_phy);
897
898     return 0;
899 }
900
901 static int stat_open(struct inode * inode, struct file * file) {
902     return single_open(file, stat_show, NULL);
903 }
904
905 static struct file_operations stat_fops = {
906     .owner = THIS_MODULE,
907     .open = stat_open, 
908     .read = seq_read,
909     .llseek = seq_lseek,
910     .release = seq_release
911 };
912
913
914 static int init_proc_files(void) {
915     struct proc_dir_entry * route_entry = NULL;
916     struct proc_dir_entry * link_entry = NULL;
917     struct proc_dir_entry * stat_entry = NULL;
918     struct proc_dir_entry * debug_entry = NULL;
919     struct proc_dir_entry * vnet_root = NULL;
920
921
922     vnet_root = proc_mkdir("vnet", palacios_get_procdir());
923
924     if (vnet_root == NULL) {
925         return -1;
926     }
927
928     route_entry = create_proc_entry("routes", 0644, vnet_root);
929     if (route_entry == NULL) {
930         remove_proc_entry("vnet", NULL);
931         return -1;
932     }
933     route_entry->proc_fops = &route_fops;
934         
935
936     link_entry = create_proc_entry("links", 0644, vnet_root);
937     if (link_entry == NULL) {
938         remove_proc_entry("routes", vnet_root);
939         remove_proc_entry("vnet", NULL);
940         return -1;
941     }
942     link_entry->proc_fops = &link_fops;
943         
944
945     stat_entry = create_proc_entry("stats", 0644, vnet_root);
946     if(stat_entry == NULL) {
947         remove_proc_entry("links", vnet_root);
948         remove_proc_entry("routes", vnet_root);
949         remove_proc_entry("vnet", NULL);
950         return -1;
951     }
952     stat_entry->proc_fops = &stat_fops;
953
954
955     debug_entry = create_proc_entry("debug", 0644, vnet_root);
956     if(debug_entry == NULL) {
957         remove_proc_entry("links", vnet_root);
958         remove_proc_entry("routes", vnet_root);
959         remove_proc_entry("stats", vnet_root);
960         remove_proc_entry("vnet", NULL);
961         return -1;
962     }
963     debug_entry->proc_fops = &debug_fops;
964
965     vnet_ctrl_s.vnet_proc_root = vnet_root;
966
967     return 0;
968 }
969
970
971 static void destroy_proc_files(void) {
972     struct proc_dir_entry * vnet_root = vnet_ctrl_s.vnet_proc_root;
973
974     remove_proc_entry("debug", vnet_root);
975     remove_proc_entry("links", vnet_root);
976     remove_proc_entry("routes", vnet_root);
977     remove_proc_entry("stats", vnet_root);
978     remove_proc_entry("vnet", palacios_get_procdir());  
979 }
980
981
982 int vnet_ctrl_init(void) {
983     if(vnet_ctrl_s.status != 0) {
984         return -1;
985     }   
986     vnet_ctrl_s.status = 1;     
987         
988     memset(&vnet_ctrl_s, 0, sizeof(struct vnet_ctrl_state));
989
990     INIT_LIST_HEAD(&(vnet_ctrl_s.link_iter_list));
991     INIT_LIST_HEAD(&(vnet_ctrl_s.route_list));
992     palacios_spinlock_init(&(vnet_ctrl_s.lock));
993
994     init_proc_files();
995         
996     NOTICE("VNET Linux control module initiated\n");
997
998     return 0;
999 }
1000
1001
1002 void vnet_ctrl_deinit(void){
1003     
1004     INFO("VNET Control Deinit Started\n");
1005
1006     destroy_proc_files();
1007
1008     deinit_links_list();
1009     deinit_routes_list();
1010
1011     vnet_ctrl_s.status = 0;
1012
1013     palacios_spinlock_deinit(&(vnet_ctrl_s.lock));
1014
1015     INFO("VNET Control Deinit Finished\n");
1016 }
1017
1018