前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RDMA_verbs编程详解-cm建连-rdma_connect

RDMA_verbs编程详解-cm建连-rdma_connect

原创
作者头像
ssbandjl
发布2024-03-12 16:19:33
2770
发布2024-03-12 16:19:33
举报
文章被收录于专栏:DPUDPU

术语

  • MAD(Management Datagram): MAD是InfiniBand网络中用于管理和配置的数据报文。它包含了各种类型的管理操作,如查询端口状态、配置端口参数等。MAD通常用于执行网络管理任务
  • uMAD(User MAD): uMAD是用户空间应用程序与InfiniBand子系统之间进行通信的接口。它允许应用程序发送和接收MAD消息,以执行特定的管理操作。通过uMAD,应用程序可以直接与InfiniBand网络进行交互,执行各种管理任务
  • RDMACM(RDMA Connection Manager): RDMACM是一个库,用于管理RDMA连接的建立、维护和关闭。它提供了一组函数,使应用程序能够发现和连接远程节点,并在需要时建立RDMA连接。RDMACM简化了RDMA连接的管理过程,使应用程序可以更方便地使用RDMA功能

简介

以libfabric使用的cm建连(rdma_connect)为例:

代码语言:javascript
复制
客户端与服务端建立连接
rdma_connect -> server -> RDMA_CM_EVENT_CONNECT_REQUEST, -> fi_senddata -> rxm_get_conn -> rdma_connect

rdma-core调用栈如下:

代码语言:javascript
复制
发起连接请求
int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
ucma_valid_param
CMA_INIT_CMD(&cmd, sizeof cmd, CONNECT)
cmd = UCMA_CMD_CONNECT -> kernel -> static ssize_t (*ucma_cmd_table[]) -> ucma_connect 转到kernel
ucma_copy_conn_param_to_kern
  dst->retry_count = 7;   // 无限次重试
    dst->rnr_retry_count = 7; // 无限次重试
ucma_copy_ece_param_to_kern_req
ret = write(id->channel->fd, &cmd, sizeof cmd)

kernel执行: ucma_connect

