Lab 3 · 20 กรกฎาคม 2569

Mininet — ทดสอบ Delay, Jitter, Loss และ Throughput

สร้างเน็ตเวิร์คจำลองด้วย Mininet บน Ubuntu ARM ใน Parallels แล้วบิดค่าลิงก์ด้วย tc netem — หน่วงเวลา ใส่ jitter ทำแพ็กเก็ตหาย แล้ววัดผลด้วย ping และ iperf3

อ่าน ~26 นาที ทำจริง ~2 ชม. ออกสอบข้อ 4 (15 คะแนน)
สรุปแลปนี้ใน 30 วินาที

ทำอะไร — แลปนี้ไม่มีอุปกรณ์จริงและไม่เกี่ยวกับ GNS3 เลย ทุกอย่างรันในลินุกซ์: สร้างโฮสต์ 4 ตัว สวิตช์ 2 ตัวด้วย Mininet แล้วใช้ tc netem ใส่ delay / jitter / loss ลงบน h1-eth0 แล้ววัดว่าเลขที่ ping กับ iperf3 รายงานเปลี่ยนไปยังไง

ได้อะไร — อ่านผล ping เป็นว่าตัวไหนคือ delay ตัวไหนคือ jitter ตัวไหนคือ loss และเข้าใจว่าทำไม TCP ถึงช้าลงเมื่อ RTT หรือ loss สูงขึ้น

ออกสอบตรงไหน — ข้อ 4 (15 คะแนน) ตรง ๆ ทั้งข้อ: สร้าง topology ตามรูปที่ 17 → ping ให้ครบทุกโหนด → (a) delay 100ms 10ms บน h1-eth0 เทียบก่อน/หลัง (b) loss 20% แล้ว ping · เปิด §3.20 อ่านก่อนเข้าห้องสอบ

3.1เป้าหมายและสิ่งที่ต้องส่ง

ใบแลปหัวข้อ 1 เขียนวัตถุประสงค์ไว้ 5 ข้อ — เมื่อทำเสร็จนักศึกษาจะสามารถ

  1. อธิบายความหมายและที่มาของค่า Delay, Jitter, Packet Loss, Bandwidth และ Throughput ได้อย่างถูกต้อง
  2. ใช้งานมินิเน็ตเพื่อจำลองเน็ตเวิร์คและปรับแต่งพารามิเตอร์ของลิงก์ด้วยคำสั่ง tc/netem
  3. วัดและบันทึกค่าประสิทธิภาพของเน็ตเวิร์คด้วยคำสั่ง ping และโปรแกรม iperf3
  4. วิเคราะห์ความสัมพันธ์ระหว่าง Delay, Jitter, Loss กับ Throughput ของ TCP โดยอ้างอิงหลักการทางทฤษฎี
  5. เปรียบเทียบผลการทดลองที่ได้จากการจำลองบนมินิเน็ตกับการทดสอบบนอุปกรณ์จริง
#สิ่งที่ใบแลปสั่งอยู่ที่ไหน
1เตรียมระบบ — ใบแลปเขียนว่า Ubuntu 18.04+ บน Windows 10/11 ผ่าน VMware Workstation Player 16 ใช้บน Mac ไม่ได้ → เราใช้ Ubuntu ARM บน Parallels แทน§3.3
2ติดตั้ง Mininet — git clone แล้ว install.sh พร้อม option -a / -nfv / -s§3.4
3สร้างเน็ตเวิร์คผ่าน GUI (MiniEdit) — ส่วนประกอบ 7 อย่าง, กำหนด IP 2 วิธี§3.5
4การเรียกชื่อโฮสต์และสวิตซ์ — h1-eth0, s1-eth1 และเรื่อง namespace / veth§3.6
5ทดสอบเน็ตเวิร์คที่สร้างขึ้น — Run → เปิด Terminal ของ h1 → ifconfig → ping§3.7
6Traffic Control (tc/netem) — เพิ่ม/แก้/ลบ delay, jitter, loss§3.8
7Iperf3 — โหมด server/client และความหมายของทุกคอลัมน์ในผลลัพธ์§3.9
8การทดลอง 8.1–8.5 — Delay, Jitter, Loss, Iperf3 และอุปกรณ์จริง ตัวข้อสอบ§3.10–§3.15
9สรุปผลการทดลอง — กรอกตารางที่ 1 แล้วอภิปรายอ้างอิงทฤษฎีในหัวข้อ 2§3.16
ค่าที่ใช้จริงในหน้านี้ — แทนเลขจากรหัส 673040128-3 ให้แล้ว

ใบแลปข้อ 8.1 เขียนว่า "กำหนด IP address ของเน็ตเวิร์คตามหมายเลขรหัสนักศึกษาของตนเอง" — ใช้กติกาเดียวกับ Lab 1/2 คือ x = เลขหลังขีด = 3 และ y = สามตัวก่อนขีด mod 254 = 128 mod 254 = 128 ได้วง 192.3.128.0/24

โหนดIPInterfaceต่อกับ
h1192.3.128.1/24h1-eth0 ตัวที่ใส่ netems1-eth1
h2192.3.128.2/24h2-eth0s1-eth2
h3192.3.128.3/24h3-eth0s2-eth1
h4192.3.128.4/24h4-eth0s2-eth2
s1 ↔ s2—s1-eth3 ↔ s2-eth3สายระหว่างสวิตช์

ทุกโหนดอยู่วงเดียวกัน /24 จึง ไม่ต้องมี router และไม่ต้องตั้ง gateway — สวิตช์สองตัวต่อกันตรง ๆ ทำงานเป็นเลเยอร์ 2 อย่างเดียว

3.2ทฤษฎีพื้นฐาน: ประสิทธิภาพของเครือข่าย

ใบแลปหัวข้อ 2 ให้อ่านก่อนเริ่มทดลอง เพราะทุกตัวเลขที่จะวัดในแลปนี้มีชื่อและที่มาชัดเจน

2.1 ความหน่วง (Delay) และองค์ประกอบของความหน่วง

ความหน่วงปลายทางถึงปลายทาง (end-to-end delay) ประกอบด้วยความหน่วงย่อยหลายส่วน ตามรูปที่ 1 ของใบแลป

Processing Delay

เวลาที่โหนดใช้ในการประมวลผลเฮดเดอร์ของแพ็กเก็ต — อ่านปลายทาง ตรวจ checksum ตัดสินใจว่าจะส่งออกทางไหน

Queuing Delay

เวลาที่แพ็กเก็ตต้องรอในคิวก่อนถูกส่งออก — ขึ้นกับปริมาณทราฟฟิกที่คับคั่งในขณะนั้น (ตัวเดียวที่แปรผันตามโหลด จึงเป็นต้นเหตุหลักของ jitter)

Transmission Delay

เวลาที่ใช้ดันข้อมูลทั้งหมดออกทางลิงก์ คำนวณจาก L / R โดย L = ขนาดแพ็กเก็ต (bit) และ R = Bandwidth (bit/s)

Propagation Delay

เวลาที่สัญญาณเดินทางผ่านตัวกลาง คำนวณจาก d / s โดย d = ระยะทาง และ s = ความเร็วของสัญญาณในตัวกลาง

ความหน่วงรวม = Σ (Processing + Queuing + Transmission + Propagation) รูปที่ 1 ของใบแลป

Transmission delay — แทนค่าจริง

L = 1500 ไบต์ = 12,000 bit · R = 100 Mbit/s
L/R = 12,000 / 100,000,000 = 0.12 ms
ถ้าลิงก์เป็น 1 Gbit/s จะเหลือ 0.012 ms — เร็วขึ้น 10 เท่าตามความเร็วลิงก์

Propagation delay — แทนค่าจริง

d = 200 km = 200,000 m · s ≈ 2×108 m/s ในสายไฟเบอร์
d/s = 200,000 / 2×108 = 1 ms
ไม่ขึ้นกับขนาดแพ็กเก็ตเลย — ขึ้นกับระยะทางอย่างเดียว

ใบแลปสรุปไว้ว่า คำสั่ง tc/netem จะเพิ่มค่า Transmission/Propagation Delay เทียมเข้าไปบนอินเตอร์เฟซที่กำหนด เพื่อจำลองสถานการณ์ที่โหนดอยู่ห่างกันทางภูมิศาสตร์ หรือลิงก์มีคุณภาพต่ำ

2.2 ความแปรปรวนของความหน่วง (Jitter)

Jitter คือความแปรปรวนของค่า Delay ในแต่ละแพ็กเก็ต ที่ส่งออกไป ตามรูปที่ 2 ของใบแลป — หากค่า Delay คงที่ทุกแพ็กเก็ต (กรณีอุดมคติ) ผู้รับจะสามารถเล่นข้อมูลได้อย่างต่อเนื่อง แต่หากมี Jitter สูง แพ็กเก็ตจะมาถึงไม่สม่ำเสมอ ซึ่งส่งผลกระทบรุนแรงต่อแอปพลิเคชันแบบเรียลไทม์ เช่น VoIP หรือวิดีโอคอล

ส่วนขยาย — ทำไม jitter ถึงฆ่า VoIP แต่ไม่ฆ่าการโหลดไฟล์

โปรแกรมเรียลไทม์ต้องเล่นเสียงออกลำโพงทุก 20 ms พอดี ถ้าแพ็กเก็ตมาช้าไปกว่าคิวเล่น (jitter buffer) ที่เตรียมไว้ ก็ต้องทิ้งไปเลย → เสียงขาด · ส่วนการโหลดไฟล์ TCP แค่เอาไปต่อกันในบัฟเฟอร์ มาช้าก็แค่รอ ไม่มีอะไรเสียหาย — ฉะนั้น jitter กระทบ VoIP มากกว่ากระทบ throughput (ข้อนี้ใบแลปถามไว้ในคำถามข้อ 8.2)

2.3 การสูญหายของแพ็กเก็ต (Packet Loss)

Packet Loss คือสัดส่วนของแพ็กเก็ตที่ส่งออกไปแต่ไม่สามารถไปถึงปลายทางได้ ใบแลประบุสาเหตุหลักไว้ 3 อย่าง

  • Buffer overflow ที่อุปกรณ์กลางทาง — คิวเต็ม แพ็กเก็ตใหม่ถูกทิ้ง
  • ข้อผิดพลาดของสัญญาณ (bit error) ที่ทำให้ต้องทิ้งแพ็กเก็ต
  • Congestion บนเส้นทาง

สำหรับ TCP การสูญหายของแพ็กเก็ตจะกระตุ้นกลไก Congestion Control ให้ลดขนาด Congestion Window (Cwnd) ลง ส่งผลให้ Throughput ลดลงตามไปด้วย

2.4 Bandwidth และ Throughput

Bandwidth

ความสามารถสูงสุดทางทฤษฎีที่ลิงก์รองรับได้ (bit/s) — เป็นตัวเลขบนกระดาษ เช่น "1 Gbit/s"

Throughput

อัตราการส่งข้อมูลจริงที่วัดได้ ซึ่งน้อยกว่าหรือเท่ากับ Bandwidth เสมอ เพราะมี Overhead ของโปรโตคอล, Delay, Jitter และ Packet Loss เข้ามาเกี่ยวข้อง

รูปที่ 3 ของใบแลปแสดงความสัมพันธ์นี้ด้วยสูตรประมาณของ Mathis et al.

Throughput ≈ MSSRTT √Loss รูปที่ 3 ของใบแลป — สูตรประมาณของ Mathis et al.
กราฟเส้นโค้งสีน้ำเงินลาดลงจากซ้ายบนไปขวาล่าง แกนตั้งกำกับว่า สูง ที่ด้านบนและ ต่ำ ที่ด้านล่าง แกนนอนกำกับว่า Delay/Loss น้อย ทางซ้ายและ Delay/Loss มาก ทางขวา มีเส้นประโยงจากแกนตั้งไปยังจุดบนเส้นโค้งสองจุด
รูปที่ 3 จากใบแลป Lab 3 — ความสัมพันธ์ระหว่าง Delay/Loss กับ Throughput ของ TCP · แกนตั้งคือ Throughput (สูง → ต่ำ) แกนนอนคือ RTT / Loss rate · เส้นโค้งตกเร็วมากในช่วงแรก — แปลว่า delay/loss เพิ่มขึ้นนิดเดียวตอนที่ยังน้อย ก็ทำให้ throughput ตกฮวบแล้ว
สัญลักษณ์ความหมายค่าที่ใช้จริง
MSSMaximum Segment Size — ข้อมูลสูงสุดที่ใส่ได้ใน 1 เซกเมนต์ TCP1460 ไบต์ = 11,680 bit (MTU 1500 − IP 20 − TCP 20)
RTTRound-Trip Time — เวลาไป-กลับ ตัวเดียวกับ avg ที่ ping รายงานวัดได้จาก ping หน่วยเป็นวินาที
Lossอัตราการสูญหายของแพ็กเก็ต (สัดส่วน ไม่ใช่เปอร์เซ็นต์)loss 1% → 0.01 · loss 20% → 0.20
แทนค่าจริง — เห็นชัดว่าอะไรทำร้าย throughput มากกว่า
กรณีRTTLossคำนวณThroughput ≈
baseline0.2 ms1%11680 / (0.0002 × 0.1)584 Mbit/s
ใส่ delay100 ms1%11680 / (0.1 × 0.1)1.17 Mbit/s ตก 500 เท่า
ใส่ loss หนัก100 ms20%11680 / (0.1 × 0.447)0.26 Mbit/s ตกอีก 4.5 เท่า

จากสูตรจะเห็นว่า Throughput ของ TCP แปรผกผันกับ RTT (เพิ่ม RTT 2 เท่า → throughput ครึ่งเดียว) และแปรผกผันกับรากที่สองของอัตราการสูญหาย (loss เพิ่ม 4 เท่า → throughput ครึ่งเดียว) ซึ่งนักศึกษาจะได้พิสูจน์ความสัมพันธ์นี้ด้วยตนเองในหัวข้อ 8.4

จุดที่คนพลาดบ่อย — สูตร Mathis ใช้ไม่ได้ตอน loss = 0

ถ้าแทน Loss = 0 ตัวส่วนเป็นศูนย์ → throughput เป็นอนันต์ ซึ่งเป็นไปไม่ได้ · สูตรนี้ใช้ได้เฉพาะตอนมี loss จริง ในกรณี loss = 0 ตัวจำกัดจะกลายเป็นขนาดหน้าต่างหารด้วย RTT แทน (Throughput ≤ Window / RTT) ซึ่งเป็นสาเหตุที่ iperf3 ตกจาก 40 Gbit/s เหลือหลักร้อย Mbit/s ทันทีที่ใส่ delay 100 ms ทั้งที่ยังไม่มี loss สักแพ็กเก็ต (ส่วนหลังเป็นส่วนขยาย ไม่ได้อยู่ในใบแลป)

3.3เตรียมระบบ — เส้นทางของ MacBook Air M2

ใบแลปหัวข้อ 3 เขียนไว้ว่า ให้ใช้ Ubuntu 18.04 ขึ้นไป บน Windows 10/11 ทำงานภายใต้ VMware Workstation Player 16 (หรือใช้ WSL ก็ได้) แล้วสั่งให้ปิด Hyper-V ผ่าน Turn Windows features on or off ก่อนติดตั้ง

ทั้งย่อหน้าข้างบนใช้กับ MacBook ไม่ได้เลยสักบรรทัด

