이더넷 (Ethernet)

1973년 Xerox PARC에서 탄생한 이더넷은 반세기가 넘는 진화를 거쳐 10 Mbps 동축 케이블 버스에서 800 Gbps 광 링크까지 확장되었습니다. 이 문서는 이더넷의 역사, 물리 계층(PHY), 프레임 구조, 리눅스 커널 구현, 오프로드 기술, 에너지 효율, 산업용 이더넷까지 다양한 시각에서 종합적으로 다룹니다.

전제 조건: 네트워크 스택 (Network Stack) 문서를 먼저 읽으면 커널의 전체 패킷 흐름을 이해하는 데 도움이 됩니다. sk_buff 자료구조에 대한 기본 지식이 있으면 커널 자료구조 섹션을 더 쉽게 이해할 수 있습니다.
일상 비유: 이더넷은 고속도로 시스템과 비슷합니다. 프레임은 화물 트럭(정해진 크기의 컨테이너에 짐을 싣는 것처럼 헤더+페이로드+FCS로 구성), MAC 주소는 차량 번호판(출발지와 목적지 식별), 스위치는 교차로의 신호 시스템(올바른 목적지로만 트럭을 보냄), 그리고 속도 진화(10M→800G)는 1차선 비포장도로가 수십 차선 고속도로로 확장된 것에 비유할 수 있습니다.

핵심 요약

  • 프레임 (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 하드웨어로 넘기는 기술. 고성능 네트워크의 핵심

단계별 이해

  1. 프레임 구조부터 파악하기
    이더넷의 기본은 프레임입니다. Preamble → MAC 주소 → EtherType → Payload → FCS 순서를 먼저 이해하세요. EtherType ≥ 0x0600이면 Ethernet II, 그보다 작으면 802.3 프레임입니다.
  2. PHY-MAC 연결 이해하기
    NIC 내부에서 MAC 계층이 프레임을 처리하고, PHY 칩이 실제 전기/광 신호로 변환합니다. ethtool eth0으로 현재 링크 속도와 PHY 상태를 확인할 수 있습니다.
  3. 커널 수신 경로 따라가기
    케이블 → NIC DMA → IRQ → napi_schedule() → NAPI poll → eth_type_trans()netif_receive_skb() 순서로 프레임이 커널에 전달됩니다. 이 흐름이 이더넷 드라이버의 핵심입니다.
  4. 오프로드와 성능 튜닝 적용하기
    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 프레임워크로 구현

역사와 진화

이더넷의 발전 과정은 컴퓨터 네트워킹 역사 그 자체입니다.

연도표준/기술속도매체의의
1973Xerox Ethernet (실험)2.94 Mbps동축 케이블Robert Metcalfe, Xerox PARC에서 최초 구현
1980DIX Ethernet (v1.0)10 Mbps동축 (Thick)DEC-Intel-Xerox 공동 표준, EtherType 필드 도입
1983IEEE 802.3 (10BASE5)10 MbpsThick 동축첫 IEEE 표준화, CSMA/CD 공식 규정
198510BASE2 (Thin Ethernet)10 MbpsThin 동축 (RG-58)저비용 동축, 185m 세그먼트
199010BASE-T10 MbpsUTP Cat3트위스트 페어 혁명, 스타 토폴로지 전환
1995802.3u (Fast Ethernet)100 MbpsUTP Cat5 / 광100BASE-TX, Auto-Negotiation 도입
1998802.3z (Gigabit Ethernet)1 Gbps광섬유1000BASE-SX/LX, 8B/10B 부호화
1999802.3ab1 GbpsUTP Cat5e1000BASE-T, PAM-5 4쌍 전송
2002802.3ae (10GbE)10 Gbps광섬유CSMA/CD 사실상 폐기, 전이중 전용
2006802.3an (10GBASE-T)10 GbpsUTP Cat6a구리선 10G, LDPC 부호화
2010802.3ba40/100 Gbps광섬유다중 레인(4×10G, 10×10G, 4×25G)
2016802.3by (25GbE)25 GbpsSFP28서버 연결 최적 대역폭
2017802.3bs200/400 Gbps광섬유PAM4 변조, 데이터센터 스파인
2024802.3df800 Gbps/1.6 Tbps광섬유AI 클러스터, 100G 레인 기술
1973 2.94M 1983 10M 1995 100M 1999 1G 2002 10G 2010 100G 2017 400G 2024 800G Xerox 10BASE5 Fast Eth GbE 10GbE 40/100G 200/400G 800G 이더넷 속도 진화 타임라인 (1973 ~ 2024) 공유 매체 + CSMA/CD 전이중 스위칭 다중 레인 + PAM4

CSMA/CD와 충돌 도메인

초기 이더넷의 핵심 프로토콜인 CSMA/CD(Carrier Sense Multiple Access / Collision Detection)는 공유 매체에서의 다중 접근 문제를 해결합니다.

알고리즘 단계

  1. Carrier Sense — 전송 전 매체가 유휴 상태인지 확인
  2. Transmit — 유휴 시 프레임 전송 시작
  3. Collision Detection — 전송 중 충돌 감지 시 jam 신호(32비트) 발송
  4. Backoff — Binary Exponential Backoff 알고리즘으로 재전송 지연
    • n번째 충돌 시: 0 ~ 2min(n,10)-1 슬롯 중 랜덤 선택
    • 슬롯 시간: 10 Mbps에서 51.2 μs (512 bit times)
    • 16번 충돌 시 전송 포기
Binary Exponential Backoff 수학: n번째 충돌 시 대기 시간은 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)으로 캡됩니다.
현대 이더넷과 CSMA/CD: 802.3ae(10GbE) 이후 표준은 전이중(Full-Duplex) 전용이므로 CSMA/CD가 적용되지 않습니다. 하지만 반이중(Half-Duplex) 모드가 여전히 사양에 존재하며, 리눅스 커널의 ethtool에서도 duplex 설정을 확인할 수 있습니다.

