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