① ไม่มี VMware Workstation Player บน macOS (ตัว Player เป็นของ Windows/Linux เท่านั้น) ② ไม่มี Hyper-V และไม่มี Windows Features บน Mac ③ ไม่มี WSL ④ ISO ของ Ubuntu ที่ใบแลปให้โหลดเป็น amd64 ซึ่งบูตบน M2 ไม่ขึ้น ต้องใช้ arm64
→ เส้นทางของเราคือ Parallels Desktop + Ubuntu ARM แล้วสั่งงานผ่าน ssh ubuntu จาก Terminal ของ macOS

ถ้ายังไม่เคยลง ให้ทำตาม หน้าติดตั้ง §0.8 ก่อน — สรุปสั้น ๆ คือ

  1. ลง Parallels Desktop (หรือ UTM ถ้าไม่อยากจ่ายเงิน) — ทั้งคู่ใช้ Apple Virtualization บน M2 ได้
  2. สร้าง VM จาก Ubuntu สำหรับ ARM64 — Parallels มีตัวเลือกดาวน์โหลด Ubuntu ARM ให้ในหน้าสร้าง VM เลย ไม่ต้องไปหา ISO เอง
  3. เปิด SSH ใน VM แล้วตั้งชื่อย่อ ubuntu ไว้ใน ~/.ssh/config ของ macOS เพื่อให้พิมพ์แค่ ssh ubuntu
    [macOS Terminal] — ~/.ssh/config
    Host ubuntu
        HostName 10.211.55.7   # IP ของ VM ดูด้วย ip -br a ใน Ubuntu
        User <ชื่อผู้ใช้ใน Ubuntu>
  4. ทดสอบว่าติด
    [macOS Terminal]
    $ ssh ubuntu
    $ ssh ubuntu 'sudo mn --test pingall'   # ต้องได้ 0% dropped
รูปที่ 4–6 ของใบแลป (ฝั่ง Windows) — กดดูได้ แต่ทำตามไม่ได้บน Mac

สามรูปนี้เป็นหน้าจอของ Windows ล้วน ๆ ใส่ไว้เพื่อให้รู้ว่าเพื่อนในห้องเห็นอะไร บน MacBook จะไม่มีหน้าจอเหล่านี้เลย — ให้ทำตามขั้นตอน Parallels ด้านบนแทน

หน้าต่าง Turn Windows features on or off ของ Windows แสดงรายการฟีเจอร์พร้อมช่องติ๊ก โดยมีรายการ Hyper-V ที่ถูกกางออกเห็น Hyper-V Management Tools และ Hyper-V Platform ซึ่งต้องเอาเครื่องหมายถูกออก
รูปที่ 4 จากใบแลป Lab 3 — ยกเลิกการใช้งาน Hyper-V (หน้าจอฝั่ง Windows — บน Mac ไม่มีสิ่งนี้ ดูขั้นตอน Mac ด้านบน)
หน้าต่างต้อนรับของ VMware Workstation 16 Player บน Windows ด้านซ้ายเป็นรายการเครื่องเสมือน Home, modern, ubuntu_18 ด้านขวามีเมนู Create a New Virtual Machine, Open a Virtual Machine, Upgrade to VMware Workstation Pro และ Help
รูปที่ 5 จากใบแลป Lab 3 — โปรแกรม VMware Workstation Player เวอร์ชัน 16 (ฝั่ง Windows — บน Mac ใช้ Parallels Desktop หรือ UTM แทน)
หน้าต่าง New Virtual Machine Wizard ของ VMware Workstation 16 Player เลือก Installer disc image file (iso) ชี้ไปที่ไฟล์ ubuntu-18.04.4-desktop-amd64 พร้อมข้อความ Ubuntu 64-bit 18.04.4 detected
รูปที่ 6 จากใบแลป Lab 3 — ติดตั้งอูบันตูจากไฟล์อิมเมจที่ดาวน์โหลดไว้ (ฝั่ง Windows · สังเกตว่าไฟล์เป็น amd64 ซึ่งบูตบน Apple Silicon ไม่ขึ้น ต้องใช้ arm64)

3.4ติดตั้งมินิเน็ต

ใบแลปหัวข้อ 4 บอกว่ามินิเน็ตโหลดได้ 2 ทาง — โหลดเป็นเวอร์ชวลแมชชีนสำเร็จรูปจาก mininet.org หรือโหลดจากซอร์ซโค้ดโดยตรง ซึ่งใบแลปเลือกวิธีหลังเพราะจะได้มินิเน็ตเวอร์ชันล่าสุด

[Ubuntu VM] — คำสั่งตามใบแลปเป๊ะ ๆ
modern@ubuntu:~$ git clone git://github.com/mininet/mininet
จุดที่คนพลาดบ่อย — git:// ใช้ไม่ได้แล้ว

GitHub ปิดโปรโตคอล git:// แบบไม่เข้ารหัสไปตั้งแต่ปี 2022 คัดลอกบรรทัดในใบแลปไปวางตรง ๆ จะค้างแล้วขึ้น Connection timed out หรือ The unauthenticated git protocol … is no longer supported · ให้เปลี่ยนเป็น https://

[Ubuntu VM] — แก้แล้ว
$ git clone https://github.com/mininet/mininet

เมื่อโหลดเสร็จ ติดตั้งด้วย ./mininet/util/install.sh [option] โดย option เป็นเงื่อนไขของการติดตั้ง

optionติดตั้งอะไร
-aติดตั้งทั้งหมด — มินิเน็ต, โอเพนวีสวิตซ์ (Open vSwitch), โอเพนโฟลว์ (OpenFlow), ไวร์ชาร์ก (Wireshark) และคอนโทรลเลอร์ POX ใบแลปแนะนำอันนี้
-nfvติดตั้งเฉพาะ มินิเน็ต, โอเพนโฟลว์ และโอเพนวีสวิตซ์
-s mydirกำหนดตำแหน่งในการติดตั้ง
[Ubuntu VM] — ผลลัพธ์ตัวอย่างในใบแลป
modern@ubuntu:~$ ./mininet/util/install.sh -nfv
Detected Linux distribution: Ubuntu 18.04 bionic amd64
sys.version_info(major=2, minor=7, micro=17, releaselevel=final, serial=0)
Detected Python (python) version 2
Installing Mininet dependencies
[sudo] password for modern:

ใบแลปย้ำว่า แนะนำให้ใช้ -a เพื่อให้ใช้ Open vSwitch, OpenFlow, Wireshark และคอนโทรลเลอร์ POX ได้ในบทถัดไป · และสำหรับ Ubuntu 18.04 ให้ติดตั้ง net-tools ด้วยเพื่อใช้คำสั่ง ifconfig

[Ubuntu VM] — ตามใบแลป
modern@ubuntu:~$ sudo apt install net-tools
ทางลัดที่เร็วกว่าและปลอดภัยกว่าบน Ubuntu ARM (ส่วนขยาย)

บน Ubuntu รุ่นใหม่ (20.04 ขึ้นไป) แพ็กเกจ mininet อยู่ใน apt อยู่แล้ว และคอมไพล์มาสำหรับ arm64 เรียบร้อย — ไม่ต้องรัน install.sh ซึ่งบางขั้นยังสมมติว่าเป็น x86 อยู่

[Ubuntu VM] — เส้นทางที่แนะนำสำหรับ M2
$ sudo apt update
$ sudo apt install -y mininet openvswitch-switch iperf3 net-tools ethtool
$ sudo mn --version          # ดูว่าลงสำเร็จ
$ sudo mn --test pingall      # ต้องได้ *** Results: 0% dropped (2/2 received)

ต้องมี iperf3 และ ethtool ด้วย — ตัวแรกใช้ในหัวข้อ 8.4 ตัวหลังใช้ปิด offload ก่อนวัดค่า (§3.8) ทั้งคู่ไม่ได้มากับ Mininet

3.5สร้างเน็ตเวิร์คผ่าน GUI (MiniEdit)

ใบแลปหัวข้อ 5 บอกว่ามินิเน็ตจัดเตรียมการใช้งานผ่าน GUI เพื่อให้สร้างเน็ตเวิร์คที่ต้องการได้โดยง่าย

[Ubuntu VM] — ต้องรันในโฟลเดอร์ mininet
modern@ubuntu:~/mininet$ sudo examples/miniedit.py
จุดที่ Mac ต่าง — MiniEdit เป็นหน้าต่าง X11 จะไม่โผล่ผ่าน ssh ubuntu เฉย ๆ

MiniEdit เขียนด้วย Tkinter คือโปรแกรมกราฟิกของลินุกซ์ ถ้า ssh ubuntu ธรรมดาแล้วสั่งรัน จะขึ้น _tkinter.TclError: no display name and no $DISPLAY environment variable
ทางที่ง่ายที่สุด: เปิดหน้าต่าง VM ของ Parallels แล้วรัน MiniEdit ในเดสก์ท็อปของ Ubuntu เอง · ทางเลือก: ลง XQuartz บน macOS แล้ว ssh -Y ubuntu ก่อน
แต่ในห้องสอบไม่ต้องใช้ MiniEdit เลย — สร้าง topology ด้วยสคริปต์ Python เร็วกว่าและไม่พึ่ง GUI → §3.10

หน้าต่างโปรแกรม MiniEdit มีแถบเมนู File Edit Run Help ด้านซ้ายเป็นแถบเครื่องมือแนวตั้งมีไอคอนลูกศร โฮสต์ สวิตช์ เลกาซีสวิตช์ ลิงก์ และคอนโทรลเลอร์ พื้นที่ตรงกลางว่างเปล่า มุมล่างซ้ายมีปุ่ม Run สีเขียวและ Stop สีแดง
รูปที่ 7 จากใบแลป Lab 3 — หน้าต่าง GUI บนมินิเน็ต (แถบเครื่องมือแนวตั้งด้านซ้ายคือทั้งหมดที่ต้องใช้ · ปุ่ม Run/Stop อยู่มุมล่างซ้าย)

ส่วนประกอบสำคัญที่ใบแลประบุไว้ 7 อย่าง

#ปุ่มใช้ทำอะไร
1Selectสำหรับเลื่อนหรือลบอุปกรณ์
2Hostสำหรับสร้างโฮสต์ (h1, h2, …)
3Switchสำหรับใช้งานโอเพนโฟลว์สวิตซ์ (ต้องมีคอนโทรลเลอร์)
4Legacy switchสำหรับสวิตซ์ปกติ — เรียนรู้ MAC เองเหมือนสวิตช์ทั่วไป ไม่ต้องมีคอนโทรลเลอร์
5Linkสำหรับเชื่อมต่ออุปกรณ์ — ลากจากอุปกรณ์หนึ่งไปอีกอุปกรณ์หนึ่ง
6Runเริ่มการทำงานของโปรแกรมเลียนแบบ
7Stopหยุดการทำงานของโปรแกรมเลียนแบบ

5.1 เน็ตเวิร์คอย่างง่าย

หน้าต่าง MiniEdit แสดงเน็ตเวิร์คอย่างง่าย มีโฮสต์ h1 อยู่ซ้าย สวิตช์ s1 อยู่กลาง และโฮสต์ h2 อยู่ขวา เชื่อมกันด้วยเส้นสีน้ำเงินสองเส้น
รูปที่ 8 จากใบแลป Lab 3 — ตัวอย่างการสร้างเน็ตเวิร์คบนมินิเน็ต (h1 — s1 — h2)

เมื่อสร้างเน็ตเวิร์คแล้ว กำหนด IP address ให้แต่ละโหนดได้ 2 วิธี

① กำหนดแอดเดรสเอง (ทีละโหนด)

คลิกขวาที่โหนดนั้น → Properties → กรอกช่อง IP Address เช่น 192.168.1.1/24

② กำหนดหมายเลขแบบอัตโนมัติ (ทั้งวง)

เมนู Edit → Preferences → ช่อง IP Base ค่าดีฟอลต์คือ 10.0.0.0/8 ให้เปลี่ยนเป็นที่ต้องการ (ใบแลปกำหนดเป็น 192.168.1.0/24)

หน้าต่าง MiniEdit เปิดเมนูคลิกขวาที่โฮสต์ h1 เห็น Host Options และ Properties พร้อมหน้าต่าง Properties ที่มีแท็บ Properties, VLAN Interfaces, External Interfaces, Private Directories และช่องกรอก Hostname เป็น h1 กับ IP Address เป็น 192.168.1.1/24
รูปที่ 9 จากใบแลป Lab 3 — การกำหนดแอดเดรสเอง (คลิกขวาที่โหนด → Properties → ช่อง IP Address ต้องใส่ prefix /24 ต่อท้ายด้วย)
หน้าต่าง Preferences ของ MiniEdit มีช่อง IP Base เป็น 192.168.1.0/24 ช่อง Default Terminal เป็น xterm ช่อง Default Switch เป็น Open vSwitch Kernel Mode และกลุ่มตัวเลือก OpenFlow 1.0 ถึง 1.3
รูปที่ 10 จากใบแลป Lab 3 — การกำหนดหมายเลขแบบอัตโนมัติ (Edit → Preferences → IP Base · ช่อง Default Terminal = xterm คือหน้าต่างที่จะเปิดตอนเลือก Terminal ของโฮสต์)
ส่วนขยาย — ค่านี้ตรงกับแฟล็กของคำสั่ง mn

ช่อง IP Base ในหน้า Preferences คือของอย่างเดียวกับแฟล็ก --ipbase ของคำสั่ง mn · ฉะนั้น sudo mn --ipbase 192.3.128.0/24 ให้ผลเหมือนกับการไปเปลี่ยนช่องนี้ใน GUI — ในห้องสอบใช้แฟล็กเร็วกว่ามาก

3.6การเรียกชื่อโฮสต์/สวิตซ์ และสิ่งที่เกิดขึ้นข้างใน

โฮสต์

แต่ละโฮสต์ที่สร้างในมินิเน็ตจะมีเนมสเปซ (network namespace) ของตนเองพร้อมเวอร์ชวลอินเตอร์เฟซ โดยทั่วไปใช้ชื่อ h1..hN — โฮสต์ 1 มีอินเตอร์เฟซ h1-eth0 โฮสต์ 2 มี h2-eth0
การตั้งค่าอินเตอร์เฟซต้องผ่านทางเนมสเปซของโฮสต์นั้นเท่านั้น

สวิตซ์

กำหนดชื่อ s1..sN โดยอินเตอร์เฟซแรกเป็น s1-eth1 และอินเตอร์เฟซที่ 2 เป็น s1-eth2 · หากมีสวิตซ์ใหม่ (s2) จะเป็น s2-eth1 และ s2-eth2
การเข้าถึงอินเตอร์เฟซของสวิตซ์ทำผ่าน "root" namespace ได้เลย

แผนภาพสองส่วน ด้านซ้ายเป็นมุมมองเชิงตรรกะ โฮสต์ h1 มี h1-eth0 ต่อผ่าน s1-eth1 เข้าสวิตช์ s1 แล้วออก s1-eth2 ไปยัง h2-eth0 ของโฮสต์ h2 ด้านขวาเป็นมุมมองจริงในลินุกซ์ กล่อง root network namespace บรรจุโปรเซส mn, ofdatapath, ofprotocol, controller และอินเตอร์เฟซ s1-eth1 s1-eth2 ส่วนกล่องล่างเป็น h2 namespace และ h3 namespace ที่มี /bin/bash และอินเตอร์เฟซของตัวเอง เชื่อมกันด้วย veth pairs
รูปที่ 11 จากใบแลป Lab 3 — โครงสร้างและการทำงานภายในมินิเน็ต (ซ้าย = ภาพที่เราคิด · ขวา = ของจริงในลินุกซ์: สวิตช์กับตัว mn อยู่ใน root namespace ส่วนโฮสต์แต่ละตัวอยู่ใน namespace แยก เชื่อมกันด้วย veth pairs)
ทำไมเรื่อง namespace ถึงสำคัญกับแลปนี้