충돌 도메인 vs 브로드캐스트 도메인

구분충돌 도메인브로드캐스트 도메인
정의동시 전송 시 충돌이 발생하는 범위브로드캐스트 프레임이 도달하는 범위
분리 장비스위치, 브릿지 (포트별 분리)라우터, VLAN
허브모든 포트가 하나의 충돌 도메인모든 포트가 하나의 브로드캐스트 도메인
스위치포트별 독립 충돌 도메인전체가 하나의 브로드캐스트 도메인
CSMA/CD 알고리즘 흐름도 프레임 전송 대기 Carrier Sense 매체 유휴? Busy 대기 (IFG) Idle 프레임 전송 충돌 감지? Collision? No 전송 성공 Yes Jam 신호 32비트 전송 재시도 < 16? n < 16? No 전송 포기 Yes Backoff 대기 0~2^min(n,10)-1 슬롯 IFG(Inter-Frame Gap): 96 bit times (9.6us@10M, 0.96us@100M) | 슬롯 시간: 512 bit times (51.2us@10M) | Jam: 32 bits

프레임 구조

이더넷 프레임은 여러 변형이 존재합니다. 가장 널리 사용되는 Ethernet II(DIX)와 IEEE 802.3 프레임을 비교합니다.

이더넷 프레임 구조 비교 Ethernet II (DIX) Preamble 7 bytes SFD 1 byte Dst MAC 6 bytes Src MAC 6 bytes EtherType 2 bytes Payload (데이터) 46 ~ 1500 bytes FCS 4 bytes IEEE 802.3 + LLC/SNAP Preamble 7 bytes SFD 1 byte Dst MAC 6 bytes Src MAC 6 bytes Length ≤1500 LLC 3 bytes SNAP 5 bytes Payload 38 ~ 1492 bytes FCS 4 bytes 802.1Q VLAN Tagged Dst MAC 6 bytes Src MAC 6 bytes TPID 0x8100 TCI 2 bytes EtherType 2 bytes Payload 42 ~ 1500 bytes FCS 4 bytes EtherType/Length 판별: 값 ≥ 0x0600 → EtherType (Ethernet II), 값 ≤ 0x05DC → Length (802.3)

주요 EtherType 값

EtherType프로토콜커널 상수
0x0800IPv4ETH_P_IP
0x0806ARPETH_P_ARP
0x8100802.1Q VLANETH_P_8021Q
0x86DDIPv6ETH_P_IPV6
0x8847MPLS UnicastETH_P_MPLS_UC
0x88A8802.1ad (QinQ)ETH_P_8021AD
0x88CCLLDPETH_P_LLDP
0x88F7PTP (IEEE 1588)ETH_P_1588
0x8906FCoEETH_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
주의: Jumbo Frame은 경로상 모든 장비(NIC, 스위치, 라우터)에서 지원해야 합니다. 중간에 MTU가 다르면 단편화나 패킷 드롭이 발생합니다.

물리 계층 (PHY)

이더넷 PHY는 MAC이 만든 디지털 데이터를 실제 전기·광 신호로 변환하고, 링크 속도·듀플렉스·pause를 협상하며, 선로 상태를 감시하는 계층입니다. 이 문서에서는 PHY를 요약만 다루고, MDIO/Clause 22·45, phylib/phylink, Device Tree, 보드 지연 보상, 실전 장애 대응은 이더넷 PHY (Physical Layer) 전용 문서로 분리했습니다.

PHY 상세 문서: 이더넷 PHY (Physical Layer)에서 MAC-PHY 경계, MDIO 레지스터, Auto-Negotiation 규격, RGMII/SGMII/USXGMII 차이, phy-mode 설계, phylib/phylink 수명주기, 링크 디버깅을 깊게 다룹니다.
구성요약 역할대표 이슈
MAC프레임, DMA, 큐, 통계 처리TX timeout, queue hang
PHY부호화, 직렬화, 링크 협상, 신호 송수신링크 불안정, CRC 증가
MDIOPHY 레지스터 관리 버스PHY ID 불일치, 설정 읽기 실패
매체케이블, 모듈, magnetics, 상대편 포트거리 민감, 속도 강등
RGMII 지연 모드 주의: RGMII는 TXC/RXC 클럭에 필요한 2ns 지연을 MAC, PHY, PCB 중 정확히 한 곳에서만 넣어야 합니다. rgmii-id 설정과 보드 지연을 동시에 쓰면 CRC 오류와 간헐적 링크 다운이 흔하게 발생합니다.

