static int qemu_rdma_broken_ipv6_kernel(Error **errp, struct ibv_context *verbs)

{

    struct ibv_port_attr port_attr;



    /* This bug only exists in linux, to our knowledge. */

#ifdef CONFIG_LINUX



    /* 

     * 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, x;

        struct ibv_device ** dev_list = ibv_get_device_list(&num_devices);

        bool roce_found = false;

        bool ib_found = false;



        for (x = 0; x < num_devices; x++) {

            verbs = ibv_open_device(dev_list[x]);



            if (ibv_query_port(verbs, 1, &port_attr)) {

                ibv_close_device(verbs);

                ERROR(errp, "Could not query initial IB port");

                return -EINVAL;

            }



            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) {

                fprintf(stderr, "WARN: 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.\n");

            } else {

                ERROR(errp, "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 -ENONET;

            }

        }



        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 potential broken kernel;

     */



    /* IB ports start with 1, not 0 */

    if (ibv_query_port(verbs, 1, &port_attr)) {

        ERROR(errp, "Could not query initial IB port");

        return -EINVAL;

    }



    if (port_attr.link_layer == IBV_LINK_LAYER_ETHERNET) {

        ERROR(errp, "Linux kernel's RoCE / iWARP does not support IPv6 "

                    "(but patches on linux-rdma in progress)");

        return -ENONET;

    }



#endif



    return 0;

}

static int qemu_rdma_broken_ipv6_kernel(Error **errp, struct ibv_context *verbs)

{

    struct ibv_port_attr port_attr;



    

#ifdef CONFIG_LINUX



    

















    if (!verbs) {

	    int num_devices, x;

        struct ibv_device ** dev_list = ibv_get_device_list(&num_devices);

        bool roce_found = false;

        bool ib_found = false;



        for (x = 0; x < num_devices; x++) {

            verbs = ibv_open_device(dev_list[x]);



            if (ibv_query_port(verbs, 1, &port_attr)) {

                ibv_close_device(verbs);

                ERROR(errp, "Could not query initial IB port");

                return -EINVAL;

            }



            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) {

                fprintf(stderr, "WARN: 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.\n");

            } else {

                ERROR(errp, "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 -ENONET;

            }

        }



        return 0;

    }



    











    

    if (ibv_query_port(verbs, 1, &port_attr)) {

        ERROR(errp, "Could not query initial IB port");

        return -EINVAL;

    }



    if (port_attr.link_layer == IBV_LINK_LAYER_ETHERNET) {

        ERROR(errp, "Linux kernel's RoCE / iWARP does not support IPv6 "

                    "(but patches on linux-rdma in progress)");

        return -ENONET;

    }



#endif



    return 0;

}

static int FUNC_0(Error **VAR_0, struct ibv_context *VAR_1)

{

    struct ibv_port_attr VAR_2;



    

#ifdef CONFIG_LINUX



    

















    if (!VAR_1) {

	    int num_devices, x;

        struct ibv_device ** dev_list = ibv_get_device_list(&num_devices);

        bool roce_found = false;

        bool ib_found = false;



        for (x = 0; x < num_devices; x++) {

            VAR_1 = ibv_open_device(dev_list[x]);



            if (ibv_query_port(VAR_1, 1, &VAR_2)) {

                ibv_close_device(VAR_1);

                ERROR(VAR_0, "Could not query initial IB port");

                return -EINVAL;

            }



            if (VAR_2.link_layer == IBV_LINK_LAYER_INFINIBAND) {

                ib_found = true;

            } else if (VAR_2.link_layer == IBV_LINK_LAYER_ETHERNET) {

                roce_found = true;

            }



            ibv_close_device(VAR_1);



        }



        if (roce_found) {

            if (ib_found) {

                fprintf(stderr, "WARN: 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.\n");

            } else {

                ERROR(VAR_0, "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 -ENONET;

            }

        }



        return 0;

    }



    











    

    if (ibv_query_port(VAR_1, 1, &VAR_2)) {

        ERROR(VAR_0, "Could not query initial IB port");

        return -EINVAL;

    }



    if (VAR_2.link_layer == IBV_LINK_LAYER_ETHERNET) {

        ERROR(VAR_0, "Linux kernel's RoCE / iWARP does not support IPv6 "

                    "(but patches on linux-rdma in progress)");

        return -ENONET;

    }



#endif



    return 0;

}

static int FUNC_0(Error **VAR_0, struct ibv_context *VAR_1)
{ struct ibv_port_attr VAR_2; #ifdef CONFIG_LINUX
if (!VAR_1) { int num_devices, x; struct ibv_device ** dev_list = ibv_get_device_list(&num_devices); bool roce_found = false; bool ib_found = false; for (x = 0; x < num_devices; x++) { VAR_1 = ibv_open_device(dev_list[x]); if (ibv_query_port(VAR_1, 1, &VAR_2)) { ibv_close_device(VAR_1); ERROR(VAR_0, "Could not query initial IB port"); return -EINVAL; } if (VAR_2.link_layer == IBV_LINK_LAYER_INFINIBAND) { ib_found = true; } else if (VAR_2.link_layer == IBV_LINK_LAYER_ETHERNET) { roce_found = true; } ibv_close_device(VAR_1); } if (roce_found) { if (ib_found) { fprintf(stderr, "WARN: 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.\n"); } else { ERROR(VAR_0, "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 -ENONET; } } return 0; } if (ibv_query_port(VAR_1, 1, &VAR_2)) { ERROR(VAR_0, "Could not query initial IB port"); return -EINVAL; } if (VAR_2.link_layer == IBV_LINK_LAYER_ETHERNET) { ERROR(VAR_0, "Linux kernel's RoCE / iWARP does not support IPv6 "
"(but patches on linux-rdma in progress)"); return -ENONET; } #endif
return 0; }