RDMA-Linux-infiniband-подсистема RDMA-анализ исходного кода-архитектура IB-инициализация и регистрация устройства IB-ядро регистрация интерфейса uverbs-механизм кэширования GID
RDMA-Linux-infiniband-подсистема RDMA-анализ исходного кода-архитектура IB-инициализация и регистрация устройства IB-ядро регистрация интерфейса uverbs-механизм кэширования GID

термин

  • Существует 4 типа сетевых ссылок RDMA:
Язык кода:c
копировать
enum {  
    RDMA_NL_IWCM = 2,  
    RDMA_NL_RSVD,  
    RDMA_NL_LS, /* RDMA Local Services */  
    RDMA_NL_NLDEV, /* RDMA device interface */  
    RDMA_NL_NUM_CLIENTS
};
  • подсетьSA/Управление напоминания СМ: InfiniBand Управление подсетями (SA) Услугу предоставляет Управление подсетямиустройство (SM) Предоставляются предопределенные универсальные сервисные прокси. (GSA)。 существовать InfiniBand Конструктивно связь с устройством должна осуществляться через SA Запросите правильный маршрут, чтобы разрешить маршруты к другим хостам.

Введение

Архитектура программного обеспечения ИБ

Адресация/Подсеть

модель управления

IB пять типов передачи и услуг

RXEВведение:

Водитель проходит Linux Реализация сетевого стека InfiniBand RDMA передача инфекции. Он позволяет системам со стандартными адаптерами Ethernet взаимодействовать с RoCE адаптер или запустить RXE Драйвер взаимодействует с другой системой. связанный InfiniBand и RoCE Документация для www.infinibandta.org и www.openfabrics.org скачать. (См. также суу, это iWARP аналогичные программные драйверы. ) Драйвер разделен на два слоя, один из которых Linux RDMA интерфейс стека и реализация команд ядра или пользовательского пространства. API。 глагол пользовательского пространства API Нужно имя по имени librxe Библиотека поддержки, разработанная Universal глагол. пользовательского пространства API libibverbs нагрузка. Еще один слой и первый 3 слоистый Linux интерфейс сетевого стека. Для настройки и использования soft-RoCE драйвер, используйте «Настроить Soft-RoCE (RXE)» ниже. wiki страница:https://github.com/linux-rdma/rdma-core/blob/master/Documentation/rxe.md

Промежуточный уровень программного обеспечения/CM/SA/SMA/PMA/GSI/MAD/QP0_1/SMI

Бит флага возможности управления

Язык кода:c
копировать
/* Management                           0x00000FFF */
#define RDMA_CORE_CAP_IB_MAD            0x00000001
#define RDMA_CORE_CAP_IB_SMI            0x00000002
#define RDMA_CORE_CAP_IB_CM             0x00000004
#define RDMA_CORE_CAP_IW_CM             0x00000008
#define RDMA_CORE_CAP_IB_SA             0x00000010
#define RDMA_CORE_CAP_OPA_MAD           0x00000020

зависимости модуля

rdma_rxe.ko зависит от ib_core.ko, ib_uverbs.ko и других сетевых модулей. Подробнее см.:

Язык кода:c
копировать
drivers/infiniband/Kconfig
# SPDX-License-Identifier: GPL-2.0-only
config RDMA_RXE
	tristate "Software RDMA over Ethernet (RoCE) driver"
	depends on INET && PCI && INFINIBAND   -> Зависит от модулей, связанных с RDMA
	depends on INFINIBAND_VIRT_DMA


Модуль rdma определяется следующим образом:
drivers/infiniband/Kconfig
# SPDX-License-Identifier: GPL-2.0-only
menuconfig INFINIBAND
	tristate "InfiniBand support"
	depends on HAS_IOMEM && HAS_DMA
	depends on NET
	depends on INET
	depends on m || IPV6 != m
	depends on !ALPHA
	select IRQ_POLL
	select DIMLIB
	help
	  Core support for InfiniBand (IB).  Make sure to also select
	  any protocols you wish to use as well as drivers for your
	  InfiniBand hardware.

if INFINIBAND

config INFINIBAND_USER_MAD
	tristate "InfiniBand userspace MAD support"
	depends on INFINIBAND

Управление подсетями

3.7.5.1 Управление подсетями Управление Подсетями фактически делится на Управление подсетямиустройство (SM) Приложения и Управление подсетямиактерское мастерство (SMA)。 Для каждой подсети требуется только одно Управление. подсетями сервера, который может находиться на любом узле, включая коммутаторы и маршрутизаторы. Управление подсетями использует специальный класс управляющих датаграмм. (MAD), известный как Управление пакет данных подсетей (SMP), который направляется в специальную пару очередей (QP0)。 Как показано на картинке 30 Как показано, каждый порт имеет QP0, каждый узел содержит СМА для: • иметь дело с QP0 получено на Get() и Set() SMP • Воля GetResp() SMP отправить QP0 • Воля Trap() SMP отправить QP0 A Управление подсетямиустройство: • ВоляSMP Из QP0 Отправить на QP0 на любой порт • иметь дело сQP0 Все полученные SMP (по SMA узла) иметь дело с СМП кроме)

3.7.5.2 Общие услуги Общие Агент услуг (GSA*) на самом деле состоит из множества агентов управляемых услуг. показано на картинке 31 показано. Некоторые услуги являются дополнительными. Использование общего сервиса называется общим пакетом управления. (GMP) формат сообщения, который представляет собой управляющую дейтаграмму (MAD), обычно направляемый на общий сервисный интерфейс, называемый (GSI) специальная пара очередей (QP1)。 Как показано на картинке 31 Как показано, каждый порт имеет QP1,QP1 все получено на GMP одним из GSA иметь дело с。 GSA Фактически способен предоставлять свои конкретные категории услуг GMP перенаправить на другую пару очередей, позволяя каждому GSA Поддерживайте собственный интерфейс связи

Формат кадра RoCEv2

глаголы виртуализации

Процесс исходного кода

процесс регистрации увербов

Я возьму, например, rdma_rxe.ko:executablemodinfo viewего мирib_coreиib_uverbs

когда Пользовательский режимiproute2/rdmaвыполнение библиотекиrdma link add rxe_ens3 type rxe netdev ens3час

Язык кода:c
копировать
qemu_vm:
/root/project/rdma/iproute2/rdma
gdb --args ./rdma link add rxe_ens3 type rxe netdev ens3
main
filename = basename(argv[0]);
err = rd_init(&rd, filename);
    rd_prepare_msg
err = rd_batch(&rd, batch_file, force)
rd_cmd(&rd, argc, argv)
    rd_exec_cmd
        rd_argv_match
        c->func(rd) -> int cmd_link
            rd_exec_cmd -> link_add
