X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2Fvnet_nic.c;h=31c026d32f0ee9c71c8aa02875962438a0103ac5;hb=a71d971190b236cdd56f7a4003d78d4839466077;hp=ae1238f3bf95fbeeb471c37de707f04b1a71891c;hpb=73f9a9166e3588c28204d5c053a48cec8e9a5ba2;p=palacios.releases.git diff --git a/palacios/src/devices/vnet_nic.c b/palacios/src/devices/vnet_nic.c index ae1238f..31c026d 100644 --- a/palacios/src/devices/vnet_nic.c +++ b/palacios/src/devices/vnet_nic.c @@ -7,8 +7,8 @@ * and the University of New Mexico. You can find out more at * http://www.v3vee.org * - * Copyright (c) 2008, Lei Xia - * Copyright (c) 2008, The V3VEE Project + * Copyright (c) 2010, Lei Xia + * Copyright (c) 2010, The V3VEE Project * All rights reserved. * * Author: Lei Xia @@ -19,160 +19,142 @@ */ //backend device for Virtio NIC -#include +#include #include #include #include #include #include +#include +#include -struct vnet_nic_state { - char mac[6]; - +#ifndef V3_CONFIG_DEBUG_VNET_NIC +#undef PrintDebug +#define PrintDebug(fmt, args...) +#endif +struct vnet_nic_state { + struct v3_vm_info * vm; + struct v3_dev_net_ops net_ops; + int vnet_dev_id; }; -//used when virtio_nic get a packet from guest and send it to the backend -// send packet to all of the virtio nic devices other than the sender -static int send(uint8_t * buf, uint32_t len, void * private_data, struct vm_device *dest_dev){ - PrintDebug("Virito NIC: In vnet_send: guest net state %p\n", private_data); - - v3_vnet_send_rawpkt(buf, len, private_data); - return 0; -} -static int receive(uint8_t * buf, uint32_t count, void * private_data, struct vm_device *src_dev){ +/* called by frontend, send pkt to VNET */ +static int vnet_nic_send(uint8_t * buf, uint32_t len, + void * private_data) { + struct vnet_nic_state * vnetnic = (struct vnet_nic_state *)private_data; - return 0; -} + struct v3_vnet_pkt pkt; + pkt.size = len; + pkt.src_type = LINK_INTERFACE; + pkt.src_id = vnetnic->vnet_dev_id; + memcpy(pkt.header, buf, ETHERNET_HEADER_LEN); + pkt.data = buf; + V3_Net_Print(2, "VNET-NIC: send pkt (size: %d, src_id: %d, src_type: %d)\n", + pkt.size, pkt.src_id, pkt.src_type); + if(net_debug >= 4){ + v3_hexdump(buf, len, NULL, 0); + } -static struct v3_dev_net_ops net_ops = { - .send = send, - .receive = receive, -}; + return v3_vnet_send_pkt(&pkt, NULL); +} -#if 0 -static int input(struct v3_vm_info *info, uchar_t * buf, uint_t len, void * private_data){ - PrintDebug("Virito NIC: In virtio_input: guest net state %p\n", private_data); +/* send pkt to frontend device */ +static int fnt_input(struct v3_vm_info * info, + struct v3_vnet_pkt * pkt, + void * private_data){ + struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data; - return __virtio_dev_send(buf, len, private_data); + V3_Net_Print(2, "VNET-NIC: receive pkt (size %d, src_id:%d, src_type: %d, dst_id: %d, dst_type: %d)\n", + pkt->size, pkt->src_id, pkt->src_type, pkt->dst_id, pkt->dst_type); + + return vnetnic->net_ops.recv(pkt->data, pkt->size, + vnetnic->net_ops.config.frontend_data); } -//register a virtio device to the vnet as backend -void register_to_vnet(struct vm_device *dev, - char *dev_name, - uchar_t mac[6]){ - struct virtio_net_state * net_state; - struct virtio_dev_state *virtio_state = (struct virtio_dev_state *)dev->private_data; - uchar_t tapmac[6] = {0x00,0x02,0x55,0x67,0x42,0x39}; //for Intel-VT test HW - //uchar_t tapmac[6] = {0x6e,0xa8,0x75,0xf4,0x82,0x95}; - uchar_t dstmac[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; - uchar_t zeromac[6] = {0,0,0,0,0,0}; +/* poll pkt from frontend device */ +static int fnt_poll(struct v3_vm_info * info, + int quote, void * private_data){ + struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data; + return vnetnic->net_ops.poll(quote, vnetnic->net_ops.config.frontend_data); +} - net_state = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state)); - memset(net_state, 0, sizeof(struct virtio_net_state)); - net_state->net_ops = (struct v3_dev_net_ops *)V3_Malloc(sizeof(struct v3_dev_net_ops)); - net_state->net_ops->send = &vnet_send; - net_state->net_ops->receive = &vnet_receive; - net_state->dev = dev; - register_dev(virtio_state, net_state); +static int vnet_nic_free(struct vnet_nic_state * vnetnic) { - PrintDebug("Virtio NIC register Device %s: queue size: %d, %d\n", dev->name, - net_state->rx_vq.queue_size, net_state->tx_vq.queue_size); - PrintDebug("Virtio NIC: connect virtio device %s, state %p, to vnet\n", dev->name, net_state); + v3_vnet_del_dev(vnetnic->vnet_dev_id); + V3_Free(vnetnic); - int idx = vnet_register_device(dev, dev_name, mac, &virtio_input, net_state); - //vnet_add_route_entry(zeromac, dstmac, MAC_ANY, MAC_NONE, idx, LINK_INTERFACE, -1, LINK_INTERFACE); - if (!strcmp(dev_name, "net_virtiodom0")){ - vnet_add_route_entry(zeromac, tapmac, MAC_ANY, MAC_NONE, idx, LINK_INTERFACE, -1, LINK_INTERFACE); - vnet_add_route_entry(zeromac, dstmac, MAC_ANY, MAC_NONE, idx, LINK_INTERFACE, -1, LINK_INTERFACE); - } - if (!strcmp(dev_name, "net_virtio")) - vnet_add_route_entry(tapmac, zeromac, MAC_NONE, MAC_ANY, idx, LINK_INTERFACE, -1, LINK_INTERFACE); - - - v3_vnet_add_node(dev_name, mac, input, priv_data); - struct v3_vnet_route route; - //add default route - memset(&route, 0, sizeof(struct v3_vnet_route)); - memcpy(&route.dest_mac, mac, 6); - route.src_mac_qual = MAC_ANY; - route.dest_mac_qual = MAC_NONE; - route.link_idx = idx; - route.link_type = LINK_EDGE; - route.src_link_idx = -1; - route.src_type = LINK_ANY; - v3_vnet_add_route(&route); - - char mac - memset(&route, 0, sizeof(struct v3_vnet_route)); - memcpy(&route.dest_mac, mac, 6); - route.src_mac_qual = MAC_ANY; - route.dest_mac_qual = MAC_NONE; - route.link_idx = idx; - route.link_type = LINK_EDGE; - route.src_link_idx = -1; - route.src_type = LINK_ANY; - v3_vnet_add_route(&route); - -} - - -/* - *called in svm/vmx handler - *iteative handled the unsent packet in incoming packet queues for - *all virtio nic devices in this guest - */ -int v3_vnetnic_pktprocess(struct guest_info * info) -{ - return 0; } -#endif +static struct v3_device_ops dev_ops = { + .free = (int (*)(void *))vnet_nic_free, -static int vnet_nic_free(struct vm_device * dev) { - return 0; -} +}; -static struct v3_device_ops dev_ops = { - .free = vnet_nic_free, - .reset = NULL, - .start = NULL, - .stop = NULL, +static struct v3_vnet_dev_ops vnet_dev_ops = { + .input = fnt_input, + .poll = fnt_poll, }; + static int vnet_nic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { struct vnet_nic_state * vnetnic = NULL; - char * name = v3_cfg_val(cfg, "name"); + char * dev_id = v3_cfg_val(cfg, "ID"); + int vnet_dev_id; v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend"); - vnetnic = (struct vnet_nic_state *)V3_Malloc(sizeof(struct vnet_nic_state)); - memset(vnetnic, 0, sizeof(struct vnet_nic_state)); + if (!frontend_cfg || !(v3_cfg_val(frontend_cfg, "tag"))) { + PrintError(vm, VCORE_NONE, "No frontend config specified, or frontend has no tag\n"); + return -1; + } + vnetnic = (struct vnet_nic_state *)V3_Malloc(sizeof(struct vnet_nic_state)); - PrintDebug("Registering vnet_nic device at\n"); + if (!vnetnic) { + PrintError(vm, VCORE_NONE, "Cannot allocate in init\n"); + return -1; + } - struct vm_device * dev = v3_allocate_device(name, &dev_ops, vnetnic); + memset(vnetnic, 0, sizeof(struct vnet_nic_state)); - if (v3_attach_device(vm, dev) == -1) { - PrintError("Could not attach device %s\n", name); + struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, vnetnic); + if (dev == NULL) { + PrintError(vm, VCORE_NONE, "Could not attach device %s\n", dev_id); + V3_Free(vnetnic); return -1; } + vnetnic->net_ops.send = vnet_nic_send; + vnetnic->vm = vm; + if (v3_dev_connect_net(vm, v3_cfg_val(frontend_cfg, "tag"), - &net_ops, frontend_cfg, vnetnic) == -1) { - PrintError("Could not connect %s to frontend %s\n", - name, v3_cfg_val(frontend_cfg, "tag")); + &(vnetnic->net_ops), frontend_cfg, vnetnic) == -1) { + PrintError(vm, VCORE_NONE, "Could not connect %s to frontend %s\n", + dev_id, v3_cfg_val(frontend_cfg, "tag")); + v3_remove_device(dev); return -1; } - + + PrintDebug(vm, VCORE_NONE, "Vnet-nic: Connect %s to frontend %s\n", + dev_id, v3_cfg_val(frontend_cfg, "tag")); + + if ((vnet_dev_id = v3_vnet_add_dev(vm, vnetnic->net_ops.config.fnt_mac, + &vnet_dev_ops, vnetnic->net_ops.config.quote, + vnetnic->net_ops.config.poll, (void *)vnetnic)) == -1) { + PrintError(vm, VCORE_NONE, "Vnet-nic device %s fails to registered to VNET\n", dev_id); + + v3_remove_device(dev); + return 0; + } + vnetnic->vnet_dev_id = vnet_dev_id; return 0; }