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

softroce-rxe收发包的异常处理流程分析

2023-10-20 07:53:32
59
0

一、TX流程上的异常处理

1、TX不处理报文的情况

  • QP被置为无效状态(QP destory);
  • QP状态是reset、error状态
  • QP状态不是ready状态

2、TX方向上送error  cqe

  • wqe opcode不正确,不支持,上送error cqe(IB_WC_LOC_QP_OP_ERR)
  • wqe 处理失败(mr不正确、发送失败等等),上送 error cqe(IB_WC_LOC_PROT_ERR), 置QP为error状态, 上送IB_EVENT_QP_FATAL事件,Flush SQ、RQ、上送error cqe (IB_WC_WR_FLUSH_ERR)

3、TX方向重传处理,主要是修改wqe的状态,重置重传标记。由ACK流程置重传标记。

for()遍历CI和PI之间的wqe,
   ->if (wqe->state == done) continue;
   ->if (wqe->state == post) break; 说明从这个wqe之后都是之前没有处理的wqe
   ->修改wqe的状态的待处理发送。对第一个要重传的wqe,计算从那个psn进行重传,计算好数据的addr和len

4、retry timer更新

首先retry timer每当处理一个wqe后,重置retry timer。retry timer到期后执行ack处理流程。因为是否需要retry,由当前接收到的ack报文决定。

5、当QP status == sqd时,上送IB_EVENT_SQ_DRAINED异步事件。

二、RX流程上的异常处理

1、RX不处理报文的情况

  • QP状态是RESET状态,丢弃报文
  • QP状态是ERROR状态,丢弃报文,上送error cqe(IB_WC_WR_FLUSH_ERR),flush qp

2、RX resp psn校验:

  • 如果收到的报文psn > 预期的psn,说明有丢包现象。
接收端:回复PSN乱序报文,报文携带本端预期的psn。这个报文存在一个隐藏信息:psn的隐式确认。
请求端:收到PSN乱序的报文后
  ->首先比较报文中的psn和本端的ack psn,if (pkt->psn > ack_psn)  更新ack_psn。
      ->if (retry_cnt > 0) :准备重传,if (retry_cnt != 7)  retry_cnt --。
      ->比较send_psn和ack_psn。if (send_psn > ack_psn) ,重传报文
  ->else (retry_cnt <= 0); 上送error cqe (IB_WC_RETRY_EXC_ERR),置QP error,上送IB_EVENT_QP_FATAL事件,flush SQ、RQ,上送error cqe (IB_WC_WR_FLUSH_ERR)
  • 如果收到的报文psn < 预期的psn,说明是重复请求。
->if (opcode == (send || write))  回复ACK。请求端:如果psn对应wqe还处理pending状态,上送IB_WC_SUCCESS cqe,ci++,然后更新ack_psn
->if (opcode == read req)  (前提:read和atomic有最大并发数, qp_attr配置字段max_dest_rd_atomic)。从接收资源中遍历查找匹配的read req。匹配规则:psn和opcode
    ->if (没有找到),不处理此报文。原因是read的并发有数量限制,如果没有找到,那说明read req端是收到了read resp。这个报文可能是延迟的无效请求包
    ->else (找到)  ,那就是一个有效的重复请求包,确保rkey,addr,len都是前一个包的字迹。按照请求长度回复read resp(可能多个包)
->if (opcode == atomic req) 和read req是一样的处理逻辑。

3、RX resp opcode校验

  • first、middle、last 报文没有按照顺序来。两种情况:丢失first;丢失last。
  • opcode不支持
  • 如果max_dest_rd_atomic <= 0,表示不支持read req/ atomic req。
接收端:上送error  cqe (IB_WC_REM_INV_REQ_ERR),回复无效请求NAK报文,置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe (IB_WC_WR_FLUSH_ERR)
请求端:上送error  cqe (IB_WC_REM_INV_REQ_ERR),置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe (IB_WC_WR_FLUSH_ERR)

 