Auto-Negotiation

Auto-Negotiation은 양쪽 PHY가 지원 속도, 듀플렉스, pause 같은 능력을 교환해 최종 링크 모드를 결정하는 절차입니다. 구리 PHY는 주로 Clause 28 FLP, SerDes 기반 연결은 Clause 37/73 in-band status를 사용합니다.

# 현재 링크 협상 결과
ethtool eth0

# 자동 협상 끄고 강제 설정
ethtool -s eth0 speed 1000 duplex full autoneg off

# 상세 PHY 문서 참고: Clause 28/37/73, advertisement, EEE, 트러블슈팅

phylink는 MAC, PHY, PCS, SFP 모듈, fixed-link를 하나의 정책 계층으로 묶어 주는 프레임워크입니다. 외부 PHY 하나만 단순 연결하는 경우보다, SFP 핫플러그, SerDes 모드 전환, in-band status가 필요한 현대 NIC/SoC에서 특히 중요합니다.

/* 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_opsethtool 유틸리티의 백엔드입니다.

/* 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 설정 변경 */
};

패킷 송수신 경로

이더넷 프레임이 커널에서 처리되는 핵심 경로입니다.

이더넷 프레임 수신 경로 (RX Path) 이더넷 케이블 NIC Hardware MAC Filter → DMA IRQ napi_schedule() NAPI poll() RX Ring 소비 skb 할당 build_skb() / napi_alloc eth_type_trans() EtherType 판별 + pkt_type napi_gro_receive() GRO 병합 시도 netif_receive_skb() 프로토콜 핸들러 디스패치 프로토콜 핸들러 ip_rcv() (0x0800) ipv6_rcv() (0x86DD) arp_rcv() (0x0806) TC ingress 트래픽 제어 (선택) XDP NAPI 이전 처리 이더넷 프레임 송신 경로 (TX Path) User Space send() / write() tcp_sendmsg() skb 생성, 세그먼트 분할 ip_output() IP 헤더 + 라우팅 dev_queue_xmit() eth_header() 이더넷 헤더 TC qdisc 큐잉/스케줄링 TSO / GSO 대형 세그먼트 → MTU 분할 TX Checksum CHECKSUM_PARTIAL 설정 ndo_start_xmit() 드라이버 TX 진입점 TX Ring Buffer DMA descriptor 매핑 Doorbell MMIO Write NIC Hardware DMA Read → PHY 전송 TX 완료 IRQ → skb 해제 consume_skb() / napi_consume_skb() BQL (Byte Queue Limit) bufferbloat 방지, 큐 깊이 제한 XPS (Transmit Packet Steering) CPU → TX Queue 매핑

하드웨어 오프로드

