2 * Palacios Raw Packet Interface Implementation
6 #include <asm/uaccess.h>
7 #include <linux/inet.h>
8 #include <linux/kthread.h>
9 #include <linux/netdevice.h>
12 #include <linux/string.h>
13 #include <linux/preempt.h>
14 #include <linux/sched.h>
15 #include <linux/if_packet.h>
16 #include <linux/errno.h>
19 #include <interfaces/vmm_packet.h>
20 #include <palacios/vmm_ethernet.h>
23 #include "util-hashtable.h"
24 #include "linux-exts.h"
28 /* there is one for each host nic */
29 struct raw_interface {
30 char eth_dev[126]; /* host nic name "eth0" ... */
32 struct socket * raw_sock;
35 struct list_head brdcast_recvers;
36 struct hashtable * mac_to_recver;
38 struct task_struct * recv_thread;
40 struct list_head node;
43 struct palacios_packet_state{
46 struct list_head open_interfaces;
49 struct palacios_packet_state packet_state;
51 static inline uint_t hash_fn(addr_t hdr_ptr) {
52 uint8_t * hdr_buf = (uint8_t *)hdr_ptr;
54 return palacios_hash_buffer(hdr_buf, ETH_ALEN);
57 static inline int hash_eq(addr_t key1, addr_t key2) {
58 return (memcmp((uint8_t *)key1, (uint8_t *)key2, ETH_ALEN) == 0);
63 recv_pkt(struct socket * raw_sock, unsigned char * pkt, unsigned int len) {
67 unsigned int size = 0;
69 if (raw_sock == NULL) {
79 msg.msg_control = NULL;
80 msg.msg_controllen = 0;
83 msg.msg_control = NULL;
87 size = sock_recvmsg(raw_sock, &msg, len, msg.msg_flags);
95 init_socket(struct raw_interface * iface, const char * eth_dev){
97 struct sockaddr_ll sock_addr;
98 struct net_device * net_dev;
100 err = sock_create(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL), &(iface->raw_sock));
102 printk(KERN_WARNING "Could not create a PF_PACKET Socket, err %d\n", err);
106 net_dev = dev_get_by_name(&init_net, eth_dev);
107 if(net_dev == NULL) {
108 printk(KERN_WARNING "Palacios Packet: Unable to get index for device %s\n", eth_dev);
109 sock_release(iface->raw_sock);
113 memset(&sock_addr, 0, sizeof(sock_addr));
114 sock_addr.sll_family = PF_PACKET;
115 sock_addr.sll_protocol = htons(ETH_P_ALL);
116 sock_addr.sll_ifindex = net_dev->ifindex;
118 err = iface->raw_sock->ops->bind(iface->raw_sock,
119 (struct sockaddr *)&sock_addr,
123 printk(KERN_WARNING "Error binding raw packet to device %s, %d\n", eth_dev, err);
124 sock_release(iface->raw_sock);
129 printk(KERN_INFO "Bind a palacios raw packet interface to device %s, device index %d\n",
130 eth_dev, net_dev->ifindex);
137 is_multicast_ethaddr(const unsigned char * addr)
139 return (0x01 & addr[0]);
143 is_broadcast_ethaddr(const unsigned char * addr)
145 unsigned char ret = 0xff;
148 for(i=0; i<ETH_ALEN; i++) {
152 return (ret == 0xff);
155 static int packet_recv_thread( void * arg ) {
158 struct v3_packet * recver_state;
159 struct raw_interface * iface = (struct raw_interface *)arg;
161 pkt = (unsigned char *)kmalloc(ETHERNET_PACKET_LEN, GFP_KERNEL);
163 printk("Palacios Raw Packet Bridge: Staring receiving on ethernet device %s\n",
166 while (!kthread_should_stop()) {
167 size = recv_pkt(iface->raw_sock, pkt, ETHERNET_PACKET_LEN);
170 printk(KERN_WARNING "Palacios raw packet receive error, Server terminated\n");
174 if(is_broadcast_ethaddr(pkt)) {
177 list_for_each_entry(recver_state, &(iface->brdcast_recvers), node) {
178 recver_state->input(recver_state, pkt, size);
181 } else if(is_multicast_ethaddr(pkt)) {
185 recver_state = (struct v3_packet *)palacios_htable_search(iface->mac_to_recver,
187 if(recver_state != NULL) {
188 recver_state->input(recver_state, pkt, size);
198 init_raw_interface(struct raw_interface * iface, const char * eth_dev){
200 memcpy(iface->eth_dev, eth_dev, V3_ETHINT_NAMELEN);
201 if(init_socket(iface, eth_dev) !=0) {
202 printk("packet: fails to initiate raw socket\n");
207 INIT_LIST_HEAD(&(iface->brdcast_recvers));
208 iface->mac_to_recver = palacios_create_htable(0, &hash_fn, &hash_eq);
209 iface->recv_thread = kthread_run(packet_recv_thread, (void *)iface, "bridge-recver");
217 deinit_raw_interface(struct raw_interface * iface){
218 struct v3_packet * recver_state;
220 kthread_stop(iface->recv_thread);
221 sock_release(iface->raw_sock);
222 palacios_free_htable(iface->mac_to_recver, 0, 0);
224 list_for_each_entry(recver_state, &(iface->brdcast_recvers), node) {
230 static inline struct raw_interface *
231 find_interface(const char * eth_dev) {
232 struct raw_interface * iface;
234 list_for_each_entry(iface, &(packet_state.open_interfaces), node) {
235 if (strncmp(iface->eth_dev, eth_dev, V3_ETHINT_NAMELEN) == 0) {
245 palacios_packet_connect(struct v3_packet * packet,
246 const char * host_nic,
247 void * host_vm_data) {
248 struct raw_interface * iface;
251 spin_lock_irqsave(&(packet_state.lock), flags);
253 iface = find_interface(host_nic);
255 iface = (struct raw_interface *)kmalloc(sizeof(struct raw_interface), GFP_ATOMIC);
257 printk("Palacios Packet Interface: Fails to allocate interface\n");
260 if(init_raw_interface(iface, host_nic) != 0) {
261 printk("Palacios Packet Interface: Fails to initiate an raw interface on device %s\n", host_nic);
263 spin_unlock_irqrestore(&(packet_state.lock), flags);
268 list_add(&(iface->node), &(packet_state.open_interfaces));
271 spin_unlock_irqrestore(&(packet_state.lock), flags);
273 packet->host_packet_data = iface;
275 list_add(&(packet->node), &(iface->brdcast_recvers));
276 palacios_htable_insert(iface->mac_to_recver,
277 (addr_t)packet->dev_mac,
280 printk(KERN_INFO "Packet: Add Receiver MAC to ethernet device %s: %2x:%2x:%2x:%2x:%2x:%2x\n",
282 packet->dev_mac[0], packet->dev_mac[1],
283 packet->dev_mac[2], packet->dev_mac[3],
284 packet->dev_mac[4], packet->dev_mac[5]);
290 palacios_packet_send(struct v3_packet * packet,
293 struct raw_interface * iface = (struct raw_interface *)packet->host_packet_data;
299 if(iface->inited == 0 ||
300 iface->raw_sock == NULL){
301 printk("Palacios Packet Interface: Send fails due to inapproriate interface\n");
306 iov.iov_base = (void *)pkt;
307 iov.iov_len = (__kernel_size_t)len;
311 msg.msg_control = NULL;
312 msg.msg_controllen = 0;
319 size = sock_sendmsg(iface->raw_sock, &msg, len);
327 palacios_packet_close(struct v3_packet * packet) {
328 struct raw_interface * iface = (struct raw_interface *)packet->host_packet_data;
330 list_del(&(packet->node));
331 palacios_htable_remove(iface->mac_to_recver, (addr_t)(packet->dev_mac), 0);
333 packet->host_packet_data = NULL;
337 static struct v3_packet_hooks palacios_packet_hooks = {
338 .connect = palacios_packet_connect,
339 .send = palacios_packet_send,
340 .close = palacios_packet_close,
343 static int packet_init( void ) {
344 V3_Init_Packet(&palacios_packet_hooks);
346 memset(&packet_state, 0, sizeof(struct palacios_packet_state));
347 spin_lock_init(&(packet_state.lock));
348 INIT_LIST_HEAD(&(packet_state.open_interfaces));
350 // REGISTER GLOBAL CONTROL to add interfaces...
355 static int packet_deinit( void ) {
356 struct raw_interface * iface;
358 list_for_each_entry(iface, &(packet_state.open_interfaces), node) {
359 deinit_raw_interface(iface);
366 static struct linux_ext pkt_ext = {
367 .name = "PACKET_INTERFACE",
369 .deinit = packet_deinit,
375 register_extension(&pkt_ext);