link_add -> link_add_type -> link_add_netdev
    rd_prepare_msg(rd, RDMA_NLDEV_CMD_NEWLINK, &seq, -> to kernel Перейдите в режим ядра через Netlink
    mnl_attr_put_strz(rd->nlh, RDMA_NLDEV_ATTR_DEV_NAME, rd->link_name);
    ...

Динамически загружать модуль rdma_rxe.ko в режиме ядра и загружать его зависимые модули.

Язык кода:c
копировать
kernel: RDMA_NLDEV_CMD_NEWLINK
static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = {
	[RDMA_NLDEV_CMD_GET] = {
		.doit = nldev_get_doit,
		.dump = nldev_get_dumpit,
	},
	[RDMA_NLDEV_CMD_GET_CHARDEV] = {
		.doit = nldev_get_chardev,
	},
	[RDMA_NLDEV_CMD_SET] = {
		.doit = nldev_set_doit,
		.flags = RDMA_NL_ADMIN_PERM,
	},
	[RDMA_NLDEV_CMD_NEWLINK] = {
		.doit = nldev_newlink, -> Согласно команде RDMA_NLDEV_CMD_NEWLINK, отправленной из пользовательского режима, Выполните эту функцию doit
		.flags = RDMA_NL_ADMIN_PERM,
	},

Загрузка модулей и зависимых модулей: MODULE_ALIAS_RDMA_LINK("rxe");

Язык кода:c
копировать
nldev_newlink
    nlmsg_parse_deprecated
    dev_get_by_name
    link_ops_get
    CONFIG_MODULES
    request_module("rdma-link-%s", type) <- #define MODULE_ALIAS_RDMA_LINK(type) MODULE_ALIAS("rdma-link-" type) -> MODULE_ALIAS_RDMA_LINK("rxe"); -> динамическая нагрузка
    ops->newlink(ibdev_name, ndev)

Выполните функции инициализации ib_core (ib_core_init) и ib_uverbs.

Язык кода:c
копировать
drivers/infiniband/core/device.c
fs_initcall(ib_core_init); -> RDMA/core:Воля sysfs Просмотр ввода ограничен init_net, который представляет собой подготовительный патч для использования в существующем пространстве имен. rdma Изоляция оборудования. Первый шаг – сделать rdma оборудованиетолькосуществовать init net Виден в пространстве имен. Последующий патч использования Воля compat ib_core_device устройства/sysfs существует дерево, включено несколько сетевых пространств имен rdma Видимость устройства. Поскольку подсистема IB зависит от сети стек, следовательно, необходимо инициализировать после существования netdev, а поскольку он поддерживает устройства, его необходимо инициализировать до существования подсистемы устройств; Поэтому Воля initcall Порядок изменен на fs_initcall существует, чтобы он был скомпилирован в образ ядра ib_core следуй правильному init заказ
static int __init ib_core_init(void)
    ib_wq = alloc_workqueue("infiniband", 0, 0)
    ib_comp_unbound_wq -> IB/ядро: к новому CQ API Добавить несвязанный WQ Тип, вышестоящий коммит ядра Воля новый, указанный ниже CQ API Рабочая очередь изменена для привязки к конкретному ЦП (вместо несвязанного). Это приводит к появлению новых CQ API Все пользователи используют одну и ту же привязку WQ。 В частности, при привязке к WQ из CPU занят иметь дело с (более высокий приоритет) прерывание, MAD иметь дело с будет сильно задерживаться. Это приводит к Безумный ответ «сердцебиения» дело с задержкой, из-за которой порт неправильно классифицируется как «неработающий». решитьэтотвопрос,пожалуйста Кновыйиз CQ API добавить вновыйиз“Не связан”WQ введите, чтобы пользователь мог выбрать привязку WQ или несвязанный WQ。 для MAD,выбиратьновыйиз“Не связан”WQ
    class_register(&ib_class) -> int class_register(const struct class *cls)
        pr_debug("device class '%s': registering\n", cls->name)
        error = sysfs_create_groups(&cp->subsys.kobj, cls->class_groups)
    rdma_nl_init -> IB/core:существовать netlink информацияиметь дело Избегайте взаимоблокировок во время c, когда не загружается rdmacm модуль, и при получении netlink сообщение, чтобы получить char информацию об устройстве, следующая последовательность вызовов используется для rdma_nl_mutex Выполняет рекурсивную блокировку, вызывая тем самым взаимоблокировку. [..] rdma_nl_rcv() mutex_lock() [..] rdma_nl_rcv_msg() ib_get_client_nl_info() request_module() iw_cm_init() rdma_nl_register() mutex_lock(); <- Тупик, снова получить мьютекс Из-за вышеописанной последовательности вызовов наблюдается следующая трассировка вызовов и взаимоблокировка. Ядро: __mutex_lock+0x35e/0x860 Ядро:? __mutex_lock+0x129/0x860 Ядро:? rdma_nl_register+0x1a/0x90 [ib_core] Ядро: rdma_nl_register+0x1a/0x90 [ib_core] Ядро:? 0xffffffffc029b000 Ядро:iw_cm_init+0x34/0x1000 [iw_cm] Ядро:do_one_initcall+0x67/0x2d4 Ядро:? kmem_cache_alloc_trace+0x1ec/0x2a0 Ядро:do_init_module+0x5a/0x223 Ядро:load_module+0x1998/0x1e10 Ядро:? __symbol_put+0x60/0x60 Ядро:__do_sys_finit_module+0x94/0xe0 Ядро:do_syscall_64+0x5a/0x270 Ядро:entry_SYSCALL_64_after_hwframe+0x49/0xbe Трассировка стека процесса:[<0>] __request_module+0x1c9/0x460 [<0>] ib_get_client_nl _Информация+0x5e/0xb0 [ib_core] [<0>] nldev_get_chardev+0x1ac/0x320 [ib_core] [<0>] rdma_nl_rcv_msg+0xeb/0x1d0 [ib_core] [<0>] rdma_nl_rcv+0xcd/0x120 [ib_core] [<0>] netlink_unicast+0x179 /0x220 [<0>] netlink_sendmsg+0x2f6/0x3f0 [<0>] sock_sendmsg+0x30/0x40 [<0>] ___sys_sendmsg+0x27a/0x290 [<0>] __sys_sendmsg+0x58/0xa0 [<0>] do_syscall_64+0x5a /0x270 [<0>]entry_SYSCALL_64_after_hwframe+0x49/0xbe Чтобы преодолеть этот тупик и позволить множеству netlink Параллелизм сообщений дело с, были реализованы следующие планы. 1. Воля защитить cb_table из блокировки разделены на индексы lock и сделайте его rwlock. Эта блокировка используется для того, чтобы гарантировать, что обратные вызовы не будут выполняться после возврата к отмене регистрации. Поскольку модуль не будет зарегистрирован после выполнения обратного вызова, это позволяет избежать взаимоблокировок. 2. Используйте smp_store_release() для обновления cb_table при регистрации, чтобы не требовалась блокировка. Это позволяет избежать мысли, что все rwsem Все они имеют одинаковый тип замка. lockdep вопрос
        init_rwsem(&rdma_nl_types[idx].sem)
    addr_init -> IB/ядро: Модуль разрешения адресов Воля ИБ интегрирован в ядро, разрешение адресов IB объявлено как модуль (ib_addr.ko), который загружается перед существующим базовым модулем IB (ib_core.ko). Это приводит к тому, что ИБ инициализация ядраизIB netlink не может быть использован в ситуации ib_addr.koиспользоватьиз. чтобы решить эту проблемувопрос,нас Воля ib_addr.ko Преобразовать в IB Часть модуля основная
        alloc_ordered_workqueue("ib_addr", 0)
        register_netevent_notifier(&nb) -> netevent_callback
            NETEVENT_NEIGH_UPDATE
            set_timeout(req, jiffies)
    ib_mad_init
        INIT_LIST_HEAD(&ib_mad_port_list) <- ib_mad_port_open
            list_add_tail(&port_priv->port_list, &ib_mad_port_list)
        ib_register_client(&mad_client)
    ib_sa_init -> Средний основной слой: Средний слой Core , Основные службы включают интерфейс управления (MAD), интерфейс менеджера соединений (CM) и Управление. интерфейс участника подсетей (SA). Должен В стек входятиспользуется для пользовательского режима, приложения ядра и компонента. Основная служба существует, работает в ядре и представляет собой глагол CM. èУправление переводит интерфейс в пользовательский режим -> Нет. 5 глава Конфигурация INFINIBAND Управление подсетямиустройство, все InfiniBand сеть должна работать Управление Подсетями устройство может работать исправно. Даже если две машины не соединены напрямую с помощью переключателя, То же самое. Может быть более одногоиз Управление подсетями устройства. существовать В том случае, когда Лорд Управление Когда один из подсетей выходит из строя, другой выступает в роли подчиненного сетевого менеджера. из системы возьмет на себя управление. большинство InfiniBand Коммутаторы содержат встроенное Управление подсетямиустройство。Однако,еслитебе нуженвозобновлятьиз Управление подсетями устройства, или Если вам нужно больше контроля, используйте Red Hat Enterprise Linux поставлятьиз OpenSM Управление подсетямиустройство        get_random_bytes(&tid, sizeof tid)
        ib_register_client(&sa_client)
        mcast_init -> IB/sa: отслеживание запросов на присоединение/выход из многоадресной рассылки, IB SA ккаждыйпорт Добавлено для многоадресной рассылки базового отслеживания./оставлятьпожалуйстапросить,и не выполняет никакого подсчета ссылок:еслитакой жепортиздвапользовательприсоединитьсятакой же Группа,И в пользователь выходит из группы Должен ,Так SA Воля удаляет порт из группы, даже если один пользователь хочет остаться ее участником. потому чтоэтот,дляподдерживать Приходитьстакой жепортизтакой же Группатранслировать Группаизнесколько пользователей,наснуждатьсяхотетьсуществовать Выполните подсчет ссылок локально。 По этой причине, чтобы ib_sa добавить В подмодуле многоадресной рассылки для выполнения операций присоединения/отключения многоадресной рассылки при подсчете ссылок. Исправлятьib_ipoib(многоадресная рассылкаизуникальный пользователь ядра)киспользоватьновыйинтерфейс
            ib_sa_register_client(&sa_client)
            ib_register_client(&mcast_client) -> mcast_add_one -> InfiniBand Управление подсетями (SA) Услугу предоставляет Управление подсетямиустройство (SM) Предоставляются предопределенные универсальные сервисные прокси. (GSA)。 существовать InfiniBand Конструктивно связь с устройством должна осуществляться через SA Запросите правильный маршрут, чтобы разрешить маршруты к другим хостам.
                rdma_cap_ib_mcast -> rdma_cap_ib_mcast - Проверьте, есть ли порт устройства Infiniband, функция многоадресной рассылки. @device: Чтобы проверить изоборудование @port_num: Чтобы проверить номер экспорта * InfiniBand Многоадресная регистрация лучше, чем обычно IPv4 или IPv6 Регистрация многоадресной рассылки более сложна. Когда каждый адаптер главного канала желает присоединиться к группе многоадресной рассылки, он должен машина с подсетями регистрации. Его следует выполнять только один раз, независимо от того, на сколько пар очередей он подписан в группе. толькосуществоватьдополнительныйприезжать Должен Группаизвсе После отсоединения пар очередей,Должно Долженоставлять Должен Группа。 * Возврат: если порт должен поддерживать SM зарегистрироваться/Отменазарегистрироватьсяки отслеживаниедополнительныйприезжатьмногоадресная рассылка Группаиз Общее количество пар очередейиздополнительные расходы на управление,затем вернись true
                ib_set_client_data(device, &mcast_client, dev)
                INIT_IB_EVENT_HANDLER(&dev->event_handler, device, mcast_event_handler)
                    switch (event->event)
                    mcast_groups_event
                        rb_first
                        rb_next
                        rb_entry
                ib_register_event_handler(&dev->event_handler)
        alloc_ordered_workqueue("ib_nl_sa_wq", WQ_MEM_RECLAIM)
        INIT_DELAYED_WORK(&ib_nl_timed_work, ib_nl_request_timeout) -> ib_nl_request_timeout
            queue_delayed_work(ib_nl_wq, &ib_nl_timed_work, delay)
            ib_sa_disable_local_svc
            send_handler -> callback
    register_blocking_lsm_notifier(&ibdev_lsm_nb) -> LSM: переключитесь на блокировку уведомлений об обновлении политики, атомарные средства обновления политики не очень полезны, поскольку обычно они не могут выполнять обновления политик самостоятельно. потому что Кажется, не строгий в отношении атомарностииз Требовать,потому чтоэтотвыключательприезжать Вариант блокировки。 При этом переименуйте функцию соответствующим образом.
        blocking_notifier_chain_register
    register_pernet_device(&rdma_dev_net_ops)
    nldev_init()
    rdma_nl_register(RDMA_NL_LS, ibnl_ls_cb_table) -> rdma_nl_register(RDMA_NL_NLDEV, nldev_cb_table)
        down_write(&rdma_nl_types[index].sem)
        rdma_nl_types[index].cb_table = NULL
    roce_gid_mgmt_init -> IB/ядро: добавлено RoCE GID Управление таблицами, RoCE GID На основе RDMA (RoCE) оборудованиепорт СвязанныйизкEthernetсетьоборудованиеначальство Конфигурацияиз IP адрес. В настоящее время каждый поддерживаемый RoCE(ocrdma、mlx4) из Драйверы низкого уровня все управляют собой RoCE порт GID поверхность. потому чтоприроданачальство Нетлюбойспецифичный дляпоставщикизсодержание,потому чтоэтотнасверно Что Входить ХОРОШОобобщать,и улучшить RDMA основной GID Кэширование делает свою работу. чтобы заполнить GID Таблица, слушаем события: (a) netdev up/down/change_addr событие - если netdev Строитьсуществоватьнасиз RoCE устройство, нам нужно добавить/удалить его IP。 Это включает в себя добавление этого ndev Связанныйизвсе GID, добавить по умолчанию GID ждать. (b) inet событие - Воляновый ГИД (по данным IP адрес) добавляется в таблицу. для порта RoCE GID таблицу для программирования, поставщик должен реализовать add_gid и del_gid перезвонить. RoCE GID Руководство просит нас существовать GID Далее объявить об ассоциации из net_device。 для управления GID поверхность,этотинформацияданеобходимыйиз。 Например, при удалении net_device час,Его отношения GID Также необходимо удалить. RoCE Требоватьв соответствии с Связанныйсетьоборудованиеиз IPv6 По умолчанию генерируется локальный канал для каждого порта GID。 с обычными IPv6 ссылка местная из GID (поскольку у нас есть IP Генерация адреса GID) Вместо этого, когда устройство выключено, по умолчанию GID Также доступен (для поддержки обратной связи). запираниеиз Вот как это делается:Долженпластырь Исправлять Понятно GID Код таблицы, подходящий для реализации add_gid/del_gid перезвонитьизновый RoCE драйвер и не реализован add_gid/del_gid Обратный звонок когда-то назад RoCE и IB водитель. возобновлятьповерхностьиз Процесс отличается,потому чтоэтотзапирание Требоватьтоже разные。 возобновлять RoCE GID стол, проход mutex_lock(&table->lock) выполнить Для нескольких авторовиз Защищать. Поскольку запись в таблицу требует от нас поиска записи в таблице (возможно, свободной записи), а затем ее изменения, этот мьютекс защищает find_gid и write_gid убеждатьсядействоватьизатомарность。 GID Каждый элемент в кэше подлежит rwlock Защищать. существовать RoCE , написанный (обычно с netdev Порядок уведомления о результатах) с участием поставщиков add_gid и del_gid обратные вызовы, которые могут спать. Таким образом, к каждой записи добавляется недопустимый флаг. RoCE извозобновлятьдапроходить Очередь работ завершенаиз,потому чтоэтот Разрешить спящий режим。 существоватьIBсередина,возобновлятьдасуществоватьwrite_lock_irq(&device->cache.lock)завершено виз,потому чтоэтотwrite_gidНет Разрешить спящий режимиadd_gid/del_gidне будетвызов。 Когда устройство Волясеть входящий/исходящий GID При кэшировании устройство всегда передается в режим удержания. (dev_hold)。 Должен код использовать один рабочий элемент, чтобы возобновить все RDMA оборудование, следуйте netdev или inet Процесс уведомления. Должен патчить Воля кэша с клиента (это да неверно из-за,потому чтодлякэшда IB инфраструктураизчасть)превратился всуществоватьоборудованиезарегистрироваться/удалитьчасявныйинициализация/выпускать, commit: https://github.com/ssbandjl/linux/commit/03db3a2d81e6e84f3ed3cb9e087cae17d762642b, drivers/infiniband/core/cache.c
        gid_cache_wq = alloc_ordered_workqueue("gid-cache-wq", 0) -> сериал
        register_inetaddr_notifier(&nb_inetaddr) -> зарегистрироватьсясетьадрессобытие -> blocking_notifier_chain_register -> Уведомитель «Воля» добавлен в цепочку уведомлений о блокировке @nh: Относится к заголовку цепочки уведомлений о блокировке К и указателю зу. @n:Цепочка уведомленийсерединаизновыйвход Уведомитель «Воля» добавлен в цепочку уведомлений о блокировке。 Должен вызываться в контексте процесса. Возврат от успеха 0, возвращается при ошибке %-EEXIST
            notifier_chain_register(&nh->head, n, unique_priority)
                trace_notifier_register((void *)n->notifier_call)
        register_inet6addr_notifier(&nb_inet6addr)
        register_netdevice_notifier(&nb_netdevice) -> мы полагаемся на netdevice Процесс уведомления Приходитьсистема счислениясерединавсесуществующийизоборудование. Наконец, подпишитесь на это уведомление, чтобы мы ничего не пропустили. IP Добавить/удалить обратные вызовы


IPv4сетьсобытие
static struct notifier_block nb_inetaddr = {
	.notifier_call = inetaddr_event
};
static struct notifier_block nb_inet6addr = {
	.notifier_call = inet6addr_event
};

IPv6сетьсобытие
inetaddr_event
    addr_event(struct notifier_block *this, unsigned long event, struct sockaddr *sa, struct net_device *ndev)
        case NETDEV_UP:
            gid_op = GID_ADD
        case NETDEV_DOWN:
            gid_op = GID_DEL
        INIT_WORK(&work->work, update_gid_event_work_handler)
        rdma_ip2gid(sa, &work->gid)
        queue_work(gid_cache_wq, &work->work) -> портUP/DownчаскуроксобытиеивозобновлятьGID
update_gid_event_work_handler
    ib_enum_all_roce_netdevs(is_eth_port_of_netdev_filter, work->gid_attr.ndev, callback_for_addr_gid_device_scan, work) -> callback_for_addr_gid_device_scan
        update_gid(parsed->gid_op, device, port, &parsed->gid, &parsed->gid_attr)

Выполните ib_uverbs_init

Язык кода:c
копировать
uverbs
module_init(ib_uverbs_init) -> [PATCH] IB uverbs:основнойвыполнить,добавить в InfiniBand глагол пользовательского пространствавыполнитьизосновной,включатьсоздаватьхарактероборудованиеузел、отпользовательраспределение пространствапожалуйстапроситьки Волясобытиеуведомитьпередачаразпользователькосмос -> commit: https://github.com/ssbandjl/linux/commit/bc38a6abdd5a50e007d0fcd9b9b6280132b79e62
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_main.c
    register_chrdev_region(IB_UVERBS_BASE_DEV, infiniband_verbs
    alloc_chrdev_region(&dynamic_uverbs_dev, 0,
    class_register(&uverbs_class)
    class_create_file(&uverbs_class, &class_attr_abi_version.attr);
    ib_register_client(&uverbs_client) -> ib_register_client - зарегистрироваться IB Клиент, @client:Клиент Приходитьзарегистрироваться IB водительизначальствослойпользователь Можеткиспользовать ib_register_client() Приходитьзарегистрироваться IB оборудованиедобавить виудалитьизперезвонить. при добавлении IB оборудованиечас,Волявызов У каждого естьзарегистрироватьсяклиентиз add метод(в соответствии склиентзарегистрироватьсяиззаказ),икогдаудалитьоборудованиечас,Волявызовкаждыйклиентиз remove метод(в соответствии склиентзарегистрироватьсяиз Напротивзаказ)。 Кроме того, при вызове ib_register_client() час,клиент Воляполучатьприезжатьвсеужезарегистрироватьсяоборудованиеиздобавить в обратном вызове
        init_completion(&client->uses_zero)
        assign_client_id(client)
        xa_for_each_marked
            add_client_context(device, client)
                client->add(device) -> ib_uverbs_add_one

Выполните ib_uverbs_add_one

Язык кода:c
копировать
ib_uverbs_add_one  -> РДМА: разрешено ib_client существоватьвызов add() часнеудача,добавить вклиентчас Нетпозволятьнеудача,новсеклиентсуществовать Чтодобавить врутинасередина У всех разныедобрыйпуть отказа。 этотбудет производитьодиндобрый Очень крайнийиз Состояние:добавить вклиентназад,существоватьдобавить впроцесссерединанеудачаи Не установленонабор client_data。 Затем,основной Код по-прежнему будетиспользовать NULL client_data Позвоните другому, чтобы client_data длясередина Сердцеиздействовать,Например remove()、rename()、get_nl_info() и get_net_dev_by_params() - этотдасбивающий с толкуи Несчастный случайиз。 если add() Если обратный вызов завершился неудачно, не вызывайте больше никаких клиентских операций для устройства, даже не удаляйте. существование появляется в обратном вызове операции удаления NULL client_data извсе Проверка избыточности. возобновлятьвсе add() Обратный вызов для правильного возврата кода ошибки. EOPNOTSUPP используется для ULP Не поддерживается ib_device из Состояние - Например,потому чтодляэтотолькоподходящийиспользуется для IB
ссылка: https://www.cnblogs.com/vlhn/p/8301427.html
    device_initialize(&uverbs_dev->dev)
    init_completion(&uverbs_dev->comp)
    uverbs_dev->xrcd_tree = RB_ROOT
    INIT_LIST_HEAD(&uverbs_dev->uverbs_file_list) <- list_add_tail(&file->list, &dev->uverbs_file_list) <- ib_uverbs_open
    ib_uverbs_create_uapi
        uverbs_alloc_api
            uapi_merge_def(uapi, ibdev, uverbs_core_api, false)
                uapi_merge_obj_tree
                    uapi_merge_method
                case UAPI_DEF_WRITE:
		            rc = uapi_create_write(uapi, ibdev, def, cur_obj_key, &cur_method_key);
                        method_elm->handler = def->func_write -> зарегистрироваться Состояние ядраuverbsинтерфейс
    dev_set_name uverbs/xxx
    cdev_init device->ops.mmap ? &uverbs_mmap_fops : &uverbs_fops);
    cdev_device_add
    ib_set_client_data
        xa_store(&device->client_data, client->client_id, data,

Интерфейс Uverbs режима ядра определяется следующим образом:

Язык кода:c
копировать
определение Состояние ядрадля Пользовательский режимиспользоватьизverbsЯдроинтерфейс
drivers/infiniband/core/uverbs_uapi.c
static const struct uapi_definition uverbs_core_api[] = {
	UAPI_DEF_CHAIN(uverbs_def_obj_counters),
	UAPI_DEF_CHAIN(uverbs_def_obj_cq),
	UAPI_DEF_CHAIN(uverbs_def_obj_device),
	UAPI_DEF_CHAIN(uverbs_def_obj_dm),
	UAPI_DEF_CHAIN(uverbs_def_obj_flow_action),
	UAPI_DEF_CHAIN(uverbs_def_obj_intf),
	UAPI_DEF_CHAIN(uverbs_def_obj_mr),
	UAPI_DEF_CHAIN(uverbs_def_write_intf),
	{},
};

rdma user/kernel api/abi:
const struct uapi_definition uverbs_def_write_intf[] = {
    ...
    DECLARE_UVERBS_OBJECT(
    UVERBS_OBJECT_PD,
    DECLARE_UVERBS_WRITE(
        IB_USER_VERBS_CMD_ALLOC_PD,
        ib_uverbs_alloc_pd,
        UAPI_DEF_WRITE_UDATA_IO(struct ib_uverbs_alloc_pd,
                    struct ib_uverbs_alloc_pd_resp),
        UAPI_DEF_METHOD_NEEDS_FN(alloc_pd)),
    DECLARE_UVERBS_WRITE(
        IB_USER_VERBS_CMD_DEALLOC_PD,
        ib_uverbs_dealloc_pd,
        UAPI_DEF_WRITE_I(struct ib_uverbs_dealloc_pd),
        UAPI_DEF_METHOD_NEEDS_FN(dealloc_pd))),
    ...
}
====>
{
    .kind = UAPI_DEF_OBJECT_START, 
    .object_start = { .object_id = UVERBS_OBJECT_PD }, 
},
{ 
    .kind = UAPI_DEF_WRITE, 
    .scope = UAPI_SCOPE_OBJECT, 
    .write = { 
        .is_ex = 0, 
        .command_num = IB_USER_VERBS_CMD_ALLOC_PD 
        }, 
        .func_write = ib_uverbs_alloc_pd,   <- method_elm->handler = def->func_write
        .write.has_resp = 1 + (sizeof(struct { int:(-!!(offsetof(struct ib_uverbs_alloc_pd, response) != 0)); })) + (sizeof(struct { int:(-!!(sizeof(((struct ib_uverbs_alloc_pd *)0)->response) != sizeof(u64))); })), 
        .write.req_size = sizeof(struct ib_uverbs_alloc_pd), .write.resp_size = sizeof(struct ib_uverbs_alloc_pd_resp), 
        .write.has_udata = 1 + (sizeof(struct { int:(-!!(offsetof(struct ib_uverbs_alloc_pd, driver_data) != sizeof(struct ib_uverbs_alloc_pd))); })) + (sizeof(struct { int:(-!!(offsetof(struct ib_uverbs_alloc_pd_resp, driver_data) != sizeof(struct ib_uverbs_alloc_pd_resp))); })), 
},
{ 
    .kind = UAPI_DEF_IS_SUPPORTED_DEV_FN, 
    .scope = UAPI_SCOPE_METHOD, 
    .needs_fn_offset = offsetof(struct ib_device_ops, alloc_pd) + (sizeof(struct { int:(-!!(sizeof(((struct ib_device_ops *)0)->alloc_pd) != sizeof(void *))); })), }, 
{ 
    .kind = UAPI_DEF_WRITE, 
    .scope = UAPI_SCOPE_OBJECT, 
    .write = { 
        .is_ex = 0, 
        .command_num = IB_USER_VERBS_CMD_DEALLOC_PD 
    }, 
    .func_write = ib_uverbs_dealloc_pd, 
    .write.req_size = sizeof(struct ib_uverbs_dealloc_pd), 
},
{ 
    .kind = UAPI_DEF_IS_SUPPORTED_DEV_FN, 
    .scope = UAPI_SCOPE_METHOD, 
    .needs_fn_offset = offsetof(struct ib_device_ops, dealloc_pd) + (sizeof(struct { int:(-!!(sizeof(((struct ib_device_ops *)0)->dealloc_pd) != sizeof(void *))); })), 
}

Продолжить выполнение ХОРОШОновыйучреждатьсоединятьops->newlink(ibdev_name, ndev)

Язык кода:c
копировать
static struct rdma_link_ops rxe_link_ops = {
	.type = "rxe",
	.newlink = rxe_newlink,
};
...
rxe_newlink -> добавить пару RDMA_NLDEV_CMD_NEWLINK/DELLINK информацияизподдерживать,Разрешить динамическое добавление вновыйиз RXE Связь. временночас Устаретьиз Опции модуля
    is_vlan_dev -> RDMA/rxe:предотвращатьсуществовать vlan Создано поверх интерфейса rxe,существовать vlan Создано поверх интерфейса rxe оборудование Волясоздаватьбесполезныйизоборудование,Долженоборудованиеимеет пустойиз gids поверхность,и Нетспособныйиспользуется для rdma cm коммуникация。 Это вызвано enum_all_gids_of_dev_cb()/is_eth_port_of_netdev() серединаизлогически обусловленоиз,Долженлогикатолькоучитыватьсоединятьприезжатьуже Конфигурациясетьоборудованиеиз“начальствослойоборудование”изсеть,привести к vlan интерфейсиз gid набор пуст и попробуйте передать это rdma соединять Невозможно разобрать gid,оборудованиесуществовать cm_init_av_for_response неуспешный. очевидно,выполнитьэтот Поведениеда Чтобы разместить каждогопортсоздавать RoCE оборудованиеиз HW-RoCE оборудование, поэтому RXE из Поведениедолжени HW-RoCE устройства идентичны и создаются только для каждого реального устройства rxe оборудование. чтобы пройти vlan интерфейс для осуществления связи пользователь должен использовать vlan адресиз gid индекс вместо передачи vlan создавать rxe
    rxe_get_dev_from_net
    rxe_net_add
        ib_alloc_device
        rxe_add
            rxe_init -> RDMA/RXE: заменить красно-черное дерево на xarray, текущий драйвер rxe использует красно-черное дерево для добавления индекса в пул объектов rxe. Linux xarrays поставлять Одиндобрыйлучшеизметод Приходитьвыполнитьиндексиз Та же функция。 этотпластырь Воляобъект пулаизкрасное черное деревозаменятьдля xarray。 потому что xarray Спинлок уже есть, используйте его вместо пула rwlock。 убеждаться xarray(index) и kref(ref count) серединаизвсе Изменятьвсекатом Способпроисходить
                rxe_init_device_param
                    rxe->attr.vendor_id			= RXE_VENDOR_ID
                    addrconf_addr_eui48((unsigned char *)&rxe->attr.sys_image_guid -> RDMA/rxe:Воля sys_image_guid Установить в соответствии HW IB Выравнивание устройства, RXE Драйвер не устанавливается sys_image_guid, а приложения пользовательского пространства видят ноль. Это приведет к pyverbs Тест не пройден со следующей трассировкой, потому что IBTA Требования характеристики действительны из sys_image_guid。 Возврат(самый последнийвызовв последний раз):документ“./tests/test_device.py”,Нет. 51 ХОРОШО,существовать test_query_device self.verify_device_attr(attr) документ“./tests/test_device.py”,Нет. 74 ХОРОШО,существовать verify_device_attr среднее утверждение attr.sys_image_guid != 0 Исправьте это, пожалуйста, Воля sys_image_guid установить равным node_guid
                rxe_init_ports -> RDMA/rxe: удалить pkey поверхность,RoCE Требования спецификации RoCE Устройство поддерживает только стандартные pkey。 Однако, rxe Водитель поддерживает 64 сущности pkey поверхность,итолькоиспользовать Нет.одинвход。 удалить pkey таблицу и использовать значение по умолчанию pkey Длина жесткого соединения 1 изповерхность Входить ХОРОШОжестко закодированный。 Воля pkey_table извсе чек на замену на default_pkey из сравнения
                    rxe_init_port_param
                        port->attr.state		= IB_PORT_DOWN
                        ...
                rxe_init_pools
                    rxe_pool_init(rxe, &rxe->uc_pool, RXE_TYPE_UC)
                        pool->rxe		= rxe
                        pool->elem_size		= ALIGN(info->size, RXE_POOL_ALIGN)
                        xa_init_flags(&pool->xa, XA_FLAGS_ALLOC)
                rxe->mcg_tree = RB_ROOT
            rxe_set_mtu
                eth_mtu_int_to_enum
                mtu = mtu ? min_t(enum ib_mtu, mtu, IB_MTU_4096) : IB_MTU_256
            rxe_register_device(rxe, ibdev_name)
                dev->node_type = RDMA_NODE_IB_CA
                ib_set_device_ops(dev, &rxe_dev_ops)
                ib_device_set_netdev(&rxe->ib_dev, rxe->ndev, 1)
                    alloc_port_data
                    add_ndev_hash
                        hash_add_rcu(ndev_hash, &pdata->ndev_hash_link,
                rxe_icrc_init
                    crypto_alloc_shash
                ib_register_device -> зарегистрироватьсяIBоборудование

Процесс регистрации устройства IB (ib_register_device)

Язык кода:c
копировать
drivers/infiniband/core/device.c -> ib_register_device - К IB основнойзарегистрироваться IB оборудование @device:хотетьзарегистрироватьсяизоборудование @name:толькоизхарактернитьоборудованиеимя。 этот Можетспособныйвключать“%”,этот Воляпривести к Волятолькоиндексдобавить вприезжатьпередачаизоборудованиеимясередина. @dma_device:обратитесь к Кподдерживать DMA изоборудованиеизуказатель。 если%NULL,но ВоляиспользоватьIB оборудование. существуют. В этом случае вызывающий абонент должен быть DMA Полностью настроен ibdev。 Обычно это означает использование dma_virt_ops。 Низкоуровневое использование драйверов ib_register_device() Воля Чтооборудованиезарегистрироватьсяприезжать IB Ядро. всезарегистрироватьсяизклиент Все Воляполучатьприезжатьдобавить визкаждыйоборудованиеизперезвонить. @device Необходимо использовать ib_alloc_device() Сделайте распределения. есливодительиспользовать ops.dealloc_driver и асинхронно вызвать любой ib_unregister_device() ,ноодин раз Долженвозврат функции,оборудованиеуказатель Можетспособныйвстречаодеяловыпускать
int ib_register_device(struct ib_device *device, const char *name, struct device *dma_device) -> roceиIBзарегистрироватьсяизflow: https://blog.csdn.net/tiantao2012/article/details/77746141
    assign_name(device, name) -> DMA/устройства: используйте xarray хранить client_data, сейчас существуют у нас небольшой ID, мы можем использовать xarray Вместо линейного поиска в связанном списке для получения данных о клиенте. этот Воляпоставлятьбыстрее и доступнее Расширятьизклиентданныепроверятьпопытаться найти,иделатьнасспособный够Исправлятьзапираниеплан。 потому чтоxarrayМожеткиспользоватьотметкахранить'going_down',потому чтоэтотполностью устраненstruct Значения ib_client_data и Volyaclient_data хранятся непосредственно в существующемxarray. Однако,этот确实нуждатьсяхотетьодинособенныйиз Итерироватьустройство,потому чтодлянасвсе ещедолжен Итерироватьлюбой NULL client_data ценить. также исключен client_data_lock для поддержки внутренних xarray запирание
        dev_set_name
            err = kobject_set_name_vargs(&dev->kobj, fmt, vargs)
        __ib_device_get_by_name <- static DEFINE_XARRAY_FLAGS(devices, XA_FLAGS_ALLOC);
            xa_for_each (&devices, index, device)
    setup_device(device) -> ib_register_device() Выполните несколько шагов выделения и инициализации. Воля Что Расколотьдляменьше、легче читатьизфункция,кудобный В审проверятьиподдерживать -> setup_device() выделять памятьинастраиватьнаборнуждатьсяхотетьвызовоборудованиедействоватьизданные,этотдасуществовать ib_alloc_device Не в период Заканчиватьэтотнекоторыйдействоватьизтолько Оригиналпотому что。 он состоит из ib_dealloc_device() Отменить
        ib_device_check_mandatory -> must option
            IB_MANDATORY_FUNC
            mandatory_table
            IB_MANDATORY_FUNC(query_device),
            ...
        setup_port_data -> RDMA/device:Воля ib_device per_port данныеобъединитьиприезжатьодин Кусочекнабор,Нетпричина Зависит отвернокаждыйпортданные Входить ХОРОШО 3 распределение. Воляэтоих Группаобъединитьсуществоватьодинростиделатьвсе Каждыйпортданныеизжизненный цикли struct ib_device соответствовать. назад续пластырь Волянуждатьсяхотеть Дажемногоспецифичный дляпортизданные,сейчассуществоватьиметьодинхорошийместо Можеткпомещатьнаборэто
            alloc_port_data
                rdma_end_port
                rdma_for_each_port
                    INIT_LIST_HEAD(&pdata->pkey_list)
                    INIT_HLIST_NODE(&pdata->ndev_hash_link)
            rdma_for_each_port
                get_port_immutable -> .get_port_immutable = irdma_roce_port_immutable -> получатьпортинформацияизатвердевать
                    ib_query_port -> Проверьте корректность порта, ли iwarp -> __ib_query_port
                        return device->ops.query_port(device, port_num, port_attr) -> or xtrdma_qeury_port
                            static int irdma_query_port(struct ib_device *ibdev, u32 port,
                                props->max_mtu = IB_MTU_4096
                                props->lid = 1;
                                props->lmc = 0;
                                props->sm_lid = 0;
                                props->sm_sl = 0;
                                props->state = IB_PORT_ACTIVE;
                                ib_get_eth_speed(ibdev, port, &props->active_speed,
                                    rdma_port_get_link_layer -> IB_LINK_LAYER_ETHERNET
                                    ib_device_get_netdev -> RDMA/устройство: Добавить ib_device_set_netdev() как get_netdev иззаменятьплан,Ассоциация netdev действительныйначальствоне должен Должен Очень динамично,потому чтоэтотдлябольшинствоводитель Приходитьобъяснять,Нетпричина Зависит от Входить ХОРОШОэтот Образецизперезвонить. предоставить API Приходитьуведомитьосновнойкодсвязанныйсеть Развивать связи,ииспользоватьосновнойподдерживатьизданныеструктура。 этотделать得основнойкодспособный够Даже加Понятноразвязать ndev связь,отипозволятьодиннекоторыйна основеэтотизновый API。 этоттакжеиспользовать Есть кто-тодобрыйзначениеначальствоиззапирание,Можетмноговодитель Всеиметьсбивающий с толкуиз RCU запирание,или ВОЗНедостаток Неправильныйиззапирание
                                        pdata = &ib_dev->port_data[port]
                                        ib_dev->ops.get_netdev(ib_dev, port) -> mlx5_ib_get_netdev -> IB/mlx5: поддерживается IB оборудованиеизперезвонитькполучать Что netdev,толькоподходящийиспользуется для Eth порт:существовать mlx5_ib_device серединаподдерживатьсетьоборудованиеуказатель,еслисетьоборудованиеи IB оборудование имеет то же самое из PCI отецоборудование,носуществовать NETDEV_REGISTER и NETDEV_UNREGISTER событиечасвозобновлятьэто。 выполнить get_netdev перезвонитьквозвращаться Долженсетьоборудование
                                            mdev = mlx5_ib_get_native_port_mdev(ibdev, port_num, NULL)
                                                mlx5_ib_port_link_layer
                                                mlx5_core_mp_enabled
                                            ndev = mlx5_lag_get_roce_netdev(mdev) -> сеть/mlx5: получить RoCE нетдев, когда LAG Когда активен, IB Водитель использует это для определения IB обязательностьоборудованиеиз netdev。 если режим не поддерживает активное резервное копирование,затем вернись PF0 из netdev;еслимодельда Активное резервное копирование,затем вернисьхозяиндвигатьсяотмашинаиз PF netdev
                                                ldev = mlx5_lag_dev(dev) -> net/mlx5: изменить модель отставания,Lagиспользуется для Волятакой жеHCAиздваPCIФункция Группаобъединить成单индивидуальныйлогика单元。 этотдаосновной Функция,потому чтоэтотдолжно бытьосновнойводительуправлять。 В настоящее время это не так. когданас Воляотстающая структура программного обеспеченияхранилищесуществоватьнижеоборудование Внутричас,Чтожизненный цикл(создавать/разрушать)Зависит от mlx5e Частичное решение. Изменятьвсевесовая модель,делать延迟инижеуровеньводительизжизненный цикл Связанный,и Нетдаи mlx5e Частично связано
                                                ldev && __mlx5_lag_is_roce(ldev)
                                            mlx5_ib_put_native_port_mdev(ibdev, port_num)
                                                mlx5_core_mp_enabled
                                                mpi = ibdev->port[port_num - 1].mp.mpi
                                        rcu_dereference_protected -> rcu_dereference_protected() - когдавозобновлятьодеяло Предотвращатьчасполучать RCU указатель @p:существоватьразвязать除Цитировать Извпередхотетьчитатьизуказатель @c: возникает условие разыменования Возврат указан RCU Защищатьуказательизценить,ноупущение READ_ONCE() 。 этотсуществоватьвозобновлятьблокировка концевого замкауказательценить Изменятьиз Состояние Вниз很иметьиспользовать。 пожалуйста Уведомление,этот Оригинал语Нетвстреча Предотвращать编译устройствоповторитьэтот Цитироватьили Воля Чтои Чтоон Цитировать Группаобъединить,потому чтоэтотне долженсуществовать Не удобнокогдазащита замкаиз Состояние Внизиспользоватьэто。 Должен Функциятолькодлявозобновлятьконециспользовать。 только при условии rcu_read_lock() Защищатьчасиспользоватьэтотфункция Воляпривести кредкийно Нет Очень некрасивоизнеудача
                                            __rcu_dereference_protected
                                        еслинасначинатьпроходитьпредотвращать传транслировать Отменазарегистрироватьсяиз netdev Приходитьускоряться Отменазарегистрироватьсяизскорость
                                    __ethtool_get_link_ksettings -> net: ethtool: добавить вновыйиз ETHTOOL_xLINKSETTINGS API,этотпластырьопределение Понятноновыйиз ETHTOOL_GLINKSETTINGS/SLINKSETTINGS API,Зависит отновыйиз get_link_ksettings/set_link_ksettings Обратный звонок иметь дело с。 этот API поставлятьвернобольшинство Старая версия ethtool_cmd Полеизподдерживать,добавить пару Даже大Связьмодельмаска(большинствомного 4064 Кусочек,переменная длина)изподдерживать,иудалить ethtool_cmd уже Устарелоиз Поле(transceiver/maxrxpkt/maxtxpkt)。 этот API Устаревшая старая версия ETHTOOL_GSET/SSET API,ипоставлятьк Вниз КСвойства пост-совместимости: - приноситьиметь Старая версияводительиз Старая версия ethtool: без изменений, все еще используется get_settings/set_settings перезвонить. - с новым get/set_link_ksettings водительиз Старая версия ethtool:использоватьновыйизводительперезвонить,данныесуществоватьвнутренний Преобразовать в Старая версия ethtool_cmd。 ETHTOOL_GSET Волятольковозвращатьсякаждый Связьмодельмаскаиз Нет.один 32b。 если пользователь попробует Воля ethtool_cmd Устаревшие поля имеют значение «не» 0 (трансивер/maxrxpkt/maxtxpkt), ETHTOOL_SSET Волянеудача。 есливодительнастраиватьнаборвыше Кусочек,нозапишу Ядропредупреждать。 - еще нет Приходитьиз ethtool С устаревшими драйверами: без изменений, все еще используется. get_settings/set_settings перезвонить,внутренний Преобразовать вновыйизданныеструктура。 Не рекомендуетсяиспользоватьиз Поле(transceiver/maxrxpkt/maxtxpkt)Воляигнорируется,А существование считается 0 в пользовательском пространстве. пожалуйста, обрати внимание,“еще нет Приходить”из ethtool инструмент Воля Нетпозволять Изменятьэтотнекоторыйуже Устарелоиз Поле。 - еще нет Приходитьиз ethtool с новымизводитель:прямойвызовновыйизперезвонить. Инструмент «Будущее» смыслда: - Запрос: попробуйте сначала ETHTOOL_GLINKSETTINGS,еслинеудачановосстанавливатьсяприезжать ETHTOOL_GSET - Настройка: сначала запросите и запомните ETHTOOL_GLINKSETTINGS или ETHTOOL_GSET Кому из них это удалось? + если ETHTOOL_GLINKSETTINGS В случае успеха используйте ETHTOOL_SLINKSETTINGS Изменять Конфигурация。 неудачадафинальныйиз(Нетхотетьпытаться ETHTOOL_SSET)。 + в противном случае ETHTOOL_GSET успех, использование ETHTOOL_SSET Изменять Конфигурация。 неудачадафинальныйиз(Нетхотетьпытаться ETHTOOL_SLINKSETTINGS)。 по новому API изинтерактивный пользователь/Ядро首Первыйнуждатьсяхотеть Входить ХОРОШОодинвторой по величинеиз ETHTOOL_GLINKSETTINGS рукопожатие,к就Связьмодель Кусочеккартинаиз Согласен насчет длины.。 если Ядро несогласно с пользователемиз Требовать,это Воля Верните ожидания пользователейиз Кусочеккартинадлинакакотрицательная длина(и cmd Поля 0)。 когда Ядроипользовательсоглашатьсячас,Ядровозвращатьсявсе Полесерединаизэффективныйинформация(即Связьмодельдлина> 0, а cmd — ETHTOOL_GLINKSETTINGS). По пользователям/Ядрограницаизданныеструктураи 32/64 Биты не имеют значения. существоватьвнутренний Преобразовать взаконныйиз Ядро Кусочеккартина。 когда Нет.один“link_settings”водительначинатьвнесейчасчас,внутренний __ethtool_get_settings Программа-помощник ядра Воля постепенно была __ethtool_get_link_ksettings заменять. Местокэтотиндивидуальныйпластырьи Нет Изменятьэто,существоватьнуждатьсяхотеть Изменять Извпередэто Воляодеялоудалить
                                        dev->ethtool_ops->get_link_ksettings(dev, link_ksettings)
                                            cmd->base.duplex = DUPLEX_FULL;
                                    ib_get_width_and_speed -> Получить/вычислить разрядность и скорость сетевой карты RDMA -> RDMA/core:отnetdevполучатьIBширинаискорость,квперед无法проверять询网卡из Количество каналов(lanes ),потому чтоэтоттакой жеизnetdev_speedприобретениеприезжатьзафиксированныйизразрядность и скорость。 вместе с Характеристики сетевой карты более Приходитькрестмного Образец化,этотдобрыйзафиксированныймодельуже经Нет再подходящийиспользовать,потому чтоэтотнуждатьсяхотетьодиндобрыйметод Приходитьв соответствии с Количество каналовполучатьправильныйизширинаискорость。 Этот патч от net_device Поиск netdev рядискорость,и Воля Что Преобразовать в IB разрядность и скорость
                                props->gid_tbl_len = 32;
                                props->pkey_tbl_len = IRDMA_PKEY_TBL_SZ -> 1
                                props->max_msg_sz = iwdev->rf->sc_dev.hw_attrs.max_hw_outbound_msg_size
                            ib_get_cached_subnet_prefix -> IB/core:проходитьчтение кэшаib_query_portсерединаизsubnet_prefix。 ib_query_port() вызов device->ops.query_port() Приходитьполучатьпортсвойство. проверять询методдаспецифичный дляоборудованиеводительиз。 такой жеизфункциявызовdevice->ops.query_gid()ПриходитьполучатьGIDиизвлекатьsubnet_prefix (gid_prefix)。 GID иsubnet_prefix Кэш хранилища существует. ноеслиоборудованиеда Infiniband оборудование,но Нетвстречаоткэшсерединачитатьэтоих。 к Вниз Изменять利использовать Понятнокэшизsubnet_prefix。 RDBMS тестповерхностьяркий,этот Изменятьделать性способныйиметь Понятнозначительно улучшено
                                *sn_pfx = device->port_data[port_num].cache.subnet_prefix;
                    immutable->max_mad_size = IB_MGMT_MAD_SIZE
                verify_immutable -> 校验затвердеватьизпортданные
                    rdma_cap_ib_mad -> rdma_cap_ib_mad - исследоватьоборудованиеизпортданетподдерживать Infiniband Управляйте датаграммами. @device: Чтобы проверить изоборудование @port_num: Чтобы проверить номер экспорта Управление датаграммами (MAD) да InfiniBand спецификацияизнеобходимыйчасть,иквсе InfiniBand оборудованиеподдерживать. OPA интерфейсвозвращатьсяподдерживатьнемного Расширятьиз Версия。 возвращаться:еслипортподдерживатьотправлять/ловитьполучатьMADданные Сумка,затем вернисьtrue
                        device->port_data[port_num].immutable.core_cap_flags & RDMA_CORE_CAP_IB_MAD
                    rdma_max_mad_size -> возвращатьсяэтот RDMA портRequiredизMax MAD размер. @device:оборудование @port_num:порт Число Должен MAD Размер включает в себя MAD заголовок и MAD нагрузка. Никакие другие заголовки не включены. возвращатьсяпортRequiredизMax MAD размер. еслипорт Не поддерживается БЕЗУМНЫЙ, а затем вернуться 0
                         device->port_data[port_num].immutable.max_mad_size
        device->ops.query_device(device, &device->attrs, &uhw) -> irdma_query_device
    ib_cache_setup_one(device) -> Настройте кеш IB(GID) -> IB/ядро: добавлено RoCE GID Управление таблицами, RoCE GID На основе RDMA (RoCE) оборудованиепорт СвязанныйизкEthernetсетьоборудованиеначальство Конфигурацияиз IP адрес. В настоящее время каждый поддерживаемый RoCE(ocrdma、mlx4) из Драйверы низкого уровня все управляют собой RoCE порт GID поверхность. потому чтоприроданачальство Нетлюбойспецифичный дляпоставщикизсодержание,потому чтоэтотнасверно Что Входить ХОРОШОобобщать,и улучшить RDMA основной GID Кэширование делает свою работу. чтобы заполнить GID Таблица, слушаем события: (a) netdev up/down/change_addr событие - если netdev Строитьсуществоватьнасиз RoCE устройство, нам нужно добавить/удалить его IP。 Это включает в себя добавление этого ndev Связанныйизвсе GID, добавить по умолчанию GID ждать. (b) inet событие - Воляновый ГИД (по данным IP адрес) добавляется в таблицу. для порта RoCE GID таблицу для программирования, поставщик должен реализовать add_gid и del_gid перезвонить. RoCE GID Руководство просит нас существовать GID Далее объявить об ассоциации из net_device。 для управления GID поверхность,этотинформацияданеобходимыйиз。 Например, при удалении net_device час,Его отношения GID Также необходимо удалить. RoCE Требоватьв соответствии с Связанныйсетьоборудованиеиз IPv6 По умолчанию генерируется локальный канал для каждого порта GID。 с обычными IPv6 ссылка местная из GID (поскольку у нас есть IP Генерация адреса GID) Вместо этого, когда устройство выключено, по умолчанию GID Также доступен (для поддержки обратной связи). запираниеиз Вот как это делается:Долженпластырь Исправлять Понятно GID Код таблицы, подходящий для реализации add_gid/del_gid перезвонитьизновый RoCE драйвер и не реализован add_gid/del_gid Обратный звонок когда-то назад RoCE и IB водитель. возобновлятьповерхностьиз Процесс отличается,потому чтоэтотзапирание Требоватьтоже разные。 возобновлять RoCE GID стол, проход mutex_lock(&table->lock) выполнить Для нескольких авторовиз Защищать. Поскольку запись в таблицу требует от нас поиска записи в таблице (возможно, свободной записи), а затем ее изменения, этот мьютекс защищает find_gid и write_gid убеждатьсядействоватьизатомарность。 GID Каждый элемент в кэше подлежит rwlock Защищать. существовать RoCE , написанный (обычно с netdev Порядок уведомления о результатах) с участием поставщиков add_gid и del_gid обратные вызовы, которые могут спать. Таким образом, к каждой записи добавляется недопустимый флаг. RoCE извозобновлятьдапроходить Очередь работ завершенаиз,потому чтоэтот Разрешить спящий режим。 существоватьIBсередина,возобновлятьдасуществоватьwrite_lock_irq(&device->cache.lock)завершено виз,потому чтоэтотwrite_gidНет Разрешить спящий режимиadd_gid/del_gidне будетвызов。 Когда устройство Волясеть входящий/исходящий GID При кэшировании устройство всегда передается в режим удержания. (dev_hold)。 Должен код использовать один рабочий элемент, чтобы возобновить все RDMA оборудование, следуйте netdev или inet Процесс уведомления. Должен патчить Воля кэша с клиента (это да неверно из-за,потому чтодлякэшда IB инфраструктураизчасть)превратился всуществоватьоборудованиезарегистрироваться/удалитьчасявныйинициализация/выпускать
        gid_table_setup_one
            _gid_table_setup_one
                struct ib_gid_table *table
                rdma_for_each_port (ib_dev, rdma_port)
                    table = alloc_gid_table(ib_dev->port_data[rdma_port].immutable.gid_tbl_len)
                    gid_table_reserve_default(ib_dev, rdma_port, table)
                        roce_gid_type_mask = roce_gid_type_mask_support(ib_dev, port)
                        num_default_gids = hweight_long(roce_gid_type_mask) -> Вычислить число 1из
                        table->default_gid_indices |= BIT(i)
                    ib_dev->port_data[rdma_port].cache.gid = table -> init gid table
            rdma_roce_rescan_device -> Тяжелыйновыйсканированиесистемасерединаизвсесетьоборудование,ив соответствии снуждатьсяхотеть Воля Что gid Добавить в связанное RoCE оборудование -> {net, IB}/mlx5: Управление несколькими портами RoCE изпортассоциация,вызов mlx5_ib_add час Конечнохотетьдобавить виз mlx5 основнойоборудованиеданетспособный够Входить ХОРОШОпарапорт RoCE действовать. еслида,пожалуйстаиспользовать num_vhca_ports иaffiliate_nic_vport_criteria Функция Конечноэтодахозяиноборудованиевозвращатьсядаотоборудование. если Долженоборудованиедаотродоборудование,пожалуйстапытатьсяпопытаться найтиприезжатьи Его отношенияхозяиноборудование. Можетк Ассоциацияоборудование Воляобщийсистема映像 GUID。 если Не глядяприезжать,пожалуйста Воля Чтопомещать入Нетассоциацияпорт Списокповерхностьсередина. еслипопытаться найтиприезжатьхозяиноборудование,нопроходитьсуществовать NIC vport начальство Вниз文середина Конфигурацияпортотродсвязь Воляпортобязательностьприезжатьэто。 такой же,когдавызов mlx5_ib_remove час Конечнопорттип. еслиэтодаотпорт,но Воля Чтоихозяиноборудование Отменаассоциация,в противном случае Только Воля Чтоот Нетассоциацияпорт Списокповерхностьсерединаудалить Вот и все。 Даже порт Нет.two не может использоваться дляассоциация,IB оборудование Такжезарегистрироватьсядля многихпортоборудование. когда Нет.двапорт稍назад附родчас,долженщеткановый GID кэш才способныйполучатькэшсередина Нет.двапортизпо умолчанию GID。 Экспортroce_rescan_deviceкпоставлятьсуществоватьобязательностьновыйпортназадщеткановыйкэшизмеханизм。 существоватьмногопорт Конфигурациясередина,все IB Объект (QP, MR, PD и т. д.) Соответствующие команды должны проходить через основной сайт. mlx5_core_dev,Чтоон命令долженотправлятьприезжатьотпорт mlx5_core_mdev,предоставитьинтерфейс Приходитьполучать Нет IB вернокак командаизправильный mdev
                ib_enum_roce_netdev pass_all_filter enum_all_gids_of_dev_cb
        rdma_for_each_port
            ib_cache_update -> IB/основной:толькосуществоватьсоответствующийсобытиеначальствовозобновлять PKEY и GID Кэширование, HCA серединаиз PKEY и GID Таблицы могут содержать сотни записей. читатьэтоихдадорогойиз。 часть Оригиналпотому чтодаиспользуется для Поискэтоихиз API Одновременно возвращается только одна запись. этотснаружи,существоватьнекоторыйвыполнитьначальство,Например СХ-3,VF существоватьэтотаспектдапаравиртуализацияиз,идолженполагаться PF драйвер для выполнения чтения. Это снова требует VF приезжать PF изкоммуникация。 IB Core изCache будет соответствии свсесобытие Входить ХОРОШОщеткановый。 потому чтоэтот,в соответствии сполучатьприезжатьизсобытиесоответственнодля IB_EVENT_PKEY_CHANGE и IB_EVENT_GID_CHANGE фильтровать PKEY и GID кэшизщеткановый
                rdma_is_port_valid
                ib_query_port(device, port, tprops)
                rdma_protocol_roce
                config_non_roce_gid_cache(device, port,	tprops) -> IB/основной:РефакторингRoCEизGIDИсправлятькод,кододеяло РефакторингдляRoCEприготовься остаться одномуизфункция,Можетк Выполнять ХОРОШОи Цитироватьсчитать Связанныйизболее сложныйиздействовать,такой жечасвсе еще Держатькодизчитабельность。 Это включает в себя (a) Упростить, чтобы не выполнять IB связьслоистыйсетьоборудованиеисследоватьи Исправлять。 (b) Не добавлять NULL сетьоборудованиеиз RoCE GID вход; Вместо этого возвращается ошибка. (c) если GID Добавить уровень провайдера add_gid() неудача,но Нетхотетьсуществоватькэшсерединадобавить в Долженвходи Держать Долженвходотметкадля INVALID。 (d) Упрощение и повторное использование ib_cache_gid_add()/del() рутина,кудобныйэтоих甚至Можеткиспользуется для Исправлятьпо умолчанию GID。 Это позволяет избежать изменения значения по умолчанию GID часизодиннекоторыйкодповторить。 (e) find_gid() Флаг ввода рутинных справочных данных в Волю GID Ограничено действительными и недействительными GID,и Нетдазависит от GID содержаниеизсвойствоиноль。 (f) gid_table_reserve_default() существоватьнастраиватьнабор GID Время за столом установлено в начале GID Свойства по умолчанию. 无нуждатьсясуществовать write_gid()、add_gid()、del_gid() Используется в функциях низкого уровня default_gid знаки, как они существуют GID поверхностьвозобновлять期между永远Нетнуждатьсяхотетьвозобновлять GID входиз DEFAULT свойство. какэтот Рефакторингизрезультат,бронироватьиз GID 0:0:0:0:0:0:0:0 Больше не доступен для поиска, как описано ниже. в соответствии с IB Каноническая версия 1.3 Нет. 4.1.1 Фестиваль Нет. (6) точка, одноадресная передача GID вход 0:0:0:0:0:0:0:0 дабронировать GID, фрагмент которого выглядит следующим образом. "Одноадресная передача GID адрес 0:0:0:0:0:0:0:0 дабронироватьиз - называемое резервирование GID。это Нет得распространять给любойконецконецпорт。это Нет得использовать作глазотметкаадресили Глобальный заголовок маршрутизации (GRH). " GID поверхностькэшсейчассуществоватьтолькохранилищеэффективныйиз GID вход。 существоватьэтотпластырь Извперед,Можеткиспользовать ib_find_cached_gid_by_port() и Чтоондобрыйпохожийизпроверятьпопытаться найтирутинасуществовать GID Поиск сохранен в таблице GID 0:0:0:0:0:0:0:0。 ноль GID больше не доступен для поиска, поскольку он не должен существовать GRH илизапись путивходсередина,нравиться IB Каноническая версия 1.3 Нет. 4.1.1 Фестиваль Нет. (6) точка、Нет. 12.7.10 Фестивальи Нет. 12.7.20 описано в разделе. ib_cache_update() одеялоупрощатьдляисследоватьсвязьслойодин Второсортный,верновсесвязьслойиспользоватьединыйиззапираниеплан,удалить Прочас gid Логика распределения/освобождения таблиц. этотснаружи,(a) Расширять ib_gid_attr кхранилищепортииндекс,кудобный GID проверять询рутина Можеткотсвойствоструктурасерединаполучатьпортииндексинформация。 (b) Расширять ib_gid_attr хранитьоборудование,кудобныйсуществовать Воля Приходитьизкодсередина,когда Заканчивать GID Цитироватьсчитатьчас,оборудованиеиспользуется длявозвращатьсяприезжать GID поверхностьвход
                    device->ops.query_gid(device, port, i, &gid_attr.gid)
                    rdma_protocol_iwarp(device, port)
                    add_modify_gid(table, &gid_attr)
                ib_query_pkey -> Get P_Key table entry
                    device->ops.query_pkey(device, port_num, index, pkey) -> irdma_query_pkey -> #define IRDMA_DEFAULT_PKEY		0xFFFF
                ib_security_cache_change -> IB/основной:существовать QP применяется на PKey безопасность,добавить вновыйиз LSM Перехватчики для выделения и освобождения контекста безопасности и проверки доступа PKey из Разрешения. создаватьиразрушать QP При выделении и освобождении контекста безопасности. этотначальство Вниз文используется дляконтрольверно PKey из визита. При запросе модификации QP Приходить Изменятьпорт、PKey индексили Альтернативный путьчас,пожалуйстаисследовать QP данет具иметьверно Долженпортподсетьвпередукрашенныйначальствоиз PKey поверхностьиндекссерединаиз PKey из Разрешения. если QP даобщийиз,пожалуйстаубеждаться QP извсе句柄также具иметьдоступ Разрешения。 хранилище QP толькосуществоватьиспользоватьизпорти PKey индекс. Тяжелыйнаборприезжать После инициализации преобразования,пользователь Можеткнезависимый Исправлятьпорт、PKey Индекс и альтернативный путь. потому чтоэтот,порти PKey настраиватьнабор Изменять Можеткда Первыйвпереднастраиватьнабориновыйнастраиватьнаборизобъединитьи。 длясуществовать PKey поверхностьилиподсетьвпередукрашенный Изменятьчас维持доступконтроль,пожалуйстабронироватькаждыйпортначальствоиспользоватькаждый PKey индексизвсе QP из Списокповерхность. еслипроисходить Изменять,ноиспользовать Долженоборудованиеипортизвсе QP Вседолжен强制Выполнять ХОРОШОновыйкэшнастраиватьнабориздоступ Разрешения。 этотнекоторый Изменять Воляделадобавить вприезжать QP В процессе модификации. если Исправлятьнеудача,нодолжен Держатьистарыйпорти PKey индексизассоциация;если Исправлятьуспех,нодолжен Воля Чтоудалить. долженсуществовать Исправлять Извпередучреждать立иновыйпорти PKey индексизассоциация,если Исправлятьнеудачано Воля Чтоудалить. 1. когда QP одеяло Исправлятьдляидентификацияпортчас,PKey индексили Альтернативный путь Воля Должен QP вставлятьприезжатьподходящийкогдаиз Списокповерхностьсередина. 2. исследоватьдоступновыйнастраиватьнабориз Разрешения. 3. еслишаг 2 Предоставьте доступ, затем попробуйте изменить QP。 4a. еслишаг 2 и 3 успех,ноудалитьлюбой Первыйвпередизассоциация。 4b. есликслишкомнеудача,пожалуйстаудалитьновыйизнастраиватьнаборассоциация。 если PKey поверхностьилиподсетьвпередукрашенныйпроисходить Изменять,но Траверс QP Списокповерхностьиисследоватьэтоихданет具иметь Разрешения。 если Нет,но Воля QP отправлятьприезжатьошибкасостояниеивызвать смертельный исходошибкасобытие。 еслиэтодаобщий QP,пожалуйстаубеждатьсяобщий real_qp извсе QP Также имеет разрешения. если иметь безопасную структуруиз QP доступ запрещен,но Безопасностьструктура Воляодеялоотметкадляэтотдобрый,и QP Воляодеялодобавить вприезжать error_list середина. один раз Воля QP Перейдите к завершению ошибки, и флаг безопасной структуры будет очищен. Правильное ведение списка поможет Воля QP Уничтожение конвертируется в транзакцию. оборудованиеизаппаратное обеспечениеводительвыпускать ib_qp структура,потому чтоэтоткогдаразрушатьтолькосуществовать Входить ХОРОШОчас,ib_qp_security структурасерединаиз ib_qp указатель не определен. когдаразрушатьпроцессначинатьчас,ib_qp_security Структура отмечена как положительное существование для разрушения. Это предотвращает QP указательвозьми любойдействовать. QP После успешного уничтожения он все еще может находиться в списке существующих. error_list начальство,ждать Долженпотокиметь дело Это перед чисткой конструкции. еслиразрушатьнеудача,но QP порти PKey настраиватьнабор Воля Тяжелыйновыйвставлятьприезжатьподходящийкогдаиз Списокповерхностьсередина,Знак разрушения Воля убран,и обеспечить контроль доступа,В случае возникновения каких-либо изменений в кэше в процессе существования. Чтобы сохранить изменения безопасности изолированными,использоватьновыйдокумент Приходитьдержатьи Безопасность Связанныйиз Функция
                    list_for_each_entry (pkey, &device->port_data[port_num].pkey_list,
                        check_pkey_qps(pkey, device, port_num, subnet_prefix)
                            ib_get_cached_pkey
                            enforce_qp_pkey_security
                                security_ib_pkey_access -> Check if access to an IB pkey is allowed
                                    return call_int_hook(ib_pkey_access, 0, sec, subnet_prefix, pkey) -> selinux_ib_pkey_access
                                        sel_ib_pkey_sid(subnet_prefix, pkey_val, &sid)
                                        avc_has_perm(sec->sid, sid,
                            qp_to_error(pp->sec)
                                .qp_state = IB_QPS_ERR
                                .event = IB_EVENT_QP_FATAL
                                ib_modify_qp(sec->qp,
                                sec->qp->event_handler(&event,
                            list_del(&pp->to_error_list)
                            complete(&pp->sec->error_complete)
    device->groups[0] = &ib_dev_attr_group; -> RDMA/core:проходитьобычно Группамеханизмсоздаватьоборудование hw_counters,и Нетдавызов device_add_groups() Воля Группадобавить вприезжатьпроходить device_add() управлятьизсуществующий Группачисло Группасередина. этотнуждатьсяхотетьсуществовать device_add() ранее установленный hw_counters,кудобныйэтоотужеразделенныйизпорт sysfs разделить на поток -> Нет.один Группаиспользуется дляоборудованиесвойство,Нет.два Группаиспользуется дляводительпоставлятьизсвойство(Необязательный)。 Нет.три Группада hw_stats этодаодинк NULL окончаниеизчисло Группа
    device->groups[1] = device->ops.device_group;
    ib_setup_device_attrs
        data = alloc_hw_stats_device(ibdev)
        ibdev->ops.get_hw_stats
        sysfs_attr_init(&attr->attr.attr)
        attr->attr.show = hw_stat_device_show
        attr->show = show_hw_stats
        attr->show = show_stats_lifespan;
        attr->attr.store = hw_stat_device_store;
        attr->store = set_stats_lifespan;
    ib_device_register_rdmacg
    rdma_counter_init
    dev_set_uevent_suppress
    ib_setup_port_attrs
    enable_device_and_get
        add_client_context
            client->add(device) -> .add    = ib_uverbs_add_one,
        add_compat_devs(device) -> RDMA/core:существоватьnetпространство именсерединавыполнитьcompat дерево устройств/sysfs,Выборib_coreиз слоя совместимости sysfsвход,кудобный Нетinit_net netпространство иментакже Можеткволосысейчасrdmaоборудование. Каждый не init_net сеть Пространства именсуществоватьвсоздавать Понятно ib_core_device。 этот Образециз ib_core_device sysfs дерево напоминает init_net пространство именсерединапопытаться найтиприезжатьиз rdma оборудование. Это позволяет пройти sysfs входсуществоватьмногоиндивидуальный Нет init_net Найдено в пространстве имен сети rdma оборудование,иверно rdma-core Пользовательское пространство полезно
            add_one_compat_dev
    dev_set_uevent_suppress
    kobject_uevent(&device->dev.kobj, KOBJ_ADD)
    ib_device_put

Перечислить все GID устройства посредством обратного вызова сканирующего устройства (вычислить GID на основе IP и кэшировать GID) (enum_all_gids_of_dev_cb)

Язык кода:c
копировать
проходитьсканированиеоборудованиеизперезвонитьперечислятьоборудованиевсеизGIDs(в соответствии сIP рассчитывает GID,и кэшируйте GID)
static void enum_all_gids_of_dev_cb(struct ib_device *ib_dev, u32 port, struct net_device *rdma_ndev,void *cookie)
    for_each_net(net) -> Два уровня цикла for
        for_each_netdev(net, ndev)
    когда Нетв Вобязательностьмодельчас,фильтридобавить вхозяинсетьоборудованиеизпо умолчанию GID,или ВОЗкогдав Вобязательностьмодельчас,добавить вобязательностьхозяиноборудованиеизпо умолчанию GID
    is_ndev_for_default_gid_filter
        add_default_gids(ib_dev, port, rdma_ndev, ndev) -> ib_cache_gid_set_default_gid
            mask = GID_ATTR_FIND_MASK_GID_TYPE | -> IB/core: исправлены изменения mac адресчасудалитьпо умолчанию GID извопрос,существовать [1] Извперед,когдасетьоборудованиеиз MAC адрес Изменятьчас,по умолчанию GID отвечать Долженодеялоудалитьидобавить враз Приходить,этотбудет нажиматьк Вниззаказ Влияниеузели/илипорт GUID。 netdevice_event() -> NETDEV_CHANGEADDR default_del_cmd() del_netdev_default_ips() bond_delete_netdev_default_gids() ib_cache_gid_set_default_gid() ib_cache_gid_del() add_cmd() [..] нода,существовать Нетобязательностьсценасередина Нетвстречавызов ib_cache_gid_del(), потому что event_ndev и rdma_ndev такой же. потому чтоэтот,ремонтэтотситуация,когдасобытие ndev и rdma_dev такой жечаспренебрегатьисследоватьначальствослойоборудование; Похоже на: bond_set_netdev_default_gids()。 этотремонт ib_cache_gid_del() одеялоправильныйвызов; нода ib_cache_gid_del() попытаться найти Нетприезжатьхотетьудалитьизпо умолчанию GID, потому что find_gid() данный default_gid = false и установить GID_ATTR_FIND_MASK_DEFAULT。 Но тогда это было ib_cache_gid_set_default_gid() крышка,как add_cmd() изчасть。 потому чтоэтот,mac адрес Изменятьв целомподходящийиспользуется дляпо умолчанию GID。 Серия рефакторингов [1],Можетк Обнаружениеприезжатьэтотдобрый Неправильныйиз Поведение。 потому чтоэтот,удалитьпо умолчаниюGIDчас,пожалуйстанастраиватьнаборdefault_gidинастраиватьнаборMASKлоготип. когдаудалитьна основеIPизGIDчас,Прозрачныйdefault_gidинастраиватьнаборMASKлоготип. [1] https://patchwork.kernel.org/patch/10319151/
            for (gid_type = 0; gid_type < IB_GID_TYPE_SIZE; ++gid_type) -> Перебрать 3 типа GID
                if (1UL << gid_type & ~gid_type_mask)
            make_default_gid(ndev, &gid)
                gid->global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL)
                addrconf_ifid_eui48(&gid->raw[8], dev) -> функцияipv6_generate_eui64финальныйвызовaddrconf_ifid_eui48генерироватьадрес.ВоляоборудованиеизMACадресdev_addrизвпередтрииндивидуальный Характер ФестивалькопироватьприезжатьIPv6адресизвторая половина(s6_addr+8)Начало;существоватьловить Вниз Приходитьиз Нет.4и Нет.5индивидуальный Характер Фестивальвдобавить в0xFFи0xFEценить;копироватьMACадресизназадтрииндивидуальный Характер Фестивальприезжатьловить Вниз ПриходитьизIPv6адресиз Нет.6индивидуальный Характер Фестиваль Начало
            __ib_cache_gid_add(ib_dev, port, &gid, &gid_attr, mask, true)
                rdma_is_zero_gid(gid) -> IB/ядро: сократить использование zgid из места,и Нетда开помещатькодирование memcmp() Приходитьисследовать Данныйиз GID да Нет, этоноль,идаиспользовать Вспомогательныйфункция Приходить Выполнять ХОРОШОэтотдействовать,ииспользовать memset заменять memcpy(z,&zgid) из Примеры
                find_gid(table, gid, attr, default_gid, mask, &empty) -> find gid from cache
                add_modify_gid(table, attr)
                    entry = alloc_gid_entry(attr)
                    add_roce_gid(entry)
                        rdma_cap_roce_gid_table
                        attr->device->ops.add_gid(attr, &entry->context) -> mlx5_ib_add_gid
                    store_gid_entry(table, entry)
                        table->data_vec[entry->attr.index] = entry; -> store gid
                dispatch_gid_change_event(ib_dev, port)
                    event.event		= IB_EVENT_GID_CHANGE
                    ib_dispatch_event_clients(&event) -> IB/основной:позволять IB основной Кэш распределениявозобновлятьсобытие глазвперед,когда Низкий уровеньводительуведомить Pkey、GID ипорт Изменятьсобытиечас,этоихвстречав соответствии сзарегистрироватьсяиззаказуведомить给ужезарегистрироватьсяизиметь дело программа. IB основнойи Чтоон УЛП (например, IPoIB) пара GID、LID、Pkey Изменятьсобытиезаинтересованный。 потому что ULP Заканчиватьизвсе GID Запросы делаются IB основнойпоставлять Служить,и IB основной Волякэшвозобновлятьоткладыватьприезжатьоперативная группа Список,потому чтоэтот Чтоонклиентсуществоватьиметь дело с Собственныйизсобытиечас Можетспособныйвстреча看приезжать Проходитьчасизкэшданные。 Например,подизвызов Деревопоказывать Понятно ipoib нравитьсячтосуществоватьвозобновлять WQ серединаизкэшизтакой жечасвызов rdma_query_gid()。 mlx5_ib_handle_event() ib_dispatch_event() ib_cache_event()queue_work() -> кэшвозобновлятьскоростьпомедленнее [..] ipoib_event()queue_work() [..] Работа иметь дело программа ipoib_ib_dev_flush_light() __ipoib_ib_dev_flush() ipoib_dev_addr_changed_valid() rdma_query_gid() <- вернуть старый GID ,кэшеще нетвозобновлять。 Волявсесобытие分派移至оперативная группа Список,кудобный始конецсуществоватьуведомитьлюбойклиент Извперед Заканчиватькэшвозобновлять
                        list_for_each_entry(handler, &event->device->event_handler_list, list)
                            handler->handler(handler, event)
    is_eth_port_of_netdev_filter
        real_dev = rdma_vlan_dev_real_dev(cookie) -> IB/core:удалитьот void приезжать net_device изуказатель Конвертировать,этотпластырьизбегать Понятноот void приезжать net_device из Нетдолженхотетьиздобрыйформа Конвертировать -> IB/основной:для IBoE добавить в VLAN поддержка IBoE добавить в 802.1q VLAN поддерживать. VLAN отметкав соответствии ск Вниз Способкодированиесуществоватьотсвязьместныйадреспроизводнаяиз GID середина: когда GID Включать VLAN Когда, ГИД[11] GID[12] Включать VLAN ID。 данные Сумкаиз 3 битовое поле приоритета пользователя и SL из 3 Кусочектакой же. для rdma_cm Приложение, Условия использования Полеиспользуется дляпрохождения двигаться направо 5 биты для генерации SL поле, тем самым эффективно занимая TOS Полеиз 3 MS Кусочек -> commit: https://github.com/ssbandjl/linux/commit/af7bd463761c6abd8ca8d831f9cc0ac19f3b7d4b
            is_vlan_dev(dev) ? vlan_dev_real_dev(dev) : NULL
                net_device *ret = vlan_dev_priv(dev)->real_dev -> while (is_vlan_dev(ret)) -> Возьмите рекурсивноприезжатьvlanоборудованиеверноотвечатьизреальностьоборудование
        rdma_is_upper_dev_rcu -> IB/core:Воля rdma_is_upper_dev_rcu перейти к головедокумент,Чтобы проверить маршрутизацию,наснуждатьсяхотетьодиндобрый Простойизметод Приходитьисследоватьсетьоборудованиеданетрод Внасиз RDMA оборудование. Воляэтот Вспомогательныйфункцияперейти к головедокументкделатьисследовать Даже容易
            netdev_has_upper_dev_all_rcu -> Check if device is linked to an upper device
                netdev_walk_all_upper_dev_rcu(dev, ____netdev_has_upper_dev,
        is_eth_active_slave_of_bonding_rcu -> IB/ядро: добавленоRoCEповерхностьобязательность(bond)поддерживать,иметь дело собязательностьи ЧтооноборудованиенуждатьсяхотетьнасвсесетьоборудованиеизGID,этотнекоторыйсетьоборудованиедаRoCEпорт Связанныйсетьоборудованиеизначальствослойоборудование. активное резервное копирование Конфигурацияприносить Приходить Понятно Дажемногоиспытание,потому чтодляпо умолчанию GID может толькосуществовать Активностьоборудованиеначальствонастраиватьнабор(этотдадолженхотетьиз,в противном случаетакой жеиз MAC Можеткиспользуется длямногоиндивидуальныйотоборудование, поэтомумногоиндивидуальныйотоборудование Воля具иметьтакой жеиз GID)。 управлятьэтотнекоторый Конфигурациядапроходитьмонитор Приходить Заканчиватьиз: (a) NETDEV_CHANGEUPPER событие (1) если Связь Понятно Связанныйизсетьоборудование,ноудалитьвсе Нет Активностьизотоборудованиепо умолчанию GID идобавить вначальствослойоборудование GID。 (2) если Связанныйсетьоборудование Не связано,ноудалитьвсеначальствослойGID,идобавить впо умолчаниюGID。 (b) NETDEV_BONDING_FAILOVER: (1) от Нет Активностьотстоятьудалитьобязательность GID (2) удалить Нет Активностьотстоятьизпо умолчанию GID (3) Воляобязательность GID добавить вприезжать Активностьотстоять -> struct bonding
            netif_is_bond_master(upper)
            bond_option_active_slave_get_rcu
                rcu_dereference_rtnl(bond->curr_active_slave)
                bond_uses_primary(bond)
    _add_netdev_ips(ib_dev, port, ndev)
        enum_netdev_ipv4_ips(ib_dev, port, ndev) -> Enum IPv4оборудованиеизIPадрес
            __in_dev_get_rcu
            list_add_tail(&entry->list, &sin_list)
            update_gid_ip(GID_ADD, ib_dev, port, ndev, (struct sockaddr *)&sin_iter->ip);
                rdma_ip2gid(addr, &gid) -> IPадресприезжатьGIDиз Конвертироватьалгоритм -> IB/core:verbs/cm структурасерединаизкEthernet L2 свойство,этотпластырьдобавить вверно verbs/cm/cma структурасерединаизкEthernet L2 свойствоизподдерживать. существоватьиметь дело с L2 кEthernetчас,насотвечать Долженкииспользовать IB L2(и L4 PKEY)свойстводобрыйпохожийиз Способиспользовать smac、dmac、vlan ID и приоритет. потому чтоэтот,этотнекоторыйсвойствоодеялодобавить вприезжатьк Внизструктурасередина: * ib_ah_attr - добавить в dmac * ib_qp_attr - добавить в smac и vlan_id,(sl бронировать vlan приоритет) * ib_wc - добавить в smac、vlan_id * ib_sa_path_rec - добавить в smac、dmac、vlan_id * cm_av - добавить в smac и vlan_id длязапись путиструктура,существует Воля Особое внимание уделяется тому, чтобы избежать появления новых полей при упаковке в проволочном формате.,потому чтоэтотнас Нетвстреча破坏 IB CM и SA проводной протокол. существоватьхозяиндвигаться侧,CM заполнен. Его внутренняя структура происходит от ULP поставлятьизпуть。 насдобавить в ETH L2 Недвижимость и Воля их заложили. CM дескриптор адреса (структура cm_av)середина. существоватьодеялодвигаться侧,CM От и REQ информация Ассоциация WC заполнить его внутреннюю структуру. насдобавить вот WC получать ETH L2 свойствоизсодержание。 когдааппаратное обеспечениеводительсуществовать WC серединапоставлятьнеобходимыйиз ETH L2 свойства, они установлены IB_WC_WITH_SMAC и IB_WC_WITH_VLAN логотип. IB основнойкодисследоватьэтотнекоторыйотметка志да Стоит ли сохранятьсуществовать,если Нет,ноот ib_init_ah_from_wc() Вспомогательныйфункция Входить ХОРОШОадресанализировать。 ib_modify_qp_is_ok такжеодеяловозобновлятькучитыватьсвязьслой。 некоторые параметрыдлякEthernetсвязьслойданеобходимыйиз,идляIBПриходитьобъяснятьноне имеющий отношения。 Исправлятьпоставщикводителькподдерживатьновыйизфункциязнак
                    case AF_INET: -> ipv4
                        ipv6_addr_set_v4mapped(((struct sockaddr_in *)addr)->sin_addr.s_addr, (struct in6_addr *)gid)
                            ipv6_addr_set(v4mapped, 0, 0, htonl(0x0000FFFF), addr)
                                __ipv6_addr_set_half(&addr->s6_addr32[0], w1, w2)
                                __ipv6_addr_set_half(&addr->s6_addr32[2], w3, w4)
                    case AF_INET6:
                        *(struct in6_addr *)&gid->raw =	((struct sockaddr_in6 *)addr)->sin6_addr
                update_gid(gid_op, ib_dev, port, &gid, &gid_attr)
                    unsigned long gid_type_mask = roce_gid_type_mask_support(ib_dev, port) -> IB/core:Воляgid_typeдобавить вприезжатьgidсвойствосередина,дляподдерживатьмногодобрыйGIDдобрыйформа,наснуждатьсяхотетьхранилищекаждыйGIDизgid_type。 Это также связано с RoCE v2 Приложение «RoCEv2 порт GID поверхностьвходотвечать具иметьповерхность Показывать L3 адресдобрыйформаиз“GID Тип «свойства» остается неизменным. когдавпередподдерживатьиз GID да IB_GID_TYPE_IB,этоттакжеда RoCE v1 GID тип. это означает gid_type отвечатьдобавить вприезжать roce_gid_table в метаданных
                    ib_cache_gid_add(ib_dev, port, gid, gid_attr) -> .is_supported = &mlx5_rdma_supported,
                        __ib_cache_gid_add
                    or ib_cache_gid_del(ib_dev, port, gid, gid_attr) -> _ib_cache_gid_del
                        find_gid
                        del_gid(ib_dev, port, table, ix) -> del_gid
                            mlx5r_del_gid_macsec_operations -> del flow
                        dispatch_gid_change_event(ib_dev, port)
        enum_netdev_ipv6_ips(ib_dev, port, ndev)
            in6_dev = in6_dev_get(ndev)
            list_add_tail(&entry->list, &sin6_list)
            rdma_ip2gid((struct sockaddr *)&sin6_iter->sin6, &gid)
            update_gid(GID_ADD, ib_dev, port, &gid, &gid_attr)


ucma_copy_iboe_route struct rdma_route -> RDMA/cma: поддержка многопутевой записи netlink Канал, поддерживает прохождение RDMA netlink Каналы получают входящие и исходящие сообщения от сервисов пользовательского пространства. IB Записи пути (и GMP PathRecord)。 этот3индивидуальныйPRсерединаизLIDМожеткэтот Образециспользовать: 1. GMP PR: используется как стандартный локальный/дистанционный идентификатор LID; 2、исходящийPRизDLID:использовать作исходящийпотокколичествоиз“dlid”Поле; 3.ВходящийPRизDLID:использовать作响отвечатьнаправлениеисходящийпотокколичествоиз“dlid”Поле。 этот Образец做изглазиздаподдерживатьсподходящийотвечатьдорога Зависит от。 использоватькогдавпередиз IB дорога Зависит отразвязать决план,когдаданные Сумкаволосывнечас,каждыйглазотметка Всевстречаодеялораспространятьодинзафиксированныйиз DLID,это означает Воляиспользоватьзафиксированныйиздорога Зависит отустройство。 Входящий/исходящийзапись путисерединаиз LID Можетиспользуется для识别позволятьи Другойодинподсеть实体Входить ХОРОШОкоммуникацияиздорога Зависит отустройство Группа。 проходитьэтоих,Приходитьсподсетьмеждусоединятьизданные Сумка Можеткпроходить Должен Группасерединаизлюбойдорога Зависит отустройствоприезжатьдостигатьглазотметка。 как Jason Подтвержденный,когдаотправлять netlink По запросу ядро ​​использует LS_RESOLVE_PATH_USE_ALL чтобы служба знала, что ядро ​​поддерживает несколько PR



IB:адрес Конвертироватьк Воля IP картографированиеприезжать IB адрес (GID),добавить вадрес Конвертировать Служить,использовать IPoIB Воля IP адрескартографированиеприезжать InfiniBand GID адрес
/**
 * struct rdma_dev_addr - Contains resolved RDMA hardware addresses
 * @src_dev_addr:	Source MAC address.
 * @dst_dev_addr:	Destination MAC address.
 * @broadcast:		Broadcast address of the device.
 * @dev_type:		The interface hardware type of the device.
 * @bound_dev_if:	An optional device interface index.
 * @transport:		The transport type used.
 * @net:		Network namespace containing the bound_dev_if net_dev.
 * @sgid_attr:		GID attribute to use for identified SGID
 */
struct rdma_dev_addr {
	unsigned char src_dev_addr[MAX_ADDR_LEN]; -> Исходный MAC(SMAC)
	unsigned char dst_dev_addr[MAX_ADDR_LEN]; -> глазизMAC(DMAC)
	unsigned char broadcast[MAX_ADDR_LEN];
	unsigned short dev_type;
	int bound_dev_if;
	enum rdma_transport_type transport;
	struct net *net;
	const struct ib_gid_attr *sgid_attr;
	enum rdma_network_type network;
	int hoplimit;
};

Разрешение адресов (addr_resolve)

Язык кода:c
копировать
addr_resolve
    rdma_set_src_addr_rcu
    ...
        rdma_translate_ip  -> Translate a local IP address to an RDMA hardware
            dev = dev_get_by_index(dev_addr->net, dev_addr->bound_dev_if) -> IB/addr:Волясетьпространство именкакпараметрпередача,дляib_addrмодульдобавить всетьпространство именподдерживать. дляэтот,всеадресанализироватьи匹配Всеотвечать Должениспользоватьподходящийкогдаизпространство имени Нетда init_net завершить. этотдапроходитьк Вниз Способвыполнитьиз: 1. Воляявныйсетьпространство именпараметрдобавить вприезжатьнуждатьсяхотетьпространство имениз Экспортфункция。 2. Воляпространство имендержатьсуществовать rdma_addr_client структурасередина. 3. вызовсеть Функциячасиспользовать。 длябронироватьвызовмодульиз Поведение,&init_net существовать Чтоонмодульизвызовсерединакакпараметрпередача。 вместе ссуществовать Дажемногоуровеньначальстводобавить впространство именподдерживать,этотсодержаниеужеодеяло Исправлять -> Deprecated for new users, call netdev_get_by_index() instead -> netdev_get_by_index() - проходить ifindex проверятьпопытаться найтиоборудование, @net:подходящийиспользоватьизсетьпространство имен @ifindex:оборудованиеиндекс @tracker:получать Цитироватьизотслеживатьвернослон @gfp:отслеживатьустройствоизфлаг распределения Поиск интерфейса по индексу. еслиеще нетпопытаться найтиприезжатьоборудованиеилиобратитесь к Коборудованиеизуказатель,затем вернись NULL。 возвращатьсяизоборудованиеужедобавить в Цитировать,иуказательда Безопасностьиз,прямойприезжатьпользовательвызов netdev_put() указать, что они закончили использовать его
                dev_get_by_index_rcu(net, ifindex)
                    hlist_for_each_entry_rcu(dev, head, index_hlist)
            rdma_copy_src_l2_addr(dev_addr, dev)
                memcpy(dev_addr->broadcast, dev->broadcast, MAX_ADDR_LEN)
            dev = rdma_find_ndev_for_src_ip_rcu(dev_addr->net, addr)
                switch (src_in->sa_family)
                case AF_INET:
                    __ip_dev_find
                        ifa = inet_lookup_ifaddr_rcu(net, addr)
                            u32 hash = inet_addr_hash(net, addr)
                            net_eq(dev_net(ifa->ifa_dev->dev), net)
                        local = fib_get_table(net, RT_TABLE_LOCAL)
                        fib_table_lookup
                            trace_fib_table_lookup
                case AF_INET6:
                    ipv6_chk_addr -> ipv6_chk_addr_and_flags -> VRF оборудованиеи ip правила в совокупности обеспечивают существование Linux сетькучасерединасоздавать虚拟дорога Зависит отидомен пересылки(Также известен как ВРФ, в частности VRF-lite) из возможностей. одиндобрыйвариант использованиядамногожилецвопрос,вкаждыйжилец Всеиметь Собственныйуникальныйиздорога Зависит отповерхность,и至少нуждатьсяхотеть Неттакой жеизпо умолчаниюшлюз。 проходить Волярозеткаобязательностьприезжать VRF оборудование,Процессы могут быть «осведомлены о VRF». Затем,проходитьрозеткаизданные Сумкаиспользоватьи VRF оборудование Ассоциациядорога Зависит отповерхность. VRF оборудованиевыполнитьизодин Тяжелыйхотетьособенностьдаэтотолько Влияние Нет. 3 слойикначальствослой,потому чтоэтот L2 инструменты (например, LLDP) не затрагиваются (т.е. им не требуется существование каждого VRF вбегаю). Должендизайнвозвращатьсяпозволятьиспользоватьболее высокий приоритетиз IP регулированиено(на основе Стратегияиздорога Зависит от,PBR),к优Первый Вв соответствии снуждатьсяхотетьгидидентификацияпотокколичествоиз VRF оборудованиерегулированиено。 этотснаружи,VRF оборудованиепозволять VRF Вложен в пространство имен существования. Например,сетьпространство именпоставлятьоборудованиеслойсетьинтерфейсизразделение,пространство имен Внутриинтерфейсначальствоиз VLAN поставлять L2 отдельно, а затем VRF оборудованиепоставлять L3 разлука. дизайн VRF оборудованиедапроходить Ассоциациядорога Зависит отповерхностьсоздаватьиз。 Тогда сетевой интерфейс подчиняется VRF оборудование:-> net/ipv6:Изменятьадресисследоватьк始конец采использоватьоборудованиепараметр,ipv6_chk_addr_and_flags Конечноадресданетдаместныйадрес,ки(Необязательный)данетдаидентификацияоборудованиеначальствоизадрес. Например, по ip6_route_info_create вызовэто Приходить Конечно Данныйизшлюзадресданетдаместныйадрес. адресисследоватькогдавперед Нетучитывать L3 домен,потому чтоэтотесли Внизодин Прыжокобратитесь к КНет.два VRF серединаизадрес,но Нетпозволятьсуществоватьодин VRF серединадобавить вдорога Зависит от。 Например, $ ip route add 2001:db8:1::/64 vrf r2 via 2001:db8:102::23 ошибка:шлюзадресневерный。 в 2001:db8:102::23 да vrf r1 серединаинтерфейсначальствоизадрес. ipv6_chk_addr_and_flags нуждатьсяхотетьпозволятьвызов ВОЗ始конец传入приноситьиметь单独параметризоборудование,котказался Воляадреспределдляидентификацияоборудование. Долженоборудованиеиспользуется для Конечнозаинтересованныйиз L3 домен. дляэтот,добавить водинпараметрк Прыжок Проходитьоборудованиеисследоватьивозобновлятьвызов ВОЗк始конецсуществовать Можетспособныйиз Состояние Внизпередачаоборудование,ииспользоватьновыйпараметр Приходитьповерхность Показыватьдоменсерединаизлюбойадрес. использовать NULL dev параметрвозобновлять ipv6_chk_addr из少числопользователь。 этотпластырьиметь дело сверноэтотнекоторыйвызов ВОЗиз Изменять,и无нуждатьсядобавить вдоменисследовать。 ip6_validate_gw Нужно иметь дело с 2 ситуация - одиндобрыйдаоборудованиекак Внизодин Прыжокспецификацияизчастьданный,Другойодиндобрыйдаоборудованиеодеялоанализировать。 по крайней мере там 1 добрый VRF Состояние,Воляисследоватьоткладыватьприезжатьтолькосуществоватьдорога Зависит отпроверятьпопытаться найтиразвязать决Изназад,оборудованиевстречанеудачаивнесейчас Нетпрямойвидизошибка“RTNETLINK Отвечать:Нетприезжатьхозяинмашинаиздорога Зависит от”,и Нетда Первый выбориз“ошибка:шлюз Нетспособныйдаместныйадрес” ”。 “Нетприезжатьхозяинмашинаиздорога Зависит от”ошибкадапотому чтооткатприезжать完整проверятьпопытаться найтиипривести киз。 исследовать两Второсортныйкизбегатьэтотошибка
                        inet6_addr_hash
                        l3mdev_master_dev_rcu
                        ipv6_addr_equal

ссылка

iproute2: https://github.com/ssbandjl/iproute2.git, https://github.com/ssbandjl/MLNX_OFED_SRC-5.9-0.5.6.0/tree/main/SOURCES/mlnx-iproute2-6.0.0

Таблица символов Linux/таблица символов загруженного модуля/драйвера: https://sysprogs.com/VisualKernel/documentation/kernelsymbols/

Загрузка модулей Linux/процесс загрузки модуля: https://www.cnblogs.com/sky-heaven/p/13280255.html, https://www.cnblogs.com/aspirs/p/15522142.html

Сяобин (ssbandjl)

блог: https://cloud.tencent.com/developer/user/5060293/articles | https://logread.cn | https://blog.csdn.net/ssbandjl | https://www.zhihu.com/people/ssbandjl/posts

столбец ДПУ

https://cloud.tencent.com/developer/column/101987

Технические друзья: Друзья, которые интересуются DPU/интеллектуальными сетевыми картами/разгрузкой/сетью, ускорением хранения данных/изоляцией безопасности и другими технологиями, могут присоединиться к группе обмена технологиями DPU.

boy illustration
Углубленный анализ переполнения памяти CUDA: OutOfMemoryError: CUDA не хватает памяти. Попыталась выделить 3,21 Ги Б (GPU 0; всего 8,00 Ги Б).
boy illustration
[Решено] ошибка установки conda. Среда решения: не удалось выполнить первоначальное зависание. Повторная попытка с помощью файла (графическое руководство).
boy illustration
Прочитайте нейросетевую модель Трансформера в одной статье
boy illustration
.ART Теплые зимние предложения уже открыты
boy illustration
Сравнительная таблица описания кодов ошибок Amap
boy illustration
Уведомление о последних правилах Points Mall в декабре 2022 года.
boy illustration
Даже новички могут быстро приступить к работе с легким сервером приложений.
boy illustration
Взгляд на RSAC 2024|Защита конфиденциальности в эпоху больших моделей
boy illustration
Вы используете ИИ каждый день и до сих пор не знаете, как ИИ дает обратную связь? Одна статья для понимания реализации в коде Python общих функций потерь генеративных моделей + анализ принципов расчета.
boy illustration
Используйте (внутренний) почтовый ящик для образовательных учреждений, чтобы использовать Microsoft Family Bucket (1T дискового пространства на одном диске и версию Office 365 для образовательных учреждений)
boy illustration
Руководство по началу работы с оперативным проектом (7) Практическое сочетание оперативного письма — оперативного письма на основе интеллектуальной системы вопросов и ответов службы поддержки клиентов
boy illustration
[docker] Версия сервера «Чтение 3» — создайте свою собственную программу чтения веб-текста
boy illustration
Обзор Cloud-init и этапы создания в рамках PVE
boy illustration
Корпоративные пользователи используют пакет регистрационных ресурсов для регистрации ICP для веб-сайта и активации оплаты WeChat H5 (с кодом платежного узла версии API V3)
boy illustration
Подробное объяснение таких показателей производительности с высоким уровнем параллелизма, как QPS, TPS, RT и пропускная способность.
boy illustration
Удачи в конкурсе Python Essay Challenge, станьте первым, кто испытает новую функцию сообщества [Запускать блоки кода онлайн] и выиграйте множество изысканных подарков!
boy illustration
[Техническая посадка травы] Кровавая рвота и отделка позволяют вам необычным образом ощипывать гусиные перья! Не распространяйте информацию! ! !
boy illustration
[Официальное ограниченное по времени мероприятие] Сейчас ноябрь, напишите и получите приз
boy illustration
Прочтите это в одной статье: Учебник для няни по созданию сервера Huanshou Parlu на базе CVM-сервера.
boy illustration
Cloud Native | Что такое CRD (настраиваемые определения ресурсов) в K8s?
boy illustration
Как использовать Cloudflare CDN для настройки узла (CF самостоятельно выбирает IP) Гонконг, Китай/Азия узел/сводка и рекомендации внутреннего высокоскоростного IP-сегмента
boy illustration
Дополнительные правила вознаграждения амбассадоров акции в марте 2023 г.
boy illustration
Можно ли открыть частный сервер Phantom Beast Palu одним щелчком мыши? Супер простой урок для начинающих! (Прилагается метод обновления сервера)
boy illustration
[Играйте с Phantom Beast Palu] Обновите игровой сервер Phantom Beast Pallu одним щелчком мыши
boy illustration
Maotouhu делится: последний доступный внутри страны адрес склада исходного образа Docker 2024 года (обновлено 1 декабря)
boy illustration
Кодирование Base64 в MultipartFile
boy illustration
5 точек расширения SpringBoot, супер практично!
boy illustration
Глубокое понимание сопоставления индексов Elasticsearch.
boy illustration
15 рекомендуемых платформ разработки с нулевым кодом корпоративного уровня. Всегда найдется та, которая вам понравится.
boy illustration
Аннотация EasyExcel позволяет экспортировать с сохранением двух десятичных знаков.