gojue/ecapture

关于在pcap模式中tc层skb_data payload数据传输的问题

caffe-in opened this issue · 3 comments

您好,我想请问kern/tc.h中skb_data_event_t结构体中只包含了timestamp,pid,comm,len和ifindex

struct skb_data_event_t {
    uint64_t ts;
    u32 pid;
    char comm[TASK_COMM_LEN];
    u32 len;
    u32 ifindex;
};

且在capture_packets函数中写入skb_events也限制了写入的大小为pkt_size=TC_PACKET_MIN_SIZE 36字节

    size_t pkt_size = TC_PACKET_MIN_SIZE;
    bpf_perf_event_output(skb, &skb_events, flags, &event, pkt_size);

而在event_openssl_tc.go中直接读出了payload

	tmpData := make([]byte, te.Len)
	if err = binary.Read(buf, binary.LittleEndian, &tmpData); err != nil {
		return
	}
	te.payload = tmpData

想请问这部分payload是如何进行内核态到用户态的传递的

    u64 flags = BPF_F_CURRENT_CPU;
    flags |= (u64)skb->len << 32;
    size_t pkt_size = TC_PACKET_MIN_SIZE;
    bpf_perf_event_output(skb, &skb_events, flags, &event, pkt_size);

重点是flags参数, 以及 bpf_perf_event_output 函数的使用。

long bpf_perf_event_output(void *ctx, struct bpf_map *map, u64
flags, void *data, u64 size)

          Description
                 Write raw data blob into a special BPF perf event
                 held by map of type BPF_MAP_TYPE_PERF_EVENT_ARRAY.
                 This perf event must have the following attributes:
                 PERF_SAMPLE_RAW as sample_type, PERF_TYPE_SOFTWARE
                 as type, and PERF_COUNT_SW_BPF_OUTPUT as config.

                 The flags are used to indicate the index in map for
                 which the value must be put, masked with
                 BPF_F_INDEX_MASK.  Alternatively, flags can be set
                 to BPF_F_CURRENT_CPU to indicate that the index of
                 the current CPU core should be used.

                 The value to write, of size, is passed through eBPF
                 stack and pointed by data.

                 The context of the program ctx needs also be passed
                 to the helper.

                 On user space, a program willing to read the values
                 needs to call perf_event_open() on the perf event
                 (either for one or for all CPUs) and to store the
                 file descriptor into the map. This must be done
                 before the eBPF program can send data into it. An
                 example is available in file
                 samples/bpf/trace_output_user.c in the Linux kernel
                 source tree (the eBPF program counterpart is in
                 samples/bpf/trace_output_kern.c).

                 bpf_perf_event_output() achieves better performance
                 than bpf_trace_printk() for sharing data with user
                 space, and is much better suitable for streaming
                 data from eBPF programs.

                 Note that this helper is not restricted to tracing
                 use cases and can be used with programs attached to
                 TC or XDP as well, where it allows for passing data
                 to user space listeners. Data can be:

                 • Only custom structs,

                 • Only the packet payload, or

                 • A combination of both.

          Return 0 on success, or a negative error in case of
                 failure.

Linux Kernel demo : https://elixir.bootlin.com/linux/v5.4/source/samples/bpf/xdp_sample_pkts_kern.c

还有其他问题吗?

没有了,谢谢您慷慨的解答'◡'