多队列网卡,一个队列对应一个中断,中断可以绑定到一个cpu上,也可以将处理该队列数据的进程绑定到这个cpu上,就实现了一个队列一个进程,一一对应的关系。
多队列就是多中断,一个队列一个中断,也可以多队列共享一个中断。每个中断都是一个中断号,可以设置这个中断号所对应的cpu。
struct rte_mempool *rte_pktmbuf_pool_create(const char *name,
unsigned int n,
unsigned int cache_size,
uint16_t priv_size,
uint16_t data_room_size,
int socket_id);name:内存池的名字
n: 内存池中元素的个数,可以存放多少了mbuf
cache_size:每个核的缓存大小。0:关闭
priv_size:私有区域大小。
data_room_size:每一个mbuf数据区的大小
socket_id:CPU socket(NUMA 节点)struct rte_mempool *mbuf_pool = rte_pktmbuf_pool_create(“mbuf_pool”,NUM_MBUFS,0,0,RTE_MBUF_DEFAULT_BUF_SIZE,rte_socket_id());
创建内存池mbuf_pool。
NUM_MBUFS:4096-1
DPDK的mempoll底层用的是环形队列管理的,队列的大小刚好是2的幂,为了区分环形队列的满和空需要牺牲一个元素,所以在设置mempool的时候通常设置为2的幂减1。
mbuf_pool是内存池,mbuf是内存池中的元素,构造的协议帧就是存放在mbuf中,通常一个mbuf一个协议帧。
dpdk的所有数据都存放在内存池中,内存池的最小单位是mbuf。
struct rte_mbuf *mbuf = rte_pktmbuf_alloc(mbuf_pool);
在内存池中申请一个报文缓冲区,也就是空闲的mbuf。
这里分配的不是固定大小,而是分配可以从哪里开始使用的地址,表示mbuf从这个地址开始,至于mbuf的大小要看用户写进去多大的数据。但不可以超过data_room_size
计算机里面有物理内存和虚拟内存,首先cpu访问的是虚拟地址,通过查找页表翻译为物理地址,再通过物理地址取数据,如果页表中没有该数据就需要到磁盘中查找数据。内存与磁盘的交互最小单位是页默认是4k。
网卡接收到数据,数据后先被放入skbuff中,协议栈通过指针移动的方式逐层解析skbuff的数据协议,不对数据拷贝。
解析完把skbuff挂到socket的接收队列上。用户在调用recv时,就把接收队列中的skbuff的真正数据拷贝到用户空间。
skbuff中有一组指针,通过指针来界定数据的范围。
一份数据,一个 sk_buff,指针移动完成解析,最后只拷贝一次到用户态。
协议栈不是把数据读出来再重新组装,而是:每一层检查自己关心的头部字段(比如 IP 层看 iph->daddr,TCP 层看 th->dest),通过 skb_pull() 把 data 指针往后移动,相当于“剥掉”本层头部。
整个过程只移动指针,不搬数据。所以“解析”的产物并不是一份新的数据副本,而是同一个 sk_buff 的 data 指针指向了 payload 的起始位置。
大端序:高位在前,网络字节序
地址:012345678
数据:123456789
小端序:低位在前,本机字节序
地址:012345678
数据:987654321
h:host本机字节序
n:network网络字节序
l:long 32bit
s:short 16bit
uint32_t htonl(uint32_t hostlong); // host to network, long (32位)
uint16_t htons(uint16_t hostshort); // host to network, short (16位)
uint32_t ntohl(uint32_t netlong); // network to host, long
uint16_t ntohs(uint16_t netshort); // network to host, short
dpdk配置好以后需要在win端设置虚拟机的静态ip。如果不设置就无法接收到数据,因为Windows 端 ARP 解析失败,导致数据包根本发不到 DPDK 网卡的问题。
正常情况下,Win10 要发数据给虚拟机,流程是:
- 查 ARP 缓存,看 虚拟机的ip
192.168.43.230对应哪个 MAC - 没有的话,发 ARP 请求广播:“谁是 192.168.43.230?”
- 对方回 ARP 应答,Win10 把 MAC 写进缓存
- 之后才用这个 MAC 封装以太网帧发出去
问题在于:虚拟机的 192.168.43.230 这个 IP 现在归 DPDK 管,而 DPDK 是用户态轮询驱动,它不会响应内核协议栈的 ARP 请求。DPDK 的 sendapp 没实现 ARP 的应答逻辑,Win10 发出去的 ARP 请求就无法到达dpdk。
手动设置静态ip后强制把 192.168.43.230 映射到 MAC 00-0c-29-df-c8-43,跳过 ARP 解析过程。这样 Win10 协议栈查 ARP 表时直接命中,立刻就能用正确的目的 MAC 封装以太网帧发出去,DPDK 那边才能收到。
ARP(Address Resolution Protocol,地址解析协议):是一个把 IP 地址翻译成 MAC 地址的协议。它工作在**局域网(二层广播域)**内,是 IPv4 通信的基础之一。
同一个广播域内,发送方用 IP 地址发数据,但不知道对方 MAC 时,才需要 ARP 解析。

