|
| 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 | +Legacy BPF Packet access instructions |
| 11 | +===================================== |
| 12 | + |
| 13 | +As mentioned in the `ISA standard documentation <instruction-set.rst#legacy-bpf-packet-access-instructions>`_, |
| 14 | +Linux has special eBPF instructions for access to packet data that have been |
| 15 | +carried over from classic BPF to retain the performance of legacy socket |
| 16 | +filters running in the eBPF interpreter. |
| 17 | + |
| 18 | +The instructions come in two forms: ``BPF_ABS | <size> | BPF_LD`` and |
| 19 | +``BPF_IND | <size> | BPF_LD``. |
| 20 | + |
| 21 | +These instructions are used to access packet data and can only be used when |
| 22 | +the program context is a pointer to a networking packet. ``BPF_ABS`` |
| 23 | +accesses packet data at an absolute offset specified by the immediate data |
| 24 | +and ``BPF_IND`` access packet data at an offset that includes the value of |
| 25 | +a register in addition to the immediate data. |
| 26 | + |
| 27 | +These instructions have seven implicit operands: |
| 28 | + |
| 29 | +* Register R6 is an implicit input that must contain a pointer to a |
| 30 | + struct sk_buff. |
| 31 | +* Register R0 is an implicit output which contains the data fetched from |
| 32 | + the packet. |
| 33 | +* Registers R1-R5 are scratch registers that are clobbered by the |
| 34 | + instruction. |
| 35 | + |
| 36 | +These instructions have an implicit program exit condition as well. If an |
| 37 | +eBPF program attempts access data beyond the packet boundary, the |
| 38 | +program execution will be aborted. |
| 39 | + |
| 40 | +``BPF_ABS | BPF_W | BPF_LD`` (0x20) means:: |
| 41 | + |
| 42 | + R0 = ntohl(*(u32 *) ((struct sk_buff *) R6->data + imm)) |
| 43 | + |
| 44 | +where ``ntohl()`` converts a 32-bit value from network byte order to host byte order. |
| 45 | + |
| 46 | +``BPF_IND | BPF_W | BPF_LD`` (0x40) means:: |
| 47 | + |
| 48 | + R0 = ntohl(*(u32 *) ((struct sk_buff *) R6->data + src + imm)) |
| 49 | + |
| 50 | +Appendix |
| 51 | +======== |
| 52 | + |
| 53 | +For reference, the following table lists legacy Linux-specific opcodes in order by value. |
| 54 | + |
| 55 | +====== ==== =================================================== ============= |
| 56 | +opcode imm description reference |
| 57 | +====== ==== =================================================== ============= |
| 58 | +0x20 any dst = ntohl(\*(uint32_t \*)(R6->data + imm)) `Legacy BPF Packet access instructions`_ |
| 59 | +0x28 any dst = ntohs(\*(uint16_t \*)(R6->data + imm)) `Legacy BPF Packet access instructions`_ |
| 60 | +0x30 any dst = (\*(uint8_t \*)(R6->data + imm)) `Legacy BPF Packet access instructions`_ |
| 61 | +0x38 any dst = ntohll(\*(uint64_t \*)(R6->data + imm)) `Legacy BPF Packet access instructions`_ |
| 62 | +0x40 any dst = ntohl(\*(uint32_t \*)(R6->data + src + imm)) `Legacy BPF Packet access instructions`_ |
| 63 | +0x48 any dst = ntohs(\*(uint16_t \*)(R6->data + src + imm)) `Legacy BPF Packet access instructions`_ |
| 64 | +0x50 any dst = \*(uint8_t \*)(R6->data + src + imm)) `Legacy BPF Packet access instructions`_ |
| 65 | +0x58 any dst = ntohll(\*(uint64_t \*)(R6->data + src + imm)) `Legacy BPF Packet access instructions`_ |
0 commit comments