netmap 介绍

netmap是一个高效的收发报文的 I/O 框架,已经集成在 FreeBSD 的内部了。
当然,也可以在 Linux 下编译使用 。

一、架构

现在的网卡都使用多个 buffer 来发送和接收 packet,并有一个叫NIC ring的环形数组。
NIC ring 是静态分配的,它的槽指向mbufs链的部分缓冲区。

Mbufs and NIC

netmap 内存映射网卡的packet buffer到用户态,实现了自己的发送和接收报文的circular ring来对应网卡的 ring,使用 netmap 时,程序运行在用户态,即使出了问题也不会 crash 操作系统。

下图显示了一个接口可以有多个 netmap ring。
将文件描述符绑定到 NIC 时,应用程序可以选择将所有 ring仅一个 ring附加到文件描述符。

  • 使用所有 ring,相同的代码可以用于单队列或多队列 NIC。
  • 使用一个 ring,可以通过每个 ring 一个进程/CPU core 来构建高性能系统,从而在系统中并行。

Shared Memory

netmap 使用poll等待网卡的文件描述符可接收或可发送。

netmap 会建立一个字符设备/dev/netmap,然后通过nm_open来注册网卡为 netmap 模式。

注意:这里顺便提一下,网卡进入 netmap 模式后,ifconfig 是看不到网卡统计信息变化的,wireshark 也抓不到报文,因为协议栈被旁路了。

内存映射的区域里面,有网卡的收发队列,这样可以通过将接收缓冲区的地址写在发送的 ring 里面实现零拷贝(Zero-copy)

二、性能

netmap 官网说在 10GigE 上测试,发包速率可以达到 14.88Mpps,收包的速率和发包相近。同时还支持多网卡队列。

Netmap vs Traditional

我在网络设备 Intel 82599EB 10-Gigabit 上测试,发包速率和 netmap 官网的速度差不多,可以达到 1400W pps,不过收包要比这个低很多。。。不知道是不是我测的方式有问题。

三、例子

这是官方的例子,不过已经很老了(也就是不能直接用了^_^),但是还是可以大概说明使用过程的:

struct netmap_if *nifp;
struct nmreq req;
int i, len;
char *buf;

fd = open("/dev/netmap", 0);  // 打开字符设备
strcpy(req.nr_name, "eth0");
ioctl(fd, NIOCREG, &req);  // 注册网卡
mem = mmap(NULL, req.nr_memsize, PROT_READ|PROT_WRITE, 0, fd, 0);
nifp = NETMAP_IF(mem, req.nr_offset);

for (;;) {
    struct pollfd x[1];
    struct netmap_ring *ring = NETMAP_RX_RING(nifp, 0);

    x[0].fd = fd;
    x[0].events = POLLIN;
    poll(x, 1, 1000);
    for (; ring->avail > 0 ; ring->avail--) {
        i = ring->cur;
        buf = NETMAP_BUF(ring, i);
        use_data(buf, ring->slot[i].len);
        ring->cur = NETMAP_NEXT(ring, i);
    }
}

参考资料

netmap 官网地址
Revisiting Network I/O APIs: The netmap Framework
netmap: a novel framework for fast packet I/O

  • 3
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
netmap是一个基于零拷贝思想的高速网络I/O架构,它通过在网卡运行在netmap模式下与主机协议栈断开连接,并创建一个netmap环来实现高效的数据包处理。\[2\]netmap的架构包括了网卡环、netmap环和用于与主机协议栈交互的环。网卡环是网卡直接将数据包存入的缓存,而netmap环是应用程序可以通过调用netmap API访问的缓存。这些缓存位于共享空间,应用程序可以直接访问数据包内容,实现了网络数据包的零拷贝。\[2\] netmap的数据结构包括了netmap_if、nmreq、netmap_ring等。netmap_if是一个结构体,用于表示一个netmap接口,其中包含了与接口相关的信息。nmreq是一个结构体,用于向内核注册一个netmap接口。netmap_ring是一个结构体,用于表示一个netmap环,其中包含了环的相关信息,如可用的数据包数量、当前处理的数据包索引等。\[3\] 在使用netmap时,可以通过打开字符设备"/dev/netmap"来获取一个文件描述符,然后使用ioctl函数来注册网卡。接下来,可以使用mmap函数将共享内存映射到用户空间,从而可以访问netmap环中的数据包内容。最后,可以使用poll函数来等待数据包的到达,并通过遍历netmap环中的数据包来处理数据。\[3\] 需要注意的是,上述提供的代码示例是一个官方的例子,可能已经过时,不能直接使用。但是它可以大致说明netmap的使用过程。\[3\] #### 引用[.reference_title] - *1* *3* [netmap 介绍](https://blog.csdn.net/fengfengdiandia/article/details/52869290)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Netmap分析(一)](https://blog.csdn.net/superbfly/article/details/51224920)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值