5 #include <asm/uaccess.h>
6 #include <linux/inet.h>
7 #include <linux/kthread.h>
8 #include <linux/netdevice.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>
18 #include <palacios/vmm_packet.h>
19 #include <palacios/vmm_host_events.h>
20 #include <palacios/vmm_vnet.h>
21 #include <palacios/vmm_ethernet.h>
24 #include "palacios-packet.h"
25 #include "palacios-hashtable.h"
28 struct palacios_packet_state {
29 struct socket * raw_sock;
32 struct hashtable * mac_vm_cache;
33 struct task_struct * server_thread;
36 static struct palacios_packet_state packet_state;
38 static inline uint_t hash_fn(addr_t hdr_ptr) {
39 uint8_t * hdr_buf = (uint8_t *)hdr_ptr;
41 return palacios_hash_buffer(hdr_buf, ETH_ALEN);
44 static inline int hash_eq(addr_t key1, addr_t key2) {
45 return (memcmp((uint8_t *)key1, (uint8_t *)key2, ETH_ALEN) == 0);
49 static int palacios_packet_add_recver(const char * mac,
50 struct v3_vm_info * vm){
53 key = (char *)kmalloc(ETH_ALEN, GFP_KERNEL);
54 memcpy(key, mac, ETH_ALEN);
56 if (palacios_htable_insert(packet_state.mac_vm_cache, (addr_t)key, (addr_t)vm) == 0) {
57 printk("Palacios Packet: Failed to insert new mac entry to the hash table\n");
61 printk("Packet: Add MAC: %2x:%2x:%2x:%2x:%2x:%2x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
66 static int palacios_packet_del_recver(const char * mac,
67 struct v3_vm_info * vm){
72 static int init_raw_socket (const char * eth_dev){
74 struct sockaddr_ll sock_addr;
78 err = sock_create(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL), &(packet_state.raw_sock));
80 printk(KERN_WARNING "Could not create a PF_PACKET Socket, err %d\n", err);
85 eth_dev = "eth0"; /* default "eth0" */
88 memset(&if_req, 0, sizeof(if_req));
89 strncpy(if_req.ifr_name, eth_dev, IFNAMSIZ); //sizeof(if_req.ifr_name));
90 err = packet_state.raw_sock->ops->ioctl(packet_state.raw_sock, SIOCGIFINDEX, (long)&if_req);
92 printk(KERN_WARNING "Palacios Packet: Unable to get index for device %s, error %d\n", if_req.ifr_name, err);
93 dev_idx = 2; /* match ALL 2:"eth0" */
96 dev_idx = if_req.ifr_ifindex;
99 printk(KERN_INFO "Palacios Packet: bind to device index: %d\n", dev_idx);
101 memset(&sock_addr, 0, sizeof(sock_addr));
102 sock_addr.sll_family = PF_PACKET;
103 sock_addr.sll_protocol = htons(ETH_P_ALL);
104 sock_addr.sll_ifindex = dev_idx;
106 err = packet_state.raw_sock->ops->bind(packet_state.raw_sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr));
108 printk(KERN_WARNING "Error binding raw packet to device %s, %d\n", eth_dev, err);
112 printk(KERN_INFO "Bind palacios raw packet interface to device %s\n", eth_dev);
119 palacios_packet_send(const char * pkt, unsigned int len, void * private_data) {
125 iov.iov_base = (void *)pkt;
126 iov.iov_len = (__kernel_size_t)len;
130 msg.msg_control = NULL;
131 msg.msg_controllen = 0;
138 size = sock_sendmsg(packet_state.raw_sock, &msg, len);
143 printk("Palacios Packet: send pkt to NIC (size: %d)\n",
145 print_hex_dump(NULL, "pkt_header: ", 0, 20, 20, pkt, 20, 0);
146 printk("palacios_packet_send return: %d\n", size);
154 static struct v3_packet_hooks palacios_packet_hooks = {
155 .send = palacios_packet_send,
156 .add_recver = palacios_packet_add_recver,
157 .del_recver = palacios_packet_del_recver,
162 recv_pkt(char * pkt, int len) {
168 if (packet_state.raw_sock == NULL) {
178 msg.msg_control = NULL;
179 msg.msg_controllen = 0;
182 msg.msg_control = NULL;
186 size = sock_recvmsg(packet_state.raw_sock, &msg, len, msg.msg_flags);
194 send_raw_packet_to_palacios(char * pkt,
196 struct v3_vm_info * vm) {
197 struct v3_packet_event event;
198 char data[ETHERNET_PACKET_LEN];
200 /* one memory copy */
201 memcpy(data, pkt, len);
205 v3_deliver_packet_event(vm, &event);
208 static int packet_server(void * arg) {
209 char pkt[ETHERNET_PACKET_LEN];
211 struct v3_vm_info *vm;
213 printk("Palacios Raw Packet Bridge: Staring receiving server\n");
215 while (!kthread_should_stop()) {
216 size = recv_pkt(pkt, ETHERNET_PACKET_LEN);
218 printk(KERN_WARNING "Palacios raw packet receive error, Server terminated\n");
224 printk("Palacios Packet: receive pkt from NIC (size: %d)\n",
226 print_hex_dump(NULL, "pkt_header: ", 0, 10, 10, pkt, 20, 0);
230 /* if VNET is enabled, send to VNET */
234 /* if it is broadcast or multicase packet */
238 vm = (struct v3_vm_info *)palacios_htable_search(packet_state.mac_vm_cache, (addr_t)pkt);
240 printk("Find destinated VM 0x%p\n", vm);
241 send_raw_packet_to_palacios(pkt, size, vm);
249 int palacios_init_packet(const char * eth_dev) {
251 if(packet_state.inited == 0){
252 packet_state.inited = 1;
254 if(init_raw_socket(eth_dev) == -1){
255 printk("Error to initiate palacios packet interface\n");
259 V3_Init_Packet(&palacios_packet_hooks);
261 packet_state.mac_vm_cache = palacios_create_htable(0, &hash_fn, &hash_eq);
263 packet_state.server_thread = kthread_run(packet_server, NULL, "raw-packet-server");
269 void palacios_deinit_packet(const char * eth_dev) {
271 kthread_stop(packet_state.server_thread);
272 packet_state.raw_sock->ops->release(packet_state.raw_sock);
273 palacios_free_htable(packet_state.mac_vm_cache, 0, 1);
274 packet_state.inited = 0;