You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用PcapPlusPlus获取并打印E2AP报文详情?

基于PcapPlusPlus解析并打印E2AP报文详情的实现步骤

1. 确认环境配置

确保你的开发环境已正确安装PcapPlusPlus,编译项目时链接必要的库:Pcap++、Packet++、Common++,同时将PcapPlusPlus的include目录加入头文件搜索路径。

2. 读取或捕获E2AP流量

E2AP基于SCTP传输,通常承载在IPv4/IPv6之上。你可以选择读取本地pcap文件(适合测试)或捕获实时网卡流量,以下是读取pcap文件的基础代码:

#include <PcapFileDevice.h>
#include <Packet.h>
#include <EthLayer.h>
#include <IPv4Layer.h>
#include <IPv6Layer.h>
#include <SctpLayer.h>

using namespace pcpp;

int main() {
    // 打开目标pcap文件
    PcapFileReaderDevice reader("e2ap_traffic.pcap");
    if (!reader.open()) {
        printf("无法打开pcap文件\n");
        return 1;
    }

    RawPacket rawPacket;
    while (reader.getNextPacket(rawPacket)) {
        Packet parsedPacket(&rawPacket);
        // 后续解析逻辑嵌入此处
    }

    reader.close();
    return 0;
}

3. 逐层解析到SCTP payload

从以太网帧开始,逐层剥离协议层,最终提取承载E2AP的SCTP数据块:

// 在上述while循环内添加以下代码
EthLayer* ethLayer = parsedPacket.getLayerOfType<EthLayer>();
if (!ethLayer) continue;

// 解析IP层(兼容IPv4/IPv6)
Layer* ipLayer = parsedPacket.getLayerOfType<IPv4Layer>();
if (!ipLayer) {
    ipLayer = parsedPacket.getLayerOfType<IPv6Layer>();
    if (!ipLayer) continue;
}

// 解析SCTP层
SctpLayer* sctpLayer = parsedPacket.getLayerOfType<SctpLayer>();
if (!sctpLayer) continue;

// 遍历SCTP数据块,筛选承载E2AP的DATA块
for (const auto& chunk : sctpLayer->getChunks()) {
    if (chunk->getChunkType() == SCTP_DATA_CHUNK) {
        SctpDataChunk* dataChunk = dynamic_cast<SctpDataChunk*>(chunk);
        if (!dataChunk) continue;
        // 获取E2AP原始字节流
        const uint8_t* e2apPayload = dataChunk->getData();
        size_t e2apPayloadLen = dataChunk->getDataLen();
        if (e2apPayloadLen == 0) continue;

        // 调用解析函数处理E2AP报文
        parseAndPrintE2AP(e2apPayload, e2apPayloadLen);
    }
}

4. 解析并打印E2AP核心字段

E2AP遵循3GPP TS 38.463协议,核心结构包含PDU类型、Procedure Code、Criticality及各类IE。由于PcapPlusPlus默认未封装E2AP解析器,需手动实现核心字段解析,示例如下:

void parseAndPrintE2AP(const uint8_t* payload, size_t len) {
    if (len < 6) {
        printf("E2AP报文过短,无法解析\n");
        return;
    }

    // 解析PDU类型(第一个字节高4位)
    uint8_t pduType = (payload[0] >> 4) & 0x0F;
    const char* pduTypeStr;
    switch(pduType) {
        case 0: pduTypeStr = "Initiating Message"; break;
        case 1: pduTypeStr = "Successful Outcome"; break;
        case 2: pduTypeStr = "Unsuccessful Outcome"; break;
        default: pduTypeStr = "Unknown PDU Type"; break;
    }

    // 解析Procedure Code(第一个字节低4位 + 第二个字节)
    uint16_t procedureCode = ((payload[0] & 0x0F) << 8) | payload[1];
    // 解析Criticality(第三个字节)
    uint8_t criticality = payload[2];
    // 解析消息长度(第4-6字节,3字节无符号整数)
    uint32_t msgLength = ((payload[3] << 16) | (payload[4] << 8) | payload[5]);
    if (msgLength + 6 > len) {
        printf("E2AP报文长度不匹配,解析终止\n");
        return;
    }

    // 打印核心基础字段
    printf("=== E2AP报文详情 ===\n");
    printf("PDU类型: %s\n", pduTypeStr);
    printf("Procedure Code: %u\n", procedureCode);
    printf("Criticality: %u\n", criticality);
    printf("消息长度: %u\n", msgLength);

    // 解析并打印IEs
    parseE2APIEs(payload + 6, msgLength);
}

void parseE2APIEs(const uint8_t* iesPayload, size_t iesLen) {
    size_t offset = 0;
    printf("--- E2AP IEs 详情 ---\n");
    while (offset < iesLen) {
        if (offset + 4 > iesLen) break;
        // 解析IE类型(前2字节)
        uint16_t ieType = ((iesPayload[offset] << 8) | iesPayload[offset+1]);
        // 解析IE长度(后2字节)
        uint16_t ieLen = ((iesPayload[offset+2] << 8) | iesPayload[offset+3]);
        offset += 4;
        if (offset + ieLen > iesLen) break;

        printf("IE类型: %u, IE长度: %u\n", ieType, ieLen);
        // 根据IE类型解析具体内容(示例:RIC Request ID)
        switch(ieType) {
            case 0: 
                if (ieLen >= 8) {
                    uint32_t ricReqId = ((iesPayload[offset] << 24) | (iesPayload[offset+1] << 16) | (iesPayload[offset+2] << 8) | iesPayload[offset+3]);
                    uint32_t ricInstanceId = ((iesPayload[offset+4] << 24) | (iesPayload[offset+5] << 16) | (iesPayload[offset+6] << 8) | iesPayload[offset+7]);
                    printf("  RIC Request ID: %u, RIC Instance ID: %u\n", ricReqId, ricInstanceId);
                }
                break;
            // 可根据3GPP规范添加更多IE类型的解析逻辑
            default:
                printf("  未实现该IE类型的解析\n");
                break;
        }
        offset += ieLen;
    }
}

5. 关键注意事项

  • SCTP数据块可能存在分段,需实现SCTP重组逻辑才能获取完整的E2AP报文;
  • E2AP的IE解析需严格遵循3GPP TS 38.463规范,不同Procedure Code对应的IE集合存在差异;
  • 若需要更完整的解析能力,可使用ASN.1编译器(如asn1c)根据3GPP提供的E2AP ASN.1定义生成解析代码,再与PcapPlusPlus的代码集成。

内容的提问来源于stack exchange,提问作者VIkrant Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 01:25:27