요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
=====================
BPF sk_lookup program
=====================
BPF sk_lookup program type (``BPF_PROG_TYPE_SK_LOOKUP``) introduces programmability
into the socket lookup performed by the transport layer when a packet is to be
delivered locally.
When invoked BPF sk_lookup program can select a socket that will receive the
incoming packet by calling the ``bpf_sk_assign()`` BPF helper function.
Hooks for a common attach point (``BPF_SK_LOOKUP``) exist for both TCP and UDP.
Motivation
==========
BPF sk_lookup program type was introduced to address setup scenarios where
binding sockets to an address with ``bind()`` socket call is impractical, such
as:
1. receiving connections on a range of IP addresses, e.g. 192.0.2.0/24, when
binding to a wildcard address ``INADRR_ANY`` is not possible due to a port
conflict,
2. receiving connections on all or a wide range of ports, i.e. an L7 proxy use
case.
Such setups would require creating and ``bind()``'ing one socket to each of the
IP address/port in the range, leading to resource consumption and potential
latency spikes during socket lookup.
Attachment
==========
BPF sk_lookup program can be attached to a network namespace with
``bpf(BPF_LINK_CREATE, ...)`` syscall using the ``BPF_SK_LOOKUP`` attach type and a
netns FD as attachment ``target_fd``.
Multiple programs can be attached to one network namespace. Programs will be
invoked in the same order as they were attached.
Hooks
=====
The attached BPF sk_lookup programs run whenever the transport layer needs to
find a listening (TCP) or an unconnected (UDP) socket for an incoming packet.
Incoming traffic to established (TCP) and connected (UDP) sockets is delivered
as usual without triggering the BPF sk_lookup hook.
The attached BPF programs must return with either ``SK_PASS`` or ``SK_DROP``
verdict code. As for other BPF program types that are network filters,
``SK_PASS`` signifies that the socket lookup should continue on to regular
hashtable-based lookup, while ``SK_DROP`` causes the transport layer to drop the
packet.
A BPF sk_lookup program can also select a socket to receive the packet by
calling ``bpf_sk_assign()`` BPF helper. Typically, the program looks up a socket
in a map holding sockets, such as ``SOCKMAP`` or ``SOCKHASH``, and passes a
``struct bpf_sock *`` to ``bpf_sk_assign()`` helper to record the
selection. Selecting a socket only takes effect if the program has terminated
with ``SK_PASS`` code.
When multiple programs are attached, the end result is determined from return
codes of all the programs according to the following rules:
1. If any program returned ``SK_PASS`` and selected a valid socket, the socket
is used as the result of the socket lookup.
2. If more than one program returned ``SK_PASS`` and selected a socket, the last
selection takes effect.
3. If any program returned ``SK_DROP``, and no program returned ``SK_PASS`` and
selected a socket, socket lookup fails.
4. If all programs returned ``SK_PASS`` and none of them selected a socket,
socket lookup continues on.
API
===
In its context, an instance of ``struct bpf_sk_lookup``, BPF sk_lookup program
receives information about the packet that triggered the socket lookup. Namely:
* IP version (``AF_INET`` or ``AF_INET6``),
* L4 protocol identifier (``IPPROTO_TCP`` or ``IPPROTO_UDP``),
* source and destination IP address,
* source and destination L4 port,
* the socket that has been selected with ``bpf_sk_assign()``.
Refer to ``struct bpf_sk_lookup`` declaration in ``linux/bpf.h`` user API
header, and `bpf-helpers(7)
<https://man7.org/linux/man-pages/man7/bpf-helpers.7.html>`_ man-page section
for ``bpf_sk_assign()`` for details.
Example
=======
See ``tools/testing/selftests/bpf/prog_tests/sk_lookup.c`` for the reference
implementation.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
전송 계층 소켓 조회 프로그래밍
1-15`BPF sk_lookup program` 문서는 `(GPL-2.0 OR BSD-2-Clause)` 라이선스를 따릅니다.
BPF sk_lookup 프로그램 형식인 `BPF_PROG_TYPE_SK_LOOKUP`은 패킷을 로컬로 전달할 때 전송 계층이 수행하는 소켓 조회에 프로그래밍 기능을 도입합니다.
BPF sk_lookup 프로그램이 호출되면 `bpf_sk_assign()` BPF 도우미 함수를 사용하여 들어오는 패킷을 받을 소켓을 선택할 수 있습니다.
공통 연결 지점인 `BPF_SK_LOOKUP` 훅은 TCP와 UDP 모두에 존재합니다.
주소와 포트 범위 처리 동기
16-32BPF sk_lookup 프로그램 형식은 `bind()` 소켓 호출로 각 주소에 소켓을 바인딩하기 어려운 다음 설정을 처리하기 위해 도입되었습니다.
- 포트 충돌 때문에 와일드카드 주소 `INADRR_ANY`를 사용할 수 없을 때 `192.0.2.0/24` 같은 IP 주소 범위에서 연결을 받는 경우
- 모든 포트 또는 넓은 포트 범위에서 연결을 받는 경우, 즉 L7 proxy 사용 사례
이런 설정은 범위 안의 IP 주소와 포트마다 소켓을 하나씩 만들고 `bind()`해야 합니다. 이는 자원을 소비하고 소켓 조회 중 지연 시간이 급증할 가능성을 만듭니다.
네트워크 네임스페이스 연결
33-42BPF sk_lookup 프로그램은 `BPF_SK_LOOKUP` 연결 형식과 네트워크 네임스페이스 파일 디스크립터를 연결 대상 `target_fd`로 지정한 `bpf(BPF_LINK_CREATE, ...)` 시스템 호출을 통해 network namespace에 연결할 수 있습니다.
하나의 네트워크 네임스페이스에 여러 프로그램을 연결할 수 있으며, 프로그램은 연결된 순서와 같은 순서로 호출됩니다.
훅 호출, 판정과 소켓 선택
43-76연결된 BPF sk_lookup 프로그램은 전송 계층이 들어오는 패킷에 사용할 listening (TCP) 소켓이나 unconnected (UDP) 소켓을 찾아야 할 때마다 실행됩니다.
이미 established (TCP) 상태이거나 connected (UDP) 상태인 소켓으로 들어오는 트래픽은 BPF sk_lookup 훅을 실행하지 않고 평소처럼 전달됩니다.
연결된 BPF 프로그램은 `SK_PASS` 또는 `SK_DROP` 판정 코드 중 하나를 반환해야 합니다. 다른 네트워크 필터 BPF 프로그램 형식과 마찬가지로 `SK_PASS`는 일반 해시 테이블 기반 소켓 조회를 계속한다는 뜻이고, `SK_DROP`은 전송 계층이 패킷을 폐기하게 합니다.
BPF sk_lookup 프로그램은 `bpf_sk_assign()` 도우미를 호출하여 패킷을 받을 소켓을 직접 선택할 수도 있습니다. 일반적으로 프로그램은 `SOCKMAP`이나 `SOCKHASH`처럼 소켓을 보관하는 맵에서 소켓을 찾은 뒤 `struct bpf_sock *`를 `bpf_sk_assign()`에 전달하여 선택을 기록합니다. 소켓 선택은 프로그램이 `SK_PASS`로 종료된 경우에만 효력이 있습니다.
여러 프로그램이 연결되어 있으면 모든 프로그램의 반환 코드로 최종 결과를 결정합니다.
- 어떤 프로그램이든 `SK_PASS`를 반환하고 유효한 소켓을 선택했다면 그 소켓을 조회 결과로 사용합니다.
- 둘 이상의 프로그램이 `SK_PASS`를 반환하고 소켓을 선택했다면 마지막 선택이 효력을 가집니다.
- 어떤 프로그램이 `SK_DROP`을 반환했고 `SK_PASS`와 함께 소켓을 선택한 프로그램이 없다면 소켓 조회가 실패합니다.
- 모든 프로그램이 `SK_PASS`를 반환했지만 어느 프로그램도 소켓을 선택하지 않았다면 일반 소켓 조회를 계속합니다.
컨텍스트 API와 참조 구현
77-98BPF sk_lookup 프로그램은 `struct bpf_sk_lookup` 인스턴스인 컨텍스트를 통해 소켓 조회를 촉발한 패킷의 다음 정보를 받습니다.
- IP 버전: `AF_INET` 또는 `AF_INET6`
- L4 프로토콜 식별자: `IPPROTO_TCP` 또는 `IPPROTO_UDP`
- 출발지와 목적지 IP 주소
- 출발지와 목적지 L4 포트
- `bpf_sk_assign()`으로 선택한 소켓
자세한 내용은 사용자 API 헤더 `linux/bpf.h`의 `struct bpf_sk_lookup` 선언과 `bpf_sk_assign()`을 설명하는 `bpf-helpers(7)` 매뉴얼 페이지 절을 참조하십시오: https://man7.org/linux/man-pages/man7/bpf-helpers.7.html
참조 구현은 `tools/testing/selftests/bpf/prog_tests/sk_lookup.c`에서 확인할 수 있습니다.
요약과 해설
prog_sk_lookup.rst:1-98`BPF_PROG_TYPE_SK_LOOKUP` 프로그램은 네트워크 네임스페이스의 `BPF_SK_LOOKUP` 지점에 연결되어, 리스닝 TCP 소켓이나 연결되지 않은 UDP 소켓을 찾는 시점에 실행됩니다.
`bpf_sk_assign()`으로 `SOCKMAP` 또는 `SOCKHASH`의 소켓을 선택할 수 있으며, 선택은 `SK_PASS`와 함께 반환되어야 적용됩니다. `SK_DROP`은 선택된 통과 소켓이 없을 때 조회와 패킷 전달을 실패시킵니다.
이 방식은 주소나 포트마다 개별 소켓을 만들고 `bind()`하는 비용을 피하므로 넓은 주소 범위 수신과 L7 프록시 같은 구성에 적합합니다.