현대 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 Pause802.3x양쪽 모두 Pause 전송 가능한 포트 혼잡 시 전체 링크 중단
Asymmetric Pause802.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 활성화
ICE 802.3x 흐름 제어 주의: Intel E810(ice)은 기본적으로 Pause 프레임이 비활성화됩니다. 802.3x Pause를 사용하려면 양측 모두 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
DCBX802.1QazDCB 파라미터 자동 협상 (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-LLDPlldpad 데몬이 관리유연한 정책 제어, 다중 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
ICE DCB 핵심 제약: ICE에서 DCB를 운영할 때 TC0(Traffic Class 0)은 반드시 존재해야 합니다. TC0을 제거하거나 대역폭 0%로 설정하면 드라이버가 설정을 거부합니다. 또한 FW-LLDP 모드에서 lldpad를 동시에 구동하면 LLDPDU 충돌이 발생하므로 한쪽을 반드시 비활성화하세요.

VLAN과 QinQ

IEEE 802.1Q VLAN 태깅은 하나의 물리적 이더넷 링크에서 논리적 네트워크를 분리합니다.

VLAN 태그 구조 (4바이트)

필드비트설명
TPID16Tag Protocol Identifier (0x8100)
PCP3Priority Code Point (QoS 우선순위 0~7)
DEI1Drop Eligible Indicator
VID12VLAN 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
ICE QinQ 제한사항: Intel E810(ice)에서 QinQ(802.1ad) 사용 시 다음 제약이 있습니다:
  • 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 (802.3az) 상태 전이 Active 전체 전력, 전송 중 LPI Sleep 저전력 유휴 Wake 복귀 중 (Tw) 유휴 감지 (Ts) 전송 필요 복귀 완료 → Active 주기적 Refresh
# EEE 상태 확인
ethtool --show-eee eth0

# EEE 비활성화 (지연 민감 환경)
ethtool --set-eee eth0 eee off

# EEE 활성화 (1GbE만)
ethtool --set-eee eth0 eee on advertise 0x8
성능 참고: EEE의 LPI→Active 복귀에 수 마이크로초 지연이 발생합니다. 지연에 민감한 환경(금융 트레이딩, 실시간 시스템)에서는 EEE를 비활성화하는 것이 좋습니다.

TSN (Time-Sensitive Networking)

IEEE 802.1 TSN 태스크 그룹은 이더넷 위에 확정적 지연(Deterministic Latency)과 시간 동기화를 구현하는 표준 집합입니다. 산업 자동화, 자동차, 방송 분야에서 전용 필드버스를 대체합니다.

핵심 TSN 표준

표준이름기능
802.1ASgPTP (Generalized PTP)네트워크 전체 시간 동기화 (<1 μs 정밀도)
802.1QbvTime-Aware Shaper (TAS)시간 기반 게이트 제어, 트래픽 클래스별 전송 시간대 할당
802.1Qbu/802.3brFrame Preemption우선순위 높은 프레임이 낮은 프레임 전송을 중단 가능
802.1CBFRER (Frame Replication and Elimination)프레임 복제로 무손실 전송 보장
802.1QciPer-Stream Filtering and Policing스트림별 필터링/폴리싱
802.1QccStream Reservation Protocol경로/대역폭 예약 관리
TSN vs 일반 이더넷: 일반 이더넷은 Best-Effort 전달만 보장하여 지연과 지터(jitter)가 불확실합니다. TSN은 시간 동기화(802.1AS), 게이트 제어(802.1Qbv), 프레임 선점(802.1Qbu)을 조합하여 확정적 지연을 달성합니다. 산업 환경에서 전용 필드버스(PROFIBUS, CAN 등)를 TSN 이더넷으로 대체하면 단일 물리 네트워크에서 실시간 제어 트래픽과 일반 IT 트래픽을 공존시킬 수 있습니다.

리눅스 TSN 지원

TSN TAS (802.1Qbv) Gate Control 타임라인 시간 0 300us 600us 1ms (사이클) TC0 (Critical) OPEN (S=01) CLOSED CLOSED TC1 (Scheduled) CLOSED OPEN (S=02) CLOSED TC2 (Best Effort) CLOSED CLOSED OPEN (S=04) Guard Band (전환 보호) 각 슬롯에서 해당 TC만 전송 가능 → 확정적 지연 보장
# 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 RTL2 (EtherType 0x8892)~1 msRaw socket / AF_PACKET
PROFINET IRTL2 + HW 스케줄링31.25 μsTSN + 전용 NIC
EtherCATL2 (EtherType 0x88A4)~50 μsIgH EtherCAT Master
EtherNet/IPTCP/UDP (CIP)~1 ms표준 소켓 API
Modbus/TCPTCP (포트 502)~10 ms표준 소켓 API
OPC UA TSNTSN + UDP<1 msopen62541 + 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로 식별됩니다.

MACsec 프레임 구조 (IEEE 802.1AE) 원본 Ethernet II: Dst MAC 6B Src MAC 6B EtherType 2B Payload (평문) 46~1500B FCS 4B MACsec 적용 MACsec 프레임: Dst MAC 6B Src MAC 6B SecTAG 0x88E5 + SCI + AN + PN EtherType 원본 2B Secure Data (암호문) AES-GCM-128/256 암호화 ICV 8~16B 인증 태그 FCS 4B SecTAG 구성: MACsec EtherType(0x88E5, 2B) | TCI/AN(1B) | SL(1B) | PN(4B) | SCI(8B, 선택) = 8~16 바이트 SCI = MAC주소(6B) + Port ID(2B) PN = 패킷 넘버 (리플레이 방지)

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에서 자동 파생
MKA 키 교환 및 MACsec 세션 수립 Node A (Key Server) Node B 사전 공유: CAK + CKN (양단 동일) ① MKPDU 교환 (EAPoL) ② 피어 검증 (ICK로 ICV 확인) ③ Key Server 선출 (낮은 우선순위 = 서버) ④ SAK 배포 (KEK로 암호화) ⑤ MACsec 보안 채널 활성화 키 계층 구조 CAK (마스터) ├ ICK (무결성) ├ KEK (키 암호화) └ SAK (데이터 암호화)

MACsec 동작 모드

모드암호화무결성용도
GCM-AES-128OO기본 모드 (대부분 HW 지원)
GCM-AES-256OO높은 보안 요구 (일부 NIC)
GCM-AES-XPN-128/256OO확장 PN (고속 링크, 64비트 PN)
Integrity OnlyXO무결성만 검증 (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
MACsec HW 오프로드: MACsec를 소프트웨어에서 처리하면 CPU 부하가 상당합니다(10GbE에서 단일 코어의 30~50%). Intel E810(ice), Mellanox ConnectX-6 Dx 이상은 하드웨어 MACsec 오프로드를 지원하여 라인 레이트 암호화가 가능합니다. 리눅스 5.12+에서 offload mac 옵션으로 활성화합니다.
MACsec vs IPsec: MACsec는 hop-by-hop(링크 단위) 암호화이므로 스위치에서 복호화→재암호화가 필요합니다. 엔드투엔드 암호화가 필요하면 IPsec/WireGuard를 사용하세요. MACsec의 장점은 모든 L2 프레임(ARP, LLDP, STP 등)을 보호한다는 점입니다. 데이터센터 내 서버-스위치 간 도청 방지에 특히 효과적입니다.

SR-IOV와 이더넷 가상화

SR-IOV(Single Root I/O Virtualization, PCI-SIG 규격)는 하나의 물리 NIC(PF, Physical Function)에서 다수의 가상 NIC(VF, Virtual Function)를 생성하여, 가상머신(VM)이나 컨테이너에 직접 할당할 수 있게 합니다. 하이퍼바이저의 가상 스위치를 우회하므로 네이티브에 가까운 성능을 달성합니다.

SR-IOV 아키텍처: PF/VF와 VM/컨테이너 연결 Host OS / Hypervisor PF Driver ice/mlx5_core OVS / Bridge (선택적) eSwitch HW 스위칭 (switchdev) VF0 repr VF1 repr VF2 repr VM 1 VF0 드라이버 VM 2 VF1 드라이버 DPDK 컨테이너 VF2 (VFIO) 물리 NIC (PCIe SR-IOV 지원) PF VF0 VF1 VF2 ... VF(N-1) (최대 128~256)

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
SR-IOV 성능 비교:
  • 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), 유저스페이스 직접 처리, 커널 우회
SR-IOV 주의사항: VF를 VM에 할당하면 라이브 마이그레이션이 불가능합니다(VF는 물리 PCIe 디바이스). Mellanox ConnectX 시리즈는 switchdev 모드에서 VF representor를 OVS에 연결하여 마이그레이션을 지원하는 방식을 제공합니다. 또한 IOMMU 그룹 단위로 할당되므로, 동일 IOMMU 그룹의 모든 디바이스가 함께 할당됩니다.

DSA (Distributed Switch Architecture)

DSA는 리눅스 커널의 이더넷 스위치 칩 추상화 프레임워크입니다. SoC에 내장되거나 MDIO/SPI로 연결된 이더넷 스위치(Marvell, Microchip, Realtek 등)를 표준 net_device로 노출하여, VLAN, 브릿지, STP 등 기존 리눅스 네트워크 도구로 스위치를 제어할 수 있게 합니다.

DSA (Distributed Switch Architecture) 구조 Host CPU / SoC MAC (eth0) DSA master dev CPU port (Tagged) 이더넷 스위치 칩 (예: Marvell 88E6352) Port 0 lan0 Port 1 lan1 Port 2 lan2 Port 3 lan3 CPU Port (to Host) DSA (cascade) PC / AP IP Phone Camera Sensor lan0~lan3은 독립 net_device → ip/bridge/tc 명령으로 직접 제어 | VLAN/FDB/MDB HW 오프로드 지원

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>; };
#         };
#     };
# };
DSA 지원 스위치 칩: Marvell 88E6xxx 시리즈, Microchip KSZ9477/KSZ9897/LAN937x, Realtek RTL8365MB/RTL8366, MediaTek MT7530/MT7531, Qualcomm QCA8K, NXP SJA1105(TSN 지원). Device Tree 또는 ACPI에서 스위치를 기술하면 커널이 자동으로 각 포트를 net_device로 생성합니다.