เพราะ h1-eth0 ไม่มีตัวตนใน Ubuntu ปกติ — มันอยู่ในเนมสเปซของ h1 เท่านั้น ถ้าเปิดเทอร์มินัลของ Ubuntu แล้วพิมพ์ sudo tc qdisc add dev h1-eth0 … ตรง ๆ จะได้ Cannot find device "h1-eth0" · ต้องสั่งผ่าน Mininet CLI (mininet> h1 tc …) หรือใน xterm ของ h1 เท่านั้น · ลองพิสูจน์ด้วย ip -br a ใน Ubuntu จะเห็นแต่ s1-eth1, s1-eth2 ที่อยู่ใน root namespace ไม่เห็น h1-eth0 เลย

3.7ทดสอบเน็ตเวิร์คที่สร้างขึ้น

ใบแลปหัวข้อ 5.3 — หลังจากสร้างเน็ตเวิร์คที่ต้องการ ให้ไปที่เมนู Run หรือคลิกปุ่ม Run

มุมล่างซ้ายของหน้าต่าง MiniEdit ขยายให้เห็นปุ่ม Run ตัวอักษรสีเขียว และปุ่ม Stop ตัวอักษรสีแดง เรียงกันในแนวตั้ง
รูปที่ 12 จากใบแลป Lab 3 — การเริ่มการทำงานของมินิเน็ต (กด Run · ตอนเลิกต้องกด Stop ทุกครั้ง ไม่งั้น veth ค้างในระบบ)

จากนั้นไปที่โฮสต์ h1 และ h2 คลิกขวา → Terminal เพื่อเรียกใช้คำสั่งต่าง ๆ

หน้าต่าง MiniEdit ด้านบนแสดงเมนูคลิกขวาที่โฮสต์ h1 มี Host Options และ Terminal ด้านล่างเป็นหน้าต่างเทอร์มินัลชื่อ Host: h1 ที่มี prompt root@ubuntu:/home/modern/mininet/examples#
รูปที่ 13 จากใบแลป Lab 3 — หน้าต่าง Terminal ของ h1 (สังเกต prompt เป็น root@ — ในเทอร์มินัลของโฮสต์คือ root อยู่แล้ว ไม่ต้องพิมพ์ sudo)
ผลลัพธ์คำสั่ง ifconfig ในเทอร์มินัลของโฮสต์ h1 แสดงอินเตอร์เฟซ h1-eth0 มี flags UP BROADCAST RUNNING MULTICAST mtu 1500 inet 192.168.1.1 netmask 255.255.255.0 และอินเตอร์เฟซ lo คือ loopback 127.0.0.1
รูปที่ 14 จากใบแลป Lab 3 — ผลลัพธ์คำสั่ง ifconfig (มีแค่ 2 อินเตอร์เฟซ: h1-eth0 กับ lo เพราะอยู่คนละ namespace กับเครื่องจริง)

การตรวจสอบการเชื่อมต่อทำได้โดยใช้คำสั่ง ping ตามด้วย IP address ของโหนดปลายทาง

ผลลัพธ์คำสั่ง ping 192.168.1.2 จากโฮสต์ h1 แสดงบรรทัด 64 bytes from 192.168.1.2 icmp_seq ตั้งแต่ 1 ถึง 6 ttl 64 time ระหว่าง 0.047 ถึง 0.206 ms ตามด้วยสถิติ 6 packets transmitted 6 received 0% packet loss time 5126ms และ rtt min avg max mdev เท่ากับ 0.047 0.127 0.206 0.051 ms
รูปที่ 15 จากใบแลป Lab 3 — ผลลัพธ์คำสั่ง ping ระหว่าง h1 และ h2 (นี่คือ ค่า baseline ที่ต้องบันทึกไว้เทียบกับตอนใส่ netem)

อ่านผล ping ให้เป็น — ตัวไหนคือ delay ตัวไหนคือ jitter ตัวไหนคือ loss

[Host: h1] — ตัวเลขชุดนี้คัดจากรูปที่ 15 ของใบแลป
--- 192.3.128.3 ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5126ms
rtt min/avg/max/mdev = 0.047/0.127/0.206/0.051 ms
#              ↑        ↑      ↑      ↑
#            เร็วสุด   avg = DELAY  ช้าสุด   mdev = JITTER
อยากได้ค่าอะไรดูตัวเลขไหนอธิบาย
Delay (RTT)avg ในบรรทัด rtt min/avg/max/mdevเวลาเฉลี่ยไป-กลับของทุกแพ็กเก็ตที่ได้คำตอบ · นี่คือค่าที่ใบแลปสั่งให้บันทึก ในข้อ 8.1
Jittermdev ตัวสุดท้ายความแปรปรวนของ RTT ในชุดนี้ · ยิ่งมากยิ่งไม่สม่ำเสมอ · ping ไม่ได้พิมพ์คำว่า "jitter" ตรง ๆ ต้องอ่านจาก mdev
Packet Loss% packet loss ในบรรทัดก่อนหน้าคิดจาก (transmitted − received) / transmitted · จะแม่นก็ต่อเมื่อยิงแพ็กเก็ตเยอะพอ (ใบแลปจึงสั่ง -c 150)
min / maxตัวแรกและตัวที่สามใช้ดูว่าค่ากระจายกว้างแค่ไหน · ช่วง max − min กว้างมาก = jitter สูง
จุดที่คนพลาดบ่อย — mdev ไม่เท่ากับตัวเลข jitter ที่สั่ง netem

ตั้ง delay 100ms 10ms แล้วคาดว่าจะเห็น mdev = 10 — ไม่ใช่ · 10ms ที่ใส่คือครึ่งความกว้างของช่วงสุ่ม (แต่ละแพ็กเก็ตหน่วงสุ่มระหว่าง 90–110 ms) ส่วน mdev คือส่วนเบี่ยงเบนของค่าเหล่านั้น ซึ่งจะได้ราว ๆ 5–6 ms ไม่ใช่ 10 · ดูภาพเคลื่อนไหวใน §3.8 ประกอบ

3.8Traffic Control (tc/netem)

Traffic Control (tc) เป็นยูทิลิตีของลินุกซ์ที่ใช้กำหนดค่า Packet Scheduler ของ Kernel ทำให้สามารถจำลองสภาวะเน็ตเวิร์คที่หลากหลาย เช่น การหน่วงเวลา การสูญหายของแพ็กเก็ต และการจำกัด Bandwidth

[รูปแบบคำสั่งตามใบแลป]
sudo tc qdisc [add|del|replace|change|show] dev dev_id root netem opts
ส่วนของคำสั่งคืออะไร
sudoรันคำสั่งด้วยสิทธิ์ผู้ดูแลระบบ (ใน Mininet CLI และใน xterm ของโฮสต์เป็น root อยู่แล้ว จะพิมพ์หรือไม่ก็ได้)
tcคำสั่งสำหรับจัดการ NETEM
qdiscqueue discipline คือกฎที่กำหนดลำดับการส่งแพ็กเก็ตที่มาจาก IP protocol output
add | del | replace | change | showการกระทำต่อ qdisc — add เพื่อเพิ่ม delay, change/del เพื่อเปลี่ยนหรือลบ delay
dev_idอินเตอร์เฟซที่ต้องการจำลองสภาวะ เช่น h1-eth0
rootติดกฎไว้ที่รากของคิวขาออก (egress) ของอินเตอร์เฟซนั้น
netemNetwork Emulator — โมดูลที่ทำหน้าที่หน่วง/ทิ้ง/ทำซ้ำแพ็กเก็ต
optsค่าของ delay, packet loss, duplication, corruption และอื่น ๆ

6.1 การเพิ่มค่าต่าง ๆ — คำสั่งครบชุดตามใบแลป

[Host: h1] หรือ [mininet> h1 …] — คัดลอกได้ทันที
# ── เพิ่ม Delay 100 ms (add) ─────────────────────────────
sudo tc qdisc add dev h1-eth0 root netem delay 100ms

# ── แก้ไขค่าเดิมเป็น 50 ms (change) — ไม่ต้องลบก่อน ──────
sudo tc qdisc change dev h1-eth0 root netem delay 50ms

# ── ลบค่าที่ติดตั้งทั้งหมด (del) ─────────────────────────
sudo tc qdisc del dev h1-eth0 root netem

# ── เพิ่ม Jitter ±10 ms (delay 100 ms, jitter 10 ms) ────
sudo tc qdisc add dev h1-eth0 root netem delay 100ms 10ms

# ── เพิ่ม Packet Loss 10% ────────────────────────────────
sudo tc qdisc add dev h1-eth0 root netem loss 10%

# ── ตรวจว่าติดจริงไหม (ส่วนขยาย — ควรทำทุกครั้ง) ────────
sudo tc qdisc show dev h1-eth0
# qdisc netem 8001: root refcnt 2 limit 1000 delay 100ms  10ms
คำสั่งย่อยใช้ตอนไหนข้อควรระวัง
addยังไม่มี qdisc อยู่บน interface นั้นถ้ามีอยู่แล้วจะขึ้น RTNETLINK answers: File exists → ใช้ change หรือ del ก่อน
changeมี qdisc อยู่แล้วและอยากเปลี่ยนค่าถ้ายังไม่มีจะขึ้น No such file or directory
replaceไม่อยากคิดว่ามีอยู่หรือยัง ปลอดภัยที่สุดทำงานได้ทั้งสองกรณี — ในห้องสอบใช้อันนี้เลย
delล้างค่าก่อนวัดรอบใหม่ถ้าไม่มีอะไรอยู่จะขึ้น No such file or directory — ไม่ใช่ error ร้ายแรง ข้ามได้
showยืนยันว่าค่าติดแล้วถ้าเห็นแค่ qdisc noqueue หรือ qdisc fq_codel = netem ยังไม่ติด
จุดที่คนพลาดบ่อย ① — netem ที่ root ทำงานเฉพาะขาออก

กฎที่ติดด้วย root อยู่บนคิวขาออก (egress) ของ h1-eth0 เท่านั้น — ICMP echo request ที่ h1 ส่งออกไปจะโดนหน่วง 100 ms แต่ reply ที่วิ่งกลับเข้ามา ไม่โดนหน่วง
→ RTT ที่ ping รายงานจึงเพิ่มขึ้นราว 100 ms ไม่ใช่ 200 ms · ถ้าอยากให้ครบ 200 ms ต้องไปใส่ที่ปลายทางด้วย (h3 tc qdisc add dev h3-eth0 root netem delay 100ms)

จุดที่คนพลาดบ่อย ② — --link tc,delay=100ms ให้ผลคนละเรื่องกับข้อสอบ

ถ้าสั่ง sudo mn --topo … --link tc,delay=100ms มินิเน็ตจะใส่ netem ให้ ปลายทั้งสองข้างของทุกลิงก์ · เส้นทาง h1→h3 ผ่าน 3 ลิงก์ ไป-กลับจึงโดนหน่วง 6 ครั้ง = 600 ms ไม่ใช่ 100 ms
ข้อสอบสั่งว่า "ใส่ delay บน h1-eth0" → ต้องใช้ tc ใส่เองที่ interface เดียว ห้ามใช้ --link tc,delay=

ต้องทำก่อนวัดทุกครั้ง — ปิด offload ไม่งั้นตัวเลขเพี้ยน

การ์ดและไดรเวอร์สมัยใหม่มีฟีเจอร์ TSO / GSO / GRO ที่รวมแพ็กเก็ตหลายใบเป็นก้อนใหญ่ก้อนเดียว (ได้ถึง 64 KB) ก่อนส่งให้เคอร์เนล — netem จึงเห็นเป็น "1 แพ็กเก็ต" แล้วหน่วง/ทิ้งทั้งก้อน ทำให้ค่า delay และ loss ที่วัดได้ไม่ตรงกับที่ตั้งไว้

[mininet>] — ทำกับทุกโฮสต์ที่จะวัด
mininet> h1 ethtool -K h1-eth0 tso off gso off gro off
mininet> h3 ethtool -K h3-eth0 tso off gso off gro off

ถ้าทำบนการ์ดจริงใน Ubuntu VM (หัวข้อ 8.5) ชื่อ interface จะเป็นแบบ enxaca7f1a9ff44 ไม่ใช่ eth0

[Ubuntu VM] — การ์ด USB-C Ethernet ตัวจริง
$ ip -br a                       # หาชื่อจริงก่อนเสมอ
$ IF=enxaca7f1a9ff44
$ sudo ethtool -K $IF tso off gso off gro off

เจาะลึก jitter — ทำไม mdev ถึงไม่ใช่ 10

ส่วนขยาย — ที่มาของเลข 5.8 (ไม่ได้อยู่ในใบแลป)

delay 100ms 10ms ทำให้ netem สุ่มค่าหน่วงแบบสม่ำเสมอ (uniform) ในช่วง 90–110 ms · ค่าเบี่ยงเบนมาตรฐานของการแจกแจงสม่ำเสมอที่มีครึ่งความกว้าง a คือ a/√3

mdev ≈ a√3 = 101.732 ≈ 5.8 ms ส่วนขยาย — ใช้ตอบคำถามข้อ 8.2.1 ได้เต็ม ๆ

อยากให้กระจายแบบโค้งระฆังเหมือนเน็ตจริงมากกว่า ให้เติม distribution normal ต่อท้าย · อยากให้ค่าติดกันเป็นช่วง ๆ (correlation) เติมเปอร์เซ็นต์ตัวที่สาม เช่น delay 100ms 10ms 25%

[mininet>] — ส่วนขยาย
mininet> h1 tc qdisc replace dev h1-eth0 root netem delay 100ms 10ms distribution normal
จุดที่คนพลาดบ่อย ③ — ใส่ jitter แล้วเลข icmp_seq สลับที่

netem สุ่มเวลาหน่วงให้แต่ละแพ็กเก็ตแยกกัน แพ็กเก็ตที่ได้เลขน้อยจึงแซงแพ็กเก็ตที่ได้เลขมากได้ — ใน ping จะเห็น icmp_seq ไม่เรียง เช่น 4, 6, 5, 7 · นี่คืออาการปกติของ jitter ไม่ใช่ของเสีย และเป็นเหตุผลว่าทำไม jitter ถึงทำร้ายแอปเรียลไทม์ (ต้องเรียงลำดับใหม่ก่อนเล่น)

3.9Iperf3

Iperf3 เป็นเครื่องมือวัดและทดสอบประสิทธิภาพของเครือข่าย โดยเฉพาะความเร็วของการส่งและรับข้อมูล พัฒนาโดยกลุ่มวิศวกรรมคอมพิวเตอร์ที่มหาวิทยาลัย California เป็นซอฟต์แวร์โอเพนซอร์ส ทดสอบได้ทั้งแบบทิศทางเดียวหรือสองทิศทาง บน TCP หรือ UDP และกำหนดระยะเวลา ขนาดข้อมูล และพารามิเตอร์อื่น ๆ ได้ตามต้องการ ทำงานในรูปแบบไคลเอนต์ (-c) และเซิร์ฟเวอร์ (-s)

เทอร์มินัลสองหน้าต่างวางคู่กัน ซ้ายรันคำสั่ง iperf3 -s แล้วขึ้นข้อความ Server listening on 5201 ขวารันคำสั่ง iperf3 -c 10.0.0.2 แล้วแสดงตาราง ID Interval Transfer Bitrate Retr Cwnd โดยช่วง 0.00 ถึง 1.00 วินาที โอนได้ 5.18 GBytes ที่ 44.5 Gbits ต่อวินาที Retr เป็น 0 และ Cwnd เป็น 843 KBytes
รูปที่ 16 จากใบแลป Lab 3 — การทดสอบด้วย Iperf3 (ฝั่งซ้ายต้องรัน iperf3 -s ค้างไว้ก่อน แล้วฝั่งขวาถึงจะต่อได้ · ตัวเลข 44.5 Gbits/sec คือ throughput ของลิงก์เสมือนที่ไม่ได้จำกัดอะไรเลย)
[รูปแบบคำสั่งตามใบแลป]
iperf3 [-s | -c] [ options ]

