使用netmap接收网卡数据,对接收的数据进行解析。
下一步,对网卡驱动进行分析,研究网卡是如何进行数据的发送和接收的。
#include<stdio.h>
#include<unistd.h>
#include<sys/poll.h>
#define NETMAP_WITH_LIBS
#include<net/netmap_user.h>
#pragma pack(1)
struct udphdr {
unsigned short source;
unsigned short dest;
unsigned short len;
unsigned short check;
};
struct iphdr {
unsigned char version:4;
unsigned char ihl:4;
unsigned char tos;
unsigned short tot_len;
unsigned short id;
unsigned short frag_off;
unsigned char ttl;
unsigned char protocol;
unsigned short check;
unsigned int saddr;
unsigned int daddr;
};
#define ETH_ALEN 6
#define PROTO_IP 0x0800
#define PROTO_UDP 17
struct ethhdr {
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
unsigned short h_proto; /* packet type ID field */
};
// 字节对齐问题
struct udppkt
{
struct ethhdr eh;
struct iphdr ip;
struct udphdr udp;
unsigned char data[]; //柔性数组,或者写成data[0]
// 特性:可以data[1] = 'a',不会越界 sizeof()一直为0
};
/**
* 1:协议栈的数据封装如上,结构体原型参考资料上的结构
* 2:如何抓取网络原始数据
* 1) raw socket
* 2) pf_ring
* 3) netmap
* 4) dpdk
* 本次sample code 以netmap为例
*
* data--->网卡---dma/其他方式--->内存
* 对内存中的相应的地址进行操作就是对网卡中的
* 数据进行操作
*/
int main()
{
// 测试柔性数组代码
// unsigned char data[0];
// printf("len :%d\n", sizeof(data));
// data[1] = 100;
// printf("len :%d\n", sizeof(data));
struct nm_desc* nmr = nm_open("netmap:eth0", NULL, 0, NULL);
if(nmr == NULL)
return 0;
struct pollfd pfd = {0};
pfd.fd = nmr->fd; // fd标识网卡信息,可以监控网卡中是否有数据
pfd.events = POLLIN;
struct nm_pkthdr h;
while (1)
{
int ret = poll(&pfd, 1, -1);
if(ret < 0)
continue;
if(pfd.eventd& POLLIN)
{
char* stream = nm_nextpkt(nmr, &h);
printf("stream: %s\n",stream);
struct ethhdr* eh = (struct ethhdr*)stream;
if(ntohs(eh->h_proto) == PROTO_IP)
{
struct udppkt* udp = (struct udppkt*)stream;
if(udp->ip.protocol == PROTO_UDP)
{
int udp_length = ntohs(udp->udp.len);
udp->data[udp->udp.len] ='\0';
printf("udp->%s\n", udp->data);
}
}
}
}
return 0;
}