help
Enable debugging for the VNET Virtio Device
+config LINUX_VNET_BRIDGE
+ bool "Enable VNET Bridge for Linux host"
+ default n
+ depends on PCI && EXPERIMENTAL && VNET && LINUX
+ help
+ Enable the VNET Bridge for Linux host
+
+config DEBUG_LINUX_VNET_BRIDGE
+ bool "VNET Host Linux Bridge Debug"
+ default n
+ depends on LINUX_VNET_BRIDGE && DEBUG_ON && LINUX
+ help
+ Enable debugging for the VNET Host Linux Bridge
+
endmenu
unsigned int period_us;
};
+struct v3_console_event {
+ unsigned char data[128];
+ unsigned int len;
+};
+
#ifdef __V3VEE__
#include <palacios/vmm_list.h>
typedef enum {HOST_KEYBOARD_EVT,
HOST_MOUSE_EVT,
- HOST_TIMER_EVT} v3_host_evt_type_t;
+ HOST_TIMER_EVT,
+ HOST_CONSLE_EVT} v3_host_evt_type_t;
union v3_host_event_handler {
int (*keyboard_handler)(struct v3_vm_info * vm, struct v3_keyboard_event * evt, void * priv_data);
int (*mouse_handler)(struct v3_vm_info * vm, struct v3_mouse_event * evt, void * priv_data);
int (*timer_handler)(struct v3_vm_info * vm, struct v3_timer_event * evt, void * priv_data);
+ int (*console_handler)(struct v3_vm_info * vm, struct v3_console_event * evt, void * priv_data);
};
struct list_head keyboard_events;
struct list_head mouse_events;
struct list_head timer_events;
+ struct list_head console_events;
};
int v3_deliver_keyboard_event(struct v3_vm_info * vm, struct v3_keyboard_event * evt);
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_console_event(struct v3_vm_info * vm, struct v3_console_event * evt);
uint8_t src_type;
uint32_t src_id;
uint8_t header[ETHERNET_HEADER_LEN];
- uint8_t *data;
+ uint8_t * data;
} __attribute__((packed));
} __attribute__((packed));
} __attribute__((packed));
};
struct v3_vnet_dev_ops {
- int (*input)(struct v3_vm_info * vm, struct v3_vnet_pkt * pkt, void * dev_data);
- void (*poll) (struct v3_vm_info *vm, void *dev_data);
+ int (*input)(struct v3_vm_info * vm,
+ struct v3_vnet_pkt * pkt,
+ void * dev_data);
+ void (*poll) (struct v3_vm_info * vm, void * dev_data);
void (*poll_xcall)(void *arg);
void (*start_tx)(void * dev_data);
};
struct v3_vnet_bridge_ops {
- int (*input)(struct v3_vm_info * vm, struct v3_vnet_pkt pkt[], uint16_t pkt_num, void * private_data);
- int (*xcall_input)(void *data);
- void (*polling_pkt)(struct v3_vm_info * vm, void *private_data);
+ int (*input)(struct v3_vm_info * vm,
+ struct v3_vnet_pkt * pkt,
+ void * private_data);
+ int (*xcall_input)(void * data);
+ void (*polling_pkt)(struct v3_vm_info * vm,
+ void * private_data);
};
obj-$(CONFIG_SYMMOD) += lnx_virtio_symmod.o
obj-$(CONFIG_CHAR_STREAM) += char_stream.o
+obj-$(CONFIG_LINUX_VNET_BRIDGE) += lnx_vnet_brg.o
}
-static int vnet_pkt_input_cb(struct v3_vm_info * vm, struct v3_vnet_pkt vnet_pkts[], uint16_t pkt_num, void * private_data){
+static int vnet_pkt_input_cb(struct v3_vm_info * vm, struct v3_vnet_pkt *pkt, void * private_data){
struct virtio_vnet_state * vnet_state = (struct virtio_vnet_state *)private_data;
struct virtio_queue * q = &(vnet_state->queue[RECV_QUEUE]);
int ret_val = -1;
unsigned long flags;
uint16_t sent;
- struct v3_vnet_pkt *pkt;
-
- if(pkt_num <= 0)
- return 0;
flags = v3_lock_irqsave(vnet_state->lock);
goto exit;
}
- PrintDebug("VNET Bridge: RX: running on cpu: %d, num of pkts: %d\n", V3_Get_CPU(), pkt_num);
-
- for(sent = 0; sent < pkt_num; sent ++) {
- pkt = &vnet_pkts[sent];
- vnet_state->pkt_recv ++;
-
- if (q->cur_avail_idx != q->avail->index) {
- uint16_t pkt_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
- struct vring_desc * pkt_desc = NULL;
- struct vnet_bridge_pkt * virtio_pkt = NULL;
+ if (q->cur_avail_idx != q->avail->index) {
+ uint16_t pkt_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
+ struct vring_desc * pkt_desc = NULL;
+ struct vnet_bridge_pkt * virtio_pkt = NULL;
- pkt_desc = &(q->desc[pkt_idx]);
- PrintDebug("VNET Bridge RX: buffer desc len: %d\n", pkt_desc->length);
+ pkt_desc = &(q->desc[pkt_idx]);
+ PrintDebug("VNET Bridge RX: buffer desc len: %d\n", pkt_desc->length);
- if (v3_gpa_to_hva(&(vm->cores[0]), pkt_desc->addr_gpa, (addr_t *)&(virtio_pkt)) == -1) {
- PrintError("Could not translate buffer address\n");
- goto exit;
- }
+ if (v3_gpa_to_hva(&(vm->cores[0]), pkt_desc->addr_gpa, (addr_t *)&(virtio_pkt)) == -1) {
+ PrintError("Could not translate buffer address\n");
+ goto exit;
+ }
- PrintDebug("VNET Bridge: RX: pkt sent to guest pkt size: %d, dst link: %d\n", pkt->size, pkt->dst_id);
+ PrintDebug("VNET Bridge: RX: pkt sent to guest pkt size: %d, dst link: %d\n", pkt->size, pkt->dst_id);
- // Fill in dst packet buffer
- virtio_pkt->link_id = pkt->dst_id;
- virtio_pkt->pkt_size = pkt->size;
- memcpy(virtio_pkt->pkt, pkt->data, pkt->size);
+ // Fill in dst packet buffer
+ virtio_pkt->link_id = pkt->dst_id;
+ virtio_pkt->pkt_size = pkt->size;
+ memcpy(virtio_pkt->pkt, pkt->data, pkt->size);
- 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 = sizeof(struct vnet_bridge_pkt);
-
- q->used->index++;
- q->cur_avail_idx++;
- } else {
- vnet_state->pkt_drop ++;
- //v3_vnet_disable_bridge();
- }
- }
+ 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 = sizeof(struct vnet_bridge_pkt);
- if(sent == 0){
- goto exit;
+ q->used->index++;
+ q->cur_avail_idx++;
+ } else {
+ vnet_state->pkt_drop ++;
}
if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
}
ret_val = 0;
-
-#ifdef CONFIG_VNET_PROFILE
- if (vnet_state->pkt_recv % 20000 == 0)
- PrintError("Vnet Bridge: sent: %ld, rxed: %ld, dropped: %ld, total exit: %ld, tx exit: %ld, rx exit: %ld\n",
- vnet_state->pkt_sent,
- vnet_state->pkt_recv,
- vnet_state->pkt_drop,
- vnet_state->total_exit,
- vnet_state->tx_exit,
- vnet_state->rx_exit);
-#endif
-
exit:
v3_unlock_irqrestore(vnet_state->lock, flags);
static int vnet_pkt_input_xcall(void *data){
struct v3_vnet_bridge_xcall_args *args = (struct v3_vnet_bridge_xcall_args *)data;
+ int i = 0;
+
+ for(i = 0; i < args->pkt_num; i++) {
+ vnet_pkt_input_cb(args->vm, args->vnet_pkts[i], args->private_data);
+ }
- return vnet_pkt_input_cb(args->vm, args->vnet_pkts, args->pkt_num, args->private_data);
+ return 0;
}
static int handle_pkt_kick(struct guest_info *core, struct virtio_vnet_state * vnet_state)
v3_pci_raise_irq(vnet_state->pci_bus, 0, vnet_state->pci_dev);
vnet_state->virtio_cfg.pci_isr = 0x1;
}
-
- //PrintError("Virtio VNET: polling %d pkts\n", recvd);
-#ifdef CONFIG_VNET_PROFILE
- if (vnet_state->pkt_sent % 20000 == 0)
- PrintError("Vnet Bridge: sent: %ld, rxed: %ld, dropped: %ld, total exit: %ld, tx exit: %ld, rx exit: %ld\n",
- vnet_state->pkt_sent,
- vnet_state->pkt_recv,
- vnet_state->pkt_drop,
- vnet_state->total_exit,
- vnet_state->tx_exit,
- vnet_state->rx_exit);
-#endif
-
return 0;
}
int socket;
sock_type_t type;
+
int link_idx;
struct list_head node;
struct vnet_brg_state {
uint32_t num_links;
-
struct list_head link_list;
int serv_sock;
sock_type_t serv_sock_type;
int serv_port;
-
- /* The thread recving pkts from sockets. */
- int serv_thread;
v3_lock_t lock;
unsigned long pkt_sent, pkt_recv, pkt_drop;
};
-static struct vnet_brg_state lnxbrg_state;
static int vnet_lnxbrg_reset(struct vnet_brg_state * state) {
memset(state, 0, sizeof(struct vnet_brg_state));
static int
-brg_send(struct vnet_brg_state * state,
- struct v3_vm_info * vm,
+brg_send( struct v3_vm_info * vm,
struct v3_vnet_pkt * vnet_pkt,
void * private_data){
+ struct vnet_brg_state * state = (struct vnet_brg_state *)private_data;
struct vnet_link * link = NULL;
#ifdef CONFIG_DEBUG_VNET_LNX_BRIGE
#endif
state->pkt_recv ++;
- link = link_by_idx(vnet_pkt->dst_id);
+ link = link_by_idx(state, vnet_pkt->dst_id);
if (link != NULL) {
- if(link->type == SOCK_TCP){
-
- }else if(link->type == SOCK_UDP){
+ if(link->type == SOCK_UDP){
udp_send(link->socket, 0, 0, vnet_pkt->data, vnet_pkt->size);
state->pkt_sent ++;
}else {
continue;
}
- link = link_by_ip(ip);
+ link = link_by_ip(state, ip);
if (link != NULL) {
pkt.src_id= link->link_idx;
}
v3_vnet_add_bridge(NULL, &brg_ops, state);
- init_serv();
+ init_serv(state);
V3_CREATE_THREAD(vnet_server, state, "VNET_LNX_BRIDGE");
PrintDebug("VNET Linux Bridge initiated\n");
case HOST_TIMER_EVT:
list_add(&(hook->link), &(host_evts->timer_events));
break;
+ case HOST_CONSLE_EVT:
+ list_add(&(hook->link), &(host_evts->console_events));
+ break;
}
return 0;
return 0;
}
+
+int v3_deliver_console_event(struct v3_vm_info * vm,
+ struct v3_console_event * evt) {
+ struct v3_host_events * host_evts = NULL;
+ struct v3_host_event_hook * hook = NULL;
+
+ if (vm == NULL) {
+ vm = v3_get_foreground_vm();
+ }
+
+ host_evts = &(vm->host_event_hooks);
+
+ if (vm->run_state != VM_RUNNING) {
+ return -1;
+ }
+
+ list_for_each_entry(hook, &(host_evts->console_events), link) {
+ if (hook->cb.console_handler(vm, evt, hook->private_data) == -1) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
return -1;
}
- return bridge->brg_ops.input(bridge->vm, pkt, 1, bridge->private_data);
+ return bridge->brg_ops.input(bridge->vm, pkt, bridge->private_data);
}