说明:qp按照max_dest_rd_atomic大小申请缓存的read/atomic req空间。按照先进先出的原则

4、RX rqe资源校验

  • 没有rqe。
接受端:回复RNR_NAK,报文携带psn和min_rnr_timer。然后丢弃此报文。
请求端:处理RNR NAK报文。
   ->if (rnr_retry > 0) : if (rnr_retry != 7) rnr_retry --,然后按照min_rnr_timer时间,修改定时器的超时时间,定时器到期后重传。
   ->else (rnr_retry <=0):上送error cqe (IB_WC_RNR_RETRY_EXC_ERR),置QP error,上送IB_EVENT_QP_FATAL事件,flush SQ、RQ,上送error cqe (IB_WC_WR_FLUSH_ERR)

5、RX mr校验

  • read / write 的dma length == 0时,不需要查找mr。
  • 没有找到mr。(mr_index不正确;access不正确;rkey不正确;pd不正确;mr范围不匹配)。
接收端:上送error  cqe  (IB_WC_REM_ACCESS_ERR),回复remote memory access NAK报文,置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe (IB_WC_WR_FLUSH_ERR)
请求端:上送error  cqe (IB_WC_REM_ACCESS_ERR),置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe  (IB_WC_WR_FLUSH_ERR)

6、RX 校验包的长度:

  • 如果send/write first / middle 报文长度不等于mtu
  • send/write only / last 需要小于等于mtu
  • send报文的长度大于rqe 所有sge的长度
接收端:上送error  cqe  (IB_WC_REM_INV_REQ_ERR),回复无效的请求NAK报文,置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe (IB_WC_WR_FLUSH_ERR)
请求端:上送error  cqe (IB_WC_REM_INV_REQ_ERR),置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe(IB_WC_WR_FLUSH_ERR)

7、RX 处理send消息的rqe不正确,无法通过lkey找到mr

接收端:上送error  cqe  (IB_WC_LOC_QP_OP_ERR),回复remote 操作错误的NAK报文,置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe (IB_WC_WR_FLUSH_ERR)
请求端:上送error  cqe (IB_WC_REM_OP_ERR),置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe(IB_WC_WR_FLUSH_ERR)

8、RX aiomic addr不是8字节对齐

接收端:上送error  cqe (IB_WC_REM_INV_REQ_ERR),回复无效请求NAK报文,置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe (IB_WC_WR_FLUSH_ERR)
请求端:上送error  cqe (IB_WC_REM_INV_REQ_ERR),置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe (IB_WC_WR_FLUSH_ERR)

9、RX cq full

首先上送IB_EVENT_CQ_ERR异步事件,然后置QP error,上送IB_EVENT_QP_FATAL事件,flush sq、cq。此时如果有CQ,就上送error cqe (IB_WC_WR_FLUSH_ERR);没有CQ就不处理。

10、read reply组包成功,发送失败

尝试发送RNR NAK,对端重试。和没有rqe的处理一样。此时可能会发不过去,对端极大可能是重传请求。

三、ACK流程

1、ack不处理报文的情况:

  • QP是无效的
  • QP状态是error
  • QP状态是reset

将收包buf中的报文全部丢弃,如果QP状态是error,将SQ消耗完,上送error cqe (IB_WC_WR_FLUSH_ERR)

2、retry标记被置位,不处理ack报文。因为retry表示需要更新pending wqe的状态,处理ack报文,也需要处理pending wqe。两边不能同时操作同一个pending wqe。

3、从SQ中根据CI获取pendingwqe

if (wqe->status == 待发送)
      ->如果是retry超时触发ack的流程,修改retry超时定时器,等待RX流程处理wqe
      ->其他情况,直接退出。
