xdp初体验

1 篇文章 0 订阅

简介

XDP是利用ebpf提供的全新内核网络性能提升方案,主要优势包括:

  • 它不需要任何专门的硬件
  • 它不需要内核绕过
  • 它不会取代 TCP/IP 堆栈
  • 它与 TCP/IP 堆栈以及 BPF 的所有优点协同工作

在没有引入XDP之前,原来是的内核网络数据包传输路径是这样的:

NIC > driver 驱动> tc流控 ==> netfilter ==> IP/TCP协议栈 ==> socket

启用XDP后,网络包传输路径是这样的:

①NIC > ②driver 驱动> ③Generic XDP==> tc流控 ==> netfilter ==> IP/TCP协议栈 ==> socket

offload模式,NIC支持xdp程序的offload, XDP程序直接hook到可编程网卡硬件设备上,与其他两种模式相比,它的处理性能最强;由于处于数据链路的最前端,过滤效率也是最高的。如果需要使用这种模式,需要在加载程序时明确声明。目前支持这种模式的网卡设备不多,有一家叫netronome网卡。

native 模式,XDP程序hook到网络设备的驱动上,它是XDP最原始的模式,因为还是先于操作系统进行数据处理,它的执行性能还是很高的,当然你的网络驱动需要支持,目前已知的有i40e, nfp, mlx系列ixgbe系列

generic模式,这是操作系统内核提供的通用XDP兼容模式,它可以在没有硬件或驱动程序支持的主机上执行XDP程序。在这种模式下,XDP的执行是由操作系统本身来完成的,以模拟native模式执行。好处是,只要内核够高,人人都能玩XDP;缺点是由于是仿真执行,需要分配额外的套接字缓冲区(SKB),导致处理性能下降,跟native模式在10倍左右的差距。

环境安装

  1. 测试环境:
[root@localhost xdp]# cat /etc/redhat-release 
CentOS Linux release 8.4.2105

编译可能需要内核相关头文件,建议安装 内核相关包

yum install -y kernel-devel
yum install -y kernel-headers
  1. 编译bpf代码需要依赖下面的工具

    • clang >= version 3.4.0
    • llvm >= version 3.7.1
    yum install -y clang
    yum install -y llvm
    
  2. 加载和卸载xdp程序依赖于ip命令

yum install -y iproute

测试代码

#include <linux/bpf.h>

/*
 * Comments from Linux Kernel:
 * Helper macro to place programs, maps, license in
 * different sections in elf_bpf file. Section names
 * are interpreted by elf_bpf loader.
 * End of comments

 * You can either use the helper header file below
 * so that you don't need to define it yourself:
 * #include <bpf/bpf_helpers.h>
 */
#define SEC(NAME) __attribute__((section(NAME), used))

SEC("xdp")
int xdp_hello_world(struct xdp_md *ctx) {
    // drop everything
    return XDP_DROP;
}

char _license[] SEC("license") = "GPL";

该例子比较简单,把收到的报文都drop掉,加载这个例子需要实现的效果就是ping不通网口,卸载则能正常ping通

XDP 结果码

使用 XDP 进行数据包处理,有 5 个返回码指示网络驱动处理数据包,列举如下:

  • 丢弃(XDP_DROP)
  • 转发(XDP_TX)
  • 重定向(XDP_REDIRECT)
  • 传递(XDP_PASS)
  • 错误(XDP_ABORTED)

编译demo

[root@localhost xdp]# clang -O2 -target bpf -c xdp-hello-world.c -o xdp-hello-world.o

查看生成的elf格式的可执行文件的相关信息,使用下面的命令能看到上文提到的Section信息:

[root@localhost xdp]# llvm-objdump -S xdp_hello_world.o

xdp_hello_world.o:      file format elf64-bpf


Disassembly of section xdp:

0000000000000000 <xdp_hello_world>:
llvm-objdump: warning: 'xdp_hello_world.o': failed to parse debug information for xdp_hello_world.o
       0:       b7 00 00 00 01 00 00 00 r0 = 1
       1:       95 00 00 00 00 00 00 00 exit
[root@localhost xdp]# readelf -a xdp_hello_world.o
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Linux BPF
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          376 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           64 (bytes)
  Number of section headers:         9
  Section header string table index: 1

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .strtab           STRTAB           0000000000000000  00000112
       0000000000000062  0000000000000000           0     0     1
  [ 2] .text             PROGBITS         0000000000000000  00000040
       0000000000000000  0000000000000000  AX       0     0     4
  [ 3] xdp               PROGBITS         0000000000000000  00000040
       0000000000000010  0000000000000000  AX       0     0     8
  [ 4] license           PROGBITS         0000000000000000  00000050
       0000000000000004  0000000000000000  WA       0     0     1
  [ 5] .eh_frame         PROGBITS         0000000000000000  00000058
       0000000000000030  0000000000000000   A       0     0     8
  [ 6] .rel.eh_frame     REL              0000000000000000  00000100
       0000000000000010  0000000000000010           8     5     8
  [ 7] .llvm_addrsig     LOOS+0xfff4c03   0000000000000000  00000110
       0000000000000002  0000000000000000   E       8     0     1
  [ 8] .symtab           SYMTAB           0000000000000000  00000088
       0000000000000078  0000000000000018           1     3     8
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  p (processor specific)