- 硬件类型。发送方想要知道的物理网络类型,以太网(1)……
- 协议类型。发送方要映射的高层协议地址类型。IPv4
- 硬件地址长度。mac地址,谁的?
- 协议地址长度。指明协议地址的长度,
- op。执行类型,响应还是请求。请求request(1),响应response(2)
- 发送端mac地址
- 发送端IP地址
- 目的mac地址
- 目的ip地址
arp有两个功能一个是repuest请求,一个是response响应。一个是广播arp包,一个是接收arp包。
当win广播arp的时候,虚拟机接收到arp包后会发送给win自己的mac地址,这样mac就会把虚拟机的mac地址写入arp表中。
arp的请求是局域网内的广播,不是一对一的。
当接收到arp表时,需要判断arp协议中的目的ip是不是自身ip,如果不是自身ip则不回应,如果是自身ip再将自身mac发送给对方。
如果不是目的ip不是自身,还发送mac地址,就属于arp攻击。
在没有arp协议的时候,win端连接不上dpdk,必须在win端加入对方的ip与mac地址。
netsh -c i i add neighbors 11 192.168.43.230 00-0c-29-df-c8-43
如果down掉静态ip,还是无法连接。
所以需要实现arp协议。
对于arp表,使用结构体构造三个字段,分别对应ip、mac、type。

struct arp_item{
uint32_t ip;
uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
uint8_t type;
struct arp_item *next;
struct arp_item *prev;
};
struct arp_table{
struct arp_item *arp_list;
int count;
};
使用双向链表存储arp表。
#define ARP_TABLE_ADD(item,list) do{ \
item->prev = NULL; \
item->next = list; \
if(list != NULL) list->prev = item; \
list = item; \
}while(0)
#define ARP_TABLE_REMOVE(item,list) do{ \
if(item->prev != NULL) item->prev->next = item->next; \
if(item->next != NULL) item->next->prev = item->prev; \
if(list == item) list = item->next; \
item->next = NULL; \
item->prev = NULL; \
}while(0)
arp表是全局唯一,可以使用单例模式。
arp的请求是定时发送的,所以还需要定时器。
定时器就直接用dpdk提供的定时器。
因为是单线程就没有实现锁,这里的添加和删除可以使用cas实现。
cas(Compare-And-Swap,比较并交换) 是一种原子操作:三个参数,内存地址,期望值,新值。只有当内存中的值等于"期望值"时,才把它改成"新值";否则什么都不做,并返回"是否成功"。
在发送arp请求的时候,是不知道对方mac地址的,那么以太网头和arp头中的对方mac字段填写什么?

