개요
IP 패킷 크기가 링크 MTU보다 클 경우 패킷을 한번에 보낼 수 없기 때문에 IP 단편화가 발생하게 된다.
원본 패킷 [IP헤더|데이터] (3020바이트)
↓ MTU 1500바이트로 제한
조각1: [IP헤더|데이터1] (1500바이트)
조각2: [IP헤더|데이터2] (1500바이트)
조각3: [IP헤더|데이터3] (60바이트)
원본 패킷: 3000 바이트 데이터 + 20 바이트 IP 헤더 = 3020 바이트
MTU: 1500 바이트
조각 1: IP헤더(20) + 데이터(1480) = 1500 바이트
- MF=1, Offset=0
조각 2: IP헤더(20) + 데이터(1480) = 1500 바이트
- MF=1, Offset=185 (1480/8)
조각 3: IP헤더(20) + 데이터(40) = 60 바이트
- MF=0, Offset=370 (2960/8)
위와 같이 MTU가 1500 바이트일 경우 패킷의 크기가 3020바이트라면 3조각으로 나누어 진다.
단, TCP기준으로 IP헤더는 20바이트를 가지므로 매 조각마다 IP헤더가 추가되어 총 패킷의 크기는 3060바이트가 된다.
단편화 발생 조건
IP 패킷 크기가 링크 MTU보다 클 경우 패킷을 한번에 보낼 수 없기 때문에 IP 단편화가 발생하게 된다.
이는 라우터에서 자동으로 수행하며 DF(Don't Fragment) 플래그가 0일 경우 발생하게 된다.
if (패킷_크기 > 링크_MTU && DF_플래그 == 0) {
// 단편화 수행
단편화_수행();
} else if (패킷_크기 > 링크_MTU && DF_플래그 == 1) {
// ICMP 에러 전송
전송_ICMP_에러();
}
만약 패킷 크기가 MTU 이하이거나 DF 플래그가 1로 설정된 경우 ICMP 에러를 반환하므로 단편화가 발생하지 않는다.
IP 헤더의 단편화 관련 필드
┌─────────────────────────────────────┐
│ Identification (16bit) │ ← 같은 원본 패킷 식별
├─────────────────────────────────────┤
│ Flags (3bit) │ Fragment Offset (13bit) │
│ [R][DF][MF] │ │
└─────────────────────────────────────┘
- DF (Don't Fragment): 단편화 금지
- MF (More Fragments): 더 많은 조각 있음
- Fragment Offset: 조각의 위치 (8바이트 단위)
1. Identification 필드
- 같은 원본 패킷의 모든 조각에 동일한 값
- 수신자가 조각들을 그룹화하는데 사용
- 16비트로 65536개의 동시 패킷 식별 가능
2. Flags 필드
- Reserved(R): 항상 0
- Don't Fragment(DF): 단편화 금지 지시
- More Fragments(MF): 뒤에 더 많은 조각이 있음을 표시
3. Fragment Offset 필드
- 원본 데이터에서 해당 조각의 시작 위치
- 8바이트 단위로 표현 (13비트 × 8 = 최대 65528바이트)
- 마지막 조각은 MF=0, 나머지는 MF=1
단편화 규칙과 제약
1. 8바이트 경계 규칙
- 마지막 조각을 제외한 모든 조각은 8바이트의 배수여야 함
- Fragment Offset이 8바이트 단위로 표현되기 때문
- 이 규칙을 위반하면 패킷이 버려질 수 있음
2. 최소 조각 크기
- IPv4: 최소 68바이트 (IP헤더 60바이트 + 데이터 8바이트)
- 실제로는 더 큰 크기가 효율적
- 너무 작은 조각은 오버헤드가 과도하게 증가
재조립 (Reassembly) 이론
1. 수신자에서의 처리
- Identification 필드로 같은 패킷의 조각들을 식별
- Fragment Offset으로 조각들의 순서 결정
- MF 플래그로 마지막 조각 확인
- 모든 조각이 도착하면 원본 패킷 재구성
2. 재조립 버퍼 관리
- 불완전한 패킷들을 임시 저장
- 타임아웃 메커니즘으로 메모리 보호
- IPv4는 최소 15초, IPv6는 60초 대기
3. 재조립 실패 조건
- 조각 중 하나라도 손실
- 재조립 타임아웃 발생
- 버퍼 공간 부족
- 조각 순서나 크기의 불일치
단편화의 성능 영향 분석
1. 처리 오버헤드
단편화 비용:
- CPU: 패킷 분할 연산
- 메모리: 추가 헤더 공간
- 네트워크: 헤더 오버헤드 증가
재조립 비용:
- CPU: 조각 순서 정렬, 버퍼 관리
- 메모리: 불완전한 패킷 버퍼링
- 타이머: 타임아웃 관리
2. 지연 시간 증가
정상 전송: RTT
단편화 전송: RTT + 재조립_대기시간 + 재전송_지연
3. 패킷 손실 위험성
원본 패킷 손실률 = 1 - (1 - 단일조각손실률)^조각수
예시:
- 단일 조각 손실률: 1%
- 3개 조각으로 분할
- 전체 패킷 손실률: 1 - (0.99)³ = 2.97%
리스크
1. 실시간성 저하
// 문제 상황
struct GamePacket {
uint32_t sequence;
uint32_t timestamp;
PlayerAction actions[50]; // 큰 패킷!
};
// 1400바이트 패킷 → 단편화 발생
// 조각 하나라도 손실되면 전체 패킷 폐기
2. 대역폭 낭비
원본 데이터: 1400 바이트
단편화 후:
- 조각1: IP헤더(20) + UDP헤더(8) + 데이터(1472) = 1500
- 조각2: IP헤더(20) + 데이터(928) = 948
총 오버헤드: 40바이트 → 60바이트 (50% 증가)
3. 버퍼 오버플로우
// 재조립 버퍼 관리
class FragmentManager {
private:
std::unordered_map<uint16_t, FragmentBuffer> buffers;
static const size_t MAX_BUFFERS = 1000;
public:
void cleanup_expired_fragments() {
auto now = std::chrono::steady_clock::now();
for (auto it = buffers.begin(); it != buffers.end();) {
if (now - it->second.timestamp > std::chrono::seconds(30)) {
it = buffers.erase(it); // 타임아웃된 조각 제거
} else {
++it;
}
}
}
};
최적화 전략
1. 패킷 크기 제한
class GamePacketManager {
private:
static const size_t SAFE_PACKET_SIZE = 1200; // 안전한 크기
public:
void send_game_state(const GameState& state) {
if (state.serialized_size() > SAFE_PACKET_SIZE) {
// 여러 패킷으로 분할 전송
split_and_send(state);
} else {
send_single_packet(state);
}
}
};
2. 적응형 MTU 설정
class AdaptiveMTU {
private:
size_t current_mtu = 1500;
size_t min_mtu = 576;
public:
void handle_fragmentation_needed(size_t suggested_mtu) {
current_mtu = std::max(min_mtu, suggested_mtu - 50); // 여유분
log_info("MTU adjusted to: " + std::to_string(current_mtu));
}
size_t get_safe_payload_size() {
return current_mtu - 20 - 8; // IP헤더 - UDP헤더
}
};
3. 압축과 델타 인코딩
// 패킷 크기 최소화
struct CompressedGameState {
uint32_t base_sequence;
std::vector<uint8_t> delta_data; // 압축된 변경사항만
size_t serialize(uint8_t* buffer) {
// zlib 압축 적용
return compress_data(delta_data, buffer);
}
};
4. QoS 기반 패킷 분류
enum PacketPriority {
CRITICAL = 0, // 작은 패킷, 단편화 방지
NORMAL = 1, // 중간 크기 허용
BULK = 2 // 큰 패킷, 단편화 허용
};
void send_packet(const void* data, size_t size, PacketPriority priority) {
if (priority == CRITICAL && size > SAFE_SIZE) {
// 중요한 패킷은 분할 전송
send_fragmented_application_layer(data, size);
} else {
send_normal(data, size);
}
}
결론
- MTU는 네트워크에서 한 번에 전송할 수 있는 최대 패킷 크기이다.
- MTU보다 큰 패킷이 송신되어야 할 경우, DF값이 0일 경우 IP 단편화가 발생하게 된다.
- 단편화된 조각을 수신자가 받아 재조립 과정을 거쳐야 한다.
- IP 단편화로 인한 조각이 많아질 수록 패킷 손실 위험성이 커진다.
- 재조립 과정에서 하나의 조각이라도 손실되면 전체 패킷을 재전송해야한다.
- 실시간이 중요한 서비스에서 이는 CPU 오버헤드가 발생한다. 즉 서비스 품질 저하로 직결된다.
- 패킷 크기 제한, 압축과 델타 인코딩 등을 통해 최적화 전략을 수립해야 한다.
728x90
'컴퓨터 과학(CS) > 네트워크' 카테고리의 다른 글
[네트워크] 캐스팅 방식 (0) | 2025.07.06 |
---|---|
[네트워크] 시리얼 통신, RS-232, RS-485 (0) | 2025.07.05 |
[네트워크] MTU(Maximum Transmission Unit) (0) | 2025.06.06 |
[네트워크] RTT(Round Trip Time) (0) | 2025.06.06 |
네트워크 병렬 서버 로드 밸런싱 - DNS, Anycast (1) | 2024.11.26 |