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.


Merge branch 'devel' of newskysaw.cs.northwestern.edu:/home/palacios/palacios into...
[palacios.git] / linux_module / palacios-vnet-brg.c
1 /* 
2  * Palacios VNET Host Bridge
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
26 #define VNET_SERVER_PORT 9000
27
28 struct vnet_link {
29     uint32_t dst_ip;
30     uint16_t dst_port;
31     
32     struct socket * sock;
33     struct sockaddr_in sock_addr;
34     vnet_brg_proto_t sock_proto;
35
36     struct nic_statistics stats;
37
38     uint32_t idx;
39
40     struct list_head node;
41 };
42
43
44 struct vnet_brg_state {
45     uint8_t status;
46
47     uint32_t num_links;
48     uint32_t link_idx;
49     struct list_head link_list;
50     struct hashtable *ip2link;
51
52     spinlock_t lock;
53
54     struct socket * serv_sock;
55     struct sockaddr_in serv_addr;
56     vnet_brg_proto_t serv_proto;
57         
58     struct task_struct * serv_thread;
59
60     void * brg_data; /* private data from vnet_core */
61
62     struct vnet_brg_stats stats;
63 };
64
65
66 static struct vnet_brg_state vnet_brg_s;
67
68
69 int vnet_brg_stats(struct vnet_brg_stats * stats){
70     memcpy(stats, &(vnet_brg_s.stats), sizeof(*stats));
71
72     return 0;
73 }
74
75 static inline struct vnet_link * _link_by_ip(uint32_t ip) {
76     return (struct vnet_link *)vnet_htable_search(vnet_brg_s.ip2link, (addr_t)&ip);
77 }
78
79 static inline struct vnet_link * _link_by_idx(int idx) {
80     struct vnet_link * link = NULL;
81
82     list_for_each_entry(link, &(vnet_brg_s.link_list), node) {
83                 
84         if (link->idx == idx) {
85             return link;
86         }
87     }
88     return NULL;
89 }
90
91
92 static void _delete_link(struct vnet_link * link){
93     unsigned long flags;
94
95     link->sock->ops->release(link->sock);
96
97     spin_lock_irqsave(&(vnet_brg_s.lock), flags);
98     list_del(&(link->node));
99     vnet_htable_remove(vnet_brg_s.ip2link, (addr_t)&(link->dst_ip), 0);
100     vnet_brg_s.num_links --;
101     spin_unlock_irqrestore(&(vnet_brg_s.lock), flags);
102
103     printk("VNET Bridge: Link deleted, ip 0x%x, port: %d, idx: %d\n", 
104            link->dst_ip, 
105            link->dst_port, 
106            link->idx);
107
108     kfree(link);
109     link = NULL;
110 }
111
112 void vnet_brg_delete_link(uint32_t idx){
113     struct vnet_link * link = _link_by_idx(idx);
114
115     if(link){
116         _delete_link(link);
117     }
118 }
119
120 static void deinit_links_list(void){
121     struct vnet_link * link;
122
123     list_for_each_entry(link, &(vnet_brg_s.link_list), node) {
124         _delete_link(link);
125     }
126 }
127
128 static uint32_t _create_link(struct vnet_link * link) {
129     int err;
130     unsigned long flags;
131     int protocol;
132
133     switch(link->sock_proto){
134         case UDP:
135             protocol = IPPROTO_UDP;
136             break;
137         case TCP:
138             protocol = IPPROTO_TCP;
139             break;
140
141         default:
142            printk("Unsupported VNET Server Protocol\n");
143             return -1;
144     }
145    
146     if ((err = sock_create(AF_INET, SOCK_DGRAM, protocol, &link->sock)) < 0) {
147         printk("Could not create socket for VNET Link, error %d\n", err);
148         return -1;
149     }
150
151     memset(&link->sock_addr, 0, sizeof(struct sockaddr));
152
153     link->sock_addr.sin_family = AF_INET;
154     link->sock_addr.sin_addr.s_addr = link->dst_ip;
155     link->sock_addr.sin_port = htons(link->dst_port);
156
157     if ((err = link->sock->ops->connect(link->sock, (struct sockaddr *)&(link->sock_addr), sizeof(struct sockaddr), 0) < 0)) {
158         printk("Could not connect to remote VNET Server, error %d\n", err);
159         return -1;
160     }
161
162     spin_lock_irqsave(&(vnet_brg_s.lock), flags);
163     list_add(&(link->node), &(vnet_brg_s.link_list));
164     vnet_brg_s.num_links ++;
165     link->idx = ++ vnet_brg_s.link_idx;
166     vnet_htable_insert(vnet_brg_s.ip2link, (addr_t)&(link->dst_ip), (addr_t)link);
167     spin_unlock_irqrestore(&(vnet_brg_s.lock), flags);
168
169     printk("VNET Bridge: Link created, ip 0x%x, port: %d, idx: %d, link: %p, protocol: %s\n", 
170            link->dst_ip, 
171            link->dst_port, 
172            link->idx, 
173            link,
174            ((link->sock_proto==UDP)?"UDP":"TCP"));
175
176     return link->idx;
177 }
178
179
180 uint32_t vnet_brg_add_link(uint32_t ip, uint16_t port, vnet_brg_proto_t proto){
181      struct vnet_link * new_link = NULL;
182      uint32_t idx;
183
184      new_link = kmalloc(sizeof(struct vnet_link), GFP_KERNEL);
185      if (!new_link) {
186         return -1;
187      }
188      memset(new_link, 0, sizeof(struct vnet_link));
189
190      new_link->dst_ip = ip;
191      new_link->dst_port = port;
192      new_link->sock_proto = proto;
193
194      idx = _create_link(new_link);
195      if (idx < 0) {
196         printk("Could not create link\n");
197         kfree(new_link);
198         return -1;
199      }
200
201      return idx;
202 }
203
204
205 int vnet_brg_link_stats(uint32_t link_idx, struct nic_statistics * stats){
206      struct vnet_link * link;
207
208      link = _link_by_idx(link_idx);
209      if(!link){
210          return -1;
211      }
212
213      memcpy(stats, &(link->stats), sizeof(*stats));
214
215      return 0;
216 }
217      
218
219 static int 
220 _udp_send(struct socket * sock, 
221          struct sockaddr_in * addr,
222          unsigned char * buf,  int len) {
223     struct msghdr msg;
224     struct iovec iov;
225     mm_segment_t oldfs;
226     int size = 0;
227
228           
229     if (sock->sk == NULL) {
230         return 0;
231     }
232
233     iov.iov_base = buf;
234     iov.iov_len = len;
235
236     msg.msg_flags = 0;
237     msg.msg_name = addr;
238     msg.msg_namelen = sizeof(struct sockaddr_in);
239     msg.msg_control = NULL;
240     msg.msg_controllen = 0;
241     msg.msg_iov = &iov;
242     msg.msg_iovlen = 1;
243     msg.msg_control = NULL;
244
245     oldfs = get_fs();
246     set_fs(KERNEL_DS);
247     size = sock_sendmsg(sock, &msg, len);
248     set_fs(oldfs);
249
250     return size;
251 }
252
253
254
255 static int 
256 _udp_recv(struct socket * sock, 
257          struct sockaddr_in * addr,
258          unsigned char * buf, int len) {
259     struct msghdr msg;
260     struct iovec iov;
261     mm_segment_t oldfs;
262     int size = 0;
263     
264     if (sock->sk == NULL) {
265         return 0;
266     }
267
268     iov.iov_base = buf;
269     iov.iov_len = len;
270     
271     msg.msg_flags = 0;
272     msg.msg_name = addr;
273     msg.msg_namelen = sizeof(struct sockaddr_in);
274     msg.msg_control = NULL;
275     msg.msg_controllen = 0;
276     msg.msg_iov = &iov;
277     msg.msg_iovlen = 1;
278     msg.msg_control = NULL;
279     
280     oldfs = get_fs();
281     set_fs(KERNEL_DS);
282     size = sock_recvmsg(sock, &msg, len, msg.msg_flags);
283         
284     set_fs(oldfs);
285     
286     return size;
287 }
288
289 /* send packets to VNET core */
290 static int 
291 send_to_palacios(unsigned char * buf, 
292                  int len,
293                  int link_id){
294     struct v3_vnet_pkt pkt;
295     pkt.size = len;
296     pkt.src_type = LINK_EDGE;
297     pkt.src_id = link_id;
298     memcpy(pkt.header, buf, ETHERNET_HEADER_LEN);
299     pkt.data = buf;
300
301     if(net_debug >= 2){
302         printk("VNET Lnx Bridge: send pkt to VNET core (size: %d, src_id: %d, src_type: %d)\n", 
303                         pkt.size,  pkt.src_id, pkt.src_type);
304         if(net_debug >= 4){
305             print_hex_dump(NULL, "pkt_data: ", 0, 20, 20, pkt.data, pkt.size, 0);
306         }
307     }
308
309     vnet_brg_s.stats.pkt_to_vmm ++;
310
311     return v3_vnet_send_pkt(&pkt, NULL);
312 }
313
314
315 /* send packet to extern network */
316 static int 
317 bridge_send_pkt(struct v3_vm_info * vm, 
318                 struct v3_vnet_pkt * pkt, 
319                 void * private_data) {
320     struct vnet_link * link;
321
322     if(net_debug >= 2){
323         printk("VNET Lnx Host Bridge: packet received from VNET Core ... pkt size: %d, link: %d\n",
324                         pkt->size,
325                         pkt->dst_id);
326         if(net_debug >= 4){
327             print_hex_dump(NULL, "pkt_data: ", 0, 20, 20, pkt->data, pkt->size, 0);
328         }
329     }
330
331     vnet_brg_s.stats.pkt_from_vmm ++;
332
333     link = _link_by_idx(pkt->dst_id);
334     if (link != NULL) {
335         switch(link->sock_proto){
336             case UDP:
337                 _udp_send(link->sock, &(link->sock_addr), pkt->data, pkt->size);
338                 vnet_brg_s.stats.pkt_to_phy ++;
339                 break;
340             case TCP:
341                 vnet_brg_s.stats.pkt_to_phy ++;
342                 break;  
343
344             default:
345                 printk("VNET Server: Invalid Link Protocol\n");
346                 vnet_brg_s.stats.pkt_drop_vmm ++;
347         }
348         link->stats.tx_bytes += pkt->size;
349         link->stats.tx_pkts ++;
350     } else {
351         printk("VNET Bridge Linux Host: wrong dst link, idx: %d, discards the packet\n", pkt->dst_id);
352         vnet_brg_s.stats.pkt_drop_vmm ++;
353     }
354
355     return 0;
356 }
357
358
359 static int init_vnet_serv(void) {
360     int protocol;
361     int err;
362
363     switch(vnet_brg_s.serv_proto){
364         case UDP:
365             protocol = IPPROTO_UDP;
366             break;
367         case TCP:
368             protocol = IPPROTO_TCP;
369             break;
370
371         default:
372            printk("Unsupported VNET Server Protocol\n");
373             return -1;
374     }
375          
376     if ((err = sock_create(AF_INET, SOCK_DGRAM, protocol, &vnet_brg_s.serv_sock)) < 0) {
377         printk("Could not create VNET server socket, error: %d\n", err);
378         return -1;
379     }
380
381     memset(&vnet_brg_s.serv_addr, 0, sizeof(struct sockaddr));
382
383     vnet_brg_s.serv_addr.sin_family = AF_INET;
384     vnet_brg_s.serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
385     vnet_brg_s.serv_addr.sin_port = htons(VNET_SERVER_PORT);
386
387     if ((err = vnet_brg_s.serv_sock->ops->bind(vnet_brg_s.serv_sock, (struct sockaddr *)&(vnet_brg_s.serv_addr), sizeof(struct sockaddr))) < 0) {
388         printk("Could not bind VNET server socket to port %d, error: %d\n", VNET_SERVER_PORT, err);
389         return -1;
390     }
391
392     printk("VNET server bind to port: %d\n", VNET_SERVER_PORT);
393
394     if(vnet_brg_s.serv_proto == TCP){
395         if((err = vnet_brg_s.serv_sock->ops->listen(vnet_brg_s.serv_sock, 32)) < 0){
396             printk("VNET Server error listening on port %d, error %d\n", VNET_SERVER_PORT, err);
397             return -1;
398         }
399     }
400
401     return 0;
402 }
403
404 static int _udp_server(void * arg) {
405     unsigned char * pkt;
406     struct sockaddr_in pkt_addr;
407     struct vnet_link * link = NULL;
408     int len;
409
410     printk("Palacios VNET Bridge: UDP receiving server ..... \n");
411
412     pkt = kmalloc(MAX_PACKET_LEN, GFP_KERNEL);
413     while (!kthread_should_stop()) {
414         
415         len = _udp_recv(vnet_brg_s.serv_sock, &pkt_addr, pkt, MAX_PACKET_LEN); 
416         if(len < 0) {
417             printk("Receive error: Could not get packet, error %d\n", len);
418             continue;
419         }
420
421         link = _link_by_ip(pkt_addr.sin_addr.s_addr);
422         if (link == NULL){
423             printk("VNET Server: No VNET Link match the src IP\n");
424             vnet_brg_s.stats.pkt_drop_phy ++;
425             continue;
426         }
427         
428         vnet_brg_s.stats.pkt_from_phy ++;
429         link->stats.rx_bytes += len;
430         link->stats.rx_pkts ++;
431
432         send_to_palacios(pkt, len, link->idx);
433     }
434
435     kfree(pkt);
436
437     return 0;
438 }
439
440
441 static int _rx_server(void * arg) {
442     
443     if(vnet_brg_s.serv_proto == UDP){
444         _udp_server(NULL);
445     }else if(vnet_brg_s.serv_proto == TCP) {
446         //accept new connection
447         //use select to receive pkt from physical network
448         //or create new kthread to handle each connection?
449     }else {
450         printk ("VNET Server: Unsupported Protocol\n");
451         return -1;
452     }
453
454     return 0;
455 }
456
457 static inline unsigned int hash_fn(addr_t hdr_ptr) {    
458     return vnet_hash_buffer((uint8_t *)hdr_ptr, sizeof(uint32_t));
459 }
460
461 static inline int hash_eq(addr_t key1, addr_t key2) {   
462     return (memcmp((uint8_t *)key1, (uint8_t *)key2, sizeof(uint32_t)) == 0);
463 }
464
465
466 int vnet_bridge_init(void) {
467     struct v3_vnet_bridge_ops bridge_ops;
468
469     if(vnet_brg_s.status != 0) {
470         return -1;
471     }   
472     vnet_brg_s.status = 1;      
473         
474     memset(&vnet_brg_s, 0, sizeof(struct vnet_brg_state));
475
476     INIT_LIST_HEAD(&(vnet_brg_s.link_list));
477     spin_lock_init(&(vnet_brg_s.lock));
478
479     vnet_brg_s.serv_proto = UDP;
480
481     vnet_brg_s.ip2link = vnet_create_htable(10, hash_fn, hash_eq);
482     if(vnet_brg_s.ip2link == NULL){
483         printk("Failure to initiate VNET link hashtable\n");
484         return -1;
485     }
486         
487     if(init_vnet_serv() < 0){
488         printk("Failure to initiate VNET server\n");
489         return -1;
490     }
491
492     vnet_brg_s.serv_thread = kthread_run(_rx_server, NULL, "vnet_brgd");
493
494     bridge_ops.input = bridge_send_pkt;
495     bridge_ops.poll = NULL;
496         
497     if( v3_vnet_add_bridge(NULL, &bridge_ops, HOST_LNX_BRIDGE, NULL) < 0){
498         printk("VNET LNX Bridge: Fails to register bridge to VNET core");
499     }
500
501     printk("VNET Linux Bridge initiated\n");
502
503     return 0;
504 }
505
506
507 void vnet_bridge_deinit(void){
508
509     v3_vnet_del_bridge(HOST_LNX_BRIDGE);
510
511     kthread_stop(vnet_brg_s.serv_thread);
512     vnet_brg_s.serv_sock->ops->release(vnet_brg_s.serv_sock);
513
514     deinit_links_list();
515
516     vnet_free_htable(vnet_brg_s.ip2link, 0, 0);
517
518     vnet_brg_s.status = 0;
519 }
520
521