【C/C++】手写 DPDK 协议栈(四):实现 ICMP Echo Reply,让 ping 通起来

📅 2026/7/29 7:16:00
【C/C++】手写 DPDK 协议栈(四):实现 ICMP Echo Reply,让 ping 通起来
目录手写 DPDK 协议栈四实现 ICMP Echo Reply让 ping 通起来1. Echo 报文结构2. 接收并定位协议头3. 原地改包与重算校验和4. 实验结果小结手写 DPDK 协议栈四实现 ICMP Echo Reply让 ping 通起来标签DPDKICMPpingIPv4icmp/icmp.c将 ARP 之后的 IPv4 分流继续推进到 ICMP。Echo Request/Reply 是最适合验证三层收发正确性的协议不需要端口和连接状态但要求正确交换地址并重算校验和。1. Echo 报文结构ICMP Echo: | Type 1B | Code 1B | Checksum 2B | Identifier 2B | Sequence 2B | Data N字节 | 字段 长度 Request Reply 作用 type 1 字节 8 0 ICMP 消息类型。8 表示 ping 请求0 表示 ping 应答。 code 1 字节 0 0 类型下的细分原因。Echo 类型里固定为 0。 checksum 2 字节 计算值 重新计算值 ICMP 校验和覆盖 ICMP 头 ICMP 数据不包含 IP 头也没有 UDP/TCP 那种伪首部。 identifier 2 字节 请求方设置 原样返回 标识一次 ping 会话常用于区分不同进程或不同 ping 实例。 sequence 2 字节 请求方递增 原样返回 序列号用来判断第几个 Echo 包也用于计算丢包和 RTT。 data N 字节 任意数据 原样返回 ping 负载。Reply 必须把 Request 的数据原样带回去。请求type8应答type0identifier、sequence和 payload 都应原样返回。ICMP 校验和覆盖 ICMP 头和数据不包含 IP 伪首部。2. 接收并定位协议头structrte_ether_hdr*ethrte_pktmbuf_mtod(mbuf,structrte_ether_hdr*);structrte_ipv4_hdr*iprte_pktmbuf_mtod_offset(mbuf,structrte_ipv4_hdr*,sizeof(*eth));if(ip-next_proto_id!IPPROTO_ICMP)return;structrte_icmp_hdr*icmp(structrte_icmp_hdr*)(ip1);if(icmp-icmp_type!RTE_IP_ICMP_ECHO_REQUEST)return;示例假定 IPv4 头为标准 20 字节。更通用的实现应从version_ihl得到IHL * 4并对 mbuf 长度、IP 总长度做边界检查。3. 原地改包与重算校验和icmp-icmp_typeRTE_IP_ICMP_ECHO_REPLY;icmp-icmp_code0;icmp-icmp_cksum0;icmp-icmp_cksumrte_raw_cksum(icmp,icmp_len);ip-hdr_checksum0;ip-hdr_checksumrte_ipv4_cksum(ip);/* 交换 Ethernet 和 IPv4 的源、目的地址后发送 */原地回包可减少一次分配但一定要在发送前同时交换二层和三层地址并在所有字段更新完成后重新计算校验和。4. 实验结果ping成功意味着主机已通过 ARP 找到 DPDK 网卡 MACDPDK 正确解析 IPv4/ICMP且回包的以太网头、IP 头与 ICMP 校验和全部有效。小结ICMP 是第一个“真正穿过 IPv4”的协议实验。它验证了偏移解析、网络字节序、校验和和回包地址交换为 UDP、TCP 的组包与分发打下了同一套基础。学习链接: https://github.com/0voice