相关代码:DPDK_Learning/ARP_response at main · mfdycs/DPDK_Learning (github.com)
相关原理
ARP数据包
- ARP Request
- ARP Response
ARP的功能
- 1.响应其他机器的arp request(本章实现)
- 2.定时主动发送arp request,响应其他机器的arp reply,记录在arp table中
ARP是一个广播协议,不是一对一的通信
ARP操作
# 查看arp表
arp -a
# 查看网卡对应的信息
netsh i i show in
# 删除网卡的arp表
netsh i i delete neighbors 22
## 此时再使用工具发送数据包,会发现找不到对应的arp映射
# 添加arp映射
netsh -c i i add neighbors 22 192.168.81.128 XX-XX-XX-XX-XX-XX
# 此时发送数据正常
对于DPDK,响应ARP请求一共有三个步骤:
- 识别ARP请求
- 是否是自己的机器
- 发送ARP响应
添加标识
#define ENABLE_ARP 1
与UDP发送类似,构造ARP响应
#if ENABLE_ARP
static int ng_encode_arp_pkt(uint8_t *msg, uint8_t *dst_mac, uint32_t sip, uint32_t dip)
{
// 1 ethhdr
struct rte_ether_hdr *eth = (struct rte_ether_hdr *)msg;
rte_memcpy(eth->s_addr.addr_bytes, gSrcMac, RTE_ETHER_ADDR_LEN);
rte_memcpy(eth->d_addr.addr_bytes, dst_mac, RTE_ETHER_ADDR_LEN);
eth->ether_type = htons(RTE_ETHER_TYPE_ARP);
// 2 arp
struct rte_arp_hdr *arp = (struct rte_arp_hdr *)(eth + 1); // eth首部下一位
arp->arp_hardware = htons(1); // 硬件类型
arp->arp_protocol = htons(RTE_ETHER_TYPE_IPV4); // 协议类型
arp->arp_hlen = RTE_ETHER_ADDR_LEN; // 硬件地址长度
arp->arp_plen = sizeof(uint32_t); // 协议地址长度: len(ipv4)
arp->arp_opcode = htons(2); // 操作码
rte_memcpy(arp->arp_data.arp_sha.addr_bytes, gSrcMac, RTE_ETHER_ADDR_LEN); // 发送者硬件地址
rte_memcpy( arp->arp_data.arp_tha.addr_bytes, dst_mac, RTE_ETHER_ADDR_LEN); // 接收者硬件地址
arp->arp_data.arp_sip = sip;
arp->arp_data.arp_tip = dip;
return 0;
}
static struct rte_mbuf* ng_send_arp(struct rte_mempool *mbuf_pool, uint8_t *dst_mac, uint32_t sip, uint32_t dip)
{
// len(arp:42) = len(eth:14) + len(arp:28)
const unsigned total_length = sizeof(struct rte_ether_hdr) + sizeof(struct rte_arp_hdr);
struct rte_mbuf *mbuf = rte_pktmbuf_alloc(mbuf_pool);
if (!mbuf) {
rte_exit(EXIT_FAILURE, "rte_pktmbuf_alloc\n");
}
mbuf->pkt_len = total_length;
mbuf->data_len = total_length;
uint8_t *pkt_data = rte_pktmbuf_mtod(mbuf, uint8_t *);
ng_encode_arp_pkt(pkt_data, dst_mac, sip, dip);
return mbuf;
}
#endif
主函数解析数据并识别
#if ENABLE_ARP
if (ethr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP)) {
struct rte_arp_hdr *arp_hdr = rte_pktmbuf_mtod_offset(mbufs[i], struct rte_arp_hdr*, sizeof(struct rte_ether_hdr));
struct in_addr addr;
addr.s_addr = arp_hdr->arp_data.arp_tip;
printf("arp ---> src: %s ", inet_ntoa(addr));
addr.s_addr = gLocalIp;
printf("arp ---> local: %s \n", inet_ntoa(addr));
if (arp_hdr->arp_data.arp_tip == gLocalIp) {
struct rte_mbuf *arpbuf = ng_send_arp(mbuf_pool, arp_hdr->arp_data.arp_sha.addr_bytes,
arp_hdr->arp_data.arp_tip, arp_hdr->arp_data.arp_sip);
rte_eth_tx_burst(DPDK_PortID, 0, &arpbuf, 1);
rte_pktmbuf_free(arpbuf);
rte_pktmbuf_free(mbufs[i]);
}
continue;
}
#endif
此时 ping 主机会显示Timeout,因为没有实现icmp协议,但是ARP响应流通(否则会显示不可到达)