(2014/09/03 14:39), Xie, Huawei wrote:
> Thanks Tetsuya:
>       Some of them are due to 80 character limitation. Is it ok to break the 
> limitation for better indentation?
It's is up to the cording style of dpdk. But, there may be no strict
rule in dpdk.
So please use your original cord. :)

Thanks,
Tetsuya

>> -----Original Message-----
>> From: Tetsuya.Mukawa [mailto:mukawa at igel.co.jp]
>> Sent: Wednesday, September 03, 2014 11:39 AM
>> To: Xie, Huawei; dev at dpdk.org
>> Subject: Re: [dpdk-dev] [PATCH 2/3] lib/librte_vhost: vhost library support 
>> to
>> facilitate integration with DPDK accelerated vswitch
>>
>> Hi Huawei,
>>
>> I added few comments. Mainly those comments are about source code indent.
>>
>> (2014/09/02 17:55), Huawei Xie wrote:
>>> +
>>> +/**
>>> + * Structure contains variables relevant to RX/TX virtqueues.
>>> + */
>>> +struct vhost_virtqueue {
>>> +   /**< descriptor ring. */
>>> +   struct vring_desc    *desc;
>>> +   /**< available ring. */
>>> +   struct vring_avail   *avail;
>>> +   /**< used ring. */
>>> +   struct vring_used    *used;
>>> +   /**< Size of descriptor ring. */
>>> +   uint32_t             size;
>>> +   /**< Backend value to determine if device should be started/stopped. */
>>> +   uint32_t             backend;
>>> +   /**< Vhost header length (varies depending on RX merge buffers. */
>>> +   uint16_t             vhost_hlen;
>>> +   /**< Last index used on the available ring. */
>>> +   volatile uint16_t    last_used_idx;
>>> +   /**< Used for multiple devices reserving buffers. */
>>> +   volatile uint16_t    last_used_idx_res;
>>> +   /**< Currently unused as polling mode is enabled. */
>>> +   eventfd_t            callfd;
>>> +   /**< Used to notify the guest (trigger interrupt). */
>>> +   eventfd_t            kickfd;
>>> +} __rte_cache_aligned;
>>> +
>>> +/**
>>> + * Information relating to memory regions including offsets to
>>> + * addresses in QEMUs memory file.
>>> + */
>>> +struct virtio_memory_regions {
>>> +   /**< Base guest physical address of region. */
>>> +   uint64_t    guest_phys_address;
>>> +   /**< End guest physical address of region. */
>>> +   uint64_t    guest_phys_address_end;
>>> +   /**< Size of region. */
>>> +   uint64_t    memory_size;
>>> +   /**< Base userspace address of region. */
>>> +   uint64_t    userspace_address;
>>> +   /**< Offset of region for address translation. */
>>> +   uint64_t    address_offset;
>>> +};
>>> +
>>> +
>>> +/**
>>> + * Memory structure includes region and mapping information.
>>> + */
>>> +struct virtio_memory {
>>> +   /**< Base QEMU userspace address of the memory file. */
>>> +   uint64_t    base_address;
>>> +   /**< Mapped address of memory file in this process's memory space. */
>>> +   uint64_t    mapped_address;
>>> +   /**< Total size of memory file. */
>>> +   uint64_t    mapped_size;
>>> +   /**< Number of memory regions. */
>>> +   uint32_t    nregions;
>>> +   /**< Memory region information. */
>>> +   struct virtio_memory_regions      regions[0];
>>> +};
>>> +
>>> +/**
>>> + * Device structure contains all configuration information relating to the
>> device.
>>> + */
>>> +struct virtio_net {
>>> +   /**< Contains all virtqueue information. */
>>> +   struct vhost_virtqueue  *virtqueue[VIRTIO_QNUM];
>>> +   /**< QEMU memory and memory region information. */
>>> +   struct virtio_memory    *mem;
>>> +   /**< Negotiated feature set. */
>>> +   uint64_t features;
>>> +   /**< Device identifier. */
>>> +   uint64_t device_fh;
>>> +   /**< Device flags, used to check if device is running on data core. */
>>> +   uint32_t flags;
>>> +   void     *priv;
>>> +} __rte_cache_aligned;
>>> +
>> Above comments of 'vhost_virtqueue', 'struct virtio_memory_regions',
>> 'struct virtio-memory'
>> and 'struct virtio-net' will break API documentation created by Doxygen.
>> Not to break, I guess those comment need to be placed after variable.
> Thanks. I will check doxgen rule. Moved the comment above to avoid 80 
> character limitation warning.
>>> +/**
>>> + * cuse_info is populated and used to register the cuse device.
>>> + * vhost_net_device_ops is passed when the device is registered in main.c.
>>> + */
>>> +int
>>> +rte_vhost_driver_register(const char *dev_name)
>>> +{
>>> +   struct cuse_info cuse_info;
>>> +   char device_name[PATH_MAX] = "";
>>> +   char char_device_name[PATH_MAX] = "";
>>> +   const char *device_argv[] = { device_name };
>>> +
>>> +   char fuse_opt_dummy[] = FUSE_OPT_DUMMY;
>>> +   char fuse_opt_fore[] = FUSE_OPT_FORE;
>>> +   char fuse_opt_nomulti[] = FUSE_OPT_NOMULTI;
>>> +   char *fuse_argv[] = {fuse_opt_dummy, fuse_opt_fore,
>> fuse_opt_nomulti};
>>> +
>>> +   if (access(cuse_device_name, R_OK | W_OK) < 0) {
>>> +           RTE_LOG(ERR, VHOST_CONFIG,
>>> +           "Character device %s can't be accessed, maybe not exist\n",
>>> +           cuse_device_name);
>> Need one more indent?
> Again to avoid 80 char warning for some lengthy RTE_LOG.
>>> +/**
>>> + * Locate the file containing QEMU's memory space and map it to our
>> address space.
>>> + */
>>> +static int
>>> +host_memory_map(struct virtio_net *dev, struct virtio_memory *mem, pid_t
>> pid,
>>> +           uint64_t addr)
>>> +{
>>> +   struct dirent *dptr = NULL;
>>> +   struct procmap procmap;
>>> +   DIR *dp = NULL;
>>> +   int fd;
>>> +   int i;
>>> +   char memfile[PATH_MAX];
>>> +   char mapfile[PATH_MAX];
>>> +   char procdir[PATH_MAX];
>>> +   char resolved_path[PATH_MAX];
>>> +   FILE *fmap;
>>> +   void *map;
>>> +   uint8_t found = 0;
>>> +   char line[BUFSIZE];
>>> +   char dlm[] = "-   :   ";
>>> +   char *str, *sp, *in[PROCMAP_SZ];
>>> +   char *end = NULL;
>>> +
>>> +   /* Path where mem files are located. */
>>> +   snprintf(procdir, PATH_MAX, "/proc/%u/fd/", pid);
>>> +   /* Maps file used to locate mem file. */
>>> +   snprintf(mapfile, PATH_MAX, "/proc/%u/maps", pid);
>>> +
>>> +   fmap = fopen(mapfile, "r");
>>> +   if (fmap == NULL) {
>>> +           RTE_LOG(ERR, VHOST_CONFIG,
>>> +                   "(%"PRIu64") Failed to open maps file for pid %d\n",
>>> +           dev->device_fh, pid);
>>> +           return -1;
>>> +   }
>>> +
>>> +   /* Read through maps file until we find out base_address. */
>>> +   while (fgets(line, BUFSIZE, fmap) != 0) {
>>> +           str = line;
>>> +           errno = 0;
>>> +           /* Split line in to fields. */
>>> +           for (i = 0; i < PROCMAP_SZ; i++) {
>>> +                   in[i] = strtok_r(str, &dlm[i], &sp);
>>> +                   if ((in[i] == NULL) || (errno != 0)) {
>>> +                           fclose(fmap);
>>> +                           return -1;
>>> +                   }
>>> +                   str = NULL;
>>> +           }
>>> +
>>> +           /* Convert/Copy each field as needed. */
>>> +           procmap.va_start = strtoull(in[0], &end, 16);
>>> +           if ((in[0] == '\0') || (end == NULL) || (*end != '\0') ||
>>> +                   (errno != 0)) {
>>> +                   fclose(fmap);
>>> +                   return -1;
>>> +           }
>>> +
>>> +           procmap.len = strtoull(in[1], &end, 16);
>>> +           if ((in[1] == '\0') || (end == NULL) || (*end != '\0') ||
>>> +                   (errno != 0)) {
>>> +                   fclose(fmap);
>>> +                   return -1;
>>> +           }
>>> +
>>> +           procmap.pgoff = strtoull(in[3], &end, 16);
>>> +           if ((in[3] == '\0') || (end == NULL) || (*end != '\0') ||
>>> +                   (errno != 0)) {
>>> +                   fclose(fmap);
>>> +                   return -1;
>>> +           }
>>> +
>>> +           procmap.maj = strtoul(in[4], &end, 16);
>>> +           if ((in[4] == '\0') || (end == NULL) || (*end != '\0') ||
>>> +                   (errno != 0)) {
>>> +                   fclose(fmap);
>>> +                   return -1;
>>> +           }
>>> +
>>> +           procmap.min = strtoul(in[5], &end, 16);
>>> +           if ((in[5] == '\0') || (end == NULL) || (*end != '\0') ||
>>> +                   (errno != 0)) {
>>> +                   fclose(fmap);
>>> +                   return -1;
>>> +           }
>>> +
>>> +           procmap.ino = strtoul(in[6], &end, 16);
>>> +           if ((in[6] == '\0') || (end == NULL) || (*end != '\0') ||
>>> +                   (errno != 0)) {
>>> +                   fclose(fmap);
>>> +                   return -1;
>>> +           }
>>> +
>>> +           memcpy(&procmap.prot, in[2], PROT_SZ);
>>> +           memcpy(&procmap.fname, in[7], PATH_MAX);
>>> +
>>> +           if (procmap.va_start == addr) {
>>> +                   procmap.len = procmap.len - procmap.va_start;
>>> +                   found = 1;
>>> +                   break;
>>> +           }
>>> +   }
>>> +   fclose(fmap);
>>> +
>>> +   if (!found) {
>>> +           RTE_LOG(ERR, VHOST_CONFIG,
>>> +           "(%"PRIu64") Failed to find memory file in pid %d maps file\n",
>>> +           dev->device_fh, pid);
>> Need one more indent?
>>
>>> +/**
>>> + * Searches the configuration core linked list and retrieves the device if 
>>> it
>> exists.
>>> + */
>>> +static struct virtio_net *
>>> +get_device(struct vhost_device_ctx ctx)
>>> +{
>>> +   struct virtio_net_config_ll *ll_dev;
>>> +
>>> +   ll_dev = get_config_ll_entry(ctx);
>>> +
>>> +   /* If a matching entry is found in the linked list, return the device
>>> +   * in that entry. */
>> Need a blank space at start of comment?
>>
>>> +   if (ll_dev)
>>> +           return &ll_dev->dev;
>>> +
>>> +   RTE_LOG(ERR, VHOST_CONFIG,
>>> +           "(%"PRIu64") Device not found in linked list.\n", ctx.fh);
>>> +   return NULL;
>>> +}
>>> +
>>> +/**
>>> + * Add entry containing a device to the device configuration linked list.
>>> + */
>>> +static void
>>> +add_config_ll_entry(struct virtio_net_config_ll *new_ll_dev)
>>> +{
>>> +   struct virtio_net_config_ll *ll_dev = ll_root;
>>> +
>>> +   /* If ll_dev == NULL then this is the first device so go to else */
>>> +   if (ll_dev) {
>>> +           /* If the 1st device_fh != 0 then we insert our device here. */
>>> +           if (ll_dev->dev.device_fh != 0) {
>>> +                   new_ll_dev->dev.device_fh = 0;
>>> +                   new_ll_dev->next = ll_dev;
>>> +                   ll_root = new_ll_dev;
>>> +           } else {
>>> +                   /* Increment through the ll until we find un unused
>>> +                   * device_fh. Insert the device at that entry*/
>> Need a blank space at end of comment?
> Will fix.
>>> +/**
>>> + * Function is called from the CUSE release function. This function will
>> cleanup
>>> + * the device and remove it from device configuration linked list.
>>> + */
>>> +static void
>>> +destroy_device(struct vhost_device_ctx ctx)
>>> +{
>>> +   struct virtio_net_config_ll *ll_dev_cur_ctx, *ll_dev_last = NULL;
>>> +   struct virtio_net_config_ll *ll_dev_cur = ll_root;
>>> +
>>> +   /* Find the linked list entry for the device to be removed. */
>>> +   ll_dev_cur_ctx = get_config_ll_entry(ctx);
>>> +   while (ll_dev_cur != NULL) {
>>> +           /* If the device is found or a device that doesn't exist is
>>> +           * found then it is removed. */
>> Need a blank space?
> Will fix.
>>> +/**
>>> + * Called from CUSE IOCTL: VHOST_SET_FEATURES
>>> + * We receive the negotiated set of features supported by us and the virtio
>>> + * device.
>>> + */
>>> +static int
>>> +set_features(struct vhost_device_ctx ctx, uint64_t *pu)
>>> +{
>>> +   struct virtio_net *dev;
>>> +
>>> +   dev = get_device(ctx);
>>> +   if (dev == NULL)
>>> +           return -1;
>>> +   if (*pu & ~VHOST_FEATURES)
>>> +           return -1;
>>> +
>>> +   /* Store the negotiated feature list for the device. */
>>> +   dev->features = *pu;
>>> +
>>> +   /* Set the vhost_hlen depending on if VIRTIO_NET_F_MRG_RXBUF is set.
>> */
>>> +   if (dev->features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
>>> +           LOG_DEBUG(VHOST_CONFIG,
>>> +           "(%"PRIu64") Mergeable RX buffers enabled\n", dev->device_fh);
>>> +           dev->virtqueue[VIRTIO_RXQ]->vhost_hlen =
>>> +                   sizeof(struct virtio_net_hdr_mrg_rxbuf);
>>> +           dev->virtqueue[VIRTIO_TXQ]->vhost_hlen =
>>> +                   sizeof(struct virtio_net_hdr_mrg_rxbuf);
>> One more indent?
>>
>>> +/**
>>> + * Called from CUSE IOCTL: VHOST_SET_MEM_TABLE
>>> + * This function creates and populates the memory structure for the device.
>>> + * This includes storing offsets used to translate buffer addresses.
>>> + */
>>> +static int
>>> +set_mem_table(struct vhost_device_ctx ctx, const void *mem_regions_addr,
>>> +   uint32_t nregions)
>>> +{
>>> +   struct virtio_net *dev;
>>> +   struct vhost_memory_region *mem_regions;
>>> +   struct virtio_memory *mem;
>>> +   uint64_t size = offsetof(struct vhost_memory, regions);
>>> +   uint32_t regionidx, valid_regions;
>>> +
>>> +   dev = get_device(ctx);
>>> +   if (dev == NULL)
>>> +           return -1;
>>> +
>>> +   if (dev->mem) {
>>> +           munmap((void *)(uintptr_t)dev->mem->mapped_address,
>>> +                   (size_t)dev->mem->mapped_size);
>>> +           free(dev->mem);
>>> +   }
>>> +
>>> +   /* Malloc the memory structure depending on the number of regions. */
>>> +   mem = calloc(1, sizeof(struct virtio_memory) +
>>> +           (sizeof(struct virtio_memory_regions) * nregions));
>>> +   if (mem == NULL) {
>>> +           RTE_LOG(ERR, VHOST_CONFIG,
>>> +                   "(%"PRIu64") Failed to allocate memory for dev-
>>> mem.\n",
>>> +                   dev->device_fh);
>>> +           return -1;
>>> +   }
>>> +
>>> +   mem->nregions = nregions;
>>> +
>>> +   mem_regions = (void *)(uintptr_t)
>>> +           ((uint64_t)(uintptr_t)mem_regions_addr + size);
>>> +
>>> +   for (regionidx = 0; regionidx < mem->nregions; regionidx++) {
>>> +           /* Populate the region structure for each region. */
>>> +           mem->regions[regionidx].guest_phys_address =
>>> +                   mem_regions[regionidx].guest_phys_addr;
>>> +           mem->regions[regionidx].guest_phys_address_end =
>>> +                   mem->regions[regionidx].guest_phys_address +
>>> +                   mem_regions[regionidx].memory_size;
>>> +           mem->regions[regionidx].memory_size =
>>> +                   mem_regions[regionidx].memory_size;
>>> +           mem->regions[regionidx].userspace_address =
>>> +                   mem_regions[regionidx].userspace_addr;
>>> +
>>> +           LOG_DEBUG(VHOST_CONFIG,
>>> +                   "(%"PRIu64") REGION: %u - GPA: %p - QEMU VA: %p -
>> SIZE "
>>> +                   "(%"PRIu64")\n",
>>> +                   dev->device_fh, regionidx,
>>> +                   (void *)(uintptr_t)
>>> +                           mem->regions[regionidx].guest_phys_address,
>>> +                   (void *)(uintptr_t)
>>> +                           mem->regions[regionidx].userspace_address,
>>> +                   mem->regions[regionidx].memory_size);
>>> +
>>> +           /*set the base address mapping*/
>> Need a blank space at start and end of comment?
> Thanks for careful review.
>>> +           if (mem->regions[regionidx].guest_phys_address == 0x0) {
>>> +                   mem->base_address =
>>> +                           mem->regions[regionidx].userspace_address;
>>> +                   /* Map VM memory file */
>>> +                   if (host_memory_map(dev, mem, ctx.pid,
>>> +                           mem->base_address) != 0) {
>>> +                           free(mem);
>>> +                           return -1;
>>> +                   }
>>> +           }
>>> +   }
>>> +
>>> +   /* Check that we have a valid base address. */
>>> +   if (mem->base_address == 0) {
>>> +           RTE_LOG(ERR, VHOST_CONFIG,
>>> +           "(%"PRIu64") Failed to find base address of qemu memory "
>>> +           "file.\n", dev->device_fh);
>> One more indent?
>>
>>> +           free(mem);
>>> +           return -1;
>>> +   }
>>> +
>>> +   /* Check if all of our regions have valid mappings. Usually one does
>>> +   * not exist in the QEMU memory file. */
>> Need a blank space?
>>
>>> +   valid_regions = mem->nregions;
>>> +   for (regionidx = 0; regionidx < mem->nregions; regionidx++) {
>>> +           if ((mem->regions[regionidx].userspace_address <
>>> +                   mem->base_address) ||
>>> +                   (mem->regions[regionidx].userspace_address >
>>> +                           (mem->base_address + mem->mapped_size)))
>>> +                           valid_regions--;
>>> +   }
>>> +
>>> +   /* If a region does not have a valid mapping we rebuild our memory
>>> +   * struct to contain only valid entries. */
>> Need a blank space?
>>> +   if (valid_regions != mem->nregions) {
>>> +           LOG_DEBUG(VHOST_CONFIG,
>>> +           "(%"PRIu64") Not all memory regions exist in the QEMU mem
>> file."
>>> +           "Re-populating mem structure\n",
>> One more indent?
>>
>>> +                   dev->device_fh);
>>> +
>>> +           /* Re-populate the memory structure with only valid regions.
>>> +           * Invalid regions are over-written with memmove. */
>> Need a blank space?
>>
>> Thanks,
>> Tetsuya

Reply via email to