else if (wqe->status == 已完成处理)(不需要ack的报文:rdma write),则上送cqe,更新CI
esle if (wqe->status == error) 上送error cqe。置QP error
else if (wqe->status == 其他状态)
      ->如果是retry超时触发ack的流程,修改retry超时定时器,置retry标记,等待RX流程重传报文
      ->如果是报文触发的ack流程,继续推进状态机。其他情况,直接退出

4、ack psn校验

  • ack_pkt->psn 大于预期psn,表示是累计ack,上送cqe,更新ci。处理pending wqe到ack_pkt->psn。如果过程中的pending wqe == rdma read / atomic。触发重传流程。
  • ack_pkt->psn 小于预期psn,表示是一个重复请求回复的ack。如果pending wqe的psn == ack_pkt->psn,要上送cqe,更新ci。否则丢包

5、ack pkt_hdr校验

  • ack报文除了read read middle报文都需要有AETH头部。上送error cqe(IB_WC_FATAL_ERR),置QP error,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe (IB_WC_WR_FLUSH_ERR) 。
  • ack报文和pending wqe的opcode 不匹配,上报error cqe(IB_WC_FATAL_ERR), 置QP error,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe (IB_WC_WR_FLUSH_ERR)
  • RNR NAK报文,修改rnr定时器,重传报文
  • 其他NAK报文,见上文RX部分
  • RDMA read resp报文。如果报文不完整(first, middle, last)上送error cqe(IB_WC_FATAL_ERR),置QP error,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe  (IB_WC_WR_FLUSH_ERR) 。

6、cq full,rxe的处理目前只上送IB_EVENT_CQ_ERR异步事件。没有其他处理。(不是很理解,应该要和rq对应的cq full处理一样)

7、read read/atomic 处理失败。上送error cqe(), 置QP error,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe  (IB_WC_WR_FLUSH_ERR) 。

8、当QP state == SQD,且ack_psn是最后一个psn时,上送IB_EVENT_SQ_DRAINED事件。

四、ibv_get_async_event()事件简要分析

五、ibv_poll_cq() 非success的简要分析

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

softroce-rxe收发包的异常处理流程分析

2023-10-20 07:53:32
59
0

一、TX流程上的异常处理

1、TX不处理报文的情况

  • QP被置为无效状态(QP destory);
  • QP状态是reset、error状态
  • QP状态不是ready状态

2、TX方向上送error  cqe

  • wqe opcode不正确,不支持,上送error cqe(IB_WC_LOC_QP_OP_ERR)
  • wqe 处理失败(mr不正确、发送失败等等),上送 error cqe(IB_WC_LOC_PROT_ERR), 置QP为error状态, 上送IB_EVENT_QP_FATAL事件,Flush SQ、RQ、上送error cqe (IB_WC_WR_FLUSH_ERR)

3、TX方向重传处理,主要是修改wqe的状态,重置重传标记。由ACK流程置重传标记。

for()遍历CI和PI之间的wqe,
   ->if (wqe->state == done) continue;
   ->if (wqe->state == post) break; 说明从这个wqe之后都是之前没有处理的wqe
   ->修改wqe的状态的待处理发送。对第一个要重传的wqe,计算从那个psn进行重传,计算好数据的addr和len

4、retry timer更新

首先retry timer每当处理一个wqe后,重置retry timer。retry timer到期后执行ack处理流程。因为是否需要retry,由当前接收到的ack报文决定。

5、当QP status == sqd时,上送IB_EVENT_SQ_DRAINED异步事件。

二、RX流程上的异常处理

1、RX不处理报文的情况

  • QP状态是RESET状态,丢弃报文
  • QP状态是ERROR状态,丢弃报文,上送error cqe(IB_WC_WR_FLUSH_ERR),flush qp

2、RX resp psn校验:

  • 如果收到的报文psn > 预期的psn,说明有丢包现象。
