|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Minios-devel] [UNIKRAFT PATCH] plat/kvm: Introduce virtio network driver
Hello, Please find my comment inline:As a general comment, check_patch produces error with "Unrecognized email address". Please fix it. In our current design, we have the different layers involved in Virtio in a single implementation. It might be wise to split them up as it would better reflect the interactions involved. I would like to summarize the brief breakdown of the layers and the interactions involved.
* The Virtio-ring is responsible for
* ring meta data maintenance
* API for add/getting buffer and maintaining the data structure
associated with the virtio-ring.
* API to enable and disable notification on the interrupt.
* The Virtio-pci is responsible for:
* Reading/Writing configuration
* Reading Status information
* Resetting the device.
* Acknowledging the PCI Device and the driver if found.
* Interrupt handling / Configuring the different type of interrupt.
* The Virtio-net is responsible for:
* Maintaining the network data buffer to be sent to the virtio-ring
* Negotiate the feature of the network device eg MAC_Address, Max
Virtqueue.
* Allocating/Deallocating the virtqueue for the TX and RX and
control queue (if necessary).
* Handling event callback from the virt-ring.
* API interacting with the network stack.
From my perspective such a split would enable us to add other virtio
device while using the rest of the infrastructure. It would also help
replace the pci with mmio as necessary.
On 07/24/2018 06:43 PM, Razvan Cojocaru wrote: This patch must be applied after Unikraft Network API is upstreamed.On Tue, Jul 24, 2018, 19:26 Razvan Cojocaru <razvan.cojocaru93@xxxxxxxxx <mailto:razvan.cojocaru93@xxxxxxxxx>> wrote: /** Review * We should define PCI_LEGACY_NW_DEVICE_ID as 0x1000. * * The PCI_CONF_SUBSYS_NET define id within the virtio id space which is * # Network Device id - 1 * # Block Device id - 2 and so on. * * Since in our current implementation we register with the PCI bus, * we should be using the PCI_LEGACY_DEVICE_ID (0x1000) * or PCI_MODERN_DEVICE_ID(0x1041) */ /** Review: * The virtio standard mentions the VIRTIO_NET_F_MAC as 5.It is wise to * retain it as 5. It would be a separation of the standard constant * from the mechanism to store it. * * It may be better to separate macro which store the bit map. */ /** Review * What do we define as PKT_BUFFER_LEN? Does this information also * include the virtio header? A comment describing why 1526 would be * helpful. */ /** Review * Virtio ring define data type to be used for 16-bit integer. We should * be using this data type instead of uint16_t. We should also probably * define a datatype of uint8_t for consistency. */ frame */ /** Review: * 1) It would be better to define the virtio-net-config to define the * configuration space. This structure is described in section * 5.1.4 [2] as below: * # MAC Address: Which is always present * # Status: These enabled based on the flag VIRTIO_NET_F_STATUS * # Max Virtualqueue pairs: Enable based on the flag VIRTIO_NET_F_MQ * which is not currently supported but most likely to added. * * I would suggest to include this structure as it would clearly define * the configuration space of the virtio-net device as it is part of the * Virtio-standard. We can query the read/write configuration space * using offset defined in the structure. eg * __offsetof(struct virtio_net_config, mac); */ /** Review: * 1) Why would we need create thread within virtio driver for the * recieve queue. It would be better manage these thread within * libuknet. The virtio-net device would be responsible for handling * callback from the virtqueue and signalling the network stack * regarding the receipt of a packet. * * 2) We also need to protect the usage of the thread and waitq with * the respective libraries. */ /** Review: * The interrupt handled in this handler is that of the virtio-pci * device. * * When we plan to restructure the virtio-layer this function * will have to shifted to the virtio-pci layer. This would create a * clear distinction between the virtio pci device and the virtio device * ie network device. * * Please refer to the top for more detailed description */ /** Review: * We are combining the network data buffer within the virtio-ring * implementation in the io_buffer. I think it is wise to decouple * information and move toward a data structure like a * scatter/gather list. * * The virtq ring structure contains internal information like the * next_avail to manage the virt-ring. It should be directly * accessed from the virtio-net device. We */ /** Review: * Why do we need to cleanup the memory? Virtio provides * us with length field to determine the size of the received * buffer? */ /** Review: * Why are we asserting for error? */ /** Review: * This should belong to the virtio-pci device. We must also check if * device want to suppress the notification. * * Please refer to the top for more detailed description */ /** Review: * Prefer if we had a helper function/macro to return the * virtio_net_device instead of invoking the __containerof directly. */ /** Review: * Is it be possible for the packet length could be > 1526 * when we set the MTU on initialization to the PKT_BUFFER_LEN. * If it is an error with the NW stack we might as well assert for it. */ /** Review: * 1) We are reclaiming the buffers freed by the device * but we must careful here as the user of the stack could possibly * enable the interrupt on the virtqueue resulting in notification * on completion of data transfer to host. The interrupt user should not * clean up the descriptor then or we will have to protect these data * structure using locks. * * It will also be better to provide a helper function which * perform the cleanup. * free_old_tx_desc(struct virtio_net_device *) * * * 2) In the below piece of code, we are manipulating the internal ring * structures which are critical. I would prefer if we * provide helper functions perform the manipulating of the * num_avail, last_used and next_avail. Something like * virtq_getbuf(struct virtq *); * * 3) In this we are using idx, which is update from the host. I * think, we require a rmb to while working with the available idx as * the host is also writing to it. */ /** Review: * We are using the internal virtq data structure (next_avail). * I would prefer if we provide helper function in virtio_ring * to get its buf. In this case we * could have something like * virtq_fetchAvailBuf(struct virtq *, int tot_buf_cnt) */ /** Review: * 1) According to spec[2] section 5.1.6.2, if the virtio checksum * feature was not negotiated the gso_type in the virtio_nethdr should * be set to VIRTIO_NET_HDR_GSO_NONE. Since we do not negotiate for the * checksum feature it would be wise explicitly set the value to * VIRTIO_NET_HDR_GSO_NONE. * * This next comment probably affect other patches * enabling networking on Unikraft * 2) Since the netdevice does not support checksum * offload, we must enforce higher layer of the network stack to * perform checksum. Currently in our lwip implementation we provide * it as a configuration option. It might we wise to generate an * compilation error if the user turn on the checksum offload * in the network stack. * It is also possible on the receive side of lwip to ignore checksums * and on sending ot should calculate one. THe problem is * that we may receive packets from another VM that set CSO. However, * since we never left the physical machine, the checksum is * never calculated and on receive the flag is set on the virtio * buffer. This means that the packet has a wrong checksum although * everything is working correctly. Packets with wrong * checksums coming from external should anyway dropped already by the * physical NIC on Dom0/Hypervsior host, so these packets will * never arrive at the VM. * * 3)We may have to think about it in the future. * If we enable the checksum offload feature, we might require * information from the network stack regarding offset and * length within the packet for performing the checksum. We might * need a way to transfer this information to the network device. */ /** Review: * If the virtq_add_descriptor throw as error we are still notifying * the device. */ /** Review: * We are notifying the device without verifying if the device has set * the flag to not notify. Move this functionality with the virtio-ring. * Since this would be common functionality across viritio-devices. * * Please refer to the top for more detailed description */ /** Review: * Prefer for the virtio-ring layer to provide an API to disable/enable * virtqueue interrupt. This would * make it easier when we move from the flag to event based on the * VIRTIO_F_EVENT_IDX flag. * * Please refer to the top for more detailed description */ /** Review: * 1) In spec[2] section 3.2.2, provides a cleaner implementation of * retrieving the buffer from the virtio-ring. * In the current implementation read barrier while reading buffer and * idx are missing. * * 2) The function remove the buffers from the ring should be moved to * the virtio-ring implementation as it is responsible for maintaining * the counter such last_used. * virtq_getbuf(struct virtq *); * could also be used to get the buffer for receiving. * * 3) In spec[2] section 5.1.6.6, it states this * * " When using legacy interfaces, transitional drivers which have not * negotiated VIRTIO_F_ANY_LAYOUT MUST use a single descriptor for the * struct virtio_net_hdr on both transmit and receive, with the network * data in the following descriptors." * * For the transmit queue we are following this but for receive queue we * are not doing this. * * 4) The used buffer is shared between the host device and the guest * driver, we might need read barrier before reading from these buffer. */ /** Review: * Prefer for the virtio-ring layer to provide an API to disable/enable * virtqueue interrupt. This would * make it easier when we move from the flag to event based on the * VIRTIO_F_EVENT_IDX flag. * * Please refer to the top for more detailed description */ /** Review: * I prefer doing this check before doing any math - this is much * clearer to understand the error case * UK_ASSERT(e->len > sizeof(struct virtio_net_hdr) && * e->len <= MAX_BUFLEN) */ /** Review * * The function remove the buffers from the ring should be moved to * the virtio-ring implementation as it is responsible for maintaining * the counter such last_used. * * virtq_getbuf(struct virtq *); * could also be used to get the buffer for receiving. * * Please refer to the top for more detailed description */ /** Review: * Asserting for an error. */ /** Review: * Prefer if we had a helper function/macro to return the * virtio_net_device instead of invoking the __containerof directly. */ /** Review: * While setting the pktlen should it not be MIN(mbuf->len, * pktlen). If buffer allocated is smaller then it we are * writting to someother location. * * An UK_ASSERT to check the length of mbuf. */ /** Review: * Prefer if we had a helper function/macro to return the * virtio_net_device instead of invoking the __containerof directly. */ /** Review: * 1) In section 3.1.1 [2] describe the device initialization to be * performed. * We initializing the virtqueue after setting the DRIVER_OK. * Prefer if we can stick with the specification. * * 2) We could also create the separate function * virtio_netdev_queue_alloc(struct virtio_net_device *) to perform the * initalization. As we are using the same step to initialize the * virtqueue_tx and virtqueue_rx as well control queues as and when * enabled. */ /** Review: * Prefer we move the io_buffer inside the virtio-net device. As it * would mean data buffer are managed by the network driver * * Please refer to the top for more detailed description */ /** Review: * Prefer if we had a helper function/macro to return the * virtio_net_device instead of invoking the __containerof directly. */ /** Review: * 1) In section 3.1.1 [2] describe the device initialization to be * performed. * We initializing the virtqueue after setting the DRIVER_OK. * Prefer if we can stick with the specification. * * 2) We could also create the separate function * virtio_netdev_queue_alloc(struct virtio_net_device *) to perform the * initalization. As we are using the same step to initialize the * virtqueue_tx and virtqueue_rx as well control queues. */ /** Review: * Prefer if we had a helper function/macro to return the * virtio_net_device instead of invoking the __containerof directly. */ /** Review: * This should be assigned while adding the device. */ /** Review: * I have a some of comments on the following piece of the code: * * 1) The acknowledgment of the device should be done while probing the * device. Why are we postponing it until we are configuring * the device? * * 2) Instead of calling the outb directly, it might be better * to have generic function, like iowrite8 to * perform the write operation. This is not specific to this patch, * as we have used the inb/outb even in virtio-ring as well as pci. * Need to look at this part when we change that. * * 3) The below code could also be moved as a part * of header file, as we would use it across virtio device drivers. * * 4) If the configuration can change should we not also reset the * device and reinitialize the device from scratch. Resetting the * may not be necessary during initialization. If we are * reconfiguring the device we will have to reset the device and * renegotiate the features. */ /** Review: * 1) Why are we asserting for the VIRTIO_NET_F_MAC, as it is a feature * set? I think would be better to throw an error and uk_printd() * message about the error. * * 2) According the spec [2] 5.1.5, if the MAC is not configured local * mac "would" be generated by the guest driver. Since we are generating * the a random MAC address we might add comment describing that we * report an error instead of generating a local MAC. */ /** Review: * According to Virtio specification[2], section 2.3.1. Config fields * greater than 32-bits cannot be atomically read. We may need to * reconsider providing generic read/write function for all these * virtio device in a separate header file which could be reused across * different virtio devices. * * Legacy Virtio PCI Device: * According to specification, we would have to the configuration * address until the same value are returned. * * 2) Why copying it two times? We could use n->data->mac_addr directly */ /** Review: * 1) Why are setting the network state within the driver? Shouldn't the * libuknet set the state? * * According to the specification[2] section 3.1, the driver of flag is * set after the virtio_ring is configured. We will have to move it as a * part of starting the net device. * * Please refer to the top for more detailed description */ /** Review: * Why is this defined as a globally visible function when we are * passing it as a function pointer. */ /** Review: * Prefer if we had a helper function/macro to return the * virtio_net_device instead of invoking the __containerof directly. */ /** Review: * Prefer for the virtio-ring layer to provide an API to enable * virtqueue interrupt. This would * make it easier when we move from the flag to event based on the * VIRTIO_F_EVENT_IDX flag. * * Please refer to the top for more detailed description */ /** Review: * Why is this defined as a globally visible function when we are * passing it as a function pointer. */ /** Review: * Prefer if we had a helper function/macro to return the * virtio_net_device instead of invoking the __containerof directly. */ /** Review: * Prefer for the virtio-ring layer to provide an API to disable * virtqueue interrupt. This would * make it easier when we move from the flag to event based on the * VIRTIO_F_EVENT_IDX flag. * * Please refer to the top for more detailed description */ /** Review: * 1) The used ring idx is a data structure between the host * device and the guest driver. I think we need mb. * * 2) This function should belong to the libuknet. As the * interrupt handler wakeup a thread in the network stack to * to perform receive operation. */ /** Review: * if rx_cb != NULL before calling it */ /** Review: * Why is this defined as a globally visible function when we are * passing it as a function pointer. */ /** Review: * Prefer if we had a helper function/macro to return the * virtio_net_device instead of invoking the __containerof directly. */ /** Review: * use snprintf instead of sprintf. safe coding practise */ /** Review: * The uk_netdev_name_set return error -ENOTSUP if the name config * flag are not set. Maybe, it would be wise to make the * uk_netdev_name_set as a function that return void. */ /** Review: * 1) Why are setting the network state within the driver? Shouldn't the * libuknet set the state? */ /** Review: * Why are we creating a thread within the virtio driver? * libuknet is the library which perform operation on the network * packet? * Should it not be responsible for creating the receiver thread and * scheduling the network stack to receive packets? */ /** Review: * Prefer for the virtio-ring layer to provide an API to disable * virtqueue interrupt. This would * make it easier when we move from the flag to event based on the * VIRTIO_F_EVENT_IDX flag. * * Please refer to the top for more detailed description */ /** Review: * Why is this defined as a globally visible function when we are * passing it as a function pointer. */ /** Review: * Prefer if we had a helper function/macro to return the * virtio_net_device instead of invoking the __containerof directly. */ /** Review: * 1) I would prefer if we call helper function while manipulating the * internal data of uk_net_dev. * * 2) What happenes to buffers submitted to virtio? Do we wait to flush * all the buffer? */ /** Review: * Prefer if we had a helper function/macro to return the * virtio_net_device instead of invoking the __containerof directly. */ /** Review: * 1) I would prefer if we call helper function while manipulating the * internal data of uk_net_dev. * * 2) What happenes to buffers submitted to virtio? Do we wait to flush * all the buffer? */ /** Review: * Do we want to initialize an internal data structure here? Should the * libuknet provide a initializer function. * * Error Check missing for uk_malloc. * * This function should do the least minimum to let libuknetdev know * that there is a network device. */ /** Review: * Why are we setting the Network MTU to 1526? If we using the Ethernet * should we not mention it as 1500. As the Ethernet packet would be * 1500 + 18(Ethernet header). */
/** Review:
* 1) Prefer to use the macro provided in pci
* PCI_DEVICE_ID(VENDOR_QUMRANET_VIRTIO, PCI_ANY_ID)
*
* 2) If we are specializing this for Network device, should we not use
* device id to be Legacy network device("0x1000")?
*
*/
/** Review: * I would not bundle virtio_net and virtio_ring as they have separate * reason to exists. Figure 3, in [1] provides a high level overview * on the different layers within the virtio. I believe * it would be better if we stick with it unless we have very good * reason to avoid it. */
[1] https://www.ibm.com/developerworks/library/l-virtio/ [2] http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.html Thanks & Regards Sharan _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |