XDP 기술을 사용 및 이해하기 위해서는 이더넷 프레임과 패킷의 구조를 알고 있어야 한다. 이에 대한 간략한 정보를 정리하겠다.
이더넷은 데이터 링크 계층에서 사용되는 프로토콜이고 패킷은 네트워크 계층에서 사용되는 프로토콜이다. XDP에서 패킷처리를 하기 위해서는 이더넷과 패킷이 어떤 구조로 되어 있는가를 알고 있어야 한다.
계층 | Layer 2 (데이터 링크 계층) | Layer 3 (네트워크 계층) |
목적 | 물리적 장비 간 전송 (MAC 주소 기반) | 네트워크 간 라우팅 (IP 주소 기반) |
전송 단위 | 프레임 (Frame) | 패킷 (Packet) |
내용물 | 패킷(IP)을 감쌈 | 실제 데이터 (TCP/UDP 세그먼트) |
예시 | 이더넷, Wi-Fi 등 | IPv4, IPv6 |
이더넷
이더넷 프레임 구조
| Ethernet Header (14B) | Payload (46~1500B) | Ethernet CRC (4B) |
이더넷 헤더의 바이트 오프셋필드 이름길이설명
#if __UAPI_DEF_ETHHDR
struct ethhdr {
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
__be16 h_proto; /* packet type ID field */
} __attribute__((packed));
#endif
필드 | 필드크기 | Byte | 설명 |
h_dest | 0~5 | 6 | 목적지 MAC |
h_source | 6~11 | 6 | 출발지 MAC |
h_proto | 12~13 | 2 | 프로토콜 식별자 |
IP 패킷 (L3 - 네트워크 레이터)
IP 패킷 구조
| IP Header (20B) | Payload (TCP/UDP/ICMP 등) |
패킷 헤더
#include <linux/ip.h>
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u8 version:4,
ihl:4;
#else
#error "Please fix <asm/byteorder.h>"
#endif
__u8 tos;
__be16 tot_len;
__be16 id;
__be16 frag_off;
__u8 ttl;
__u8 protocol;
__sum16 check;
__be32 saddr;
__be32 daddr;
/* The options start here (if ihl > 5) */
};
필드크기 (비트)설명
필드 | Bit | 설명 |
Version | 4 | IP 버전 (IPv4 = 4) |
IHL | 4 | 헤더 길이 |
Type of Service | 8 | QoS 관련 |
Total Length | 16 | 전체 패킷 길이 |
Identification | 16 | 분할 재조합용 ID |
Flags | 3 | 분할 관련 제어 비트 |
Fragment Offset | 13 | 분할 위치 정보 |
TTL | 8 | 생존 시간 |
Protocol | 8 | 상위 프로토콜 (TCP=6, UDP=17 등) |
Header Checksum | 16 | 오류 검출 |
Source IP | 32 | 출발지 IP 주소 |
Destination IP | 32 | 목적지 IP 주소 |
패킷 구조 종합
[ Ethernet Frame ]
└── Ethernet Header (14B)
└── [ IP Packet ]
└── IP Header (20B)
└── [ TCP Segment ]
└── TCP Header (20B)
└── Application Data (ex: HTTP)
XDP 구조체
eBPF의 XDP (eXpress Data Path) 프로그램에서 사용되는 메타데이터 구조체
struct xdp_md {
__u32 data;
__u32 data_end;
__u32 data_meta;
__u32 ingress_ifindex;
__u32 rx_queue_index;
__u32 egress_ifindex;
};
필드명의미
data | 패킷 시작 주소 오프셋 |
data_end | 패킷 끝 주소 오프셋 |
data_meta | 메타데이터 시작 지점 (사용자 정의용) |
ingress_ifindex | 들어온 NIC 인터페이스 index |
rx_queue_index | NIC의 수신 큐 번호 |
egress_ifindex | 나가는 인터페이스 index (옵션) |