cilium / ebpf

ebpf-go is a pure-Go library to read, modify and load eBPF programs and attach them to various hooks in the Linux kernel.

Home Page:https://ebpf-go.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

load program: invalid argument: unknown func bpf_redirect_peer#155 (51 line(s) omitted)

guozijing opened this issue · comments

Describe the bug

I want to redirect the sock to an interface within container,
so i use the func bpf_redirect_peer, but i got the error:
load program: invalid argument: unknown func bpf_redirect_peer#155 (51 line(s) omitted)

Can anyone help me?
                switch (protol) {
		case IPPROTO_TCP: {
			// 192.168.222.1 1dea8c0
			// 10.42.31.114 721f2a0a
			if (ip == 0x721f2a0a) {
				return bpf_redirect_peer(39, 0);
			} else {
				goto done;
			}
		}
		default: {
			goto done;
		}

How to reproduce

#include "bpf_endian.h"
#include "common.h"

char __license[] SEC("license") = "Dual MIT/GPL";

#define MAX_MAP_ENTRIES 16

/* Define an LRU hash map for storing packet count by source IPv4 address */
struct {
	__uint(type, BPF_MAP_TYPE_LRU_HASH);
	__uint(max_entries, MAX_MAP_ENTRIES);
	__type(key, __u32); // source IPv4 address
	__type(value, __u32); // packet count
} xdp_stats_map SEC(".maps");

/*
Attempt to parse the IPv4 source address from the packet.
Returns 0 if there is no IPv4 header field; otherwise returns non-zero.
*/
static __always_inline int parse_ip_src_addr(struct xdp_md *ctx, __u32 *ip_src_addr, __u32 *protol) {
	void *data_end = (void *)(long)ctx->data_end;
	void *data     = (void *)(long)ctx->data;

	// First, parse the ethernet header.
	struct ethhdr *eth = data;
	if ((void *)(eth + 1) > data_end) {
		return 0;
	}

	if (eth->h_proto != bpf_htons(ETH_P_IP)) {
		// The protocol is not IPv4, so we can't parse an IPv4 source address.
		return 0;
	}

	// Then parse the IP header.
	struct iphdr *ip = (void *)(eth + 1);
	if ((void *)(ip + 1) > data_end) {
		return 0;
	}

	// Return the source IP address in network byte order.
	*ip_src_addr = (__u32)(ip->daddr);
	*protol = (__u32)(ip->protocol);
	return 1;
}

SEC("xdp")
int xdp_prog_func(struct xdp_md *ctx) {
	__u32 ip;
	__u32 protol;
	if (parse_ip_src_addr(ctx, &ip, &protol)) {
		bpf_map_update_elem(&xdp_stats_map, &ip, &protol, BPF_ANY);
		// Not an IPv4 packet, so don't count it.
		switch (protol) {
		case IPPROTO_TCP: {
			// 192.168.222.1 1dea8c0
			// 10.42.31.114 721f2a0a
			if (ip == 0x721f2a0a) {
				return bpf_redirect_peer(39, 0);
			} else {
				goto done;
			}
		}
		default: {
			goto done;
		}
		}
	}

done:
	// Try changing this to XDP_DROP and see what happens!
	return XDP_PASS;
}

Version information

latest