接收端:回复PSN乱序报文,报文携带本端预期的psn。这个报文存在一个隐藏信息:psn的隐式确认。
请求端:收到PSN乱序的报文后
  ->首先比较报文中的psn和本端的ack psn,if (pkt->psn > ack_psn)  更新ack_psn。
      ->if (retry_cnt > 0) :准备重传,if (retry_cnt != 7)  retry_cnt --。
      ->比较send_psn和ack_psn。if (send_psn > ack_psn) ,重传报文
  ->else (retry_cnt <= 0); 上送error cqe (IB_WC_RETRY_EXC_ERR),置QP error,上送IB_EVENT_QP_FATAL事件,flush SQ、RQ,上送error cqe (IB_WC_WR_FLUSH_ERR)
  • 如果收到的报文psn < 预期的psn,说明是重复请求。
->if (opcode == (send || write))  回复ACK。请求端:如果psn对应wqe还处理pending状态,上送IB_WC_SUCCESS cqe,ci++,然后更新ack_psn
->if (opcode == read req)  (前提:read和atomic有最大并发数, qp_attr配置字段max_dest_rd_atomic)。从接收资源中遍历查找匹配的read req。匹配规则:psn和opcode
    ->if (没有找到),不处理此报文。原因是read的并发有数量限制,如果没有找到,那说明read req端是收到了read resp。这个报文可能是延迟的无效请求包
    ->else (找到)  ,那就是一个有效的重复请求包,确保rkey,addr,len都是前一个包的字迹。按照请求长度回复read resp(可能多个包)
->if (opcode == atomic req) 和read req是一样的处理逻辑。

3、RX resp opcode校验

  • first、middle、last 报文没有按照顺序来。两种情况:丢失first;丢失last。
  • opcode不支持
  • 如果max_dest_rd_atomic <= 0,表示不支持read req/ atomic req。
接收端:上送error  cqe (IB_WC_REM_INV_REQ_ERR),回复无效请求NAK报文,置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe (IB_WC_WR_FLUSH_ERR)
请求端:上送error  cqe (IB_WC_REM_INV_REQ_ERR),置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe (IB_WC_WR_FLUSH_ERR)

 

说明:qp按照max_dest_rd_atomic大小申请缓存的read/atomic req空间。按照先进先出的原则

4、RX rqe资源校验

  • 没有rqe。
接受端:回复RNR_NAK,报文携带psn和min_rnr_timer。然后丢弃此报文。
请求端:处理RNR NAK报文。
   ->if (rnr_retry > 0) : if (rnr_retry != 7) rnr_retry --,然后按照min_rnr_timer时间,修改定时器的超时时间,定时器到期后重传。
   ->else (rnr_retry <=0):上送error cqe (IB_WC_RNR_RETRY_EXC_ERR),置QP error,上送IB_EVENT_QP_FATAL事件,flush SQ、RQ,上送error cqe (IB_WC_WR_FLUSH_ERR)

5、RX mr校验

  • read / write 的dma length == 0时,不需要查找mr。
  • 没有找到mr。(mr_index不正确;access不正确;rkey不正确;pd不正确;mr范围不匹配)。
接收端:上送error  cqe  (IB_WC_REM_ACCESS_ERR),回复remote memory access NAK报文,置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe (IB_WC_WR_FLUSH_ERR)
请求端:上送error  cqe (IB_WC_REM_ACCESS_ERR),置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe  (IB_WC_WR_FLUSH_ERR)

6、RX 校验包的长度:

  • 如果send/write first / middle 报文长度不等于mtu
  • send/write only / last 需要小于等于mtu
  • send报文的长度大于rqe 所有sge的长度
接收端:上送error  cqe  (IB_WC_REM_INV_REQ_ERR),回复无效的请求NAK报文,置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe (IB_WC_WR_FLUSH_ERR)
请求端:上送error  cqe (IB_WC_REM_INV_REQ_ERR),置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe(IB_WC_WR_FLUSH_ERR)

7、RX 处理send消息的rqe不正确,无法通过lkey找到mr