AF_XDP와 고성능 패킷 처리

AF_XDP(eXpress Data Path 소켓)는 리눅스 커널 4.18+에서 도입된 고성능 패킷 처리 인터페이스입니다. XDP 프로그램이 NIC에서 수신한 패킷을 커널 네트워크 스택을 완전히 우회하여 유저스페이스 애플리케이션에 제로카피로 전달합니다.

AF_XDP 제로카피 패킷 경로 NIC Hardware RX DMA → UMEM XDP 프로그램 (eBPF, 드라이버 내) XDP_REDIRECT 커널 스택 (우회됨) redirect AF_XDP Socket (XSK) RX Ring ← Fill Ring TX Ring → Completion Ring UMEM (공유 메모리 영역) 사용자/커널 공유 패킷 버퍼 | 프레임 크기: 2048/4096B | 제로카피: NIC DMA 직접 접근 DMA mmap User App poll() / busy-poll 패킷 처리 AF_XDP 4-Ring 구조 Fill Ring (User→Kern) RX Ring (Kern→User) TX Ring (User→Kern) Completion (Kern→User)

AF_XDP 동작 모드

모드성능요구 사항설명
Zero-Copy최고 (~25 Mpps)드라이버 지원 필수NIC DMA가 UMEM에 직접 쓰기, 복사 없음
Copy Mode중간 (~5 Mpps)모든 XDP 드라이버커널이 RX 버퍼에서 UMEM으로 복사
SKB Mode낮음 (~2 Mpps)XDP genericskb 할당 후 처리, 호환성 최대
# 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
AF_XDP vs DPDK: AF_XDP는 커널 BPF 인프라 위에서 동작하여 커널 업데이트와 호환성이 좋고, 일부 큐만 XDP로 리다이렉트하여 나머지는 일반 커널 스택이 처리하는 하이브리드 구성이 가능합니다. DPDK는 NIC 전체를 유저스페이스에서 관리하므로 더 높은 절대 성능이 가능하지만, 커널 네트워크 기능(iptables, tc 등)을 사용할 수 없습니다.

