我确实有一些 DPDK 经验,但目前我正在阅读许多有关 XDP 的博客。我正在尝试比较这两种技术并了解 DPDK 和 XDP 之间的差异。这引发了一些问题。我希望有人能帮助我解决以下问题:
预先感谢您的帮助!
我找到了一个 eBPF 示例,它代理请求,根据目标端口过滤哪些请求。
我试图按客户端的 process_id 而不是目标端口进行过滤,并尝试添加bpf_get_current_pid_tgid() here。然而,该方法似乎在该上下文中未找到/可用。
在这种情况下,如何找到正确的方法来获取连接所有者 process_id ?
我尝试进入XDP,为此我有一个非常小的程序:
// SPDX-License-Identifier: GPL-2.0
#include <linux/bpf.h>
#include "bpf/bpf_helpers.h"
#include "xdpsock.h"
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, MAX_SOCKS);
__uint(key_size, sizeof(int));
__uint(value_size, sizeof(int));
} xsks_map SEC(".maps");
SEC("xdp_sock") int xdp_sock_prog(struct xdp_md *ctx) {
return XDP_DROP;
}
Run Code Online (Sandbox Code Playgroud)
但如果我尝试将其加载到虚拟接口中veth-basic02,则会收到此错误:
$ sudo ip -force link set dev veth-basic02 xdp 对象 xdpsock_kern.o 部分 xdp_sock
Prog 部分“xdp_sock”被拒绝:不允许操作 (1)!- 类型:6 - 指令:2(0 超出限制) - 许可证:
验证者分析:
获取节目/地图时出错!
内核版本:5.3.0-28-generic
这是我正在使用的 Makefile:
OBJS = xdpsock_kern.o
LLC ?= llc
CLANG ?= clang
INC_FLAGS = -nostdinc -isystem `$(CLANG) -print-file-name=include` …Run Code Online (Sandbox Code Playgroud) 对于以下程序,我从验证器处收到一条错误,指出它超过了 1M 指令,即使它不应该。该程序查找 HTTP 数据包的主机名。
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
struct server_name {
char server_name[256];
__u16 length;
};
#define MAX_SERVER_NAME_LENGTH 253
#define HEADER_LEN 6
SEC("xdp")
int collect_ips_prog(struct xdp_md *ctx) {
char *data_end = (char *)(long)ctx->data_end;
char *data = (char *)(long)ctx->data;
int host_header_found = 0;
for (__u16 i = 0; i <= 512 - HEADER_LEN; i++) {
host_header_found = 0;
if (data_end < data + HEADER_LEN) {
goto end;
}
// Elf loader does not allow NULL terminated strings, so have to …Run Code Online (Sandbox Code Playgroud) 我有一个带有以下映射定义的 eBPF 程序:
struct bpf_map_def SEC("maps") servers = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(struct ip_key),
.value_size = sizeof(struct dest_info),
.max_entries = MAX_SERVERS,
};
struct bpf_map_def SEC("maps") client_addrs = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(struct port_key),
.value_size = sizeof(struct client_port_addr),
.max_entries = MAX_CLIENTS,
};
Run Code Online (Sandbox Code Playgroud)
其中结构体定义如下:
struct port_key {
__u16 port;
__u16 pad[3];
};
struct ip_key {
__u32 key;
__u32 pad;
};
struct dest_info {
__u32 saddr;
__u32 daddr;
__u64 bytes;
__u64 pkts;
__u8 dmac[6];
__u16 pad;
};
struct client_port_addr …Run Code Online (Sandbox Code Playgroud) 我可以从文档中确认,如果在 HASH_MAP 上完成,bpf_map_update_elem 是一个原子操作。来源(https://man7.org/linux/man-pages/man2/bpf.2.html)。[引用:map_update_elem() 以原子方式替换现有元素]
我的问题是2倍。
如果元素不存在怎么办,map_update_elem 仍然是原子的吗?
XDP 操作 bpf_map_delete_elem 线程在用户空间程序中安全吗?
该映射是 HASH_MAP。
我刚刚学习XDP。在旅途中,我遇到了一个我无法理解的案例。当我注意到没有任何变化时,我在某些 UDP 数据包上尝试了一些奇特的东西。所以我尝试用一个最小的例子来重现这个问题。这是最小的例子:
#include <linux/bpf.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/udp.h>
#define SEC(NAME) __attribute__((section(NAME), used))
SEC("obfuscator_main")
int dropper(struct xdp_md *ctx) {
return XDP_DROP;
}
char _license[] SEC("license") = "GPL";
Run Code Online (Sandbox Code Playgroud)
(不要介意“混淆器”名称,它是其余代码的剩余部分)。
我编译并加载这个:
clang -Wall -O2 -target bpf -c obfuscate.c -o obfuscate.o
sudo ip link set dev enp3s0 xdp obj obfuscate.o sec obfuscator_main
Run Code Online (Sandbox Code Playgroud)
我确认到我的计算机的传入流量已完全丢失。但是,数据包仍然可以出去。我 ping 运行 tcpdump 的远程服务器,它看到了 ICMP 请求。但我在本地计算机上没有得到任何响应。
为什么它不能对传出的数据包执行任何操作?
我试图通过运行以下 BPF 程序将数据(IP 地址)从内核空间发送到用户空间:
struct bpf_map_def EVENTS = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(__u32),
.value_size = sizeof(__u32),
.max_entries = 1,
};
SEC("xdp")
int _xdp_ip_filter(struct xdp_md *ctx) {
bpf_printk("got a packet\n");
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
struct ethhdr *eth = data;
// check packet size
if (eth + 1 > data_end) {
return XDP_PASS;
}
// get the source address of the packet
struct iphdr *iph = data + sizeof(struct ethhdr);
if (iph + 1 …Run Code Online (Sandbox Code Playgroud)