From: Lei Xia Date: Tue, 1 Nov 2011 02:49:52 +0000 (-0500) Subject: Restructure of direct host network bridge. X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=9a32111c4074aafd55cd9590a24bd5c751a6fe61 Restructure of direct host network bridge. Now each VM's virtual NIC can be bridged to different host NIC, which can be configured in guest's XML file. Remove host events for packet injecting, instead using call back function provided by palacios to inject packets --- diff --git a/linux_module/iface-packet.c b/linux_module/iface-packet.c index b067987..c03d628 100644 --- a/linux_module/iface-packet.c +++ b/linux_module/iface-packet.c @@ -17,32 +17,41 @@ #include #include -#include -#include - - -#define __V3VEE__ -#include #include -#undef __V3VEE__ #include "palacios.h" +#include "util-hashtable.h" #include "linux-exts.h" +#include "vm.h" + -struct palacios_packet_state { +/* there is one for each host nic */ +struct raw_interface { + char eth_dev[126]; /* host nic name "eth0" ... */ + struct socket * raw_sock; uint8_t inited; - - struct hashtable * mac_vm_cache; - struct task_struct * server_thread; + + struct list_head brdcast_recvers; + struct hashtable * mac_to_recver; + + struct task_struct * recv_thread; + + struct list_head node; +}; + +struct palacios_packet_state{ + spinlock_t lock; + + struct list_head open_interfaces; }; -static struct palacios_packet_state packet_state; +struct palacios_packet_state packet_state; static inline uint_t hash_fn(addr_t hdr_ptr) { uint8_t * hdr_buf = (uint8_t *)hdr_ptr; - return v3_hash_buffer(hdr_buf, ETH_ALEN); + return palacios_hash_buffer(hdr_buf, ETH_ALEN); } static inline int hash_eq(addr_t key1, addr_t key2) { @@ -50,237 +59,311 @@ static inline int hash_eq(addr_t key1, addr_t key2) { } -static int palacios_packet_add_recver(const char * mac, - struct v3_vm_info * vm){ - char * key; - - key = (char *)kmalloc(ETH_ALEN, GFP_KERNEL); - memcpy(key, mac, ETH_ALEN); - - if (v3_htable_insert(packet_state.mac_vm_cache, (addr_t)key, (addr_t)vm) == 0) { - printk("Palacios Packet: Failed to insert new mac entry to the hash table\n"); +static int +recv_pkt(struct socket * raw_sock, unsigned char * pkt, unsigned int len) { + struct msghdr msg; + struct iovec iov; + mm_segment_t oldfs; + unsigned int size = 0; + + if (raw_sock == NULL) { return -1; } - printk("Packet: Add MAC: %2x:%2x:%2x:%2x:%2x:%2x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + iov.iov_base = pkt; + iov.iov_len = len; - return 0; + msg.msg_flags = 0; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + + oldfs = get_fs(); + set_fs(KERNEL_DS); + size = sock_recvmsg(raw_sock, &msg, len, msg.msg_flags); + set_fs(oldfs); + + return size; } -static int palacios_packet_del_recver(const char * mac, - struct v3_vm_info * vm){ - return 0; -} - -static int init_raw_socket(const char * eth_dev){ +static int +init_socket(struct raw_interface * iface, const char * eth_dev){ int err; struct sockaddr_ll sock_addr; struct ifreq if_req; - int dev_idx; - - err = sock_create(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL), &(packet_state.raw_sock)); + err = sock_create(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL), &(iface->raw_sock)); if (err < 0) { printk(KERN_WARNING "Could not create a PF_PACKET Socket, err %d\n", err); return -1; } - if (eth_dev == NULL){ - eth_dev = "eth0"; /* default "eth0" */ - } - memset(&if_req, 0, sizeof(if_req)); - strncpy(if_req.ifr_name, eth_dev, IFNAMSIZ); //sizeof(if_req.ifr_name)); - - err = packet_state.raw_sock->ops->ioctl(packet_state.raw_sock, SIOCGIFINDEX, (long)&if_req); + strncpy(if_req.ifr_name, eth_dev, sizeof(if_req.ifr_name)); + err = iface->raw_sock->ops->ioctl(iface->raw_sock, SIOCGIFINDEX, (long)&if_req); if (err < 0){ printk(KERN_WARNING "Palacios Packet: Unable to get index for device %s, error %d\n", if_req.ifr_name, err); - dev_idx = 2; /* match ALL 2:"eth0" */ - } else { - dev_idx = if_req.ifr_ifindex; - } - printk(KERN_INFO "Palacios Packet: bind to device index: %d\n", dev_idx); + sock_release(iface->raw_sock); + return -1; + } memset(&sock_addr, 0, sizeof(sock_addr)); sock_addr.sll_family = PF_PACKET; sock_addr.sll_protocol = htons(ETH_P_ALL); - sock_addr.sll_ifindex = dev_idx; + sock_addr.sll_ifindex = if_req.ifr_ifindex; - err = packet_state.raw_sock->ops->bind(packet_state.raw_sock, - (struct sockaddr *)&sock_addr, - sizeof(sock_addr)); + err = iface->raw_sock->ops->bind(iface->raw_sock, + (struct sockaddr *)&sock_addr, + sizeof(sock_addr)); if (err < 0){ printk(KERN_WARNING "Error binding raw packet to device %s, %d\n", eth_dev, err); + sock_release(iface->raw_sock); + return -1; } - printk(KERN_INFO "Bind palacios raw packet interface to device %s\n", eth_dev); + printk(KERN_INFO "Bind a palacios raw packet interface to device %s, device index %d\n", + if_req.ifr_name, if_req.ifr_ifindex); return 0; } -static int -palacios_packet_send(const char * pkt, unsigned int len, void * private_data) { - struct msghdr msg; - struct iovec iov; - mm_segment_t oldfs; - int size = 0; - - iov.iov_base = (void *)pkt; - iov.iov_len = (__kernel_size_t)len; +static inline int +is_multicast_ethaddr(const unsigned char * addr) +{ + return (0x01 & addr[0]); +} - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_flags = 0; +static inline int +is_broadcast_ethaddr(const unsigned char * addr) +{ + unsigned char ret = 0xff; + int i; + + for(i=0; ieth_dev); + while (!kthread_should_stop()) { + size = recv_pkt(iface->raw_sock, pkt, ETHERNET_PACKET_LEN); + + if (size < 0) { + printk(KERN_WARNING "Palacios raw packet receive error, Server terminated\n"); + break; + } -static struct v3_packet_hooks palacios_packet_hooks = { - .send = palacios_packet_send, - .add_recver = palacios_packet_add_recver, - .del_recver = palacios_packet_del_recver, -}; + if(is_broadcast_ethaddr(pkt)) { + /* Broadcast */ + + list_for_each_entry(recver_state, &(iface->brdcast_recvers), node) { + recver_state->input(recver_state, pkt, size); + } + + } else if(is_multicast_ethaddr(pkt)) { + /* MultiCast */ + + } else { + recver_state = (struct v3_packet *)palacios_htable_search(iface->mac_to_recver, + (addr_t)pkt); + if(recver_state != NULL) { + recver_state->input(recver_state, pkt, size); + } + } + } + + return 0; +} static int -recv_pkt(char * pkt, int len) { - struct msghdr msg; - struct iovec iov; - mm_segment_t oldfs; - int size = 0; - - if (packet_state.raw_sock == NULL) { +init_raw_interface(struct raw_interface * iface, const char * eth_dev){ + + memcpy(iface->eth_dev, eth_dev, V3_ETHINT_NAMELEN); + if(init_socket(iface, eth_dev) !=0) { + printk("packet: fails to initiate raw socket\n"); return -1; } - - iov.iov_base = pkt; - iov.iov_len = len; - msg.msg_flags = 0; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - oldfs = get_fs(); - set_fs(KERNEL_DS); - size = sock_recvmsg(packet_state.raw_sock, &msg, len, msg.msg_flags); - set_fs(oldfs); + INIT_LIST_HEAD(&(iface->brdcast_recvers)); + iface->mac_to_recver = palacios_create_htable(0, &hash_fn, &hash_eq); + iface->recv_thread = kthread_run(packet_recv_thread, (void *)iface, "bridge-recver"); - return size; + iface->inited = 1; + + return 0; } +static void inline +deinit_raw_interface(struct raw_interface * iface){ + struct v3_packet * recver_state; -static void -send_raw_packet_to_palacios(char * pkt, - int len, - struct v3_vm_info * vm) { - struct v3_packet_event event; - char data[ETHERNET_PACKET_LEN]; - - /* one memory copy */ - memcpy(data, pkt, len); - event.pkt = data; - event.size = len; - - v3_deliver_packet_event(vm, &event); + kthread_stop(iface->recv_thread); + sock_release(iface->raw_sock); + palacios_free_htable(iface->mac_to_recver, 0, 0); + + list_for_each_entry(recver_state, &(iface->brdcast_recvers), node) { + kfree(recver_state); + } } -static int packet_server(void * arg) { - char pkt[ETHERNET_PACKET_LEN]; - int size; - struct v3_vm_info *vm; - - printk("Palacios Raw Packet Bridge: Staring receiving server\n"); - - while (!kthread_should_stop()) { - size = recv_pkt(pkt, ETHERNET_PACKET_LEN); - if (size < 0) { - printk(KERN_WARNING "Palacios raw packet receive error, Server terminated\n"); - break; +static inline struct raw_interface * +find_interface(const char * eth_dev) { + struct raw_interface * iface; + + list_for_each_entry(iface, &(packet_state.open_interfaces), node) { + if (strncmp(iface->eth_dev, eth_dev, V3_ETHINT_NAMELEN) == 0) { + return iface; } + } + return NULL; +} - /* if VNET is enabled, send to VNET */ - // ... - - - /* if it is broadcast or multicase packet */ - // ... - - - vm = (struct v3_vm_info *)v3_htable_search(packet_state.mac_vm_cache, (addr_t)pkt); - if (vm != NULL){ - printk("Find destinated VM 0x%p\n", vm); - send_raw_packet_to_palacios(pkt, size, vm); +static int +palacios_packet_connect(struct v3_packet * packet, + const char * host_nic, + void * host_vm_data) { + struct raw_interface * iface; + unsigned long flags; + + spin_lock_irqsave(&(packet_state.lock), flags); + + iface = find_interface(host_nic); + if(iface == NULL){ + iface = (struct raw_interface *)kmalloc(sizeof(struct raw_interface), GFP_KERNEL); + if(init_raw_interface(iface, host_nic) != 0) { + printk("Palacios Packet Interface: Fails to initiate an raw interface on device %s\n", host_nic); + kfree(iface); + spin_unlock_irqrestore(&(packet_state.lock), flags); + + return -1; } + + list_add(&(iface->node), &(packet_state.open_interfaces)); } - + + spin_unlock_irqrestore(&(packet_state.lock), flags); + + packet->host_packet_data = iface; + + list_add(&(packet->node), &(iface->brdcast_recvers)); + palacios_htable_insert(iface->mac_to_recver, + (addr_t)packet->dev_mac, + (addr_t)packet); + + printk(KERN_INFO "Packet: Add Receiver MAC to ethernet device %s: %2x:%2x:%2x:%2x:%2x:%2x\n", + iface->eth_dev, + packet->dev_mac[0], packet->dev_mac[1], + packet->dev_mac[2], packet->dev_mac[3], + packet->dev_mac[4], packet->dev_mac[5]); + return 0; } +static int +palacios_packet_send(struct v3_packet * packet, + unsigned char * pkt, + unsigned int len) { + struct raw_interface * iface = (struct raw_interface *)packet->host_packet_data; + struct msghdr msg; + struct iovec iov; + mm_segment_t oldfs; + int size = 0; + + if(iface->inited == 0 || + iface->raw_sock == NULL){ + printk("Palacios Packet Interface: Send fails due to inapproriate interface\n"); + + return -1; + } + + iov.iov_base = (void *)pkt; + iov.iov_len = (__kernel_size_t)len; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_flags = 0; -static int packet_init( void ) { + oldfs = get_fs(); + set_fs(KERNEL_DS); + size = sock_sendmsg(iface->raw_sock, &msg, len); + set_fs(oldfs); - const char * eth_dev = NULL; + return size; +} - if (packet_state.inited == 0){ - packet_state.inited = 1; - if (init_raw_socket(eth_dev) == -1){ - printk("Error to initiate palacios packet interface\n"); - return -1; - } - - V3_Init_Packet(&palacios_packet_hooks); +static void +palacios_packet_close(struct v3_packet * packet) { + struct raw_interface * iface = (struct raw_interface *)packet->host_packet_data; + + list_del(&(packet->node)); + palacios_htable_remove(iface->mac_to_recver, (addr_t)(packet->dev_mac), 0); + + packet->host_packet_data = NULL; +} - packet_state.mac_vm_cache = v3_create_htable(0, &hash_fn, &hash_eq); - packet_state.server_thread = kthread_run(packet_server, NULL, "raw-packet-server"); - } - +static struct v3_packet_hooks palacios_packet_hooks = { + .connect = palacios_packet_connect, + .send = palacios_packet_send, + .close = palacios_packet_close, +}; +static int packet_init( void ) { + V3_Init_Packet(&palacios_packet_hooks); + + memset(&packet_state, 0, sizeof(struct palacios_packet_state)); + spin_lock_init(&(packet_state.lock)); + INIT_LIST_HEAD(&(packet_state.open_interfaces)); + // REGISTER GLOBAL CONTROL to add interfaces... return 0; } static int packet_deinit( void ) { - - - kthread_stop(packet_state.server_thread); - packet_state.raw_sock->ops->release(packet_state.raw_sock); - v3_free_htable(packet_state.mac_vm_cache, 0, 1); - packet_state.inited = 0; - + struct raw_interface * iface; + + list_for_each_entry(iface, &(packet_state.open_interfaces), node) { + deinit_raw_interface(iface); + kfree(iface); + } + return 0; } - - static struct linux_ext pkt_ext = { .name = "PACKET_INTERFACE", .init = packet_init, diff --git a/palacios/include/interfaces/vmm_packet.h b/palacios/include/interfaces/vmm_packet.h index a4ba3e5..812cc11 100644 --- a/palacios/include/interfaces/vmm_packet.h +++ b/palacios/include/interfaces/vmm_packet.h @@ -24,19 +24,35 @@ #include #include +#define V3_ETHINT_NAMELEN 126 + +struct v3_packet { + void * host_packet_data; + void * guest_packet_data; + + char dev_mac[ETH_ALEN]; + int (*input)(struct v3_packet * packet, uint8_t * buf, uint32_t len); + + struct list_head node; +}; + #ifdef __V3VEE__ +#include -int V3_send_raw(const char * pkt, uint32_t len); -int V3_packet_add_recver(const char * mac, struct v3_vm_info * vm); -int V3_packet_del_recver(const char * mac, struct v3_vm_info * vm); +struct v3_packet * v3_packet_connect(struct v3_vm_info * vm, const char * host_nic, + const char * mac, + int (*input)(struct v3_packet * packet, uint8_t * buf, uint32_t len), + void * guest_packet_data); + +int v3_packet_send(struct v3_packet * packet, uint8_t * buf, uint32_t len); +void v3_packet_close(struct v3_packet * packet); #endif struct v3_packet_hooks { - - int (*send)(const char * pkt, unsigned int size, void * private_data); - int (*add_recver)(const char * mac, struct v3_vm_info * vm); - int (*del_recver)(const char * mac, struct v3_vm_info * vm); + int (*connect)(struct v3_packet * packet, const char * host_nic, void * host_vm_data); + int (*send)(struct v3_packet * packet, uint8_t * buf, uint32_t len); + void (*close)(struct v3_packet * packet); }; extern void V3_Init_Packet(struct v3_packet_hooks * hooks); diff --git a/palacios/include/palacios/vmm_host_events.h b/palacios/include/palacios/vmm_host_events.h index 15bcb7d..47c6715 100644 --- a/palacios/include/palacios/vmm_host_events.h +++ b/palacios/include/palacios/vmm_host_events.h @@ -58,8 +58,7 @@ typedef enum { HOST_KEYBOARD_EVT, HOST_MOUSE_EVT, HOST_TIMER_EVT, HOST_CONSOLE_EVT, - HOST_SERIAL_EVT, - HOST_PACKET_EVT} v3_host_evt_type_t; + HOST_SERIAL_EVT} v3_host_evt_type_t; union v3_host_event_handler { @@ -68,7 +67,6 @@ union v3_host_event_handler { int (*timer_handler)(struct v3_vm_info * vm, struct v3_timer_event * evt, void * priv_data); int (*serial_handler)(struct v3_vm_info * vm, struct v3_serial_event * evt, void * priv_data); int (*console_handler)(struct v3_vm_info * vm, struct v3_console_event * evt, void * priv_data); - int (*packet_handler)(struct v3_vm_info * vm, struct v3_packet_event * evt, void * priv_data); }; @@ -86,7 +84,6 @@ struct v3_host_events { struct list_head timer_events; struct list_head serial_events; struct list_head console_events; - struct list_head packet_events; }; @@ -110,7 +107,6 @@ int v3_deliver_mouse_event(struct v3_vm_info * vm, struct v3_mouse_event * evt); int v3_deliver_timer_event(struct v3_vm_info * vm, struct v3_timer_event * evt); int v3_deliver_serial_event(struct v3_vm_info * vm, struct v3_serial_event * evt); int v3_deliver_console_event(struct v3_vm_info * vm, struct v3_console_event * evt); -int v3_deliver_packet_event(struct v3_vm_info * vm, struct v3_packet_event * evt); #endif diff --git a/palacios/src/devices/lnx_virtio_nic.c b/palacios/src/devices/lnx_virtio_nic.c index 8032b13..400cb0c 100644 --- a/palacios/src/devices/lnx_virtio_nic.c +++ b/palacios/src/devices/lnx_virtio_nic.c @@ -199,7 +199,7 @@ static int tx_one_pkt(struct guest_info * core, PrintDebug("Could not translate buffer address\n"); return -1; } - + V3_Net_Print(2, "Virtio-NIC: virtio_tx: size: %d\n", len); if(net_debug >= 4){ v3_hexdump(buf, len, NULL, 0); @@ -209,10 +209,10 @@ static int tx_one_pkt(struct guest_info * core, virtio->stats.tx_dropped ++; return -1; } - + virtio->stats.tx_pkts ++; virtio->stats.tx_bytes += len; - + return 0; } @@ -226,7 +226,7 @@ static inline int copy_data_to_desc(struct guest_info * core, uint_t dst_offset){ uint32_t len; uint8_t * desc_buf = NULL; - + if (v3_gpa_to_hva(core, desc->addr_gpa, (addr_t *)&(desc_buf)) == -1) { PrintDebug("Could not translate buffer address\n"); return -1; @@ -301,17 +301,19 @@ static int handle_pkt_tx(struct guest_info * core, /* here we assumed that one ethernet pkt is not splitted into multiple buffer */ struct vring_desc * buf_desc = &(q->desc[desc_idx]); if (tx_one_pkt(core, virtio_state, buf_desc) == -1) { - PrintError("Virtio NIC: Error handling nic operation\n"); - goto exit_error; + PrintError("Virtio NIC: Fails to send packet\n"); } if(buf_desc->next & VIRTIO_NEXT_FLAG){ PrintError("Virtio NIC: TX more buffer need to read\n"); } - - q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size]; - q->used->ring[q->used->index % q->queue_size].length = buf_desc->length; /* What do we set this to???? */ - q->used->index ++; + q->used->ring[q->used->index % q->queue_size].id = + q->avail->ring[q->cur_avail_idx % q->queue_size]; + + q->used->ring[q->used->index % q->queue_size].length = + buf_desc->length; /* What do we set this to???? */ + + q->used->index ++; q->cur_avail_idx ++; if(++txed >= quote && quote > 0){ @@ -319,9 +321,9 @@ static int handle_pkt_tx(struct guest_info * core, break; } } - + v3_unlock_irqrestore(virtio_state->tx_lock, flags); - + if (txed && !(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) { v3_pci_raise_irq(virtio_state->virtio_dev->pci_bus, 0, virtio_state->pci_dev); @@ -334,9 +336,9 @@ static int handle_pkt_tx(struct guest_info * core, } return left; - -exit_error: - + + exit_error: + v3_unlock_irqrestore(virtio_state->tx_lock, flags); return -1; } diff --git a/palacios/src/devices/nic_bridge.c b/palacios/src/devices/nic_bridge.c index 518fa75..1033b52 100644 --- a/palacios/src/devices/nic_bridge.c +++ b/palacios/src/devices/nic_bridge.c @@ -33,44 +33,43 @@ struct nic_bridge_state { struct v3_vm_info * vm; struct v3_dev_net_ops net_ops; + struct v3_packet * packet_state; }; static int bridge_send(uint8_t * buf, uint32_t len, - int synchronize, void * private_data) { - + struct nic_bridge_state * bridge = (struct nic_bridge_state *)private_data; + #ifdef V3_CONFIG_DEBUG_NIC_BRIDGE { PrintDebug("NIC Bridge: send pkt size: %d\n", len); v3_hexdump(buf, len, NULL, 0); } #endif - - return V3_send_raw(buf, len); + + return v3_packet_send(bridge->packet_state, buf, len); } -static int packet_input(struct v3_vm_info * vm, - struct v3_packet_event * evt, - void * private_data) { - struct nic_bridge_state * bridge = (struct nic_bridge_state *)private_data; - +static int packet_input(struct v3_packet * packet_state, uint8_t * pkt, uint32_t size) { + struct nic_bridge_state * bridge = (struct nic_bridge_state *)packet_state->guest_packet_data; + #ifdef V3_CONFIG_DEBUG_NIC_BRIDGE { - PrintDebug("NIC Bridge: recv pkt size: %d\n", evt->size); - v3_hexdump(evt->pkt, evt->size, NULL, 0); + PrintDebug("NIC Bridge: recv pkt size: %d\n", size); + v3_hexdump(pkt, size, NULL, 0); } #endif - - return bridge->net_ops.recv(evt->pkt, - evt->size, - bridge->net_ops.frontend_data); + + return bridge->net_ops.recv(pkt, + size, + bridge->net_ops.config.frontend_data); } static int nic_bridge_free(struct nic_bridge_state * bridge) { - - /*detach from front device */ - + /*TODO: detach from front device */ + + v3_packet_close(bridge->packet_state); V3_Free(bridge); return 0; @@ -78,29 +77,36 @@ static int nic_bridge_free(struct nic_bridge_state * bridge) { static struct v3_device_ops dev_ops = { .free = (int (*)(void *))nic_bridge_free, - + }; static int nic_bridge_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { struct nic_bridge_state * bridge = NULL; char * dev_id = v3_cfg_val(cfg, "ID"); - + char * host_nic; + v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend"); - + + v3_cfg_tree_t * hostnic_cfg = v3_cfg_subtree(cfg, "hostnic"); + host_nic = v3_cfg_val(hostnic_cfg, "name"); + if(host_nic == NULL) { + host_nic = "eth0"; + } + bridge = (struct nic_bridge_state *)V3_Malloc(sizeof(struct nic_bridge_state)); memset(bridge, 0, sizeof(struct nic_bridge_state)); - + struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, bridge); - + if (dev == NULL) { PrintError("Could not attach device %s\n", dev_id); V3_Free(bridge); return -1; } - + bridge->net_ops.send = bridge_send; bridge->vm = vm; - + if (v3_dev_connect_net(vm, v3_cfg_val(frontend_cfg, "tag"), &(bridge->net_ops), frontend_cfg, bridge) == -1) { PrintError("Could not connect %s to frontend %s\n", @@ -108,14 +114,20 @@ static int nic_bridge_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { v3_remove_device(dev); return -1; } - + PrintDebug("NIC-Bridge: Connect %s to frontend %s\n", - dev_id, v3_cfg_val(frontend_cfg, "tag")); - - - V3_packet_add_recver(bridge->net_ops.fnt_mac, vm); - v3_hook_host_event(vm, HOST_PACKET_EVT, V3_HOST_EVENT_HANDLER(packet_input), bridge); - + dev_id, v3_cfg_val(frontend_cfg, "tag")); + + bridge->packet_state = v3_packet_connect(vm, host_nic, + bridge->net_ops.config.fnt_mac, + packet_input, + (void *)bridge); + + if(bridge->packet_state == NULL){ + PrintError("NIC-Bridge: Error to connect to host ethernet device\n"); + return -1; + } + return 0; } diff --git a/palacios/src/interfaces/vmm_packet.c b/palacios/src/interfaces/vmm_packet.c index 10bdbda..b46325e 100644 --- a/palacios/src/interfaces/vmm_packet.c +++ b/palacios/src/interfaces/vmm_packet.c @@ -16,7 +16,6 @@ * This is free software. You are permitted to use, * redistribute, and modify it as specified in the file "V3VEE_LICENSE". */ - #include #include #include @@ -25,35 +24,49 @@ static struct v3_packet_hooks * packet_hooks = 0; -int V3_send_raw(const char * pkt, uint32_t len) { - if(packet_hooks != NULL && packet_hooks->send != NULL){ - return packet_hooks->send(pkt, len, NULL); - } +void V3_Init_Packet(struct v3_packet_hooks * hooks) { + packet_hooks = hooks; + PrintDebug("V3 raw packet interface inited\n"); - return -1; + return; } +struct v3_packet * v3_packet_connect(struct v3_vm_info * vm, + const char * host_nic, + const char * vm_mac, + int (*input)(struct v3_packet * packet, uint8_t * buf, uint32_t len), + void * guest_packet_data) { + struct v3_packet * packet = NULL; -int V3_packet_add_recver(const char * mac, struct v3_vm_info * vm){ - if(packet_hooks != NULL && packet_hooks->add_recver != NULL){ - return packet_hooks->add_recver(mac, vm); - } - - return -1; -} + V3_ASSERT(packet_hooks != NULL); + V3_ASSERT(packet_hooks->connect != NULL); + packet = V3_Malloc(sizeof(struct v3_packet)); -int V3_packet_del_recver(const char * mac, struct v3_vm_info * vm){ - if(packet_hooks != NULL && packet_hooks->del_recver != NULL){ - return packet_hooks->del_recver(mac, vm); + memcpy(packet->dev_mac, vm_mac, ETH_ALEN); + packet->input = input; + packet->guest_packet_data = guest_packet_data; + if(packet_hooks->connect(packet, host_nic, vm->host_priv_data) != 0){ + V3_Free(packet); + return NULL; } - return -1; + return packet; } -void V3_Init_Packet(struct v3_packet_hooks * hooks) { - packet_hooks = hooks; - PrintDebug("V3 raw packet interface inited\n"); +int v3_packet_send(struct v3_packet * packet, uint8_t * buf, uint32_t len) { + V3_ASSERT(packet_hooks != NULL); + V3_ASSERT(packet_hooks->send != NULL); + + return packet_hooks->send(packet, buf, len); +} - return; +void v3_packet_close(struct v3_packet * packet) { + V3_ASSERT(packet_hooks != NULL); + V3_ASSERT(packet_hooks->close != NULL); + + packet_hooks->close(packet); + V3_Free(packet); } + + diff --git a/palacios/src/palacios/vmm_host_events.c b/palacios/src/palacios/vmm_host_events.c index 3e6d09b..28543f7 100644 --- a/palacios/src/palacios/vmm_host_events.c +++ b/palacios/src/palacios/vmm_host_events.c @@ -29,7 +29,6 @@ int v3_init_host_events(struct v3_vm_info * vm) { INIT_LIST_HEAD(&(host_evts->timer_events)); INIT_LIST_HEAD(&(host_evts->serial_events)); INIT_LIST_HEAD(&(host_evts->console_events)); - INIT_LIST_HEAD(&(host_evts->packet_events)); return 0; } @@ -67,12 +66,6 @@ int v3_deinit_host_events(struct v3_vm_info * vm) { V3_Free(hook); } - - list_for_each_entry_safe(hook, tmp, &(host_evts->packet_events), link) { - list_del(&(hook->link)); - V3_Free(hook); - } - return 0; } @@ -110,9 +103,6 @@ int v3_hook_host_event(struct v3_vm_info * vm, case HOST_CONSOLE_EVT: list_add(&(hook->link), &(host_evts->console_events)); break; - case HOST_PACKET_EVT: - list_add(&(hook->link), &(host_evts->packet_events)); - break; } return 0; @@ -228,27 +218,3 @@ int v3_deliver_console_event(struct v3_vm_info * vm, return 0; } - -int v3_deliver_packet_event(struct v3_vm_info * vm, - struct v3_packet_event * evt) { - struct v3_host_events * host_evts = NULL; - struct v3_host_event_hook * hook = NULL; - - - host_evts = &(vm->host_event_hooks); - - if (vm->run_state != VM_RUNNING) { - return -1; - } - - list_for_each_entry(hook, &(host_evts->packet_events), link) { - if (hook->cb.packet_handler(vm, evt, hook->private_data) == -1) { - return -1; - } - } - - return 0; -} - - -