searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

UD

2025-04-15 01:49:39
4
0

UD模式

UD(Unreliable Datagram)是RDMA的一种传输模式。

AH

AH(Address Handle)是IB传输过程中描述通信节点的信息集合,属性描述如下

struct ibv_ah_attr {
	struct ibv_global_route	grh;
	uint16_t		dlid;			//dest lid, 仅IB模式有效
	uint8_t			sl;				//service level, 仅IB模式有效
	uint8_t			src_path_bits;	//src lid path bits 仅IB模式有效
	uint8_t			static_rate;	//enum ibv_rate{} 和包的传输速率有关
	uint8_t			is_global;		//grh是否有效
	uint8_t			port_num;		//gid所在的port num, 一般都是1
};

struct ibv_global_route {
	union ibv_gid		dgid;	//dest ip
	uint32_t		flow_label;	//数据报文的标签,在ipv6中是ipv6hdr->flow_labal.
	uint8_t			sgid_index;	//source ip index
	uint8_t			hop_limit;	//等同于ipv4hdr->ttl
	uint8_t			traffic_class;	//等同于ipv4hdr->tos
};

创建AH

(1) 通过ibv_create_ah()接口创建ah

struct ibv_ah *ibv_create_ah(struct ibv_pd *pd, struct ibv_ah_attr *attr);

入参:

Pd

Protection Domain

Attr

ah 属性

返回值:

NULL

成功
NULL  失败

流程如下:

ibv_create_ah()
    ->driver->ops->create_ah()
        ->ibv_cmd_create_ah()
            ->ib_uverbs_create_ah()

ib_uverbs_create_ah()
    ->rdma_is_port_valid(),检测port_num 是否是有效的
    -> fill struct rdma_ah_attr{}
    -> rdma_create_user_ah()
        ->RoCE v2会通过ib_resolve_eth_dmac()查找arp和路由
        ->_rdma_create_ah()
            ->driver->ops.create_ah() 完成ah创建

2、通过ibv_create_ah_from_wc() 接口创建ah

struct ibv_ah *ibv_create_ah_from_wc(struct ibv_pd *pd, struct ibv_wc *wc, struct ibv_grh *grh, uint8_t port_num);

说明:根据poll CQ 得到recv wc创建ah_attr

入参:

Pd

Protection Domain

wc

poll cq得到的recv wc

grh

recv wr的前40字节

Port_num

gid所在的port id,一般是1

返回值:

NULL

成功
NULL  失败

流程:

ibv_create_ah_from_wc()
    ->ibv_init_ah_from_wc()
    ->ibv_create_ah()

ibv_init_ah_from_wc()
    ->set_ah_attr_generic_fields() 从wc中获取信息,填充ah_attr
	ah_attr->grh.flow_label = be32toh(grh->version_tclass_flow) & 0xFFFFF;
	ah_attr->dlid = wc->slid;
	ah_attr->sl = wc->sl;
	ah_attr->src_path_bits = wc->dlid_path_bits;
	ah_attr->port_num = port_num;
    ->wc->wc_flag一定要带有IBV_WC_GRH 标记,这样才能根据wc填充剩余的ah_attr
        ->set_ah_attr_by_ipv4() IPv4模式从rqe的起始位置偏移20字节,获取IP hdr,填充ah_attr->grh
        ->set_ah_attr_by_ipv6()IPv4模式从rqe的起始位置获取IPv6 hdr,填充ah_atr->grh

销毁AH

通过 int ibv_destroy_ah(struct ibv_ah *ah); 销毁AH

入参:

ah UD ah

返回值:

0 成功
非0 失败

流程:

ibv_destroy_ah()
    ->driver->ops->destroy_ah()
        ->ibv_cmd_destroy_ah() 陷入内核
            ->uverbs_free_ah()

uverbs_free_ah()
    ->rdma_destroy_ah_user()
        ->driver->ops.destroy_ah()
    ->dec reference count;

数据收发

send:

通过ibv_post_send(struct ibv_qp *qp, struct ibv_send_wr *wr,struct ibv_send_wr **bad_wr),填充send data搭配send queue中,完成数据发送

入参:

qp ud qp
wr

 work request待发送的数据

出参:

bad_wr

没有填充到queue中的wr

返回值

0 success
其他 errno

