요약

  • IPv4는 프래그먼트 오프셋을 여덟 옥텟 단위로 인코딩하므로, 오프셋 값 32는 해당 프래그먼트 데이터를 원본 데이터그램의 256바이트 위치에 배치합니다.
  • 압축된 좌표가 데이터그램 전체 범위에 도달할 수 있는 것은, 마지막이 아닌 모든 프래그먼트가 8로 나누어떨어지는 데이터 길이를 갖기 때문입니다.

바이트를 가리키지 않는 오프셋

프래그먼트 오프셋 필드에 32가 들어 있는 IPv4 프래그먼트를 생각해 보십시오. 이 값을 바이트 위치로 읽으면 프래그먼트가 원본 데이터그램의 거의 시작 부근에 놓이게 됩니다. 그러나 IPv4는 이 값에 8을 곱합니다. 즉, 해당 프래그먼트의 데이터는 256바이트에서 시작합니다.

이 곱셈은 나중에 필드 위에 얹힌 관행이 아닙니다. RFC 791은 13비트 오프셋을 여덟 옥텟 단위로 정의합니다. 수신 측은 디코딩된 시작 위치와 프래그먼트의 데이터 길이를 결합하여 원본 데이터그램의 어느 구간이 도착했는지를 판단합니다.

이 선택은 헤더의 세 부분을 연결합니다. 총 길이(Total Length)는 16비트로 약 65,536옥텟에 이르는 데이터그램을 표현할 수 있습니다. 프래그먼트 오프셋은 13비트뿐이므로 8192개의 서로 다른 값을 가집니다. 값당 여덟 옥텟을 적용하면 이 좌표 척도가 65,536옥텟으로 확장됩니다. 필드는 하위 3비트를 암묵적으로 두는 방식으로 필요한 크기에 도달합니다.

3비트를 절약하면 경계 규칙이 생긴다

암묵적인 8의 배수는 여덟 옥텟 경계에 정렬된 시작 위치만 표현할 수 있습니다. 따라서 IPv4 단편화는 뒤따르는 프래그먼트를 임의의 바이트에 배치할 수 없습니다. 데이터그램을 분할할 때 앞쪽 부분은 8의 배수인 데이터 옥텟을 담아야 합니다.

마지막 부분은 다릅니다. 다른 프래그먼트를 위한 표현 가능한 시작 위치를 만들 필요가 없으므로, 마지막 부분의 데이터 길이는 8의 배수가 아니어도 됩니다. 이것이 바로 정확한 규칙이 “모든 프래그먼트가 8의 배수여야 한다”가 아닌 이유입니다. MF(More Fragments) 비트가 설정된 모든 프래그먼트는 이 경계를 충족해야 하고, 마지막 프래그먼트는 남은 데이터를 그대로 사용할 수 있습니다.

헤더는 이 계산에 영향을 주지 않습니다. 프래그먼트 오프셋은 각 프래그먼트의 IPv4 헤더 시작점이 아니라 원본 데이터 영역을 기준으로 프래그먼트 데이터의 위치를 지정합니다. 각 프래그먼트는 자신의 헤더를 가지며, 총 길이는 그 헤더와 프래그먼트 데이터를 함께 계산합니다. 여덟 옥텟 제약은 다음 오프셋을 결정하는 데 쓰이는 데이터 부분에 적용됩니다.

큰 데이터그램을 가로지르는 압축 좌표

산술적 계산이 설계 의도를 설명해 줍니다. 16비트 길이 공간 전체를 커버하는 바이트 단위 오프셋은 그 자체로 약 16비트가 필요합니다. IPv4는 플래그(Flags)가 같은 16비트 워드를 공유하기 때문에 13비트만 할당했습니다. 8의 배수만 표현함으로써, 오프셋은 디코딩 시 사실상 하위 3개의 0을 복원합니다.

이것은 일상적 의미의 압축이라기보다 표현상의 절충입니다. 전송되는 데이터에는 생략된 0이 담기지 않지만, 송신자는 그 0들이 정확하도록 프래그먼트를 배치해야 합니다. 수신자는 필드에 8을 곱해 바이트 좌표를 되찾습니다.

이 형식은 IPv4의 최소 전달 요구와도 맞닿아 있습니다. RFC 791은 최대 60옥텟 헤더와 최소 여덟 옥텟 프래그먼트를 합쳐 68옥텟 데이터그램이 되면, 모든 인터넷 모듈이 이를 추가 단편화 없이 전달할 수 있어야 한다고 명시합니다.

오프셋과 MF 비트는 서로 다른 근거를 전달한다

프래그먼트 오프셋은 해당 프래그먼트가 어디서 시작하는지를 말합니다. 그것이 마지막 프래그먼트인지는 알려 주지 않습니다. 그 사실은 MF 플래그가 제공합니다. MF=1은 뒤에 더 많은 프래그먼트 데이터가 따름을 뜻하고, MF=0은 마지막 프래그먼트임을 표시합니다.

