Hi Fabiano, On Tue, Apr 1, 2025 at 9:32 PM Fabiano Rosas <faro...@suse.de> wrote: > > Jack Wang <jinpu.w...@ionos.com> writes: > > > I hit following error which testing migration in pure RoCE env: > > "-incoming rdma:[::]:8089: RDMA ERROR: You only have RoCE / iWARP devices > > in your > > systems and your management software has specified '[::]', but IPv6 over > > RoCE / > > iWARP is not supported in Linux.#012'." > > > > In our setup, we use rdma bind on ipv6 on target host, while connect from > > source > > with ipv4, remove the qemu_rdma_broken_ipv6_kernel, migration just work > > fine. > > > > Checking the git history, the function was added since introducing of > > rdma migration, which is more than 10 years ago. linux-rdma has > > improved support on RoCE/iWARP for ipv6 over past years. There are a few > > fixes > > back in 2016 seems related to the issue, eg: > > aeb76df46d11 ("IB/core: Set routable RoCE gid type for ipv4/ipv6 networks") > > > > other fixes back in 2018, eg: > > 052eac6eeb56 RDMA/cma: Update RoCE multicast routines to use net namespace > > 8d20a1f0ecd5 RDMA/cma: Fix rdma_cm raw IB path setting for RoCE > > 9327c7afdce3 RDMA/cma: Provide a function to set RoCE path record L2 > > parameters > > 5c181bda77f4 RDMA/cma: Set default GID type as RoCE when resolving RoCE > > route > > 3c7f67d1880d IB/cma: Fix default RoCE type setting > > be1d325a3358 IB/core: Set RoCEv2 MGID according to spec > > 63a5f483af0e IB/cma: Set default gid type to RoCEv2 > > > > So remove the outdated function and it's usage. > > > > Cc: Peter Xu <pet...@redhat.com> > > Cc: Li Zhijian <lizhij...@fujitsu.com> > > Cc: Yu Zhang <yu.zh...@ionos.com> > > Cc: qemu-devel@nongnu.org > > Cc: linux-r...@vger.kernel.org > > Cc: mich...@flatgalaxy.com > > Signed-off-by: Jack Wang <jinpu.w...@ionos.com> > > Tested-by: Li zhijian <lizhij...@fujitsu.com> > > Reviewed-by: Michael Galaxy <mrgal...@nvidia.com> > > --- > > v1: drop RFC, fix build error (zhijian), collect Reviewed-by and Tested-by > > > > migration/rdma.c | 159 ----------------------------------------------- > > 1 file changed, 159 deletions(-) > > > > diff --git a/migration/rdma.c b/migration/rdma.c > > index 76fb0349238a..e228520b8e01 100644 > > --- a/migration/rdma.c > > +++ b/migration/rdma.c > > @@ -767,149 +767,6 @@ static void qemu_rdma_dump_gid(const char *who, > > struct rdma_cm_id *id) > > trace_qemu_rdma_dump_gid(who, sgid, dgid); > > } > > > > -/* > > - * As of now, IPv6 over RoCE / iWARP is not supported by linux. > > - * We will try the next addrinfo struct, and fail if there are > > - * no other valid addresses to bind against. > > - * > > - * If user is listening on '[::]', then we will not have a opened a device > > - * yet and have no way of verifying if the device is RoCE or not. > > - * > > - * In this case, the source VM will throw an error for ALL types of > > - * connections (both IPv4 and IPv6) if the destination machine does not > > have > > - * a regular infiniband network available for use. > > - * > > - * The only way to guarantee that an error is thrown for broken kernels is > > - * for the management software to choose a *specific* interface at bind > > time > > - * and validate what time of hardware it is. > > - * > > - * Unfortunately, this puts the user in a fix: > > - * > > - * If the source VM connects with an IPv4 address without knowing that the > > - * destination has bound to '[::]' the migration will unconditionally fail > > - * unless the management software is explicitly listening on the IPv4 > > - * address while using a RoCE-based device. > > - * > > - * If the source VM connects with an IPv6 address, then we're OK because > > we can > > - * throw an error on the source (and similarly on the destination). > > - * > > - * But in mixed environments, this will be broken for a while until it is > > fixed > > - * inside linux. > > - * > > - * We do provide a *tiny* bit of help in this function: We can list all of > > the > > - * devices in the system and check to see if all the devices are RoCE or > > - * Infiniband. > > - * > > - * If we detect that we have a *pure* RoCE environment, then we can safely > > - * thrown an error even if the management software has specified '[::]' as > > the > > - * bind address. > > - * > > - * However, if there is are multiple hetergeneous devices, then we cannot > > make > > - * this assumption and the user just has to be sure they know what they are > > - * doing. > > - * > > - * Patches are being reviewed on linux-rdma. > > - */ > > -static int qemu_rdma_broken_ipv6_kernel(struct ibv_context *verbs, Error > > **errp) > > -{ > > - /* This bug only exists in linux, to our knowledge. */ > > -#ifdef CONFIG_LINUX > > - struct ibv_port_attr port_attr; > > - > > - /* > > - * Verbs are only NULL if management has bound to '[::]'. > > - * > > - * Let's iterate through all the devices and see if there any pure IB > > - * devices (non-ethernet). > > - * > > - * If not, then we can safely proceed with the migration. > > - * Otherwise, there are no guarantees until the bug is fixed in linux. > > - */ > > - if (!verbs) { > > - int num_devices; > > - struct ibv_device **dev_list = ibv_get_device_list(&num_devices); > > - bool roce_found = false; > > - bool ib_found = false; > > - > > - for (int x = 0; x < num_devices; x++) { > > - verbs = ibv_open_device(dev_list[x]); > > - /* > > - * ibv_open_device() is not documented to set errno. If > > - * it does, it's somebody else's doc bug. If it doesn't, > > - * the use of errno below is wrong. > > - * TODO Find out whether ibv_open_device() sets errno. > > - */ > > - if (!verbs) { > > - if (errno == EPERM) { > > - continue; > > - } else { > > - error_setg_errno(errp, errno, > > - "could not open RDMA device context"); > > - return -1; > > - } > > - } > > - > > - if (ibv_query_port(verbs, 1, &port_attr)) { > > - ibv_close_device(verbs); > > - error_setg(errp, > > - "RDMA ERROR: Could not query initial IB port"); > > - return -1; > > - } > > - > > - if (port_attr.link_layer == IBV_LINK_LAYER_INFINIBAND) { > > - ib_found = true; > > - } else if (port_attr.link_layer == IBV_LINK_LAYER_ETHERNET) { > > - roce_found = true; > > - } > > - > > - ibv_close_device(verbs); > > - > > - } > > - > > - if (roce_found) { > > - if (ib_found) { > > - warn_report("migrations may fail:" > > - " IPv6 over RoCE / iWARP in linux" > > - " is broken. But since you appear to have a" > > - " mixed RoCE / IB environment, be sure to only" > > - " migrate over the IB fabric until the kernel " > > - " fixes the bug."); > > - } else { > > - error_setg(errp, "RDMA ERROR: " > > - "You only have RoCE / iWARP devices in your > > systems" > > - " and your management software has specified > > '[::]'" > > - ", but IPv6 over RoCE / iWARP is not supported > > in Linux."); > > - return -1; > > - } > > - } > > - > > - return 0; > > - } > > - > > - /* > > - * If we have a verbs context, that means that some other than '[::]' > > was > > - * used by the management software for binding. In which case we can > > - * actually warn the user about a potentially broken kernel. > > - */ > > - > > - /* IB ports start with 1, not 0 */ > > - if (ibv_query_port(verbs, 1, &port_attr)) { > > - error_setg(errp, "RDMA ERROR: Could not query initial IB port"); > > - return -1; > > - } > > - > > - if (port_attr.link_layer == IBV_LINK_LAYER_ETHERNET) { > > - error_setg(errp, "RDMA ERROR: " > > - "Linux kernel's RoCE / iWARP does not support IPv6 " > > - "(but patches on linux-rdma in progress)"); > > - return -1; > > - } > > - > > -#endif > > - > > - return 0; > > -} > > - > > /* > > * Figure out which RDMA device corresponds to the requested IP hostname > > * Also create the initial connection manager identifiers for opening > > @@ -955,7 +812,6 @@ static int qemu_rdma_resolve_host(RDMAContext *rdma, > > Error **errp) > > > > /* Try all addresses, saving the first error in @err */ > > for (struct rdma_addrinfo *e = res; e != NULL; e = e->ai_next) { > > - Error **local_errp = err ? NULL : &err; > > > > inet_ntop(e->ai_family, > > &((struct sockaddr_in *) e->ai_dst_addr)->sin_addr, ip, sizeof > > ip); > > @@ -964,13 +820,6 @@ static int qemu_rdma_resolve_host(RDMAContext *rdma, > > Error **errp) > > ret = rdma_resolve_addr(rdma->cm_id, NULL, e->ai_dst_addr, > > RDMA_RESOLVE_TIMEOUT_MS); > > if (ret >= 0) { > > - if (e->ai_family == AF_INET6) { > > - ret = qemu_rdma_broken_ipv6_kernel(rdma->cm_id->verbs, > > - local_errp); > > - if (ret < 0) { > > - continue; > > - } > > - } > > error_free(err); > > err is now unused and should be removed entirely. The comment before the > loop needs touching up as well.
Good catch, will fix both in v2. > > > goto route; > > } > > @@ -2663,7 +2512,6 @@ static int qemu_rdma_dest_init(RDMAContext *rdma, > > Error **errp) > > > > /* Try all addresses, saving the first error in @err */ > > for (e = res; e != NULL; e = e->ai_next) { > > - Error **local_errp = err ? NULL : &err; > > > > inet_ntop(e->ai_family, > > &((struct sockaddr_in *) e->ai_dst_addr)->sin_addr, ip, sizeof > > ip); > > @@ -2672,13 +2520,6 @@ static int qemu_rdma_dest_init(RDMAContext *rdma, > > Error **errp) > > if (ret < 0) { > > continue; > > } > > - if (e->ai_family == AF_INET6) { > > - ret = qemu_rdma_broken_ipv6_kernel(listen_id->verbs, > > - local_errp); > > - if (ret < 0) { > > - continue; > > - } > > - } > > error_free(err); > > Same here. > > > break; > > }