下载
中文
注册

开发流程

介绍RPing功能实现的详细流程。

总体流程

RPing功能开发的流程总览如下图所示。

图1 RPing功能开发流程

详细步骤

  1. 初始化RPing功能,启动网络状态监测。

    调用HccnRpingInit接口进行RPing功能初始化,对于每一个参与RPing监测功能的NPU,都需要调用一次该接口。且一个进程里,一个NPU仅能调用一次该接口,不支持重复调用。

    初始化RPing功能前,首先需要定义HccnRpingInitAttr对象,初始化相关信息,并指定Device,代码片段示例如下:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
        // 初始化信息配置
        int ipLen = 16;
        int devId = 4;
        HccnRpingInitAttr *initAttr = new HccnRpingInitAttr();
        initAttr->mode = HCCN_RPING_MODE_ROCE; // 网络类型,当前只支持RoCE类型
        initAttr->port = 13886; // 侦听端口,指定一个未使用的端口即可
        initAttr->npuNum = 128; // 参与此次探测的全部NPU数量,即需要初始化的NPU个数
        initAttr->bufferSize = 4096 * 50; // 配置值需要4K对齐,且必须大于:向每个探测目标的发包数量 * 2048 * 目标NPU数量
        initAttr->ipAddr = new char[ipLen];
        strcpy(initAttr->ipAddr, deviceIp[devId]);
        HccnRpingCtx rpingCtx = nullptr;
        aclrtSetDevice(devId); // 初始化之前需要指定Device
        HccnRpingInit(devId, initAttr, &rpingCtx); // 调用初始化接口,获取RPingCtx
    
  2. 添加探测目标,建立发送端client NPU与接收端target NPU之间的RPing通信链路。
    调用HccnRpingAddTarget接口为作为client的NPU添加target,target即为需要被探测的NPU。
    • 调用该接口前,需要定义被探测的target信息,类型为HccnRpingTargetInfo
    • 调用该接口之后,如果目标target超过120s还没有通过HccnRpingInit接口初始化,会超时失败。
    • 该接口可以反复调用,并支持按照IP地址为target信息去重,只保留第一个target信息。
    • 该接口有一个targrt添加失败就会返回错误。
    • 该接口支持一次最多添加16个target,若需要添加的target总数超过16个,请多次调用该接口实现。
    添加探测目标的代码片段示例如下:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
        // 添加探测target
        char deviceIp[8][16] = 
        {   
            "192.168.99.127",
            "192.168.99.128",
            "192.168.99.129",
            "192.168.99.130",
            "192.168.99.131",
            "192.168.99.132",
            "192.168.99.133",
            "192.168.99.134"
        };
        int ipLen = 16;
    
        int targetNum = devices.size() - 1;
        HccnRpingTargetInfo *target = new HccnRpingTargetInfo[targetNum];
        for (int i = 0; i < devices.size() - 1; i++) {
            int devTargetId = devices[i]; // 从devices向量中取出target的deviceLogicId
            target[i].srcPort = 0; // tcp/udp 源端口
            target[i].sl = 4; // RDMA网卡的service level , 取值范围:[0,7]
            target[i].tc = (33 & 0x3f) << 2; // RDMA网卡的traffic class,配置为RoCE报文的DSCP值 * 4
            target[i].port = 13886; // socket连接端口,与target device初始化时配置的port一致
            target[i].srcIp = new char[ipLen];
            target[i].dstIp = new char[ipLen];
            strcpy(target[i].srcIp, deviceIp[devClientId]);
            strcpy(target[i].dstIp, deviceIp[devTargetId]);
        }
        if (rpingCtx == nullptr) {
            printf("rpingCtx is null!\n");
            return -1;
        }
        HccnRpingAddTarget(rpingCtx, targetNum, target);
    

    HccnRpingAddTarget接口可以按照HccnRpingTargetInfo对象中“dstIp”的值对入参中的target数组去重。targetNum需要与target数组大小一致,否则可能会导致数组访问越界。

  3. 发起探测请求。
    调用HccnRpingBatchPingStart接口发起探测请求,开起BatchPing任务,client NPU会按照该接口中配置的发包数量及间隔时间向target NPU发送探测包。
    • 该接口调用前需要确保client NPU上已添加需要探测的target NPU信息,并且未处在探测任务执行的状态(即未处在BatchPing任务的执行状态)。
    • 如果想要重复调用该接口,可以在调用前先调用HccnRpingBatchPingStop接口终止BatchPing任务。

    发起探测请求的代码片段示例如下:

    1
    2
    3
    4
        uint32_t pktNum = 10;   // 发给每个target的报文数量
        uint32_t interval = 1;  // 发送报文的间隔时间,单位为ms
        uint32_t timeout = 100; // client从发包到收包的等待的最大时长,单位为ms
        HccnRpingBatchPingStart(rpingCtx, pktNum, interval, timeout);
    

    HccnRpingBatchPingStart接口在发起探测之前会校验HccnRpingInit接口配置的bufferSize值,bufferSize值需要大于“pktNum * 2048 * targetNum”,其中pktnum为向每个探测目标的发包数量,targetNum为该client要探测的target NPU总数。

  4. 调用HccnRpingGetResult接口获取探测结果。

    探测结果以数组的形式呈现,每一个元素中存储的是探测target返回的信息。该接口不支持去重,因此需要确保入参中的“target”不包含重复信息。探测结果中的“state”字段代表了该探测结果的有效性,每个target result都会有一个对应的state,当其值为“HCCN_RPING_RESULT_STATE_VALID”时,代表结果真实有效,否则结果无效。

    获取探测结果的代码片段示例如下:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
        // 获取探测结果
        HccnRpingResultInfo *result = new HccnRpingResultInfo[targetNum];
        HccnResult hccnRet = HCCN_E_AGAIN;
        while(hccnRet == HCCN_E_AGAIN) {
            sleep(1);
            hccnRet =  HccnRpingGetResult(rpingCtx, targetNum, target, result);
        }
        for (int i = 0; i < targetNum; i++) {
            printf("txPkt[%u] rxPkt[%u] minRTT[%u] maxRTT[%u] avgRTT[%u] state[%u] payloadLen[%u]\n",
                result[i].txPkt, // 发送报文数
                result[i].rxPkt, // 接收报文数
                result[i].minRTT,// 最小收发包时延
                result[i].maxRTT,// 最大收发包时延
                result[i].avgRTT,// 平均收发包时延
                result[i].state);// 获取结果的状态
        }
    
  5. 中止探测任务

    获取结果之后,调用HccnRpingBatchPingStop接口中止探测任务。

    1
    2
        // 中止探测任务    
        HccnRpingBatchPingStop(rpingCtx);
    
  6. 移除探测目标

    结束探测任务之前,移除添加的探测目标,断开先前建立的RPing通信链路。

    • 该接口调用前须确保没有探测任务在执行。
    • 该接口调用前要保证有target信息添加过。
    1
    2
        // 删除探测目标
        HccnRpingRemoveTarget(rpingCtx, targetNum, target);
    
  7. 释放RPing资源。

    进程结束前需要调用HccnRpingDeinit接口释放内存资源。

    • 该接口必须在HccnRpingInit接口调用并返回成功的情形下才可以调用,否则会释放不存在的内存资源导致异常。
    • 该接口无法重复调用,重复调用会导致对内存的重复释放,可能造成段错误甚至coredump。
    1
    2
        // 释放内存
        HccnRpingDeinit(rpingCtx);