1

我正在尝试检测带有 VLAN 标签的数据包。我有一些 PCAP 文件包含要测试的 VLAN 标记数据包。示例数据包的 Wireshark 屏幕截图:

在此处输入图像描述

在阅读了一些教程后,我编写了以下代码:

#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/in.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_endian.h>


#define bpf_printk(fmt, ...)                              \
({                                                        \
  char ____fmt[] = fmt;                                   \
  bpf_trace_printk(____fmt, sizeof(____fmt),              \
                   ##__VA_ARGS__);                        \
})

SEC("xdpvlan")
int myxdpprogram(struct xdp_md *ctx) {
  void *data = (void *)(long)ctx->data;
  void *data_end = (void *)(long)ctx->data_end;
  struct ethhdr *eth = data;

  if ((void*)eth + sizeof(*eth) <= data_end) {
    bpf_printk("h_proto is: 0x%x, ETH_P_8021Q is: 0x%x\n", bpf_ntohs(eth->h_proto), ETH_P_8021Q);
  }
  return XDP_PASS;
}

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

中的输出/sys/kernel/debug/tracing/trace是这样的:

bpf_trace_printk: h_proto is: 0x800, ETH_P_8021Q is: 0x8100

我期望:

bpf_trace_printk: h_proto is: 0x8100, ETH_P_8021Q is: 0x8100

我正在使用 Fedora 34 进行测试,内核版本:5.11.12-300.fc34.x86_64. 为什么h_proto不等于0x8100

更新

我有两台虚拟机,我tcpreplay用来将数据包(PCAP 文件)从一个虚拟机发送到另一个具有 eBPF 程序的虚拟机。虚拟机通过仅主机接口连接。我使用以下方法加载程序: ip link set dev ens37 xdpgeneric obj xdp_vlan_kern.o sec xdpvlan

4

4 回答 4

1

在 xdpdrv 模式下运行 xdp 时,我遇到了同样的问题。在本教程中,我发现了有关 NIC 接口上的 VLAN 卸载的说明:

由于 XDP 需要将 VLAN 标头视为数据包标头的一部分,因此关闭 VLAN 硬件卸载(大多数硬件 NIC 都支持)很重要,因为这会从数据包标头中删除 VLAN 标记,而是在带外进行通信通过数据包硬件描述符到内核。testenv 脚本在设置环境时已经禁用了 VLAN 卸载,但作为参考,这里是如何使用 ethtool 为其他设备关闭它:

# Check current setting:
ethtool -k DEV | grep vlan-offload
# Disable for both RX and TX
ethtool --offload DEV rxvlan off txvlan off
# Same as:
# ethtool -K DEV rxvlan off txvlan off
于 2021-05-25T08:30:58.187 回答
1

[编辑] 不确定这个答案是否正确,请查看评论以获取详细信息。

通用 XDP 或 SKB 模式 XDP 是一种 XDP 模式,主要用于试验 XDP(并为未来基于驱动程序的实现提供模型)。鉴于它不需要 NIC 驱动程序的支持,它更易于使用,但性能低于其他模式(驱动程序/本机 XDP 或 XDP 硬件卸载)。

没有驱动程序支持的一个后果是,与原生 XDP 相比,通用 XDP 的挂钩在网络堆栈中必然更高。通用 XDP 在分配了套接字缓冲区 (SKB) 后运行。这意味着您的数据包可能已经进行了一些处理。在您的情况下,网络堆栈已经从其 VXLAN 标头中解封装了数据包,因此您只需观察常规 IP 数据包。

切换到驱动程序级 XDP,如果您的硬件(或虚拟接口)使用支持它的驱动程序,应该允许您在将数据包发送到内核堆栈和删除 VXLAN 之前对其进行处理。

于 2021-05-21T09:54:36.740 回答
0

建议我尝试将驱动程序模式用作@Qeole。我创建了一对虚拟接口,因为我的 NIC 驱动程序不支持驱动程序特定挂钩。

ip link add dev veth1 type veth peer name veth2

我加载了程序:

ip link set dev veth1 xdpdrv obj xdp_vlan_kern.o sec xdpvlan

并且重放了 PCAP 文件(在同一个虚拟机上):

tcpreplay -i veth2 vlan.pcap

输出如我所料:

bpf_trace_printk: h_proto is: 0x8100, ETH_P_8021Q is: 0x8100

于 2021-05-21T09:54:10.420 回答
0

罗曼索科洛夫的回答是正确的。
在发送端禁用 txvlan 修复了该错误。

ip link add veth0 type veth peer name veth1
ip link add link veth0 name veth0.100 type vlan id 100

ip link set veth0 up
ip link set veth1 up
ip link set veth0.100 up

ip addr add 10.100.0.4/24 dev veth0.100

ethtool -K veth0 txvlan off

veth1在使用模式下附加ebpf程序SKB,将数据包注入veth0.100(只需运行arping就足够了),然后我可以在我的ebpf程序中获取带有vlan标签的数据包。

only但是,当我禁用rxvlan时它并没有解决问题veth1。我尚未在物理设备上对此进行测试,稍后我会尝试并修改此答案。

于 2021-08-31T12:40:26.607 回答