이더넷 (Ethernet)
1973년 Xerox PARC에서 탄생한 이더넷은 반세기가 넘는 진화를 거쳐 10 Mbps 동축 케이블 버스에서 800 Gbps 광 링크까지 확장되었습니다. 이 문서는 이더넷의 역사, 물리 계층(PHY), 프레임 구조, 리눅스 커널 구현, 오프로드 기술, 에너지 효율, 산업용 이더넷까지 다양한 시각에서 종합적으로 다룹니다.
핵심 요약
- 프레임 (Frame) — 이더넷의 전송 단위. 목적지/출발지 MAC, EtherType, 페이로드, FCS로 구성되며 64~1518바이트 크기
- MAC 주소 — 48비트(6바이트) 하드웨어 주소로, NIC마다 고유하게 할당되어 L2에서 장치를 식별
- PHY / MAC — PHY는 전기/광 신호 변환을 담당하는 물리 계층 칩, MAC은 프레임 조립/해석을 담당하는 계층. RGMII 등의 인터페이스로 연결
- ethtool — 리눅스에서 NIC 속도, 오프로드, 링 버퍼, EEE 등을 조회하고 설정하는 핵심 유틸리티
- 오프로드 (Offload) — TSO, GRO, RSS 등 CPU 부담을 NIC 하드웨어로 넘기는 기술. 고성능 네트워크의 핵심
단계별 이해
- 프레임 구조부터 파악하기
이더넷의 기본은 프레임입니다. Preamble → MAC 주소 → EtherType → Payload → FCS 순서를 먼저 이해하세요.EtherType ≥ 0x0600이면 Ethernet II, 그보다 작으면 802.3 프레임입니다. - PHY-MAC 연결 이해하기
NIC 내부에서 MAC 계층이 프레임을 처리하고, PHY 칩이 실제 전기/광 신호로 변환합니다.ethtool eth0으로 현재 링크 속도와 PHY 상태를 확인할 수 있습니다. - 커널 수신 경로 따라가기
케이블 → NIC DMA → IRQ →napi_schedule()→ NAPI poll →eth_type_trans()→netif_receive_skb()순서로 프레임이 커널에 전달됩니다. 이 흐름이 이더넷 드라이버의 핵심입니다. - 오프로드와 성능 튜닝 적용하기
ethtool -k eth0로 현재 오프로드 상태를 확인하고,ethtool -G eth0 rx 4096으로 링 버퍼를 조정하며,ethtool -C eth0 adaptive-rx on으로 인터럽트 병합을 최적화합니다.
개요
이더넷(Ethernet)은 IEEE 802.3 표준으로 규정된 유선 LAN 기술로, 전 세계 네트워크 인프라의 핵심입니다. 원래 공유 매체(Shared Medium) 기반 CSMA/CD 프로토콜이었지만, 스위칭 기술과 전이중(Full-Duplex) 통신의 도입으로 현대 이더넷은 충돌 없는 점대점(Point-to-Point) 링크가 되었습니다.
- 프레임 기반 — 가변 길이(64~1518바이트, Jumbo Frame 시 ~9000바이트) 프레임 전송
- MAC 주소 — 48비트 EUI-48 하드웨어 주소로 장치 식별
- 속도 진화 — 10M → 100M → 1G → 10G → 25G → 40G → 100G → 200G → 400G → 800G
- 물리 계층 독립 — 동축, UTP, 광섬유, 백플레인 등 다양한 매체 지원
- 리눅스 커널 —
struct ethhdr,eth_type_trans(),ethtool_ops, phylink 프레임워크로 구현
역사와 진화
이더넷의 발전 과정은 컴퓨터 네트워킹 역사 그 자체입니다.
| 연도 | 표준/기술 | 속도 | 매체 | 의의 |
|---|---|---|---|---|
| 1973 | Xerox Ethernet (실험) | 2.94 Mbps | 동축 케이블 | Robert Metcalfe, Xerox PARC에서 최초 구현 |
| 1980 | DIX Ethernet (v1.0) | 10 Mbps | 동축 (Thick) | DEC-Intel-Xerox 공동 표준, EtherType 필드 도입 |
| 1983 | IEEE 802.3 (10BASE5) | 10 Mbps | Thick 동축 | 첫 IEEE 표준화, CSMA/CD 공식 규정 |
| 1985 | 10BASE2 (Thin Ethernet) | 10 Mbps | Thin 동축 (RG-58) | 저비용 동축, 185m 세그먼트 |
| 1990 | 10BASE-T | 10 Mbps | UTP Cat3 | 트위스트 페어 혁명, 스타 토폴로지 전환 |
| 1995 | 802.3u (Fast Ethernet) | 100 Mbps | UTP Cat5 / 광 | 100BASE-TX, Auto-Negotiation 도입 |
| 1998 | 802.3z (Gigabit Ethernet) | 1 Gbps | 광섬유 | 1000BASE-SX/LX, 8B/10B 부호화 |
| 1999 | 802.3ab | 1 Gbps | UTP Cat5e | 1000BASE-T, PAM-5 4쌍 전송 |
| 2002 | 802.3ae (10GbE) | 10 Gbps | 광섬유 | CSMA/CD 사실상 폐기, 전이중 전용 |
| 2006 | 802.3an (10GBASE-T) | 10 Gbps | UTP Cat6a | 구리선 10G, LDPC 부호화 |
| 2010 | 802.3ba | 40/100 Gbps | 광섬유 | 다중 레인(4×10G, 10×10G, 4×25G) |
| 2016 | 802.3by (25GbE) | 25 Gbps | SFP28 | 서버 연결 최적 대역폭 |
| 2017 | 802.3bs | 200/400 Gbps | 광섬유 | PAM4 변조, 데이터센터 스파인 |
| 2024 | 802.3df | 800 Gbps/1.6 Tbps | 광섬유 | AI 클러스터, 100G 레인 기술 |
CSMA/CD와 충돌 도메인
초기 이더넷의 핵심 프로토콜인 CSMA/CD(Carrier Sense Multiple Access / Collision Detection)는 공유 매체에서의 다중 접근 문제를 해결합니다.
알고리즘 단계
- Carrier Sense — 전송 전 매체가 유휴 상태인지 확인
- Transmit — 유휴 시 프레임 전송 시작
- Collision Detection — 전송 중 충돌 감지 시 jam 신호(32비트) 발송
- Backoff — Binary Exponential Backoff 알고리즘으로 재전송 지연
- n번째 충돌 시: 0 ~ 2min(n,10)-1 슬롯 중 랜덤 선택
- 슬롯 시간: 10 Mbps에서 51.2 μs (512 bit times)
- 16번 충돌 시 전송 포기
random(0, 2^min(n,10) - 1) x 슬롯시간입니다. 예를 들어 3번째 충돌이면 0~7 슬롯(0~358.4 us @10Mbps) 중 랜덤 선택합니다. 지수를 min(n,10)으로 제한하는 이유는 2^16 = 65,536 슬롯(약 3.35초)이면 대기 시간이 과도하기 때문입니다. n=10에서 최대 1,023 슬롯(약 52.4ms)으로 캡됩니다.
ethtool에서도 duplex 설정을 확인할 수 있습니다.
충돌 도메인 vs 브로드캐스트 도메인
| 구분 | 충돌 도메인 | 브로드캐스트 도메인 |
|---|---|---|
| 정의 | 동시 전송 시 충돌이 발생하는 범위 | 브로드캐스트 프레임이 도달하는 범위 |
| 분리 장비 | 스위치, 브릿지 (포트별 분리) | 라우터, VLAN |
| 허브 | 모든 포트가 하나의 충돌 도메인 | 모든 포트가 하나의 브로드캐스트 도메인 |
| 스위치 | 포트별 독립 충돌 도메인 | 전체가 하나의 브로드캐스트 도메인 |
프레임 구조
이더넷 프레임은 여러 변형이 존재합니다. 가장 널리 사용되는 Ethernet II(DIX)와 IEEE 802.3 프레임을 비교합니다.
주요 EtherType 값
| EtherType | 프로토콜 | 커널 상수 |
|---|---|---|
| 0x0800 | IPv4 | ETH_P_IP |
| 0x0806 | ARP | ETH_P_ARP |
| 0x8100 | 802.1Q VLAN | ETH_P_8021Q |
| 0x86DD | IPv6 | ETH_P_IPV6 |
| 0x8847 | MPLS Unicast | ETH_P_MPLS_UC |
| 0x88A8 | 802.1ad (QinQ) | ETH_P_8021AD |
| 0x88CC | LLDP | ETH_P_LLDP |
| 0x88F7 | PTP (IEEE 1588) | ETH_P_1588 |
| 0x8906 | FCoE | ETH_P_FCOE |
Jumbo Frames
표준 이더넷 MTU(1500바이트)를 넘는 Jumbo Frame(최대 9000바이트)은 데이터센터 환경에서 처리량을 높이고 CPU 오버헤드를 줄입니다.
# MTU 변경
ip link set eth0 mtu 9000
# 확인
ip -d link show eth0 | grep mtu
# 경로 MTU 확인
tracepath -n 192.168.1.1
물리 계층 (PHY)
이더넷 PHY는 MAC이 만든 디지털 데이터를 실제 전기·광 신호로 변환하고, 링크 속도·듀플렉스·pause를 협상하며, 선로 상태를 감시하는 계층입니다. 이 문서에서는 PHY를 요약만 다루고, MDIO/Clause 22·45, phylib/phylink, Device Tree, 보드 지연 보상, 실전 장애 대응은 이더넷 PHY (Physical Layer) 전용 문서로 분리했습니다.
phy-mode 설계, phylib/phylink 수명주기, 링크 디버깅을 깊게 다룹니다.
| 구성 | 요약 역할 | 대표 이슈 |
|---|---|---|
| MAC | 프레임, DMA, 큐, 통계 처리 | TX timeout, queue hang |
| PHY | 부호화, 직렬화, 링크 협상, 신호 송수신 | 링크 불안정, CRC 증가 |
| MDIO | PHY 레지스터 관리 버스 | PHY ID 불일치, 설정 읽기 실패 |
| 매체 | 케이블, 모듈, magnetics, 상대편 포트 | 거리 민감, 속도 강등 |
rgmii-id 설정과 보드 지연을 동시에 쓰면 CRC 오류와 간헐적 링크 다운이 흔하게 발생합니다.
Auto-Negotiation
Auto-Negotiation은 양쪽 PHY가 지원 속도, 듀플렉스, pause 같은 능력을 교환해 최종 링크 모드를 결정하는 절차입니다. 구리 PHY는 주로 Clause 28 FLP, SerDes 기반 연결은 Clause 37/73 in-band status를 사용합니다.
- 링크 업과 링크 품질은 별개입니다. 링크가 올라와도 pause나 duplex가 잘못 합의되면 처리량과 오류율이 나빠질 수 있습니다.
- 한쪽만
autoneg off로 강제하면 상대편이 평행 감지로 링크를 올리면서 duplex를 다르게 해석할 수 있습니다. - 멀티기가비트 포트가 1G로만 붙으면 케이블 품질과 advertisement mask를 먼저 확인하세요.
# 현재 링크 협상 결과
ethtool eth0
# 자동 협상 끄고 강제 설정
ethtool -s eth0 speed 1000 duplex full autoneg off
# 상세 PHY 문서 참고: Clause 28/37/73, advertisement, EEE, 트러블슈팅
phylink 프레임워크
phylink는 MAC, PHY, PCS, SFP 모듈, fixed-link를 하나의 정책 계층으로 묶어 주는 프레임워크입니다. 외부 PHY 하나만 단순 연결하는 경우보다, SFP 핫플러그, SerDes 모드 전환, in-band status가 필요한 현대 NIC/SoC에서 특히 중요합니다.
- phylib는 PHY 장치를 공통 인터페이스로 다루는 계층입니다.
- phylink는 그 위에서 MAC 콜백과 링크 정책을 통합합니다.
- 상세 API와 상태 머신은 이더넷 PHY (Physical Layer)와 Network Device 드라이버 문서를 함께 보면 흐름이 연결됩니다.
/* include/linux/phylink.h */
struct phylink_mac_ops {
void (*mac_config)(...);
void (*mac_link_down)(...);
void (*mac_link_up)(...);
};
커널 자료구조
리눅스 커널에서 이더넷 프레임을 처리하는 핵심 자료구조입니다.
struct ethhdr
/* include/uapi/linux/if_ether.h */
struct ethhdr {
unsigned char h_dest[ETH_ALEN]; /* 목적지 MAC (6 bytes) */
unsigned char h_source[ETH_ALEN]; /* 출발지 MAC (6 bytes) */
__be16 h_proto; /* EtherType 또는 Length */
} __attribute__((packed));
/* 주요 상수 */
#define ETH_ALEN 6 /* MAC 주소 길이 */
#define ETH_HLEN 14 /* 이더넷 헤더 길이 */
#define ETH_ZLEN 60 /* 최소 프레임 (FCS 제외) */
#define ETH_DATA_LEN 1500 /* 최대 페이로드 */
#define ETH_FRAME_LEN 1514 /* 최대 프레임 (FCS 제외) */
#define ETH_FCS_LEN 4 /* FCS 길이 */
eth_type_trans() 프로토콜 판별
/* net/ethernet/eth.c */
__be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
{
struct ethhdr *eth;
skb->dev = dev;
skb_reset_mac_header(skb); /* MAC 헤더 위치 기록 */
eth = (struct ethhdr *)skb->data;
skb_pull_inline(skb, ETH_HLEN); /* data 포인터를 페이로드로 이동 */
/* 수신 패킷 유형 분류 */
if (unlikely(is_multicast_ether_addr(eth->h_dest))) {
if (ether_addr_equal_64bits(eth->h_dest, dev->broadcast))
skb->pkt_type = PACKET_BROADCAST;
else
skb->pkt_type = PACKET_MULTICAST;
} else if (unlikely(!ether_addr_equal_64bits(eth->h_dest, dev->dev_addr)))
skb->pkt_type = PACKET_OTHERHOST;
/* EtherType vs Length 판별 */
if (likely(ntohs(eth->h_proto) >= ETH_P_802_3_MIN))
return eth->h_proto; /* Ethernet II: EtherType 그대로 */
/* 802.3 프레임: LLC/SNAP 확인 후 프로토콜 결정 */
...
}
ethtool_ops 구조체
NIC 드라이버가 구현하는 ethtool_ops는 ethtool 유틸리티의 백엔드입니다.
/* include/linux/ethtool.h (주요 콜백) */
struct ethtool_ops {
void (*get_drvinfo)(...); /* 드라이버 정보 */
int (*get_link_ksettings)(...); /* 링크 속도/듀플렉스 조회 */
int (*set_link_ksettings)(...); /* 링크 설정 변경 */
void (*get_ethtool_stats)(...); /* NIC 통계 */
void (*get_strings)(...); /* 통계 이름 문자열 */
int (*get_sset_count)(...); /* 통계 세트 크기 */
u32 (*get_link)(...); /* 링크 상태 */
int (*get_coalesce)(...); /* 인터럽트 병합 설정 */
int (*set_coalesce)(...); /* 인터럽트 병합 변경 */
void (*get_ringparam)(...); /* 링 버퍼 크기 */
int (*set_ringparam)(...); /* 링 버퍼 변경 */
int (*get_rxnfc)(...); /* RSS/ntuple 규칙 */
int (*get_ts_info)(...); /* 타임스탬프 능력 */
int (*get_eee)(...); /* EEE 설정 조회 */
int (*set_eee)(...); /* EEE 설정 변경 */
};
패킷 송수신 경로
이더넷 프레임이 커널에서 처리되는 핵심 경로입니다.
하드웨어 오프로드
현대 NIC은 CPU 부담을 줄이기 위해 다양한 하드웨어 오프로드를 지원합니다.
오프로드 유형
| 오프로드 | 방향 | 기능 | ethtool 기능명 |
|---|---|---|---|
| TX Checksum | 송신 | IP/TCP/UDP 체크섬을 NIC에서 계산 | tx-checksum-ipv4 |
| RX Checksum | 수신 | 수신 패킷 체크섬 HW 검증 | rx-checksum |
| TSO (TCP Segmentation Offload) | 송신 | 대형 TCP 세그먼트를 NIC에서 분할 | tx-tcp-segmentation |
| GSO (Generic Segmentation Offload) | 송신 | SW 폴백 세그멘테이션 | tx-generic-segmentation |
| GRO (Generic Receive Offload) | 수신 | 소형 패킷을 대형으로 병합 | rx-gro |
| LRO (Large Receive Offload) | 수신 | HW에서 대형 세그먼트 조합 (deprecated) | rx-lro |
| RSS (Receive Side Scaling) | 수신 | 해시 기반 멀티큐 분산 | rx-hashing |
| Scatter-Gather | 송신 | 비연속 메모리 DMA 전송 | tx-scatter-gather |
오프로드 확인/설정
# 현재 오프로드 상태 확인
ethtool -k eth0
# TSO 비활성화 (디버깅용)
ethtool -K eth0 tso off
# GRO 비활성화
ethtool -K eth0 gro off
# RSS 해시 키/indirection table 확인
ethtool -x eth0
# RSS 해시 필드 설정 (TCP 4-tuple)
ethtool -N eth0 rx-flow-hash tcp4 sdfn
# 링 버퍼 크기 조정
ethtool -G eth0 rx 4096 tx 4096
# 인터럽트 병합 (Coalescing) 설정
ethtool -C eth0 rx-usecs 50 rx-frames 64
Pause 프레임과 흐름 제어
IEEE 802.3x Pause Frame은 수신 버퍼 오버플로우 방지를 위한 L2 흐름 제어 메커니즘입니다.
흐름 제어 유형
| 유형 | 표준 | 동작 | 단점 |
|---|---|---|---|
| Symmetric Pause | 802.3x | 양쪽 모두 Pause 전송 가능 | 한 포트 혼잡 시 전체 링크 중단 |
| Asymmetric Pause | 802.3x | 한쪽만 Pause 전송 | 유연하지만 설정 복잡 |
| PFC (Priority Flow Control) | 802.1Qbb | 우선순위별 독립 제어 (8개 클래스) | DCB 전체 구성 필요 |
# Pause 프레임 설정
ethtool -A eth0 rx on tx on
# PFC 설정 (DCB)
mlnx_qos -i eth0 --pfc 0,0,0,1,0,0,0,0 # TC3만 PFC 활성화
ethtool -A ethX rx on tx on으로 활성화해야 합니다.
한쪽만 활성화하면 포트가 hang 상태에 빠질 수 있으므로 반드시 양단 설정을 동기화하세요.
# ICE 흐름 제어 확인 및 양단 동기화
ethtool -a eth0 # RX/TX Pause 상태 확인
ethtool -A eth0 rx on tx on # 양측 모두 활성화 필수
ECN과 DCB
ECN(Explicit Congestion Notification, RFC 3168)은 패킷 드롭 없이 혼잡을 알리는 메커니즘입니다. DCB(Data Center Bridging)는 데이터센터 이더넷에서 무손실 전송을 위한 IEEE 표준 집합입니다.
ECN 마킹 과정
송신 측이 IP 헤더의 ECN 필드를 ECT(0) 또는 ECT(1)로 설정하면, 혼잡한 스위치/라우터가 이를 CE(Congestion Experienced)로 변경합니다. 수신 측은 TCP ACK에 ECE 플래그를 설정하여 송신 측에 혼잡을 알리고, 송신 측은 CWR 플래그로 윈도우 축소를 확인합니다.
DCB 컴포넌트
| 컴포넌트 | 표준 | 기능 | 리눅스 도구 |
|---|---|---|---|
| ETS (Enhanced Transmission Selection) | 802.1Qaz | 트래픽 클래스별 대역폭 보장/분배 | mlnx_qos, lldptool |
| PFC (Priority Flow Control) | 802.1Qbb | 우선순위별 독립 흐름 제어 (8 TC) | mlnx_qos --pfc |
| CN (Congestion Notification) | 802.1Qau | 혼잡 지점에서 rate limiter 피드백 | lldptool |
| DCBX | 802.1Qaz | DCB 파라미터 자동 협상 (LLDP 확장) | lldpad, dcbtool |
# ECN 활성화 (리눅스 커널)
sysctl -w net.ipv4.tcp_ecn=1 # ECN 활성화 (요청 및 수락)
sysctl -w net.ipv4.tcp_ecn=2 # ECN 서버 모드 (수락만)
# DCB 상태 확인
mlnx_qos -i eth0
# ETS (Enhanced Transmission Selection) 대역폭 분배
mlnx_qos -i eth0 --tc_bw 10,10,10,40,10,10,5,5
# DCBX 모드 확인/설정
lldptool -ti eth0 -V IEEE-DCBX
lldptool -Ti eth0 -V ETS-CFG willing=yes
# RoCE (RDMA over Converged Ethernet)용 PFC + ECN 설정
# TC3에 PFC 활성화, ECN으로 혼잡 관리
mlnx_qos -i eth0 --pfc 0,0,0,1,0,0,0,0
sysctl -w net.ipv4.tcp_ecn=1
ICE DCB 운영 — DCBX 모드와 FW-LLDP
Intel E810(ice)은 DCBX 협상을 펌웨어(FW-LLDP) 또는 소프트웨어(SW-LLDP)에서 처리할 수 있습니다. 기본값은 FW-LLDP이며, lldpad와의 통합이 필요한 환경에서는 SW-LLDP로 전환합니다.
| 모드 | LLDP 에이전트 | 장점 | 제약 |
|---|---|---|---|
| FW-LLDP (기본) | 펌웨어가 LLDPDU 송수신 | OS 부팅 전에도 DCBX 협상 가능 | lldpad와 동시 사용 불가 |
| SW-LLDP | lldpad 데몬이 관리 | 유연한 정책 제어, 다중 NIC 통합 관리 | OS 준비 전 DCBX 미동작 |
# FW-LLDP ↔ SW-LLDP 전환 (private flag)
ethtool --set-priv-flags eth0 fw-lldp-agent off # SW-LLDP 활성화
ethtool --set-priv-flags eth0 fw-lldp-agent on # FW-LLDP 복원
# 현재 LLDP 모드 확인
ethtool --show-priv-flags eth0 | grep fw-lldp
# ICE DCB 상태 확인
lldptool -ti eth0 -V IEEE-DCBX
# TC0에 최소 대역폭 할당 (ICE 필수 조건: TC0은 항상 존재해야 함)
lldptool -Ti eth0 -V ETS-CFG tcbw=50,50,0,0,0,0,0,0 tsa=ets,ets,strict,strict,strict,strict,strict,strict up2tc=0:0,1:0,2:1,3:1,4:0,5:0,6:0,7:0
lldpad를 동시에 구동하면 LLDPDU 충돌이 발생하므로 한쪽을 반드시 비활성화하세요.
VLAN과 QinQ
IEEE 802.1Q VLAN 태깅은 하나의 물리적 이더넷 링크에서 논리적 네트워크를 분리합니다.
VLAN 태그 구조 (4바이트)
| 필드 | 비트 | 설명 |
|---|---|---|
| TPID | 16 | Tag Protocol Identifier (0x8100) |
| PCP | 3 | Priority Code Point (QoS 우선순위 0~7) |
| DEI | 1 | Drop Eligible Indicator |
| VID | 12 | VLAN Identifier (0~4095, 유효: 1~4094) |
리눅스 VLAN 설정
# VLAN 인터페이스 생성
ip link add link eth0 name eth0.100 type vlan id 100
ip link set eth0.100 up
ip addr add 10.0.100.1/24 dev eth0.100
# QinQ (802.1ad) — 서비스 프로바이더 VLAN
ip link add link eth0 name eth0.200 type vlan proto 802.1ad id 200
ip link add link eth0.200 name eth0.200.10 type vlan id 10
# VLAN 오프로드 확인
ethtool -k eth0 | grep vlan
- RX 체크섬 오프로드 미지원 — QinQ 패킷의 하드웨어 체크섬 검증이 동작하지 않으므로 소프트웨어 검증에 의존
- VLAN stripping 비활성화 필요 — QinQ 동작을 위해
ethtool -K eth0 rxvlan off로 HW VLAN stripping을 꺼야 함 - VF QinQ 송신 조건 — VF에서 QinQ 패킷을 송신하려면 PF에서 해당 VF에 outer VLAN을 할당해야 함 (
ip link set eth0 vf 0 vlan 200 proto 802.1ad)
EEE (Energy Efficient Ethernet)
IEEE 802.3az Energy Efficient Ethernet은 트래픽이 없을 때 PHY를 저전력 유휴(LPI) 상태로 전환하여 에너지를 절약합니다.
# EEE 상태 확인
ethtool --show-eee eth0
# EEE 비활성화 (지연 민감 환경)
ethtool --set-eee eth0 eee off
# EEE 활성화 (1GbE만)
ethtool --set-eee eth0 eee on advertise 0x8
TSN (Time-Sensitive Networking)
IEEE 802.1 TSN 태스크 그룹은 이더넷 위에 확정적 지연(Deterministic Latency)과 시간 동기화를 구현하는 표준 집합입니다. 산업 자동화, 자동차, 방송 분야에서 전용 필드버스를 대체합니다.
핵심 TSN 표준
| 표준 | 이름 | 기능 |
|---|---|---|
| 802.1AS | gPTP (Generalized PTP) | 네트워크 전체 시간 동기화 (<1 μs 정밀도) |
| 802.1Qbv | Time-Aware Shaper (TAS) | 시간 기반 게이트 제어, 트래픽 클래스별 전송 시간대 할당 |
| 802.1Qbu/802.3br | Frame Preemption | 우선순위 높은 프레임이 낮은 프레임 전송을 중단 가능 |
| 802.1CB | FRER (Frame Replication and Elimination) | 프레임 복제로 무손실 전송 보장 |
| 802.1Qci | Per-Stream Filtering and Policing | 스트림별 필터링/폴리싱 |
| 802.1Qcc | Stream Reservation Protocol | 경로/대역폭 예약 관리 |
리눅스 TSN 지원
# TAS (Time-Aware Shaper) 설정 - taprio qdisc
tc qdisc replace dev eth0 parent root handle 100 taprio \
num_tc 3 \
map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 \
queues 1@0 1@1 2@2 \
base-time 0 \
sched-entry S 01 300000 \
sched-entry S 02 300000 \
sched-entry S 04 400000 \
flags 0x2
# CBS (Credit-Based Shaper) - cbs qdisc
tc qdisc add dev eth0 parent 100:1 cbs \
idleslope 98688 sendslope -901312 \
hicredit 153 locredit -1389
# ETF (Earliest TxTime First) - 정밀 전송 시간 제어
tc qdisc add dev eth0 parent 100:2 etf \
clockid CLOCK_TAI delta 200000 offload
산업용 이더넷
표준 이더넷 프레임을 기반으로 실시간 산업 통신을 구현하는 프로토콜들입니다.
| 프로토콜 | 계층 | 사이클 시간 | 리눅스 지원 |
|---|---|---|---|
| PROFINET RT | L2 (EtherType 0x8892) | ~1 ms | Raw socket / AF_PACKET |
| PROFINET IRT | L2 + HW 스케줄링 | 31.25 μs | TSN + 전용 NIC |
| EtherCAT | L2 (EtherType 0x88A4) | ~50 μs | IgH EtherCAT Master |
| EtherNet/IP | TCP/UDP (CIP) | ~1 ms | 표준 소켓 API |
| Modbus/TCP | TCP (포트 502) | ~10 ms | 표준 소켓 API |
| OPC UA TSN | TSN + UDP | <1 ms | open62541 + taprio |
MACsec (IEEE 802.1AE) 계층 2 암호화
MACsec(Media Access Control Security, IEEE 802.1AE)는 이더넷 프레임을 링크 단위로 암호화하는 L2 보안 프로토콜입니다. IPsec(L3)이나 TLS(L4+)와 달리 이더넷 헤더 직후에서 암호화가 이루어져, ARP, DHCP, LLDP 등 모든 L2 프로토콜 트래픽을 보호합니다.
MACsec 프레임 구조
MACsec는 원본 이더넷 프레임에 SecTAG(Security Tag, 8~16바이트)와 ICV(Integrity Check Value, 8~16바이트)를 추가합니다. EtherType 0x88E5로 식별됩니다.
MKA (MACsec Key Agreement)
IEEE 802.1X-2010에 정의된 MKA(MACsec Key Agreement) 프로토콜은 링크 양단에서 암호화 키를 자동으로 교환하고 갱신합니다.
| 키 유형 | 역할 | 생성 |
|---|---|---|
| CAK (Connectivity Association Key) | 마스터 키, MKA 세션의 기반 | 사전 공유(PSK) 또는 802.1X EAP |
| CKN (CAK Name) | CAK 식별자 | CAK와 함께 설정 |
| SAK (Secure Association Key) | 실제 데이터 암호화 키 | CAK에서 KDF로 자동 파생 |
| KEK (Key Encrypting Key) | SAK 전송 시 암호화용 | CAK에서 자동 파생 |
| ICK (ICV Key) | MKPDU 무결성 검증 | CAK에서 자동 파생 |
MACsec 동작 모드
| 모드 | 암호화 | 무결성 | 용도 |
|---|---|---|---|
| GCM-AES-128 | O | O | 기본 모드 (대부분 HW 지원) |
| GCM-AES-256 | O | O | 높은 보안 요구 (일부 NIC) |
| GCM-AES-XPN-128/256 | O | O | 확장 PN (고속 링크, 64비트 PN) |
| Integrity Only | X | O | 무결성만 검증 (ICV만 추가) |
리눅스 MACsec 설정
# MACsec 인터페이스 생성 (PSK 모드)
ip link add link eth0 macsec0 type macsec sci 1 encrypt on
# 수신 SA 추가 (피어로부터 수신하는 키)
ip macsec add macsec0 rx sci 0x0002 sa 0 pn 1 on \
key 00 dffafc8d7b9a43d5b9a3dfbbf6a30c16
# 송신 SA 추가 (자신이 송신하는 키)
ip macsec add macsec0 tx sa 0 pn 1 on \
key 01 ead3664f508eb06c40ac7104cdae4ce2
# MACsec 인터페이스 활성화
ip link set macsec0 up
ip addr add 192.168.100.1/24 dev macsec0
# MACsec 상태 확인
ip macsec show
# wpa_supplicant MKA 자동 키 교환 (802.1X 연동)
# /etc/wpa_supplicant/wpa_supplicant-macsec.conf
# network={
# key_mgmt=IEEE8021X
# eapol_flags=0
# macsec_policy=1
# mka_cak=dffafc8d7b9a43d5b9a3dfbbf6a30c16
# mka_ckn=31323334353637383930313233343536
# mka_priority=255
# }
# HW 오프로드 확인 (지원 NIC: Intel E810, Mellanox ConnectX-6 Dx+)
ethtool -k eth0 | grep macsec
ip link add link eth0 macsec0 type macsec offload mac
offload mac 옵션으로 활성화합니다.
SR-IOV와 이더넷 가상화
SR-IOV(Single Root I/O Virtualization, PCI-SIG 규격)는 하나의 물리 NIC(PF, Physical Function)에서 다수의 가상 NIC(VF, Virtual Function)를 생성하여, 가상머신(VM)이나 컨테이너에 직접 할당할 수 있게 합니다. 하이퍼바이저의 가상 스위치를 우회하므로 네이티브에 가까운 성능을 달성합니다.
SR-IOV VF 생성 및 관리
# VF 생성 (최대 수는 NIC마다 다름)
echo 4 > /sys/class/net/eth0/device/sriov_numvfs
# VF 확인
ip link show eth0
# ... vf 0 MAC aa:bb:cc:dd:ee:00, spoof checking on, link-state auto
# ... vf 1 MAC aa:bb:cc:dd:ee:01, spoof checking on, link-state auto
# VF MAC 주소 설정 (PF에서)
ip link set eth0 vf 0 mac aa:bb:cc:dd:ee:00
# VF VLAN 태그 설정
ip link set eth0 vf 0 vlan 100
# VF 대역폭 제한 (Mbps)
ip link set eth0 vf 0 max_tx_rate 1000 min_tx_rate 100
# VF Spoof 체크 비활성화 (DPDK 등 직접 MAC 설정 시)
ip link set eth0 vf 0 spoofchk off
# VF Trust 모드 (Promiscuous 허용)
ip link set eth0 vf 0 trust on
# VF를 QEMU/KVM에 직접 할당 (VFIO passthrough)
# 1. IOMMU 활성화 (커널 파라미터: intel_iommu=on iommu=pt)
# 2. VF를 vfio-pci에 바인딩
echo "0000:03:02.0" > /sys/bus/pci/drivers/ice/unbind
echo "vfio-pci" > /sys/bus/pci/devices/0000:03:02.0/driver_override
echo "0000:03:02.0" > /sys/bus/pci/drivers/vfio-pci/bind
# eSwitch 모드 전환 (Mellanox switchdev)
devlink dev eswitch set pci/0000:03:00.0 mode switchdev
devlink dev eswitch show pci/0000:03:00.0
- virtio-net (에뮬레이션): ~5 Gbps, CPU 사용률 높음, vhost-net으로 개선 가능
- macvtap: ~8 Gbps, 호스트 네트워크 스택 일부 우회
- SR-IOV VF (VFIO): ~25 Gbps (25GbE NIC), 네이티브의 95%+, CPU 오버헤드 최소
- DPDK + VF: 라인 레이트(25~100 Gbps), 유저스페이스 직접 처리, 커널 우회
switchdev 모드에서 VF representor를 OVS에 연결하여 마이그레이션을 지원하는 방식을 제공합니다. 또한 IOMMU 그룹 단위로 할당되므로, 동일 IOMMU 그룹의 모든 디바이스가 함께 할당됩니다.
DSA (Distributed Switch Architecture)
DSA는 리눅스 커널의 이더넷 스위치 칩 추상화 프레임워크입니다. SoC에 내장되거나 MDIO/SPI로 연결된 이더넷 스위치(Marvell, Microchip, Realtek 등)를 표준 net_device로 노출하여, VLAN, 브릿지, STP 등 기존 리눅스 네트워크 도구로 스위치를 제어할 수 있게 합니다.
DSA 설정 및 관리
# DSA 포트 확인
ip link show type dsa
# DSA 스위치 포트를 브릿지에 추가
ip link add br0 type bridge vlan_filtering 1
ip link set lan0 master br0
ip link set lan1 master br0
ip link set lan2 master br0
# 포트별 VLAN 설정 (HW 오프로드)
bridge vlan add dev lan0 vid 10 pvid untagged
bridge vlan add dev lan1 vid 20 pvid untagged
bridge vlan add dev lan2 vid 10
bridge vlan add dev lan2 vid 20 # trunk 포트
# FDB (포워딩 데이터베이스) 확인
bridge fdb show br br0
# DSA 태깅 프로토콜 확인
cat /sys/class/net/eth0/dsa/tagging
# Device Tree에서의 DSA 정의 예시
# &mdio {
# switch@0 {
# compatible = "marvell,mv88e6085";
# reg = <0>;
# ports {
# port@0 { label = "lan0"; };
# port@5 { label = "cpu"; ethernet = <&gmac0>; };
# };
# };
# };
net_device로 생성합니다.
AF_XDP와 고성능 패킷 처리
AF_XDP(eXpress Data Path 소켓)는 리눅스 커널 4.18+에서 도입된 고성능 패킷 처리 인터페이스입니다. XDP 프로그램이 NIC에서 수신한 패킷을 커널 네트워크 스택을 완전히 우회하여 유저스페이스 애플리케이션에 제로카피로 전달합니다.
AF_XDP 동작 모드
| 모드 | 성능 | 요구 사항 | 설명 |
|---|---|---|---|
| Zero-Copy | 최고 (~25 Mpps) | 드라이버 지원 필수 | NIC DMA가 UMEM에 직접 쓰기, 복사 없음 |
| Copy Mode | 중간 (~5 Mpps) | 모든 XDP 드라이버 | 커널이 RX 버퍼에서 UMEM으로 복사 |
| SKB Mode | 낮음 (~2 Mpps) | XDP generic | skb 할당 후 처리, 호환성 최대 |
# AF_XDP 제로카피 지원 드라이버 확인
# Intel: ice, i40e, ixgbe, igc
# Mellanox: mlx5
# Amazon: ena
# Netronome: nfp
# XDP 프로그램 로드 (xdpsock 예시)
ip link set dev eth0 xdp obj xdp_prog.o sec xdp
# AF_XDP 소켓 기본 사용법 (C 코드 개요)
/* 1. UMEM 생성 */
/* struct xsk_umem *umem;
xsk_umem__create(&umem, buffer, size, &fill, &comp, &cfg); */
/* 2. AF_XDP 소켓 생성 */
/* struct xsk_socket *xsk;
xsk_socket__create(&xsk, "eth0", queue, umem, &rx, &tx, &cfg); */
/* 3. poll() 또는 busy-poll로 패킷 수신 */
/* 4. RX Ring에서 descriptor 읽기 → UMEM 주소로 패킷 접근 */
# libbpf AF_XDP 헬퍼 (xsk.h)
# xsk_ring_prod__reserve(), xsk_ring_cons__peek()
# xsk_ring_prod__submit(), xsk_ring_cons__release()
# XDP 통계 확인
bpftool prog show
bpftool net show
# ethtool XDP 통계
ethtool -S eth0 | grep xdp
성능 튜닝
이더넷 네트워크 성능을 최적화하는 주요 커널/드라이버 파라미터입니다.
링 버퍼 최적화
# 링 버퍼 현재 크기 확인
ethtool -g eth0
# 링 버퍼 최대로 설정 (패킷 드롭 방지)
ethtool -G eth0 rx 4096 tx 4096
# 인터럽트 병합 (지연 vs 처리량 트레이드오프)
ethtool -C eth0 adaptive-rx on adaptive-tx on
adaptive-rx on을 사용하면 드라이버가 트래픽 패턴에 따라 인터럽트 병합 파라미터를 자동 조절합니다. 저부하 시 지연을 최소화하고, 고부하 시 인터럽트 수를 줄여 CPU 사용률을 낮춥니다. Intel igb/ixgbe/ice, Mellanox mlx5 등 주요 드라이버가 지원합니다.
# 멀티큐 확인
ethtool -l eth0
# 큐 수 변경
ethtool -L eth0 combined 8
IRQ 어피니티
# NIC IRQ 확인
grep eth0 /proc/interrupts
# IRQ 어피니티 자동 설정 스크립트
set_irq_affinity eth0
# 수동 설정: IRQ 42번을 CPU 0에 바인딩
echo 1 > /proc/irq/42/smp_affinity
# XPS (Transmit Packet Steering) 설정
echo 1 > /sys/class/net/eth0/queues/tx-0/xps_cpus
sysctl 네트워크 튜닝
# 수신 버퍼
sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.rmem_default=1048576
# 송신 버퍼
sysctl -w net.core.wmem_max=16777216
sysctl -w net.core.wmem_default=1048576
# 네트워크 백로그
sysctl -w net.core.netdev_max_backlog=30000
sysctl -w net.core.netdev_budget=600
# TCP 자동 튜닝
sysctl -w net.ipv4.tcp_rmem="4096 1048576 16777216"
sysctl -w net.ipv4.tcp_wmem="4096 1048576 16777216"
FEC (Forward Error Correction)
FEC(전진 오류 정정)는 고속 이더넷(25G 이상)에서 비트 오류율(BER)을 허용 수준(10-12 이하)으로 낮추기 위해 송신 측에서 중복 데이터를 추가하고, 수신 측에서 오류를 복원하는 기술입니다. PAM4 변조를 사용하는 25G+ 이더넷에서는 FEC가 필수적입니다.
FEC 유형 비교
| FEC 유형 | 표준 | 속도 | 지연 | 정정 능력 | 오버헤드 |
|---|---|---|---|---|---|
| BaseR FEC (Firecode/FC-FEC) | 802.3 Clause 74 | 10G/25G/40G | ~50 ns | 단일 비트 버스트 (11비트) | ~2.6% |
| RS-FEC (Reed-Solomon) | 802.3 Clause 91/108 | 25G/50G/100G+ | ~100 ns | 다중 심볼 오류 (최대 ~7%) | ~2.7% |
| RS-FEC (544,514) | 802.3 Clause 119 | 50G/100G/200G/400G+ (PAM4) | ~100 ns | 더 강한 정정 (PAM4용) | ~5.8% |
| 없음 (No FEC) | - | 10G 이하 | 0 | 없음 | 0% |
FEC 설정 및 모니터링
# 현재 FEC 설정 확인
ethtool --show-fec eth0
# FEC 모드 변경
ethtool --set-fec eth0 encoding rs # RS-FEC 강제
ethtool --set-fec eth0 encoding baser # BaseR-FEC 강제
ethtool --set-fec eth0 encoding auto # 자동 협상
ethtool --set-fec eth0 encoding off # FEC 비활성화
# FEC 통계 확인 (정정/미정정 블록 수)
ethtool -S eth0 | grep -i fec
# fec_corrected_blocks: 12345 ← 정정 성공 (정상)
# fec_uncorrectable_blocks: 0 ← 미정정 (이 값이 증가하면 문제)
# FEC 미정정 블록이 증가하면:
# 1. SFP 모듈의 RX Power 확인 (ethtool -m ethX)
# 2. 광 패치 코드 교체
# 3. FEC 모드를 RS-FEC으로 변경 (더 강한 정정)
# 4. 링크 양단 FEC 모드 일치 확인
이더넷 케이블과 커넥터 가이드
물리 계층의 성능은 케이블과 커넥터에 크게 의존합니다. 올바른 케이블 선택은 안정적인 이더넷 링크의 기본입니다.
UTP 케이블 카테고리 비교
| 카테고리 | 최대 주파수 | 최대 속도 | 최대 거리 | 차폐 | 용도 |
|---|---|---|---|---|---|
| Cat5 | 100 MHz | 100 Mbps | 100m | UTP | 레거시 (사용 지양) |
| Cat5e | 100 MHz | 1 Gbps / 2.5 Gbps | 100m | UTP | 일반 사무/가정용 |
| Cat6 | 250 MHz | 5 Gbps(100m) / 10G(55m) | 55~100m | UTP/STP | 기업 환경, PoE+ |
| Cat6a | 500 MHz | 10 Gbps | 100m | F/UTP, U/FTP | 10GbE 표준, 데이터센터 |
| Cat7 | 600 MHz | 10 Gbps | 100m | S/FTP (전쌍 차폐) | EMI 환경, 산업용 |
| Cat7a | 1000 MHz | 10 Gbps (40G@50m) | 50~100m | S/FTP | 미래 대비, 특수 환경 |
| Cat8 | 2000 MHz | 25/40 Gbps | 30m | S/FTP | 데이터센터 스위치 간 |
케이블 테스트 및 진단
# 케이블 테스트 (TDR: Time Domain Reflectometry)
ethtool --cable-test eth0
# 결과 확인 (NIC 지원 필요: ice, igc, aqc111 등)
# pair A code open, length 15m
# pair B code ok
# pair C code ok
# pair D code short, length 8m
# 케이블 진단 코드 해석:
# ok — 정상 연결
# open — 단선 (선이 끊어짐)
# short — 합선 (선끼리 접촉)
# impedance-mismatch — 임피던스 불일치 (커넥터 불량)
# 광 커넥터 (SFP) 연결 상태 확인
ethtool -m eth0
# RX Power가 -30 dBm 이하이면 광 손실 과다
# 정상 범위: -1 ~ -12 dBm (모듈마다 다름)
DAC와 AOC
| 유형 | 정식 명칭 | 매체 | 최대 거리 | 소비 전력 | 용도 |
|---|---|---|---|---|---|
| DAC | Direct Attach Copper | 트윈악스 구리 | 5~7m | 매우 낮음 (~0.1W) | ToR-서버 단거리 |
| AOC | Active Optical Cable | 광섬유 (일체형) | 30~100m | ~1W | 랙 간 중거리 |
| 트랜시버+패치코드 | SFP/QSFP + LC/MPO | 광섬유 (분리형) | 300m~40km | ~1.5W | 장거리, 유연한 구성 |
FCS와 CRC-32
이더넷 프레임의 마지막 4바이트 FCS(Frame Check Sequence)는 CRC-32 다항식으로 계산됩니다.
- 다항식:
x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 - 검사 범위: Destination MAC ~ Payload (Preamble, SFD 제외)
- HW 오프로드: 현대 NIC은 FCS를 하드웨어에서 계산/검증,
skb->ip_summed로 커널에 알림
/* 커널 CRC-32 API */
#include <linux/crc32.h>
u32 crc = crc32_le(~0, data, len); /* Little-endian CRC-32 */
u32 fcs = ~crc; /* 최종 보수(complement) */
PTP와 하드웨어 타임스탬프
IEEE 1588 PTP(Precision Time Protocol)는 이더넷 네트워크에서 나노초 수준 시간 동기화를 달성합니다.
# PTP 하드웨어 타임스탬프 능력 확인
ethtool -T eth0
# linuxptp로 PTP 동기화
ptp4l -i eth0 -m -H # Hardware timestamping
phc2sys -s eth0 -c CLOCK_REALTIME -O 0 -m
# PHC (PTP Hardware Clock) 확인
cat /sys/class/ptp/ptp0/clock_name
WoL (Wake-on-LAN)
Wake-on-LAN은 이더넷을 통해 원격으로 시스템을 깨우는 기능입니다. 시스템이 완전히 동작하지 않는 상태여도 NIC의 일부 블록은 대기 전원으로 살아 있으며, 매직 패킷이나 드라이버가 허용한 웨이크 패턴을 감시합니다.
실무에서는 S3(대기), S4(디스크 절전), S5(소프트 오프)에서 WoL을 기대하지만, 실제 지원 범위는 메인보드 전원 설계, BIOS/UEFI 정책, NIC의 D3hot/D3cold 동작에 따라 달라집니다. 커널은 시스템을 절전 상태로 넘기기 전에 NIC 드라이버에 웨이크 패턴을 프로그래밍하고, 이후 NIC는 패턴이 일치하면 PME# 같은 웨이크 이벤트를 플랫폼에 전달합니다.
| 항목 | WoL에서 실제로 남아 있는 것 | 주의할 점 |
|---|---|---|
| 전원 상태 | S3, S4, S5에서 주로 사용 | 보드에 따라 S5 WoL을 막거나 ErP 설정으로 대기 전원을 끌 수 있습니다. |
| NIC 내부 블록 | PHY/MAC 일부와 패턴 매처 | D3cold로 너무 깊게 내려가면 링크 복구가 늦거나 WoL이 완전히 막힐 수 있습니다. |
| 웨이크 신호 | PME# 또는 펌웨어 경유 ACPI 웨이크 | 운영체제 설정만으로는 부족하고 BIOS/UEFI 허용이 함께 필요합니다. |
| 네트워크 범위 | 보통 같은 L2 브로드캐스트 도메인 | 라우터는 브로드캐스트를 기본적으로 넘기지 않으므로 중계나 포워딩 설계가 필요합니다. |
매직 패킷은 데이터 페이로드 어디에 있어도 되지만, 일반적으로는 같은 L2 세그먼트에서 브로드캐스트 주소로 보내는 방식이 가장 단순합니다. NIC는 운영체제가 거의 꺼진 상태에서도 이 패턴을 비교할 수 있도록 최소한의 수신 경로를 유지합니다.
- 펌웨어 정책: BIOS/UEFI에서 WoL이나 PCIe Power On이 꺼져 있으면 커널 설정이 맞아도 깨우지 못합니다.
- 대기 전원 차단: ErP, Deep Sleep, S5 절전 강화 옵션이 NIC의 대기 전원을 끌 수 있습니다.
- 네트워크 경로 문제: 브로드캐스트가 다른 서브넷으로 전달되지 않거나 스위치/AP가 절전 중 링크를 내릴 수 있습니다.
- 드라이버 비영속: 재부팅 또는 링크 재초기화 뒤 WoL 플래그가 초기화되면 다음 절전부터 동작하지 않습니다.
# WoL 지원 확인
ethtool eth0 | grep Wake-on
# WoL 활성화 (Magic Packet)
ethtool -s eth0 wol g
# WoL 비활성화
ethtool -s eth0 wol d
# 매직 패킷 전송 (다른 시스템에서)
wakeonlan AA:BB:CC:DD:EE:FF
디버깅과 진단
ethtool 진단
# 드라이버 정보
ethtool -i eth0
# NIC 통계 (드라이버별)
ethtool -S eth0
# 링크 상태 상세
ethtool eth0
# PHY 레지스터 덤프
ethtool -d eth0
# NIC 자가진단 (지원 시)
ethtool -t eth0 online
# 모듈(SFP) 정보
ethtool -m eth0
이더넷 오류 유형
이더넷 통신에서 발생하는 주요 오류 유형과 원인, 증상, 해결 방법을 정리합니다.
| 오류 유형 | 원인 | 증상 | 해결 |
|---|---|---|---|
| CRC 오류 | 케이블 손상, EMI, 불량 커넥터 | rx_crc_errors 증가 | 케이블 교체, 접지 확인 |
| Alignment 오류 | 바이트 경계 미정렬, PHY 문제 | rx_align_errors 증가 | PHY 칩 교체, 듀플렉스 불일치 확인 |
| Runt Frame | 충돌, 잘못된 드라이버 | 64바이트 미만 프레임 수신 | 듀플렉스 설정, 케이블 길이 확인 |
| Giant Frame | MTU 불일치, Jabber | 최대 크기 초과 프레임 | 양단 MTU/Jumbo Frame 설정 동기화 |
| Late Collision | 케이블 과장, 듀플렉스 불일치 | 512 bit time 이후 충돌 감지 | 케이블 100m 이내 확인, Full-Duplex 강제 |
| Carrier Sense 오류 | PHY 링크 불안정 | tx_carrier_errors 증가 | SFP 모듈/케이블 교체, PHY 펌웨어 업데이트 |
ethtool -S 출력에서 오류 카운터를 해석하는 예시입니다.
# NIC 오류 통계 확인
ethtool -S eth0 | grep -i error
# 주요 오류 카운터 해석
# rx_crc_errors — CRC 불일치 (물리 계층 문제)
# rx_missed_errors — 링 버퍼 부족으로 누락
# rx_length_errors — 길이 필드 불일치
# rx_over_errors — RX FIFO 오버플로우
# tx_aborted_errors — 전송 중단 (과도한 충돌)
# tx_fifo_errors — TX FIFO 언더런
# 시간 경과에 따른 오류 증가율 모니터링
watch -n 1 'ethtool -S eth0 | grep -i error'
# sysfs 오류 카운터 직접 확인
for f in /sys/class/net/eth0/statistics/*error*; do
echo "$(basename $f): $(cat $f)"
done
패킷 카운터 확인
# 인터페이스 통계
ip -s link show eth0
# 상세 오류 카운터
cat /sys/class/net/eth0/statistics/rx_errors
cat /sys/class/net/eth0/statistics/rx_dropped
cat /sys/class/net/eth0/statistics/tx_carrier_errors
# SNMP MIB 카운터
cat /proc/net/snmp | grep Ip
# 드롭 원인 추적
dropwatch -l kas
# 또는 perf를 사용
perf trace -e 'skb:kfree_skb'
패킷 캡처
# 이더넷 헤더 포함 캡처
tcpdump -i eth0 -e -nn -c 10
# VLAN 태그 포함 캡처
tcpdump -i eth0 -e vlan
# ARP만 캡처
tcpdump -i eth0 arp -e
# 특정 EtherType 캡처
tcpdump -i eth0 ether proto 0x88cc # LLDP
이더넷 드라이버 작성 가이드
리눅스 이더넷 드라이버의 핵심 구조를 이해하면 NIC 관련 문제를 디버깅하고 커스텀 드라이버를 작성하는 데 큰 도움이 됩니다. 최소한의 이더넷 드라이버 스켈레톤을 통해 핵심 콜백과 초기화 흐름을 살펴봅니다.
최소 드라이버 스켈레톤
/* 최소 이더넷 드라이버 구조 (개요) */
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
struct my_priv {
struct pci_dev *pdev;
void __iomem *hw_addr; /* MMIO base */
struct napi_struct napi;
/* TX/RX descriptor rings, DMA 주소 등 */
};
/* ---- TX 경로 ---- */
static netdev_tx_t my_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct my_priv *priv = netdev_priv(dev);
/* 1. TX descriptor에 skb 매핑 */
dma_addr_t dma = dma_map_single(&priv->pdev->dev,
skb->data, skb->len, DMA_TO_DEVICE);
/* 2. Descriptor에 DMA 주소/길이 기록 */
/* 3. Doorbell (tail pointer) 업데이트 */
writel(new_tail, priv->hw_addr + TX_TAIL_REG);
return NETDEV_TX_OK;
}
/* ---- RX 경로 (NAPI poll) ---- */
static int my_poll(struct napi_struct *napi, int budget)
{
struct my_priv *priv = container_of(napi, struct my_priv, napi);
int cleaned = 0;
while (cleaned < budget) {
/* RX descriptor에서 완료된 패킷 확인 */
if (!rx_desc_done(priv))
break;
struct sk_buff *skb = napi_alloc_skb(napi, pkt_len);
/* DMA 언맵 + 데이터 복사 (또는 page flip) */
skb->protocol = eth_type_trans(skb, priv->ndev);
napi_gro_receive(napi, skb);
cleaned++;
}
if (cleaned < budget) {
napi_complete_done(napi, cleaned);
/* 인터럽트 재활성화 */
my_irq_enable(priv);
}
return cleaned;
}
/* ---- IRQ 핸들러 ---- */
static irqreturn_t my_irq(int irq, void *data)
{
struct my_priv *priv = data;
/* 인터럽트 비활성화 (NAPI가 처리) */
my_irq_disable(priv);
napi_schedule(&priv->napi);
return IRQ_HANDLED;
}
/* ---- net_device_ops ---- */
static const struct net_device_ops my_netdev_ops = {
.ndo_open = my_open, /* ip link set up */
.ndo_stop = my_close, /* ip link set down */
.ndo_start_xmit = my_xmit, /* 패킷 송신 */
.ndo_set_rx_mode = my_set_rx_mode,/* 프로미스큐어스/멀티캐스트 */
.ndo_set_mac_address = eth_mac_addr, /* 기본 MAC 변경 */
.ndo_change_mtu = my_change_mtu, /* MTU 변경 */
.ndo_get_stats64 = my_get_stats, /* 통계 */
};
/* ---- PCI probe ---- */
static int my_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct net_device *ndev;
struct my_priv *priv;
pci_enable_device(pdev);
pci_set_master(pdev);
dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
ndev = alloc_etherdev(sizeof(*priv));
priv = netdev_priv(ndev);
priv->pdev = pdev;
priv->hw_addr = pci_ioremap_bar(pdev, 0);
ndev->netdev_ops = &my_netdev_ops;
ndev->ethtool_ops = &my_ethtool_ops;
/* MAC 주소 읽기 (NIC EEPROM/레지스터에서) */
my_read_mac(priv, ndev->dev_addr);
netif_napi_add(ndev, &priv->napi, my_poll);
register_netdev(ndev);
pci_set_drvdata(pdev, ndev);
return 0;
}
- DMA 일관성:
dma_map_single()/dma_unmap_single()쌍을 반드시 맞추고, 매핑 실패 시dma_mapping_error()로 확인 - NAPI 원칙: IRQ 핸들러에서는
napi_schedule()만 호출하고, 실제 패킷 처리는 poll 콜백에서 수행. budget 초과 시 poll을 재스케줄링 - 메모리 배리어: descriptor ring 업데이트 시
wmb()/rmb()로 DMA 순서 보장 - 에러 경로: probe에서 실패 시 할당된 모든 리소스를 역순으로 해제 (goto 패턴)
- XDP 지원:
ndo_bpf,ndo_xdp_xmit콜백 구현으로 XDP 프로그램 연동
자주 하는 실수와 트러블슈팅
이더넷 환경에서 반복적으로 발생하는 문제와 해결 방법을 정리합니다.
1. 듀플렉스 불일치 (Duplex Mismatch)
late_collision, rx_crc_errors가 증가합니다.
원인: 한쪽은 Full-Duplex, 다른 쪽은 Half-Duplex로 설정된 경우. Auto-Negotiation을 한쪽만 끄면 흔히 발생합니다.
해결: 양쪽 모두
autoneg on으로 설정하거나, 양쪽 모두 동일하게 강제 설정합니다.
# 진단
ethtool eth0 | grep -E "Speed|Duplex|Auto-negotiation"
ethtool -S eth0 | grep -i "late_collision\|crc"
# 해결: 양단 Auto-Negotiation 활성화
ethtool -s eth0 autoneg on
2. MTU 불일치
ping -s 1472이 실패합니다.
원인: 경로상 한 장비의 MTU가 다른 장비보다 작고, PMTUD(Path MTU Discovery)가 차단된 경우.
해결: 경로 전체 MTU를 통일하거나, ICMP "Fragmentation Needed" 메시지가 차단되지 않았는지 확인합니다.
# 경로 MTU 확인
tracepath -n 10.0.0.1
ping -M do -s 8972 10.0.0.1 # Jumbo Frame 경로 테스트
# 모든 장비 MTU 확인
ip link show | grep mtu
3. 오프로드 문제 (체크섬/TSO 오류)
원인: TX checksum 오프로드가 활성화된 상태에서 NIC이 보내기 전의 패킷을 캡처하면 체크섬이 아직 계산되지 않아 잘못된 것처럼 보입니다. 이는 정상 동작입니다.
실제 문제인 경우: RX checksum 오류가 지속적으로 증가하면 NIC 하드웨어 또는 드라이버 버그입니다.
# tcpdump "bad checksum"이 TX 오프로드 때문인지 확인
ethtool -k eth0 | grep "tx-checksum"
# 오프로드 비활성화로 문제 격리
ethtool -K eth0 tx off rx off tso off gro off
# 문제가 사라지면 오프로드 관련 드라이버 버그
# 하나씩 다시 켜며 원인 특정
ethtool -K eth0 rx on # RX checksum
ethtool -K eth0 tx on # TX checksum
ethtool -K eth0 tso on # TSO
ethtool -K eth0 gro on # GRO
4. FEC 불일치로 링크 미연결
ethtool eth0에서 "Link detected: no".
원인: FEC 모드가 양단에서 다릅니다 (예: 한쪽 RS-FEC, 다른 쪽 No FEC).
해결: 양단 FEC 모드를 동일하게 맞추거나
auto로 설정합니다.
ethtool --show-fec eth0
ethtool --set-fec eth0 encoding auto
5. RGMII 지연 이중 적용
원인: Device Tree에서
phy-mode = "rgmii-id"로 PHY가 TX/RX 지연을 추가하는데, PHY 레지스터에도 내부 지연이 켜져 있어 이중 지연(4ns)이 됩니다.
해결: Device Tree와 PHY 레지스터 중 정확히 한 곳에서만 지연을 추가합니다.
# Device Tree 확인
cat /sys/firmware/devicetree/base/ethernet*/phy-mode
# PHY 레지스터에서 지연 설정 확인 (MDIO)
ethtool -d eth0 # 또는 phytool
# RGMII 모드 종류:
# "rgmii" — 지연 없음 (PCB 트레이스로 추가)
# "rgmii-id" — PHY가 TX+RX 지연 모두 추가
# "rgmii-txid" — PHY가 TX 지연만 추가
# "rgmii-rxid" — PHY가 RX 지연만 추가
6. 링 버퍼 부족으로 패킷 드롭
rx_missed_errors 또는 rx_no_buffer_count가 증가합니다. ifconfig에서 RX dropped 증가.
원인: RX Ring Buffer 크기가 작아서 NAPI가 처리하기 전에 새 패킷이 덮어씌워집니다.
해결: Ring Buffer를 최대로 늘리고, Adaptive Coalescing을 활성화합니다.
# 현재 Ring 크기 확인
ethtool -g eth0
# 최대로 설정
ethtool -G eth0 rx 4096 tx 4096
# Adaptive Coalescing 활성화
ethtool -C eth0 adaptive-rx on adaptive-tx on
# 드롭 원인 상세 추적
dropwatch -l kas
7. IRQ 편중 (단일 CPU 과부하)
/proc/interrupts에서 한 CPU에 NIC IRQ가 집중됩니다.
원인:
irqbalance가 NIC IRQ를 적절히 분산하지 못하거나, IRQ affinity가 설정되지 않았습니다.
해결: 수동으로 IRQ affinity를 설정하거나 드라이버 제공 스크립트를 사용합니다.
# IRQ 분포 확인
grep eth0 /proc/interrupts
# IRQ를 CPU별로 분산 (예: 8큐 NIC)
# Queue 0 → CPU 0, Queue 1 → CPU 1, ...
for i in $(seq 0 7); do
irq=$(grep "eth0-TxRx-$i" /proc/interrupts | awk '{print $1}' | tr -d :)
echo $((1 << $i)) > /proc/irq/$irq/smp_affinity
done
# 또는 Intel 제공 스크립트
set_irq_affinity eth0
8. EEE로 인한 지연 증가
원인: EEE(Energy Efficient Ethernet)의 LPI 복귀 시간이 영향을 줍니다.
해결: 지연에 민감한 환경에서는 EEE를 비활성화합니다.
ethtool --show-eee eth0
ethtool --set-eee eth0 eee off
종합 트러블슈팅 체크리스트
| 증상 | 1차 확인 | 2차 확인 | 3차 확인 |
|---|---|---|---|
| 링크 미연결 | 케이블/SFP 물리 연결 | ethtool --show-fec FEC 일치 | ethtool -s 속도/듀플렉스 강제 |
| 간헐적 끊김 | ethtool -S CRC/alignment 오류 | ethtool -m SFP RX Power | ethtool --cable-test |
| 성능 저하 | ethtool -g Ring 크기 | ethtool -c Coalescing | IRQ affinity, CPU 분산 |
| 패킷 드롭 | ethtool -S rx_missed/no_buffer | ethtool -G Ring 증가 | sysctl netdev_budget |
| 높은 CPU 사용률 | 오프로드 확인 ethtool -k | RSS 큐 수 확인 ethtool -l | GRO/TSO 활성화 |
| 지연 변동 | --show-eee EEE 확인 | Coalescing 값 조정 | NUMA/CPU pinning |
커널 소스 참조
| 파일/디렉토리 | 역할 |
|---|---|
include/uapi/linux/if_ether.h | 이더넷 상수, struct ethhdr |
net/ethernet/eth.c | eth_type_trans(), eth_header() |
include/linux/ethtool.h | ethtool_ops, 링크 설정 구조체 |
net/ethtool/ | ethtool Netlink 인터페이스 (커널 5.6+) |
include/linux/phylink.h | phylink API, phylink_mac_ops |
drivers/net/phy/ | PHY 드라이버 (Marvell, Broadcom, Realtek 등) |
drivers/net/ethernet/ | 이더넷 NIC 드라이버 (intel/, mellanox/, broadcom/ 등) |
net/8021q/ | 802.1Q VLAN 구현 |
net/sched/sch_taprio.c | TSN TAS (taprio qdisc) |
net/sched/sch_cbs.c | TSN CBS (Credit-Based Shaper) |
net/sched/sch_etf.c | TSN ETF (Earliest TxTime First) |
drivers/net/macsec.c | MACsec 소프트웨어 구현 |
include/net/macsec.h | MACsec 구조체, offload API |
net/dsa/ | DSA 프레임워크 코어 |
drivers/net/dsa/ | DSA 스위치 드라이버 (mv88e6xxx, ksz, sja1105 등) |
net/xdp/ | XDP 코어, AF_XDP 소켓 |
include/net/xdp_sock.h | AF_XDP 소켓 구조체 |
drivers/net/ethernet/intel/ice/ | Intel E810 드라이버 (SR-IOV, MACsec, PTP) |
drivers/net/ethernet/mellanox/mlx5/ | Mellanox ConnectX 드라이버 (eSwitch, SR-IOV) |
관련 문서
- MAC 주소 (MAC Address) — EUI-48 비트 구조, ARP/Neighbor, Bridge FDB, MAC 필터링
- sk_buff 자료구조 — 이더넷 프레임을 담는 핵심 커널 버퍼
- 네트워크 스택 — 전체 네트워크 스택 아키텍처와 패킷 흐름
- GSO/GRO 네트워크 오프로드 — 세그멘테이션/병합 오프로드 상세
- NAPI (New API) — 인터럽트 완화와 폴링 기반 패킷 수신
- Network Device 드라이버 — net_device_ops, NAPI, ethtool 구현
- Bridge/VLAN/Bonding — L2 브릿지, VLAN, 링크 어그리게이션
- TC (Traffic Control) — 트래픽 셰이핑, 큐잉 디시플린
- IP 프로토콜 (IPv4/IPv6) — 이더넷 위의 L3 프로토콜