# ── ฝั่งเซิร์ฟเวอร์ ─────────────────────────────
iperf3 -s

# ── ฝั่งไคลเอนต์ (เซิร์ฟเวอร์อยู่ที่ 10.0.0.2) ──
iperf3 -c 10.0.0.2

# ── ไคลเอนต์ ทดสอบเป็นเวลา 5 วินาที ────────────
iperf3 -c 10.0.0.2 -t 5

ผลลัพธ์ที่ได้ประกอบด้วย 6 คอลัมน์ตามที่ใบแลประบุ

คอลัมน์ความหมายตามใบแลปใช้ตอบอะไรในการทดลอง
IDหมายเลขการเชื่อมต่อไม่ต้องสนใจ ถ้าเปิดสตรีมเดียวจะมีเลขเดียว
Intervalช่วงเวลาการแสดงผลบรรทัดสุดท้ายที่เขียน 0.00-5.00 sec คือสรุปรวม — ใช้บรรทัดนี้กรอกตาราง
Transferปริมาณข้อมูลที่ส่งในช่วงเวลานั้นช่องที่ 1 ของตารางที่ 1
Bitrateทรูพุต (throughput) ที่ได้ช่องที่ 2 ของตารางที่ 1 — ตัวเลขหลักที่ต้องเทียบทุกกรณี
Retrจำนวนแพ็กเก็ตที่ส่งใหม่ (retransmission)ช่องที่ 3 ของตารางที่ 1 — ตัวชี้วัดว่ามี loss เกิดขึ้นจริง ยิ่ง loss สูง Retr ยิ่งพุ่ง
Cwndขนาดของ congestion window (เฉพาะ TCP)ดูได้โดยตรงว่า Congestion Control หด window ลงจริงไหมเมื่อมี loss
ส่วนขยาย — วิธีรัน iperf3 ใน Mininet CLI ให้ไม่ค้าง

iperf3 -s จะค้างรอไปเรื่อย ๆ ถ้าพิมพ์ใน Mininet CLI ตรง ๆ จะกด Ctrl-C ออกยาก · ให้ใส่ -D (daemon) หรือ & ต่อท้าย แล้วค่อยสั่งฝั่งไคลเอนต์

[mininet>]
mininet> h2 iperf3 -s -D                # เปิดเซิร์ฟเวอร์ค้างไว้เบื้องหลัง
mininet> h1 iperf3 -c 192.3.128.2 -t 5   # ยิงจาก h1 ไปหา h2 นาน 5 วินาที
mininet> h2 pkill iperf3                 # ปิดเซิร์ฟเวอร์เมื่อเลิกใช้

3.10การทดลอง — โทโพโลยีตามรูปที่ 17

ใบแลปหัวข้อ 8 เขียนสั้น ๆ ว่า "จากรูปที่ 17 ให้นักศึกษาสร้างเน็ตเวิร์คและทดสอบการตั้งค่าต่อไปนี้" — รูปนี้คือโจทย์ทั้งข้อ และเป็นรูปเดียวกับที่ข้อสอบข้อ 4 อ้างถึง

โทโพโลยีสำหรับการทดลอง: โฮสต์ h1 อยู่บนซ้ายและ h2 อยู่ล่างซ้าย ทั้งคู่ต่อเข้าสวิตช์ s1 ที่อยู่กลางซ้าย · สวิตช์ s1 ต่อกับสวิตช์ s2 ที่อยู่กลางขวาด้วยเส้นเดียว โดยมีข้อความกำกับว่า h1-eth0 (ทดสอบ delay/jitter/loss) · โฮสต์ h3 อยู่บนขวาและ h4 อยู่ล่างขวา ทั้งคู่ต่อเข้าสวิตช์ s2 · รวมทั้งหมดเป็นโฮสต์ 4 ตัว สวิตช์ 2 ตัว และลิงก์ 5 เส้น
รูปที่ 17 จากใบแลป Lab 3 — โทโพโลยีสำหรับการทดลอง (ต้องสร้างตามรูปนี้ในข้อสอบข้อ 4) · ป้าย h1-eth0 (ทดสอบ delay/jitter/loss) ในรูปหมายถึงอินเตอร์เฟซของ h1 คือจุดที่จะติด netem ไม่ใช่ชื่อของสายระหว่างสวิตช์
นับให้ชัด — รูปที่ 17 ต้องสร้างอะไร กี่ตัว
สิ่งที่ต้องสร้างจำนวนรายละเอียด
โฮสต์ (Host)4h1, h2 อยู่ฝั่งซ้าย · h3, h4 อยู่ฝั่งขวา
สวิตช์ (Switch)2s1 ฝั่งซ้าย · s2 ฝั่งขวา
ลิงก์ (Link)5h1–s1 · h2–s1 · h3–s2 · h4–s2 · s1–s2 (เส้นกลางที่เชื่อมสองฝั่งเข้าด้วยกัน)
Router0ทุกโหนดอยู่วง 192.3.128.0/24 เดียวกัน → ไม่ต้องมี router ไม่ต้องตั้ง gateway
Controller0ใช้สวิตช์แบบ failMode=standalone ให้ทำงานเป็นสวิตช์เรียนรู้ MAC ธรรมดา → §3.19

วิธีที่ 1 — สคริปต์ Python แนะนำสำหรับห้องสอบ

วิธีนี้ดีที่สุดเพราะได้ชื่อโหนดเป็น h1–h4 เป๊ะตามรูป จึงมี h1-eth0 ให้ใส่ netem ตามที่โจทย์สั่ง และตั้ง IP ตามรหัสนักศึกษาไปในตัว · ก็อปทั้งบล็อกนี้วางในเทอร์มินัลได้เลย มันจะสร้างไฟล์ให้เอง

[Ubuntu VM] — คัดลอกทั้งก้อนวางครั้งเดียว สร้างไฟล์ lab3.py
cat > ~/lab3.py <<'EOF'
#!/usr/bin/env python3
# Lab 3 — topology ตามรูปที่ 17 : h1,h2 -- s1 -- s2 -- h3,h4
from mininet.net import Mininet
from mininet.node import OVSKernelSwitch
from mininet.cli import CLI
from mininet.log import setLogLevel

def run():
    net = Mininet(controller=None, switch=OVSKernelSwitch, autoSetMacs=True)

    # ── โฮสต์ 4 ตัว · IP จากรหัส 673040128-3 → 192.3.128.0/24 ──
    h1 = net.addHost('h1', ip='192.3.128.1/24')
    h2 = net.addHost('h2', ip='192.3.128.2/24')
    h3 = net.addHost('h3', ip='192.3.128.3/24')
    h4 = net.addHost('h4', ip='192.3.128.4/24')

    # ── สวิตช์ 2 ตัว · standalone = ทำงานเองได้ ไม่ต้องมี controller ──
    s1 = net.addSwitch('s1', failMode='standalone')
    s2 = net.addSwitch('s2', failMode='standalone')

    # ── ลิงก์ 5 เส้น · ลำดับนี้ทำให้ได้ h1-eth0 และ s1-eth1..3 ──
    net.addLink(h1, s1)      # h1-eth0 <-> s1-eth1
    net.addLink(h2, s1)      # h2-eth0 <-> s1-eth2
    net.addLink(h3, s2)      # h3-eth0 <-> s2-eth1
    net.addLink(h4, s2)      # h4-eth0 <-> s2-eth2
    net.addLink(s1, s2)      # s1-eth3 <-> s2-eth3

    net.start()
    # ปิด offload ทุกโฮสต์ ไม่งั้น netem วัดค่าเพี้ยน
    for h in (h1, h2, h3, h4):
        h.cmd('ethtool -K %s-eth0 tso off gso off gro off' % h.name)
    CLI(net)
    net.stop()

if __name__ == '__main__':
    setLogLevel('info')
    run()
EOF
[Ubuntu VM] — รันแล้วจะตกเข้า Mininet CLI ทันที
$ sudo mn -c                  # ล้างของค้างจากรอบก่อนเสมอ
$ sudo python3 ~/lab3.py
# *** Adding hosts: h1 h2 h3 h4
# *** Adding switches: s1 s2
# *** Adding links: (h1, s1) (h2, s1) (h3, s2) (h4, s2) (s1, s2)
# *** Starting CLI:
mininet>

วิธีที่ 2 — คำสั่ง mn บรรทัดเดียว

[Ubuntu VM] — เร็วแต่มีข้อจำกัด อ่านกล่องเตือนข้างล่างก่อน
$ sudo mn --topo linear,2,2 --controller none \
       --switch ovsk,failMode=standalone --ipbase 192.3.128.0/24 --mac
จุดที่คนพลาดบ่อย — linear,2,2 ตั้งชื่อโฮสต์ไม่เหมือนรูป

--topo linear,k,n = สวิตช์ k ตัวเรียงกัน แต่ละตัวมีโฮสต์ n ตัว → รูปร่างตรงกับรูปที่ 17 พอดี แต่เมื่อ n มากกว่า 1 มินิเน็ตจะตั้งชื่อโฮสต์เป็น h1s1, h2s1, h1s2, h2s2 ไม่ใช่ h1–h4
ผลคือ ไม่มีอินเตอร์เฟซชื่อ h1-eth0 — พอสั่ง tc … dev h1-eth0 จะได้ Cannot find device "h1-eth0" ซึ่งเป็นสิ่งที่ข้อสอบสั่งตรง ๆ
→ ในห้องสอบใช้วิธีที่ 1 (สคริปต์ Python) · ถ้าจำเป็นต้องใช้วิธีนี้จริง ๆ ให้เปลี่ยนคำสั่งเป็น dev h1s1-eth0 แทน

วิธีที่ 3 — MiniEdit (GUI)

วางไอคอน Host 4 ตัว, Legacy switch 2 ตัว แล้วลาก Link 5 เส้นตามรูป · ตั้ง IP ทีละตัวด้วยคลิกขวา → Properties หรือเปลี่ยน IP Base ที่ Edit → Preferences ก่อน แล้วกด Run · ต้องมีหน้าจอกราฟิก ดูข้อจำกัดของ Mac ที่ §3.5

ตรวจว่าโทโพโลยีถูกก่อนไปต่อ

[mininet>] — สามคำสั่งนี้ต้องผ่านก่อนเริ่มทดลอง
mininet> net
# h1 h1-eth0:s1-eth1
# h2 h2-eth0:s1-eth2
# h3 h3-eth0:s2-eth1
# h4 h4-eth0:s2-eth2
# s1 lo:  s1-eth1:h1-eth0 s1-eth2:h2-eth0 s1-eth3:s2-eth3
# s2 lo:  s2-eth1:h3-eth0 s2-eth2:h4-eth0 s2-eth3:s1-eth3

mininet> dump
# <Host h1: h1-eth0:192.3.128.1 pid=...>   ← ตรวจว่า IP ถูกทุกตัว

mininet> pingall
# *** Results: 0% dropped (12/12 received)   ← 4 โฮสต์ = 4x3 = 12 คู่
ทำไมต้องเป็น 12/12

pingall ยิงจากทุกโหนดไปทุกโหนดที่เหลือ — โฮสต์ 4 ตัว ได้ 4 × 3 = 12 คู่ · ถ้าเห็น 0% dropped (12/12 received) แปลว่าข้อกำหนด "ping ได้ทุกโหนด" ของข้อสอบผ่านแล้ว ให้ถ่ายรูป/คัดลอกบรรทัดนี้เก็บไว้ทันที

ส่วนขยาย — Mininet CLI แทนชื่อโหนดเป็น IP ให้เอง

พิมพ์ h1 ping -c 4 h3 ได้เลย ไม่ต้องจำ IP — CLI จะแทน h3 ด้วย 192.3.128.3 ให้อัตโนมัติ · แต่ในรายงานควรเขียน IP เต็ม เพื่อให้เห็นว่าตั้ง IP ตามรหัสนักศึกษาจริง

3.11การทดลอง 8.1 — ทดสอบ Delay

ใบแลปสั่งไว้ 7 ขั้น ทำตามลำดับนี้แล้วบันทึกค่าทุกครั้ง

  1. กำหนด IP address ของเน็ตเวิร์คตามหมายเลขรหัสนักศึกษา — ทำไปแล้วในสคริปต์ (192.3.128.1–.4)
  2. ตรวจสอบข้อมูลอินเตอร์เฟซของทุกโหนดด้วย ifconfig
    [mininet>]
    mininet> h1 ifconfig
    mininet> h2 ifconfig
    mininet> h3 ifconfig
    mininet> h4 ifconfig
    # ต้องเห็น h1-eth0 มี inet 192.3.128.1 netmask 255.255.255.0 (เทียบรูปที่ 14)
    # ถ้าไม่มี net-tools ให้ใช้  h1 ip -br a  แทน ได้ผลเหมือนกัน
  3. ping จาก h1 ไป h3 — บันทึก min/avg/max/mdev baseline
    [mininet>] — ก่อนใส่ netem
    mininet> h1 ping -c 10 192.3.128.3
    # --- 192.3.128.3 ping statistics ---
    # 10 packets transmitted, 10 received, 0% packet loss, time 9200ms
    # rtt min/avg/max/mdev = 0.047/0.127/0.206/0.051 ms   ← ระดับที่ควรเห็น
  4. ping จาก h2 ไป h4 — บันทึกค่า
    [mininet>]
    mininet> h2 ping -c 10 192.3.128.4
  5. เพิ่ม delay ที่ h1-eth0 เป็น 100 ms แล้ว ping h1 → h3 อีกครั้ง
    [mininet>] — หัวใจของข้อสอบข้อ 4(a)
    mininet> h1 tc qdisc add dev h1-eth0 root netem delay 100ms
    mininet> h1 tc qdisc show dev h1-eth0     # ยืนยันว่าติดแล้ว
    mininet> h1 ping -c 10 192.3.128.3
    # rtt min/avg/max/mdev = 100.0/100.1/100.3/0.08 ms   ← เพิ่มขึ้น ~100 ไม่ใช่ ~200
  6. ping h1 → h3 พร้อมกับ ping h2 → h3 ในเวลาเดียวกัน แล้วเทียบกับข้อ 3
    [mininet>] — ใส่ & ให้ตัวแรกวิ่งเบื้องหลัง
    mininet> h2 ping -c 20 192.3.128.3 > /tmp/h2.txt &
    mininet> h1 ping -c 20 192.3.128.3
    mininet> h2 cat /tmp/h2.txt          # อ่านผลของ h2 ทีหลัง
  7. ลบค่า delay ที่ตั้งไว้ทั้งหมด
    [mininet>] — ต้องทำก่อนเริ่มข้อ 8.2 เสมอ
    mininet> h1 tc qdisc del dev h1-eth0 root netem
    mininet> h1 tc qdisc show dev h1-eth0     # ต้องไม่เหลือ netem แล้ว

คำถามท้ายข้อ 8.1

1. ค่า delay พื้นฐาน (ไม่ตั้งค่าใด ๆ) ที่วัดได้ระหว่าง h1–h3 ใกล้เคียง 0 ms หรือไม่ เพราะเหตุใด

ใกล้ 0 มาก แต่ไม่เป็น 0 พอดี — จากรูปที่ 15 ของใบแลปเองค่า avg อยู่ที่ 0.127 ms คือระดับเศษหนึ่งส่วนสิบของมิลลิวินาที

