VPP 패킷 버퍼 구조 (vlib_buffer_t)
VPP vlib_buffer_t 구조체 상세: 2-캐시라인 레이아웃, 메타데이터 영역, current_data/current_length, chained buffer, 메모리 할당 패턴을 다룹니다.
선행 문서: 이 페이지는 기초와 아키텍처의 벡터 패킷 처리·그래프 노드 개념을 전제로 합니다. 내부 구현 카테고리의 다른 페이지와 함께 읽어 주세요.
vlib_buffer_t 메모리 레이아웃과 캐시라인
vlib_buffer_t는 VPP에서 패킷 데이터를 관리하는 핵심 구조체로, 커널의 sk_buff에 대응합니다. 정확히 2개의 캐시라인(128바이트)으로 설계되어 캐시 효율을 극대화합니다.
| 필드 | 오프셋(Offset) | 크기 | 용도 |
|---|---|---|---|
current_data | 0x00 | i16 | data[0]부터 현재 패킷 시작 위치까지의 오프셋 |
current_length | 0x02 | u16 | 현재 버퍼의 유효 데이터 길이 |
flags | 0x04 | u32 | VLIB_BUFFER_TOTAL_LENGTH_VALID, IS_TRACED 등 플래그 |
flow_id | 0x08 | u32 | NIC RSS 해시(Hash) 또는 플로우 분류 ID |
next_buffer | 0x0C | u32 | 체인 버퍼의 다음 버퍼 인덱스 (점보 프레임) |
current_config_index | 0x10 | u32 | Feature arc 설정 인덱스 |
error | 0x14 | u16 | 노드별 에러 코드 인덱스 |
n_add_refs | 0x16 | u8 | 추가 참조 카운트(Reference Count) (복제 시) |
buffer_pool_index | 0x17 | u8 | 버퍼가 속한 풀 인덱스 |
opaque[10] | 0x18 | 40B | 노드별 메타데이터 (ip4_header_t *, adjacency index 등) |
opaque2[16] | 0x40 | 64B | 확장 메타데이터 (vnet 계층, 트레이스 정보) |
trace_handle | — | u32 | show trace 결과와 연결되는 핸들 |
핵심 접근 API
/* vlib_buffer_t 핵심 접근 API */
/* 버퍼 인덱스(u32)로 버퍼 포인터 획득 */
vlib_buffer_t *b = vlib_get_buffer(vm, buffer_index);
/* 현재 데이터 시작 포인터 */
void *data = vlib_buffer_get_current(b);
/* 헤더 추가/제거 (current_data 이동) */
vlib_buffer_advance(b, -sizeof(ethernet_header_t)); /* 헤더 추가 */
vlib_buffer_advance(b, sizeof(ip4_header_t)); /* 헤더 제거 */
/* 체인 버퍼의 전체 길이 */
u32 total = vlib_buffer_length_in_chain(vm, b);
/* 버퍼 복제 (멀티캐스트 등) */
u32 clone_bi;
vlib_buffer_clone(vm, buffer_index, &clone_bi, 1, CLIB_CACHE_LINE_BYTES);
코드 설명
-
3행
vlib_get_buffer()는 32비트 인덱스를 버퍼 포인터로 변환합니다. 버퍼 풀의 시작 주소에 인덱스를 더하는 단순 산술 연산으로, O(1) 시간에 완료됩니다. -
6행
vlib_buffer_get_current()는b->data + b->current_data를 반환합니다. 각 노드가 헤더를 파싱한 후current_data오프셋을 전진시키므로, 다음 노드는 자신의 헤더 시작 위치를 바로 얻습니다. -
9~10행
vlib_buffer_advance()는 음수 값이면 헤더를 추가(포인터 후퇴), 양수이면 헤더를 소비(포인터 전진)합니다. 데이터 복사 없이 오프셋만 조정하여 제로 카피 처리를 가능하게 합니다. -
16~17행
vlib_buffer_clone()은 멀티캐스트나 미러링 시 사용됩니다. 원본 데이터는 공유하고 메타데이터만 복제하여 메모리 사용과 복사 비용을 최소화합니다.
opaque 영역과 버퍼 풀 운영
/* opaque 영역 사용 예: ip4 노드가 저장하는 메타데이터 */
typedef struct {
ip4_header_t *ip_header;
u32 adj_index;
u32 flow_hash;
u32 fib_index;
} ip4_buffer_opaque_t;
/* opaque 접근 매크로 */
#define vnet_buffer(b) ((vnet_buffer_opaque_t *)(b)->opaque)
#define vnet_buffer2(b) ((vnet_buffer_opaque2_t *)(b)->opaque2)
버퍼 풀 고갈 증상:
show buffers에서 free 카운트가 0에 가까워지면, 패킷이 error-drop 노드로 전달되며 show errors에 no-buffer 에러가 증가합니다. buffers-per-numa 값을 늘리거나 hugepage를 추가 할당하세요.