eSwitch (Embedded Switch)
eSwitch(embedded Switch)는 SmartNIC/DPU에서 호스트와 VF/SF 간의 네트워크 트래픽을 하드웨어에서 직접 스위칭하는 기능을 제공합니다. switchdev 모드를 통해 TC flower 규칙의 하드웨어 오프로드가 가능하며, OVS-DPDK와 결합하여 가상 스위칭의 성능 병목(Bottleneck) 문제를 해결합니다. 커널 내부 데이터 경로, 핵심 자료구조/API, 운영 환경 튜닝 포인트와 장애 디버깅(Debugging) 절차까지 실무 관점으로 다룹니다.
핵심 요약
- eSwitch — NIC에 내장된 하드웨어 스위치 (PF/VF/SF 간 패킷 라우팅(Routing))
- switchdev 모드 — eSwitch를 커널 브릿지처럼 운영, TC 규칙 HW offload 지원
- Representor — VF/SF를 나타내는 가상 netdev (호스트에서 제어 가능)
- TC flower — 트래픽 분류 규칙 (eSwitch HW로 오프로드됨)
- OVS HW offload — OVS 플로우를 eSwitch에서 직접 처리 (CPU 오버헤드(Overhead) 90%+ 절감)
단계별 이해
- Legacy 모드 이해
기존 SR-IOV 방식. VF는 독립 PCI 함수로 동작하고, PF의 스위칭 기능은 VLAN 태깅만 지원합니다. (자세히 보기) - switchdev 전환
devlink를 통해 eSwitch를 switchdev 모드로 전환하면 PF가 브릿지 역할을 하고, VF가 포트로 동작합니다. (자세히 보기) - Representor 생성
각 VF에 대응하는 representor netdev가 생성됩니다. 호스트에서 이 포트를 통해 VF 트래픽을 제어합니다. - TC flower 규칙 설치
tc 명령어로 representor에 필터 규칙을 설치하면, 드라이버가 이를 eSwitch HW로 변환합니다. - OVS offload 확인
OVS에서_hw-offload=true 설정 후, ovs-appctl로 offloaded 플로우를 확인합니다.
eSwitch 개요
eSwitch (Embedded Switch)는 Mellanox(NVIDIA) SmartNIC와 DPU에 내장된 하드웨어 스위치입니다. 호스트 PCIe 버스(Bus) 위에서 PF(Physical Function)와 VF(Virtual Function), 그리고 SF(Scalable Function) 간의 패킷 스위칭을 NIC 자체에서 수행합니다. 이를 통해 소프트웨어 기반 가상 스위칭의 CPU 오버헤드를 대폭 줄이고, 라인 레이트(초당 패킷 처리) 성능을 달성할 수 있습니다.
실제 사용 시나리오: 하이퍼바이저(Hypervisor) VM 네트워크
eSwitch가 실제 환경(하이퍼바이저)에서 어떻게 동작하는지 보여줍니다.
- Representor는 Host OS (커널)에 있음 — VF를 나타내는 "가상의 케이블"
- VF ↔ Representor는 1:1 매핑(Mapping) — PCIe 버스로 연결됨
- tc 규칙을 representor에 설치 → 드라이버가 VF의 ASIC 테이블에 저장
- eSwitch (ASIC) — VF/PF 간 패킷 스위칭을 하드웨어에서 수행
eSwitch는 두 가지 운영 모드를 지원합니다:
- Legacy 모드: 기존 SR-IOV 방식. VF는 독립 PCI 함수로 동작하고, PF의 스위칭 기능은 기본적인 VLAN 태깅만 지원합니다. (자세히 보기)
- Switchdev 모드: PF를 브릿지처럼 운영하면서 VF/SF 간 트래픽을 eSwitch 하드웨어에서 스위칭합니다. TC(traffic control) 규칙의 하드웨어 오프로드가 핵심입니다.
eSwitch 아키텍처
eSwitch 아키텍처는 호스트 커널, 드라이버, NIC 펌웨어(Firmware)의 3계층으로 구성됩니다. 각 계층이 역할을 분담하여 하드웨어 오프로드를 가능하게 합니다.
아키텍처 개요
eSwitch/switchdev는 다음 3계층 구조로 구성됩니다. 각 벤더는 동일한 아키텍처를 따르지만, 드라이버와 구현은 다릅니다.
NVIDIA/Mellanox (mlx5) 상세 아키텍처
mlx5 드라이버의 상세 구성 요소입니다.
| 컴포넌트 | 설명 | 커널 경로 |
|---|---|---|
| mlx5_core | NIC 기본 드라이버, firmware 관리 | drivers/net/ethernet/mellanox/mlx5/core/ |
| mlx5e | 이더넷 netdev 드라이버 | drivers/net/ethernet/mellanox/mlx5/core/en_*.c |
| mlx5_eswitch | eSwitch 관리 (switchdev 모드) | drivers/net/ethernet/mellanox/mlx5/core/eswitch*.c |
| mlx5e_rep | Representor netdev 드라이버 | drivers/net/ethernet/mellanox/mlx5/core/en_rep.c |
Legacy 모드
Legacy 모드는 eSwitch의 기본 운영 모드입니다. 이 모드에서 eSwitch는 기본적인 VLAN 태깅 기능을 제외한 대부분의 스위칭 기능을 비활성화하고, 전통적인 SR-IOV 방식처럼 VF(Virtual Function)를 독립된 PCI 함수로 동작시킵니다. 이는 하이퍼바이저 기반 가상화(Virtualization) 환경에서 가장 일반적으로 사용되는 설정입니다.
Legacy 모드의 기본 동작
Legacy 모드에서 eSwitch는 "passthrough" 모드로 동작합니다. VF는 PF와 독립적으로 작동하며, 각 VF는 직접 PCIe 버스를 통해 호스트와 통신합니다. PF의 스위칭 기능은 다음으로 제한됩니다:
- VLAN 태깅: IEEE 802.1Q VLAN 헤더의 추가/제거만 HW에서 처리
- 기본 필터링: MAC 주소 기반 필터링 ( whitelist)
- MTU 설정: VF별 최대 전송 단위 관리
Legacy 모드 아키텍처
- VF 직접 할당: VF가 VM에 직접 할당되어 PCIe 함수로 동작
- 스위칭 없음: VF ↔ VF 통신 시 PF를 거치지 않으며, 호스트에서 소프트웨어 브릿지 필요
- 제한된 HW 기능: VLAN 태깅만 HW에서 지원, TC 규칙 offload 불가
- 단순한 설정: SR-IOV 활성화만으로 즉시 사용 가능
Legacy vs Switchdev 모드 비교
| 특징 | Legacy 모드 | Switchdev 모드 |
|---|---|---|
| 스위칭 방식 | Passthrough (VF ↔ PF 직접) | eSwitch HW 스위칭 |
| VF ↔ VF 통신 | SW 브릿지 필요 (CPU overhead) | HW에서 직접 처리 |
| TC Flower Offload | ❌ 미지원 | ✅ HW offload 가능 |
| VLAN 지원 | 기본 VLAN만 | 다양한 VLAN/VXLAN |
| Representor | ❌ 미생성 | ✅ VF당 representor 생성 |
| OVS Offload | ❌ SW 처리만 | ✅ HW offload 가능 |
| 복잡도 | 단순 | 설정 복잡 |
| 성능 (VM↔VM) | CPU 의존 | 라인레이트 |
| conntrack offload | ❌ | ✅ |
| RDMA 지원 | VF RDMA만 | VF RDMA + eSwitch |
Legacy 모드 설정 명령어
# ━━━ Legacy 모드 확인 및 설정 ━━━
# 1. 현재 eSwitch 모드 확인 (기본값: legacy)
devlink dev eswitch show pci/0000:03:00.0
# pci/0000:03:00.0: mode legacy inline-mode transport encap mode: NOTSET
# 2. VF 생성 (Legacy 모드에서)
# Legacy 모드에서는 VF를 생성하면 바로 VM에 할당 가능
echo 4 > /sys/bus/pci/devices/0000:03:00.0/sriov_numvfs
# 3. VF 확인
lspci | grep -i "virtual function"
# 03:00.1 Virtual function
# 03:00.2 Virtual function
# 03:00.3 Virtual function
# 4. VF를 VM에 할당 (libvirt 예시)
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000' bus='0x03' slot='0x00' function='0x1'/>
</source>
</hostdev>
Legacy 모드 사용 시나리오
Legacy 모드는 다음과 같은 상황에서 여전히 유용합니다:
- 단순 VM 네트워크: 각 VM이 외부 네트워크와만 통신하고, VM 간 통신이 필요 없는 경우
- RDMA 직접 할당: VM에 VF를 직접 할당하여 RDMA를 사용해야 하는 경우 (GPUDirect RDMA)
- 기존 호환성: 기존 SR-IOV 설정을 유지하고 싶은 경우 (마이그레이션 호환)
- 제한된 NIC: eSwitch를 지원하지 않는 오래된 NIC에서 SR-IOV를 사용하는 경우
- 빠른 배포: 복잡한 설정 없이 SR-IOV를 빠르게 구성해야 하는 경우
Legacy 모드의 한계
Legacy 모드에서는 다음과 같은 기능이 제한됩니다:
- TC Flower Offload 불가: 커널 TC 규칙을 HW로 오프로드할 수 없어 모든 패킷이 CPU를 경유
- VM 간 통신 성능: VF ↔ VF 통신 시 호스트에서 소프트웨어 브릿지를 거치므로 CPU 오버헤드 발생
- OVS 성능 병목: OVS-DPDK를 사용하더라도 VM ↔ VM 통신은 소프트웨어 처리
- 제한된 네트워크 기능: VLAN만 지원하며, VXLAN, Geneve, conntrack offload 등 고급 기능 미지원
- Representor 부재: VF를 제어할 수 있는 representator 포트가 없어 네트워크 정책 적용 어려움
- 스케일링 제한: 많은 수의 VF를 관리할 때 CPU bottleneck 발생
Legacy 모드에서 Switchdev 모드로 전환
Legacy 모드의 한계를 극복하려면 switchdev 모드로 전환해야 합니다. 전환 과정은 다음과 같습니다:
# ━━━ Legacy → Switchdev 모드 전환 ━━━
# 1. Legacy 모드 상태 확인
devlink dev eswitch show pci/0000:03:00.0
# pci/0000:03:00.0: mode legacy
# 2. 모든 VF 삭제 (필수)
echo 0 > /sys/bus/pci/devices/0000:03:00.0/sriov_numvfs
# 3. switchdev 모드로 전환
devlink dev eswitch set pci/0000:03:00.0 mode switchdev
# 4. 전환 확인
devlink dev eswitch show pci/0000:03:00.0
# pci/0000:03:00.0: mode switchdev
# 5. VF 다시 생성 (이제 representor 생성됨)
echo 4 > /sys/bus/pci/devices/0000:03:00.0/sriov_numvfs
# 6. Representor 확인
ip link show
# enp3s0f0np0 <-- PF (uplink)
# enp3s0f0np0_0 <-- VF0 representor
# enp3s0f0np0_1 <-- VF1 representor
- VF에 할당된 모든 VM을 종료해야 합니다
- 전환 중 네트워크 서비스 중단이 발생합니다
- VF의 MAC 주소가 변경될 수 있습니다
- 전환 후 OVS/브릿지 재구성이 필요합니다
Switchdev → Legacy 역전환
운영 환경에서 switchdev 모드를 사용하다가 legacy 모드로 되돌려야 하는 경우가 있습니다. 롤백(문제 발생 시 원복), 인프라 단순화(OVS·TC 오프로드가 불필요해진 경우), 또는 구형 관리 도구와의 호환성 확보 등이 대표적인 이유입니다. 그러나 역전환은 항상 가능한 것이 아니며, 드라이버·펌웨어 버전·현재 리소스 상태에 따라 지원 여부와 절차가 달라집니다.
드라이버별 역전환 지원 현황
devlink eswitch mode를 통한 역전환 지원은 드라이버마다 다릅니다. 아래 표는 주요 드라이버의 역전환 지원 현황을 정리한 것입니다.
| 드라이버 | NIC/ASIC | 역전환 지원 | 조건 | 비고 |
|---|---|---|---|---|
| mlx5 | ConnectX-5/6/7, BlueField | ✅ 완전 지원 | VF/SF 삭제, TC 규칙 제거, OVS 언바인드 필수 | 가장 성숙한 역전환 구현. SF도 모두 삭제해야 함 |
| ice | E810/E830 | ✅ 지원 | FW ≥ 2.50, VF 삭제 필수 | 구형 FW는 EOPNOTSUPP 반환 |
| bnxt_en | BCM57500 시리즈 | ⚠️ 제한적 | FW 의존, TruFlow 리소스 해제 필요 | FW에서 리소스 해제 실패 시 전환 불가 |
| rocker | 가상 스위치 칩 | ❌ 해당 없음 | — | 고정 switchdev 모드, legacy 개념 없음 |
| mv88e6xxx/DSA | Marvell Link Street | ❌ 해당 없음 | — | DSA 프레임워크, devlink eswitch 미사용 |
devlink dev eswitch 대신 DSA 프레임워크 자체의
포트 추상화(dsa_switch_ops)를 사용하므로 legacy/switchdev 모드 전환이 적용되지 않습니다.
역전환 절차
mlx5·ice 등 역전환을 지원하는 드라이버에서의 표준 절차입니다.
각 단계를 건너뛰면 EBUSY 등의 오류가 발생합니다.
# ━━━ Switchdev → Legacy 역전환 절차 ━━━
# 1. 현재 모드 확인
devlink dev eswitch show pci/0000:03:00.0
# pci/0000:03:00.0: mode switchdev ...
# 2. VM/컨테이너 중지 (VF를 사용하는 모든 게스트)
virsh shutdown vm-with-vf-01
virsh shutdown vm-with-vf-02
# 3. OVS 포트 제거 (representor가 OVS에 연결된 경우)
ovs-vsctl del-port br-phy enp3s0f0np0_0
ovs-vsctl del-port br-phy enp3s0f0np0_1
ovs-vsctl del-port br-phy enp3s0f0np0 # uplink representor
# 4. TC flower 규칙 삭제 (representor에 설치된 규칙)
tc filter del dev enp3s0f0np0_0 ingress
tc filter del dev enp3s0f0np0_1 ingress
tc filter del dev enp3s0f0np0 ingress
# 5. VF 삭제 (sriov_numvfs → 0)
echo 0 > /sys/class/net/enp3s0f0np0/device/sriov_numvfs
# 6. SF 삭제 (mlx5 전용, SF가 있는 경우)
devlink port del pci/0000:03:00.0/32768
devlink port del pci/0000:03:00.0/32769
# 7. Legacy 모드로 전환
devlink dev eswitch set pci/0000:03:00.0 mode legacy
# 8. 전환 확인
devlink dev eswitch show pci/0000:03:00.0
# pci/0000:03:00.0: mode legacy ...
- 모든 VF 게스트(VM/컨테이너(Container))가 중지되었는가?
- OVS/브릿지에서 representor 포트가 제거되었는가?
- TC flower 규칙이 모두 삭제되었는가?
sriov_numvfs가 0인가?- SF(Scalable Function)가 모두 삭제되었는가? (mlx5)
- RDMA/RoCE 연결이 종료되었는가?
전환 실패 오류 코드 및 진단
역전환 시 흔히 발생하는 커널 오류 코드와 원인, 해결 방법입니다.
| 오류 코드 | errno | 원인 | 해결 |
|---|---|---|---|
EBUSY |
-16 | VF/SF/TC 리소스가 아직 활성 상태 | 활성 리소스를 모두 해제한 후 재시도 |
EOPNOTSUPP |
-95 | 드라이버 또는 FW가 역전환 미지원 | FW 업데이트, 또는 대안 사용 |
EINVAL |
-22 | 잘못된 파라미터 또는 이미 legacy 모드 | 현재 모드 확인 후 올바른 명령어 사용 |
# ━━━ 역전환 실패 진단 ━━━
# dmesg에서 eswitch 관련 오류 확인
dmesg | grep -i "eswitch\|esw\|mode change" | tail -20
# devlink 상세 오류 메시지 확인 (verbose 모드)
devlink dev eswitch set pci/0000:03:00.0 mode legacy 2>&1
# 현재 리소스 상태 점검
cat /sys/class/net/enp3s0f0np0/device/sriov_numvfs
devlink port show pci/0000:03:00.0 # SF 포트 목록
tc filter show dev enp3s0f0np0 ingress
ovs-vsctl show | grep enp3s0f0np0
전환 차단 조건
다음 조건 중 하나라도 해당되면 EBUSY가 발생하며 역전환이 차단됩니다.
각 조건별로 정리(해제) 명령어를 함께 제시합니다.
| # | 차단 조건 | 확인 명령어 | 정리 명령어 |
|---|---|---|---|
| 1 | 활성 VF (sriov_numvfs > 0) |
cat /sys/class/net/<PF>/device/sriov_numvfs |
echo 0 > /sys/class/net/<PF>/device/sriov_numvfs |
| 2 | 활성 SF (mlx5 전용) | devlink port show | grep "flavour sf" |
devlink port del pci/<BDF>/<sfnum> |
| 3 | TC flower 규칙 (representor에 설치) | tc filter show dev <rep> ingress |
tc filter del dev <rep> ingress |
| 4 | OVS 브릿지 바인딩 | ovs-vsctl show | grep <rep> |
ovs-vsctl del-port <bridge> <rep> |
| 5 | 활성 RDMA/RoCE 연결 | rdma res show qp |
연결 종료 후 rdma dev로 확인 |
| 6 | vDPA 디바이스 | vdpa dev show |
vdpa dev del <name> |
Legacy 전환이 불가능할 때의 대안
드라이버가 역전환을 지원하지 않거나, 리소스 해제가 불가능한 상황에서 사용할 수 있는 대안을 소개합니다.
| # | 대안 | 적용 상황 | 장점 | 단점 |
|---|---|---|---|---|
| 1 | Switchdev 유지 + representor 무시 | switchdev를 유지해도 무방할 때 | 재부팅/재로드 불필요 | 리소스 약간 낭비, representor netdev 잔존 |
| 2 | 드라이버 모듈 재로드 | 서비스 중단 허용 시 | 강제로 초기(legacy) 상태 복원 | 네트워크 완전 단절, NIC 재초기화 |
| 3 | macvtap으로 VM 네트워킹 대체 | SR-IOV 없이 VM에 네트워크 제공 | VF 불필요, 설정 단순 | 성능 저하 (소프트웨어 경로) |
| 4 | vDPA/virtio로 SR-IOV 대체 | 하드웨어 가속 유지 + legacy 불필요 | 라이브 마이그레이션 지원 | mlx5 전용, 설정 복잡 |
| 5 | devlink reload / FW 리셋 | 소프트웨어 상태 초기화 필요 시 | 모듈 재로드보다 빠름 | 드라이버별 지원 차이, 데이터 경로 중단 |
# ━━━ 대안 2: 드라이버 모듈 재로드 ━━━
# mlx5 예시 — 네트워크 완전 중단됨, 주의!
modprobe -r mlx5_ib mlx5_core
modprobe mlx5_core
# 기본값(legacy)으로 초기화됨
devlink dev eswitch show pci/0000:03:00.0
# pci/0000:03:00.0: mode legacy ...
# ━━━ 대안 5: devlink reload ━━━
# devlink reload로 드라이버 소프트 리셋 (FW 상태 유지)
devlink dev reload pci/0000:03:00.0 action driver_reinit
# 또는 FW까지 리셋:
devlink dev reload pci/0000:03:00.0 action fw_activate
- 긴급 롤백 + 서비스 중단 허용: 대안 2 (모듈 재로드) — 가장 확실한 초기화
- 서비스 중단 최소화: 대안 1 (switchdev 유지) 또는 대안 5 (devlink reload)
- SR-IOV 자체가 불필요: 대안 3 (macvtap) — 가장 단순한 대체
- 하드웨어 가속 유지 필요: 대안 4 (vDPA/virtio) — mlx5 전용
Switchdev 모드 전환
eSwitch를 switchdev 모드로 전환하면 PF가 브릿지 역할을 수행하고, 각 VF에 대응하는 representor 포트가 생성됩니다. 이 모드에서만 TC flower 규칙의 하드웨어 오프로드가 가능합니다.
# ━━━ switchdev 모드 전환 ━━━
# 1. 현재 모드 확인 (기본값: legacy)
devlink dev eswitch show pci/0000:03:00.0
# pci/0000:03:00.0: mode legacy inline-mode transport encap mode: NOTSET
# 2. eSwitch를 switchdev 모드로 전환
devlink dev eswitch set pci/0000:03:00.0 mode switchdev
# 3. 전환 후 모드 확인
devlink dev eswitch show pci/0000:03:00.0
# pci/0000:03:00.0: mode switchdev inline-mode transport encap mode: NOTSET
# 4. VF 생성 (기존 legacy 모드에서 생성된 VF가 있다면 먼저 삭제)
echo 0 > /sys/bus/pci/devices/0000:03:00.0/sriov_numvfs
echo 4 > /sys/bus/pci/devices/0000:03:00.0/sriov_numvfs
# 5. Representor 포트 확인
ip link show
# enp3s0f0np0 <-- PF (uplink)
# enp3s0f0np0_0 <-- VF0 representor
# enp3s0f0np0_1 <-- VF1 representor
# enp3s0f0np0_2 <-- VF2 representor
# enp3s0f0np0_3 <-- VF3 representor
- switchdev 모드 전환 전 모든 VF를 삭제해야 합니다. 기존 VF가 있으면 모드 전환이 거부됩니다.
- 모드 전환은 네트워크 중단을 유발합니다. 유지보수 시간에 진행하세요.
- switchdev 모드에서는 VF가 직접 PF의 브릿지 포트로 동작하므로, VF 간 통신이 eSwitch HW에서 처리됩니다.
Switchdev 모드 아키텍처
Switchdev 모드에서 eSwitch는 완전한 L2 스위치로 동작합니다. PF가 브릿지 역할을 수행하고, 각 VF와 SF는 브릿지의 포트로 연결됩니다. 이 구조에서 모든 패킷이 eSwitch 하드웨어를 통과하면서 TC flower 규칙에 기반한 필터링과 포워딩이 가능합니다.
- PF = 브릿지: PF가 브릿지 마스터 역할을 수행
- VF = 포트: 각 VF가 브릿지의 포트로 연결
- Representor: VF를 대표하는 호스트측 netdev (OVS에 연결)
- Flow Table: TC flower 규칙이 저장되는 ASIC 테이블
- HW 스위칭: 모든 패킷이 eSwitch HW를 통과하여 CPU 오버헤드 없음
Switchdev 내부 동작
Switchdev 모드에서 패킷이 어떻게 처리되는지 상세하게 살펴봅니다. 데이터플로우는 fast-path(하드웨어 처리)와 slow-path(소프트웨어 처리)로 나뉩니다.
Fast-Path (하드웨어 처리)
TC flower 규칙이 설치된 후, 매칭되는 패킷은 CPU 관여 없이 하드웨어에서 직접 처리됩니다:
- 패킷 수신: NIC가 패킷을 버퍼(Buffer)에 수신
- Flow Table 조회: ASIC의 플로우 테이블에서 매칭 규칙 검색 (src/dst IP, port, VLAN, protocol 등)
- 액션 수행: 매칭된 규칙의 액션(drop, redirect, vlan-modify 등)을 HW에서 직접 실행
- 포워딩: 해당 포트로 패킷 전송 (VF, PF, 또는 다른 representor)
Slow-Path (소프트웨어 처리)
플로우 테이블에 규칙이 없거나, 복잡한 액션이 필요한 경우 패킷이 소프트웨어로 전송됩니다:
- 테이블 미스: 플로우 테이블에 매칭 규칙이 없는 경우
- CPU 인터럽트(Interrupt): NIC가 CPU로 패킷을 전송 (MSI-X 인터럽트)
- 커널 처리: softirq 컨텍스트에서 네트워크 스택 처리
- 플로우 학습: OVS/브릿지가 플로우를 분석하여 TC 규칙 생성
- 규칙 설치: TC flower 규칙을 representor에 설치하면 HW로 오프로드
# ━━━ Fast-path vs Slow-path 확인 ━━━
# TC flower 규칙의 HW offload 상태 확인
tc -s filter show dev enp3s0f0np0_0 ingress
# 출력 예시 (HW 오프로드 성공):
# filter protocol ip pref 1 flower chain 0
# eth_type ipv4
# ip_proto tcp
# dst_port 80
# in_hw in_hw_count 1 <-- HW에서 처리됨
# action order 1: gact action drop
# Slow-path 확인 (in_hw_count 0인 경우)
# in_hw in_hw_count 0 <-- 소프트웨어에서 처리
Encapsulation Mode (캡슐화(Encapsulation) 모드)
Switchdev 모드에서 터널(Tunnel)링(VXLAN, Geneve 등)을 사용할 때 캡슐화 모드를 설정합니다. 이 설정은 터널 헤더 처리를 하드웨어에서 수행할지 결정합니다.
# ━━━ Encapsulation Mode 설정 ━━━
# 캡슐화 미사용 (기본값)
devlink dev eswitch set pci/0000:03:00.0 encap mode none
# 기본 캡슐화 지원 (VXLAN, Geneve 등)
devlink dev eswitch set pci/0000:03:00.0 encap mode basic
# 캡슐화 모드 확인
devlink dev eswitch show pci/0000:03:00.0
# pci/0000:03:00.0: mode switchdev inline-mode transport encap mode: basic
| 모드 | 설명 | 사용 시나리오 |
|---|---|---|
none | 캡슐화 미지원, 일반 L2/L3 스위칭만 | 단순 브릿징, VLAN |
basic | VXLAN, Geneve, NVGRE 등 기본 터널링 지원 | 가상화, 오버레이(Overlay) 네트워크 |
vDPA (vhost Data Path Acceleration) 지원
mlx5 드라이버는 switchdev 모드에서 vDPA를 지원합니다. vDPA는 VM의 virtio-net 드라이버와 DPU/NIC 간의 데이터패스를 직접 연결하여 성능을 향상시킵니다.
# ━━━ vDPA 설정 (mlx5) ━━━
# 1. vdpa 도구 설치 확인
which vdpa
# 2. vDPA 장치 생성
vdpa mgmtdev show
vdpa dev add name vdpadev0 parent pci/0000:03:00.0
# 3. vDPA 장치 확인
vdpa dev show
# vdpadev0: dummy (0) virtio0: addresses=[58:a8:fa:00:00:01]
# 4. VM에 vDPA 장치 할당 (QEMU)
# -device vhost-vdpa-pci,vdpa=vdpadev0
# 5. vDPA 통계 확인
vdpa -s dev vdpadev0
- VM의 virtio-net 드라이버가 DPU의 직접 데이터패스에 연결
- VF 할당 없이도 고성능 네트워킹 가능
- 호스트 커널 오버헤드 없이 NIC에서 직접 패킷 처리
- Live migration 지원 (vDPA 장치의 마이그레이션)
Scalable Function (SF)과의 통합
Switchdev 모드에서 SF(Scalable Function)를 사용할 수 있습니다. SF는 VF보다 가벼운 단위로, 더 많은 수의 네트워크 기능을 생성할 수 있습니다.
# ━━━ SF (Scalable Function) 생성 및 관리 ━━━
# 1. SF 영역(resource) 확인
mlxdevm resource show pci/0000:03:00.0 | grep -A5 sf
# 2. SF 생성
mlxdevm port add pci/0000:03:00.0 flavour pcivf vport_index 100
# 3. SF Representor 확인
ip link show
# enp3s0f0np0s0 <-- SF 0 representor
# enp3s0f0np0s1 <-- SF 1 representor
# 4. SF에 IP 주소 할당
ip addr add 10.0.0.1/24 dev enp3s0f0np0s0
# 5. TC flower 규칙 설치 (VF와 동일)
tc qdisc add dev enp3s0f0np0s0 ingress
tc filter add dev enp3s0f0np0s0 ingress protocol ip flower \
dst_ip 10.0.0.5 action drop
# 6. SF 삭제
mlxdevm port del pci/0000:03:00.0/1
OVS Hardware Offload 상세 설정
Switchdev 모드에서 OVS의 하드웨어 오프로드를 설정하는 상세한 단계입니다.
# ━━━ OVS Hardware Offload 설정 ━━━
# 1. eSwitch를 switchdev 모드로 전환
devlink dev eswitch set pci/0000:03:00.0 mode switchdev
devlink dev eswitch set pci/0000:03:00.0 encap mode basic
# 2. VF 생성
echo 4 > /sys/bus/pci/devices/0000:03:00.0/sriov_numvfs
# 3. OVS 데몬 시작 (DPDK 모드)
ovs-vsctl --no-wait set Open_vSwitch . ovs_version=
systemctl start openvswitch
# 4. HW Offload 활성화
ovs-vsctl set Open_vSwitch . other_config:hw-offload=true
ovs-vsctl set Open_vSwitch . other_config:tc-policy=skip_sw
ovs-vsctl set Open_vSwitch . other_config:max-revalidator=100
# 5. 브릿지 생성
ovs-vsctl add-br br-int
ovs-vsctl set bridge br-int datapath_type=netdev
# 6. 포트 추가 (PF + VF Representor)
ovs-vsctl add-port br-int enp3s0f0np0
ovs-vsctl add-port br-int enp3s0f0np0_0
ovs-vsctl add-port br-int enp3s0f0np0_1
# 7. 흐름 규칙 추가
ovs-ofctl add-flow br-int "actions=output:2"
ovs-ofctl add-flow br-int "priority=100,tcp,actions=output:2"
# 8. Offloaded 플로우 확인
ovs-appctl dpctl/dump-flows type=offloaded
# recirc_id(0),in_port(2),eth(...),ipv4(...),packets:1000,bytes:64000,used:0.001s,flags:SFPR
# 9. SW (non-offloaded) 플로우 확인
ovs-appctl dpctl/dump-flows type=sw
# recirc_id(0),in_port(1),eth(...),packets:10,bytes:1280,flags:SP
Conntrack Offload
Switchdev 모드에서 conntrack(연결 추적(Connection Tracking))을 하드웨어로 오프로드할 수 있습니다. 이를 통해 Stateful firewall 기능을 HW 있습니다. 에서 처리할 수
# ━━━ Conntrack Offload 설정 ━━━
# 1. conntrack 모듈 로드 확인
lsmod | grep nf_conntrack
# 2. NF_CONNTRACK_OFFLOAD 커널 옵션 활성화 (이미 활성화되어 있을 수 있음)
# CONFIG_NF_CONNTRACK_OFFLOAD=y
# 3. Representor에서 conntrack 활성화
modprobe nf_conntrack
modprobe nf_conntrack_netlink
# 4. TC flower로 conntrack 상태 기반 필터링
# new 연결만 특정 VF로 리다이렉트
tc filter add dev enp3s0f0np0_0 ingress protocol ip \
flower ct_state +trk+new \
action mirred egress redirect dev enp3s0f0np0_1
# established 연결 허용
tc filter add dev enp3s0f0np0_0 ingress protocol ip \
flower ct_state +trk+est \
action mirred egress redirect dev enp3s0f0np0_1
# 5. conntrack 상태 확인
conntrack -L
# tcp 6 431999 ESTABLISHED src=10.0.0.1 dst=10.0.0.2 sport=12345 dport=80
# 6. HW offload 확인
tc -s filter show dev enp3s0f0np0_0 ingress
# ct_state 0x1/0x1 means NEW
# ct_state 0x2/0x2 means ESTABLISHED
VXLAN Offload
VXLAN(Virtual Extensible LAN) 터널의 캡슐화/디캡슐화를 하드웨어에서 처리할 수 있습니다.
# ━━━ VXLAN Offload 설정 ━━━
# 1. eSwitch에서 캡슐화 모드 활성화
devlink dev eswitch set pci/0000:03:00.0 encap mode basic
# 2. VXLAN 디바이스 생성
ip link add vxlan0 type vxlan id 1000 \
dstport 4789 \
local 10.0.0.1 \
remote 10.0.0.2 \
dev enp3s0f0np0
# 3. 브릿지에 VXLAN 포트 추가
ip link set vxlan0 master br-int
# 4. TC flower로 VXLAN VNI 기반 필터링
tc filter add dev enp3s0f0np0_0 ingress protocol 0x86dd \
flower enc_src_ip 10.0.0.2 \
enc_dst_ip 10.0.0.1 \
enc_key_id 1000 \
action tunnel_key set \
src_ip 10.0.0.1 \
dst_ip 10.0.0.2 \
dst_port 4789 \
id 1000 \
action mirred egress redirect dev enp3s0f0np0_1
# 5. VXLAN offload 확인
ip -d link show vxlan0
# vxlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
# vxlan id 1000 remote 10.0.0.2 local 10.0.0.1 srcport 4789 4790
# noudp6zerocsumrx tx-udp_tnl-csum-segmentation rx-udp_tnl-segmentation
NIC 리소스 관리
Switchdev 모드에서 NIC의 다양한 리소스를 확인하고 관리하는 방법입니다.
# ━━━ NIC 리소스 확인 ━━━
# 1. 전체 리소스 확인
mlxdevm resource show pci/0000:03:00.0
# 2. Flow Table 리소스 확인
mlxdevm resource show pci/0000:03:00.0 | grep -A10 flow_table
# resource: flow_table
# id: 0
# size: 16384
# used: 256
# max_flows: 8192
# 3. 리소스 풀 확인
mlxdevm resource show pci/0000:03:00.0 | grep -A5 general
# resource: general
# size: 1000
# used: 500
# 4. vport 리소스 확인
mlxdevm resource show pci/0000:03:00.0 | grep -A5 vport
# resource: vport
# size: 64
# used: 8
# 5. NIC 포트 정보
devlink port show pci/0000:03:00.0
# pci/0000:03:00.0/0: type eth netdev enp3s0f0np0
# flavor: physical
# pci/0000:03:00.0/1: type eth netdev enp3s0f0np0_0
# flavor: vport
# pfnum: 0
# vport: 0
Failover 및 고가용성
Switchdev 모드에서 링크 failover와 고가용성 설정을 구성합니다.
# ━━━ Failover 설정 ━━━
# 1. Bonding 생성 (PF와 VF Representor)
ip link add bond0 type bond mode active-backup
ip link set enp3s0f0np0 master bond0
ip link set enp3s0f0np0_0 master bond0
ip link set bond0 up
# 2. Mellanox Team 드라이버 (mlx5 Bond)
# mlx5 드라이버는 네이티브 bond 지원
teamdctl bond0 state
# {
# "runner": {"type": "activebackup"},
# "link_watches": [ ... ]
# }
# 3. VF 링크 상태 모니터링
# VF 링크 장애 시 자동 리다이렉션 설정
tc qdisc add dev enp3s0f0np0_0 ingress
tc filter add dev enp3s0f0np0_0 ingress protocol all \
flower action mirred egress redirect dev enp3s0f0np0_1
# 4. LACP (Link Aggregation)
# OVS에서 LACP 설정
ovs-vsctl add-br br-int
ovs-vsctl add-port br-int bond0 bond mode=balance-tcp lacp=active
보안 설정
Switchdev 모드에서 보안을 강화하기 위한 설정들입니다.
# ━━━ Switchdev 보안 설정 ━━━
# 1. VF MAC 주소 고정 ( Spoofing 방지)
ip link set enp3s0f0np0_0 address aa:bb:cc:dd:ee:ff
ip link set enp3s0f0np0_0 type vf mac aa:bb:cc:dd:ee:ff spoofchk on
# 2. VF VLAN 설정 (VLAN 기반 격리)
ip link set enp3s0f0np0_0 type vf vlan 100 qos 0
# 3. VF 트래픽률 제한 (Rate Limiting)
ip link set enp3s0f0np0_0 type vf rate 10000 # 10 Gbps
# 4. Trust 모드 설정 (VF가 보안 기능 우회)
ip link set enp3s0f0np0_0 type vf trust off
# 5. TC flower로 보안 필터링
# 특정 IP만 허용
tc filter add dev enp3s0f0np0_0 ingress protocol ip \
flower src_ip 10.0.0.0/24 \
action pass
# 다른 IP는 드롭
tc filter add dev enp3s0f0np0_0 ingress protocol ip \
flower action drop
# 6. 미사용 VF 비활성화
echo 0 > /sys/bus/pci/devices/0000:03:00.0/sriov_numvfs
모니터링 및 성능 분석
Switchdev 모드의 성능을 모니터링하고 분석하는 도구들입니다.
# ━━━ 성능 모니터링 ━━━
# 1. Representor 통계
ip -s link show enp3s0f0np0_0
# RX: bytes packets errors dropped
# TX: bytes packets errors dropped
# 2. NIC 하드웨어 통계 (ethtool)
ethtool -S enp3s0f0np0_0 | grep -i "vf\|flow\|hw"
# hw_vf_rule_bytes: 123456
# hw_vf_rule_packets: 7890
# rx_vf_messages: 100
# 3. TC 통계
tc -s filter show dev enp3s0f0np0_0 ingress
# Packets: 1000000
# Bytes: 64000000
# 4. 드라이버 통계
cat /sys/class/net/enp3s0f0np0_0/statistics/*
# rx_bytes, rx_packets, rx_dropped, tx_bytes, tx_packets, tx_dropped
# 5. Flow table 사용률
devlink dev flowtable show pci/0000:03:00.0
# pci/0000:03:00.0/flowtable:0
# size 8192
# used 1024
# 6. NIC 벤치마크 (perftest)
perftest -z -n 3 -d mlx5_0 -f tx_mcast
Representor 포트
Representor port는 switchdev 모드에서 DPU/NIC가 호스트 측에 노출하는 가상 netdev입니다. 각 VF/SF에 대응하는 representor가 생성되어, 호스트에서 TC flower 규칙을 통해 VF/SF 트래픽을 제어할 수 있습니다. 이는 OVS offload의 핵심 메커니즘입니다.
벤더별 eSwitch/switchdev 지원
eSwitch(embedded Switch) 및 switchdev 프레임워크는 Mellanox/NVIDIA뿐만 아니라 여러 벤더에서 지원합니다. 각 벤더별 특징과 지원 수준은 다음과 같습니다.
| 벤더 | 드라이버 | ASIC/모델 | 지원 레벨 | 특징 |
|---|---|---|---|---|
| NVIDIA/Mellanox | mlx5 |
ConnectX-4/5/6/7, BlueField | ⭐⭐⭐⭐⭐ | 완전한 eSwitch 지원, SF, RDMA, vDPA 통합 |
| Intel | ice |
E810-XXV, E810-CQ | ⭐⭐⭐⭐ | eSwitch/switchdev, TC flower, bridge offload |
| Broadcom | rocker |
Broadcom OF-DPA 호환 | ⭐⭐⭐ | switchdev 프로토타이핑, L2/L3 offload |
| Marvell | mv88e6xxx |
88E6xxx 시리즈 | ⭐⭐⭐ | DSA 기반, 스위치 칩 통합 |
Intel (ice 드라이버)
Intel Ethernet Controller E810 시리즈는 Mellanox mlx5 다음으로 eSwitch/switchdev를 지원하는 대표적인 랜카드입니다. ice 드라이버를 통해 TC flower 규칙의 하드웨어 오프로드가 가능합니다.
# ━━━ Intel E810 eSwitch 설정 ━━━
# 1. eSwitch를 switchdev 모드로 전환
devlink dev eswitch set pci/0000:3b:00.0 mode switchdev
# 2. Representor 포트 확인
ip link show
# eth0, eth1, eth2, eth3 <-- VF representor
# 3. hw-tc-offload 활성화
ethtool -K eth0 hw-tc-offload on
# 4. TC flower 규칙 설치
tc qdisc add dev eth0 ingress
tc filter add dev eth0 ingress protocol ip flower \
dst_ip 10.0.0.5 action drop
# 5. eSwitch 모드 확인
devlink dev eswitch show pci/0000:3b:00.0
# pci/0000:3b:00.0: mode switchdev
- NVM 펌웨어 v2.50 이상
- ice 드라이버 v1.5.8 이상
- iavf (VF) 드라이버 v4.0.1 이상
- Linux 커널 4.12+
Broadcom (rocker 드라이버)
rocker 드라이버는 Broadcom OF-DPA(Abstract Switch Specification) 기반으로 구현된 switchdev 프로토타이핑용 드라이버입니다. 실제 하드웨어 ASIC 없이도 QEMU에서 테스트가 가능하며, L2 브릿징과 L3 라우팅 offload를 지원합니다.
# ━━━ Broadcom rocker 스위치 설정 ━━━
# rocker 포트 확인 (일반적으로 swp0, swp1, ...)
ip link show
# swp0 <-- 스위치 포트 1
# swp1 <-- 스위치 포트 2
# 브릿지 생성 및 포트 연결
ip link add br0 type bridge
ip link set swp0 master br0
ip link set swp1 master br0
# FDB offload 확인
bridge fdb show
- QEMU 기반 에뮬레이션 지원 (소프트웨어 스위치)
- Broadcom OF-DPA 스펙 기반
- L2 브릿지, L3 라우팅 offload 지원
- 실제 하드웨어 없이 switchdev 테스트 가능
Marvell (DSA/mv88e6xxx)
Marvell 88E6xxx 시리즈는 DSA(Distributed Switch Architecture)를 사용하여 네트워크 스위치 칩을 Linux에 통합합니다. eSwitch와는 slightly 다른 접근 방식이지만, similar 한 기능(포트 representor, TC offload)을 제공합니다.
# ━━━ Marvell mv88e6xxx DSA 설정 ━━━
# DSA 포트 확인 (일반적으로 lan1, lan2, ... 또는 swp0, swp1)
ip link show
# lan1 <-- DSA 포트 1
# lan2 <-- DSA 포트 2
# lan0 <-- CPU 포트 (uplink)
# VLAN 설정
ip link add link lan1 name lan1.10 type vlan id 10
bridge vlan add vid 10 dev lan1
# TC offload (일부 모델만 지원)
ethtool -K lan1 hw-tc-offload on
벤더별 기능 비교
| 기능 | mlx5 (NVIDIA) | ice (Intel) | rocker (Broadcom) | mv88e6xxx (Marvell) |
|---|---|---|---|---|
| switchdev 모드 | ✅ | ✅ | ✅ | DSA |
| VF Representor | ✅ | ✅ | ✅ | ✅ ( DSA) |
| TC Flower Offload | ✅ | ✅ | 제한적 | 제한적 |
| Bridge Offload | ✅ | ✅ | ✅ | ✅ |
| L3 Routing Offload | ✅ | ✅ | ✅ | 제한적 |
| RDMA/RoCE | ✅ | ❌ | ❌ | ❌ |
| vDPA | ✅ | ❌ | ❌ | ❌ |
| Scalable Function | ✅ | ❌ | ❌ | ❌ |
| VXLAN Offload | ✅ | ✅ | ❌ | ❌ |
| Conntrack Offload | ✅ | ✅ | ❌ | ❌ |
| Legacy 역전환 | ✅ | ✅ | ❌ (해당없음) | ❌ (해당없음) |
/* drivers/net/ethernet/mellanox/mlx5/core/eswitch.h */
struct mlx5_eswitch_rep {
struct mlx5_eswitch *esw;
u16 vport; /* 연결된 VF/SF의 vport 번호 */
u16 vlan; /* 기본 VLAN */
struct net_device *netdev; /* representor netdev */
struct mlx5_flow_handle *send_to_vport_rule;
struct mlx5e_rep_priv *rep_data;
};
/* Representor의 역할:
* 1. VF/SF로 향하는 slow-path 패킷의 수신/송신 경로
* 2. TC flower 규칙의 연결점 (representor에 규칙 설치 → eSwitch HW로 오프로드)
* 3. OVS 브릿지의 포트로 연결 (ovs-vsctl add-port br0 enp3s0f0np0_0)
* 4. conntrack offload의 앵커 포인트
*/
코드 설명
-
3행
esw포인터는 부모 eSwitch 구조체를 참조합니다. 하나의 eSwitch가 모든 VF/SF의 representor를 관리하며,esw->vports[vport]->rep로 vport에서 representor를 역참조합니다. -
4행
vport는 NIC 내부의 가상 포트 번호입니다. PF는 vport 0, 첫 번째 VF는 vport 1부터 순차 할당됩니다. eSwitch FDB 규칙의 source/destination은 이 vport 번호로 지정됩니다. -
7행
send_to_vport_rule은 eSwitch FDB에 설치되는 기본 포워딩 규칙입니다. representor로 전송된 slow-path 패킷을 대응하는 VF의 vport로 전달하며, representor 생성 시 자동으로 설치됩니다. -
8행
rep_data는 representor의 드라이버 전용 데이터로, RX/TX 큐 설정, 통계 카운터, ethtool private 플래그 등을 관리합니다. - 10-15행 Representor의 4가지 핵심 역할: (1) VF slow-path 패킷의 수신/송신 경로, (2) TC flower 규칙의 연결점(이 인터페이스에 규칙 설치 → eSwitch HW 오프로드), (3) OVS 브릿지 포트, (4) conntrack 오프로드의 앵커 포인트입니다.
/* drivers/net/ethernet/mellanox/mlx5/core/en_rep.c */
static const struct net_device_ops mlx5e_netdev_ops_rep = {
.ndo_open = mlx5e_rep_open,
.ndo_stop = mlx5e_rep_close,
.ndo_start_xmit = mlx5e_rep_xmit, /* slow-path 송신 */
.ndo_setup_tc = mlx5e_rep_setup_tc, /* TC flower offload 진입점 */
.ndo_get_stats64 = mlx5e_rep_get_stats, /* HW 카운터 기반 통계 */
.ndo_set_rx_mode = mlx5e_rep_set_rx_mode, /* unicast/multiucast 필터 */
};
코드 설명
-
2행
net_device_ops는 커널 네트워크 스택이 디바이스와 상호작용하는 콜백 테이블입니다. Representor는 물리 NIC이 아니라 가상 인터페이스이므로, 일반 mlx5 드라이버(mlx5e_netdev_ops)와 다른 전용 ops 테이블을 사용합니다. -
5행
ndo_start_xmit은 slow-path 송신 경로입니다. Representor로 전송된 패킷은 eSwitch를 통해 대응하는 VF로 전달됩니다. TC flower 오프로드된 트래픽은 이 경로를 거치지 않고 HW에서 직접 처리됩니다. -
6행
ndo_setup_tc는 TC 서브시스템이 flower 규칙을 설치/삭제할 때 호출하는 핵심 진입점입니다.mlx5e_rep_setup_tc()내부에서TC_SETUP_CLSFLOWER명령을 처리하고,mlx5e_tc_add_fdb_flow()로 eSwitch FDB(Forwarding Database)에 HW 규칙을 설치합니다. -
7행
ndo_get_stats64는 HW 카운터 기반 통계를 반환합니다. Representor의 RX/TX 카운터는 eSwitch의 vport 통계에서 읽어오며,ethtool -S나ip -s link show로 확인할 수 있습니다.
Representor 이해하기: "가상의 케이블"
Representor는 가장 중요한 개념 중 하나입니다. "가상의 케이블"로 생각하면 이해하기 쉽습니다.
- Representor는 VF의 "호스트측 복사본"입니다
- VF로 가는 트래픽을 호스트에서 모니터링/제어할 수 있게 해줍니다
- tc filter를 representor에 설치하면 실제 VF의 ASIC에 규칙이 들어갑니다
- VM이 직접 VF를 사용해도, representor를 통해 네트워크를 제어할 수 있습니다
TC Flower Offload
TC flower는 Linux 트래픽 제어(traffic control)의 필터 매칭 규칙입니다. switchdev 모드에서는 이 규칙이 eSwitch 하드웨어로 오프로드되어, CPU 처리 없이 NIC에서 직접 패킷을 분류하고 액션을 수행합니다.
# ━━━ TC Flower Offload 설정 예시 ━━━
# 1. 기본 ingress qdisc 설정 (필수)
tc qdisc add dev enp3s0f0np0_0 ingress
# 2. TC flower 규칙 추가 (VLAN 필터링 + VLAN 태그 제거 후 다른 VF로 포워딩)
tc filter add dev enp3s0f0np0_0 ingress \
protocol 802.1Q \
flower \
vlan_id 100 \
action vlan pop \
action mirred egress redirect dev enp3s0f0np0_1
# 3. IP/Port 기반 필터링 (L4 액션)
tc filter add dev enp3s0f0np0_0 ingress \
protocol ip \
flower \
ip_proto tcp \
dst_port 80 \
action drop
# 4. conntrack 상태 기반 필터링
tc filter add dev enp3s0f0np0_0 ingress \
protocol ip \
flower \
ct_state +trk+new \
action mirred egress redirect dev enp3s0f0np0_1
# 5. 오프로드 상태 확인 (in_hw_count가 1이면 HW 오프로드 성공)
tc -s filter show dev enp3s0f0np0_0 ingress
# filter protocol ip pref 1 flower chain 0
# eth_type ipv4
# ip_proto tcp
# dst_port 80
# in_hw in_hw_count 1 <-- HW 오프로드 확인
# action order 1: gact action drop
TC Offload 처리 흐름
TC flower 규칙이 설치된 후, 패킷은 fast-path(하드웨어에서 직접 처리)와 slow-path(소프트웨어에서 처리)로 나뉩니다.
OVS Hardware Offload
Open vSwitch(OVS)는 가상 스위칭의 표준이지만, 소프트웨어 처리로 인해 CPU 오버헤드가 큽니다. DPU의 eSwitch를 활용하면 OVS 플로우를 하드웨어로 오프로드하여 호스트 CPU 사용을 90% 이상 줄일 수 있습니다.
# ━━━ OVS-DPDK + TC Flower HW Offload 설정 ━━━
# 1. eSwitch를 switchdev 모드로 전환
devlink dev eswitch set pci/0000:03:00.0 mode switchdev
# 2. OVS에서 하드웨어 오프로드 활성화
ovs-vsctl set Open_vSwitch . other_config:hw-offload=true
ovs-vsctl set Open_vSwitch . other_config:tc-policy=skip_sw
# 3. OVS 브릿지에 PF와 VF representor 연결
ovs-vsctl add-br br-int
ovs-vsctl add-port br-int enp3s0f0np0 # PF (uplink)
ovs-vsctl add-port br-int enp3s0f0np0_0 # VF0 representor
ovs-vsctl add-port br-int enp3s0f0np0_1 # VF1 representor
# 4. 오프로드 동작 흐름:
# a) 첫 패킷: eSwitch → representor → OVS userspace → flow 결정
# b) OVS가 TC flower 규칙을 representor에 설치
# c) 드라이버가 TC flower → eSwitch HW 규칙으로 변환
# d) 이후 패킷: eSwitch HW에서 직접 포워딩 (CPU 바이패스)
# 오프로드된 플로우 확인
tc -s filter show dev enp3s0f0np0_0 ingress
# filter protocol ip pref 2 flower chain 0
# eth_type ipv4
# src_ip 10.0.0.5
# dst_ip 10.0.0.10
# in_hw in_hw_count 1 ← HW 오프로드 확인
# action order 1: mirred (Egress Redirect to device enp3s0f0np0_1)
# hw_stats immediate
# OVS 오프로드 통계 확인
ovs-appctl dpctl/dump-flows type=offloaded
# recirc_id(0),in_port(2),eth(...),ipv4(src=10.0.0.5,dst=10.0.0.10,...)
# packets:1523400, bytes:97497600, used:0.001s, flags:SFPR
- 모든 OVS 액션이 HW 오프로드 가능한 것은 아닙니다.
ct()(conntrack),output,set()등 기본 액션은 지원되지만,learn(),clone()등 복잡한 액션은 소프트웨어 폴백됩니다 - eSwitch의 HW 플로우 테이블 크기가 유한합니다 (보통 수백만 엔트리). 초과 시 자동 소프트웨어 폴백
conntrack offload는 지원 연결 수와 타임아웃 동작이 소프트웨어 conntrack과 다를 수 있습니다- VXLAN/Geneve 등 오버레이 터널의 캡슐화/해제도 HW 오프로드 가능하지만, 드라이버와 펌웨어 버전에 따라 지원 범위가 다릅니다
Inline Mode 설정
eSwitch의 inline 모드는 패킷 헤더 처리를 호스트와 NIC 간 어떻게 분담할지를 결정합니다. 모드에 따라 메타데이터의 위치와 CPU 관여 수준이 달라집니다.
# ━━━ Inline Mode 종류 ━━━
# none (기본): 메타데이터 없음, 완전한 패킷만 전송
devlink dev eswitch set pci/0000:03:00.0 inline-mode none
# transport: 메타데이터를 PCIe transport 레이어에 포함 (즉시 처리)
devlink dev eswitch set pci/0000:03:00.0 inline-mode transport
# network: 메타데이터를 네트워크 헤더에 포함 (터널 시나리오)
devlink dev eswitch set pci/0000:03:00.0 inline-mode network
# 현재 설정 확인
devlink dev eswitch show pci/0000:03:00.0
# pci/0000:03:00.0: mode switchdev inline-mode transport encap mode: NOTSET
| 모드 | 설명 | 사용 시나리오 |
|---|---|---|
none | 메타데이터 없음, 완전한 패킷만 전송 | 기본 브릿징, VLAN |
transport | 메타데이터를 PCIe transport 레이어에 포함 | TC offload, conntrack offload |
network | 메타데이터를 네트워크 헤더에 포함 | VXLAN/Geneve 터널 오프로드 |
Scalable Function (SF)
Scalable Function (SF)은 VF보다 더 가벼운 단위의 가상 기능입니다. VF가 PCIe 함수인 반면, SF는 PCIe 리소스를 공유하면서도 더 작은 세분화로 생성하고 관리할 수 있습니다. DPU에서 다수의 마이크로서비스를 위한 네트워크 기능을 제공할 때 사용됩니다.
# ━━━ SF (Scalable Function) 생성 및 관리 ━━━
# 1. SF 영역 확인
mlxdevm resource show pci/0000:03:00.0 | grep -A5 sf
# 2. SF 생성
mlxdevm port add pci/0000:03:00.0 flavour pcivf vport_index 88
# 3. SFRepresentor 확인
ip link show
# enp3s0f0np0s0 <-- SF 0 representor
# enp3s0f0np0s1 <-- SF 1 representor
# 4. SF 삭제
mlxdevm port del pci/0000:03:00.0/1
디버깅 및 트러블슈팅
eSwitch 관련 문제 발생 시 다음 명령어로 상태를 진단할 수 있습니다.
# ━━━ eSwitch 디버깅 명령어 ━━━
# 1. eSwitch 상태 확인
devlink dev eswitch show pci/0000:03:00.0
devlink dev info pci/0000:03:00.0
# 2. Representor 통계 확인
ip -s link show enp3s0f0np0_0
ethtool -S enp3s0f0np0_0 | grep -i rep
# 3. HW 플로우 테이블 상태
devlink dev flowtable show pci/0000:03:00.0
# 4. 드라이버 로그에서 eSwitch 이벤트 확인
dmesg | grep -i "eswitch\|switchdev\|rep"
# [12345.678901] mlx5_core 0000:03:00.0: eSwitch: switchdev mode enabled
# [12345.678902] mlx5_core 0000:03:00.0: eSwitch: representor enp3s0f0np0_0 created
# 5. VF와 representor 매핑 확인
cat /sys/class/net/enp3s0f0np0_0/phys_switch_id
cat /sys/class/net/enp3s0f0np0_0/phys_port_name
# 6. TC offload 실패 시 소프트웨어 폴백 확인
tc -s filter show dev enp3s0f0np0_0 ingress | grep -i "hw\|sw"
# in_hw_count 0: 소프트웨어에서 처리 중
# in_hw_count 1: 하드웨어에서 처리 중
# 7. 드라이버 health 상태 확인
devlink health show pci/0000:03:00.0 reporter eswitch
- 모드 전환 실패: VF가 활성화되어 있으면 실패합니다. 먼저 모든 VF를 삭제하세요. (자세한 역전환 가이드는 Switchdev → Legacy 역전환을 참고)
- TC offload 안됨: 드라이버 로그에서 "cannot offload" 메시지 확인. 드라이버/펌웨어 호환성 문제일 수 있습니다.
- representor 생성 안됨: firmware에서 sriov_en=true 설정 확인.
- 플로우 테이블 초과: "Failed to create flow: table full" 오류 시 불필요한 규칙 정리.
커널 설정
eSwitch/switchdev를 사용하기 위해 필요한 커널 설정 옵션들입니다. 사용하는 NIC에 따라 해당 드라이버를 활성화하세요.
# ━━━ 커널 설정 옵션 ━━━
# =============================================
# 공통: TC flower offload (모든 벤더에 필요)
# =============================================
CONFIG_NET_SCHED=y
CONFIG_NET_CLS=y
CONFIG_NET_CLS_FLOWER=y
CONFIG_NET_ACT_POLICE=y
# Conntrack offload (mlx5, ice 지원)
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_OFFLOAD=y
# OVS-DPDK (선택)
CONFIG_OPENVSWITCH=y
CONFIG_DPDK=y
# =============================================
# Mellanox/NVIDIA (mlx5)
# =============================================
CONFIG_MLX5_CORE=y
CONFIG_MLX5_MDEV=y # SF(Scalable Function) 지원
CONFIG_MLX5_ESWITCH=y # eSwitch 지원 - 필수
CONFIG_MLX5_EN_ETHERNET=y # 이더넷 드라이버
CONFIG_MLX5_INFINIBAND=y # RDMA/RoCE 지원
CONFIG_MLX5_VDPA=y # vDPA 지원
# =============================================
# Intel (ice)
# =============================================
CONFIG_ICE=y
# =============================================
# Broadcom (rocker)
# =============================================
CONFIG_ROCKER=y
# =============================================
# Marvell (DSA)
# =============================================
CONFIG_NET_DSA=y
CONFIG_NET_DSA_MV88E6XXX=y
CONFIG_NET_DSA_MV88E6XXX_PTP=y # PTP 지원
Performance Tuning
eSwitch의 성능을 최적화하기 위해 고려해야 할 주요 튜닝 포인트들입니다. 올바른 설정을 통해 라인레이트(초당 패킷 처리)에 근접한 성능을 달성할 수 있습니다.
Receive Queue (RSS) 튜닝
VF의 RSS(Receive Side Scaling) 설정을 통해_multiple CPU 코어에서 패킷을 병렬 처리할 수 있습니다.
# ━━━ RSS (Receive Side Scaling) 튜닝 ━━━
# 1. VF의 RSS 해시 키 확인
ethtool -x enp3s0f0np0_0
# RX flow hash indirection table for enp3s0f0np0_0:
# Table size: 128
# Layout: context=default
# RX queue: 0 1 2 3 4 5 6 7 ...
# 2. RSS 큐 수 설정 (CPU 코어 수와 일치)
ethtool -L enp3s0f0np0_0 combined 8
# 3. RSS 해시 설정 (L3/L4 해시 활성화)
ethtool -N enp3s0f0np0_0 rx-flow-hash udp4 tcp4 tcp6 udp6 sge
# 4. Large RX 버퍼 설정 (대용량 패킷 처리용)
ethtool -G enp3s0f0np0_0 rx 4096 tx 4096
# 5. RSS 해시 결과 확인
ethtool -n enp3s0f0np0_0
Buffer Tuning
NIC 버퍼 크기를 조정하여 버스트 트래픽 처리 능력을 향상시킬 수 있습니다.
# ━━━ Buffer 튜닝 ━━━
# 1. 현재 버퍼 상태 확인
ethtool -g enp3s0f0np0_0
# 2. RX/TX Ring 크기 증가
ethtool -G enp3s0f0np0_0 rx 4096 tx 4096
# 3. Interrupt Coalescing 설정
ethtool -C enp3s0f0np0_0 rx-usecs 64 tx-usecs 64
# 4. Flow Director 설정 (Intel 랜카드)
ethtool -K enp3s0f0np0_0 ntuple on
NVIDIA/mlx5 특화 튜닝
mlx5 드라이버의 특화된 튜닝 파라미터들입니다.
# ━━━ mlx5 특화 튜닝 ━━━
# 1. eSwitch 모드에서 페이로드 크기 설정
ip link set enp3s0f0np0 mtu 9000
# 2. Flow 테이블 크기 확인
mlxdevm resource show pci/0000:03:00.0 | grep -A10 flow_table
# 3. Representor의 RSS 설정
mlxreg -d /dev/mst/mt4123_pciconf0 --reg_name RSS --set rss_xj=1,hash_field=1 --yes
# 4. 드롭 패킷 모니터링
ip -s link show enp3s0f0np0_0 | grep -i "drop\|error"
벤치마크 방법
eSwitch offload 성능을 측정하는 표준적인 벤치마크 방법입니다.
# ━━━ 벤치마크 ━━━
# 1. pktgen으로 패킷 생성
modprobe pktgen
pgset "count 0"
pgset "delay 0"
pgset "pkt_size 64"
pgset "dst 10.0.0.5"
pgset "start"
# 2.iperf3으로 대역폭 측정
iperf3 -s -p 5201
# 클라이언트:
iperf3 -c 10.0.0.5 -p 5201 -t 30 -P 8
# 3. mpstat로 CPU 사용률 확인
mpstat -P ALL 1
- 64B 패킷: ~100Mpps (라인레이트)
- 1500B 패킷: ~14.8Mpps (~100Gbps)
- TC flower offload 시 CPU 사용: 0% (HW 처리)
- Latency: ~1-2μs (HW 경유)
보안 고려사항
eSwitch를 활용한 네트워크 구성에서 고려해야 할 보안 요소들입니다.
VF 간 격리(Isolation)
switchdev 모드에서 VF 간 통신은 eSwitch HW에서 처리됩니다. 올바른 VLAN/VNI 설정이 필수입니다.
# ━━━ VF 격리 설정 ━━━
# 1. VF별 VLAN 설정
ip link set enp3s0f0np0_0 master br0
bridge vlan add dev enp3s0f0np0_0 vid 100 pvid untagged
ip link set enp3s0f0np0_1 master br0
bridge vlan add dev enp3s0f0np0_1 vid 200 pvid untagged
# 2. VF 간 통신 차단
ip link add br-isolated-1 type bridge
ip link add br-isolated-2 type bridge
ip link set enp3s0f0np0_0 master br-isolated-1
ip link set enp3s0f0np0_1 master br-isolated-2
# 3. TC flower로 VF 간 통신 제어
tc filter add dev enp3s0f0np0_0 ingress protocol all flower \
action drop
MAC/ARP 필터링
Representor에서 MAC 주소 필터링을 통해 비정상적인 트래픽을 차단할 수 있습니다.
# ━━━ MAC/ARP 필터링 ━━━
# 1. 허용된 MAC 주소만 수신
ip link set enp3s0f0np0_0 address 00:00:00:00:00:05
ip link set enp3s0f0np0_0 type bridge_setlink brport restricted 1
# 2. TC flower로 특정 MAC 필터링
tc filter add dev enp3s0f0np0_0 ingress protocol all flower \
dst_mac 00:11:22:33:44:55 \
action drop
Trusted VF 설정
보안이 검증된 VF에는 트러스트 플래그를 설정하여 추가 권한을 부여할 수 있습니다.
# ━━━ Trusted VF 설정 ━━━
# 1. VF를 Trusted로 설정
ip link set enp3s0f0np0_0 type vf trust on
# 2. VF별 VLAN 태그 허용/차단
ip link set enp3s0f0np0_0 type vf vlan 100 qos 5
# 3. VF MAC 주소 고정
ip link set enp3s0f0np0_0 type vf mac 00:00:00:00:00:05
# 4. VF별 최대 대역폭 설정
ip link set enp3s0f0np0_0 type vf rate 10000
- VF 트러스트: 필요한 VF만 trust=on으로 설정
- MAC 주소 고정: VF의 MAC 주소를 고정하여 ARP 스푸핑 방지
- VLAN 격리: 서로 다른 테넌트의 VF는 반드시 다른 VLAN/VNI에 배치
- 펌웨어 업데이트: 보안 패치(Patch)가 포함된 최신 펌웨어 사용
VXLAN/Geneve Offload
VXLAN와 Geneve는 데이터센터에서 가장 널리 사용되는 네트워크 가상화 터널 프로토콜입니다. eSwitch는 이러한 터널의 캡슐화/해제를 하드웨어에서 처리할 수 있어 CPU 오버헤드를 크게 줄입니다.
VXLAN Offload 아키텍처
# ━━━ VXLAN Offload 설정 ━━━
# 1. VXLAN 디바이스 생성 (HW offload 활성화)
ip link add vxlan0 type vxlan id 1000 \
dstport 4789 \
local 192.168.1.1 \
remote 192.168.1.2 \
dev enp3s0f0np0 \
external
# 2. 브릿지에 VXLAN 포트 추가
ip link set vxlan0 master br-vxlan
# 3. eSwitch에서 VXLAN offload 활성화
devlink dev eswitch set pci/0000:03:00.0 encap mode enable
# 4. VXLAN VNI ↔ 브릿지 매핑
bridge vlan add dev vxlan0 vid 1000
Geneve Offload
Geneve는 VXLAN보다 유연한 확장성을 제공하는 터널 프로토콜입니다.
# ━━━ Geneve Offload 설정 ━━━
# 1. Geneve 디바이스 생성
ip link add geneve0 type geneve id 2000 \
remote 192.168.2.1 \
dev enp3s0f0np0 \
external
# 2. Geneve + TC flower 규칙
tc qdisc add dev enp3s0f0np0_0 ingress
tc filter add dev enp3s0f0np0_0 ingress protocol all flower \
enc_src_port 6081 \
enc_dst_port 6081 \
enc_key_id 2000 \
action mirred egress redirect dev geneve0
- VXLAN: 24비트 VNI (1600만 VM), UDP 포트 4789, 광범위한 하드웨어 지원
- Geneve: 24비트 VNI + TLV 확장, UDP 포트 6081, 유연한 메타데이터 전송
QoS 및 Rate Limiting
eSwitch에서 QoS와 Rate Limiting을 통해 트래픽을 제어할 수 있습니다.
QoS Offload
# ━━━ QoS 설정 ━━━
# 1. 우선순위 큐 (Priority Queue) 설정
tc qdisc add dev enp3s0f0np0_0 root mqprio \
num_tc 4 \
map 0 1 2 3 \
queues 4@0 4@4 4@8 4@12 \
hw 1
# 2. VF별 대역폭 제한
ip link set enp3s0f0np0_0 type vf rate 10000
# 3. TC로 상세 QoS 규칙
tc qdisc add dev enp3s0f0np0_0 handle 800: parent root htb default 10
tc class add dev enp3s0f0np0_0 parent 800: classid 800:10 htb rate 5gbit burst 15k
vDPA (vhost Data Path Acceleration)
vDPA는 DPU/이더넷 카드의 하드웨어 가속을 VM 또는 컨테이너의 virtio 드라이버에 제공하는 프레임워크입니다.
vDPA 아키텍처
# ━━━ vDPA 설정 ━━━
# 1. vDPA 디바이스 생성 (mlx5의 경우)
vdpa mlx5 add -n vhost0 -k 16 -m 4
# 2. vDPA 디바이스 확인
vdpa dev show
# 3. QEMU에서 vDPA 사용
qemu-system-x86_64 \
-m 8G \
-drive file=vm.qcow2,if=virtio \
-netdev type=vhost-vdpa,id=vdpa0,vhostdev=/dev/vhost-vdpa-0 \
-device virtio-net-pci,netdev=vdpa0,mac=00:00:00:00:00:05
- 최적의 성능: virtio 규약을 준수하면서 HW 가속
- eSwitch 통합: VXLAN, TC flower offload와 완벽히 통합
- 표준 인터페이스: Linux vDPA 프레임워크 기반
Live Migration 시나리오
VM의 Live Migration 시 eSwitch 환경에서 고려해야 할 사항들입니다.
마이그레이션 도전과제
# ━━━ Live Migration 준비 ━━━
# 1. Source Host: VF 할당 확인
virsh dumpxml vm1 | grep -A10 "interface"
# 2. Destination Host: 동일한 VF 구성
echo 4 > /sys/bus/pci/devices/0000:03:00.0/sriov_numvfs
devlink dev eswitch set pci/0000:03:00.0 mode switchdev
# 3. Destination Host: Representor 준비
ip link show | grep enp3s0f0np0_
# 4. OVS 플로우 복제
ovs-ofctl dump-flows br0 > /tmp/flows.txt
모범 사례
- VF MAC 고정: 마이그레이션 시 MAC 주소가 변경되지 않도록 VF MAC을 고정
- VLAN 일관성: Source/Destination 모두 동일한 VLAN 구성
- OVS 플로우 백업: 마이그레이션 전 OVS 플로우를 백업하고 복원
Multi-Host 시나리오 (EVPN-VXLAN)
대규모 데이터센터에서는 여러 호스트 간의 네트워크를 EVPN-VXLAN으로 구성합니다.
EVPN-VXLAN 개요
# ━━━ EVPN-VXLAN 설정 ━━━
# 1. BGP EVPN 피어 설정
router bgp 65001
neighbor 10.0.0.2 remote-as 65001
address-family l2vpn evpn
neighbor 10.0.0.2 activate
exit-address-family
# 2. VXLAN 브릿지 도메인 설정
bridge vlan del dev br0 vid 1 self
bridge vlan add dev br0 vid 1000
# 3. eSwitch에서 EVPN 활성화
devlink dev eswitch set pci/0000:03:00.0 mode switchdev
devlink dev eswitch set pci/0000:03:00.0 encap mode enable
# 4. EVPN VNI 매핑
bridge fdb add 00:00:00:00:00:05 dev vxlan0 self static vni 1000
- 스케일러블: 1600만 이상의 VM/VNI 지원
- 로드밸런싱: ECMP 기반 다중 경로 지원
- MAC Mobility: VM 이동 시 MAC 주소 자동 학습
- HW Offload: eSwitch에서 VXLAN/Tunnel Offload
OVS Offload + eSwitch 연동 실전 구성
OVS(Open vSwitch)와 eSwitch를 연동하면, OVS의 소프트웨어 플로우 테이블을 NIC 하드웨어에 직접 설치하여 CPU 오버헤드를 90% 이상 절감할 수 있습니다. 이 섹션에서는 처음부터 끝까지 완전한 설정 과정과 offload 상태 확인 방법을 다룹니다.
전체 설정 절차
# ━━━ OVS + eSwitch HW Offload 전체 구성 ━━━
# 1단계: SR-IOV VF 생성
echo 0 > /sys/bus/pci/devices/0000:03:00.0/sriov_numvfs
echo 4 > /sys/bus/pci/devices/0000:03:00.0/sriov_numvfs
# 2단계: VF 바인딩 해제 (switchdev 전환 전 필수!)
for vf in $(ls /sys/bus/pci/devices/0000:03:00.0/virtfn*/driver 2>/dev/null | xargs -I{} readlink {} | xargs -I{} basename {}); do
echo "$vf" > /sys/bus/pci/drivers/mlx5_core/unbind 2>/dev/null
done
# 3단계: eSwitch를 switchdev 모드로 전환
devlink dev eswitch set pci/0000:03:00.0 mode switchdev
# 4단계: VF 다시 바인딩
for vf in $(ls -d /sys/bus/pci/devices/0000:03:00.0/virtfn* 2>/dev/null | xargs -I{} readlink {} | xargs -I{} basename {}); do
echo "$vf" > /sys/bus/pci/drivers/mlx5_core/bind 2>/dev/null
done
# 5단계: OVS hw-offload 활성화
ovs-vsctl set Open_vSwitch . other_config:hw-offload=true
ovs-vsctl set Open_vSwitch . other_config:tc-policy=skip_sw
# 6단계: OVS 재시작 (hw-offload 적용)
systemctl restart openvswitch-switch
# 7단계: OVS 브릿지 생성 및 포트 추가
ovs-vsctl add-br br-eswitch
ovs-vsctl add-port br-eswitch enp3s0f0np0 # PF uplink
ovs-vsctl add-port br-eswitch enp3s0f0np0_0 # VF0 representor
ovs-vsctl add-port br-eswitch enp3s0f0np0_1 # VF1 representor
# 8단계: representor 인터페이스 활성화
ip link set enp3s0f0np0 up
ip link set enp3s0f0np0_0 up
ip link set enp3s0f0np0_1 up
offload 상태 확인
# ━━━ OVS offload 동작 확인 ━━━
# offloaded 플로우 확인 (in_hw 표시가 핵심)
ovs-appctl dpctl/dump-flows type=offloaded
# 출력 예시:
# recirc_id(0),in_port(2),eth(src=52:54:00:01:02:03),eth_type(0x0800),
# ipv4(src=10.0.0.10/32,dst=10.0.0.20/32), packets:1234567, bytes:789012345,
# used:0.001s, flags:P, offloaded:yes, dp:tc
# TC 규칙에서 in_hw 플래그 확인
tc -s filter show dev enp3s0f0np0_0 ingress
# filter ... action ... in_hw in_hw_count 1
# offloaded vs non-offloaded 플로우 비교
ovs-appctl dpctl/dump-flows type=offloaded | wc -l # HW 처리
ovs-appctl dpctl/dump-flows type=ovs | wc -l # SW 처리
# CPU 사용률 비교 (offload 전후)
mpstat -P ALL 1 5
# eSwitch HW 통계 확인
ethtool -S enp3s0f0np0 | grep -E "tx_vport|rx_vport"
ethtool -S enp3s0f0np0_0 | grep -E "packets|bytes"
other_config:tc-policy=skip_sw를 설정하면 HW에 offload할 수 없는 플로우는
아예 설치되지 않으므로, 처음에는 none(기본값)으로 시작하여 SW fallback을 허용하는 것이 안전합니다.
VF Representor 트래픽 미러링 및 모니터링
VF representor를 활용하면 가상 머신의 트래픽을 호스트에서 투명하게 미러링하고 모니터링할 수 있습니다. 기존 물리 스위치의 SPAN/미러 포트와 유사한 기능을 소프트웨어 정의 방식으로 구현합니다.
TC mirred를 이용한 미러링 설정
# ━━━ VF Representor 트래픽 미러링 ━━━
# 1. 모니터 인터페이스 준비
ip link add name mon0 type dummy
ip link set mon0 up
ip link set mon0 promisc on
# 2. VF0 representor에 미러링 규칙 설치
# 모든 ingress 트래픽을 mon0으로 미러링 + 원래 목적지로도 전달
tc qdisc add dev enp3s0f0np0_0 ingress
tc filter add dev enp3s0f0np0_0 ingress \
protocol all pref 1 \
flower \
action mirred egress mirror dev mon0 \
action mirred egress redirect dev enp3s0f0np0_1
# 3. 특정 트래픽만 미러링 (예: TCP 포트 80)
tc filter add dev enp3s0f0np0_0 ingress \
protocol ip pref 10 \
flower ip_proto tcp dst_port 80 \
action mirred egress mirror dev mon0 pipe \
action mirred egress redirect dev enp3s0f0np0_1
# 4. 미러링된 트래픽 캡처
tcpdump -i mon0 -w /tmp/mirror_capture.pcap
# 5. 미러링 규칙 확인
tc -s filter show dev enp3s0f0np0_0 ingress
# in_hw 플래그가 보이면 HW offload 성공
# 6. 양방향 미러링 (egress도 캡처)
tc qdisc add dev enp3s0f0np0_0 clsact
tc filter add dev enp3s0f0np0_0 egress \
protocol all pref 1 \
flower \
action mirred egress mirror dev mon0
TC Flower 하드웨어 오프로드 실전 예제
TC flower는 eSwitch에서 가장 중요한 트래픽 분류 메커니즘입니다. 커널의 TC 서브시스템이 flower 필터를 통해 매치 조건과 액션을 정의하고, NIC 드라이버가 이를 하드웨어 플로우 테이블에 설치합니다.
기본 TC flower 오프로드 규칙
# ━━━ TC Flower HW Offload 규칙 예제 ━━━
# ingress qdisc 생성 (clsact 권장)
tc qdisc add dev enp3s0f0np0_0 clsact
# ── L2 기반 필터링 ──
# 특정 MAC 주소의 트래픽을 VF1으로 리다이렉트
tc filter add dev enp3s0f0np0_0 ingress \
protocol all pref 1 \
flower \
src_mac 52:54:00:01:02:03 \
action mirred egress redirect dev enp3s0f0np0_1
# ── L3 기반 필터링 ──
# 특정 서브넷 트래픽을 uplink으로 전달
tc filter add dev enp3s0f0np0_0 ingress \
protocol ip pref 10 \
flower \
dst_ip 192.168.100.0/24 \
action mirred egress redirect dev enp3s0f0np0
# ── L4 기반 필터링 ──
# SSH 트래픽(포트 22)만 특정 VF로 전달
tc filter add dev enp3s0f0np0_0 ingress \
protocol ip pref 20 \
flower \
ip_proto tcp dst_port 22 \
action mirred egress redirect dev enp3s0f0np0_1
# ── VLAN 기반 필터링 ──
# VLAN 100 트래픽을 VF0으로, VLAN 200을 VF1으로
tc filter add dev enp3s0f0np0 ingress \
protocol 802.1Q pref 30 \
flower vlan_id 100 \
action vlan pop \
action mirred egress redirect dev enp3s0f0np0_0
tc filter add dev enp3s0f0np0 ingress \
protocol 802.1Q pref 31 \
flower vlan_id 200 \
action vlan pop \
action mirred egress redirect dev enp3s0f0np0_1
고급 TC flower 규칙 (터널, 수정, 폴리싱)
# ━━━ 고급 TC Flower 규칙 ━━━
# ── VXLAN 터널 디캡슐레이션 ──
# VNI 1000 트래픽을 디캡슐레이션하고 VF0로 전달
tc filter add dev vxlan_sys_4789 ingress \
protocol ip pref 1 \
flower \
enc_dst_ip 10.0.0.1 \
enc_key_id 1000 \
enc_dst_port 4789 \
action tunnel_key unset \
action mirred egress redirect dev enp3s0f0np0_0
# ── 패킷 헤더 수정 (pedit) ──
# 소스 MAC 재작성
tc filter add dev enp3s0f0np0_0 ingress \
protocol ip pref 15 \
flower \
dst_ip 10.0.0.0/24 \
action pedit ex munge eth src set 00:11:22:33:44:55 \
action mirred egress redirect dev enp3s0f0np0
# ── 레이트 폴리싱 (QoS) ──
# VF0에서 오는 트래픽을 1Gbps로 제한
tc filter add dev enp3s0f0np0_0 ingress \
protocol all pref 5 \
flower \
action police rate 1gbit burst 1m conform-exceed drop/ok \
action mirred egress redirect dev enp3s0f0np0
# ── skip_sw / skip_hw 플래그 ──
# skip_sw: SW fallback 없이 HW only (성능 보장)
tc filter add dev enp3s0f0np0_0 ingress \
protocol ip pref 50 \
flower skip_sw \
dst_ip 10.0.0.100/32 \
action mirred egress redirect dev enp3s0f0np0_1
# skip_hw: SW only (디버깅/테스트용)
tc filter add dev enp3s0f0np0_0 ingress \
protocol ip pref 51 \
flower skip_hw \
dst_ip 10.0.0.200/32 \
action mirred egress redirect dev enp3s0f0np0_1
규칙 확인 및 디버깅
# ━━━ TC Flower 규칙 검증 ━━━
# 전체 규칙 목록 (통계 포함)
tc -s filter show dev enp3s0f0np0_0 ingress
# 핵심 확인 포인트:
# in_hw → HW에 offload됨
# not_in_hw → offload 실패 (SW에서만 동작)
# in_hw_count → offload된 HW 인스턴스 수
# HW 통계 확인 (패킷/바이트 카운터)
tc -s -d filter show dev enp3s0f0np0_0 ingress
# 규칙 삭제
tc filter del dev enp3s0f0np0_0 ingress pref 10
# 전체 ingress 규칙 초기화
tc qdisc del dev enp3s0f0np0_0 clsact
# 드라이버 디버그 로그 (offload 실패 원인 추적)
dmesg | grep -i "flower\|offload\|tc filter"
# mlx5 드라이버 내부 카운터
ethtool -S enp3s0f0np0 | grep -E "tc_|flower_"
- mirred redirect/mirror: 패킷 전달/미러링
- vlan push/pop: VLAN 태그 추가/제거
- tunnel_key set/unset: VXLAN/Geneve 캡슐레이션
- pedit: 헤더 필드 수정 (MAC, IP, 포트)
- police: 레이트 제한
- drop: 패킷 드롭
- ct: Connection Tracking offload (커널 5.7+)
흔한 실수와 안티패턴
eSwitch 설정에서 자주 발생하는 실수와 문제 해결 방법을 정리합니다. 이러한 안티패턴을 미리 인지하면 디버깅 시간을 크게 줄일 수 있습니다.
실수 1: switchdev 모드 전환 시 VF 바인딩 해제 누락
# ━━━ 안티패턴: VF 바인딩 해제 없이 switchdev 전환 ━━━
# ✗ 잘못된 방법 — VF가 바인딩된 상태에서 전환 시도
echo 4 > /sys/bus/pci/devices/0000:03:00.0/sriov_numvfs
devlink dev eswitch set pci/0000:03:00.0 mode switchdev
# 결과: -EBUSY 오류 또는 커널 패닉 가능
# Error: devlink answered: Resource busy
# ✓ 올바른 방법 — 반드시 VF unbind 후 전환
echo 4 > /sys/bus/pci/devices/0000:03:00.0/sriov_numvfs
# VF를 모두 unbind
echo 0000:03:00.2 > /sys/bus/pci/drivers/mlx5_core/unbind
echo 0000:03:00.3 > /sys/bus/pci/drivers/mlx5_core/unbind
echo 0000:03:00.4 > /sys/bus/pci/drivers/mlx5_core/unbind
echo 0000:03:00.5 > /sys/bus/pci/drivers/mlx5_core/unbind
# switchdev 모드로 전환
devlink dev eswitch set pci/0000:03:00.0 mode switchdev
# VF를 다시 bind
echo 0000:03:00.2 > /sys/bus/pci/drivers/mlx5_core/bind
echo 0000:03:00.3 > /sys/bus/pci/drivers/mlx5_core/bind
echo 0000:03:00.4 > /sys/bus/pci/drivers/mlx5_core/bind
echo 0000:03:00.5 > /sys/bus/pci/drivers/mlx5_core/bind
실수 2: TC flower 규칙 우선순위(Priority) 충돌
# ━━━ 안티패턴: 동일 우선순위로 충돌하는 규칙 ━━━
# ✗ 잘못된 방법 — 같은 pref 값으로 충돌하는 규칙
tc filter add dev enp3s0f0np0_0 ingress protocol ip pref 10 \
flower dst_ip 10.0.0.0/24 action mirred egress redirect dev enp3s0f0np0_1
tc filter add dev enp3s0f0np0_0 ingress protocol ip pref 10 \
flower dst_ip 10.0.0.0/16 action drop
# 결과: 두 번째 규칙이 첫 번째를 덮어쓰거나 EEXIST 오류
# ✓ 올바른 방법 — 명시적 우선순위 할당 (낮은 pref = 높은 우선순위)
tc filter add dev enp3s0f0np0_0 ingress protocol ip pref 10 \
flower dst_ip 10.0.0.0/24 action mirred egress redirect dev enp3s0f0np0_1
tc filter add dev enp3s0f0np0_0 ingress protocol ip pref 20 \
flower dst_ip 10.0.0.0/16 action drop
# pref 10이 먼저 매치 → /24에 해당하면 VF1으로 전달
# pref 20이 나중 매치 → 나머지 /16은 드롭
# 규칙 우선순위 확인
tc filter show dev enp3s0f0np0_0 ingress | grep pref
실수 3: Representor 네트워크 네임스페이스(Namespace) 설정 오류
# ━━━ 안티패턴: Representor를 VM의 netns에 넣음 ━━━
# ✗ 잘못된 방법 — representor를 VM 네임스페이스로 이동
ip link set enp3s0f0np0_0 netns vm1_ns
# 결과: OVS가 representor를 잃어버려서 offload 불가
# representor는 호스트에 남아야 OVS/TC가 제어 가능
# ✓ 올바른 구성:
# - VF: VM에 passthrough (vfio-pci 또는 virtio-forwarder)
# - Representor: 호스트의 default netns에 유지
# - OVS 브릿지에 representor 추가
ovs-vsctl add-port br0 enp3s0f0np0_0 # representor는 호스트에서 관리
# VF를 VM에 passthrough (QEMU/KVM 예시)
# QEMU 인자: -device vfio-pci,host=0000:03:00.2
# representor 위치 확인
ip -n vm1_ns link show enp3s0f0np0_0 2>&1 || echo "올바름: representor가 호스트 netns에 있음"
ip link show enp3s0f0np0_0 && echo "올바름: representor가 호스트에서 보임"
실수 4: inline-mode 설정 누락으로 인한 오프로드 실패
# ━━━ 안티패턴: inline-mode 미설정 ━━━
# inline-mode는 eSwitch가 패킷 파싱 범위를 결정
# ConnectX-5 이전: L4 매칭에 inline-mode transport 필수
# ✗ 잘못된 방법 — inline-mode 없이 L4 필터 설치
tc filter add dev enp3s0f0np0_0 ingress \
protocol ip pref 10 \
flower ip_proto tcp dst_port 80 \
action mirred egress redirect dev enp3s0f0np0_1
# 결과: not_in_hw 표시 (SW에서만 동작)
# ✓ 올바른 방법 — inline-mode를 먼저 설정
devlink dev eswitch set pci/0000:03:00.0 inline-mode transport
# 이후 L4 필터 설치
tc filter add dev enp3s0f0np0_0 ingress \
protocol ip pref 10 \
flower ip_proto tcp dst_port 80 \
action mirred egress redirect dev enp3s0f0np0_1
# 현재 inline-mode 확인
devlink dev eswitch show pci/0000:03:00.0
# pci/0000:03:00.0: mode switchdev inline-mode transport ...
# ConnectX-6 이상: inline-mode network (기본값)으로 L4 매칭 가능
# 별도 설정 불필요 (HW가 자동 L4 파싱)
- switchdev 전환 전 반드시 VF unbind (EBUSY 방지)
- TC flower 규칙의 pref 값을 고유하게 (우선순위 충돌 방지)
- Representor는 항상 호스트 netns에 유지 (VM netns에 넣지 않음)
- L4 매칭 시 inline-mode 확인 (ConnectX-5 이전은 transport 설정 필수)
tc filter show에서 in_hw 플래그 확인 (not_in_hw면 offload 실패)- OVS hw-offload 변경 후 OVS 재시작 필수
Connection Tracking Offload
커널 5.7부터 TC flower의 ct 액션을 통해 Connection Tracking(conntrack)을
eSwitch 하드웨어에 오프로드할 수 있습니다. 이를 통해 상태 기반(stateful) 방화벽(Firewall) 규칙도
라인레이트로 처리할 수 있으며, NAT 변환까지 하드웨어에서 수행합니다.
CT offload 설정
# ━━━ Connection Tracking Offload 설정 ━━━
# 전제: eSwitch switchdev 모드 + OVS hw-offload 활성화
# 1. TC flower CT 규칙 — established 연결을 HW offload
# (ingress: 새 연결은 SW에서 처리, 확립되면 HW로 offload)
tc filter add dev enp3s0f0np0_0 ingress \
protocol ip pref 1 \
flower ct_state +trk+new \
action ct zone 1 \
action mirred egress redirect dev enp3s0f0np0
tc filter add dev enp3s0f0np0_0 ingress \
protocol ip pref 2 \
flower ct_state +trk+est \
action ct zone 1 \
action mirred egress redirect dev enp3s0f0np0
# 2. CT + NAT offload (DNAT 예시)
tc filter add dev enp3s0f0np0 ingress \
protocol ip pref 5 \
flower ct_state +trk+new \
dst_ip 10.0.0.100 \
action ct zone 1 nat dst addr 192.168.1.10 \
action mirred egress redirect dev enp3s0f0np0_0
tc filter add dev enp3s0f0np0 ingress \
protocol ip pref 6 \
flower ct_state +trk+est \
action ct zone 1 \
action mirred egress redirect dev enp3s0f0np0_0
# 3. OVS에서 CT offload 활성화
ovs-vsctl set Open_vSwitch . other_config:tc-policy=skip_sw
ovs-ofctl add-flow br0 "table=0,in_port=1,ip,ct_state=-trk,action=ct(zone=1,table=1)"
ovs-ofctl add-flow br0 "table=1,in_port=1,ip,ct_state=+trk+est,action=output:2"
ovs-ofctl add-flow br0 "table=1,in_port=1,ip,ct_state=+trk+new,action=ct(commit,zone=1),output:2"
# 4. CT offload 상태 확인
ovs-appctl dpctl/dump-flows type=offloaded | grep ct_state
conntrack -L | head -20
cat /proc/net/nf_conntrack | wc -l
CT offload 성능 튜닝
# ━━━ CT Offload 성능 튜닝 ━━━
# 1. conntrack 테이블 크기 조정 (대규모 연결 환경)
sysctl -w net.netfilter.nf_conntrack_max=2097152
sysctl -w net.netfilter.nf_conntrack_buckets=524288
# 2. CT 타임아웃 조정 (HW aging과 일치)
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=3600
sysctl -w net.netfilter.nf_conntrack_udp_timeout=120
# 3. HW CT 테이블 크기 확인
mlxdevm resource show pci/0000:03:00.0 | grep -A5 ct
# 4. CT offload 통계 모니터링
ethtool -S enp3s0f0np0 | grep -E "ct_|offload"
conntrack -C # 현재 연결 수
# 5. CT aging 상태 확인
cat /sys/kernel/debug/mlx5/0000:03:00.0/ct/stats 2>/dev/null
- 커널: 5.7+ (tc ct action), 5.12+ (NAT offload 개선)
- 하드웨어: ConnectX-6 Dx 이상 (CT offload 지원)
- OVS: 2.13+ (ct offload 지원)
- 제한: IPv4 TCP/UDP만 offload 가능 (ICMP, IPv6는 SW fallback)
Multi-host eSwitch: BlueField DPU 연동
NVIDIA BlueField DPU는 SmartNIC에 ARM 프로세서를 탑재하여 자체적으로 eSwitch를 운영합니다. 호스트의 x86 CPU와 독립적으로 네트워크 처리, 보안, 스토리지 가속을 수행하며, eSwitch가 DPU 측에서 관리되어 호스트의 공격 표면을 최소화합니다.
BlueField DPU eSwitch 설정
# ━━━ BlueField DPU eSwitch 구성 ━━━
# DPU ARM 측에서 실행 (ssh로 DPU에 접속)
ssh ubuntu@192.168.100.2 # DPU OOBM IP
# 1. DPU eSwitch 모드 확인
mlxconfig -d /dev/mst/mt41686_pciconf0 q | grep INTERNAL_CPU_MODEL
# INTERNAL_CPU_MODEL = SEPARATED_HOST(1)
# 2. eSwitch switchdev 모드 전환 (DPU 측)
devlink dev eswitch set pci/0000:03:00.0 mode switchdev
# 3. Host VF representor 확인 (DPU 측에서 보임)
ip link show | grep "pf0hpf\|pf0vf"
# pf0hpf : 호스트 PF의 representor (DPU에서)
# pf0vf0 : 호스트 VF0의 representor (DPU에서)
# pf0vf1 : 호스트 VF1의 representor (DPU에서)
# 4. OVS 브릿지 구성 (DPU 측)
ovs-vsctl add-br br-dpu
ovs-vsctl add-port br-dpu p0 # DPU uplink (물리 포트)
ovs-vsctl add-port br-dpu pf0hpf # Host PF representor
ovs-vsctl add-port br-dpu pf0vf0 # Host VF0 representor
ovs-vsctl add-port br-dpu pf0vf1 # Host VF1 representor
# 5. 호스트 PF ↔ 외부 연결 (기본 브릿지)
ovs-ofctl add-flow br-dpu "in_port=p0,action=pf0hpf"
ovs-ofctl add-flow br-dpu "in_port=pf0hpf,action=p0"
# 6. 보안 정책: VF 간 직접 통신 차단
ovs-ofctl add-flow br-dpu "in_port=pf0vf0,dl_dst=ff:ff:ff:ff:ff:ff,action=p0"
ovs-ofctl add-flow br-dpu "in_port=pf0vf0,action=p0" # VF0→외부만 허용
# VF0→VF1 직접 통신 규칙 없음 = 차단
DPU 운영 모드 비교
| 특성 | SEPARATED_HOST | EMBEDDED_CPU |
|---|---|---|
| eSwitch 제어 | DPU ARM | Host x86 |
| 보안 격리 | 높음 (호스트 침해 시에도 정책 유지) | 낮음 (호스트 root가 전체 제어) |
| Representor 위치 | DPU 측 (pf0hpf, pf0vfN) | 호스트 측 (기존 방식) |
| OVS 실행 위치 | DPU ARM | 호스트 x86 |
| 용도 | 클라우드 프로바이더, Zero Trust | 온프레미스, 레거시 호환 |
| 성능 | DPU ARM 코어 제약 (OVS slow path) | 호스트 CPU 사용 |
eSwitch와 DPDK/VPP 연동
DPDK(Data Plane Development Kit)와 VPP(Vector Packet Processing)는 커널 바이패스 방식의 고성능 패킷 처리 프레임워크입니다. eSwitch의 VF representor를 DPDK 포트로 사용하거나, VPP의 dpdk-input 노드와 연결하여 하이브리드 오프로드 아키텍처를 구현할 수 있습니다.
DPDK + OVS-DPDK + eSwitch 구성
# ━━━ OVS-DPDK + eSwitch HW Offload ━━━
# 1. Hugepages 설정 (DPDK 필수)
echo 2048 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
mkdir -p /dev/hugepages
mount -t hugetlbfs hugetlbfs /dev/hugepages
# 2. OVS-DPDK 초기화
ovs-vsctl set Open_vSwitch . other_config:dpdk-init=true
ovs-vsctl set Open_vSwitch . other_config:dpdk-socket-mem=1024
ovs-vsctl set Open_vSwitch . other_config:hw-offload=true
systemctl restart openvswitch-switch
# 3. DPDK 브릿지 생성
ovs-vsctl add-br br-dpdk -- set bridge br-dpdk datapath_type=netdev
# 4. PF를 DPDK 포트로 추가
ovs-vsctl add-port br-dpdk pf -- \
set Interface pf type=dpdk options:dpdk-devargs=0000:03:00.0
# 5. VF representor를 DPDK 포트로 추가
ovs-vsctl add-port br-dpdk vf0_rep -- \
set Interface vf0_rep type=dpdk \
options:dpdk-devargs=0000:03:00.0,representor=vf0
ovs-vsctl add-port br-dpdk vf1_rep -- \
set Interface vf1_rep type=dpdk \
options:dpdk-devargs=0000:03:00.0,representor=vf1
# 6. offload 상태 확인
ovs-appctl dpctl/dump-flows type=offloaded
ovs-appctl dpif/show
VPP + eSwitch 연동
# ━━━ VPP + eSwitch 설정 ━━━
# VPP startup.conf 예시
# /etc/vpp/startup.conf
dpdk {
dev 0000:03:00.0 {
name pf0
num-rx-queues 4
num-tx-queues 4
}
dev 0000:03:00.2 {
name vf0
num-rx-queues 2
}
}
# VPP 시작
systemctl start vpp
# VPP CLI에서 인터페이스 확인
vppctl show interface
# Name Idx State MTU Counter
# GigabitEthernet3/0/0 1 up 9000 ...
# VPP L2 브릿지 도메인 설정
vppctl set interface l2 bridge pf0 1
vppctl set interface l2 bridge vf0 1
# VPP에서 eSwitch representor 사용
vppctl create interface rdma host-if enp3s0f0np0_0 name rep0
vppctl set interface l2 bridge rep0 1
- OVS-DPDK: 가상 스위칭 중심, OpenFlow 규칙 관리, 클라우드 네트워크
- VPP: 고성능 L3/L4 처리, 라우팅/NAT/IPsec, 통신사 네트워크
- 공통: eSwitch HW offload와 결합하면 first-packet은 SW, 이후 HW 처리
eSwitch 커널 소스 분석
eSwitch의 핵심 커널 코드를 분석합니다. mlx5 드라이버의 eSwitch 관련 구현은 drivers/net/ethernet/mellanox/mlx5/core/ 디렉토리에 있으며, 모드 전환, FDB 테이블 관리, TC flower 오프로드가 핵심 경로입니다.
struct mlx5_eswitch — eSwitch 핵심 상태
/* drivers/net/ethernet/mellanox/mlx5/core/eswitch.h */
struct mlx5_eswitch {
struct mlx5_core_dev *dev; /* 부모 PCI 디바이스 */
struct mlx5_nb nb; /* notifier block */
struct mlx5_eswitch_fdb fdb_table; /* FDB 플로우 테이블 */
struct mlx5_vport *vports; /* 모든 vport 배열 */
u16 total_vports; /* 총 vport 수 */
u16 enabled_vports; /* 활성화된 vport 수 */
int mode; /* MLX5_ESWITCH_LEGACY 또는 OFFLOADS */
struct mlx5_esw_offload offloads; /* switchdev 오프로드 상태 */
struct mutex state_lock; /* 모드 전환 동기화 */
};
코드 설명
-
3행
mlx5_core_dev는 mlx5 PCI 디바이스의 최상위 구조체입니다. eSwitch는 이 디바이스의 서브 컴포넌트로,dev->priv.eswitch에서 접근합니다. -
5행
fdb_table은 eSwitch의 Forwarding Database로, HW 플로우 규칙이 저장되는 계층적 플로우 테이블입니다. TC flower 오프로드 규칙은 이 FDB의offloads.slow_fdb/fast_fdb에 설치됩니다. -
7-9행
vports배열은 PF, VF, SF 각각에 대응하는 vport를 관리합니다. 각 vport는 MAC 필터, VLAN 필터, QoS 설정을 독립적으로 가지며,enabled_vports는 현재 활성화된 vport 수입니다. -
11행
mode는MLX5_ESWITCH_LEGACY(SR-IOV 전통 모드) 또는MLX5_ESWITCH_OFFLOADS(switchdev 모드)입니다.devlink eswitch set명령이 이 값을 변경하며, 전환 시 모든 VF를 일시 중지해야 합니다.
mlx5_eswitch_enable_switchdev() — 모드 전환
/* drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c (간략화) */
int mlx5_eswitch_enable_switchdev(struct mlx5_eswitch *esw)
{
/* 1. FDB 오프로드 테이블 생성 */
err = esw_create_offloads_fdb_tables(esw);
/* 2. 모든 vport에 대해 representor 로드 */
mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) {
err = mlx5e_vport_rep_load(esw, vport);
}
/* 3. 모드 전환 완료 */
esw->mode = MLX5_ESWITCH_OFFLOADS;
/* 4. devlink 이벤트 통지 */
mlx5_devlink_traps_register(esw->dev);
return 0;
}
코드 설명
-
5행
esw_create_offloads_fdb_tables()는 eSwitch의 2단계 FDB 파이프라인을 생성합니다. Level 0(fast_fdb)은 TC flower 오프로드 규칙용, Level 1(slow_fdb)은 miss 시 slow-path로 보내는 폴백 규칙용입니다. fast_fdb는auto_grouped_flow_table로 생성되어 HW가 자동으로 규칙을 그룹화합니다. -
8-10행
mlx5e_vport_rep_load()는 각 VF에 대한 representor netdev를 생성하고 등록합니다. 내부적으로alloc_netdev()로 네트워크 디바이스를 할당하고,mlx5e_netdev_ops_rep를 ops로 설정하며,register_netdevice()로 커널에 등록합니다. -
13행
모드를
MLX5_ESWITCH_OFFLOADS로 설정하면 이후 VF 트래픽이 eSwitch의 FDB를 통해 라우팅됩니다. Legacy 모드에서는 L2 MAC 기반의 단순 스위칭만 가능하지만, switchdev 모드에서는 TC flower 규칙으로 세밀한 패킷 제어가 가능합니다.
TC Flower 오프로드 커널 경로
/* net/sched/cls_flower.c — TC flower 규칙 파싱 (간략화) */
static int fl_change(struct net *net, struct Qdisc *sch,
struct nlattr **tca, unsigned long *arg)
{
/* 1단계: netlink 메시지에서 flower 키 파싱 */
err = fl_set_key(net, tb, &fnew->key, &fnew->mask);
/* 2단계: TC 액션 검증 (drop, redirect, mirred 등) */
err = tcf_exts_validate(net, &fnew->exts, tca[TCA_FLOWER_ACT]);
/* 3단계: HW 오프로드 요청 (skip_sw 또는 기본) */
if (!(fnew->flags & TCA_CLS_FLAGS_SKIP_HW)) {
err = fl_hw_replace_filter(tp, fnew);
}
return 0;
}
/* fl_hw_replace_filter → tc_setup_cb_call → 드라이버 콜백 */
static int fl_hw_replace_filter(struct tcf_proto *tp,
struct cls_fl_filter *f)
{
struct flow_cls_offload cls_flower = {};
/* flower key → flow_rule 변환 */
cls_flower.rule = flow_rule_alloc(tcf_exts_num_actions(&f->exts));
tc_cls_flower_offload_flow_rule(&f->key, &f->mask, cls_flower.rule);
/* 드라이버 콜백 체인 호출 */
return tc_setup_cb_call(tp->chain->block, TC_SETUP_CLSFLOWER,
&cls_flower, ...);
/* → mlx5e_rep_setup_tc() → mlx5e_tc_add_fdb_flow() */
}
코드 설명
-
6행
fl_set_key()는 netlink 메시지에서 매칭 키(src/dst IP, port, protocol 등)와 마스크를 파싱합니다. flower 필터의 키는struct fl_flow_key에 저장되며, L2~L4 헤더의 다양한 필드를 조합할 수 있습니다. -
12-13행
skip_hw플래그가 없으면fl_hw_replace_filter()로 HW 오프로드를 시도합니다.skip_sw가 설정되면 SW 경로를 건너뛰고 HW만 사용하며, 오프로드 실패 시 규칙 설치 자체가 실패합니다. -
25-26행
flow_rule_alloc()은 TC의 flower 키/마스크를 일반화된flow_rule구조로 변환합니다. 이 추상화 덕분에 드라이버는 TC 내부 구조를 알 필요 없이flow_rule만 처리하면 됩니다. -
29-30행
tc_setup_cb_call()은 block에 등록된 모든 드라이버 콜백을 순회합니다. mlx5의 경우mlx5e_rep_setup_tc()가 호출되고, 여기서mlx5e_tc_add_fdb_flow()가 flower 규칙을 mlx5의 match/action spec으로 변환하여 FDB에 설치합니다.
devlink eSwitch 모드 설정 경로
/* drivers/net/ethernet/mellanox/mlx5/core/devlink.c (간략화) */
static int mlx5_devlink_eswitch_mode_set(struct devlink *devlink,
u16 mode)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
struct mlx5_eswitch *esw = dev->priv.eswitch;
/* 현재 모드와 동일하면 skip */
if (esw->mode == mode)
return 0;
/* 기존 모드 비활성화 */
mlx5_eswitch_disable(esw);
/* 새 모드 활성화 */
if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV)
err = mlx5_eswitch_enable_switchdev(esw);
else
err = mlx5_eswitch_enable_legacy(esw);
return err;
}
코드 설명
-
2-3행
mlx5_devlink_eswitch_mode_set()은devlink dev eswitch set명령의 커널 진입점입니다. devlink 프레임워크가 netlink 메시지를 파싱한 후 이 콜백을 호출합니다. -
13행
mlx5_eswitch_disable()은 현재 모드의 모든 리소스를 해제합니다. switchdev 모드에서는 모든 representor를 해제하고 FDB 테이블을 삭제하며, VF 트래픽이 일시 중단됩니다. 이것이 모드 전환 전에 VF를 unbind해야 하는 이유입니다. -
16-19행
switchdev 모드 전환 시
mlx5_eswitch_enable_switchdev()가 FDB 테이블 생성, representor 로드, 오프로드 인프라 초기화를 수행합니다. Legacy 모드는 기본 L2 MAC 스위칭만 설정하므로 훨씬 가볍습니다.
Connection Tracking 오프로드 구조체
/* drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c (간략화) */
struct mlx5_tc_ct_priv {
struct mlx5_core_dev *dev;
struct mlx5_flow_table *ct; /* CT 전용 플로우 테이블 */
struct mlx5_flow_table *ct_nat; /* NAT 변환 테이블 */
struct mlx5_flow_table *post_ct; /* CT 이후 후처리 */
struct mapping_ctx *zone_mapping; /* CT zone → HW 레지스터 매핑 */
struct mapping_ctx *labels_mapping; /* CT label → HW 매핑 */
struct rhashtable ct_tuples_ht; /* 5-tuple → CT 엔트리 해시 */
struct rhashtable ct_tuples_nat_ht; /* NAT 변환 후 해시 */
};
코드 설명
-
4-6행
CT 오프로드는 3단계 플로우 테이블 파이프라인을 사용합니다.
ct테이블에서 연결 추적,ct_nat에서 NAT 변환,post_ct에서 후처리(mark 설정, 포워딩 결정)를 수행합니다. 이 분리 덕분에 NAT이 필요 없는 연결은ct_nat을 건너뛸 수 있습니다. -
7-8행
zone_mapping은 소프트웨어의 CT zone 번호를 HW의 제한된 레지스터 공간에 매핑합니다. NIC 하드웨어는 보통 8비트 레지스터만 제공하므로, 소프트웨어의 16비트 zone ID를 압축 매핑해야 합니다. -
9-10행
ct_tuples_ht는rhashtable(resizable hash table)로 구현된 5-tuple 해시 테이블입니다. 새 연결의 첫 패킷이 slow-path에서 conntrack을 생성하면, 이 해시에 등록되고 이후 패킷은 HW에서 직접 매칭됩니다.
VF Representor 생성 흐름
/* drivers/net/ethernet/mellanox/mlx5/core/en_rep.c (간략화) */
static int mlx5e_vport_rep_load(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
{
struct mlx5_eswitch_rep *rep = vport->rep;
struct net_device *netdev;
/* 1. representor netdev 할당 */
netdev = mlx5e_create_netdev(esw->dev, &mlx5e_rep_profile);
/* 2. ops 테이블 설정 */
netdev->netdev_ops = &mlx5e_netdev_ops_rep;
/* 3. send-to-vport 규칙 설치: representor → VF 경로 */
rep->send_to_vport_rule = mlx5_eswitch_create_vport_rx_rule(
esw, rep->vport, netdev);
/* 4. 커널에 등록 */
err = register_netdevice(netdev);
rep->netdev = netdev;
return 0;
}
코드 설명
-
9행
mlx5e_create_netdev()는mlx5e_rep_profile을 사용하여 representor 전용 netdev를 생성합니다. 이 프로필은 일반 NIC 프로필과 달리 RX/TX 큐 수가 적고(보통 1개), ethtool 기능이 제한됩니다. -
15-16행
send_to_vport_rule은 eSwitch FDB에 설치되는 기본 규칙으로, slow-path 패킷을 representor에서 대응하는 VF로 전달합니다. 이 규칙이 없으면 representor로 전송된 패킷이 VF에 도달하지 못합니다. -
19행
register_netdevice()후 representor는 호스트에서enp3s0f0_0같은 이름의 네트워크 인터페이스로 나타납니다. OVS나 TC flower 규칙은 이 인터페이스에 연결하여 VF 트래픽을 제어합니다.
SF(Scalable Function) 생성 경로
/* drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c (간략화) */
static int mlx5_sf_port_new(struct devlink *devlink,
const struct devlink_port_new_attrs *new_attr)
{
/* 1. SF 번호 할당 */
u32 sfnum = new_attr->sfnum;
/* 2. auxiliary_device 생성 */
sf_dev = mlx5_sf_dev_add(dev, sfnum);
/* 3. vport 활성화 (eSwitch에 SF 등록) */
err = mlx5_esw_offloads_sf_vport_enable(esw, sf_dev->vport);
/* 4. representor 생성 */
err = mlx5e_vport_rep_load(esw, vport);
return 0;
}
코드 설명
-
전체
SF(Scalable Function)는 VF의 경량 대안으로, PCIe 가상화 없이 NIC 리소스를 분할합니다.
devlink port add명령이 이 함수를 호출하며, VF처럼 독립적인 네트워크 인터페이스와 representor를 가집니다. -
9행
mlx5_sf_dev_add()는auxiliary_device를 생성하여 auxiliary_bus에 등록합니다. SF는 VF와 달리 PCIe SR-IOV가 아닌 NIC 내부의 기능 분할이므로, 수백 개까지 생성할 수 있고 생성/삭제가 빠릅니다. -
12행
mlx5_esw_offloads_sf_vport_enable()은 새 SF의 vport를 eSwitch에 등록하고 MAC/VLAN 필터를 설정합니다. 이후 SF의 트래픽은 eSwitch FDB를 통해 라우팅되며, TC flower 오프로드 대상이 됩니다.
커널 6.x eSwitch 최신 변경사항
커널 6.x 시리즈에서 eSwitch/switchdev 관련 중요 변경사항을 정리합니다. 새로운 기능과 API 변경, 성능 개선 사항을 포함합니다.
Port Function API (커널 5.18+)
devlink port function API는 VF/SF의 상태, MAC, 로밍 등을 통합 관리하는 인터페이스입니다. 기존의 분산된 sysfs/netlink 인터페이스를 대체합니다.
# ━━━ Port Function API ━━━
# 포트 함수 목록 확인
devlink port function show pci/0000:03:00.0/0
# pci/0000:03:00.0/0: state active hw_addr 00:00:00:00:00:00
# VF MAC 주소 설정 (port function API)
devlink port function set pci/0000:03:00.0/1 hw_addr 52:54:00:01:02:03
# VF 상태 변경
devlink port function set pci/0000:03:00.0/1 state active
devlink port function set pci/0000:03:00.0/1 state inactive
# RoCE 비활성화 (네트워크 전용 VF)
devlink port function set pci/0000:03:00.0/1 roce disable
# migratable 속성 설정 (Live Migration 지원)
devlink port function set pci/0000:03:00.0/1 migratable enable
# IPsec crypto offload 활성화
devlink port function set pci/0000:03:00.0/1 ipsec_crypto enable
devlink port function set pci/0000:03:00.0/1 ipsec_packet enable
Rate Limiting API (커널 5.18+)
devlink rate API를 통해 VF/SF의 대역폭을 세밀하게 제어할 수 있습니다. 기존 ip link의 max_tx_rate보다 유연한 계층적 QoS를 지원합니다.
# ━━━ devlink Rate Limiting ━━━
# 1. rate 노드(그룹) 생성
devlink rate add pci/0000:03:00.0/rate_group_a
# 2. rate 그룹에 대역폭 설정
devlink rate set pci/0000:03:00.0/rate_group_a \
tx_max 50gbit \
tx_share 10gbit
# 3. VF를 rate 그룹에 할당
devlink rate set pci/0000:03:00.0/1 parent rate_group_a
devlink rate set pci/0000:03:00.0/2 parent rate_group_a
# 4. 개별 VF rate 제한
devlink rate set pci/0000:03:00.0/1 \
tx_max 25gbit \
tx_share 5gbit
# 5. rate 설정 확인
devlink rate show pci/0000:03:00.0
# pci/0000:03:00.0/1: tx_max 25gbit tx_share 5gbit parent rate_group_a
# pci/0000:03:00.0/2: tx_max 25gbit tx_share 5gbit parent rate_group_a
# 6. rate 그룹 삭제
devlink rate del pci/0000:03:00.0/rate_group_a
커널 버전별 주요 변경사항
| 커널 버전 | 변경사항 | 영향 |
|---|---|---|
| 5.7 | TC ct action (CT offload) | stateful 방화벽 HW offload 가능 |
| 5.9 | SF (Scalable Function) 도입 | SR-IOV 없이 가상 함수 생성 |
| 5.12 | CT NAT offload 개선 | SNAT/DNAT HW 처리 안정화 |
| 5.15 | devlink rate API | 계층적 QoS 지원 |
| 5.18 | port function hw_addr/state | VF/SF 통합 관리 API |
| 6.0 | port function roce/migratable | 기능별 세분화 제어 |
| 6.2 | port function ipsec_crypto | IPsec 하드웨어 오프로드 |
| 6.4 | eswitch multi-port 지원 | 듀얼 포트 NIC에서 통합 eSwitch |
| 6.6 | TC sample offload 개선 | 패킷 샘플링 HW offload |
| 6.8 | bridge offload 개선 | FDB/MDB 항목 HW offload 확대 |
| 6.10 | eswitch manager 변경 | DPU SEPARATED_HOST 모드 개선 |
대규모 규칙 관리
프로덕션 환경에서 수만~수십만 개의 TC flower 규칙을 관리할 때 고려해야 할 사항과 최적화 기법을 다룹니다. HW 플로우 테이블의 크기 제한, 규칙 설치 속도, 메모리 사용량 등이 핵심 과제입니다.
HW 플로우 테이블 크기 및 제한
# ━━━ 대규모 규칙 관리 ━━━
# 1. HW 플로우 테이블 용량 확인
mlxdevm resource show pci/0000:03:00.0
# flow_table:
# size: 4194304 (4M entries)
# occ: 15234 (현재 사용)
# 2. 대량 규칙 벌크 설치 (배치 모드)
# tc 명령을 반복 실행하면 느림 → 배치 파일 사용
cat <<'EOF' > /tmp/tc_batch.txt
filter add dev enp3s0f0np0_0 ingress protocol ip pref 100 flower dst_ip 10.0.1.0/24 action mirred egress redirect dev enp3s0f0np0
filter add dev enp3s0f0np0_0 ingress protocol ip pref 101 flower dst_ip 10.0.2.0/24 action mirred egress redirect dev enp3s0f0np0
filter add dev enp3s0f0np0_0 ingress protocol ip pref 102 flower dst_ip 10.0.3.0/24 action mirred egress redirect dev enp3s0f0np0
EOF
tc -b /tmp/tc_batch.txt
# 3. 규칙 설치 속도 측정
time for i in $(seq 1000 2000); do
tc filter add dev enp3s0f0np0_0 ingress protocol ip pref $i \
flower dst_ip 10.$((i/256)).$((i%256)).0/24 \
action mirred egress redirect dev enp3s0f0np0
done
# 기대치: ConnectX-6 Dx에서 약 1000~3000 rules/sec
# 4. 현재 규칙 수 확인
tc -s filter show dev enp3s0f0np0_0 ingress | grep -c "filter"
# 5. 규칙 전체 삭제 (재설정 시)
tc qdisc del dev enp3s0f0np0_0 clsact
규칙 최적화 기법
# ━━━ 규칙 최적화 ━━━
# 1. 와일드카드 마스크 활용 (규칙 수 줄이기)
# 10.0.0.0/8 전체를 하나의 규칙으로 커버
tc filter add dev enp3s0f0np0_0 ingress protocol ip pref 1 \
flower dst_ip 10.0.0.0/8 \
action mirred egress redirect dev enp3s0f0np0
# 2. 체인(chain)을 활용한 다단계 매칭
# chain 0: L2 매칭 → chain 1로 점프
tc filter add dev enp3s0f0np0_0 ingress protocol ip pref 1 chain 0 \
flower src_mac 52:54:00:00:00:00/ff:ff:ff:00:00:00 \
action goto chain 1
# chain 1: L3/L4 세부 매칭
tc filter add dev enp3s0f0np0_0 ingress protocol ip pref 1 chain 1 \
flower dst_port 80 \
action mirred egress redirect dev enp3s0f0np0_1
# 3. CT offload로 규칙 수 감소
# 방향별 규칙 2개 → CT established 1개로 통합
tc filter add dev enp3s0f0np0_0 ingress protocol ip pref 1 \
flower ct_state +trk+est \
action ct zone 1 \
action mirred egress redirect dev enp3s0f0np0
# 4. 규칙 통계 비활성화 (규칙 수 대폭 증가 시)
# HW 카운터 비활성으로 테이블 용량 2배 확보
tc filter add dev enp3s0f0np0_0 ingress protocol ip pref 1 \
flower skip_sw no_percpu \
dst_ip 10.0.0.0/24 \
action mirred egress redirect dev enp3s0f0np0
- 규칙 수 목표: ConnectX-6 Dx 기준 100만+ 규칙 가능 (카운터 미사용 시)
- 설치 속도: 배치 모드로 3000+ rules/sec 달성 가능
- 와일드카드 활용: 가능한 넓은 마스크로 규칙 수 최소화
- 체인 활용: 다단계 매칭으로 규칙 공간 효율화
- 모니터링: HW 테이블 사용량을 주기적으로 확인 (overflow 방지)
eSwitch 운영 모니터링
프로덕션 환경에서 eSwitch의 상태를 지속적으로 모니터링하기 위한 핵심 메트릭과 도구들을 정리합니다.
핵심 모니터링 메트릭
# ━━━ eSwitch 모니터링 ━━━
# 1. VF/Representor 트래픽 통계
for rep in $(ip -o link show | grep "np0_" | awk -F: '{print $2}' | tr -d ' '); do
echo "=== $rep ==="
ethtool -S $rep | grep -E "rx_packets|tx_packets|rx_bytes|tx_bytes|rx_dropped|tx_dropped"
done
# 2. eSwitch offload 상태
tc -s filter show dev enp3s0f0np0_0 ingress | grep -E "in_hw|not_in_hw|packets|bytes"
# 3. OVS offload 비율
total=$(ovs-appctl dpctl/dump-flows | wc -l)
offloaded=$(ovs-appctl dpctl/dump-flows type=offloaded | wc -l)
echo "Offload ratio: $offloaded / $total ($((offloaded*100/total))%)"
# 4. HW 플로우 테이블 사용량
mlxdevm resource show pci/0000:03:00.0 2>/dev/null | grep -A2 flow_table
# 5. conntrack offload 상태 (CT offload 사용 시)
conntrack -C
cat /proc/net/nf_conntrack | wc -l
# 6. PCI 오류 확인
lspci -vvv -s 03:00.0 2>/dev/null | grep -i "error\|correctable\|fatal"
# 7. NIC 온도 및 전력
mlxdevm health show pci/0000:03:00.0 reporter fw 2>/dev/null
sensors 2>/dev/null | grep -A5 mlx
알림 기준 설정
| 메트릭 | 경고 임계값 | 위험 임계값 | 확인 명령 |
|---|---|---|---|
| HW 플로우 테이블 사용률 | 70% | 90% | mlxdevm resource show |
| offload 실패율 | 5% | 20% | tc filter show (not_in_hw) |
| representor rx_dropped | 0.1% | 1% | ethtool -S |
| conntrack 테이블 사용률 | 70% | 90% | conntrack -C / nf_conntrack_max |
| PCIe correctable errors | 1/hour | 10/hour | lspci -vvv |
| NIC 온도 | 85C | 95C | sensors / mlxdevm health |
참고자료
커널 공식 문서
- Linux Kernel SwitchDev Documentation — switchdev 드라이버 모델, FDB/MDB 오프로드 API
- Port Representors — VF/SF representor netdev 모델, 메타데이터 전달
- Devlink — eSwitch 모드 전환, 리소스 관리, 파라미터 설정
- TC conntrack action 사용법 — TC flower ct action으로 HW CT offload
- DSA (Distributed Switch Architecture) — 임베디드 스위치 칩 추상화
- mlx5 SwitchDev Mode — mlx5 eSwitch switchdev 모드 상세
- mlx5 드라이버 문서 — ConnectX/BlueField 통합 드라이버 아키텍처
벤더 기술 문서
- NVIDIA Mellanox SwitchDev Mode — ConnectX/BlueField switchdev 설정 가이드
- OVS Hardware Offload Guide — OVS + TC flower HW 오프로드 구성
- NVIDIA Scalable Functions (SF) — SR-IOV VF 대비 SF 장점, eSwitch 통합
- NVIDIA CT Offload — ConnectX-6/7 Connection Tracking HW 오프로드
- Intel E810 eSwitch Configuration Guide — E810 switchdev 모드 설정
- NVIDIA BlueField TC Flower Offload — BlueField DPU TC flower 규칙 HW 오프로드
OVS 통합
- OVS TC Offload Guide — OVS + TC flower offload 설정 및 디버깅
- OVS-DPDK Bridge — DPDK datapath와 eSwitch 비교
- Open vSwitch 공식 사이트 — OVS 프로젝트 홈, 문서, 릴리스
주요 참고 글
- Switchdev: the Linux switching framework (LWN) — switchdev 커널 프레임워크 설계
- TC Flower Hardware Offload (Netdev 0x14) — TC flower offload 아키텍처와 성능
- mlxsw Wiki — Spectrum ASIC SwitchDev 드라이버 개발 가이드
- SwitchDev Memory Model — 하드웨어 플로우 테이블 리소스 모델
커널 소스 경로
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c— mlx5 eSwitch 코어 구현drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c— eSwitch TC offload 로직drivers/net/ethernet/mellanox/mlx5/core/en_rep.c— VF/SF representor netdevdrivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c— Spectrum SwitchDev 구현drivers/net/ethernet/intel/ice/ice_eswitch.c— Intel ice eSwitch 구현net/switchdev/switchdev.c— SwitchDev 코어 프레임워크net/sched/cls_flower.c— TC flower 분류기 (HW offload 진입점)net/sched/act_ct.c— TC conntrack actioninclude/net/switchdev.h— SwitchDev API 헤더include/net/devlink.h— Devlink API 헤더
- SmartNIC/DPU — DPU의 전체 아키텍처와 활용 시나리오
- DPDK — 데이터 평면 개발 키트
- TC (Traffic Control) — 리눅스 트래픽 제어
- Bridge/VLAN/Bonding — 가상 스위칭
관련 문서
- Netfilter Flowtable — Netfilter Flowtable SW/HW 오프로드 메커니즘, conntrack 대비
- NAT (Network Address Translation) — nf_nat 아키텍처, SNAT/DNAT/MASQUERADE, conntrack 연동, n
- eBPF 기반 보안 정책 — eBPF BPF LSM 보안 훅, cgroup_skb 컨테이너 방화벽, Seccomp-BP
- TPROXY 완전 실습 랩 — TCP·UDP·nftables·netns·C epoll 프록시·eBPF·Squid/Envo