작성일: 2024년 7월 16일
아래 글은 나의 주관적 생각이 포함된 것이므로 정확한 기술 Spec을 원하는 분은 이 글을 참고용으로만 읽고,
이 블로그의 중간에 링크를 달아둔 Official document를 열람하는 것을 권장함.
XDP 개요 (들어가는 글)
XDP(eXpress Data Path)는 OS network stack을 우회하여 별도의 user application으로 보내고 받도록 하는데 사용되는 eBPF 기반의 data path이다.
Linux kernel version 4.8부터 XDP를 포함하므로 XDP 프로그래밍을 위해서 별도로 library를 설치할 필요는 없다.
아래 그림만 잘 들여다보면, XDP_* 처리(Action)에 대한 감이 온다.
위 그림에서 (start), interface output을 물리 네트워크 포트 또는 NIC port 라고 가정하고 보면 Packet 흐름이 자연스러워진다.
그리고, 이 블로그에서는 (start), interface output 가 동일 NIC port라고 가정하고 나머지 내용을 설명할 것이다.
XDP_* Action Code |
Description |
XDP_PASS |
원래의 network packet이 처리되는 것처럼 Network stack으로 보낸다. (즉, XDP가 없더라도 원래 동작하던 network packet 처리) |
XDP_DROP |
패킷을 drop (폐기) |
XDP_ABORTED |
Trace point exception과 함께 해당 packet을 drop (폐기) |
XDP_TX |
위 그림에 묘사된 것처럼 아무 처리하지 않고, 바로 NIC port로 되돌려 보낸다. (반송 처리) |
XDP_REDIRECT |
AF_XDP Address Family를 통해 packet을 다른 NIC port로 보내거나 User Space Socket으로 redirect한다. --- 참고로 AF_XDP address family는 Linux kernel 4.18부터 추가되었다.
|
예제 / 실습 자료
위 내용을 바탕으로 실습하고자 한다면, 아래 tutorial을 참고할 것!
XDP tutorial : 문서 링크 열기
아래 git repo에 여러 실습 예제가 있는데, 그 중에서 "basic01-xdp-pass"와 같은 쉬운 예제부터 실습하면서
전체 처리 절차를 이해하는 추천함!
Tutorial one liners (bpftrace) : 문서 링크 열기
Go Packet Generator (go-pktgen) : 문서 링크 열기
-> 위 go-pktgen 프로그램은 아래 go package를 사용하므로, 아래 golang pkg source code 분석하는 것을 추천.
XDP Go Package : 소스 코드 링크 열기
Linux kernel source code에서 XDP 관련 코드를 찾아보기 (예시)
Linux kernel source code에서 network driver와 관련한 code를 찾아 보면,
XDP_*와 관련있는 부분을 쉽게 만날 수 있다.
그 중에서 몇 개를 여기에 적어보겠다.
##
## File: linux/latest/source/drivers/net/ethernet/intel/i40e/i40e_txrx.c
##
... 중간 생략 ...
/**
* i40e_run_xdp - run an XDP program
* @rx_ring: Rx ring being processed
* @xdp: XDP buffer containing the frame
* @xdp_prog: XDP program to run
**/
static int i40e_run_xdp(struct i40e_ring *rx_ring, struct xdp_buff *xdp, struct bpf_prog *xdp_prog)
{
int err, result = I40E_XDP_PASS;
struct i40e_ring *xdp_ring;
u32 act;
if (!xdp_prog)
goto xdp_out;
prefetchw(xdp->data_hard_start); /* xdp_frame write */
act = bpf_prog_run_xdp(xdp_prog, xdp);
switch (act) {
case XDP_PASS: ## NOTE: 따로 처리할 것이 없다.
break; ## 그냥, 원래 하던대로 network stack으로 보내면 된다.
case XDP_TX: ## NOTE: RX 패킷이 들어온 NIC을 찾아서 TX 패킷을 그 NIC으로 보내도록 한다.
xdp_ring = rx_ring->vsi->xdp_rings[rx_ring->queue_index];
result = i40e_xmit_xdp_tx_ring(xdp, xdp_ring);
if (result == I40E_XDP_CONSUMED)
goto out_failure;
break;
case XDP_REDIRECT:
err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog);
if (err)
goto out_failure;
result = I40E_XDP_REDIR;
break;
default:
bpf_warn_invalid_xdp_action(rx_ring->netdev, xdp_prog, act);
fallthrough;
case XDP_ABORTED: ## NOTE: 패킷을 폐기
out_failure:
trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
fallthrough; /* handle aborts by dropping packet */
case XDP_DROP: ## NOTE: 패킷을 폐기
result = I40E_XDP_CONSUMED;
break;
}
xdp_out:
return result;
}
... 중간 생략 ...
eBPF 공식 문서
What is eBPF?
문서 링크: https://ebpf.io/what-is-ebpf/
The eBPF Library for Go
문서 링크: https://ebpf-go.dev/
추천 글
eBPF/XDP: 당신만 모르는 안전하고 빠른 Networking
https://pangyoalto.com/ebpf-and-xdp/
Unlocking Network Performance with XDP and eBPF
https://medium.com/@khushichhillar02/unlocking-network-performance-with-xdp-and-ebpf-67c712128025
Kernel-bypass techniques for high-speed network packet processing(XDP, DPDK, eBPF, SmartNIC)
https://youtu.be/MpjlWt7fvrw?si=bnUQJmA0O3qRf3Jg
WireGuard로 VPN 서버 구축하기
아래 문서에서 다루는 내용은;
- WireGuard
- KeyCloak SSO 연동
- Kernel networking stack을 이용하여 특정 Group 접근을 제어
- VPN server에서 사용하는 인증(Authentication)
- eBPF를 이용한 패킷 필터링(Packet filtering)
- eBPF map (Key/Value store)
https://tech.devsisters.com/posts/wireguard-vpn-2/