เพราะเหตุใดถึงเกือบ 0 — Mininet ไม่มีสายจริง ทุกลิงก์เป็น veth pair ในหน่วยความจำของเครื่องเดียวกัน ฉะนั้นเมื่อเทียบกับสูตรความหน่วงในหัวข้อ 2.1

  • Propagation delay ≈ 0 — ระยะทาง d เป็นศูนย์ ไม่มีสายให้สัญญาณวิ่ง
  • Transmission delay ≈ 0 — R คือความเร็วของหน่วยความจำ ระดับหลายสิบ Gbit/s (รูปที่ 16 วัดได้ 44.5 Gbit/s)
  • Queuing delay ≈ 0 — ping ยิงแค่ 1 แพ็กเก็ต/วินาที ไม่มีคิว

เพราะเหตุใดถึงไม่เป็น 0 เป๊ะ — ยังเหลือ Processing delay จริง ๆ อยู่ คือเวลาที่เคอร์เนลใช้สลับ network namespace, คัดลอกแพ็กเก็ตข้าม veth, ให้ Open vSwitch ตัดสินใจส่งต่อ และปลุกโปรเซส ping ขึ้นมาอ่านคำตอบ — งานพวกนี้กินเวลาระดับไมโครวินาทีถึงร้อยไมโครวินาที จึงได้ตัวเลข 0.05–0.2 ms

2. เมื่อเพิ่ม delay 100 ms บน h1-eth0 ค่า RTT ที่วัดได้จาก ping ควรมีค่าประมาณเท่าใด (คำนวณและเปรียบเทียบกับผลจริง)

คำตอบ: ประมาณ 100 ms (ไม่ใช่ 200 ms)

RTTใหม่ = RTTbaseline + delayขาออก = 0.13 + 100 ≈ 100.1 ms netem ที่ root หน่วงเฉพาะขาออกของ h1-eth0

เหตุผล — qdisc ที่ติดด้วยคำว่า root อยู่บนคิวขาออก (egress) ของ h1-eth0 เท่านั้น

  • ICMP echo request ออกจาก h1 → โดนหน่วง 100 ms
  • ICMP echo reply จาก h3 วิ่งกลับเข้า h1-eth0 (ingress) → ไม่โดนหน่วง

รวมไป-กลับจึงโดนหน่วงแค่ครั้งเดียว = +100 ms

ถ้าอยากได้ 200 ms จริง ๆ ต้องใส่ที่ปลายทางด้วย: h3 tc qdisc add dev h3-eth0 root netem delay 100ms — คราวนี้ reply ก็โดนหน่วงด้วย รวมเป็น 200 ms

3. การ ping พร้อมกันจาก h1 และ h2 ไปยัง h3 ทำให้เกิด queuing delay เพิ่มขึ้นหรือไม่ สังเกตได้จากอะไร

ทางทฤษฎีเกิด แต่ในทางปฏิบัติบน Mininet มักวัดแทบไม่ได้

สังเกตได้จาก ตัวเลข avg, max และ mdev ที่สูงขึ้นเมื่อเทียบกับตอน ping ตัวเดียว โดยเฉพาะ max ที่จะโดดขึ้นเป็นบางแพ็กเก็ต (แพ็กเก็ตที่บังเอิญมาต่อคิวหลังแพ็กเก็ตของอีกฝั่งพอดี)

ทำไมถึงมักไม่ขยับ — จากสูตรในหัวข้อ 2.1 queuing delay เกิดเมื่ออัตราขาเข้าเกินอัตราขาออก · แต่ ping ยิงแค่ 1 แพ็กเก็ต × 64 ไบต์ ต่อวินาที สองเครื่องรวมกันก็ราว 1 kbit/s ขณะที่ลิงก์ veth วิ่งได้หลายสิบ Gbit/s → โหลดต่ำกว่าความจุประมาณ 7 หลัก คิวจึงว่างตลอด

ส่วนขยาย — วิธีทำให้เห็น queuing delay จริง ๆ

มี 2 ทาง ① บีบความจุลิงก์ ตอนสร้าง topology (net.addLink(h1, s1, cls=TCLink, bw=1) = 1 Mbit/s) ② อัดโหลดให้เต็มลิงก์ ด้วย h2 iperf3 -c 192.3.128.3 -t 20 & แล้ว ping ไปพร้อมกัน — จะเห็น avg และ max พุ่งขึ้นชัดเจน นี่คือ bufferbloat ที่หนังสือพูดถึง

3.12การทดลอง 8.2 — ทดสอบ Jitter

  1. เพิ่ม delay 100 ms และ jitter 10 ms ที่ h1-eth0 แล้ว ping h1 → h3
    [mininet>] — คำสั่งตรงกับข้อสอบข้อ 4(a) เป๊ะ ๆ
    mininet> h1 tc qdisc add dev h1-eth0 root netem delay 100ms 10ms
    mininet> h1 tc qdisc show dev h1-eth0
    # qdisc netem 8001: root refcnt 2 limit 1000 delay 100ms  10ms
    #                                                  ↑        ↑
    #                                                delay    jitter
    mininet> h1 ping -c 20 192.3.128.3
    # rtt min/avg/max/mdev = 90.3/100.4/109.8/5.8 ms
    #                        ↑            ↑      ↑
    #                    ~ 100-10     ~100+10   jitter ที่วัดได้
  2. ping h1 → h3 พร้อมกับ ping h2 → h3 เปรียบเทียบผลกับข้อที่แล้ว
    [mininet>]
    mininet> h2 ping -c 20 192.3.128.3 > /tmp/h2j.txt &
    mininet> h1 ping -c 20 192.3.128.3
    mininet> h2 cat /tmp/h2j.txt

    คาดหวัง: h2 แทบไม่เปลี่ยน เพราะ netem อยู่ที่ h1-eth0 ไม่ได้อยู่ที่ h2-eth0 — เป็นการยืนยันว่ากฎ tc ผูกกับ interface ตัวเดียว ไม่ใช่กับทั้งเน็ตเวิร์ค

  3. ลบค่าเดิมทั้งหมด
    [mininet>]
    mininet> h1 tc qdisc del dev h1-eth0 root netem

คำถามท้ายข้อ 8.2

1. ค่า mdev (mean deviation) ที่ได้จาก ping สัมพันธ์กับค่า jitter ที่กำหนดไว้อย่างไร

สัมพันธ์กันแบบแปรผันตรง แต่ตัวเลขไม่เท่ากัน — mdev จะได้ประมาณครึ่งหนึ่งของค่า jitter ที่ตั้ง

  • 10ms ที่ใส่ให้ netem = ครึ่งความกว้างของช่วงสุ่ม → แต่ละแพ็กเก็ตถูกหน่วงด้วยค่าสุ่มระหว่าง 90–110 ms
  • mdev ที่ ping รายงาน = ค่าเบี่ยงเบนของ RTT ทั้งชุด ซึ่งของการแจกแจงสม่ำเสมอกว้าง ±10 ms จะได้ 10/√3 ≈ 5.8 ms

ทดสอบความสัมพันธ์ได้ — ตั้ง jitter เป็น 2 เท่า (delay 100ms 20ms) แล้ว mdev จะขึ้นเป็น 2 เท่าตาม (~11.5 ms) · ส่วน max − min จะเข้าใกล้ 2 × jitter = 20 ms

สรุปคำตอบที่เขียนลงรายงานได้เลย: "mdev แปรผันตรงกับค่า jitter ที่กำหนด แต่มีค่าประมาณ 0.58 เท่า (1/√3) เพราะ netem สุ่มค่าหน่วงแบบสม่ำเสมอในช่วง ±jitter ขณะที่ mdev คือส่วนเบี่ยงเบนของค่าเหล่านั้น ไม่ใช่ความกว้างของช่วง"

2. หากเป็นแอปพลิเคชันแบบเรียลไทม์ เช่น VoIP ค่า jitter ระดับ 10 ms จะส่งผลกระทบต่อคุณภาพเสียงอย่างไร

ระดับ 10 ms ยังถือว่ารับได้ ไม่ทำให้เสียงขาด เพราะโปรแกรม VoIP ทุกตัวมี jitter buffer คอยกันไว้อยู่แล้ว

กลไกที่เกิดขึ้น — VoIP ส่งเสียงเป็นแพ็กเก็ตเล็ก ๆ ทุก 20 ms และต้องเล่นออกลำโพงให้ต่อเนื่องพอดี ๆ เมื่อแพ็กเก็ตมาถึงไม่สม่ำเสมอ (ตามรูปที่ 2 ของใบแลป) ฝั่งรับจึงต้อง

  • พักแพ็กเก็ตไว้ในบัฟเฟอร์ก่อน แล้วค่อยทยอยเล่น — ต้องพักนานอย่างน้อยเท่ากับ jitter ที่คาดไว้
  • ผลข้างเคียงคือ ความหน่วงปลายทางเพิ่มขึ้น (บัฟเฟอร์ยิ่งใหญ่ ยิ่งกันกระตุกได้ดี แต่ยิ่งพูดสวนกันลำบาก)
  • แพ็กเก็ตที่มาช้าเกินคิวเล่นจะถูกทิ้ง กลายเป็น loss ทั้งที่เน็ตเวิร์คส่งถึงแล้ว

ตัวเลขอ้างอิงที่เขียนลงรายงานได้ — เกณฑ์ที่นิยมใช้กันในอุตสาหกรรมคือ jitter ควร ต่ำกว่า 30 ms และ one-way delay ควรต่ำกว่า 150 ms · ที่ 10 ms จึงอยู่ในเกณฑ์ดี เสียงจะยังเรียบ แต่ถ้าดันขึ้นเป็น 50–100 ms จะเริ่มได้ยินเสียงกระตุก ขาดหาย หรือคำซ้อนกัน (เกณฑ์ตัวเลขนี้เป็นส่วนขยาย ไม่ได้อยู่ในใบแลป)

3.13การทดลอง 8.3 — ทดสอบ Packet Loss

  1. เพิ่มค่า loss ที่ h1-eth0 เป็น 5%
    [mininet>]
    mininet> h1 tc qdisc add dev h1-eth0 root netem loss 5%
  2. ping 150 ครั้งจาก h1 ไป h3 บันทึกอัตราการสูญหายจริง
    [mininet>] — ใบแลปสั่ง -c 150 ตรง ๆ
    mininet> h1 ping -c 150 192.3.128.3
    # --- 192.3.128.3 ping statistics ---
    # 150 packets transmitted, 143 received, 4.67% packet loss, time 152300ms
    #                                        ↑↑↑↑↑ ตัวเลขนี้คือคำตอบที่ต้องบันทึก

    เตือน: ping -c 150 แบบค่าเริ่มต้นยิงวินาทีละครั้ง = ใช้เวลา 150 วินาที · ถ้าเวลาไม่พอ ให้เติม -i 0.2 (ยิงทุก 0.2 วินาที เหลือ 30 วินาที) — ส่วนขยาย ผลทางสถิติเหมือนกัน

  3. เปลี่ยนเป็น 10% และ 15% แล้วเปรียบเทียบผล
    [mininet>] — ใช้ change ไม่ต้องลบก่อน
    mininet> h1 tc qdisc change dev h1-eth0 root netem loss 10%
    mininet> h1 ping -c 150 -i 0.2 192.3.128.3
    
    mininet> h1 tc qdisc change dev h1-eth0 root netem loss 15%
    mininet> h1 ping -c 150 -i 0.2 192.3.128.3
    
    # ── ค่าที่ข้อสอบข้อ 4(b) สั่ง ──
    mininet> h1 tc qdisc change dev h1-eth0 root netem loss 20%
    mininet> h1 ping -c 150 -i 0.2 192.3.128.3
    
    mininet> h1 tc qdisc del dev h1-eth0 root netem   # ล้างก่อนไปข้อ 8.4

คำถามท้ายข้อ 8.3

1. อัตราการสูญหายจริงที่วัดได้จาก ping ใกล้เคียงกับค่าที่กำหนดไว้ใน tc/netem หรือไม่

ใกล้เคียงมาก แต่ไม่ตรงเป๊ะ และจะยิ่งใกล้เมื่อยิงแพ็กเก็ตมากขึ้น — นี่คือเหตุผลที่ใบแลปสั่งให้ ping -c 150 ไม่ใช่ -c 10

เพราะเหตุใด — netem ตัดสินใจทิ้งแพ็กเก็ตทีละใบแบบสุ่มอิสระ ด้วยความน่าจะเป็นที่ตั้งไว้ ผลรวมจึงเป็นการแจกแจงทวินาม (binomial) ค่าที่วัดได้จะแกว่งรอบค่าที่ตั้ง

ตั้งไว้ยิง 10 ครั้งยิง 150 ครั้ง
5%ได้ 0% หรือ 10% หรือ 20% เท่านั้น — ละเอียดสุดแค่ 10%ได้ราว 3–8% ใกล้ 5% พอสมควร
20%ได้ 10–40% แกว่งมากได้ราว 16–24%

อีกเหตุผลที่ตัวเลขตรงพอดีกว่าที่คิด — netem อยู่ที่ ขาออก ของ h1 อย่างเดียว ทิ้งได้แค่ request ส่วน reply ที่วิ่งกลับเข้ามาไม่โดนทิ้ง · ถ้าโดนทั้งสองทางที่ 20% ค่าที่วัดจะเป็น 1 − (0.8 × 0.8) = 36% ไม่ใช่ 20%

2. เมื่อ loss เพิ่มจาก 5% เป็น 15% ค่า RTT เฉลี่ยเปลี่ยนแปลงหรือไม่ เพราะเหตุใด

แทบไม่เปลี่ยน — avg ยังอยู่ที่ระดับเดิม

เพราะเหตุใด — สองข้อ

  1. netem ทิ้งแพ็กเก็ตทิ้งไปเลย ไม่ได้ถ่วงเวลา — แพ็กเก็ตที่ถูกเลือกให้หาย จะหายทันทีที่ต้นทาง ไม่ได้ไปนั่งรอในคิวก่อน จึงไม่มี delay เพิ่มให้ใคร
  2. ping คำนวณ min/avg/max/mdev จากแพ็กเก็ตที่ได้คำตอบกลับมาเท่านั้น — แพ็กเก็ตที่หายไม่มี RTT ให้เอามาเฉลี่ย จึงไม่ถูกนับ

สิ่งที่เปลี่ยนแทน คือตัวเลข received และ % packet loss เท่านั้น

แต่กับ TCP เรื่องกลับกันสิ้นเชิง

ICMP ไม่สนใจว่าแพ็กเก็ตหาย แต่ TCP ต้องส่งซ้ำ — เวลาที่ผู้ใช้รู้สึกว่า "ช้า" จึงพุ่งขึ้นมหาศาลทั้งที่ RTT ของ ping ยังนิ่ง · ดูผลจริงในข้อ 8.4 ที่ค่า Retr จะพุ่งและ Bitrate จะตก

3.14การทดลอง 8.4 — ทดสอบด้วย Iperf3

ใบแลปสั่งให้ทดสอบ ระหว่าง h1 กับ h2 (ทั้งคู่อยู่ใต้ s1) แล้วสรุป Transfer, Bitrate และ Retr ของทุกกรณีลงในตารางเดียว

[mininet>] — ชุดคำสั่งครบทั้งข้อ 8.4 · ทำตามลำดับ
# ── เตรียม: เปิดเซิร์ฟเวอร์ที่ h2 ค้างไว้ครั้งเดียว ──────────────
mininet> h2 iperf3 -s -D

