LAN 어댑터가 프리앰블, 스타트 프레임 딜리미터 및 FCS를 부가한 후 전기 신호로 변환하면 이제 연결된 케이블에 패킷(정확히는 전기 신호)을 송신할 수 있다.
이 패킷은 허브를 향해 송신되며 허브는 받은 패킷을 다음 목적지인 라우터 혹은 수신지에 전송한다.
이 때 사용하는 허브는 "반이중 모드"를 사용하는 리피터 허브와 "전이중 모드"를 사용하는 스위칭 허브가 존재한다.
전이중이란 송신 동작과 수신 동작을 동시에 병행할 수 있는 것이고 반이중 모드는 특정 시점에서 송신과 수신 중 1개만 처리 가능한 것을 말한다.
이 중 전이중 모드를 사용하는 스위칭 허브는 최근 네트워크에서 활용하는 주류 허브로써 나중에 자세히 설명하겠다.
현 단계에선 반이중 모드에 대해서만 알아보자.
반이중 모드에서 가장 중요시 생각해야 하는 것은 특정 시점에서 송신과 수신 동작 중 한 개만 가능하다는 것이다.
패킷을 송신하기 위한 처리를 하고 있을 때 수신 패킷이 올 경우에 대비해야 한다는 의미이다.
만약 신호가 흐르고 있을 때 송신 동작을 시작하면 신호가 충돌할 것이기 때문이다.
(참고로 전이중 모드는 송신과 수신을 동시에 수행하므로 이러한 충돌에 대한 걱정은 할 필요가 없다)
반이중 모드에선 이러한 신호의 충돌을 피하기 위해 먼저 (리피터 허브에 연결된) 케이블에 다른 기기가 송신한 신호가 흐르고 있는지 조사한다.
그리고 신호가 정지했거나 흐르지 않고 있다면 패킷 송신 동작을 시작한다.
그렇다면 패킷 송신 동작에서 일어나는 일에 대해서 알아보자.
일단 디지털 데이터를 전기 신호로 변환한 뒤 PHY 혹은 MAU라는 송/수신 신호 부분에 보낸다.
이때 디지털 데이터를 신호로 변환하는 속도가 곧 전송 속도를 의미한다.
PHY(MAU) 회로는 MAC 회로에서 전달받은 신호를 케이블에 송출할 수 있는 형식으로 변환하여 송신한다.
이더넷이나 다른 네트워크 프로토콜은 케이블의 종류나 전송 속도에 따라 몇 가지 신호 형식이 규정되어 있다.
MAC 회로는 이러한 신호 형식을 신경 쓰지 않고 모든 신호 형식으로 변환할 수 있는 공통 형식의 신호로 만든 뒤 PHY(MAU) 회로에 보낸다.
이렇게 만들어진 공통 형식의 신호를 네트워크 프로토콜과 환경에 맞도록 변환시켜주는 변환 회로 역할을 하는 것이 PHY(MAU)이다.
PHY(MAU) 회로가 케이블에 신호를 송신한 이후의 동작을 알아보자.
반이중 모드의 경우 리피터 허브가 송신 개시 전 수신 신호선에 신호가 존재하는지 확인했다.
즉, 송신을 시작했다는 것은 수신 신호선에 신호가 흐르지 않았다는 의미이므로 충돌 없이 신호가 송신될 것이다.
신호 송신을 완료할 때까지 수신 신호선에 신호가 들어오지 않을 경우 케이블을 통한 패킷의 송/수신 동작은 끝이 난다.
이때 "이더넷"이라는 네트워크 프로토콜은 송신한 패킷이 정상적으로 상대에게 도착했는지는 큰 관심을 두지 않는다.
이더넷은 사양에 따라 기기와 기기 사이를 연결하는 케이블을 한정시킨다.
예를 들어 트위스트 페어 케이블을 사용할 경우 케이블 길이를 100m로 한정시킨다.
이렇게 케이블 길이를 한정시킴으로써 패킷이 전달되는 과정에서 오류가 거의 발생하지 않는다.
1만 분의 1 이하의 확률로 오류가 발생했다 하더라도 이더넷은 이를 인지하지 못하며 나중에 패킷 수신 목적지의 프로토콜 스택 TCP 담당이 이를 확인하게 된다.
반이중 모드에선 또 신경 써야 할 것이 있는데, 바로 송신과 수신 패킷이 만나 충돌하는 경우이다.
신호를 송신하고 있는 사이 수신 신호가 흘러들어오지 않도록 많은 노력을 기울이긴 하였으나 모든 일이 그렇듯 100% 상황을 피할 수는 없다.
낮은 확률이지만 동시에 복수의 기기가 송신 동작에 들어갈 가능성이 있다.
이 경우 분명 기기가 확인할 땐 수신할 패킷이 없었지만 패킷을 송신할 때는 동시에 송신 동작을 수행한 기기가 존재하므로 충돌이 발생할 수 있는 것이다.
충돌이 발생했다면 계속 패킷을 송신할 의미가 없으므로 일단 송신 동작을 중지한다.
이후 충돌이 일어났다는 사실을 다른 기기에도 알리기 위하여 재밍 신호라는 특수 신호를 잠시 동안 흘린다.
송신 동작을 멈춘 뒤 잠시 기다렸다 다시 한번 송신 동작을 시도하는데 복수의 기기가 송신 동작에 들어가 충돌이 발생한 상황에서 모든 기기의 대기 시간이 동일할 경우 다시 충돌이 발생할 것이다.
따라서 각 기기의 대기 시간이 중복되지 않도록 MAC 주소를 바탕으로 난수를 생성하는 방식으로 이미 고안되어 있다.
하지만 이렇게 대기 시간을 다르게 해도 이더넷이 혼잡할 경우(즉 통신하는 패킷이 많을 경우) 다시 충돌이 발생할 수 있다.
이 때는 대기 시간을 2배로 늘린 뒤 패킷을 다시 보낸다. 충돌이 일어날 때마다 이전 대기 시간의 2배로 대기시간을 가진 뒤 패킷을 다시 보내며 만약 열 번째까지 다시 보냈는데도 해결되지 않을 경우 네트워크 오류로 판단한다.
LAN 어댑터에서 디지털 데이터를 전기 신호로 변환한 뒤 케이블을 통해 송신까지 수행하였다.
이제는 패킷을 수신하는 동작에 대해서 알아볼 차례이다.
리피터 허브를 이용한 반이중 동작의 이더넷에서는 1대가 송신한 신호가 리피터 허브에 접속된 케이블 전부에 흘러간다.
이는 이전 LAN 어댑터의 개요에 대해 설명하며 다뤘던 이야기이다.
따라서 리피터 허브의 수신 동작은 일단 연결된 모든 케이블에서 전달되는 신호를 받는 것부터 시작한다.
신호의 맨 앞에는 프리앰블과 스타트 프레임 딜리미터가 있을 것이므로 이를 통해 빛/전기 신호를 디지털 데이터로 변환한다. 이후 패킷의 내용을 계산식에 적용한 뒤 FCS에 저장된 값과 동일한지 검사하여 패킷의 내용이 노이즈 등의 영향으로 변경되지 않았는지 확인한다.
만약 값이 동일하지 않다면 오류 패킷으로 간주하여 폐기한다.
FCS에 문제가 없다면 MAC 헤더의 수신처 MAC 주소를 확인한다.
만약 수신처 MAC 주소가 현재 기기의 MAC 주소와 동일하지 않을 경우 자신이 처리할 패킷이 아니므로 폐기 처리한다.
반대로 수신처 MAC 주소에 저장된 값이 현재 기기의 MAC 주소라면 현재 기기로 전송되어야 할 패킷이었다는 의미이다.
이 때는 패킷을 버퍼 메모리에 저장한 뒤 패킷을 수신했다는 사실을 애플리케이션측에 전달하면 패킷의 수신 동작이 끝나는 것이다.
참고로 패킷이 자신에게 오는 것인지를 검사하지 않고 전부 수신하는 경우가 있는데 이를 "무차별 모드(Promiscuous mode)"라고 한다.
패킷이 버퍼 메모리에 저장되었다면 애플리케이션 측에 패킷이 도착했다는 것을 알려야 한다.
그리고 이 동작은 "인터럽트"라는 구조를 통해 수행된다.
컴퓨터 같은 기기는 패키 송/수신 동작 이외에도 다양한 작업을 수행하고 있다.
다른 말로 하자면 LAN 어댑터 측에서 패킷을 수신했거나 패킷을 보내야 하는 상황에도 기기 측에 알려주지 않는 이상 전혀 인지하지 못한다는 것이다.
이런 상황에서 기기가 수행하고 있던 작업에 끼어들어 LAN 어댑터가 패킷을 송/수신해야 한다는 것을 알리는 것이 인터럽트이다.
먼저 LAN 어댑터는 확장 버스 슬롯 부분에 있는 인터럽트용 신호선에 신호를 보낸다.
이 신호선은 기기의 인터럽트 컨트롤러를 통해 CPU에 연결되어 있는데 만약 신호가 흘러들어올 경우 CPU는 실행하고 있던 작업을 보류하고 OS 내부의 인터럽트 처리용 프로그램으로 전환한다.
이후 LAN 드라이버가 호출되어 LAN 어댑터를 제어함으로써 패킷 송/수신 동작을 실행할 수 있는 것이다.
인터럽트에는 번호가 할당되어 있는데 하드웨어 기기를 설치할 때 번호를 설정한다.
그리고 인터럽트 처리용 프로그램은 하드웨어의 인터럽트 번호에 대응하도록 드라이버 소프트웨어를 등록하도록 되어 있다.
예를 들어 LAN 어댑터에 11이라는 인터럽트 번호가 설정되어 있고 LAN 어댑터가 인터럽트를 걸면 해당 LAN 어댑터를 관리하는 LAN 드라이버가 11번에 의해 호출되도록 설정되어 있는 것이다.
현재는 PnP(Plug and Play) 사양에 따라 하드웨어에 대한 번호가 자동으로 설정되므로 인터럽트 번호를 걱정할 필요는 없다.
이러한 인터럽트에 의하여 LAN 드라이버가 동작하고 LAN 어댑터가 버퍼 메모리에 저장했던 패킷을 추출하면 LAN 드라이버는 MAC 헤더의 이더 타입 값으로부터 프로토콜을 판별한다.
MAC 헤더의 이더 타입 값으로부터 프로토콜을 판별한 LAN 드라이버는 패킷을 처리할 수 있는 프로토콜 스택에게 이를 전달한다.
만약 이더 타입 값이 0800일 경우 LAN 드라이버는 TCP/IP의 프로토콜 스택에 패킷을 처리하라고 건네준다.
IP 담당은 일단 IP 헤더 부분을 조사하여 포맷에 문제가 없는지를 확인한다.
만약 IP 담당이 어떠한 오류를 파악했을 경우 ICMP라는 메시지를 사용하여 통신 상대에게 오류를 통지하게 되어 있다.
ICMP에는 여러 타입의 메시지가 정의되어 있으며 아래에 주요 메시지에 대하여 설명하겠다.
만약 IP 담당이 문제를 발견하지 못한다면 Fragmenatation 기능에 의해 나눠진 패킷을 다시 합치는 작업을 수행한다.
이전에 말했듯 LAN 어댑터 중 짧은 패킷만 다룰 수 있는 경우가 있기 때문에 패킷 송신 측이 아닌 중간 노드에서도 패킷을 쪼갤 수 있는데 이를 Fragmentation(조각 나누기; 단편화) 작업이라고 한다.
IP 헤더의 "플래그" 항목을 통해 수신한 패킷이 Fragmentation에 의하여 분할된 패킷인지 확인할 수 있다.
만약 분할된 패킷이라면 IP 담당은 IP 담당 내부 메모리에 패킷을 일시적으로 보관한다.
Fragmenatation에 의해 분할된 패킷은 IP 헤더의 ID 정보 값이 모두 동일하기 때문에 ID 정보가 동일한 패킷이 모두 도착하기를 기다린다.
ID 정보가 동일한 패킷이 모두 도착하여 메모리에 저장되었다면 Fragment Offset(프래그먼트 오프셋)이라는 값을 활용한다.
이 값은 분할된 패킷이 분할되기 전 패킷의 어느 위치에 저장되어 있었는지를 알려준다.
이렇게 분할된 패킷이 도착하기를 전부 기다렸다 원래 패킷으로 복원하는 작업을 "리어셈블링(Reassembling)"이라고 한다.
리어셈블링 작업까지 끝났다면 IP 담당은 TCP 담당에 패킷을 건네준다.
TCP 담당은 IP 헤더의 수신처/송신처 IP 주소와 TCP 헤더의 수신처/송신처 포트 번호를 조사하여 해당하는 소켓을 찾는다.
이 소켓에는 통신 진행 상태가 기록되어 있으므로 상황에 따라 적절한 동작을 실행한다.
이 둘은 한 세트이기 때문에 같이 설명하겠다.
ping 명령에 사용되는 메시지는 Echo로써 이 메시지를 받은 상대는 Echo reply 메시지를 돌려준다.
이 2개의 메시지를 주고 받음으로써 상대 서버가 동작하고 있는지를 확인할 수 있다.
패킷이 목적지에 도달할 수 없음을 의미하며 목적지 도달 불가에는 다양한 이유가 존재한다.
이런 다양한 이유를 Code를 통해 정리해 놓았다.
라우팅 경로가 잘못되어 새로운 경로를 이전 경유지 또는 호스트에게 알려주는 메시지이다.
ICMP Redirect 공격 시 이 메시지를 활용한다.
타임아웃이 발생하여 IP 패킷이 폐기되었음을 알리는 메시지이다.
타임아웃의 이유는 Code를 통해 알 수 있다.