代码语言:javascript
复制
drivers/infiniband/core/ucma.c
static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
                   const char __user *inbuf,
                   int in_len, int out_len) = {
    [RDMA_USER_CM_CMD_CREATE_ID]     = ucma_create_id,
    [RDMA_USER_CM_CMD_DESTROY_ID]    = ucma_destroy_id,
    [RDMA_USER_CM_CMD_BIND_IP]   = ucma_bind_ip,
    [RDMA_USER_CM_CMD_RESOLVE_IP]    = ucma_resolve_ip,
    [RDMA_USER_CM_CMD_RESOLVE_ROUTE] = ucma_resolve_route,
    [RDMA_USER_CM_CMD_QUERY_ROUTE]   = ucma_query_route,
    [RDMA_USER_CM_CMD_CONNECT]   = ucma_connect, // 内核执行此函数
    [RDMA_USER_CM_CMD_LISTEN]    = ucma_listen,
    [RDMA_USER_CM_CMD_ACCEPT]    = ucma_accept,
    [RDMA_USER_CM_CMD_REJECT]    = ucma_reject,
    [RDMA_USER_CM_CMD_DISCONNECT]    = ucma_disconnect,
    [RDMA_USER_CM_CMD_INIT_QP_ATTR]  = ucma_init_qp_attr,
    [RDMA_USER_CM_CMD_GET_EVENT]     = ucma_get_event,
    [RDMA_USER_CM_CMD_GET_OPTION]    = NULL,
    [RDMA_USER_CM_CMD_SET_OPTION]    = ucma_set_option,
    [RDMA_USER_CM_CMD_NOTIFY]    = ucma_notify,
    [RDMA_USER_CM_CMD_JOIN_IP_MCAST] = ucma_join_ip_multicast,
    [RDMA_USER_CM_CMD_LEAVE_MCAST]   = ucma_leave_multicast,
    [RDMA_USER_CM_CMD_MIGRATE_ID]    = ucma_migrate_id,
    [RDMA_USER_CM_CMD_QUERY]     = ucma_query,
    [RDMA_USER_CM_CMD_BIND]      = ucma_bind,
    [RDMA_USER_CM_CMD_RESOLVE_ADDR]  = ucma_resolve_addr,
    [RDMA_USER_CM_CMD_JOIN_MCAST]    = ucma_join_multicast
};
​
UCMA_CMD_CONNECT -> static ssize_t (*ucma_cmd_table[]) -> static ssize_t ucma_connect
    copy_from_user
    ucma_get_ctx_dev
    ucma_copy_conn_param -> RDMA/cma:为AF_IB设置qkey,允许用户在使用AF_IB时指定qkey。 qkey 被添加到 struct rdma_ucm_conn_param 中代替保留字段,但为了向后兼容,仅当关联的 rdma_cm_id 使用 AF_IB 时才可访问
        ...
        dst->qkey = (id->route.addr.src_addr.ss_family == AF_IB) ? src->qkey : 0;
    rdma_connect_ece -> RDMA/ucma:扩展ucma_connect以接收ECE参数,CMID的主动方通过librdmacm的rdma_connect()和内核的ucma_connect()发起连接。 扩展 UCMA 接口来处理这些新参数
        rdma_connect(id, conn_param) -> rdma_connect_locked
            cma_comp_exch(id_priv, RDMA_CM_ROUTE_RESOLVED, RDMA_CM_CONNECT)
            rdma_cap_ib_cm(id->device, id->port_num) -> rdma_cap_ib_cm - 检查设备端口是否具有 Infiniband Communication Manager 功能。 @device:要检查的设备 @port_num:要检查的端口号 InfiniBand 通信管理器是通过通用服务接口 (GSI) 访问的许多预定义通用服务代理 (GSA) 之一。 它的作用是促进节点之间连接的建立以及已建立的连接的其他管理相关任务。 返回:如果端口支持 IB CM,则返回 true(但这并不能保证 CM 实际正在运行)
                RDMA_CORE_CAP_IB_CM
            if (id->qp_type == IB_QPT_UD) -> cma_resolve_ib_udp -> RDMA/cma:添加对 RDMA_PS_UDP 的支持,允许通过 rdma_cm 使用 UD QP,以便为使用 SIDR 解析数据报消息的 IB 地址提供地址转换服务
            or cma_connect_ib
                check_add_overflow
                ib_create_cm_id(id_priv->id.device, cma_ib_handler, id_priv) -> 下方拆解
                    cm_alloc_id_priv -> RDMA/cm:简化建立监听cm_id
                        RB_CLEAR_NODE(&cm_id_priv->service_node) -> rb_tree
                        init_completion(&cm_id_priv->comp)
                        xa_alloc_cyclic -> 在 XArray 中找到存储此条目的位置
                trace_cm_send_req
                ib_send_cm_req
                    msg->context[1] = (void *)(unsigned long)IB_CM_REQ_SENT
                    ib_post_send_mad -> [IB] 修复 MAD 层 DMA 映射,以避免在映射后触及数据缓冲区。MAD 层在 DMA 映射完成后触及用于发送的数据缓冲区,从而违反了 DMA API。 这会导致非缓存一致性架构出现问题,因为执行 DMA 的设备不会看到仅存在于 CPU 缓存中的有效负载缓冲区的更新。 通过让所有 MAD 使用者使用 ib_create_send_mad() 分配其发送缓冲区,并将 DMA 映射移动到 MAD 层,以便可以在调用 send 之前(以及 MAD 层对发送缓冲区进行任何修改之后)完成此操作,可以解决此问题。 在非缓存一致性 PowerPC 440SPe 系统上进行测试
                        ib_mad_enforce_security -> IB/核心:在管理数据报上强制执行安全性,在创建和销毁 MAD 代理时分配和释放安全上下文。 该上下文用于控制对 PKey 的访问以及发送和接收 SMP。 发送或接收 MAD 时,检查代理是否有权访问端口子网前缀的 PKey。 在 SMI QP 的 MAD 和监听代理注册期间,检查调用进程是否有权访问管理子网并向 LSM 注册回调以获取策略更改通知。 当发生策略更改通知时,重新检查权限并设置一个标志,指示允许发送和接收 SMP。 发送和接收 MAD 时,如果代理位于 SMI QP 上,请检查代理是否有权访问 SMI。 由于安全策略可以更改,因此在创建代理时可能允许许可,但不再允许
                            rdma_protocol_ib
                            ib_security_pkey_access
                        ib_is_mad_class_rmpp
                        handle_outgoing_dr_smp
                        ib_mad_kernel_rmpp_agent
                        ib_send_rmpp_mad
                        ib_send_mad
                            ib_dma_map_single
                                ib_uses_virt_dma
                                dma_map_single
                            ib_post_send
                                .post_send = mlx5_ib_post_send_nodrain,
            or cma_connect_iw
    ucma_put_ctx