# ── ① baseline: ไม่กำหนดอะไรเลย ────────────────────────────────
mininet> h1 tc qdisc del dev h1-eth0 root netem   # กันของค้าง (ไม่มีก็ไม่เป็นไร)
mininet> h1 iperf3 -c 192.3.128.2 -t 5

# ── ② delay 100 ms ─────────────────────────────────────────────
mininet> h1 tc qdisc replace dev h1-eth0 root netem delay 100ms
mininet> h1 iperf3 -c 192.3.128.2 -t 5

# ── ③ delay 100 ms + jitter 10 ms ──────────────────────────────
mininet> h1 tc qdisc replace dev h1-eth0 root netem delay 100ms 10ms
mininet> h1 iperf3 -c 192.3.128.2 -t 5

# ── ④ loss 1% ──────────────────────────────────────────────────
mininet> h1 tc qdisc replace dev h1-eth0 root netem loss 1%
mininet> h1 iperf3 -c 192.3.128.2 -t 5

# ── ⑤ loss 5% ──────────────────────────────────────────────────
mininet> h1 tc qdisc replace dev h1-eth0 root netem loss 5%
mininet> h1 iperf3 -c 192.3.128.2 -t 5

# ── ⑥ UDP (คำถามข้อ 3) ─────────────────────────────────────────
mininet> h1 iperf3 -c 192.3.128.2 -t 5 -u -b 100M

# ── ล้าง ───────────────────────────────────────────────────────
mininet> h1 tc qdisc del dev h1-eth0 root netem
mininet> h2 pkill iperf3

อ่านผล iperf3 ให้เป็น

[Host: h1] — บรรทัดที่ต้องคัดไปกรอกตารางคือบรรทัด sender
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  5.18 GBytes  44.5 Gbits/sec    0    843 KBytes
...
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-5.00   sec  25.9 GBytes  44.5 Gbits/sec   0             sender
[  5]   0.00-5.00   sec  25.9 GBytes  44.5 Gbits/sec                 receiver
#                        ↑ Transfer   ↑ Bitrate      ↑ Retr
#                        ช่องที่ 1    ช่องที่ 2      ช่องที่ 3 ของตาราง
จุดที่คนพลาดบ่อย — จดผิดบรรทัด

iperf3 พิมพ์ผลรายวินาทีก่อน แล้วค่อยสรุปท้ายเป็น 2 บรรทัด (sender / receiver) · ให้จดจากบรรทัด sender เพราะเป็นบรรทัดเดียวที่มีคอลัมน์ Retr · อย่าจดบรรทัดรายวินาทีบรรทัดใดบรรทัดหนึ่งไปกรอกตาราง

คำถามท้ายข้อ 8.4

1. Throughput ลดลงมากที่สุดเมื่อเพิ่ม delay, jitter หรือ loss เพราะเหตุใด

เรียงจากกระทบมากไปน้อย: delay ≫ loss > jitter — และเหตุผลของแต่ละตัวไม่เหมือนกัน

พารามิเตอร์ผลต่อ Bitrateกลไก
delay 100 msตกแรงที่สุด จากระดับ Gbit/s เหลือหลักร้อย Mbit/s หรือน้อยกว่าTCP ส่งได้ไม่เกิน 1 หน้าต่างต่อ 1 RTT — พอ RTT โตจาก 0.13 ms เป็น 100 ms (770 เท่า) เพดานก็ตกลงตามสัดส่วนนั้นทันที โดยยังไม่มี loss สักแพ็กเก็ต · และช่วง slow start ก็ยาวขึ้น 770 เท่าด้วย
loss 1% → 5%ตกซ้ำอีก และ Retr พุ่งทุกครั้งที่มี loss TCP ตีความว่าเน็ตแออัด → หด Cwnd ลงครึ่งหนึ่ง แล้วค่อย ๆ ไต่ขึ้นใหม่ · จากสูตร Mathis throughput แปรผกผันกับ √Loss → loss เพิ่ม 5 เท่า throughput เหลือ 1/√5 ≈ 45%
jitter 10 msกระทบน้อยสุดTCP ไม่สนใจว่าแพ็กเก็ตมาไม่สม่ำเสมอ ตราบใดที่ยังมาครบ · ผลที่มีคือ RTO ประมาณการยากขึ้นเล็กน้อย และแพ็กเก็ตสลับลำดับทำให้เกิด duplicate ACK บ้าง แต่ throughput แทบไม่ขยับ · (jitter จะไปทำร้าย VoIP แทน ดู 8.2)

คำตอบสั้นที่เขียนลงรายงาน: "delay กระทบมากที่สุด เพราะ throughput ของ TCP ถูกจำกัดด้วย window/RTT โดยตรง ส่วน loss กระทบรองลงมาผ่านกลไก congestion control (แปรผกผันกับ √loss) และ jitter กระทบน้อยที่สุดเพราะ TCP ไม่ได้ต้องการความสม่ำเสมอของเวลามาถึง"

2. ผลที่ได้สอดคล้องกับสูตรความสัมพันธ์ระหว่าง Throughput, RTT และ Loss ในรูปที่ 3 หรือไม่ อธิบายเชิงปริมาณ

เอาสูตร Mathis มาแทนค่าแล้วเทียบกับที่วัดได้จริง

Throughput ≈ MSSRTT √Loss · MSS = 1460 B = 11,680 bit รูปที่ 3 ของใบแลป
กรณีRTTLossแทนค่าทำนาย
delay 100 ms + loss 1%0.1 s0.0111680 / (0.1 × 0.100)1.17 Mbit/s
delay 100 ms + loss 5%0.1 s0.0511680 / (0.1 × 0.224)0.52 Mbit/s

เชิงปริมาณที่ตรวจสอบได้ง่ายที่สุด — loss เพิ่มจาก 1% เป็น 5% คือ 5 เท่า สูตรทำนายว่า throughput ควรเหลือ 1/√5 = 0.447 หรือ ประมาณ 45% ของเดิม · เอาตัวเลข Bitrate สองแถวนี้จากตารางมาหารกันดู ถ้าได้ราว ๆ 0.4–0.5 ก็ถือว่าสอดคล้อง

ข้อจำกัดที่ควรเขียนไว้ในรายงานด้วย

① กรณี loss = 0 สูตรใช้ไม่ได้ (หารด้วยศูนย์) ตัวจำกัดกลายเป็น Window / RTT แทน ② สูตร Mathis เป็นค่าประมาณสำหรับ TCP Reno ส่วน Linux สมัยใหม่ใช้ CUBIC ซึ่งฟื้นตัวเร็วกว่า → ค่าที่วัดได้จริงมักสูงกว่าที่สูตรทำนาย ③ ค่าที่ทำนายไว้ในตารางเป็นตัวเลขระดับ Mbit/s แต่ลิงก์ veth ไม่มีเพดาน จึงเห็นความต่างชัด ไม่โดนความจุลิงก์บัง

3. หากทดสอบด้วย UDP (iperf3 -u) แทน TCP ผลลัพธ์ในกรณี loss จะแตกต่างจาก TCP อย่างไร

ต่างกันสิ้นเชิง เพราะ UDP ไม่มี congestion control และไม่ส่งซ้ำ

หัวข้อTCP (iperf3 -c)UDP (iperf3 -c -u -b 100M)
เมื่อมี loss 5%ลดความเร็วตัวเองลง — หด Cwnd แล้วส่งซ้ำยิงเท่าเดิมไม่สนใจ — ยังคง 100 Mbit/s ตามที่สั่งด้วย -b
Bitrate ฝั่งส่งตกลงชัดเจนคงที่ ตาม -b ที่ตั้ง
ข้อมูลที่ถึงปลายทางครบ 100% เสมอ (ส่งซ้ำจนกว่าจะถึง)หายไป ~5% ถาวร ไม่มีการส่งซ้ำ
คอลัมน์ในรายงานมี Retr และ Cwndไม่มี Retr/Cwnd แต่มี Jitter และ Lost/Total Datagrams แทน
[Host: h1] — หน้าตาสรุปของฝั่ง UDP
[ ID] Interval        Transfer     Bitrate      Jitter    Lost/Total Datagrams
[  5] 0.00-5.00 sec   59.6 MBytes  100 Mbits/sec  0.000 ms  0/43200 (0%)  sender
[  5] 0.00-5.00 sec   56.6 MBytes  95.0 Mbits/sec 0.412 ms  2160/43200 (5%) receiver
#                                                  ↑ jitter    ↑ loss ที่ปลายทางเห็น

ประโยชน์ในการทดลอง — โหมด UDP เป็นวิธีเดียวที่ iperf3 รายงาน jitter ให้ตรง ๆ จึงเหมาะกับการยืนยันผลข้อ 8.2 · ลองรัน -u พร้อมกับตั้ง netem delay 100ms 10ms แล้วดูช่อง Jitter จะเห็นตัวเลขขยับขึ้นตามที่ตั้งไว้ (ส่วนขยาย)

3.15การทดลอง 8.5 — ติดตั้งอุปกรณ์จริงและทดสอบด้วย Iperf3

ข้อสุดท้ายให้ออกจากโลกจำลองไปทดสอบกับสวิตช์จริงในห้องปฏิบัติการ ใบแลปสั่งไว้ 4 ข้อ

  1. ต่อวงจรเช่นเดียวกับรูปที่ 17 โดยให้เหลือเพียง 2 เครื่องเท่านั้น (ตามคู่ของ Lab) — เครื่องเราเป็นโหนดหนึ่ง เครื่องเพื่อนเป็นอีกโหนด ผ่านสวิตช์ในห้อง
  2. กำหนด IP Address ของเครื่องตนเองโดยไม่ต้องเชื่อมต่ออินเทอร์เน็ต
    [Ubuntu VM] — ตั้ง IP ให้การ์ด USB-C Ethernet ที่ passthrough เข้ามา
    $ ip -br a                         # หาชื่อการ์ดจริงก่อนเสมอ
    # enp0s5           UP   10.211.55.7/24    <- การ์ดเสมือนของ Parallels (อย่าแตะ)
    # enxaca7f1a9ff44  UP                     <- USB-C Ethernet ตัวจริง
    
    $ IF=enxaca7f1a9ff44
    $ sudo ip addr add 192.3.128.5/24 dev $IF
    $ sudo ip link set $IF up
    $ sudo ethtool -K $IF tso off gso off gro off   # ปิด offload ก่อนวัด
  3. ใช้สวิตซ์ในห้องปฏิบัติการทดสอบด้วย iperf3 โดยเปรียบเทียบระหว่างสวิตซ์ 2 รุ่นที่แตกต่างกัน บันทึกว่าแตกต่างกันหรือไม่ อย่างไร
    [Ubuntu VM] — เครื่องหนึ่งเป็น server อีกเครื่องเป็น client
    $ iperf3 -s                            # เครื่องที่เป็นเซิร์ฟเวอร์
    $ iperf3 -c 192.3.128.6 -t 10          # เครื่องที่เป็นไคลเอนต์

    สวิตช์รุ่นเก่าที่พอร์ตเป็น FastEthernet (100 Mbit/s) จะได้ Bitrate ราว 94–95 Mbit/s ส่วนรุ่นใหม่ที่เป็น GigabitEthernet จะได้ราว 940 Mbit/s — ตัวเลขที่วัดได้จะต่ำกว่าตัวเลขบนกล่องเสมอ เพราะมี overhead ของ Ethernet + IP + TCP header

  4. สลับบทบาทระหว่างไคลเอนต์และเซิร์ฟเวอร์ระหว่างคู่ Lab เปรียบเทียบผลการทำงานว่าต่างกันหรือไม่ หากต่าง เพราะเหตุใด
    [Ubuntu VM] — หรือใช้ -R สลับทิศทางโดยไม่ต้องย้ายเครื่อง ส่วนขยาย
    $ iperf3 -c 192.3.128.6 -t 10 -R       # reverse: server ส่ง client รับ

คำถามท้ายข้อ 8.5

1. ผลที่ได้จากอุปกรณ์จริงแตกต่างจากผลจำลองบนมินิเน็ตหรือไม่ เพราะเหตุใด

ต่างกันมาก และต่างในทางที่คาดเดาได้

หัวข้อMininetอุปกรณ์จริง
Throughputหลายสิบ Gbit/s (รูปที่ 16 = 44.5 Gbit/s)ถูกจำกัดด้วยความเร็วพอร์ตจริง — ~95 Mbit/s หรือ ~940 Mbit/s
ที่มาของเพดานความเร็วของ RAM และ CPU — ไม่มีสายไฟจริงให้ส่งสัญญาณความเร็วของ PHY/สายทองแดง ตาม 100BASE-TX หรือ 1000BASE-T
Delay พื้นฐาน~0.1 ms (Processing อย่างเดียว)สูงกว่าเล็กน้อย เพราะมี Transmission + Propagation จริง บวก store-and-forward ของสวิตช์
Loss พื้นฐาน0% เสมอ ไม่มี bit errorอาจมี loss เล็กน้อยจากสัญญาณรบกวน สายไม่ดี หรือ buffer เต็ม
Jitterต่ำมาก ค่อนข้างนิ่งสูงกว่า เพราะมีทราฟฟิกอื่นในสวิตช์และการจัดคิวจริง

สรุปที่เขียนลงรายงาน: "Mininet จำลอง พฤติกรรมของโปรโตคอล ได้ถูกต้อง แต่ไม่ได้จำลอง ข้อจำกัดทางกายภาพ ของสายและ PHY เพราะทุกลิงก์เป็น veth ในหน่วยความจำเดียวกัน ค่าที่วัดได้จึงถูกจำกัดด้วยความเร็วของ CPU/RAM แทนความเร็วของสาย"

2. ปัจจัยใดในอุปกรณ์จริง (เช่น NIC, สาย, driver) ที่อาจทำให้ผลต่างจากการจำลอง
  • ความเร็วของ NIC และการเจรจา auto-negotiation — ถ้าฝั่งหนึ่งเป็น 1 Gbit/s อีกฝั่งเป็น 100 Mbit/s ลิงก์จะตกลงกันที่ตัวช้ากว่า · ตรวจด้วย ethtool $IF ดูบรรทัด Speed: และ Duplex:
  • Duplex mismatch — ถ้าฝั่งหนึ่งเป็น half duplex จะเกิด collision throughput ตกฮวบและ loss พุ่ง เป็นอาการคลาสสิกของการตั้งค่าพอร์ตไม่ตรงกัน
  • คุณภาพสายและระยะ — สาย Cat5 เก่า หัวหลวม หรือยาวเกิน 100 เมตร ทำให้เกิด bit error → เฟรมเสียถูกทิ้ง → TCP ส่งซ้ำ (Retr ขึ้น)
  • Driver และฟีเจอร์ offload — TSO/GSO/GRO ทำให้เห็นตัวเลขสวยเกินจริง และทำให้ netem วัดค่าเพี้ยน · จึงต้อง sudo ethtool -K $IF tso off gso off gro off ก่อนวัดทุกครั้ง
  • ขนาดบัฟเฟอร์ของสวิตช์ — สวิตช์ราคาถูกบัฟเฟอร์เล็ก พอมีทราฟฟิกพุ่งจะทิ้งแพ็กเก็ตทันที (ตรงกับสาเหตุ buffer overflow ในหัวข้อ 2.3)
  • CPU ของเครื่องปลายทาง — ที่ความเร็วระดับ Gbit/s ถ้าเครื่องช้าหรือรันอยู่ใน VM ตัว CPU จะกลายเป็นคอขวดแทนสาย
  • ทราฟฟิกอื่นบนสวิตช์เดียวกัน — ห้องแลปมีหลายคู่ทดสอบพร้อมกัน ทำให้เกิด queuing delay และ jitter จริง ๆ ซึ่ง Mininet ที่รันคนเดียวไม่มี

