精华内容
下载资源
问答
  • Zeek :: Netmap 此插件为Zeek提供本地支持,作为数据包源。 安装 请遵循NETMAP的说明来获取其内核模块以及可能安装的自定义驱动程序。 然后通过Zeek软件包管理器安装此插件: # zkg install zeek/zeek-netmap 要...
  • 注意:此自述文件取自原始的netmap-ipfw,并在需要时采用。 netmap-ipfwjit 该目录包含一个版本的ipfw和dummynet,可以使用NETMAP作为数据包I / O的后端在userland中运行。 这样可以使吞吐量比相应的内核版本高约10...
  • Netmap:快速数据包I / O的框架 介绍 Netmap是一个用于从用户空间进行非常快速的数据包I / O的框架。 VALE是使用netmap API的同样快速的内核L2软件交换机。 两者都是作为FreeBSD和Linux的单个内核模块实现的。 ...
  • netmap安装.docx

    2020-09-24 11:27:27
    详细的安装手册,针对遇到的问题进行了详细的说明。netmap安装主要用来进行大流量的收发报文,同DPDK一样,只不过使用的方法有所区别。喜欢研究的同学可以进行对比一下。
  • nmsynproxy是使用netmap,OpenDataPlane(ODP)或L Data Plane(LDP)的用于IPv4和IPv6Linux用户空间TCP SYN代理。 今天推荐的变体是LDP变体。 SYN代理混合使用SYN cookie和SYN缓存。 它还可以混合使用TCP序列号和...
  • netmap-netfilter 从netmap-ipfw和linux的netfilter一起砍掉了代码。 使用debian的3.2内核和debian的1.4.14-3.1 iptables进行了测试。 需要将以下内容添加到/lib/modules/3.2.0-4-amd64/build/include/generated/...
  • ixgbe-linux-netmap-single-queue Netmap 启用带有补丁的 ixgbe 驱动程序,这些补丁可以仅在单个队列上进行调整 它是启用 netmap 的 ixgbe 驱动程序的补丁: :
  • 这是Click模块化路由器的扩展版本,具有改进的Netmap支持和新的DPDK支持。 这是我们的ANCS论文的结果,该论文可从获得,但此后获得了许多贡献和改进。 提供有关元素以及如何使用某些FastClick功能(例如批处理)的...
  • netperf-netmap-源码

    2021-05-09 23:40:27
    netperf-netmap 该项目是一个简单的原型,用于测试netperf中的Netmap内核旁路网络API。 原始自述文件和许可证 这里是原始的projet和 。
  • 高性能网络 I/O 框架 -netmap 源码分析 (1) 作者 gfree.wind@ 博客 微博 /glinuxer QQ 技术群 4367710 前几天听一个朋友提到这个 netmap 看了它的介绍和设计确实是个好东西其设计思想 与业界不谋而合 因为为了
  • packet-bricks, 一种基于netmap的数据包分发与过滤 自述文件Packet是一个 linux/freebsd守护进程,它能够接收和分配到用户应用程序的输入流量。 它的主要职责可能包括( i ) 负载平衡。( 二) 复制和/或者( iii ) 过滤...
  • 网图 图形包,用于Internet映射和可视化
  • centos安装netmap

    2020-11-13 18:21:59
    新机器可能很多环境都没有安装,需要将环境初始化好 像gcc,make等, ...centos安装netmap相对来说比较简单。 1. 主要第一步安装kernel-devel 从光盘安装kernel-devel包,默认安装即可,安装完毕应.

    新机器可能很多环境都没有安装,需要将环境初始化好

    像gcc,make等,

    在最开始是configure总是失败,查找config.log可以看到问题

    安装缺少的包,搜索一下:yum search libelf-dev,可以看到相应的包 elfutils-libelf-devel.x86_64,

    安装之后,重新configure,即可

    centos安装netmap相对来说比较简单。

    1. 主要第一步安装kernel-devel

    从光盘安装kernel-devel包,默认安装即可,安装完毕应该在/usr/src/kernel/...
    

    2、下载netmap       

    git clone https://github.com/luigirizzo/netmap.git

    ======================================问题描述开始=======================

    3. make,make install

    但是现在centos最新版是centos8.2,安装netmap会报错误,使用wiki方法指定网卡驱动版本,还是不行,

    指定网卡驱动版本方法:

    ./configure --prefix=/usr/local/src/buildnetmap  --kernel-sources=/usr/src/kernels/4.18.0-193.el8.x86_64 --kernel-dir=/usr/src/kernels/4.18.0-193.el8.x86_64  --driver-suffix=-netmap --select-version=e1000e:3.8.4 --drivers=e1000e

    看出问题的报错信息像是版本不兼容问题:出错信息:

    /usr/local/src/netmap/netmap-tmpdir/__test__11.c:15:23: 附注:(在‘ndo.ndo_select_queue’的初始化附近)
    cc1:所有的警告都被当作是错误
    make[2]: *** [scripts/Makefile.build:318:/usr/local/src/netmap/netmap-tmpdir/__test__11.o] 错误 1
      CC [M]  /usr/local/src/netmap/netmap-tmpdir/__test__10.o
      CC [M]  /usr/local/src/netmap/netmap-tmpdir/__test__8.o
    /usr/local/src/netmap/netmap-tmpdir/__test__8.c: 在函数‘dummy’中:
    /usr/local/src/netmap/netmap-tmpdir/__test__8.c:8:20: 错误:提供给函数‘ndo->ndo_select_queue’的实参太少
                 return ndo->ndo_select_queue(NULL, NULL, NULL);
                        ^~~
    /usr/local/src/netmap/netmap-tmpdir/__test__8.c:9:5: 错误:在有返回值的函数中,控制流程到达函数尾 [-Werror=return-type]
         }
         ^
    cc1:所有的警告都被当作是错误
    make[2]: *** [scripts/Makefile.build:318:/usr/local/src/netmap/netmap-tmpdir/__test__8.o] 错误 1
      CC [M]  /usr/local/src/netmap/netmap-tmpdir/__test__9.o
      CC [M]  /usr/local/src/netmap/netmap-tmpdir/__test__7.o
    /usr/local/src/netmap/netmap-tmpdir/__test__7.c: 在函数‘dummy’中:
    /usr/local/src/netmap/netmap-tmpdir/__test__7.c:8:20: 错误:提供给函数‘ndo->ndo_select_queue’的实参太少
                 return ndo->ndo_select_queue(NULL, NULL);
                        ^~~
    /usr/local/src/netmap/netmap-tmpdir/__test__7.c:9:5: 错误:在有返回值的函数中,控制流程到达函数尾 [-Werror=return-type]
         }
         ^
    cc1:所有的警告都被当作是错误
    make[2]: *** [scripts/Makefile.build:319:/usr/local/src/netmap/netmap-tmpdir/__test__7.o] 错误 1
      CC [M]  /usr/local/src/netmap/netmap-tmpdir/__test__6.o
    /usr/local/src/netmap/netmap-tmpdir/__test__6.c: 在函数‘dummy’中:
    /usr/local/src/netmap/netmap-tmpdir/__test__6.c:9:3: 错误:implicit declaration of function ‘kthread_use_mm’; did you mean ‘kthread_parkme’? [-Werror=implicit-function-declaration]
       kthread_use_mm(mm);
       ^~~~~~~~~~~~~~
       kthread_parkme
    cc1:所有的警告都被当作是错误
    make[2]: *** [scripts/Makefile.build:319:/usr/local/src/netmap/netmap-tmpdir/__test__6.o] 错误 1
      CC [M]  /usr/local/src/netmap/netmap-tmpdir/__test__3.o
      CC [M]  /usr/local/src/netmap/netmap-tmpdir/__test__2.o
      CC [M]  /usr/local/src/netmap/netmap-tmpdir/__test__5.o
      CC [M]  /usr/local/src/netmap/netmap-tmpdir/__test__4.o
      CC [M]  /usr/local/src/netmap/netmap-tmpdir/__test__1.o
    /usr/local/src/netmap/netmap-tmpdir/__test__1.c: 在函数‘dummy’中:
    /usr/local/src/netmap/netmap-tmpdir/__test__1.c:8:15: 错误:‘struct net_device’ has no member named ‘ax25_ptr’; did you mean ‘tipc_ptr’?
       return dev->ax25_ptr;
                   ^~~~~~~~
                   tipc_ptr
    /usr/local/src/netmap/netmap-tmpdir/__test__1.c:9:2: 错误:在有返回值的函数中,控制流程到达函数尾 [-Werror=return-type]
      }
      ^
    cc1:所有的警告都被当作是错误
    make[2]: *** [scripts/Makefile.build:318:/usr/local/src/netmap/netmap-tmpdir/__test__1.o] 错误 1
    make[2]: 由于错误目标“__build”并未重新制作。
    make[1]: *** [Makefile:1542:_module_/usr/local/src/netmap/netmap-tmpdir] 错误 2
    make[1]: 由于错误目标“_all”并未重新制作。
    make: *** [Makefile:12:tests] 错误 2
    make: 由于错误目标“all”并未重新制作。
    ********************************** WARNING **********************************
    *** There were problems building the external driver e1000e.
    *** 
    *** Please note that this is not related to the netmap patches,
    *** that were not applied.
    *** 
    *** Disabling e1000e.
    *****************************************************************************

     

    ======================================问题描述结束=======================

    更换centos7 实验一下,实验中。。。。。问题终于解决。原来是路走偏了。如上图所出的错误是测试例子出的,按理说也不行。事实是configure只要生成makefile即可。

    然后make、makeinstall生成netmap.ko文件。

    安装netmap最好升级下内核:

    yum -y update

     

     

     

     

    展开全文
  • 1、netmap.h 头文件 netmap.h 被 netmap_user.h 调用,里面定义了一些宏和几个主要的结构体,如nmreq{}, netmap_if{}, netmap_ring{}, netmap_slot{}。 一个网卡(或者网络接口)只有一个 netmap_if{}结构,在使用 ...

    一、C10M问题

    1.1 C10K

    在讲解C10M问题之前,我们先回顾C10K的问题。

    10年前,开发人员处理C10K可扩展性问题时,尽量避免服务处理器超过1万个的并发连接。通过改进操作系统内核以及用事件驱动服务器(典型技术实现如nginx和Node)代替线程服务器(典型代表:Apache),使得这个问题已经被解决。

    以传统的网络编程模型作为代表的Apache为例,C10K问题上的局限表现在:服务器的性能会随着连接数的增多而变差。


    性能和扩展性是不是一回事?
    答案是否定的。
    比如Apache,持续几秒的短期连接,比如快速事务,如果每秒处理1000个事务,只能约1000个并发连接到服务器。如果事务延长到10秒,要维持每秒1000个事务则必须打开10000个并发连接。这种情况下,即使不顾DOS攻击,Apache性能也会性能陡降,同时大量的下载操作也会使Apache崩溃。
    如果每秒处理的连接从5千到1万,如果升级硬件并提高处理器速度到原理的2倍,我们得到了2倍的性能,但没有得到两倍的处理规模。每秒处理连接可能只达到了6000,如果继续提高速度,情况也没有改善。甚至16倍的性能时,仍然不能处理1万个并发连接。因此,性能和可扩展性是不一样的。
    问题在于Apache会创建一个CGI进程,然后关闭,这个步骤并没有扩展。内核使用的O(N^2)算法使处理器无法处理1万个并发连接。


    OS 内核中的两个基本问题

    • 连接数=线程数/进程数:当一个数据包进来,内核会遍历其所有进程以决定由哪个进程来处理这个数据包。
    • 连接数=选择数/轮询次数(单线程):同样的可扩展性问题,每个包都要走一遭列表上所有的 socket。

    针对Apache表现出来的问题,彻底解决并发性能问题的解决方法的根本是改进OS内核使其在常数时间内查找,使线程切换时间与线程数量无关,使用一个新的可扩展epoll()/IO completion Port常数时间去做socket查询。


    1.2 C10M

    实现C10M(1千万)并发连接意味着什么?

    • 1千万的并发连接数。
    • 100万个连接/秒:每个连接以这个速度保持约10秒;
    • 10GB/秒的连接:快速连接到互联网;
    • 1千万个数据包/秒:据估计目前的服务器每秒处理 50K 数据包,以后会更多;
    • 10 微秒的延迟: 可扩展服务器也许可以处理这个规模(但延迟可能会飙升);
    • 10 微秒的抖动: 限制最大延迟;
    • 并发 10 核技术: 软件应支持更多核的服务器(通常情况下,软件能轻松扩展到四核,服务器可以扩展到更多核,因此需要重写软件,以支持更多核的服务器)。


    解决C10M问题的一些思路:
    将功能逻辑做好恰当的划分:数据面专门负责数据的处理,属于资源消耗的主要因素;控制面只负责一些偶尔才有非业务逻辑,比如与外部用户的交互、信息统计等。
    另外,归纳一些高性能的网络数据处理框架( Intel 的 DPDK、6wind、windriver),我们发现有如下共同点可以参考:

    • 数据包直接传递到业务逻辑,不经过linux内核协议栈。
    • 多线程的核间绑定:每个线程绑定到一个处理核心,好处是最大化核心CACHE利用、实现无锁设计、避免进程切换消耗等。
    • 内存是另外一个核心要素:常见的内存池设计必须得以切实应用。

    同时,我们不能单纯从软件上去思考解决方案,而是需要结合操作系统,比如:内存、CPU、磁盘、网卡、应用程序、操作系统。


    二、用户态协议栈设计

    我们来看下,一般的客户端请求到应用程序的具体数据流程:

    在这里插入图片描述

    步骤:
    1)客户端请求数据,先经过网卡,服务器需要从网卡copy数据到内核协议栈(tcp/bsd)。
    2)再从内核协议栈copy数据到应用程序。

    由此可见,客户端与应用程序之间的数据交互,多了两次数据拷贝的操作,在大量数据并发的情况下,必将会严重影响性能。

    优化思路:可以跳过内核协议栈,去除拷贝操作,数据直接从网卡到应用程序,这种方式称为零拷贝。


    mmap
    mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对应关系。
    在这里插入图片描述
    有了mmap的映射,应用程序进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。netmap开源框架就是采用这种方式实现的。

    简单实现流程可表述如下图:
    在这里插入图片描述


    三、netmap

    netmap是一个高性能收发原始数据包的框架,其包含了内核模块以及用户态库函数。
    目标是:不修改现有操作系统软件以及不需要特殊硬件支持,实现用户态和网卡之间数据包的高性能传递。
    原理如下图:数据包不经过操作系统内核进行处理,,用户空间程序收发数据包时,直接与网卡进行通信。
    在这里插入图片描述
    NIC:linux下的子系统,是网卡的一层软件封装,为了兼容不同厂家的网卡。
    Eth0:NIC的实例化对象,参数跟物理网卡一一对应。


    3.1 netmap数据结构

    在netmap框架,内核拥有数据包池,发送环接收环上的数据包不需要动态申请,有数据到达网卡时,直接从数据包池中取出一个数据包,然后将数据放入此数据包中,再将数据包的描述符放入接收环中。内核中的数据包池,通过mmap技术映射到用户空间,用户态程序最终通过netmap_if获取接收发送环netmap_ring,进行数据包的获取发送。
    在这里插入图片描述


    3.2 netmap特点

    1. 性能高:数据包不走传统协议栈,不需要层层解析,用户态直接与网卡的接收环和发送环交互。性能高的具体原因有:
      - 系统调用以及处理数据包的时间花费少。
      - 不需要进行数据包的内存分配:采用数据包池,当有数据到达时,直接从数据包池中取出一个数据包,然后将数据放入此数据包中,再将数据包的描述符放入接收环中。
      - 数据拷贝次数少:内核中的数据包采用mmap技术映射到用户态。所以数据包在到达用户态时,不需要进行数据包的拷贝。

    2. 稳定性高:有关网卡寄存器数据的维护都是在内核模块进行,用户不会直接操作寄存器。所以在用户态操作时,不会导致操作系统崩溃。

    3. 亲和性:采用了CPU亲和性,实现CPU和网卡绑定,提高性能。

    4. 易用性好:API操作简单,用户态只需要调用ioctl函数即可完成数据包收发工作。

    5. 与硬件解耦:不依赖硬件,只需要对网卡驱动程序稍微做点修改就可以使用此框架,传统网卡驱动将数据包传递给操作系统内核协议栈,而修改后的数据包直接放入netmap_ring供用户使用。


    3.3 netmap API

    netmap API函数主要为2个头文件,netmap.h和netmap_user.h,当解压下载好的netmap程序后,在./netmap/sys/net/目录下,文本主要对这2个头文件进行分析。


    1、netmap.h 头文件

    • netmap.h 被 netmap_user.h 调用,里面定义了一些宏和几个主要的结构体,如nmreq{}, netmap_if{}, netmap_ring{}, netmap_slot{}。
    • 一个网卡(或者网络接口)只有一个 netmap_if{}结构,在使用 mmap()申请的共享内存中,通过 netmap_if{}结构可以访问到任何一个发送/接收环(也就是 netmap_ring{}结构,一个netmap_if{}可以对应多发送/接收环,这应该和物理硬件有关。
    • 找到 netmap_ring{}的地址后,我们就可以找到环中每一个 buffer 的地址(buffer 里面存储的是将要发送/接收的数据包)。
    • 通过一个 nifp 是如何访问到多个收/发环的,通过一个 ring 如何找到多个不同的 buffer地址的,其实都是通过存储这些结构体相邻的后面一部分空间实现。


    2、宏定义
    1)_NETMAP_OFFSET

    #define _NETMAP_OFFSET(type, ptr, offset) \
    ((type)(void *)((char *)(ptr) + (offset)))
    

    该宏将ptr指针(强转成char*类型)向右偏移offset个字节,再将其转化为指定的类型type。


    2)NETMAP_IF

    #define NETMAP_IF(_base, _ofs) _NETMAP_OFFSET(struct netmap_if *,
    _base, _ofs)
    

    该宏将_base 指针向右偏移_ofs 个字节后,强转为 netmap_if *类型返回。在 nemap中通过此宏得到 d->nifp 的地址。


    3)NETMAP_TXRING

    define NETMAP_TXRING(nifp, index) _NETMAP_OFFSET(struct netmap_ring
    *, \
    nifp, (nifp)->ring_ofs[index] )
    

    通过该宏定义,可以找到 nifp 的第 index 个发送环的地址(index 是从 0 开始的),ring_ofs[index]为偏移量,由内核生成。
    其中,我们注意到 struct netmap_if{}最后面只定义了 const ssize_t ring_ofs[0], 实际上其它的 netmap 环的偏移量都写在了该结构体后面的内存地址里面,直接访问就可以了。


    4)NETMAP_RXRING

    #define NETMAP_RXRING(nifp, index) _NETMAP_OFFSET(struct netmap_ring
    *, \
    nifp, (nifp)->ring_ofs[index + (nifp)->ni_tx_rings + 1] )
    

    通过该宏定义,可以找到 nifp 的第 index 个接收环的地址,其中(nifp)->ring_ofs[]里面的下标为 index+(nifp)->ni_tx_rings+1,正好与发送环的偏移量区间隔开 1 个。


    5)NETMAP_BUF

    #define NETMAP_BUF(ring, index) \
    ((char *)(ring) + (ring)->buf_ofs +
    ((index)*(ring)->nr_buf_size))
    

    通过该宏定义,可以找到 ring 这个环的第 index 个 buffer 的地址(buffer 里面存的就是我们接收/将发送的完整数据包),每个 buffer 占的长度是 2048 字节(在(ring)->nr_buf_size也给出了)。
    其中(ring) ->buf_ofs 是固定的偏移量,不同的环这个值不相同,但所有的(char*)(ring)+(ring)->buf_ofs 会指向同一个地址,也就是存放 buffer 的连续内存的开始地址(d->buf_start 会指向该地址)。


    6)NETMAP_BUF_IDX

    #define NETMAP_BUF_IDX(ring, buf) \
    ( ((char *)(buf) - ((char *)(ring) + (ring)->buf_ofs) ) / \
    (ring)->nr_buf_size )
    

    在讲 NETMAP_BUF 的时候我们说(char *)(ring) + (ring)->buf_ofs)总会指向存放 buffer 的起始位置 (无论是哪一个环 ),在这段内存中将第一个 buffer 下标标记为 0 的话,NETMAP_BUF_IDX 计算的恰好是指针 buf 所指 buffer 的下标。


    3、nm_open函数

    static struct nm_desc *nm_open(const char *ifname, const struct nmreq *req,
                                   uint64_t new_flags, const struct nm_desc *arg)
    

    说明:
    1)调用nm_open函数会对传递的ifname指针里面的字符串进行分析,提取出网络接口名。
    如:nmr = nm_open("netmap:eth0", NULL, 0, NULL)

    2)nm_open() 会 对 struct nm_desc *d 申 请 内 存 空 间 , 并 通 过 d->fd =open(NETMAP_DEVICE_NAME, O_RDWR);打开一个特殊的设备/dev/netmap 来创建文件描述符 d->fd。

    3)通过 ioctl(d->fd, NIOCREGIF, &d->req)语句,将 d->fd 绑定到一个特殊的接口,并对 d->req结构体里面的成员做初始化,包括:

    • 在共享内存区域中 nifp 的偏移,
    • 共享区域的大小nr_memsize,
    • tx/rx 环的大小 nr_tx_slots/nr_rx_slots(大小为 256),
    • tx/rx 环的数量 nr_tx_rings、nr_rx_rings(视硬件性能而定)等。

    4)接着在 if ((!(new_flags & NM_OPEN_NO_MMAP) || parent) && nm_mmap(d, parent))语句中调用 nm_mmap 函数, 继续给 d 指针指向的内存赋值。


    4、nm_mmap函数

    static int nm_mmap(struct nm_desc *, const struct nm_desc *);
    
    static int nm_mmap(struct nm_desc *d, const struct nm_desc *parent)
    {
    	//XXX TODO: check if mmap is already done
    
    	if (IS_NETMAP_DESC(parent) && parent->mem &&
    	    parent->req.nr_arg2 == d->req.nr_arg2) {
    		/* do not mmap, inherit from parent */
    		D("do not mmap, inherit from parent");
    		d->memsize = parent->memsize;
    		d->mem = parent->mem;
    	} else {
    		/* XXX TODO: check if memsize is too large (or there is overflow) */
    		d->memsize = d->req.nr_memsize; //将需要申请的内存大小赋值给d->memsize
    		d->mem = mmap(0, d->memsize, PROT_WRITE | PROT_READ, MAP_SHARED,
    				d->fd, 0); //申请共享内存
    		if (d->mem == MAP_FAILED) {
    			goto fail;
    		}
    		d->done_mmap = 1;
    	}
    	{
    		struct netmap_if *nifp = NETMAP_IF(d->mem, d->req.nr_offset); //通过 d->req.nr_offset 这个偏移量的到 nifp 的地址, NETMAP_IF 前面说过
    		struct netmap_ring *r = NETMAP_RXRING(nifp, d->first_rx_ring); ///对 nifp,找接收包的环 r,因为 index 为 0,所以省略了
    		if ((void *)r == (void *)nifp) {
    			/* the descriptor is open for TX only */
    			r = NETMAP_TXRING(nifp, d->first_tx_ring);
    		}
    
    		*(struct netmap_if **)(uintptr_t)&(d->nifp) = nifp;对d->nifp 赋值,虽然 d->nifp 使用 const 定义的,但对其取地址再强值类型转换后,依然可以对其指向的空间进行操作
    		*(struct netmap_ring **)(uintptr_t)&d->some_ring = r; //同理,对 d->some_ring 进行赋值,此处指向了第一个接受(rx)环。
    		*(void **)(uintptr_t)&d->buf_start = NETMAP_BUF(r, 0); //计算第一个 buffer 的地址,并存入 d->buf_start 指针中
    		*(void **)(uintptr_t)&d->buf_end =
    			(char *)d->mem + d->memsize; //计算共享区间的最后一个地址,赋值给 d->buf_end
    	}
    
    	return 0;
    
    fail:
    	return EINVAL;
    }
    

    说明:
    1)nifp 为申请的共享内存首地址 d->mem 向右偏移 d->req.nr_offset(该值在调用前面的ioctl()时得到)得到。并且一个网络接口(网卡)只对应一个 nifp。 (使用宏 NETMAP_IF 计算)

    2)得到的 nifp 的地址,nifp 结构体里最后定义的 ring_ofs[0]以及接下来内存中的 ring_ofs[1],ring_ofs[2]…,这些内存中存储的是访问每一个环(tx or rx ring)的偏移量,通过这个偏移量我们可以得到每一个环的地址(使用宏 NETMAP_RXRING/NETMAP_TXRING 进行计算)。

    3)得到每个收/发环的地址了, netmap_ring 结构体最后面有一个 struct netmap_slot slot[0];,通过 slot[0],后面内存的slot[1], slot[2], slot[3]…, 取出里面的偏移量就可以得到每一个 buffer(也叫数据包槽)的地址了(使用宏 NETMAP_BUF 计算得到)。 到这里, netmap 如何访问到内存槽中的每一个 buffer 的。

    4)在 struct nm_desc 中, nifp, some_ring, buf_start, buf_end 等指针都定义为 const 的,但我们通过对其取地址再强转指针的方式去往这些指针指向的内存中赋值。
    注:在 nm_mmap()中使用 mmap()申请共享的时候, 这些数据结构里数据的设计是内核模块就已写好了的,我们在这里其实是在做验证。


    5、nm_nextpkt函数

    static u_char *nm_nextpkt(struct nm_desc *, struct nm_pkthdr *);
    
    static u_char *nm_nextpkt(struct nm_desc *d, struct nm_pkthdr *hdr)
    {
    	int ri = d->cur_rx_ring;  //当前接收环的编号
    
    	do {
    		/* compute current ring to use */
    		struct netmap_ring *ring = NETMAP_RXRING(d->nifp, ri); //得到当前rx环的地址
    		if (!nm_ring_empty(ring)) { //判断环里是否有新到的包
    			u_int i = ring->cur;    //当前该访问哪个槽(buffer)了
    			u_int idx = ring->slot[i].buf_idx;  //得到第i个buffer的下标
    			u_char *buf = (u_char *)NETMAP_BUF(ring, idx); //得到存有到来数据包的地址
    
    			// __builtin_prefetch(buf);
    			hdr->ts = ring->ts;
    			hdr->len = hdr->caplen = ring->slot[i].len;
    			ring->cur = nm_ring_next(ring, i); //ring->cur向后移动一位
    			/* we could postpone advancing head if we want
    			 * to hold the buffer. This can be supported in
    			 * the future.
    			 */
    			ring->head = ring->cur;
    			d->cur_rx_ring = ri; //将当前环(d->cur_rx_ring)指向第ri个(因为可能有多个环)
    			return buf;  //将数据包地址返回
    		}
    		ri++;
    		if (ri > d->last_rx_ring) //如果ri超过了rx环的数量,则再从第一个rx环开始检测是否有包到来
    			ri = d->first_rx_ring;
    	} while (ri != d->cur_rx_ring);
    	return NULL; /* nothing found */
    }
    

    说明:
    1)nm_nextpkt()是用来接收网卡上到来的数据包的函数。

    2)nm_nextpkt()会将所有rx环都检查一遍,当发现有一个rx环有需要接收的数据包时,得到这个数据包的地址,并返回。所以nm_nextpkt()每次只能获取一个数据包。


    6、nm_inject函数

    static int nm_inject(struct nm_desc *, const void *, size_t);
    
    /*
     * Same prototype as pcap_inject(), only need to cast.
     */
    static int nm_inject(struct nm_desc *d, const void *buf, size_t size)
    {
    	u_int c, n = d->last_tx_ring - d->first_tx_ring + 1,
    		ri = d->cur_tx_ring;
    
    	for (c = 0; c < n ; c++, ri++) {
    		/* compute current ring to use */
    		struct netmap_ring *ring;
    		uint32_t i, j, idx;
    		size_t rem;
    
    		if (ri > d->last_tx_ring)
    			ri = d->first_tx_ring;
    		ring = NETMAP_TXRING(d->nifp, ri);
    		rem = size;
    		j = ring->cur;
    		while (rem > ring->nr_buf_size && j != ring->tail) {
    			rem -= ring->nr_buf_size;
    			j = nm_ring_next(ring, j);
    		}
    		if (j == ring->tail && rem > 0)
    			continue;
    		i = ring->cur;
    		while (i != j) {
    			idx = ring->slot[i].buf_idx;
    			ring->slot[i].len = ring->nr_buf_size;
    			ring->slot[i].flags = NS_MOREFRAG;
    			nm_pkt_copy(buf, NETMAP_BUF(ring, idx), ring->nr_buf_size);
    			i = nm_ring_next(ring, i);
    			buf = (char *)buf + ring->nr_buf_size;
    		}
    		idx = ring->slot[i].buf_idx;
    		ring->slot[i].len = rem;
    		ring->slot[i].flags = 0;
    		nm_pkt_copy(buf, NETMAP_BUF(ring, idx), rem);
    		ring->head = ring->cur = nm_ring_next(ring, i);
    		d->cur_tx_ring = ri;
    		return size;
    	}
    	return 0; /* fail */
    }
    

    说明:
    1)nm_inject()是用来往共享内存中写入待发送的数据包数据的。数据包经共享内存拷贝到网卡,然后发送出去。所以 nm_inject()是用来发包的。

    2)nm_inject()也会查找所有的发送环(tx 环),找到一个可以发送的槽,就将数据包写入并返回,所以每次函数调用也只能发送一个包。


    7、nm_close函数

    static int nm_close(struct nm_desc *d)
    
    static int nm_close(struct nm_desc *d)
    {
    	/*
    	 * ugly trick to avoid unused warnings
    	 */
    	static void *__xxzt[] __attribute__ ((unused))  =
    		{ (void *)nm_open, (void *)nm_inject,
    		  (void *)nm_dispatch, (void *)nm_nextpkt } ;
    
    	if (d == NULL || d->self != d)
    		return EINVAL;
    	if (d->done_mmap && d->mem)
    		munmap(d->mem, d->memsize);  //释放申请的共享内存
    	if (d->fd != -1) {
    		close(d->fd);  //关闭文件描述符
    	}
    
    	bzero(d, sizeof(*d)); //将d指向的空间全部置0
    	free(d);	//释放指针d指向的空间
    	return 0;
    }
    

    说明:
    nm_close 函数就是回收动态内存,回收共享内存,关闭文件描述符。

    展开全文
  • netmap说明文档

    2016-02-23 17:57:43
    netmap的英文说明文档,讲的还是比较清晰的。有需要可以下载来看看
  • insmod netmap.ko rmmod ixgbe insmod /home/xxx/netmap-master/ixgbe-5.3.7/src/ixgbe.ko 验证安装结果: [root@localhost ~]# ls /dev/netmap /dev/netmap [root@localhost ~]# lsmod|grep netmap ...

    suricata 简介

    Suricata 是一个免费、开源、成熟、快速、健壮的网络威胁检测引擎。Suricata 引擎能够进行实时入侵检测(IDS)、内联入侵预防(IPS)、网络安全监控(NSM)和离线 pcap 处理。Suricata 使用强大而广泛的规则和签名语言来检查网络流量,并提供强大的 Lua 脚本支持来检测复杂的威胁。使用标准的输入和输出格式(如 YAML 和 JSON),使用现有的 SIEMs、Splunk、Logstash/Elasticsearch、Kibana 和其他数据库等工具进行集成将变得非常简单。Suricata 项目和代码由开放信息安全基金会(OISF)拥有和支持,OISF 是一个非盈利基金会,致力于确保 Suricata 作为一个开源项目的开发和持续成功。

    suricata 支持多种抓包模式,比如通过 AF-packet 抓包,比如采用 PF_RING(高性能的网络库,免费版本不支持 Zero Copy)抓包,还支持 Netmap 抓包三种模式,其中性能最好的就是 netmap 抓包模式,本文就是介绍如何编译 netmap 版本的 suricata。

    一 安装前准备

    suricata 可以正常编译的临时下做以下操作检查。
    1)netmap 是需要更改网卡驱动的,所以开始时候必须看下网卡的类型,采用命令如下:

    [root@localhost ~]# ethtool -i p1p1
    driver: ixgbe
    version: 5.3.7
    firmware-version: 0x800003af
    expansion-rom-version:
    bus-info: 0000:01:00.0
    supports-statistics: yes
    supports-test: yes
    supports-eeprom-access: yes
    supports-register-dump: yes
    supports-priv-flags: yes
    

    通过上面命令看到驱动程序对应的网卡类型为 ixgbe 即 10G 即万兆网卡,英特尔的 10G 网卡(例如,82598、82599,x540)由 ixgbe 驱动支持,我们以后应该限制住网卡类型。对于常见的驱动,我们在安装过一次的 netmap 后,netmap 会自动下载这些驱动文件,我们提供的 netmap 软件最好使用这些驱动,防止客户环境无法下载这些驱动了。
    2)内核源码查看 netmap 编译的时候需要内核源码的支持,需要先查看内核的版本,并且在/ usr / src 目录下看看是否存在内核源码,如果不存在则需要下载内核的内核并解压缩,放到此处。

    [root@localhost netmap-master]# uname -r
    3.10.0-693.el7.x86_64
    

    或者:

    [root@localhost netmap-master]# rpm -qa|grep kernel
    kernel-3.10.0-693.el7.x86_64
    kernel-tools-libs-3.10.0-693.el7.x86_64
    kernel-headers-3.10.0-693.21.1.el7.x86_64
    kernel-devel-3.10.0-693.el7.x86_64
    kernel-tools-3.10.0-693.el7.x86_64
    

    查询到内核版本后,可以查看源码是否存在:

    [root@localhost ~]# ll /usr/src/
    debug/   kernels/
    [root@localhost ~]# ll /usr/src/
    debug/   kernels/
    [root@localhost ~]# ll /usr/src/kernels/
    总用量 4
    drwxr-xr-x. 22 root root 4096 9月  11 10:28 3.10.0-693.el7.x86_64
    

    二 netmap 编译和安装

    1. 以下为 makefie 文件生成和编译安装,说明如下:--drivers 后面带着网卡的类型。--kernel-sources 和 --kernel-dir 指定内核内核位置,如果内核内核为/usr/src/kernels 下面则可以不提供这两个选项。make install 命令需要 root 权限。

    ./configure  --kernel-sources=/usr/src/kernels/$(uname -r) --kernel-dir=/usr/src/kernels/$(uname -r) --prefix=/usr
    make&& make install
    
    1. 网卡上参数设置: 网卡本身有些技术提升抓包性能,对于 suricata 的抓包来说,需要关闭,下面参考 suricata 的相关文档来设置的

    • LRO/GRO 关闭 数据包在数据量链路层传输的时候不能超过 MTU(1500 个字节),那么就需要进行拆包和组包,这部分工作如果有 cpu 来做,将耗费 cpu 资源,LRO 和 GRO 技术是由网卡来进行组包和拆包。这是 suricata 的限制.ethtool -K p1p1 gro off lro off

    • 关闭硬件校验 如果启动这个,dsize 在 suricata 中不可用了和 tcp 状态的跟踪,如果不用这个关键字可以考虑打开。ethtool -K p1p1 tx off rx off

    • 合并队列 对很多网卡来说,不支持对称 hash 算法的话,如果多队列,会造成同一个流不同方向的包发到不同的队列上去,对 suricata 组包会有问题,所以大部分情况下,我们把队列个数改成 1 个,如果性能要求比较高,网卡支持对称 hash 算法的话,我们会考虑设置对称 hash 算法和改成多个队列的模式.

    [root@localhost ~]# ethtool -l p1p1
    Channel parameters for p1p1:
    Pre-set maximums:
    RX:     0
    TX:     0
    Other:      1
    Combined:   63   #一共支持多少个队列
    Current hardware settings:
    RX:     0
    TX:     0
    Other:      1
    Combined:   4  #现在起作用的是多少个队列
    

    合并成一个队列

    ethtool -L p1p1 combined 1
    
    • 网卡队列中包数目修改 网卡丢包原因可以通过以下命令查看:

    [root@localhost netmap-master]# ethtool -S p2p1|grep 'error'
         rx_errors: 0
         tx_errors: 0
         rx_over_errors: 0
         rx_crc_errors: 0
         rx_frame_errors: 0
         rx_fifo_errors: 0
         rx_missed_errors: 0
         tx_aborted_errors: 0
         tx_carrier_errors: 0
         tx_fifo_errors: 0
         tx_heartbeat_errors: 0
         rx_long_length_errors: 0
         rx_short_length_errors: 0
         rx_csum_offload_errors: 0
         fcoe_last_errors: 0
    [root@localhost netmap-master]# ethtool -S p2p1|grep 'drop'
         rx_dropped: 0
         tx_dropped: 0
         rx_fcoe_dropped: 0
    

    如果是 rx_missed_errors 错误个数很多,需要扩大些队列的包数量. 如果是 rx_dropped 多般是程序取包慢了造成缓冲区满了,包被丢掉,如果这种情况,扩大队列数量会稍微好点,但是如果流量持续很大,提升程序性能是王道。

    #查看网卡队列中可以保存的包的大小。
    [root@localhost netmap-master]# ethtool -g p2p1
    Ring parameters for p2p1:
    Pre-set maximums:
    RX:  4096
    RX Mini: 0
    RX Jumbo: 0
    TX:  4096
    Current hardware settings:
    RX:  512
    RX Mini: 0
    RX Jumbo: 0
    TX:  512
    
    # 队列中的包数量改成1024个,空间增加防止丢包
    [root@localhost netmap-master]# ethtool -G p2p1 rx 1024
    [root@localhost netmap-master]# ethtool -G p2p1 tx 1024
    
    1. 替换网卡驱动 如果是你替换的是 ssh 或 telnet 的网卡,会造成掉线,有时候也只是闪断。

    #!bin/sh
    #在netmap下执行替换ixgbe的网卡驱动,网卡类型不同则不同,另外由于netmap会接管整个网卡需要注意下不能正在连接网卡上操作,会造成断网。
    insmod netmap.ko
    rmmod  ixgbe
    insmod /home/xxx/netmap-master/ixgbe-5.3.7/src/ixgbe.ko
    

    验证安装结果:

    [root@localhost ~]# ls /dev/netmap
    /dev/netmap
    [root@localhost ~]# lsmod|grep netmap
    netmap                165523  1 ixgbe
    # 看下内核日志
    [root@localhost ~]# dmesg|grep netmap
    
    1. 运行测试程序 pkt-gen 是 netmap 自带的发包和收包工具,性能比 tcpreplay 更好,可以跑满网卡。位置如下:

    [root@localhost netmap-master]# tree ./build-apps/pkt-gen/
    ./build-apps/pkt-gen/
    ├── GNUmakefile -> /home/miaohq/netmap-master/LINUX/../apps/pkt-gen/GNUmakefile
    ├── pkt-gen
    ├── pkt-gen-b
    └── pkt-gen-b.o
    

    用法如下:

    #发包命令:
     pkt-gen -i p1p1 -n 100000 -z -Z -4 -l 512 -f tx
    
    #收包命令:
     pkt-gen -i p1p1 -f rx
    

    对于物理网卡来说,都有其网速极限,这个极限被称为线性速度,包的大小不同,pps 即每秒转发包的数量不同,极限如下:

    For a physical link, the maximum numer of packets per second can
    be computed with the formula:
        pps = line_rate / (672 + 8 * pkt_size)
    where "line_rate" is the nominal link rate (e.g 10 Gbit/s) and
    pkt_size is the actual packet size including MAC headers and CRC.
    The following table summarizes some results
                LINE RATE
        pkt_size \  100M    1G  10G 40G
          64    .1488   1.488   14.88   59.52
         128    .0589   0.589    5.89   23.58
         256    .0367   0.367    3.67   14.70
         512    .0209   0.209    2.09    8.38
        1024    .0113   0.113    1.13    4.51
        1518    .0078   0.078    0.78    3.12
    

    三 suricata 编译安装

    ./configure --prefix=/usr/local --sysconfdir=/etc/ --localstatedir=/usr/local/ --enable-unix-socket --with-libnss-libraries=/usr/lib64 --with-libnss-includes=/usr/include/nss3 --with-libnspr-libraries=/usr/lib64 --with-libnspr-includes=/usr/include/nspr4  --enable-nfqueue --enable-lua --enable-netmap
    

    关键部分就是带上了--enable-netmap 然后再进行make && make install 即可完成编译安装。

    验证编译后可执行文件是否支持 netmap,可以通过以下命令查看:

    [root@localhost .libs]# suricata --build-info
    This is Suricata version 5.0.3 RELEASE
    Features: PCAP_SET_BUFF AF_PACKET NETMAP HAVE_PACKET_FANOUT LIBCAP_NG LIBNET1.1 HAVE_HTP_URI_NORMALIZE_HOOK PCRE_JIT HAVE_NSS HAVE_LIBJANSSON TLS MAGIC RUST
    SIMD support: none
    Atomic intrinsics: 1 2 4 8 byte(s)
    64-bits, Little-endian architecture
    GCC version 9.3.0, C version 199901
    compiled with _FORTIFY_SOURCE=0
    L1 cache line size (CLS)=64
    thread local storage method: __thread
    compiled with LibHTP v0.5.33, linked against LibHTP v0.5.33
    
    Suricata Configuration:
      AF_PACKET support:                       yes
      eBPF support:                            no
      XDP support:                             no
      PF_RING support:                         no
      NFQueue support:                         no
      NFLOG support:                           no
      IPFW support:                            no
      Netmap support:                          yes v12
    ....
    

    有此命令:Netmap support: yes 表示支持。

    四 诗词欣赏

    商山早行
    [唐] 温庭筠
    晨起动征铎,客行悲故乡。
    鸡声茅店月,人迹板桥霜。
    槲叶落山路,枳花明驿墙。
    因思杜陵梦,凫雁满回塘。
    
    展开全文
  • vxlan-netmap netmap 是一个用于高速数据包 I/O 的框架。 关于 netmap,请参见 。 此实现是使用 netmap I/O 的 vxlan 网关。 ./vxlan-netmap usage of vxlan-netmap -o : overlay interface name -i : ...
  • 本文主要描述centos 8.2安装 netmap 1。 需要首先更新系统版本: yum -y update 2。 重启,选择新更新的内核 3。 安装相应的软件: yum install -y git make gcc patch wget yum install tar install rpm-...

    本文主要描述centos 8.2安装 netmap

    1。 需要首先更新系统版本:

    yum -y update

    2。 重启,选择新更新的内核

    3。 安装相应的软件:

    yum install -y git make gcc patch wget
    yum install tar
    install rpm-build redhat-rpm-config asciidoc hmaccalc perl-ExtUtils-Embed pesign xmlto
    yum install audit-libs-devel binutils-devel elfutils-devel elfutils-libelf-devel
    yum install ncurses-devel newt-devel numactl-devel pciutils-devel python-devel zlib-devel
    
    查一下内核版本:
    cat /etc/redhat-release 
    yum search kernel-devel
    安装内核版本
    yum install kernel-devel.x86_64 
    

    4。 下载netmap程序,可以从其他机器上拷贝,因为github经常被墙

    git clone https://github.com/luigirizzo/netmap.git
    

    到目前位置,netmap的环境基本安装完成

    5。 进入netmap目录的LINUX目录:

    cd netmap/LINUX/

    6. 执行configure

    ./configure --prefix=/usr/local/src/buildnetmap  --kernel-sources=/usr/src/kernels/4.18.0-240.22.1.el8_3.x86_64 --kernel-dir=/usr/src/kernels/4.18.0-240.22.1.el8_3.x86_64

    7。 执行make,make install

    find / -name netmap.ko
    make
    find / -name netmap.ko
    make install
    find / -name netmap.ko

    如上,netmap即可安装完成

     

     

    展开全文
  • netmap

    2017-08-09 23:07:45
    http://blog.csdn.net/fengfengdiandia/article/details/52869290
  • In this paper we present netmap, a novel framework that enables commodity operating systems to handle the millions of packets per seconds traversing 1..10 Gbit/s links, without requiring custom ...
  • 一、Netmap 简介 Netmap 是一个高性能收发原始数据包的框架,由 Luigi Rizzo 等人开发完成,其包含了内核模块以及用户态库函数。其目标是,不修改现有操作系统软件以及不需要特殊硬件支持,实现用户态和网卡之间...
  • 一、概述netmap 的简单介绍可以看我之前的一篇博客 netmap 介绍。netmap 分成两个部分:内核态部分和用户态部分使用方式:在网卡驱动中插入 netmap 相关代码,接管原来驱动程序的处理流程。
  • 【包】dpdk、ettercap、netmap、netsniff-ng

    千次阅读 2018-10-31 19:56:16
    (1)测试openstack架构下,相同租户不同子网之间的通信:数据包需要经过路由器,br-int作为二层网桥,没有学习功能。...(4)配置使用netmap网络架构,与tcpdmup对比抓包效率。 (5)配置使用netsniff-ng工具,与t...
  • ubuntu上安装netmap

    2020-08-27 18:16:30
    在学习过程中,因为需要在ubuntu上安装netmap,所以在网上找了很多方法,但是在安装过程中也遇到了麻烦,最后总算是成功,这里做一下网上的总结和记录,方便后面配置的时候回顾,如果内容涉及到侵权,请联系我删除,我...
  • 简单 对比 netmap 和 DPDK

    千次阅读 2020-10-16 11:15:57
    被问到,口头说不清楚,写一写。 细节不精确,大致原理差不多。...@@@ 简单 对比 netmap 和 DPDK。 netmap 对比 DPDK 可能唯一相同之处就是: 将 NIC 的 rx_ring_buffer 和 tx_ring_buffer,映射到 user...
  • libusnet 是一个轻量级的基于 netmap 的网络堆栈 [1]。 该库的目的是为 delelopers 提供一种简单的方法来构建具有数百万个连接的高性能服务器。 在 FreeBSD 和 Debian 机器上,与使用 FreeBSD 网络堆栈编写的 echo ...
  • netmap到dpdk,从硬件到协议栈,4个维度让网络体系构建起来【linux服务器开发】 专注于服务器后台开发,包括C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,...
  • 1 首先在ubuntu里面,需要把网卡的名字改成eth 类似这样的。 vim /etc/default/grub 找到GRUB_CMDLINE_LINUX="" ...2 安装netmap https://gitee.com/mirrors/netmap.git ./configure make &&a...
  • netmap 收发报文是采用 poll,主要函数是netmap_poll,我们这里只分析收包过程,发包过程类似。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,293
精华内容 517
关键字:

netmap