ud wr 属性:

struct ibv_send_wr {
	uint64_t		wr_id;
	struct ibv_send_wr     *next;	//下一个wr, 为NULL时截至
	struct ibv_sge	       *sg_list;  //当前send wr对应的sge list
	int			num_sge;
	enum ibv_wr_opcode	opcode;	//IBV_WR_SEND 或 IBV_WR_SEND_WITH_IMM,
	unsigned int		send_flags;
	union {
		__be32			imm_data;			//send with imm时有效
		uint32_t		invalidate_rkey;
	};
	union {
		.
		.
		.
		struct {
			struct ibv_ah  *ah;		//ah
			uint32_t	remote_qpn;	//远端的QPn,两端交互得到
			uint32_t	remote_qkey;//远端的Qkey,用于接收校验,两端交互得到
		} ud;
	} wr;
	.
	.
	.
};

说明:post send根据struct ibv_ah *ah得到驱动的ah信息,填充wqectrl字段,比如udp sport,traffic_class等信息交给硬件,然后硬件完成组包发送。

recv:

通过ibv_post_recv(struct ibv_qp *qp, struct ibv_recv_wr *wr, struct ibv_recv_wr **bad_wr); 填充recv buf,接收send only/ send only with immediate数据

入参:

qp ud qp
wr

work request,带填充的recv buf

出参:

bad_wr

没有填充到queue中的wr

返回值

0 success
其他 errno

说明:post recv不区分UD模式和RC模式,只不过需要注意的是UD模式的recv wr的长度接收报文的长度加上40B。这40B是报文的ip hdr空间。

poll cq

通过ibv_poll_cq(struct ibv_cq *cq, int num_entries, struct ibv_wc *wc) 接口处理

入参:

cq

指定的complete queue

num_entrie

wc数组的长度

出参:

wc

work complete

返回值

 大于0

 wc的实际数量

小于0

errno

说明:wc分为send和recv两侧

send侧

struct ibv_wc {
	uint64_t		wr_id;			//对应的send wr
	enum ibv_wc_status	status;		//表示当前send wr是否处理成功
	enum ibv_wc_opcode	opcode;		// IBV_WC_SEND
	uint32_t		vendor_err;
	uint32_t		byte_len;		//不填充
	union {
		__be32		imm_data;		//不填充
		uint32_t	invalidated_rkey; //不填充
	};

	uint32_t		qp_num;			//本段的QPn
	uint32_t		src_qp;			//不填充
	unsigned int		wc_flags;	//send with imm时 | IBV_WC_WITH_IMM
	uint16_t		pkey_index;		//不填充
	uint16_t		slid;			//不填充
	uint8_t			sl;				//不填充
	uint8_t			dlid_path_bits;	//不填充
};

recv侧

struct ibv_wc {
	uint64_t		wr_id;			//对应的recv wr
	enum ibv_wc_status	status;		//表示当前recv wr是否处理成功
	enum ibv_wc_opcode	opcode;		//IBV_WC_RECV
	uint32_t		vendor_err;
	uint32_t		byte_len;		//40B加上实际的数据长度,
									//rqe的前40B是L3 hdr(struct iphdr/ipv6hdr)
									//如果是ipv4 偏移20B位置处取数据
									//如果是ipv6 偏移0B位置处取数据
									//报文在 偏移40B位置处获取
	union {
		__be32		imm_data;		//send only with immediate时携带
		uint32_t	invalidated_rkey;	//ud模式不支持
	};
	uint32_t		qp_num;			//本段的QPn
	uint32_t		src_qp;			//表示发送端的QPn,源自DETH中的source qpn
	unsigned int		wc_flags;	//在UD模式下需要 | IBV_WC_GRH
	uint16_t		pkey_index;		//bth->pkey 默认是65535
	uint16_t		slid;			//source lid 在IB模式下有效
	uint8_t			sl;				//service level 在IB模式下有效
	uint8_t			dlid_path_bits;	//dest lid path bit 在IB模式下有效
};

补充说明:在IB spec中描述到在接收侧的需要给用户一个L3 header和L2 info,L3 header放在rqe中,标准IB是支持的,但是在RoCE v2模式中wc有没有存放l2 info的位置。所以下面这段描述可能存在错误。