เฉพาะของ MacBook Air M2 — เราต่อผ่าน USB-C → Ethernet adapter แล้ว passthrough เข้า VM อีกชั้น จึงมีคอขวดเพิ่มอีกสองจุดคือบัส USB และชั้น virtualization ของ Parallels · ตัวเลขที่วัดได้อาจต่ำกว่าเพื่อนที่เสียบพอร์ต RJ-45 ในตัวเครื่องโดยตรง — ควรเขียนข้อจำกัดนี้ลงในรายงานด้วย

3.16สรุปผลการทดลอง (ตารางที่ 1)

ใบแลปหัวข้อ 9 สั่งให้สรุปผลทั้งหมดในรูปแบบตารางเปรียบเทียบ พร้อมอภิปรายความสัมพันธ์ระหว่างพารามิเตอร์ที่ปรับ (Delay, Jitter, Loss) กับผลลัพธ์ที่วัดได้ (RTT, Throughput, Retransmission) โดยอ้างอิงหลักการทางทฤษฎีในหัวข้อ 2

การตั้งค่าRTT (ms)
avg จาก ping
Throughput (Mbps)
Bitrate จาก iperf3
Retr
จาก iperf3
Loss จริง (%)
จาก ping
ไม่ตั้งค่า (baseline)…………
Delay 100 ms…………
Delay 100 ms + Jitter 10 ms…………
Loss 1%…………
Loss 5%…………

ตารางที่ 1 ของใบแลป (ให้นักศึกษากรอกผลที่วัดได้)

แนวโน้มที่ต้องเห็นในตาราง — ถ้าไม่เป็นแบบนี้ แปลว่าทำอะไรผิด
  • RTT — baseline ต่ำกว่า 1 ms · แถว Delay ทั้งสองต้องอยู่ราว 100 ms · แถว Loss ต้องกลับมาต่ำเหมือน baseline (loss ไม่เพิ่ม RTT)
  • Throughput — baseline สูงสุด (ระดับ Gbit/s) · ตกฮวบทันทีที่ใส่ delay · ตกต่อเมื่อใส่ loss และตกมากขึ้นเมื่อ loss มากขึ้น
  • Retr — baseline และ delay ควรเป็น 0 หรือใกล้ 0 · แถว loss ต้องมีเลข และ loss 5% ต้องมากกว่า loss 1%
  • Loss จริง — เป็น 0% ทุกแถวยกเว้นสองแถวล่าง ซึ่งต้องใกล้เคียง 1% และ 5% ตามที่ตั้ง

คำถามสรุป

1. พารามิเตอร์ใด (Delay, Jitter, Loss) ส่งผลกระทบต่อ Throughput ของ TCP มากที่สุด เพราะเหตุใด

Delay (RTT) มากที่สุด — ดูจากสูตร Mathis ในรูปที่ 3 จะเห็นว่า RTT อยู่ในตัวส่วนแบบเชิงเส้น ส่วน Loss อยู่ใต้รากที่สอง

เปลี่ยนอะไรThroughput เหลือเท่าไร
RTT เพิ่ม 2 เท่า1/2 = 50%
Loss เพิ่ม 2 เท่า1/√2 = 71%
Loss เพิ่ม 4 เท่า1/√4 = 50% — ต้องเพิ่มถึง 4 เท่าจึงกระทบเท่ากับ RTT 2 เท่า

ในเชิงกลไก — TCP ส่งได้ไม่เกิน 1 หน้าต่างต่อ 1 RTT แล้วต้องรอ ACK ก่อนส่งต่อ ฉะนั้น RTT คือตัวคูณเวลาของทุกอย่าง ทั้งช่วง slow start และช่วง congestion avoidance ยาวขึ้นตามสัดส่วน · ส่วน loss แค่ทำให้ Cwnd หดเป็นครั้ง ๆ ซึ่ง TCP ไต่กลับขึ้นมาได้ · Jitter กระทบน้อยที่สุด เพราะ TCP ไม่ได้ต้องการความสม่ำเสมอของเวลามาถึง

2. ถ้าออกแบบเน็ตเวิร์คให้แอปที่ไวต่อ Jitter (VoIP) และแอปที่ไวต่อ Throughput (File Transfer) จะให้ความสำคัญกับพารามิเตอร์ใดก่อน

VoIP / วิดีโอคอล → คุม Jitter เป็นอันดับแรก

  • Jitter — ต้องนิ่ง เพราะเสียงต้องเล่นออกทุก 20 ms ตรงเวลา (จากหัวข้อ 2.2)
  • Delay — รองลงมา ต้องต่ำพอให้คุยสวนกันได้
  • Throughput — สำคัญน้อยสุด เสียงใช้แค่หลักสิบ kbit/s
  • วิธีทำ — ให้ QoS priority queue กับทราฟฟิกเสียง คุมขนาดคิวไม่ให้ยาว และเลือกเส้นทางที่เสถียร

File Transfer → คุม Loss และ Delay เป็นอันดับแรก

  • Loss — ทุกแพ็กเก็ตที่หายทำให้ TCP หด Cwnd ทันที
  • Delay (RTT) — เป็นตัวคูณของ throughput โดยตรง
  • Jitter — แทบไม่มีผล ข้อมูลมาช้าก็แค่รอในบัฟเฟอร์
  • วิธีทำ — เพิ่ม bandwidth ให้ไม่แออัด ทำให้ buffer พอไม่ให้ล้น และวางเซิร์ฟเวอร์ใกล้ผู้ใช้เพื่อลด RTT

ประโยคสรุปสำหรับรายงาน: "VoIP ให้ความสำคัญกับ jitter แล้วจึง delay ส่วน throughput แทบไม่สำคัญ · File transfer ให้ความสำคัญกับ loss และ delay เพราะทั้งคู่กระทบ throughput ของ TCP โดยตรงตามสูตรของ Mathis ส่วน jitter แทบไม่มีผล"

3. มินิเน็ตเหมาะสมกับการศึกษาประสิทธิภาพเครือข่ายในระดับใด และมีข้อจำกัดใดที่ควรระวัง

เหมาะมากในระดับ "เข้าใจพฤติกรรมและแนวโน้ม" แต่ไม่เหมาะกับการอ้างตัวเลขสัมบูรณ์

เหมาะกับ

  • ศึกษาพฤติกรรมของโปรโตคอล — TCP congestion control, ARP, STP, OpenFlow ทำงานด้วยโค้ดจริงของลินุกซ์
  • ดูแนวโน้มเชิงเปรียบเทียบ เช่น "เพิ่ม RTT 2 เท่า throughput ลดครึ่ง"
  • ทดลองซ้ำได้เป๊ะ ๆ เพราะควบคุมทุกตัวแปรได้ และสร้าง topology ใหญ่ ๆ ได้ในไม่กี่วินาที
  • ไม่ต้องมีอุปกรณ์ — เรียนได้จากโน้ตบุ๊กเครื่องเดียว

ข้อจำกัดที่ต้องระวัง

  • ไม่มีชั้นกายภาพจริง — ไม่มี propagation delay, bit error, duplex mismatch, สัญญาณรบกวน
  • ตัวเลขความเร็วสูงเกินจริง — 44.5 Gbit/s เป็นความเร็วของ RAM ไม่ใช่ของสาย
  • ทุกโหนดแย่ง CPU ตัวเดียวกัน — ถ้าสร้างโหนดเยอะหรืออัดทราฟฟิกหนัก CPU จะกลายเป็นคอขวดปลอม ๆ
  • ผลกระทบจาก offload — ถ้าไม่ปิด TSO/GSO/GRO ค่าที่ netem ให้จะเพี้ยน
  • รันบน VM ซ้อนอีกชั้น (กรณี Mac) ทำให้ตัวเลขยิ่งแกว่ง

สรุป: ใช้ Mininet เพื่อตอบคำถามว่า "ทำไม" และ "แนวโน้มไปทางไหน" ได้ดีมาก แต่ถ้าต้องตอบว่า "ระบบจริงจะได้กี่ Mbit/s" ต้องไปวัดบนอุปกรณ์จริงตามหัวข้อ 8.5

3.17จุดที่ Mac ต่างจากที่ใบแลปเขียนไว้

เรื่องใบแลปเขียนไว้ (Windows)ของ Mac ต้องทำแบบนี้
ตัวรัน VMVMware Workstation Player 16 (หรือ WSL)ไม่มีทั้งคู่บน macOS → ใช้ Parallels Desktop (หรือ UTM ถ้าเอาฟรี)
ปิด Hyper-VTurn Windows features on or off → เอาเครื่องหมายถูกหน้า Hyper-V ออก → รีสตาร์ท (รูปที่ 4)ไม่มีขั้นตอนนี้ — macOS ไม่มี Hyper-V และไม่มี Windows Features · ข้ามไปได้เลย
ไฟล์ UbuntuISO ubuntu-18.04-desktop-amd64 (รูปที่ 6)ต้องเป็น arm64 เท่านั้น — amd64 บูตบน M2 ไม่ขึ้น · Parallels มีตัวเลือกดาวน์โหลด Ubuntu ARM ให้ในหน้าสร้าง VM
สั่งงาน Mininetเปิดหน้าต่าง VM แล้วพิมพ์ในเทอร์มินัลของ Ubuntussh ubuntu จาก Terminal ของ macOS — คัดลอกผลลัพธ์ไปแปะรายงานได้ง่ายกว่ามาก
MiniEdit (GUI)sudo examples/miniedit.py แล้วหน้าต่างเด้งขึ้นมาเลยเป็นหน้าต่าง X11 — ผ่าน ssh ธรรมดาจะขึ้น no display name and no $DISPLAY · ให้รันในเดสก์ท็อปของ VM หรือลง XQuartz แล้ว ssh -Y ubuntu · ในห้องสอบใช้สคริปต์ Python แทน
ชื่อการ์ด Ethernet ใน VMeth0enxaca7f1a9ff44 (ชื่อสร้างจาก MAC ของการ์ด USB) · enp0s5 คือการ์ดเสมือนของ Parallels คนละใบ · ดูชื่อจริงด้วย ip -br a ก่อนเสมอ
พอร์ต Ethernetโน้ตบุ๊ก Windows ส่วนใหญ่มีช่อง RJ-45 ในตัวMacBook Air M2 ไม่มีช่อง Ethernet → ใช้ USB-C → Ethernet adapter แล้วต้องทำ USB passthrough: Parallels → Devices → USB & Bluetooth → เลือกการ์ด
ก่อนวัดค่าด้วย netemใบแลปไม่ได้เขียนไว้sudo ethtool -K $IF tso off gso off gro off ทุกครั้ง ไม่งั้น delay/loss ที่วัดได้เพี้ยน ส่วนขยายที่จำเป็น
git clonegit://github.com/mininet/mininetต้องเป็น https://github.com/mininet/mininet — GitHub ปิด git:// ไปแล้ว (ไม่ใช่เรื่องของ Mac แต่ใบแลปเก่าแล้ว)
ติดตั้ง Mininet./mininet/util/install.sh -aบน ARM ใช้ sudo apt install -y mininet openvswitch-switch iperf3 net-tools ethtool ง่ายและชัวร์กว่า
คัดลอกผลลัพธ์ลากเมาส์ในหน้าต่าง VMssh ubuntu '…' | tee ~/Desktop/lab3_result.txt — เก็บลง Mac ตรง ๆ ใช้แนบรายงานได้เลย ส่วนขยาย

3.18เช็คว่าทำถูกไหม

คำสั่งต้องได้ผลอะไร
sudo mn --test pingallทดสอบว่า Mininet เองยังทำงาน — ต้องได้ *** Results: 0% dropped (2/2 received)
mininet> netต้องเห็น h1-eth0:s1-eth1 … s1-eth3:s2-eth3 ครบ 5 ลิงก์ตามรูปที่ 17
mininet> dumpทุกโฮสต์ต้องมี IP 192.3.128.1–.4 ตรงตามตารางใน §3.1
mininet> pingall*** Results: 0% dropped (12/12 received) — ข้อสอบสั่งข้อนี้ตรง ๆ ("ping ได้ทุกโหนด")
mininet> h1 ifconfigเห็น h1-eth0 มี inet 192.3.128.1 netmask 255.255.255.0 (เทียบรูปที่ 14)
mininet> h1 tc qdisc show dev h1-eth0หลังใส่ค่าต้องเห็น qdisc netem … delay 100ms 10ms · ถ้าเห็นแต่ noqueue / fq_codel = ยังไม่ติด
mininet> h1 ping -c 10 192.3.128.3baseline avg < 1 ms · หลัง delay 100 ms ต้องได้ avg ≈ 100 ms (ไม่ใช่ 200)
mininet> h1 iperf3 -c 192.3.128.2 -t 5ต้องได้บรรทัดสรุป sender ที่มีคอลัมน์ Retr — baseline ระดับ Gbit/s และ Retr = 0
ip -br a (ใน Ubuntu ไม่ใช่ใน mininet)เห็น s1-eth1, s1-eth2, s1-eth3 ใน root namespace แต่ ไม่เห็น h1-eth0 — ถูกต้องแล้ว เพราะอยู่คนละ namespace (§3.6)

3.19ถ้าไม่ผ่าน ให้ไล่ตามนี้

อาการสาเหตุคำสั่งแก้
pingall ได้ 100% dropped ทั้งที่ topology ถูกสวิตช์รอ controller อยู่ — OVS โหมด secure จะไม่ส่งอะไรเลยถ้าไม่มี controllerใช้ failMode='standalone' ในสคริปต์ หรือเติม --controller none --switch ovsk,failMode=standalone ท้ายคำสั่ง mn
Exception: Error creating interface pair (s1-eth1,h1-eth0): RTNETLINK answers: File existsของค้างจากรอบก่อน — ปิด Mininet ไม่สนิท (ปิดหน้าต่างเฉย ๆ หรือ Ctrl-C ตอนกำลังสร้าง)sudo mn -c แล้วรันใหม่ — คำสั่งนี้ต้องจำไปห้องสอบ
Cannot find device "h1-eth0"① พิมพ์ tc ในเทอร์มินัลของ Ubuntu ไม่ใช่ใน namespace ของ h1 ② หรือใช้ --topo linear,2,2 ซึ่งโฮสต์ชื่อ h1s1สั่งผ่าน mininet> h1 tc qdisc … หรือใน xterm h1 · ถ้าใช้ linear,2,2 ให้เปลี่ยนเป็น dev h1s1-eth0 → §3.10
RTNETLINK answers: File exists ตอนสั่ง tc qdisc addมี netem อยู่บน interface นั้นแล้วใช้ tc qdisc replace แทน add หรือ tc qdisc del … root netem ก่อน
RTNETLINK answers: No such file or directory ตอนสั่ง tc qdisc delไม่มี qdisc ให้ลบอยู่แล้วไม่ใช่ปัญหา ข้ามได้เลย — เป็นแค่การยืนยันว่าสะอาดอยู่แล้ว
ใส่ delay 100 ms แล้ว RTT ได้ ~600 msใช้ --link tc,delay=100ms ซึ่งใส่ให้ทุกปลายของทุกลิงก์ เส้นทาง h1→h3 ผ่าน 3 ลิงก์ ไป-กลับ = 6 ครั้งสร้าง topology ไม่ใส่ --link tc แล้วใช้ tc qdisc ใส่เองที่ h1-eth0 ตัวเดียว → §3.8
ใส่ delay 100 ms แล้ว RTT ได้ ~200 msเผลอใส่ netem ที่ ปลายทางด้วย (เช่นลืมลบของ h3 จากรอบก่อน)h3 tc qdisc show dev h3-eth0 ตรวจดู แล้ว h3 tc qdisc del dev h3-eth0 root netem
ค่าที่วัดได้แกว่งมาก / loss ไม่ตรงกับที่ตั้งยังไม่ปิด TSO/GSO/GRO — เคอร์เนลรวมแพ็กเก็ตเป็นก้อนใหญ่ก่อนถึง netemh1 ethtool -K h1-eth0 tso off gso off gro off ทำกับทุกโฮสต์ที่วัด
iperf3: error - unable to connect to serverยังไม่ได้เปิดฝั่ง server หรือปิดไปแล้วh2 iperf3 -s -D ก่อน แล้วค่อยสั่งฝั่ง client · เช็กว่ารันอยู่ด้วย h2 pgrep -a iperf3
iperf3: error - the server is busy running a testเทสต์เดิมยังไม่จบ หรือมี process ค้างh2 pkill iperf3 แล้วเปิดใหม่
miniedit.py ขึ้น no display name and no $DISPLAY environment variableรันผ่าน ssh ธรรมดา ซึ่งไม่มีหน้าจอกราฟิกรันในเดสก์ท็อปของ VM · หรือลง XQuartz บน Mac แล้ว ssh -Y ubuntu · หรือใช้สคริปต์ Python แทน (เร็วกว่า)
ifconfig: command not foundUbuntu รุ่นใหม่ไม่ได้ลง net-tools มาให้sudo apt install net-tools (ใบแลปเขียนไว้แล้ว) หรือใช้ ip -br a แทน
git clone ค้าง / unauthenticated git protocol … no longer supportedใบแลปใช้ git:// ซึ่ง GitHub ปิดไปแล้วเปลี่ยนเป็น https://github.com/mininet/mininet หรือ sudo apt install mininet ไปเลย
ssh ubuntu ไม่ติดVM ยังไม่บูต หรือ IP ของ VM เปลี่ยนเปิดหน้าต่าง Parallels ดูว่า Ubuntu บูตแล้ว แล้ว ip -br a ใน VM เอา IP ใหม่ไปแก้ ~/.ssh/config
ออกจาก Mininet แล้วเน็ตของ Ubuntu รวนปิดไม่สนิท เหลือ veth และ bridge ค้างในระบบพิมพ์ exit ใน Mininet CLI ให้เรียบร้อย แล้ว sudo mn -c

