On 17.01.2019 3:25, Ophir Munk wrote: > Hi Ilya, > Thanks for the quick review. > Please find comments inline. > >> -----Original Message----- >> From: Ilya Maximets <i.maxim...@samsung.com> >> Sent: Wednesday, January 16, 2019 5:42 PM >> To: Ophir Munk <ophi...@mellanox.com>; ovs-dev@openvswitch.org; Ian >> Stokes <ian.sto...@intel.com> >> Cc: Asaf Penso <as...@mellanox.com>; Shahaf Shuler >> <shah...@mellanox.com>; Thomas Monjalon <tho...@monjalon.net>; Olga >> Shern <ol...@mellanox.com>; Kevin Traynor <ktray...@redhat.com>; Aaron >> Conole <acon...@redhat.com> >> Subject: Re: [PATCH v5] netdev-dpdk: support port representors >> >> Not a full review. >> Comments inline. >> >> Best regards, Ilya Maximets. >> >>> >>> @@ -1361,12 +1382,32 @@ netdev_dpdk_destruct(struct netdev *netdev) >>> dev->started = false; >>> >>> if (dev->attached) { >>> + /* Retrieve eth device data before closing it. >>> + * FIXME: avoid direct access to DPDK internal array >>> rte_eth_devices. >>> + */ >>> + eth_dev = &rte_eth_devices[dev->port_id]; >>> + uint32_t remove_on_close = >>> + eth_dev->data->dev_flags & RTE_ETH_DEV_CLOSE_REMOVE; >> >> All other variables declared at the start of this function. >> Please, be consistent. >> > > In v6 > >>> + rte_dev = eth_dev->device; >>> + >>> + /* Remove the eth device. */ >>> rte_eth_dev_close(dev->port_id); >>> - rte_eth_dev_info_get(dev->port_id, &dev_info); >>> - if (dev_info.device && !rte_dev_remove(dev_info.device)) { >>> - VLOG_INFO("Device '%s' has been detached", dev->devargs); >>> + >>> + /* Remove this rte device and all its eth devices if flag >>> + * RTE_ETH_DEV_CLOSE_REMOVE is not supported (which means >> representors >>> + * are not supported), or if all the eth devices belonging to the >>> rte >>> + * device are closed. >>> + */ >>> + if (!remove_on_close || !netdev_dpdk_get_num_ports(rte_dev)) { >>> + if (rte_dev_remove(rte_dev) < 0) { >>> + VLOG_ERR("Device '%s' can not be detached", dev->devargs); >>> + } else { >>> + /* Device was closed and detached. */ >>> + VLOG_INFO("Device '%s' has been detached", dev->devargs); >>> + } >>> } else { >>> - VLOG_ERR("Device '%s' can not be detached", dev->devargs); >>> + /* Device was only closed. rte_dev_remove() was not called. */ >>> + VLOG_INFO("Device '%s' has been removed", dev->devargs); >> >> IMHO, this should be printed regardless of detaching. (Before it) >> > > As I suggested to Kevin in a recent review - "Device has been detached" was > changed to "Device has been removed and detached". > This will accurately reflect the operations on the device. > >>> + >>> +static int >>> +netdev_dpdk_check_dup_dev(dpdk_port_t port_id, struct netdev *netdev, >>> + const char *devargs, char **errp) { >> >> OVS_REQUIRES(dpdk_mutex) >> >> Also, the '{' should be on a new line in function definitions. >> > > This function is removed in v6 > >>> + struct netdev_dpdk *dup_dev; >>> + >>> + dup_dev = netdev_dpdk_lookup_by_port_id(port_id); >>> + if (dup_dev) { >>> + VLOG_WARN_BUF(errp, "'%s' is trying to use device '%s' " >>> + "which is already in use by '%s'", >>> + netdev_get_name(netdev), devargs, >>> + netdev_get_name(&dup_dev->up)); >>> + return EADDRINUSE; >>> + } >>> + return 0; >> >> Indents are off in the previous 3 lines. >> > > In v6 > >>> +} >>> + >>> /* >>> - * Normally, a PCI id is enough for identifying a specific DPDK port. >>> + * Normally, a PCI id (optionally followed by a representor number) >>> + * is enough for identifying a specific DPDK port. >>> * However, for some NICs having multiple ports sharing the same PCI >>> * id, using PCI id won't work then. >>> * >>> @@ -1641,32 +1728,35 @@ netdev_dpdk_get_port_by_mac(const char >> *mac_str) >>> * >>> * Note that the compatibility is fully kept: user can still use the >>> * PCI id for adding ports (when it's enough for them). >>> + * >>> + * In order to avoid clang errors add OVS_REQUIRES(dpdk_mutex) to >>> + this function >>> + * since it is required by netdev_dpdk_lookup_by_port_id() while the >>> + dpdk_mutex >>> + * is taken outside of this function. >> >> Agree with Aaron that the comment is not needed. >> > > Comment removed in v6 > >>> */ >>> static dpdk_port_t >>> netdev_dpdk_process_devargs(struct netdev_dpdk *dev, >>> const char *devargs, char **errp) >>> + OVS_REQUIRES(dpdk_mutex) >>> { >>> - char *name; >>> dpdk_port_t new_port_id = DPDK_ETH_PORT_ID_INVALID; >>> >>> if (strncmp(devargs, "class=eth,mac=", 14) == 0) { >>> new_port_id = netdev_dpdk_get_port_by_mac(&devargs[14]); >>> } else { >>> - name = xmemdup0(devargs, strcspn(devargs, ",")); >>> - if (rte_eth_dev_get_port_by_name(name, &new_port_id) >>> - || !rte_eth_dev_is_valid_port(new_port_id)) { >>> - /* Device not found in DPDK, attempt to attach it */ >>> - if (!rte_dev_probe(devargs) >>> - && !rte_eth_dev_get_port_by_name(name, &new_port_id)) { >>> - /* Attach successful */ >>> - dev->attached = true; >>> - VLOG_INFO("Device '%s' attached to DPDK", devargs); >>> + new_port_id = netdev_dpdk_probe_port_by_devargs(devargs); >>> + if (!rte_eth_dev_is_valid_port(new_port_id)) { >>> + new_port_id = DPDK_ETH_PORT_ID_INVALID; >>> + } else { >>> + if (netdev_dpdk_check_dup_dev(new_port_id, &dev->up, >>> + devargs, errp)) { >>> + new_port_id = DPDK_ETH_PORT_ID_INVALID; >> >> Still don't understand why you need to check duplicated ports twice. >> Upper layer should handle this case. >> Also, indents are off. > > Duplicate check is removed in v6 > >>> +1846,9 @@ netdev_dpdk_set_config(struct netdev *netdev, const struct >> smap *args, >>> /* Already configured, do not reconfigure again */ >>> err = 0; >>> } else { >>> - struct netdev_dpdk *dup_dev; >>> - >>> - dup_dev = netdev_dpdk_lookup_by_port_id(new_port_id); >>> - if (dup_dev) { >>> - VLOG_WARN_BUF(errp, "'%s' is trying to use device '%s' >>> " >>> - "which is already in use by '%s'", >>> - netdev_get_name(netdev), new_devargs, >>> - netdev_get_name(&dup_dev->up)); >>> - err = EADDRINUSE; >>> - } else { >>> + err = netdev_dpdk_check_dup_dev(new_port_id, netdev, >>> + new_devargs, errp); >> >> Indents off. >> It's better to be: >> >> err = netdev_dpdk_check_dup_dev(new_port_id, netdev, >> new_devargs, errp); >> > > In v6 this function call is replaced by the function contents. > >>> @@ -3253,15 +3342,26 @@ netdev_dpdk_detach(struct unixctl_conn *conn, >> int argc OVS_UNUSED, >>> goto error; >>> } >>> >>> - rte_eth_dev_close(port_id); >>> + /* FIXME: avoid direct access to DPDK internal array rte_eth_devices. >>> */ >>> + eth_dev = &rte_eth_devices[port_id]; >>> + rte_dev = eth_dev->device; >>> + >>> + if ((eth_dev->data->dev_flags & RTE_ETH_DEV_CLOSE_REMOVE) && >>> + (netdev_dpdk_get_num_ports(rte_dev) > 1)) { > > This line requires a fix. It should be ">=1" instead of ">1".
But current device is not closed yet. It'll be counted by netdev_dpdk_get_num_ports(). > The two lines above are rewritten in v6. > >> >> We still need to close the port here because if you'll have 2 sibling ports >> you'll >> not be able do detach any of them because another one still open. >> >> Anyway, Logic seems wrong here. >> > > I will try to explain the logic > >> The function intended to detach pci devices. And the usecase is detaching >> devices that was added by the whitelist and not attached in >> 'netdev_dpdk_process_devargs', i.e. has 'dev->attached = false'. >> > > Correct > >> The workflow should be: >> >> * Iterate over all the siblings of the desired device. >> * if port_id still used by OVS (netdev_dpdk_lookup_by_port_id(port_id) >> != >> NULL) >> print "Device '%s' is being used by interface '%s'. Remove it >> before >> detaching" >> > > For PMDs not supporting representors the code is backward compatible with > previous versions. > For PMDs supporting representors and in cases we have dozens of multi-ports > (representors/interfaces) - is it desirable to print dozens of such messages? > The current patch suggests one message for all cases: > "Device '%s' is being shared with other interfaces. Remove them before > detaching.", > IMHO, I would leave it this way for this patch. If you still think it is > useful to have a message per interface - I suggest adding it in a follow up > patch. > What do you think? This function used only in manual appctl command. It's not an issue to have a big output. By the way, you may collect all the port names and print like this: struct netdev_dpdk *dev; struct ds used_interfaces = DS_EMPTY_INITIALIZER; bool used = false; ds_put_format(&used_interfaces, "Device '%s' is being used by following interfaces:", argv[1]); FOR_EACH_SIBLING (&port_id) { dev = netdev_dpdk_lookup_by_port_id(port_id); if (dev) { used = true; ds_put_format(&used_interfaces, " %s", netdev_get_name(&dev->up)); } } if (used) { ds_put_cstr(&used_interfaces, ". Remove them before detaching."); response = ds_steal_cstr(&used_interfaces); ds_destroy(&used_interfaces); goto error; } ds_destroy(&used_interfaces); > >> * If some ports are still used by OVS >> return >> >> * If none of the ports still used by OVS >> Iterate over all the siblings and close them. >> (rte_eth_dev_close(port_id)) >> Try to remove the device. (rte_dev_remove(rte_dev)) > > The responsibility for closing all eth devices before detaching the rte > device should be embedded in the rte_dev_remove() call itself. > In other words, when calling rte_dev_remove() - all opened eth devices should > be automatically closed and then the rte device should be unplugged/detached. > It requires a PMD supporting representors to implement the remove() callback > as part of struct rte_pci_driver. > Hence, if none of the sibling ports is used by OVS - it is sufficient to call > rte_dev_remove(rte_dev) and there is no need to iterate over all the siblings > and close them. > _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev