← Documents Documentation/bpf/linux-notes.rst GitHub 원문 ↗

Linux 6.18.37 · BPF

Linux implementation notes

eBPF instruction set의 Linux 구현에서 byte swap alias, verifier 제한, map·variable reference, legacy packet access가 동작하는 방식을 설명합니다.

Source pathDocumentation/bpf/linux-notes.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

linux-notes.rst:1-84

Linux eBPF 구현은 byte-order conversion alias를 제공하지만 register에서 helper ID를 읽는 `(0x8d)` call instruction은 아직 verifier가 허용하지 않습니다. Map reference는 `fd_array`, variable address는 BTF ID를 사용합니다.

Classic BPF에서 이어받은 ABS·IND packet load는 `struct sk_buff` context에서만 쓸 수 있습니다. R6를 input, R0를 output으로 사용하고 R1-R5를 clobber하며 packet boundary를 넘으면 execution을 종료합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. contents::
2 .. sectnum::
3
4 ==========================
5 Linux implementation notes
6 ==========================
7
8 This document provides more details specific to the Linux kernel implementation of the eBPF instruction set.
9
10 Byte swap instructions
11 ======================
12
13 ``BPF_FROM_LE`` and ``BPF_FROM_BE`` exist as aliases for ``BPF_TO_LE`` and ``BPF_TO_BE`` respectively.
14
15 Jump instructions
16 =================
17
18 ``BPF_CALL | BPF_X | BPF_JMP`` (0x8d), where the helper function
19 integer would be read from a specified register, is not currently supported
20 by the verifier. Any programs with this instruction will fail to load
21 until such support is added.
22
23 Maps
24 ====
25
26 Linux only supports the 'map_val(map)' operation on array maps with a single element.
27
28 Linux uses an fd_array to store maps associated with a BPF program. Thus,
29 map_by_idx(imm) uses the fd at that index in the array.
30
31 Variables
32 =========
33
34 The following 64-bit immediate instruction specifies that a variable address,
35 which corresponds to some integer stored in the 'imm' field, should be loaded:
36
37 ========================= ====== === ========================================= =========== ==============
38 opcode construction opcode src pseudocode imm type dst type
39 ========================= ====== === ========================================= =========== ==============
40 BPF_IMM | BPF_DW | BPF_LD 0x18 0x3 dst = var_addr(imm) variable id data pointer
41 ========================= ====== === ========================================= =========== ==============
42
43 On Linux, this integer is a BTF ID.
44
45 Legacy BPF Packet access instructions
46 =====================================
47
48 As mentioned in the `ISA standard documentation
49 <instruction-set.html#legacy-bpf-packet-access-instructions>`_,
50 Linux has special eBPF instructions for access to packet data that have been
51 carried over from classic BPF to retain the performance of legacy socket
52 filters running in the eBPF interpreter.
53
54 The instructions come in two forms: ``BPF_ABS | <size> | BPF_LD`` and
55 ``BPF_IND | <size> | BPF_LD``.
56
57 These instructions are used to access packet data and can only be used when
58 the program context is a pointer to a networking packet. ``BPF_ABS``
59 accesses packet data at an absolute offset specified by the immediate data
60 and ``BPF_IND`` access packet data at an offset that includes the value of
61 a register in addition to the immediate data.
62
63 These instructions have seven implicit operands:
64
65 * Register R6 is an implicit input that must contain a pointer to a
66 struct sk_buff.
67 * Register R0 is an implicit output which contains the data fetched from
68 the packet.
69 * Registers R1-R5 are scratch registers that are clobbered by the
70 instruction.
71
72 These instructions have an implicit program exit condition as well. If an
73 eBPF program attempts access data beyond the packet boundary, the
74 program execution will be aborted.
75
76 ``BPF_ABS | BPF_W | BPF_LD`` (0x20) means::
77
78 R0 = ntohl(*(u32 *) ((struct sk_buff *) R6->data + imm))
79
80 where ``ntohl()`` converts a 32-bit value from network byte order to host byte order.
81
82 ``BPF_IND | BPF_W | BPF_LD`` (0x40) means::
83
84 R0 = ntohl(*(u32 *) ((struct sk_buff *) R6->data + src + imm))
85

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Linux eBPF 구현 참고 사항

1-8

문서는 `contents`와 `sectnum` directive로 목차와 절 번호를 구성합니다. `Linux implementation notes`는 eBPF instruction set의 Linux kernel 구현에만 해당하는 세부 사항을 설명합니다.

Byte swap instruction

9-14

`BPF_FROM_LE`와 `BPF_FROM_BE`는 각각 `BPF_TO_LE`와 `BPF_TO_BE`의 alias로 존재합니다.

Jump instruction 제한

15-22

지정한 register에서 helper function integer를 읽는 `BPF_CALL | BPF_X | BPF_JMP` instruction `(0x8d)`은 현재 verifier가 지원하지 않습니다. 이 지원이 추가되기 전까지 해당 instruction이 포함된 program은 load에 실패합니다.

Map reference 구현

23-30

Linux는 element가 하나뿐인 array map에 대해서만 `map_val(map)` operation을 지원합니다.

Linux는 BPF program과 연결된 map을 `fd_array`에 저장합니다. 따라서 `map_by_idx(imm)`은 array의 해당 index에 있는 fd를 사용합니다.

Variable address immediate instruction

31-44

다음 64-bit immediate instruction은 `imm` field에 저장된 integer에 대응하는 variable address를 load하도록 지정합니다.

Opcode 구성OpcodeSrcPseudocodeImm typeDst type
`BPF_IMM | BPF_DW | BPF_LD``0x18``0x3``dst = var_addr(imm)`Variable IDData pointer

Linux에서 이 integer는 `BTF ID`입니다.

Legacy BPF packet access instruction

45-84

[ISA standard documentation](instruction-set.html#legacy-bpf-packet-access-instructions)에서 설명하듯 Linux는 packet data에 접근하는 특별한 eBPF instruction을 제공합니다. 이 instruction은 eBPF interpreter에서 실행되는 legacy socket filter의 performance를 유지하기 위해 classic BPF에서 이어받았습니다.

Instruction은 `BPF_ABS | <size> | BPF_LD`와 `BPF_IND | <size> | BPF_LD` 두 형태입니다. Program context가 networking packet을 가리키는 pointer일 때만 packet data access에 사용할 수 있습니다.

`BPF_ABS`는 immediate data가 지정한 absolute offset의 packet data에 접근합니다. `BPF_IND`는 immediate data에 register value를 더한 offset으로 packet data에 접근합니다.

이 instruction에는 다음 일곱 implicit operand가 있습니다.

  • Register `R6`는 `struct sk_buff` pointer를 담아야 하는 implicit input입니다.
  • Register `R0`는 packet에서 가져온 data를 담는 implicit output입니다.
  • Register `R1-R5`는 instruction이 clobber하는 scratch register입니다.

Implicit program exit condition도 있습니다. eBPF program이 packet boundary를 넘어 data에 접근하려 하면 program execution을 abort합니다.

`BPF_ABS | BPF_W | BPF_LD` `(0x20)`의 의미는 다음과 같습니다.

R0 = ntohl(*(u32 *) ((struct sk_buff *) R6->data + imm))

`ntohl()`은 32-bit value를 network byte order에서 host byte order로 변환합니다.

`BPF_IND | BPF_W | BPF_LD` `(0x40)`의 의미는 다음과 같습니다.

R0 = ntohl(*(u32 *) ((struct sk_buff *) R6->data + src + imm))