3.20ถ้าออกสอบ ต้องทำอะไรได้บ้าง

ข้อสอบข้อ 4 (15 คะแนน) — โจทย์เต็ม ๆ ของปีที่แล้ว

"ใช้ Mininet สร้าง network ตามรูป ให้ทุกโหนด ping ได้ แล้ว (a) ใส่ delay 100 ms + jitter 10 ms บน h1-eth0 เทียบผล ping ก่อน/หลัง (b) ใส่ loss 20% แล้วทดสอบ ping"

รันบอร์ดสำหรับห้องสอบ — ทำตามลำดับนี้ ไม่ต้องคิดเอง

  1. เปิด VM แล้ว ssh เข้าไป · ล้างของค้างก่อนเสมอ
    [macOS Terminal]
    $ ssh ubuntu
    $ sudo mn -c
  2. สร้างไฟล์ topology — คัดลอกทั้งบล็อกจาก §3.10 วิธีที่ 1 วางครั้งเดียว แล้ว sudo python3 ~/lab3.py
  3. พิสูจน์ว่า "ping ได้ทุกโหนด" — เก็บผลไว้เป็นหลักฐานทันที
    [mininet>]
    mininet> dump
    mininet> pingall
    # *** Results: 0% dropped (12/12 received)   ← ถ่ายรูป/คัดลอกเก็บ
  4. วัด baseline ก่อนใส่อะไร — ข้อสอบสั่ง "เทียบก่อน/หลัง" ถ้าไม่มีค่าก่อน จะเทียบไม่ได้
    [mininet>] — ห้ามข้ามขั้นนี้
    mininet> h1 ping -c 10 192.3.128.3
    # rtt min/avg/max/mdev = 0.047/0.127/0.206/0.051 ms  ← จดไว้
  5. (a) ใส่ delay 100 ms + jitter 10 ms บน h1-eth0 แล้ววัดใหม่
    [mininet>] — สามบรรทัดนี้คือคำตอบข้อ (a)
    mininet> h1 tc qdisc add dev h1-eth0 root netem delay 100ms 10ms
    mininet> h1 tc qdisc show dev h1-eth0
    mininet> h1 ping -c 20 192.3.128.3
    # rtt min/avg/max/mdev = 90.x/100.x/109.x/5.8 ms   ← จดเทียบกับ baseline

    ต้องอธิบายให้ได้ 3 อย่าง ① avg ขึ้นจาก 0.13 → ~100 ms ② mdev ขึ้นจาก 0.05 → ~5.8 ms คือ jitter ③ ทำไมถึง ~100 ไม่ใช่ ~200 (netem หน่วงเฉพาะขาออก)

  6. ล้างค่าก่อนทำข้อถัดไป
    [mininet>]
    mininet> h1 tc qdisc del dev h1-eth0 root netem
  7. (b) ใส่ loss 20% แล้ว ping
    [mininet>] — คำตอบข้อ (b)
    mininet> h1 tc qdisc add dev h1-eth0 root netem loss 20%
    mininet> h1 tc qdisc show dev h1-eth0
    mininet> h1 ping -c 100 -i 0.2 192.3.128.3
    # 100 packets transmitted, 81 received, 19% packet loss
    #                                        ↑ ใกล้ 20% = ถูกต้อง

    ต้องอธิบายให้ได้ 2 อย่าง ① ยิงน้อยเกินจะไม่แม่น (จึงยิง 100–150 ครั้ง) ② avg RTT แทบไม่เปลี่ยน เพราะ netem ทิ้งแพ็กเก็ตเลย ไม่ได้หน่วง และ ping เฉลี่ยเฉพาะแพ็กเก็ตที่ได้คำตอบ

  8. ล้างทุกอย่างและเก็บผล
    [mininet>]
    mininet> h1 tc qdisc del dev h1-eth0 root netem
    mininet> exit
    $ sudo mn -c
คำสั่งที่ต้องจำได้โดยไม่ต้องเปิดดู — มีแค่ 6 บรรทัด
[ท่องให้ขึ้นใจ]
sudo mn -c                                                # ล้างของค้าง
sudo python3 ~/lab3.py                                    # สร้าง topology
pingall                                                   # พิสูจน์ว่า ping ได้ทุกโหนด
h1 tc qdisc add dev h1-eth0 root netem delay 100ms 10ms   # (a)
h1 tc qdisc add dev h1-eth0 root netem loss 20%           # (b)
h1 tc qdisc del dev h1-eth0 root netem                    # ล้าง
จุดที่คนพลาดบ่อยในห้องสอบ

① ลืมวัด baseline ก่อน — ข้อสอบสั่ง "เทียบก่อน/หลัง" ไม่มีค่าก่อน = เสียคะแนน ② ลืมลบ netem ระหว่างข้อ (a) กับ (b) — ค่าจะซ้อนกัน ③ ใช้ --topo linear,2,2 แล้วไม่มี h1-eth0 ④ ping แค่ 4–10 ครั้งตอนวัด loss 20% ทำให้ตัวเลขแกว่งจนอธิบายไม่ได้ ⑤ ลืม sudo mn -c ก่อนเริ่ม แล้วเจอ File exists ตอนตื่นเต้น

3.21เช็คความเข้าใจ

baseline ping จาก h1 ไป h3 ได้ avg = 0.13 ms · จากนั้นสั่ง h1 tc qdisc add dev h1-eth0 root netem delay 100ms แล้ว ping ใหม่ — ค่า avg ควรออกมาประมาณเท่าไร
ประมาณ 200 ms เพราะ RTT คือไป-กลับ แพ็กเก็ตจึงโดนหน่วงสองครั้ง
ประมาณ 100 ms เพราะ netem ที่ root หน่วงเฉพาะแพ็กเก็ตขาออกของ h1-eth0
ประมาณ 50 ms เพราะ 100 ms ถูกแบ่งครึ่งระหว่างขาไปกับขากลับ
ประมาณ 0.13 ms เท่าเดิม เพราะ ICMP ไม่ผ่าน qdisc
qdisc ที่ติดด้วยคำว่า root อยู่บนคิวขาออก (egress) ของอินเตอร์เฟซนั้นอย่างเดียว · ICMP echo request ที่ h1 ส่งออกไปโดนหน่วง 100 ms แต่ echo reply ที่วิ่งกลับเข้า h1-eth0 เป็นทิศ ingress ไม่โดนหน่วง → RTT รวมเพิ่มขึ้นครั้งเดียว ได้ราว 100.1 ms · ถ้าอยากได้ 200 ms ต้องไปใส่ที่ h3-eth0 ด้วย · ระวังคนละเรื่องกับ --link tc,delay=100ms ซึ่งใส่ให้ทุกปลายของทุกลิงก์ เส้นทาง h1→h3 ผ่าน 3 ลิงก์จะได้ ~600 ms
สั่ง h1 tc qdisc add dev h1-eth0 root netem delay 100ms 10ms แล้ว ping 20 ครั้ง ได้ rtt min/avg/max/mdev = 90.4/100.2/109.6/5.8 ms — ทำไม mdev ถึงไม่ใช่ 10
เพราะ ping ปัดเศษ mdev ลงครึ่งหนึ่งเสมอ
เพราะ netem ทำ jitter ได้แค่ครึ่งเดียวของที่สั่ง จึงต้องใส่ 20ms ถ้าอยากได้ 10
เพราะ 10ms คือครึ่งความกว้างของช่วงสุ่ม (90–110 ms) ส่วน mdev คือส่วนเบี่ยงเบนของค่าเหล่านั้น ซึ่งได้ราว 10/√3 ≈ 5.8
เพราะยังไม่ได้ปิด TSO/GSO/GRO ถ้าปิดแล้วจะได้ 10 พอดี
ตัวเลขสองตัวนี้วัดคนละอย่าง · delay 100ms 10ms สั่งให้ netem สุ่มค่าหน่วงแบบสม่ำเสมอในช่วง 90–110 ms (ซึ่งตรงกับ min ≈ 90.4 และ max ≈ 109.6 ที่วัดได้พอดี) ส่วน mdev ที่ ping รายงานคือส่วนเบี่ยงเบนของ RTT ทั้งชุด ซึ่งของการแจกแจงสม่ำเสมอครึ่งความกว้าง a จะเท่ากับ a/√3 = 10/1.732 ≈ 5.8 ms · ทดสอบได้ ถ้าเปลี่ยนเป็น 20ms ค่า mdev จะขึ้นเป็นสองเท่า (~11.5 ms) แสดงว่าแปรผันตรงกันจริง แต่ไม่ใช่ตัวเลขเดียวกัน
สร้าง topology ตามรูปที่ 17 เสร็จ net และ dump ถูกทุกอย่าง IP ครบ แต่ pingall ขึ้น *** Results: 100% dropped (0/12 received) — ควรแก้ยังไง
ตั้งสวิตช์เป็น failMode=standalone (หรือเติม --controller none --switch ovsk,failMode=standalone) ให้ OVS ทำงานเป็นสวิตช์เรียนรู้ MAC เอง
เพิ่ม default gateway ให้ทุกโฮสต์ชี้ไปที่ 192.3.128.254
ลบ netem ที่ h1-eth0 ออกก่อน เพราะมันบล็อกทั้งเน็ตเวิร์ค
เปลี่ยน subnet เป็น 10.0.0.0/8 เพราะ Mininet รองรับแค่วงนี้
Open vSwitch ค่าเริ่มต้นเป็นโหมด secure ซึ่งไม่ยอมส่งต่อเฟรมใด ๆ จนกว่าจะมี controller มาสั่ง — ถ้าสร้าง topology โดยไม่มี controller สวิตช์จะเงียบสนิท ทุกอย่างจึง drop หมด · แก้ด้วยการตั้ง failMode='standalone' ให้สวิตช์กลับไปทำตัวเป็น L2 learning switch ธรรมดาเหมือน Legacy switch ใน MiniEdit · ข้ออื่นผิดเพราะ ทุกโหนดอยู่ /24 เดียวกันจึงไม่ต้องมี gateway · netem ที่ h1-eth0 กระทบแค่ทราฟฟิกที่ออกจาก h1 ไม่ทำให้ h2↔h3 พังด้วย · และ Mininet ใช้วงไหนก็ได้ผ่าน --ipbase หรือกำหนดเองในสคริปต์
ใส่ netem loss 15% ที่ h1-eth0 แล้ว ping -c 150 — พบว่า % packet loss ขึ้นเป็น ~15% แต่ avg RTT เท่าเดิมกับตอนไม่มี loss ทั้งที่ iperf3 กลับช้าลงมาก อธิบายอย่างไร
ping กับ iperf3 วัดคนละเส้นทาง จึงเทียบกันไม่ได้
RTT ไม่ขึ้นเพราะ netem ใส่ delay กับ loss พร้อมกันไม่ได้
iperf3 ช้าลงเพราะเปิด server ค้างไว้นานเกินไป ไม่เกี่ยวกับ loss
netem ทิ้งแพ็กเก็ตทันทีโดยไม่หน่วงเวลา และ ping เฉลี่ยเฉพาะแพ็กเก็ตที่ได้คำตอบ · แต่ TCP ต้องส่งซ้ำและหด Cwnd throughput จึงตก
สองเครื่องมือมองคนละมุม · ping วัด RTT จากแพ็กเก็ตที่ได้คำตอบกลับมาเท่านั้น — แพ็กเก็ตที่ถูก netem ทิ้งไม่มี RTT ให้เอามาเฉลี่ย และ netem ก็ทิ้งทันทีโดยไม่ได้ถ่วงเวลาใคร ค่า avg จึงนิ่ง · ส่วน TCP ตีความทุก loss ว่าเป็นสัญญาณความแออัด จึงหด Congestion Window ลงครึ่งหนึ่ง แล้วยังต้องส่งซ้ำ (เห็นเป็นคอลัมน์ Retr ที่พุ่งขึ้น) ผลคือ Bitrate ตกตามสูตร Mathis ที่ throughput แปรผกผันกับ √Loss · บทเรียน: "RTT นิ่ง" ไม่ได้แปลว่า "เน็ตยังดี"
เก็บก่อนออกจากแลปนี้

① Mininet รันบน Linux เท่านั้น — Mac ต้องใช้ Ubuntu ARM ใน Parallels แล้ว ssh ubuntu (VMware Player/Hyper-V/WSL ในใบแลปใช้ไม่ได้) ② โฮสต์อยู่ใน namespace แยก → h1-eth0 มองเห็นได้เฉพาะผ่าน mininet> h1 … หรือ xterm h1 ③ รูปที่ 17 = โฮสต์ 4 · สวิตช์ 2 · ลิงก์ 5 · ไม่มี router ไม่มี controller ④ pingall ต้องได้ 0% dropped (12/12) ⑤ tc qdisc add dev h1-eth0 root netem delay 100ms 10ms และ … netem loss 20% คือสองบรรทัดของข้อสอบ ⑥ netem ที่ root = ขาออกอย่างเดียว → RTT เพิ่ม ~100 ไม่ใช่ 200 ⑦ อ่านผล ping: avg = delay · mdev = jitter (≈ jitter/√3) · % packet loss = loss ⑧ iperf3: Bitrate = throughput · Retr = ส่งซ้ำ · จดจากบรรทัด sender ⑨ ก่อนวัดต้อง ethtool -K … tso off gso off gro off ⑩ พังเมื่อไร sudo mn -c