VPP API 계층 레퍼런스
clib · vlib · vnet · VCL · TLS · offload로 이어지는 VPP API 계층 구조와 각 계층의 책임을 한 장의 지도로 정리합니다.
선행 문서: 이 페이지는 기초와 아키텍처의 벡터 패킷 처리·그래프 노드 개념을 전제로 합니다. 내부 구현 카테고리의 다른 페이지와 함께 읽어 주세요.
VPP의 소스 트리에는 기능이 비슷해 보이는 접두사(clib_, vlib_, vnet_, session_, vppcom_, tls_, vnet_crypto_)가 여러 개 섞여 있어서 처음 접하면 어느 계층의 API를 써야 할지 판단하기 어렵습니다. 이 절은 각 접두사가 어느 계층의 책임을 지고, 어떤 핵심 자료형(Type)과 함수가 있으며, 플러그인과 애플리케이션이 각각 어디에서 시작해야 하는지를 정리합니다. 아래 SVG는 전체 계층을 단 한 장에 펼쳐 본 지도(Map)입니다.
이 지도를 사용하는 기본 원칙은 단순합니다. 아래 계층은 위 계층의 언어를 모른다는 것입니다. 예를 들어 clib_bihash는 자기가 FIB를 저장하는지 ACL을 저장하는지 알지 못하고, vlib는 패킷이 TLS인지 IPsec인지 구분하지 않으며, vnet은 애플리케이션 세션이 어떤 소켓 API를 통해 접근하는지 신경 쓰지 않습니다. 이 단방향 의존성 덕분에 VPP는 플러그인으로 기능을 갈아 끼워도 하부가 흔들리지 않습니다.
각 계층의 책임과 대표 API
| 계층 | 주요 디렉터리 | 대표 자료형 | 대표 API | 언제 직접 호출하는가 |
|---|---|---|---|---|
| ⑤ clib/vppinfra | src/vppinfra/ |
u8 * 벡터, pool_t, clib_bihash_*_t |
clib_mem_alloc, vec_add1, pool_get, clib_bihash_add_del, clib_atomic_fetch_add, clib_spinlock_lock |
플러그인 내부 자료구조, 집계 카운터, 해시 기반 세션/플로우 테이블을 손수 만들 때 |
| ④ vlib | src/vlib/ |
vlib_main_t, vlib_buffer_t, vlib_node_registration_t, vlib_frame_t |
VLIB_REGISTER_NODE, vlib_get_buffer, vlib_get_next_frame, vlib_validate_buffer_enqueue_*, vlib_process_wait_for_event, vlib_worker_thread_barrier_sync |
새 그래프 노드를 작성하거나 CLI/프로세스 노드를 등록할 때 — 플러그인 개발의 기본 언어 |
| ③ vnet | src/vnet/ |
vnet_main_t, vnet_hw_interface_t, ip4_fib_t, ipsec_sa_t, vnet_crypto_op_t |
vnet_sw_interface_set_flags, fib_table_entry_path_add, ipsec_sa_add_and_lock, vnet_feature_enable_disable, vnet_crypto_process_ops |
인터페이스, 라우팅, ACL, IPsec, 암호화(Encryption)처럼 "네트워크 장비다운" 기능을 붙일 때 |
| ② session / transport | src/vnet/session/, tcp/, tls/, quic/ |
session_t, app_worker_t, tls_ctx_t, svm_fifo_t |
session_alloc_for_connection, tcp_connection_alloc, tls_init_ctx, svm_fifo_enqueue |
TCP/TLS/QUIC 엔진을 확장하거나 새 트랜스포트를 플러그인으로 추가할 때. 일반 플러그인은 거의 직접 만지지 않음 |
| ① 애플리케이션 / VCL | src/vcl/ |
vppcom_endpt_t, vls_handle_t, vppcom_cert_key_pair_t |
vppcom_app_create, vppcom_session_create, vppcom_session_connect, vppcom_epoll_wait, vppcom_add_cert_key_pair |
유저 프로세스가 VPP 호스트 스택을 "소켓처럼" 사용하고자 할 때 (대부분의 애플리케이션 개발 경로) |
| ⑥ 오프로드 | DPDK · cryptodev · ipsecmb | rte_mbuf, rte_crypto_op, rte_cryptodev_* |
rte_eth_rx_burst, rte_cryptodev_enqueue_burst, rte_cryptodev_dequeue_burst, IPsec-MB의 IMB_AES_GCM_ENC_* |
드라이버 또는 vnet_crypto 백엔드를 직접 작성할 때 — 일반적으로 플러그인은 vnet_crypto_*를 통해 간접 사용 |
하나의 요청이 계층을 어떻게 관통하는가
추상 개념을 구체화하기 위해, HTTPS 요청이 들어와서 IPsec 터널로 재전송되는 극단적인 경로를 따라가 봅니다. 이 한 줄의 플로우가 위 여섯 계층을 모두 건드립니다.
- ⑥ DPDK PMD가 NIC 링에서
rte_mbuf를 가져와 VPP의vlib_buffer_t로 감쌉니다. - ④ vlib의
dpdk-input노드가 프레임을 만들고, 벡터 단위로 다음 노드에 넘깁니다. - ③ vnet의
ethernet-input → ip4-input → ip4-lookup이ip4_fib_t와adj_*를 사용해 FIB 룩업을 수행합니다. - ② session의
tcp-established가 TCP 상태 머신을 돌리고, TLS 세션이면tls_* → svm_fifo_*경로로 복호화(Decryption)된 평문을 RX FIFO에 적재합니다. - ① VCL 애플리케이션이
vppcom_session_read로 평문을 읽고, 검사/변형 후vppcom_session_write로 다른 세션에 씁니다. - 반대 방향으로 내려오는 패킷은 다시 ③ vnet의
esp-encrypt가 ⑤ clib의clib_atomic_fetch_add로ipsec_sa_t.seq를 증가시키고,vnet_crypto_process_ops를 호출합니다. - ⑥ cryptodev(QAT)가 실제 AES-GCM 연산을 수행하고, 완료된 버퍼가 ④ vlib의 TX 경로로 돌아옵니다.
읽기 순서 가이드: 처음 VPP를 익힐 때는 이 지도의 ④ vlib → ⑤ clib → ③ vnet → ② session → ① VCL 순서가 이해도가 가장 빠릅니다. vlib는 "어떻게 움직이는가"를, clib는 "어떤 자료구조가 가용한가"를, vnet은 "네트워크 의미가 어떻게 붙는가"를, session/VCL은 "커널 소켓을 어떻게 흉내 내는가"를 설명합니다. ⑥ 오프로드는 필요할 때만 파고들어도 됩니다.
접두사만 보고 계층을 판별하는 법
실전에서는 헤더 파일명과 함수 접두사만 보고도 어느 계층에서 호출해야 하는지 거의 판단할 수 있습니다.
clib_*,vec_,pool_,hash_,bihash_→ ⑤ clib. 자료구조, 원자 연산, 락, 시간. 어디서든 자유롭게 호출 가능.vlib_*,VLIB_*매크로 → ④ vlib. 반드시vlib_main_t *vm컨텍스트가 있어야 하며, 워커 스레드 안에서 또는 배리어 아래서만 호출해야 하는 경우가 있음.vnet_*,fib_*,ip4_*,ipsec_*,classify_*→ ③ vnet. "네트워크 장비 의미"를 바꾸는 API. 대부분 메인 스레드 배리어 아래에서 호출 필요.session_*,tcp_*,udp_*,tls_*,quic_*,svm_fifo_*→ ② 세션/전송. 호스트 스택 엔진 내부. 일반 플러그인은 VCL 또는 session API 상위만 사용하는 편이 안전.vppcom_*,vls_*→ ① VCL. 유저스페이스 애플리케이션 전용. VPP 프로세스 내부(플러그인)에서 호출 금지.rte_*,IMB_*,qat_*→ ⑥ 오프로드. DPDK/ipsecmb/QAT 라이브러리의 직접 API. 일반 코드는vnet_crypto_*로 우회해 호출.
자주 하는 혼동:
clib_*와 vlib_*는 이름이 비슷해 보이지만, clib_*는 컨텍스트가 없는 순수 유틸리티이고 vlib_*는 반드시 런타임 컨텍스트(vm)를 요구합니다. 예를 들어 clib_mem_alloc은 어디서든 부를 수 있지만 vlib_get_buffer(vm, bi)는 vm 없이 호출되면 세그폴트합니다. 이 차이가 플러그인 초기화 함수에서 가장 자주 틀리는 지점입니다.