Изменяемые свойства QP описывают свойства отправки и получения QP. В QP UC и RC это означает подключение QP к удаленному QP. В Infiniband необходимо выполнить запрос пути у администратора подсети (SA), чтобы определить, какие свойства должен быть настроен для QP, или в качестве лучшего решения используйте Communications Manager (CM) или общий агент CM RDMA (CMA) для подключения к КП. Однако некоторые приложения (например, ceph) предпочитают сами подключаться к QP и обмениваться данными через сокет, чтобы решить, какие свойства QP использовать. В RoCE GRH должен быть настроен в свойствах QP подключенного QP или в дескрипторе адреса UD QP. В iWARP для подключения к QP следует использовать только общий агент CM RDMA (CMA). Структура: struct ibv_qp_attr описывает атрибуты очереди к QP:
struct ibv_qp_attr {
enum ibv_qp_state qp_state;
enum ibv_qp_state cur_qp_state;
enum ibv_mtu path_mtu;
enum ibv_mig_state path_mig_state;
uint32_t qkey;
uint32_t rq_psn;
uint32_t sq_psn;
uint32_t dest_qp_num;
unsigned int qp_access_flags;
struct ibv_qp_cap cap;
struct ibv_ah_attr ah_attr;
struct ibv_ah_attr alt_ah_attr;
uint16_t pkey_index;
uint16_t alt_pkey_index;
uint8_t en_sqd_async_notify;
uint8_t sq_draining;
uint8_t max_rd_atomic;
uint8_t max_dest_rd_atomic;
uint8_t min_rnr_timer;
uint8_t port_num;
uint8_t timeout;
uint8_t retry_cnt;
uint8_t rnr_retry;
uint8_t alt_port_num;
uint8_t alt_timeout;
uint32_t rate_limit;
};
Подробную информацию о конечном автомате и параметрах можно найти по ссылкеmojoblog: https://www.rdmamojo.com/2013/01/12/ibv_modify_qp/
https://www.rdmamojo.com/2012/05/05/qp-state-machine/
...
handle_connection
activate()
modify_qp_to_rtr
qpa.qp_state = IBV_QPS_RTR
ibv_modify_qp
modify_qp_to_rts
qpa.qp_state = IBV_QPS_RTS
ibv_modify_qp
Свойства RTR следующие:
int Infiniband::QueuePair::modify_qp_to_rtr(void)
{
// move from INIT to RTR state
ibv_qp_attr qpa;
// FIPS zeroization audit 20191115: this memset is not security related.
memset(&qpa, 0, sizeof(qpa));
qpa.qp_state = IBV_QPS_RTR;
qpa.path_mtu = IBV_MTU_1024;
qpa.dest_qp_num = peer_cm_meta.local_qpn;
qpa.rq_psn = peer_cm_meta.psn;
qpa.max_dest_rd_atomic = 1;
qpa.min_rnr_timer = 0x12;
qpa.ah_attr.is_global = 1;
qpa.ah_attr.grh.hop_limit = 6;
qpa.ah_attr.grh.dgid = peer_cm_meta.gid;
qpa.ah_attr.grh.sgid_index = infiniband.get_device()->get_gid_idx();
qpa.ah_attr.grh.traffic_class = cct->_conf->ms_async_rdma_dscp;
//qpa.ah_attr.grh.flow_label = 0;
qpa.ah_attr.dlid = peer_cm_meta.lid;
qpa.ah_attr.sl = cct->_conf->ms_async_rdma_sl;
qpa.ah_attr.src_path_bits = 0;
qpa.ah_attr.port_num = (uint8_t)(ib_physical_port);
ldout(cct, 20) << __FFL__ << " Choosing gid_index " << (int)qpa.ah_attr.grh.sgid_index << ", sl " << (int)qpa.ah_attr.sl << dendl;
int attr_mask = IBV_QP_STATE | IBV_QP_AV | IBV_QP_PATH_MTU | IBV_QP_DEST_QPN | IBV_QP_RQ_PSN | IBV_QP_MIN_RNR_TIMER | IBV_QP_MAX_DEST_RD_ATOMIC;
int r = ibv_modify_qp(qp, &qpa, attr_mask);
...
}
Конфигурация RTS следующая:
int Infiniband::QueuePair::modify_qp_to_rts(void)
{
// move from RTR state RTS
ibv_qp_attr qpa;
// FIPS zeroization audit 20191115: this memset is not security related.
memset(&qpa, 0, sizeof(qpa));
qpa.qp_state = IBV_QPS_RTS;
/*
* How long to wait before retrying if packet lost or server dead.
* Supposedly the timeout is 4.096us*2^timeout. However, the actual
* timeout appears to be 4.096us*2^(timeout+1), so the setting
* below creates a 135ms timeout.
*/
qpa.timeout = 0x12;
// How many times to retry after timeouts before giving up.
qpa.retry_cnt = 7;
/*
* How many times to retry after RNR (receiver not ready) condition
* before giving up. Occurs when the remote side has not yet posted
* a receive request.
*/
qpa.rnr_retry = 7; // 7 is infinite retry.
qpa.sq_psn = local_cm_meta.psn;
qpa.max_rd_atomic = 1;
int attr_mask = IBV_QP_STATE | IBV_QP_TIMEOUT | IBV_QP_RETRY_CNT | IBV_QP_RNR_RETRY | IBV_QP_SQ_PSN | IBV_QP_MAX_QP_RD_ATOMIC;
int r = ibv_modify_qp(qp, &qpa, attr_mask);
...
}
static ucs_status_t
uct_ud_iface_create_qp(uct_ud_iface_t *self, const uct_ud_iface_config_t *config)
{
uct_ud_iface_ops_t *ops = ucs_derived_of(self->super.ops, uct_ud_iface_ops_t);
uct_ib_qp_attr_t qp_init_attr = {};
struct ibv_qp_attr qp_attr;
static ucs_status_t status;
int ret;
qp_init_attr.qp_type = IBV_QPT_UD;
qp_init_attr.sq_sig_all = 0;
qp_init_attr.cap.max_send_wr = config->super.tx.queue_len;
qp_init_attr.cap.max_recv_wr = config->super.rx.queue_len;
qp_init_attr.cap.max_send_sge = config->super.tx.min_sge + 1;
qp_init_attr.cap.max_recv_sge = 1;
qp_init_attr.cap.max_inline_data = config->super.tx.min_inline;
status = ops->create_qp(&self->super, &qp_init_attr, &self->qp);
if (status != UCS_OK) {
return status;
}
self->config.max_inline = qp_init_attr.cap.max_inline_data;
memset(&qp_attr, 0, sizeof(qp_attr));
/* Modify QP to INIT state */
qp_attr.qp_state = IBV_QPS_INIT;
qp_attr.pkey_index = self->super.pkey_index;
qp_attr.port_num = self->super.config.port_num;
qp_attr.qkey = UCT_IB_KEY;
ret = ibv_modify_qp(self->qp, &qp_attr,
IBV_QP_STATE | IBV_QP_PKEY_INDEX | IBV_QP_PORT | IBV_QP_QKEY);
if (ret) {
ucs_error("Failed to modify UD QP to INIT: %m");
goto err_destroy_qp;
}
/* Modify to RTR */
qp_attr.qp_state = IBV_QPS_RTR;
ret = ibv_modify_qp(self->qp, &qp_attr, IBV_QP_STATE);
if (ret) {
ucs_error("Failed to modify UD QP to RTR: %m");
goto err_destroy_qp;
}
/* Modify to RTS */
qp_attr.qp_state = IBV_QPS_RTS;
qp_attr.sq_psn = 0;
ret = ibv_modify_qp(self->qp, &qp_attr, IBV_QP_STATE | IBV_QP_SQ_PSN);
...
}
ncclResult_t ncclIbConnect(int dev, void* opaqueHandle, void** sendComm)
if (stage->state == ncclIbCommStateSend) goto ib_send;
NCCLCHECK(ncclIbInitVerbs(dev, ctx, &comm->verbs))
...
ncclIbCreateQp
rdma:
ncclResult_t ncclIbCreateQp
qpInitAttr.qp_type = IBV_QPT_RC
qpInitAttr.cap.max_send_wr = 2*MAX_REQUESTS -> 128
qpInitAttr.cap.max_recv_wr = MAX_REQUESTS -> 64
wrap_ibv_modify_qp
...
ncclResult_t ncclIbCreateQp(uint8_t ib_port, struct ncclIbVerbs* verbs, int access_flags, struct ibv_qp** qp) {
struct ibv_qp_init_attr qpInitAttr;
memset(&qpInitAttr, 0, sizeof(struct ibv_qp_init_attr));
qpInitAttr.send_cq = verbs->cq;
qpInitAttr.recv_cq = verbs->cq;
qpInitAttr.qp_type = IBV_QPT_RC;
// We might send 2 messages per send (RDMA and RDMA_WITH_IMM)
qpInitAttr.cap.max_send_wr = 2*MAX_REQUESTS;
qpInitAttr.cap.max_recv_wr = MAX_REQUESTS;
qpInitAttr.cap.max_send_sge = 1;
qpInitAttr.cap.max_recv_sge = 1;
qpInitAttr.cap.max_inline_data = ncclParamIbUseInline() ? sizeof(struct ncclIbSendFifo) : 0;
NCCLCHECK(wrap_ibv_create_qp(qp, verbs->pd, &qpInitAttr));
struct ibv_qp_attr qpAttr;
memset(&qpAttr, 0, sizeof(struct ibv_qp_attr));
qpAttr.qp_state = IBV_QPS_INIT;
qpAttr.pkey_index = ncclParamIbPkey();
qpAttr.port_num = ib_port;
qpAttr.qp_access_flags = access_flags;
NCCLCHECK(wrap_ibv_modify_qp(*qp, &qpAttr, IBV_QP_STATE | IBV_QP_PKEY_INDEX | IBV_QP_PORT | IBV_QP_ACCESS_FLAGS));
return ncclSuccess;
}
RTR:
ncclResult_t ncclIbRtrQp(struct ibv_qp* qp, uint32_t qpn, struct ncclIbQpInfo* info) {
struct ibv_qp_attr qpAttr;
memset(&qpAttr, 0, sizeof(struct ibv_qp_attr));
qpAttr.qp_state = IBV_QPS_RTR;
qpAttr.path_mtu = info->mtu;
qpAttr.dest_qp_num = qpn;
qpAttr.rq_psn = 0;
qpAttr.max_dest_rd_atomic = 1;
qpAttr.min_rnr_timer = 12;
if (info->link_layer == IBV_LINK_LAYER_ETHERNET) {
qpAttr.ah_attr.is_global = 1;
qpAttr.ah_attr.grh.dgid.global.subnet_prefix = info->spn;
qpAttr.ah_attr.grh.dgid.global.interface_id = info->iid;
qpAttr.ah_attr.grh.flow_label = 0;
qpAttr.ah_attr.grh.sgid_index = ncclParamIbGidIndex();
qpAttr.ah_attr.grh.hop_limit = 255;
qpAttr.ah_attr.grh.traffic_class = ncclParamIbTc();
} else {
qpAttr.ah_attr.is_global = 0;
qpAttr.ah_attr.dlid = info->lid;
}
qpAttr.ah_attr.sl = ncclParamIbSl();
qpAttr.ah_attr.src_path_bits = 0;
qpAttr.ah_attr.port_num = info->ib_port;
NCCLCHECK(wrap_ibv_modify_qp(qp, &qpAttr, IBV_QP_STATE | IBV_QP_AV | IBV_QP_PATH_MTU | IBV_QP_DEST_QPN | IBV_QP_RQ_PSN | IBV_QP_MAX_DEST_RD_ATOMIC | IBV_QP_MIN_RNR_TIMER));
return ncclSuccess;
}
RTS:
ncclResult_t ncclIbRtsQp(struct ibv_qp* qp) {
struct ibv_qp_attr qpAttr;
memset(&qpAttr, 0, sizeof(struct ibv_qp_attr));
qpAttr.qp_state = IBV_QPS_RTS;
qpAttr.timeout = ncclParamIbTimeout();
qpAttr.retry_cnt = ncclParamIbRetryCnt();
qpAttr.rnr_retry = 7;
qpAttr.sq_psn = 0;
qpAttr.max_rd_atomic = 1;
NCCLCHECK(wrap_ibv_modify_qp(qp, &qpAttr, IBV_QP_STATE | IBV_QP_TIMEOUT | IBV_QP_RETRY_CNT | IBV_QP_RNR_RETRY | IBV_QP_SQ_PSN | IBV_QP_MAX_QP_RD_ATOMIC));
return ncclSuccess;
}
Существуют и другие проекты, такие как: spdk, ядро также можно использовать в качестве ссылки.
ibv_modify_qp
.modify_qp = irdma_umodify_qp,
ibv_cmd_modify_qp_ex
copy_modify_qp_fields
...
cmd->retry_cnt = attr->retry_cnt
...
execute_cmd_write_ex IB_USER_VERBS_EX_CMD_MODIFY_QP -> Перейти к обработке через интерфейс ABI ядра
irdma_mmap
or ibv_cmd_modify_qp
ibv_modify_qp -> IB_USER_VERBS_EX_CMD_MODIFY_QP -> ib_uverbs_ex_modify_qp
modify_qp
uobj_get_obj_read UVERBS_OBJECT_QP
Проверить параметры
...
ib_modify_qp_with_udata
_ib_modify_qp -> IB/ядро: будет DMAC Анализ ограничен пользовательским пространством QP, текущий ah_attr Зависит от ib_cm Цели слоя основаны на rdma_cm приложение инициализируется. для RoCE транспорт,ah_attr.roce.dmac уже Зависит от ib_cm、rdma_cm от wc、запись пути、дорога Зависит отанализировать、явныйзапись настройки пути (зависит от активной или пассивной стороны QP) инициализация. Так что избегайте быть потребителем ядра QP анализировать DMAC
attr_mask & IB_QP_AV -> IBV_QP_AV,В основном используется для указания ядру анализировать адреса.,дляRoCE,тогда продолжайL3приезжатьMACадресиз Конвертировать
rdma_fill_sgid_attr
rdma_check_ah_attr
rdma_ah_retrieve_grh
rdma_get_gid_attr
rdma_gid_table
get_gid_entry
ib_resolve_eth_dmac -> Вызовите ib_resolve_eth_dmacанализироватьудаленный gid соответствует изMAC-адресу
...
rdma_resolve_ip resolve_cb
complete -> 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Давайте поговоримноне имеющий отношения。 Измените драйвер поставщика для поддержки новой сигнатуры функции.
rdma_lag_get_ah_roce_slave
rdma_read_gid_attr_ndev_rcu
rdma_get_xmit_slave_udp
rdma_build_skb
netdev_get_xmit_slave RDMA_LAG_FLAGS_HASH_ALL_SLAVES
rdma_counter_bind_qp_auto
ib_security_modify_qp -> 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 list и проверьте, есть ли у них разрешения. если Нет,но Воля 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 on, дождитесь, пока поток обработает его, а затем очистите структуру. если уничтожение не удалось,но QP порт и PKey настраивать Воля重новыйвставлятьприезжатьподходящийкогдаиз Списокповерхностьсередина,Флаг разрушения будет очищен,и обеспечить контроль доступа,На всякий случайсуществовать Любые изменения кэша, происходящие в процессе уничтожения.。 Чтобы сохранить изменения безопасности изолированными, используйте новые файлы для сохранения функций, связанных с безопасностью.
port_pkey_list_insert -> существования, прежде чем проверять разрешения, поставьте это QP добавить вприезжатьновыйпорт и pkey Установите в списке, чтобы предотвратить одновременные обновления кэша. 遍历Списокповерхностьруководить缓存更改不会Получатьбезопасный мьютекс,Пока не QP отправить на ошибку
check_qp_port_pkey_settings
get_pkey_and_subnet_prefix
ib_get_cached_pkey
ib_get_cached_subnet_prefix
enforce_qp_pkey_security
modify_qp -> .modify_qp = irdma_modify_qp_roce
rdma_lag_put_ah_roce_slave
release_qp:
rdma_lookup_put_uobject
...
irdma_modify_qp_roce
irdma_query_pkey
rdma_get_udp_sport -> в соответствии с grh.flow_label или lqpn/rqrpn Получать QP изисточник udp Номер порта. Это может лучше пересечь NIC RX трафик распространения очереди
irdma_qp_rem_qos
dev->ws_remove
rdma_read_gid_l2_fields
irdma_roce_get_vlan_prio
vlan_dev_get_egress_qos_mask
irdma_qp_add_qos
list_add(&qp->list, &vsi->qos[qp->user_pri].qplist)
ib_modify_qp_is_ok
qp_state_table[cur_state][next_state].valid) -> ИБ: добавить ib_modify_qp_is_ok() Библиотечные функции в ядре mthca Драйвер содержитповерхность,Чтосерединаизсвойстводлякаждый队Список对状态Конвертировать Все действительны。 Оказывается, положительное существование готово слиться из двух других. IB драйвер (ipath и эхха) все копировать таблицу, ошибки и т.д. Во избежание дублирования кода переместите эту таблицу и для проверки параметров кода в функцию библиотеки среднего уровня. ib_modify_qp_is_ok() середина
Таблица состояния и параметры qp: qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1]
switch (attr->qp_state) -> Конечный автомат QP
...
irdma_flush_wqes
irdma_hw_flush_wqes
cqp_request->callback_fcn = irdma_hw_flush_wqes_callback
cqp_info->cqp_cmd = IRDMA_OP_QP_FLUSH_WQES
irdma_handle_cqp_op -> cqp Контроль качества
irdma_process_cqp_cmd
irdma_exec_cqp_cmd
switch (pcmdinfo->cqp_cmd) -> суждение Контроль качества Заказтип
case IRDMA_OP_CEQ_CREATE -> Драйвер публикует привилегированные команды в очередь управления оборудованием (управление QP или CQP), чтобы запросить оборудование для выполнения операций управления. выполнить CQP создавать/уничтожать и поддерживать функции, структуры данных и заголовки для обработки различных CQP Заказ
irdma_sc_cq_create
irdma_sc_cqp_get_next_send_wqe
set_64bit_val(wqe, 0, cq->cq_uk.cq_size) -> Установите его значение поразрядно (каждые 8 байт)
dma_wmb()
irdma_sc_cqp_post_sq
writel(IRDMA_RING_CURRENT_HEAD(cqp->sq_ring), cqp->dev->cqp_db) -> Регистр записи (после чипа отображения памяти из ввода-вывода Запишите 4 байта данных в пространство)
...
irdma_sc_qp_setctx_roce
void irdma_sc_qp_setctx_roce(struct irdma_sc_qp *qp, __le64 *qp_ctx,
set_64bit_val rq_wqe_size
...
mojo ibv_modify_qp: https://www.rdmamojo.com/2013/01/12/ibv_modify_qp/
Конечный автомат QP: https://www.rdmamojo.com/2012/05/05/qp-state-machine/
При внешнем подключении: https://zhuanlan.zhihu.com/p/655663006
Переведенная версия: https://blog.csdn.net/bandaoyu/article/details/115764839
IBM ibv_modify_qp: https://www.ibm.com/docs/zh-tw/aix/7.3?topic=management-ibv-modify-qp
QP в RDMA: https://www.cnblogs.com/zafu/p/11587457.html
блог: https://cloud.tencent.com/developer/user/5060293/articles | https://logread.cn | https://blog.csdn.net/ssbandjl | https://www.zhihu.com/people/ssbandjl/posts