성능 튜닝

이더넷 네트워크 성능을 최적화하는 주요 커널/드라이버 파라미터입니다.

링 버퍼 최적화

TX/RX Descriptor Ring Buffer 구조 RX Ring Desc 0 Desc 1 Desc 2 Desc 3 ▼ NIC DMA (Producer) ▲ NAPI poll (Consumer) NIC HW DMA Engine 시스템 메모리 skb 데이터 버퍼 완료 IRQ napi_schedule TX Ring Desc 0 Desc 1 Desc 2 Desc 3 ▼ Driver (Producer) ▲ NIC HW (Consumer) dev_queue_xmit skb → descriptor Doorbell MMIO Write NIC 전송 DMA Read Descriptor 구조 • buffer_addr: 데이터 버퍼의 물리 주소 (DMA 가능) • length: 버퍼 크기 / 수신 패킷 길이 • status/flags: DD(Done), EOP(End of Packet), VLAN tag 등 • vlan/checksum: VLAN ID, HW 체크섬 결과 ⚠ RX Ring이 가득 차면 → rx_missed_errors ⚠ TX Ring이 가득 차면 → netif_stop_queue() ✓ NAPI poll이 Ring을 비워야 새 패킷 수신 가능 ✓ TX 완료 IRQ에서 skb 해제 (consume_skb)
# 링 버퍼 현재 크기 확인
ethtool -g eth0

# 링 버퍼 최대로 설정 (패킷 드롭 방지)
ethtool -G eth0 rx 4096 tx 4096

# 인터럽트 병합 (지연 vs 처리량 트레이드오프)
ethtool -C eth0 adaptive-rx on adaptive-tx on
Adaptive Coalescing: adaptive-rx on을 사용하면 드라이버가 트래픽 패턴에 따라 인터럽트 병합 파라미터를 자동 조절합니다. 저부하 시 지연을 최소화하고, 고부하 시 인터럽트 수를 줄여 CPU 사용률을 낮춥니다. Intel igb/ixgbe/ice, Mellanox mlx5 등 주요 드라이버가 지원합니다.
Interrupt Coalescing 전략 비교 No Coalescing (IRQ Storm) 시간 패킷 1개마다 IRQ 발생 지연: 최소 (~0 us) CPU: 매우 높음 고부하 시 CPU 포화 Static Coalescing 시간 4 pkts 4 pkts rx-usecs / rx-frames 고정 지연: 중간 (설정값 고정) CPU: 중간 저부하 시 불필요한 지연 Adaptive Coalescing 시간 1p 8 pkts 트래픽에 따라 자동 조절 저부하: 낮은 지연 고부하: 낮은 CPU 권장 (adaptive-rx on)
# 멀티큐 확인
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 7410G/25G/40G~50 ns단일 비트 버스트 (11비트)~2.6%
RS-FEC (Reed-Solomon)802.3 Clause 91/10825G/50G/100G+~100 ns다중 심볼 오류 (최대 ~7%)~2.7%
RS-FEC (544,514)802.3 Clause 11950G/100G/200G/400G+ (PAM4)~100 ns더 강한 정정 (PAM4용)~5.8%
없음 (No FEC)-10G 이하0없음0%
FEC 동작 원리: RS-FEC (Reed-Solomon) 송신 MAC 원본 데이터 FEC Encoder RS(528,514) 또는 RS(544,514) 채널 (전송 매체) 광섬유 / 구리선 BER: ~10⁻⁵ (비트 오류) FEC Decoder 오류 감지 + 복원 BER → 10⁻¹² 이하 RX RS-FEC 인코딩 상세 입력: 514 심볼 (데이터) 514 심볼 (원본 데이터) 출력: 528 심볼 (데이터 + 패리티) 514 심볼 (데이터) 14 패리티 RS(528,514): 최대 7 심볼 오류 정정 (14 패리티 ÷ 2) RS(544,514): 최대 15 심볼 오류 정정 (30 패리티 ÷ 2) PAM4는 NRZ 대비 SNR이 ~9.5dB 낮아 FEC 필수

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 모드 일치 확인
FEC 불일치 문제: FEC 모드가 링크 양단에서 일치하지 않으면 링크 자체가 올라오지 않습니다. 25GbE 이상에서 링크가 올라오지 않을 때 가장 먼저 FEC 설정을 확인하세요. 일반적인 조합: 10GbE(No FEC 또는 BaseR), 25GbE(RS-FEC 또는 BaseR), 100GbE+(RS-FEC 필수).

이더넷 케이블과 커넥터 가이드

물리 계층의 성능은 케이블과 커넥터에 크게 의존합니다. 올바른 케이블 선택은 안정적인 이더넷 링크의 기본입니다.