0条评论
0 / 1000
z****n
10文章数
1粉丝数
z****n
10 文章 | 1 粉丝
原创

UD

2025-04-15 01:49:39
4
0

UD模式

UD(Unreliable Datagram)是RDMA的一种传输模式。

AH

AH(Address Handle)是IB传输过程中描述通信节点的信息集合,属性描述如下

struct ibv_ah_attr {
	struct ibv_global_route	grh;
	uint16_t		dlid;			//dest lid, 仅IB模式有效
	uint8_t			sl;				//service level, 仅IB模式有效
	uint8_t			src_path_bits;	//src lid path bits 仅IB模式有效
	uint8_t			static_rate;	//enum ibv_rate{} 和包的传输速率有关
	uint8_t			is_global;		//grh是否有效
	uint8_t			port_num;		//gid所在的port num, 一般都是1
};

struct ibv_global_route {
	union ibv_gid		dgid;	//dest ip
	uint32_t		flow_label;	//数据报文的标签,在ipv6中是ipv6hdr->flow_labal.
	uint8_t			sgid_index;	//source ip index
	uint8_t			hop_limit;	//等同于ipv4hdr->ttl
	uint8_t			traffic_class;	//等同于ipv4hdr->tos
};

创建AH

(1) 通过ibv_create_ah()接口创建ah

struct ibv_ah *ibv_create_ah(struct ibv_pd *pd, struct ibv_ah_attr *attr);

入参:

Pd

Protection Domain

Attr

ah 属性

返回值:

NULL

成功
NULL  失败

流程如下:

ibv_create_ah()
    ->driver->ops->create_ah()
        ->ibv_cmd_create_ah()
            ->ib_uverbs_create_ah()

ib_uverbs_create_ah()
    ->rdma_is_port_valid(),检测port_num 是否是有效的
    -> fill struct rdma_ah_attr{}
    -> rdma_create_user_ah()
        ->RoCE v2会通过ib_resolve_eth_dmac()查找arp和路由
        ->_rdma_create_ah()
            ->driver->ops.create_ah() 完成ah创建

2、通过ibv_create_ah_from_wc() 接口创建ah

struct ibv_ah *ibv_create_ah_from_wc(struct ibv_pd *pd, struct ibv_wc *wc, struct ibv_grh *grh, uint8_t port_num);

说明:根据poll CQ 得到recv wc创建ah_attr

入参:

Pd

Protection Domain

wc

poll cq得到的recv wc

grh

recv wr的前40字节

Port_num

gid所在的port id,一般是1

返回值:

NULL

成功
NULL  失败

流程:

ibv_create_ah_from_wc()
    ->ibv_init_ah_from_wc()
    ->ibv_create_ah()

ibv_init_ah_from_wc()
    ->set_ah_attr_generic_fields() 从wc中获取信息,填充ah_attr
	ah_attr->grh.flow_label = be32toh(grh->version_tclass_flow) & 0xFFFFF;
	ah_attr->dlid = wc->slid;
	ah_attr->sl = wc->sl;
	ah_attr->src_path_bits = wc->dlid_path_bits;
	ah_attr->port_num = port_num;
    ->wc->wc_flag一定要带有IBV_WC_GRH 标记,这样才能根据wc填充剩余的ah_attr
        ->set_ah_attr_by_ipv4() IPv4模式从rqe的起始位置偏移20字节,获取IP hdr,填充ah_attr->grh
        ->set_ah_attr_by_ipv6()IPv4模式从rqe的起始位置获取IPv6 hdr,填充ah_atr->grh

销毁AH

通过 int ibv_destroy_ah(struct ibv_ah *ah); 销毁AH

入参:

ah UD ah

返回值:

0 成功
非0 失败

流程:

ibv_destroy_ah()
    ->driver->ops->destroy_ah()
        ->ibv_cmd_destroy_ah() 陷入内核
            ->uverbs_free_ah()

uverbs_free_ah()
    ->rdma_destroy_ah_user()
        ->driver->ops.destroy_ah()
    ->dec reference count;

数据收发

send:

通过ibv_post_send(struct ibv_qp *qp, struct ibv_send_wr *wr,struct ibv_send_wr **bad_wr),填充send data搭配send queue中,完成数据发送

入参:

qp ud qp
wr

 work request待发送的数据

出参:

bad_wr

没有填充到queue中的wr