CM状态机:

代码语言:javascript
复制
cm状态机:
enum rdma_cm_state {
    RDMA_CM_IDLE,
    RDMA_CM_ADDR_QUERY,
    RDMA_CM_ADDR_RESOLVED,
    RDMA_CM_ROUTE_QUERY,
    RDMA_CM_ROUTE_RESOLVED,
    RDMA_CM_CONNECT,
    RDMA_CM_DISCONNECT,
    RDMA_CM_ADDR_BOUND,
    RDMA_CM_LISTEN,
    RDMA_CM_DEVICE_REMOVAL,
    RDMA_CM_DESTROYING
};
代码语言:javascript
复制
cma_ib_handler
switch (ib_event->event)
case IB_CM_REP_RECEIVED
    ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0) -> IB/cma:为回复消息发送MRA,RDMA_CM的当前实现仅针对请求消息发送MRA(消息接收确认),而不针对响应消息发送MRA。 因此,连接的缓慢主动方可能会在延迟太长的情况下向被动方发送就绪消息,而被动方无法等待。 该补丁在收到响应消息时添加了对 ib_send_cm_mra() 的调用,从而告诉对方将服务超时修改为更大的值,是之前的 16 倍。 与请求情况一样,仅当重复响应到达时才会发送用于回复的 MRA
        ...

总结

  • 如果需要使用CM建连, 则需要内核协议栈以及芯片逻辑做支持
  • 对于不支持CM建连, 可以使用socket建连, 然后交换QP建连所需的lid, gid, index等信息, 通过ibv_modify_qp转QP的状态机(INIT -> RTR -> RTS)实现QP建连
  • CM通信库简化了应用编程, 以及基于CM事件回调的异步轮询编程模型, 相比ibv_modify_qp等接口更易使用
  • RDMA建连与TCP差异明显
  • 可对比Intel E810和Nvidia MLX5用户态和内核态驱动做更深入的研究与分析

参考

【infiniband】 MAD、 uMAD、Verbs、RDMACM: https://blog.csdn.net/eidolon_foot/article/details/132840943

rdma-core和linux kernel驱动

晓兵(ssbandjl)

博客: https://cloud.tencent.com/developer/user/5060293/articles | https://logread.cn | https://blog.csdn.net/ssbandjl | https://www.zhihu.com/people/ssbandjl/posts

DPU专栏

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

技术会友: 欢迎对DPU/智能网卡/卸载/网络,存储加速/安全隔离等技术感兴趣的朋友加入DPU技术交流群

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 术语
  • 简介
  • 总结
  • 参考
  • 晓兵(ssbandjl)
    • DPU专栏
    相关产品与服务
    访问管理
    访问管理(Cloud Access Management,CAM)可以帮助您安全、便捷地管理对腾讯云服务和资源的访问。您可以使用CAM创建子用户、用户组和角色,并通过策略控制其访问范围。CAM支持用户和角色SSO能力,您可以根据具体管理场景针对性设置企业内用户和腾讯云的互通能力。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档