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.


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