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.


moved linux module to main Palacios tree
[palacios.git] / linux_module / palacios-packet.c
1 /* 
2  * VM Raw Packet 
3  * (c) Lei Xia, 2010
4  */
5 #include <asm/uaccess.h>
6 #include <linux/inet.h>
7 #include <linux/kthread.h>
8 #include <linux/netdevice.h>
9 #include <linux/ip.h>
10 #include <linux/in.h>
11 #include <linux/string.h>
12 #include <linux/preempt.h>
13 #include <linux/sched.h>
14 #include <linux/if_packet.h>
15 #include <linux/errno.h>
16 #include <asm/msr.h>
17  
18 #include <palacios/vmm_packet.h>
19 #include <palacios/vmm_host_events.h>
20 #include <palacios/vmm_vnet.h>
21
22 #include "palacios.h"
23 #include "palacios-packet.h"
24
25 //#define DEBUG_PALACIOS_PACKET
26
27 static struct socket * raw_sock;
28
29 static int packet_inited = 0;
30
31 static int init_raw_socket (const char * eth_dev){
32     int err;
33     struct sockaddr_ll sock_addr;
34     struct ifreq if_req;
35     int dev_idx;
36
37     err = sock_create(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL), &raw_sock); 
38     if (err < 0) {
39         printk(KERN_WARNING "Could not create a PF_PACKET Socket, err %d\n", err);
40         return -1;
41     }
42
43     if(eth_dev == NULL){
44         return 0;
45     }
46
47     memset(&if_req, 0, sizeof(if_req));
48     strncpy(if_req.ifr_name, eth_dev, sizeof(if_req.ifr_name));
49
50     err = raw_sock->ops->ioctl(raw_sock, SIOCGIFINDEX, (long)&if_req);
51     if(err < 0){
52         printk(KERN_WARNING "Palacios Packet: Unable to get index for device %s, error %d\n", if_req.ifr_name, err);
53         dev_idx = 2; /* default "eth0" */
54     }
55     else{
56         dev_idx = if_req.ifr_ifindex;
57     }
58
59     printk(KERN_INFO "Palacios Packet: bind to device index: %d\n", dev_idx);
60
61     memset(&sock_addr, 0, sizeof(sock_addr));
62     sock_addr.sll_family = PF_PACKET;
63     sock_addr.sll_protocol = htons(ETH_P_ALL);
64     sock_addr.sll_ifindex = dev_idx;
65
66     err = raw_sock->ops->bind(raw_sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr));
67     if (err < 0){
68         printk(KERN_WARNING "Error binding raw packet to device %s, %d\n", eth_dev, err);
69         return -1;
70     }
71
72     printk(KERN_INFO "Bind palacios raw packet interface to device %s\n", eth_dev);
73
74     return 0;
75 }
76
77
78 static int
79 palacios_packet_send(const char * pkt, unsigned int len, void * private_data) {
80     struct msghdr msg;
81     struct iovec iov;
82     mm_segment_t oldfs;
83     int size = 0;
84
85 #ifdef DEBUG_PALACIOS_PACKET
86     {
87         printk("Palacios Packet: send pkt to NIC (size: %d)\n", 
88                         len);
89         //print_hex_dump(NULL, "pkt_data: ", 0, 20, 20, pkt, len, 0);
90     }
91 #endif
92         
93
94     iov.iov_base = (void *)pkt;
95     iov.iov_len = (__kernel_size_t)len;
96
97     msg.msg_iov = &iov;
98     msg.msg_iovlen = 1;
99     msg.msg_control = NULL;
100     msg.msg_controllen = 0;
101     msg.msg_name = NULL;
102     msg.msg_namelen = 0;
103     msg.msg_flags = 0;
104
105     oldfs = get_fs();
106     set_fs(KERNEL_DS);
107     size = sock_sendmsg(raw_sock, &msg, len);
108     set_fs(oldfs);
109
110     return size;
111 }
112
113
114 static struct v3_packet_hooks palacios_packet_hooks = {
115     .send       = palacios_packet_send,
116 };
117
118
119 static int 
120 recv_pkt(char * pkt, int len) {
121     struct msghdr msg;
122     struct iovec iov;
123     mm_segment_t oldfs;
124     int size = 0;
125     
126     if (raw_sock == NULL) {
127         return -1;
128     }
129
130     iov.iov_base = pkt;
131     iov.iov_len = len;
132     
133     msg.msg_flags = 0;
134     msg.msg_name = NULL;
135     msg.msg_namelen = 0;
136     msg.msg_control = NULL;
137     msg.msg_controllen = 0;
138     msg.msg_iov = &iov;
139     msg.msg_iovlen = 1;
140     msg.msg_control = NULL;
141     
142     oldfs = get_fs();
143     set_fs(KERNEL_DS);
144     size = sock_recvmsg(raw_sock, &msg, len, msg.msg_flags);
145     set_fs(oldfs);
146     
147     return size;
148 }
149
150
151 void
152 send_raw_packet_to_palacios(char * pkt,
153                                int len,
154                                struct v3_vm_info * vm) {
155     struct v3_packet_event event;
156
157     event.pkt = kmalloc(len, GFP_KERNEL);
158     memcpy(event.pkt, pkt, len);
159     event.size = len;
160         
161     v3_deliver_packet_event(vm, &event);
162 }
163
164 static int packet_server(void * arg) {
165     char pkt[ETHERNET_PACKET_LEN];
166     int size;
167
168     printk("Palacios Raw Packet Bridge: Staring receiving server\n");
169
170     while (!kthread_should_stop()) {
171         size = recv_pkt(pkt, ETHERNET_PACKET_LEN);
172         if (size < 0) {
173             printk(KERN_WARNING "Palacios Packet Socket receive error\n");
174             break;
175         }
176
177 #ifdef DEBUG_PALACIOS_PACKET
178     {
179         printk("Palacios Packet: receive pkt from NIC (size: %d)\n", 
180                         size);
181         //print_hex_dump(NULL, "pkt_data: ", 0, 20, 20, pkt, size, 0);
182     }
183 #endif
184
185         send_raw_packet_to_palacios(pkt, size, NULL);
186     }
187
188     return 0;
189 }
190
191
192 int palacios_init_packet(const char * eth_dev) {
193
194     if(packet_inited == 0){
195         packet_inited = 1;
196         init_raw_socket(eth_dev);
197         V3_Init_Packet(&palacios_packet_hooks);
198
199         kthread_run(packet_server, NULL, "raw-packet-server");
200     }
201         
202     return 0;
203 }
204