단편화되지 않은 데이터그램은 오프셋이 0이고 MF도 0입니다. 첫 번째 프래그먼트 역시 오프셋이 0이지만, 뒤에 데이터가 더 남아 있으므로 MF가 설정됩니다. 중간 프래그먼트는 0이 아닌 오프셋과 설정된 MF를 가집니다. 마지막 프래그먼트는 0이 아닌 오프셋을 가지면서 MF가 해제될 수 있습니다.

이러한 조합 덕분에 수신자는 하나의 필드만으로 지나치게 많은 것을 추론할 수 없습니다. 오프셋이 0이라고 해서 데이터그램이 단편화된 적이 없다고 증명되지 않으며, MF가 0이라고 해서 현재 프래그먼트가 0에서 시작한다고 증명되지 않습니다. 재조립에는 위치와 종료에 대한 근거가 모두 필요하고, 한 데이터그램의 프래그먼트를 다른 데이터그램의 프래그먼트와 구별하는 식별자(Identification)와 다른 튜플 필드도 함께 필요합니다.

재조립은 단위를 다시 구간으로 되돌린다

RFC 815는 재조립을 바이트 범위와 비어 있는 “구멍(hole)”의 개념으로 설명합니다. 부분적으로 조립된 데이터그램에는 이미 수신된 구간과 아직 없는 구간이 함께 있습니다. 도착하는 각 프래그먼트는 첫 바이트와 마지막 바이트를 가지며, 이 경계는 구멍을 완전히 채우거나 한쪽을 잘라내거나 두 개의 더 작은 구멍으로 나눌 수 있습니다.

프래그먼트 오프셋은 8을 곱한 값으로 첫 바이트를 제공합니다. 프래그먼트 데이터 길이는 마지막으로 덮인 바이트를 제공합니다. MF가 해제되어 있으면 수신자는 원본 데이터의 최종 범위도 알게 됩니다. 이 범위 안에 구멍이 더 이상 없으면 재조립이 완료됩니다.

이 구간 관점은 오프셋이 제공하지 않는 것을 명확히 합니다. 오프셋은 프래그먼트의 서수 위치를 열거하지 않고, 프래그먼트가 순서대로 도착한다고 약속하지 않으며, 덮인 바이트가 새로운 것이라고 선언하지도 않습니다. 중복 및 겹치는 프래그먼트는 이미 존재하는 구간을 다시 가리킬 수 있습니다. 좌표는 배치를 가능하게 할 뿐, 모든 재조립 정책을 결정하지는 않습니다.

재단편화도 같은 좌표계를 유지한다

IPv4는 정책과 헤더 상태가 허용하면 프래그먼트를 다시 단편화할 수 있습니다. 새 조각들은 별도의 로컬 번호 체계를 시작하지 않습니다. 그 오프셋은 여전히 단편화되지 않은 원본 데이터그램의 시작을 기준으로 합니다.

RFC 791의 단편화 절차는 기존 프래그먼트 오프셋에 새로 만들어진 뒤쪽 조각 앞에 놓인 여덟 옥텟 블록 수를 더합니다. 앞선 분할 자체가 여덟 옥텟 경계에서 이루어지므로, 그 결과는 같은 13비트 단위로 표현 가능한 상태를 유지합니다.

이 조합 가능성은 운영상 중요합니다. 여러 라우터가 트래픽을 분할하더라도 수신지가 단편화 이벤트의 트리를 재구성할 필요가 없습니다. 모든 조각은 하나의 공통된 원본 데이터 공간 안에서의 좌표와 함께 도착합니다.

파서가 의존하는 규칙이기에 유지되는 제약

여덟 옥텟 규칙은 비트 예산과 재조립 계산을 함께 고려하기 전까지는 임의적인 역사적 제한처럼 보일 수 있습니다. 이 규칙 덕분에 13비트 필드가 16비트 길이가 암시하는 크기를 커버할 수 있습니다. 그 대가로, 단편화 수행자는 정렬된 경계를 선택함으로써 사라진 하위 3비트를 보존해야 합니다.

이 설계는 손실, 중복, 겹침, 악의적인 프래그먼트를 막지 못합니다. 애플리케이션이 8바이트 레코드 단위로 동작한다고 말하지도 않습니다. 이 설계는 제약된 헤더 형식 아래에서 공유 좌표계를 제공할 뿐입니다.

오래 지속되는 교훈은 이것입니다. 압축된 전송 표현은 복잡성을 제거하는 것이 아니라 옮긴다는 점입니다. IPv4는 모든 헤더에서 오프셋 3비트를 절약했고, 송신자는 단편화 경계 규칙을, 수신자는 재조립 맵을 갱신하기 전에 바이트 좌표를 복원하는 비용을 치렀습니다.

출처