Files
document-haness/docs/virtualization/final/.techviz/packet-control-and-data-paths/spec.json
T

545 lines
14 KiB
JSON

{
"version": "1.1",
"id": "packet-control-and-data-paths",
"title": "control/setup path 는 QEMU 를 지나고 data path 는 backend 에 따라 QEMU 를 지나기도 안 지나기도 한다",
"question": "설정하는 경로와 packet 이 흐르는 경로는 어디에서 갈라지고, 그 두 갈래 가운데 어느 쪽이 QEMU 사용자 공간을 지나는가",
"type": "network",
"direction": "LR",
"audience": [
"가상 머신 안의 요청이 느릴 때 계층을 가르려는 사람",
"vhost-net 이 무엇을 우회하는지 확인하려는 사람"
],
"summary": "virsh 에서 시작한 control/setup path 는 libvirt 와 QEMU 를 지나 virtio-net Device Model 에서 backend 를 설정하고, packet 이 흐르는 data path 는 TAP 에서 그 backend 둘 가운데 하나로 갈라져 vhost-net 쪽은 QEMU 사용자 공간을 지나지 않고 virtqueue 로 모인다.",
"alt": "위쪽 줄은 virsh, libvirt, QEMU, virtio-net Device Model 로 이어지는 control/setup path 이고 아래쪽 줄은 Physical NIC 에서 TAP 까지 이어지는 data path 다. 두 줄이 vhost-net 과 QEMU virtio backend 에서 만나 virtqueue 를 지나 Guest 로 모이는 구성도.",
"long_description": "왼쪽에서 오른쪽으로 읽는다. 위쪽 줄이 control/setup path 다. virsh 에서 libvirt 와 QEMU 를 지나 virtio-net Device Model 에 닿고, 그 device model 이 virtual NIC 생성과 feature negotiation, virtqueue 설정, vhost-net backend 설정을 맡는다. 아래쪽 줄이 data path 다. Physical NIC 에서 Physical NIC Driver 와 Linux Bridge, TAP 까지 온다. 두 줄은 네 번째 열 다음에서 만난다. device model 은 점선으로 backend 둘을 설정하고, TAP 은 실선으로 그 둘 가운데 실제로 쓰는 쪽에 packet 을 넘긴다. vhost-net 을 쓰면 packet 은 Host Kernel 안에서 처리돼 QEMU 사용자 공간을 지나지 않고, QEMU virtio backend 를 쓰면 같은 packet 이 QEMU 사용자 공간을 지난다. 어느 쪽이든 virtqueue 에서 만나 Guest 로 올라간다. 이 Host 가 둘 중 어느 backend 를 쓰고 있는지는 그림이 말하지 않는다.",
"source_context": {
"document": "docs/virtualization/final/document.md",
"document_sha256": "8c4ecc64c8cea9a4450ed7131fdd9cb2048dc092b66cd969f6346ed77887c210",
"anchor": {
"kind": "heading",
"value": "125. 최종 기준 구조",
"line": 5695
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "이 절이 세운 것은 방향이 있는 경로 셋이고 그 셋이 같은 device model 과 같은 virtqueue 를 공유한다. SSOT 는 셋을 각각 따로 선 직선으로 적어 두어서 QEMU 가 control 에는 남고 data 에서는 빠질 수 있다는 사실이 한 장에 보이지 않는다. comparison 은 관계선을 지워도 뜻이 남는 자리에 쓰는 문법이라 여기서는 표가 되고, two-zone-pipeline 은 구역을 둘로 못 나눈다 — 여기 갈래는 경계가 아니라 backend 선택이 만든다. component-flow 는 갈라졌다 모이는 경로를 그대로 옮긴다.",
"focus_node": "virtio-net-device-model"
},
"groups": [],
"nodes": [
{
"id": "virsh",
"label": "virsh",
"kind": "cli",
"role": "actor",
"shape": "box",
"details": [
"User"
],
"description": "VM/network 관리 CLI. packet datapath 에는 직접 참여하지 않는다.",
"evidence": [
{
"start_line": 5675,
"end_line": 5675
},
{
"start_line": 5700,
"end_line": 5702
}
],
"assumption": false
},
{
"id": "libvirt",
"label": "libvirt",
"kind": "service",
"role": "service",
"shape": "box",
"description": "VM lifecycle 과 NIC/network configuration 을 관리한다.",
"evidence": [
{
"start_line": 5676,
"end_line": 5676
},
{
"start_line": 5704,
"end_line": 5704
}
],
"assumption": false
},
{
"id": "qemu",
"label": "QEMU",
"kind": "process",
"role": "service",
"shape": "box",
"details": [
"Host Userspace"
],
"description": "실제로 실행되는 프로세스. 이 안에 virtio-net device model 이 있다.",
"evidence": [
{
"start_line": 5679,
"end_line": 5679
},
{
"start_line": 5706,
"end_line": 5706
}
],
"assumption": false
},
{
"id": "virtio-net-device-model",
"label": "virtio-net Device Model",
"kind": "service",
"role": "service",
"shape": "box",
"emphasis": "primary",
"details": [
"virtual NIC 생성",
"feature negotiation",
"virtqueue 설정",
"vhost-net backend 설정"
],
"description": "control/setup path 가 닿는 자리. 장치를 만들고 backend 를 연결한다.",
"evidence": [
{
"start_line": 5679,
"end_line": 5679
},
{
"start_line": 5708,
"end_line": 5713
}
],
"assumption": false
},
{
"id": "physical-nic",
"label": "Physical NIC",
"kind": "hardware",
"role": "source",
"shape": "box",
"description": "밖에서 온 packet 이 처음 닿는 하드웨어.",
"evidence": [
{
"start_line": 5719,
"end_line": 5721
}
],
"assumption": false
},
{
"id": "physical-nic-driver",
"label": "Physical NIC Driver",
"kind": "driver",
"role": "service",
"shape": "box",
"description": "그 하드웨어를 제어하는 Host kernel driver.",
"evidence": [
{
"start_line": 5687,
"end_line": 5687
},
{
"start_line": 5723,
"end_line": 5723
}
],
"assumption": false
},
{
"id": "linux-bridge",
"label": "Linux Bridge /\nRouting / NAT",
"kind": "network",
"role": "service",
"shape": "box",
"description": "L2 software switch 와 L3 routing, 주소 변환이 놓이는 자리.",
"evidence": [
{
"start_line": 5685,
"end_line": 5686
},
{
"start_line": 5725,
"end_line": 5725
}
],
"assumption": false
},
{
"id": "tap",
"label": "TAP",
"kind": "network",
"role": "service",
"shape": "box",
"details": [
"Host-side interface"
],
"description": "VM 의 Ethernet frame 과 Host Linux networking 을 잇는 접점.",
"evidence": [
{
"start_line": 5684,
"end_line": 5684
},
{
"start_line": 5727,
"end_line": 5727
}
],
"assumption": false
},
{
"id": "vhost-net",
"label": "vhost-net",
"kind": "kernel",
"role": "service",
"shape": "box",
"details": [
"Host Kernel"
],
"description": "반복되는 packet datapath 를 Host kernel 에서 처리하는 backend.",
"evidence": [
{
"start_line": 5682,
"end_line": 5682
},
{
"start_line": 5729,
"end_line": 5729
}
],
"assumption": false
},
{
"id": "qemu-virtio-backend",
"label": "QEMU virtio backend",
"kind": "process",
"role": "service",
"shape": "box",
"details": [
"QEMU Userspace"
],
"description": "vhost-net 을 쓰지 않을 때 datapath backend 를 맡는 쪽.",
"evidence": [
{
"start_line": 5681,
"end_line": 5681
},
{
"start_line": 5755,
"end_line": 5755
}
],
"assumption": false
},
{
"id": "virtqueue",
"label": "virtqueue",
"kind": "queue",
"role": "queue",
"shape": "box",
"details": [
"shared queue"
],
"description": "Guest 와 Host backend 가 I/O buffer 를 주고받는 descriptor 기반 공유 큐.",
"evidence": [
{
"start_line": 5680,
"end_line": 5680
},
{
"start_line": 5731,
"end_line": 5731
}
],
"assumption": false
},
{
"id": "guest",
"label": "Guest",
"kind": "service",
"role": "sink",
"shape": "box",
"details": [
"virtio-net Frontend Driver",
"Guest TCP/IP Stack",
"Socket",
"Keycloak"
],
"description": "packet 이 올라가 애플리케이션 socket 에 닿는 쪽.",
"evidence": [
{
"start_line": 5677,
"end_line": 5678
},
{
"start_line": 5733,
"end_line": 5739
}
],
"assumption": false
}
],
"edges": [
{
"id": "virsh-to-libvirt",
"from": "virsh",
"to": "libvirt",
"label": "Control / Setup",
"kind": "control",
"style": "solid",
"evidence": [
{
"start_line": 5675,
"end_line": 5676
},
{
"start_line": 5697,
"end_line": 5704
}
],
"assumption": false
},
{
"id": "libvirt-to-qemu",
"from": "libvirt",
"to": "qemu",
"label": "NIC config",
"kind": "control",
"style": "solid",
"evidence": [
{
"start_line": 5676,
"end_line": 5676
},
{
"start_line": 5704,
"end_line": 5706
}
],
"assumption": false
},
{
"id": "qemu-to-device-model",
"from": "qemu",
"to": "virtio-net-device-model",
"label": "QEMU process",
"kind": "control",
"style": "solid",
"evidence": [
{
"start_line": 5679,
"end_line": 5679
},
{
"start_line": 5706,
"end_line": 5708
}
],
"assumption": false
},
{
"id": "nic-to-driver",
"from": "physical-nic",
"to": "physical-nic-driver",
"label": "Ethernet Frame",
"kind": "data",
"style": "solid",
"evidence": [
{
"start_line": 5684,
"end_line": 5684
},
{
"start_line": 5721,
"end_line": 5723
}
],
"assumption": false
},
{
"id": "driver-to-bridge",
"from": "physical-nic-driver",
"to": "linux-bridge",
"label": "L2 forwarding",
"kind": "data",
"style": "solid",
"evidence": [
{
"start_line": 5685,
"end_line": 5685
},
{
"start_line": 5723,
"end_line": 5725
}
],
"assumption": false
},
{
"id": "bridge-to-tap",
"from": "linux-bridge",
"to": "tap",
"label": "Ethernet Frame",
"kind": "data",
"style": "solid",
"evidence": [
{
"start_line": 5684,
"end_line": 5684
},
{
"start_line": 5725,
"end_line": 5727
}
],
"assumption": false
},
{
"id": "setup-vhost-backend",
"from": "virtio-net-device-model",
"to": "vhost-net",
"label": "vhost-net backend 설정",
"kind": "control",
"style": "dashed",
"evidence": [
{
"start_line": 5713,
"end_line": 5713
},
{
"start_line": 5729,
"end_line": 5729
}
],
"assumption": false
},
{
"id": "setup-qemu-backend",
"from": "virtio-net-device-model",
"to": "qemu-virtio-backend",
"label": "",
"kind": "control",
"style": "dashed",
"evidence": [
{
"start_line": 5681,
"end_line": 5681
},
{
"start_line": 5713,
"end_line": 5713
}
],
"assumption": false
},
{
"id": "tap-to-vhost",
"from": "tap",
"to": "vhost-net",
"label": "vhost-net 사용",
"kind": "data",
"style": "solid",
"evidence": [
{
"start_line": 5716,
"end_line": 5716
},
{
"start_line": 5727,
"end_line": 5729
}
],
"assumption": false
},
{
"id": "tap-to-qemu-backend",
"from": "tap",
"to": "qemu-virtio-backend",
"label": "",
"kind": "data",
"style": "solid",
"evidence": [
{
"start_line": 5742,
"end_line": 5742
},
{
"start_line": 5753,
"end_line": 5755
}
],
"assumption": false
},
{
"id": "vhost-to-virtqueue",
"from": "vhost-net",
"to": "virtqueue",
"label": "Data Path",
"kind": "data",
"style": "solid",
"evidence": [
{
"start_line": 5716,
"end_line": 5716
},
{
"start_line": 5729,
"end_line": 5731
}
],
"assumption": false
},
{
"id": "qemu-backend-to-virtqueue",
"from": "qemu-virtio-backend",
"to": "virtqueue",
"label": "Data Path",
"kind": "data",
"style": "solid",
"evidence": [
{
"start_line": 5742,
"end_line": 5742
},
{
"start_line": 5755,
"end_line": 5757
}
],
"assumption": false
},
{
"id": "virtqueue-to-guest",
"from": "virtqueue",
"to": "guest",
"label": "frontend",
"kind": "data",
"style": "solid",
"evidence": [
{
"start_line": 5677,
"end_line": 5677
},
{
"start_line": 5731,
"end_line": 5739
}
],
"assumption": false
}
],
"legend": [],
"metadata": {
"rationale": "이 절이 세운 것은 control/setup path와 두 data path가 device model·backend·virtqueue에서 갈라지고 다시 만나는 구조다. component-flow와 LR를 사용하면 이 관계를 상자 충돌 없이 보존한다. NIC config는 NIC/network configuration의 축약이고 frontend는 도착 노드의 virtio-net Frontend Driver를 반복하지 않기 위한 edge 축약이다. backend 선택이라는 핵심 의미와 QEMU userspace 우회 여부는 node/edge 구조로 그대로 남는다."
}
}