文章目录
- 1、安装编译netmap
- 2、使用netmap
- 3、运行编写自己的代码
1、安装编译netmap
github地址
git clone https://github.com/luigirizzo/netmap
1、进入目录
cd netmap-master/LINUX
2、安装编译环境
apt-get install build-essential
3、初始化配置环境
./configure
出现这个界面不是卡住了,需要长时间等待完成,这个过程可能比较长,运行到下面表示成功
4、编译和安装
make && make install
2、使用netmap
每次使用前都需要insmod netmap.ko ,然后我们查看ls /dev/netmap -l,出现下面的设备就说明开启成功了。
# 在netmap-master/LINUX执行
insmod netmap.ko
ls /dev/netmap -l
取消加载
rmmod netmap
3、运行编写自己的代码
# 头文件 #include<net/netmap_user.h> 在 /netmap/sys/目录下
gcc -o nty_udp nty_udp.c -I /netmap/sys/
#include <stdio.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#define NETMAP_WITH_LIBS
#include <net/netmap_user.h>
#define ETH_ADDR_LENGTH 6
#define PROTO_IP 0x0800
#define PROTO_ARP 0x0806
#define PROTO_UDP 17
#pragma pack(1)
// 以太网帧头 14字节
struct ethhdr{
unsigned char h_dst[ETH_ADDR_LENGTH];
unsigned char h_stc[ETH_ADDR_LENGTH];
unsigned short h_proto;
};
// ip头 20字节
struct iphdr{
// 位域 版本表示:使用的是ipv4还是ipv6
// 首部长度表示:最大长度可以是 15*4=60
unsigned char hdrlen:4,
version:4;
unsigned char tos;
unsigned short tolen;
unsigned short flag_offset;
unsigned char ttl;
unsigned char type;
unsigned long check;
unsigned int sip;
unsigned int dip;
};
struct updhdr{
unsigned short sport;
unsigned short dport;
unsigned short length;
unsigned short check;
};
struct arphdr{
unsigned short h_type;
unsigned short h_proto;
unsigned char h_addr;
unsigned char h_protolen;
unsigned char oper;
unsigned char smac[ETH_ADDR_LENGTH];
unsigned int sip;
unsigned char dmac[ETH_ADDR_LENGTH];
unsigned int dip;
};
struct udppkt{
struct ethhdr eh;
struct iphdr ip;
struct udphdr upd;
// 数据长度不确定,所以使用柔性数组
unsigned char data[0];
};
struct arppkt{
struct ethhdr eh;
struct arphdr arp;
};
// 在netmap目录下
// insmod netmap.ko
// ls /dev/netmap -l
int main()
{
//
struct nm_pkthdr head;
struct nm_desc *nmr = nm_open("netmap:eth0",NULL,0,NULL);
if(nmr == NULL) return -1;
// 通过poll检测是否有事件读事件来了
struct pollfd pfd = {0};
pfd.fd = nmr->fd;
while(1){
int ret = poll(&pfd,1,-1);
if(ret < 0) continue;
if(pfd.revents & POLLIN){
// 从ringbuffer环形队列中取出一帧数据
unsigned char *stream = nm_nextpkt(nmr,&h);
// 解包
struct ethhdr *eh = (struct ethhdr*)stream;
if(ntohs(eh->h_proto) == PROTO_IP){
struct udppkt *udp = (struct udppkt*)stream;
if(upd->ip.type == PROTO_UDP){
int udplength = ntohs(udp->udp.length);
udp->data[udplength-8] = '\0';
printf("%s\n",udp->data);
}
}else if (ntohs(eh->h_proto) == PROTO_ARP){
// 先判断
struct arppkt *arp = (struct arppkt*)stream;
struct arppkt arp_rt;
if(arp->arp.dip == inet_addr("192.168.0.123")){
}
}
}
}
return 0;
}