可以看出,以太网头在不知道对方mac时填写的是0xffffffffffff,而arp填写的是0x000000000000
arp请求需要给局域网内的每一个ip都发送一遍,在发送的时候如果arp表里面没有它的mac地址就按照上面的方式组织,如果有mac地址,就按照正确的mac地址组织协议帧。
所以需要遍历1-254,结尾的所有ip。没有0和255,是因为0表示整个网段的网络地址,255表示广播地址,所以可用的ip地址是1-254。
static uint8_t* ng_get_dst_macaddr(uint32_t dip) 在arp.h中static实现,那么包含这个arp.h的main.c文件可以使用这个static的函数吗?
可以,只不过调用ng_get_dst_macaddr函数的.c文件都会拷贝一份这个函数,而不是公用一个函数。
如果static uint8_t* ng_get_dst_macaddr(uint32_t dip) 在arp.c中static实现,那么包含这个arp.h的main.c文件可以使用这个static的函数吗?
不可以,arp.h中没有声明,其他文件无法使用。
如果arp.h中声明uint8_t* ng_get_dst_macaddr(uint32_t dip) ;可以使用吗?
不能使用。
如果static uint8_t* ng_get_dst_macaddr(uint32_t dip);声明可以使用吗?
不能使用。
在.c文件static函数,表示这个函数仅限于本文件使用,其他文件无法调用。
如果打印信息没有立即返回,而是隔了一段时间再集中返回大概率是因为没有加换行符。
cat /proc/interrupts | grep eth0
至少两个网卡。
修改虚拟机的vmx文件。
sudo su
ifconfig eth0
inet addr: 172.27.155.113
172.18.126.146
192.168.43.230
HWaddr 00:0c:29:df:c8:43
ifconfig eth0 down
cd /home/king/share/dpdk/dpdk-stable-19.08.2
export RTE_SDK=/home/king/share/dpdk/dpdk-stable-19.08.2/
export RTE_TARGET=x86_64-native-linux-gcc
./usertools/dpdk-setup.sh
43
44
45
46
512
47
512
49
etho: 0000:03:00.0
60
win10:
arp -a
接口: 192.168.43.121 — 0xb
0xb=11
netsh -c i i add neighbors 11 192.168.43.230 00-0c-29-df-c8-43
netsh -c i i add neighbors 36 172.27.155.113 00-0c-29-df-c8-43
172.27.155.113
netsh i i show in
netsh interface ipv4 show interfaces
11 50 1500 connected WLAN
可以看到11对应WLAN,Wireshark监听的时候选择WLAN
验证dpdk
./build/l3fwd -l 4-7 -n 4 – -p 0x3 --config=“(0, 0, 4),(1, 0, 5)” --parse-ptype
gcc -o helloword main.c -I /usr/local/include/dpdk/ -ldpdk -lpthread -lnuma -ldl
./helloword -l 0-3 -n 4
xshell断开连接后重新配置是没有eth0的,但是udp连接不了,重启虚拟机,不要连接收集热点,eth0是172.27.155.113后再重新配置。
配置完成后,再连接手机热点。
.43是手机热点的网段。
win没有重启
断开热点
重启虚拟机
eth0没有显示ip
win没有重启
断开热点
重启虚拟机
eth0没有显示ip
win没有重启
连接热点
重启虚拟机
还是不显示ip
断开热点
win重启
开启虚拟机
172.17.109.134
172.19.98.54
断开热点
win重启
开启虚拟机
172.19.98.54
可以dpdk
连接手机热点,无法dpdk
更改eth3为nat模式
重启虚拟机
关闭热点
eth0与eth2没有ip
连接热点
eth0与eth3没有ip
使用eth2
192.168.222.134
00:0c:29:df:c8:61
0000:13:00.0
netsh -c i i add neighbors 23 192.168.222.134 00-0c-29-df-c8-61
连接热点
也可以dpdk
连接热点
开启虚拟机
使用eth2
192.168.222.134
00:0c:29:df:c8:61
0000:13:00.0
可以使用
文章参考<零声教育>的C/C++linux服务期高级架构系统教程学习:0voice · GitHub
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/fanjunchuang/article/details/167917901