UTP 케이블 카테고리 비교

카테고리최대 주파수최대 속도최대 거리차폐용도
Cat5100 MHz100 Mbps100mUTP레거시 (사용 지양)
Cat5e100 MHz1 Gbps / 2.5 Gbps100mUTP일반 사무/가정용
Cat6250 MHz5 Gbps(100m) / 10G(55m)55~100mUTP/STP기업 환경, PoE+
Cat6a500 MHz10 Gbps100mF/UTP, U/FTP10GbE 표준, 데이터센터
Cat7600 MHz10 Gbps100mS/FTP (전쌍 차폐)EMI 환경, 산업용
Cat7a1000 MHz10 Gbps (40G@50m)50~100mS/FTP미래 대비, 특수 환경
Cat82000 MHz25/40 Gbps30mS/FTP데이터센터 스위치 간
RJ45 T568B 핀 배치와 이더넷 핀 사용 RJ45 커넥터 (T568B) Pin 1 주/백 Pin 2 주황 Pin 3 녹/백 Pin 4 파랑 Pin 5 파/백 Pin 6 녹색 Pin 7 갈/백 Pin 8 갈색 속도별 핀 사용 10/100BASE-T (2쌍 사용): TX+: Pin 1 (주/백) TX-: Pin 2 (주황) RX+: Pin 3 (녹/백) RX-: Pin 6 (녹색) Pin 4,5,7,8: 미사용 (PoE 전력 가능) 1000BASE-T / 2.5G~10G (4쌍 전부): Pair A: Pin 1,2 Pair B: Pin 3,6 Pair C: Pin 4,5 Pair D: Pin 7,8 4쌍 양방향 동시 전송 (echo cancellation) PAM-5(1G), DSQ128(2.5G~10G) 변조 PoE (Power over Ethernet) 전력 공급 Type 1 (802.3af): 15.4W | Type 2 (802.3at): 30W | Type 3 (802.3bt): 60W | Type 4 (802.3bt): 90W — 4쌍 모두 사용

케이블 테스트 및 진단

# 케이블 테스트 (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

유형정식 명칭매체최대 거리소비 전력용도
DACDirect Attach Copper트윈악스 구리5~7m매우 낮음 (~0.1W)ToR-서버 단거리
AOCActive Optical Cable광섬유 (일체형)30~100m~1W랙 간 중거리
트랜시버+패치코드SFP/QSFP + LC/MPO광섬유 (분리형)300m~40km~1.5W장거리, 유연한 구성
데이터센터 케이블 선택 기준: 서버-ToR 스위치(~3m)는 DAC이 비용과 전력 면에서 최적입니다. ToR-Spine(~30m)은 AOC 또는 SR 트랜시버, Spine-Core(~300m 이상)는 LR/ER 트랜시버를 사용합니다. 25GbE 이상에서는 반드시 FEC 호환성을 확인하세요.

FCS와 CRC-32

이더넷 프레임의 마지막 4바이트 FCS(Frame Check Sequence)는 CRC-32 다항식으로 계산됩니다.

/* 커널 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 동기화 메시지 교환 (IEEE 1588) Master Slave ① Sync (t1) t1 기록 ② Follow_Up (t1 전달) t2 기록 ③ Delay_Req (t3) t3 기록 ④ Delay_Resp (t4 전달) t4 기록 오프셋 계산: offset = ((t2-t1)-(t4-t3))/2 delay = ((t2-t1)+(t4-t3))/2 시간 →
# 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 브로드캐스트 도메인라우터는 브로드캐스트를 기본적으로 넘기지 않으므로 중계나 포워딩 설계가 필요합니다.
WoL 웨이크 경로 관리자 시스템 wakeonlan / ether-wake 대상 MAC을 포함한 매직 패킷 송신 L2 스위치 / 브로드캐스트 같은 세그먼트에서는 브로드캐스트 또는 직접 유니캐스트 전달 대상 NIC 대기 전원 유지 PHY/MAC 일부만 활성 패턴 매처 동작 웨이크 이벤트 매직 패킷 일치 PME# 또는 ACPI 신호 칩셋에 전달 플랫폼 재개 BIOS/UEFI 허용 펌웨어 확인 후 CPU/메모리 복귀 브로드캐스트는 보통 라우터를 넘지 않습니다. 원격 사이트에서 WoL을 쓰려면 중계 호스트, Directed Broadcast, VPN 같은 별도 설계가 필요합니다.

매직 패킷은 데이터 페이로드 어디에 있어도 되지만, 일반적으로는 같은 L2 세그먼트에서 브로드캐스트 주소로 보내는 방식이 가장 단순합니다. NIC는 운영체제가 거의 꺼진 상태에서도 이 패턴을 비교할 수 있도록 최소한의 수신 경로를 유지합니다.

WoL Magic Packet 구조 FF:FF:FF:FF:FF:FF 동기화 (6바이트) Target MAC #1 AA:BB:CC:DD:EE:FF Target MAC #2 AA:BB:CC:DD:EE:FF ··· Target MAC #16 AA:BB:CC:DD:EE:FF 총 102바이트: 동기화 6B + (Target MAC 6B × 16) = 6 + 96 NIC은 저전력 상태에서도 패턴을 감시하며, 일치 시 플랫폼에 웨이크 이벤트를 전달합니다. SecureOn은 마지막에 6바이트 비밀번호를 더하지만, 모든 NIC가 지원하는 기능은 아닙니다.
WoL이 자주 실패하는 이유:
  • 펌웨어 정책: 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 FrameMTU 불일치, 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 관련 문제를 디버깅하고 커스텀 드라이버를 작성하는 데 큰 도움이 됩니다. 최소한의 이더넷 드라이버 스켈레톤을 통해 핵심 콜백과 초기화 흐름을 살펴봅니다.

이더넷 드라이버 초기화 및 핵심 콜백 흐름 module_init() pci_register_driver .probe = my_probe() my_probe() pci_enable_device() pci_request_regions() alloc_etherdev() net_device 할당 + 이더넷 기본값 netdev_ops 설정 .ndo_open, .ndo_stop .ndo_start_xmit, .ndo_set_mac_address netif_napi_add() NAPI poll 등록 register_netdev() 핵심 런타임 콜백 ndo_open() IRQ 할당, Ring 할당, NAPI 활성화 ndo_start_xmit() skb→TX descriptor, DMA 매핑 napi_poll() RX Ring 소비, skb 빌드, GRO ndo_stop() NAPI 비활성화, IRQ 해제, Ring 해제 ethtool_ops 통계, 링크 설정, 링 버퍼 제어 ndo_set_rx_mode() 프로미스큐어스, 멀티캐스트 필터 ndo_change_mtu() MTU 변경, 버퍼 재할당

최소 드라이버 스켈레톤

/* 최소 이더넷 드라이버 구조 (개요) */
#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 불일치