返回值

0 success
其他 errno

ud wr 属性:

struct ibv_send_wr {
	uint64_t		wr_id;
	struct ibv_send_wr     *next;	//下一个wr, 为NULL时截至
	struct ibv_sge	       *sg_list;  //当前send wr对应的sge list
	int			num_sge;
	enum ibv_wr_opcode	opcode;	//IBV_WR_SEND 或 IBV_WR_SEND_WITH_IMM,
	unsigned int		send_flags;
	union {
		__be32			imm_data;			//send with imm时有效
		uint32_t		invalidate_rkey;
	};
	union {
		.
		.
		.
		struct {
			struct ibv_ah  *ah;		//ah
			uint32_t	remote_qpn;	//远端的QPn,两端交互得到
			uint32_t	remote_qkey;//远端的Qkey,用于接收校验,两端交互得到
		} ud;
	} wr;
	.
	.
	.
};

说明:post send根据struct ibv_ah *ah得到驱动的ah信息,填充wqectrl字段,比如udp sport,traffic_class等信息交给硬件,然后硬件完成组包发送。

recv:

通过ibv_post_recv(struct ibv_qp *qp, struct ibv_recv_wr *wr, struct ibv_recv_wr **bad_wr); 填充recv buf,接收send only/ send only with immediate数据

入参:

qp ud qp
wr

work request,带填充的recv buf

出参:

bad_wr

没有填充到queue中的wr

返回值

0 success
其他 errno

说明:post recv不区分UD模式和RC模式,只不过需要注意的是UD模式的recv wr的长度接收报文的长度加上40B。这40B是报文的ip hdr空间。

poll cq

通过ibv_poll_cq(struct ibv_cq *cq, int num_entries, struct ibv_wc *wc) 接口处理

入参:

cq

指定的complete queue

num_entrie

wc数组的长度

出参:

wc

work complete

返回值

 大于0

 wc的实际数量

小于0

errno

说明:wc分为send和recv两侧

send侧

struct ibv_wc {
	uint64_t		wr_id;			//对应的send wr
	enum ibv_wc_status	status;		//表示当前send wr是否处理成功
	enum ibv_wc_opcode	opcode;		// IBV_WC_SEND
	uint32_t		vendor_err;
	uint32_t		byte_len;		//不填充
	union {
		__be32		imm_data;		//不填充
		uint32_t	invalidated_rkey; //不填充
	};

	uint32_t		qp_num;			//本段的QPn
	uint32_t		src_qp;			//不填充
	unsigned int		wc_flags;	//send with imm时 | IBV_WC_WITH_IMM
	uint16_t		pkey_index;		//不填充
	uint16_t		slid;			//不填充
	uint8_t			sl;				//不填充
	uint8_t			dlid_path_bits;	//不填充
};

recv侧

struct ibv_wc {
	uint64_t		wr_id;			//对应的recv wr
	enum ibv_wc_status	status;		//表示当前recv wr是否处理成功
	enum ibv_wc_opcode	opcode;		//IBV_WC_RECV
	uint32_t		vendor_err;
	uint32_t		byte_len;		//40B加上实际的数据长度,
									//rqe的前40B是L3 hdr(struct iphdr/ipv6hdr)
									//如果是ipv4 偏移20B位置处取数据
									//如果是ipv6 偏移0B位置处取数据
									//报文在 偏移40B位置处获取
	union {
		__be32		imm_data;		//send only with immediate时携带
		uint32_t	invalidated_rkey;	//ud模式不支持
	};
	uint32_t		qp_num;			//本段的QPn
	uint32_t		src_qp;			//表示发送端的QPn,源自DETH中的source qpn
	unsigned int		wc_flags;	//在UD模式下需要 | IBV_WC_GRH
	uint16_t		pkey_index;		//bth->pkey 默认是65535
	uint16_t		slid;			//source lid 在IB模式下有效
	uint8_t			sl;				//service level 在IB模式下有效
	uint8_t			dlid_path_bits;	//dest lid path bit 在IB模式下有效
};

补充说明:在IB spec中描述到在接收侧的需要给用户一个L3 header和L2 info,L3 header放在rqe中,标准IB是支持的,但是在RoCE v2模式中wc有没有存放l2 info的位置。所以下面这段描述可能存在错误。

文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0