There are no section groups in this file.

There are no program headers in this file.

There is no dynamic section in this file.

Relocation section '.rel.eh_frame' at offset 0x100 contains 1 entry:
  Offset          Info           Type           Sym. Value    Sym. Name
00000000001c  000200000001 unrecognized: 1       0000000000000000 xdp

The decoding of unwind sections for machine type Linux BPF is not currently supported.

Symbol table '.symtab' contains 5 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS xdp_hello_world.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     3: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    4 _license
     4: 0000000000000000    16 FUNC    GLOBAL DEFAULT    3 xdp_hello_world

No version information found in this file.

还可以通过llvm-objdump这个工具来分析下这个可执行文件的反汇编指令信息:

[root@localhost xdp]# llvm-objdump -S xdp_hello_world.o

xdp_hello_world.o:      file format elf64-bpf


Disassembly of section xdp:

0000000000000000 <xdp_hello_world>:
       0:       b7 00 00 00 01 00 00 00 r0 = 1
       1:       95 00 00 00 00 00 00 00 exit

测试demo

  1. 加载
[root@localhost xdp]# ip link set dev ens19 xdp obj xdp_hello_world.o sec xdp

ip link set命令可以支持 ip link help查看帮助

ip link set [ { xdp | xdpgeneric | xdpdrv | xdpoffload } { off |
                          object FILE [ section NAME ] [ verbose ] |
                          pinned FILE } ]

sec [section name] 就是上文提到的通过Section来指定程序入口

device name 是本机某个网卡设备的名称,可以通过ip a查看本机所有的网卡设备。一般可以选取本机对外的IP所在的网卡设备。

xdpgeneric 对应上面的generic模式,xdpdrv对应上面的native模式,xdpoffload对应上面的offload模式

  1. 卸载
ip link set dev ens19 xdp off
  1. 测试效果

    3.1 加载xdp程序前

    [ych@localhost ~]$ ping 5.5.5.2
    PING 5.5.5.2 (5.5.5.2) 56(84) bytes of data.
    64 bytes from 5.5.5.2: icmp_seq=1 ttl=63 time=1.60 ms
    64 bytes from 5.5.5.2: icmp_seq=2 ttl=63 time=6.09 ms
    64 bytes from 5.5.5.2: icmp_seq=3 ttl=63 time=2.42 ms
    64 bytes from 5.5.5.2: icmp_seq=4 ttl=63 time=2.53 ms
    64 bytes from 5.5.5.2: icmp_seq=5 ttl=63 time=1.25 ms
    64 bytes from 5.5.5.2: icmp_seq=6 ttl=63 time=4.25 ms
    64 bytes from 5.5.5.2: icmp_seq=7 ttl=63 time=6.98 ms
    64 bytes from 5.5.5.2: icmp_seq=8 ttl=63 time=2.98 ms
    ^C
    --- 5.5.5.2 ping statistics ---
    8 packets transmitted, 8 received, 0% packet loss, time 18ms
    

    3.2 加载xdp程序后

    [ych@localhost ~]$ ping 5.5.5.2
    PING 5.5.5.2 (5.5.5.2) 56(84) bytes of data.
    64 bytes from 5.5.5.2: icmp_seq=1 ttl=63 time=1.53 ms
    64 bytes from 5.5.5.2: icmp_seq=2 ttl=63 time=2.45 ms
    64 bytes from 5.5.5.2: icmp_seq=3 ttl=63 time=3.62 ms
    64 bytes from 5.5.5.2: icmp_seq=4 ttl=63 time=1.19 ms
    
    ^C
    --- 5.5.5.2 ping statistics ---
    20 packets transmitted, 4 received, 80% packet loss, time 393ms
    rtt min/avg/max/mdev = 1.191/2.199/3.624/0.942 ms
    

    3.3 卸载后则能正常ping通

XDP 和 DPDK

XDP 有时与 DPDK 并列,当两者都是完美的方法时。XDP 为希望获得性能同时仍然利用内核的可编程性的用户提供了另一种选择。XDP 提供的一些功能包括:

  • 无需第三方代码和许可
  • 允许选择忙轮询或中断驱动网络
  • 无需分配大页面
  • 无需专用 CPU,因为用户在 CPU 之间构建工作时有更多选择
  • 无需从 3rd 方用户空间应用程序向内核注入数据包
  • 无需为访问网络硬件定义新的安全模型

相关网站地址

xdp官网

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值