接收端:上送error  cqe  (IB_WC_LOC_QP_OP_ERR),回复remote 操作错误的NAK报文,置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe (IB_WC_WR_FLUSH_ERR)
请求端:上送error  cqe (IB_WC_REM_OP_ERR),置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe(IB_WC_WR_FLUSH_ERR)

8、RX aiomic addr不是8字节对齐

接收端:上送error  cqe (IB_WC_REM_INV_REQ_ERR),回复无效请求NAK报文,置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe (IB_WC_WR_FLUSH_ERR)
请求端:上送error  cqe (IB_WC_REM_INV_REQ_ERR),置QP error状态,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe (IB_WC_WR_FLUSH_ERR)

9、RX cq full

首先上送IB_EVENT_CQ_ERR异步事件,然后置QP error,上送IB_EVENT_QP_FATAL事件,flush sq、cq。此时如果有CQ,就上送error cqe (IB_WC_WR_FLUSH_ERR);没有CQ就不处理。

10、read reply组包成功,发送失败

尝试发送RNR NAK,对端重试。和没有rqe的处理一样。此时可能会发不过去,对端极大可能是重传请求。

三、ACK流程

1、ack不处理报文的情况:

  • QP是无效的
  • QP状态是error
  • QP状态是reset

将收包buf中的报文全部丢弃,如果QP状态是error,将SQ消耗完,上送error cqe (IB_WC_WR_FLUSH_ERR)

2、retry标记被置位,不处理ack报文。因为retry表示需要更新pending wqe的状态,处理ack报文,也需要处理pending wqe。两边不能同时操作同一个pending wqe。

3、从SQ中根据CI获取pendingwqe

if (wqe->status == 待发送)
      ->如果是retry超时触发ack的流程,修改retry超时定时器,等待RX流程处理wqe
      ->其他情况,直接退出。
else if (wqe->status == 已完成处理)(不需要ack的报文:rdma write),则上送cqe,更新CI
esle if (wqe->status == error) 上送error cqe。置QP error
else if (wqe->status == 其他状态)
      ->如果是retry超时触发ack的流程,修改retry超时定时器,置retry标记,等待RX流程重传报文
      ->如果是报文触发的ack流程,继续推进状态机。其他情况,直接退出

4、ack psn校验

  • ack_pkt->psn 大于预期psn,表示是累计ack,上送cqe,更新ci。处理pending wqe到ack_pkt->psn。如果过程中的pending wqe == rdma read / atomic。触发重传流程。
  • ack_pkt->psn 小于预期psn,表示是一个重复请求回复的ack。如果pending wqe的psn == ack_pkt->psn,要上送cqe,更新ci。否则丢包

5、ack pkt_hdr校验

  • ack报文除了read read middle报文都需要有AETH头部。上送error cqe(IB_WC_FATAL_ERR),置QP error,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe (IB_WC_WR_FLUSH_ERR) 。
  • ack报文和pending wqe的opcode 不匹配,上报error cqe(IB_WC_FATAL_ERR), 置QP error,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe (IB_WC_WR_FLUSH_ERR)
  • RNR NAK报文,修改rnr定时器,重传报文
  • 其他NAK报文,见上文RX部分
  • RDMA read resp报文。如果报文不完整(first, middle, last)上送error cqe(IB_WC_FATAL_ERR),置QP error,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe  (IB_WC_WR_FLUSH_ERR) 。

6、cq full,rxe的处理目前只上送IB_EVENT_CQ_ERR异步事件。没有其他处理。(不是很理解,应该要和rq对应的cq full处理一样)

7、read read/atomic 处理失败。上送error cqe(), 置QP error,上送IB_EVENT_QP_FATAL事件,flush qp,上送error cqe  (IB_WC_WR_FLUSH_ERR) 。

8、当QP state == SQD,且ack_psn是最后一个psn时,上送IB_EVENT_SQ_DRAINED事件。

四、ibv_get_async_event()事件简要分析

五、ibv_poll_cq() 非success的简要分析

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