증상: 작은 패킷은 정상이지만, 대용량 전송(SCP, NFS 등)이 극도로 느리거나 멈춥니다. 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 오류)

증상: tcpdump에서 "bad checksum" 표시, 패킷 캡처 시 TCP checksum이 틀림.
원인: 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 불일치로 링크 미연결

증상: 25GbE/100GbE에서 케이블을 연결해도 링크가 올라오지 않습니다. ethtool eth0에서 "Link detected: no".
원인: FEC 모드가 양단에서 다릅니다 (예: 한쪽 RS-FEC, 다른 쪽 No FEC).
해결: 양단 FEC 모드를 동일하게 맞추거나 auto로 설정합니다.
ethtool --show-fec eth0
ethtool --set-fec eth0 encoding auto

5. RGMII 지연 이중 적용

증상: 임베디드 보드에서 GbE 링크가 올라오지만 패킷 손실, CRC 오류가 빈번합니다. 100Mbps로 폴백하면 정상 동작합니다.
원인: 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 과부하)

증상: 멀티큐 NIC인데 CPU 0만 100%이고, 나머지 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로 인한 지연 증가

증상: 유휴 후 첫 패킷의 지연이 비정상적으로 높습니다 (수 밀리초). Idle 상태에서 갑자기 트래픽이 오면 순간 지연이 급증합니다.
원인: 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 Powerethtool --cable-test
성능 저하ethtool -g Ring 크기ethtool -c CoalescingIRQ affinity, CPU 분산
패킷 드롭ethtool -S rx_missed/no_bufferethtool -G Ring 증가sysctl netdev_budget
높은 CPU 사용률오프로드 확인 ethtool -kRSS 큐 수 확인 ethtool -lGRO/TSO 활성화
지연 변동--show-eee EEE 확인Coalescing 값 조정NUMA/CPU pinning

커널 소스 참조

파일/디렉토리역할
include/uapi/linux/if_ether.h이더넷 상수, struct ethhdr
net/ethernet/eth.ceth_type_trans(), eth_header()
include/linux/ethtool.hethtool_ops, 링크 설정 구조체
net/ethtool/ethtool Netlink 인터페이스 (커널 5.6+)
include/linux/phylink.hphylink 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.cTSN TAS (taprio qdisc)
net/sched/sch_cbs.cTSN CBS (Credit-Based Shaper)
net/sched/sch_etf.cTSN ETF (Earliest TxTime First)
drivers/net/macsec.cMACsec 소프트웨어 구현
include/net/macsec.hMACsec 구조체, offload API
net/dsa/DSA 프레임워크 코어
drivers/net/dsa/DSA 스위치 드라이버 (mv88e6xxx, ksz, sja1105 등)
net/xdp/XDP 코어, AF_XDP 소켓
include/net/xdp_sock.hAF_XDP 소켓 구조체
drivers/net/ethernet/intel/ice/Intel E810 드라이버 (SR-IOV, MACsec, PTP)
drivers/net/ethernet/mellanox/mlx5/Mellanox ConnectX 드라이버 (eSwitch, SR-IOV)
필수 관련 문서: 참고 문서: