3 คะแนน โดย GN⁺ 2024-04-10 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • เป็นบันทึกการสร้างฮาร์ดแวร์ที่เพิ่มความสามารถรับส่ง 10BASE-T Ethernet ให้กับ คอมพิวเตอร์ลอจิกแบบดิสครีต ที่สร้างขึ้นโดยไม่มี CPU เชิงพาณิชย์หรือชิปเครือข่ายเฉพาะทาง
  • เพิ่มโมดูลชั้น MAC บน อะแดปเตอร์ชั้นกายภาพ 10BASE-T↔SPI ที่เคยสร้างไว้ก่อนหน้า เพื่อเชื่อมต่อกับ homebrew computer และจัดโครงสร้างตัวส่งกับตัวรับให้เป็นฟูลดูเพล็กซ์ที่ทำงานแยกกัน
  • ตัวรับแปลงข้อมูล SPI เป็นไบต์แล้วเก็บใน SRAM 2 kB และตรวจสอบ 6 ไบต์แรกด้วยฮาร์ดแวร์ โดยรับเฉพาะ FE:FA:F6:F2:EE:EA หรือ MAC แบบบรอดแคสต์เท่านั้น
  • เพื่อลดความซับซ้อนของวงจร ตัวส่งให้ ซอฟต์แวร์รับผิดชอบการสร้าง FCS และการเตรียมพรีแอมเบิล และรองรับเฉพาะเฟรมความยาวคงที่ 1024 ไบต์
  • สร้างแม้กระทั่งคอมไพเลอร์ C ที่คอมไพล์ uIP 1.0 ได้เพื่อรันแอปเครือข่าย โดยผลลัพธ์อยู่ที่ ping เฉลี่ย 85 ms และดาวน์โหลดไฟล์สแตติกผ่าน HTTP ได้ 2.6 kB/s

ต่อ Ethernet เข้ากับคอมพิวเตอร์ลอจิกแบบดิสครีต

  • ในฐานะงานต่อยอดจากการสร้างระบบคอมพิวเตอร์ทั้งชุดด้วย ชิ้นส่วนลอจิกแบบดิสครีต ได้พัฒนาอะแดปเตอร์ Ethernet ที่สามารถรันแอปพลิเคชันเครือข่ายได้
  • ก่อนหน้านี้เคยสร้าง อะแดปเตอร์ชั้นกายภาพที่แปลงสัญญาณ 10BASE-T Ethernet เป็น SPI และแปลงกลับ และในตอนนั้นใช้ไมโครคอนโทรลเลอร์ STM32 สำหรับทดสอบการทำงาน
  • หัวใจของงานครั้งนี้คือ โมดูลชั้น MAC สำหรับเชื่อมต่ออะแดปเตอร์ดังกล่าวเข้ากับ homebrew computer
  • อะแดปเตอร์มีโครงสร้างแบบ ฟูลดูเพล็กซ์ โดยภาคส่งและภาครับทำงานอย่างเป็นอิสระจากกัน

ตัวรับ: บันทึกข้อมูล SPI ลงในเฟรมบัฟเฟอร์

  • ตัวรับจะแปลงข้อมูลอนุกรม SPI เป็นข้อมูลขนานระดับไบต์ และแยก byte clock ออกมา
  • ตรวจสอบที่อยู่ MAC ปลายทางจาก 6 ไบต์แรก และปฏิเสธเฟรมที่ไม่ตรงตามเกณฑ์
  • ไบต์ที่รับได้จะถูกเขียนลงในบัฟเฟอร์ 6116 2 kB SRAM
  • เมื่อเฟรมจบ ตัวรับจะถูกปิดใช้งาน และจะไม่รับเฟรมเพิ่มเติมจนกว่าจะถูกเปิดใช้งานอีกครั้ง
  • ตัวนับไบต์ยังคงค่าหลังจากหยุด เพื่อให้ CPU อ่านความยาวที่รับได้
  • FCS ไม่ได้ถูกตรวจสอบในฮาร์ดแวร์
  • การเก็บข้อมูลและการเข้าถึงบัฟเฟอร์

    • ข้อมูลอนุกรม SPI เข้าสู่ชิฟต์รีจิสเตอร์ U32 โดย U30 และ U31 นับบิตและไบต์ตามลำดับ
    • D flip-flop U29B สร้างสัญญาณเขียน SRAM recv_buf_we และสัญญาณนี้จะลดต่ำลงชั่วครู่ทุก ๆ ข้อมูลอินพุต 8 บิต
    • ไบต์ที่รับได้ถูกเขียนลงใน 6116 SRAM ซึ่งคือ U20
    • U13, U16, U18 ประกอบกันเป็น address multiplexer เพื่อเลือกตัวนับไบต์หรือ system address bus เป็นอินพุตที่อยู่ของ SRAM
    • U21 ทำหน้าที่เป็น บัฟเฟอร์สามสถานะ ที่ส่งไบต์ที่รับได้ไปยัง RAM
    • RAM และตัวนับไบต์เชื่อมต่อกับ system data bus เพื่อให้ CPU เข้าถึงข้อมูลที่รับและความยาวได้
    • U25 เชื่อม RAM ฝั่งรับเข้ากับ system data bus
    • หลังเฟรมเสร็จ ค่าของตัวนับไบต์จะคงอยู่บนบัส recv_byte_cnt
    • U26, U27 จะส่งค่านี้ไปยัง system data bus เมื่อมีคำขออ่านที่อยู่เฉพาะ
    • ครึ่งที่เหลือของ U27 สร้างรีจิสเตอร์สถานะแบบอ่านอย่างเดียว 2 บิตสำหรับตรวจสถานะตัวรับและตัวส่ง

การกรองที่อยู่ MAC ด้วยฮาร์ดแวร์

  • เมื่อวิเคราะห์ทราฟฟิก Ethernet พบว่าเฟรมมักเข้ามาเป็น กลุ่มเล็ก ๆ ชุดละ 3~4 เฟรม คั่นด้วยดีเลย์สั้น ๆ และแม้ในกลุ่มเดียวกันก็มักมีที่อยู่ MAC ปลายทางต่างกัน
  • คอมพิวเตอร์อาจไม่เร็วพอที่จะทำ MAC filtering ด้วยซอฟต์แวร์แล้วเปิดใช้งานตัวรับใหม่ จึงจำเป็นต้องมี MAC filtering ด้วยฮาร์ดแวร์
  • วิธีเก็บที่อยู่ MAC ที่ผู้ใช้กำหนดแล้วเปรียบเทียบกับ 6 ไบต์แรกนั้นซับซ้อนเกินไป จึงตัดออก
  • ที่อยู่ MAC แบบไบต์เดียวซ้ำ ๆ ก็เป็นไปได้ แต่สุดท้ายเลือกสร้างที่อยู่ MAC เป็นฟังก์ชันของดัชนีไบต์
    • bit 0 ตรึงไว้ที่ 0
    • bit 1 ตรึงไว้ที่ 1
    • bit 2~4 เป็นค่ากลับบิตของดัชนีไบต์
    • bit 5~7 ตรึงไว้ที่ 1
  • ที่อยู่ MAC ที่ได้จากกฎนี้คือ FE:FA:F6:F2:EE:EA
  • เพื่อให้ ARP ทำงานได้ จึงรับ MAC แบบบรอดแคสต์ FF:FF:FF:FF:FF:FF ด้วย
  • U33 เปรียบเทียบว่า data bit 0 และ bit 2~4 ตรงกับค่าที่ต้องการหรือไม่ และเอาต์พุต U34A จะเป็นสูงเมื่อบิตเหล่านั้นตรงกัน
  • U35A ใช้ตรวจ MAC แบบบรอดแคสต์ โดยเอาต์พุตจะเป็นสูงเมื่อ bit 0 และ bit 2~4 เป็น 1 ทั้งหมด
  • สัญญาณทั้งสองถูกรวมกันด้วย diode OR โดยใช้ D7 และ R6 และ U35B ตรวจว่าบิตที่เหลือทั้งหมดเป็น 1 หรือไม่
  • ผลความถูกต้องของไบต์เดียวถูกสะสมใน U10A
    • เมื่อไม่ได้รับเฟรม สัญญาณ incoming SPI slave select ss จะต่ำ และ U10A ถูกตั้งเป็น 1
    • ระหว่างรับเฟรม ค่าจะถูกอัปเดตทุกไบต์ที่รับ
    • หากที่อยู่ MAC ปลายทางตรงตามเกณฑ์ ค่า U10A จะคงเป็นสูง
    • เมื่อที่อยู่ไบต์ถึง 5 ค่าสุดท้ายจะถูก latch เข้า U36B และหากที่อยู่ปลายทางไม่ตรง การรับเฟรมจะถูกบล็อก

ตัวส่ง: ลดความซับซ้อนของวงจรด้วยเฟรมความยาวคงที่

  • เช่นเดียวกับตัวรับ ตัวส่งไม่สร้าง FCS ในฮาร์ดแวร์ แต่ให้ซอฟต์แวร์จัดการ
  • เพื่อลดวงจร ตัวส่งรองรับเฉพาะเฟรมความยาวคงที่
  • เลือกความยาวเฟรมเป็น 1024 ไบต์ ซึ่งใกล้เคียงกับ MTU ทั่วไป 1500 ไบต์
  • พรีแอมเบิลที่จำเป็นสำหรับ 10BASE-T ประกอบด้วย 0x55 หลายตัวและ 0xD5 ที่ท้าย โดยซอฟต์แวร์ต้องโหลดรวมไว้ใน 1024 ไบต์นี้ด้วย
  • ความยาวเฟรมคงที่ไม่กระทบโปรโตคอลชั้นบน
    • โปรโตคอลชั้นบนเข้ารหัสขนาดแพ็กเก็ตไว้ใน header
    • ไม่พึ่งพาความยาวเฟรม Ethernet จริง
  • เส้นทางข้อมูลส่ง

    • ข้อมูลส่งถูกเก็บไว้ใน SRAM
    • clock 20 MHz ถูกป้อนเข้าตัวนับ 4 บิต และใช้เอาต์พุต overflow เป็น byte clock
    • เมื่อเขียนค่าใด ๆ ไปยังตำแหน่งหน่วยความจำแบบเขียนอย่างเดียวที่กำหนด ตัวนับจะเริ่มทำงานและเริ่มส่งเฟรม
    • ข้อมูลไบต์แบบขนานถูก serialize ผ่านชิฟต์รีจิสเตอร์
    • เช่นเดียวกับตัวรับ U12 นับบิตและ U14 นับไบต์
    • clock 20 MHz มาจากออสซิลเลเตอร์ในตัว และไม่ได้ใช้โดยตรง แต่แบ่งความถี่อย่างน้อย 2 เท่าก่อนใช้งาน
    • วิธีนี้ทำให้ duty cycle ของออสซิลเลเตอร์ไม่ส่งผลต่อสัญญาณเอาต์พุต
  • RAM, ชิฟต์รีจิสเตอร์ และไทมิง

    • การเลือกอินพุตที่อยู่ของ RAM U22 ใช้มัลติเพล็กเซอร์ 74HC157 จำนวนสามตัวเช่นเดียวกับตัวรับ
    • U23 ใช้สำหรับโหลดข้อมูลเข้า RAM
    • U24 ทำหน้าที่เป็น ที่พักข้อมูลชั่วคราว ของไบต์ที่กำลังส่งอยู่
    • ตัวนับไบต์ 74HC4040 เป็น ripple counter จึงเสถียรช้า
    • U24 ให้เอาต์พุตที่เสถียรในช่วงที่เอาต์พุต RAM ยังไม่ valid
    • ข้อมูลเข้าสู่ชิฟต์รีจิสเตอร์ U28 แล้วเลื่อนทีละบิต
    • มีบั๊กฮาร์ดแวร์ที่ต่อเรียงลำดับบิตจาก RAM ไปยังชิฟต์รีจิสเตอร์ผิด จึงต้องให้ซอฟต์แวร์สลับบิตเพื่อเลี่ยงปัญหา
    • MOSI และ SCK ต้องซิงโครไนซ์อย่างแม่นยำเพื่อสร้างสัญญาณ 10BASE-T ที่ดี
    • U11A และ U8B จัดการการซิงโครไนซ์นี้
    • tx_cnt0 คือ bit 0 ของตัวนับบิต และใช้เป็น clock ด้วยสัญญาณที่ได้จากการหาร 20 MHz ด้วย 2
    • U11A เปลี่ยนเอาต์พุตตามสัญญาณนี้
    • U8B หน่วง clock เพื่อให้สอดคล้องกับดีเลย์ที่ U11A สร้างขึ้น
    • D latch ซับซ้อนกว่า AND gate แบบง่ายและมีดีเลย์มากกว่าประมาณ 5 ns จึงใช้ 74LV74A ที่เร็วกว่า
    • 74LV74A เป็นชิปตระกูลความเร็วสูงตัวเดียวบนบอร์ดนี้

อินเทอร์เฟซ CPU และการแมปหน่วยความจำ

  • จากมุมมองของโปรแกรมเมอร์ อะแดปเตอร์ Ethernet ปรากฏเป็นอินเทอร์เฟซแบบ memory-mapped
  • เฟรมบัฟเฟอร์ทั้งสองถูกแมปที่ 0xF000
  • มีรีจิสเตอร์อ่านอย่างเดียวสองตัว
    • รีจิสเตอร์สถานะ 8 บิตที่ 0xFB00 มีแฟล็ก RX_FULL และ TX_BUSY
    • RX_FULL แสดงสถานะรับเฟรมเสร็จ
    • TX_BUSY แสดงสถานะกำลังส่งเฟรม
    • รีจิสเตอร์ 16 บิตที่ 0xFB02 เก็บความยาวข้อมูลที่รับได้
  • การเขียนถูกใช้เป็นคำสั่งควบคุม
    • เขียนค่าใด ๆ ไปที่ 0xFB00 เพื่อเปิดใช้งานตัวรับอีกครั้ง
    • เขียนค่าใด ๆ ไปที่ 0xFB01 เพื่อเริ่มส่ง
  • เนื่องจาก CPU ไม่รองรับ interrupt จึง ไม่มี interrupt
  • ที่อยู่ที่เกี่ยวข้องทั้งหมดเริ่มด้วย F ซึ่งมี 4 บิตบนเป็น 1 และ U2A ตรวจเงื่อนไขนี้
  • ที่อยู่บัฟเฟอร์ต้องมี bit 11 เป็น 0 โดย U1D, D2, R2, U1E ตรวจเงื่อนไขนี้
  • ที่อยู่รีจิสเตอร์ต้องมีเลขฐานสิบหกหลักที่สองเป็น B หรือ 1011 โดย U1B และ U2B ตรวจสอบ
  • ดีโคเดอร์ U4A, U4B ใช้เลือกฟังก์ชันแต่ละอย่าง
  • LED สองดวงแสดงการเข้าถึงบัฟเฟอร์หรือรีจิสเตอร์

การเขียนโปรแกรมและประสิทธิภาพ

  • ต้องการการรองรับเครือข่าย แต่ไม่อยากสร้าง TCP/IP stack เอง และการเขียน assembly ก็ไม่สะดวก จึงสร้าง คอมไพเลอร์ C
  • คอมไพเลอร์นี้สมบูรณ์พอที่จะคอมไพล์ uIP 1.0 ซึ่งเป็นไลบรารี TCP/IP ขนาดเล็กได้
  • code density ของ CPU ต่ำมาก แต่ uIP ใส่ลงใน RAM ได้ และยังเหลือพื้นที่สำหรับแอปพลิเคชันจริงด้วย
  • ประสิทธิภาพเครือข่ายต่ำ แต่เป็นผลลัพธ์ที่ได้โดยไม่ใช้ CPU เชิงพาณิชย์หรือชิปพิเศษ
    • ค่าเฉลี่ยรอบไปกลับของ ping: 85 ms
    • ความเร็วดาวน์โหลดของ HTTP server: 2.6 kB/s
    • HTTP server ให้บริการไฟล์สแตติกจาก SD card
  • โมเดล ไฟล์แผนผังวงจร และแบบ PCB อยู่ใน GitHub repository

1 ความคิดเห็น

 
GN⁺ 2024-04-10
ความคิดเห็นจาก Hacker News
  • งานเจ๋งมาก ขอบคุณที่แชร์ โดยเฉพาะ stack trace ของกระบวนการให้เหตุผล นั้นดีมาก และการที่อธิบายหลายอย่างจากหลักการพื้นฐาน หรือพยายามอธิบายในมุมมองของมือใหม่ ก็มีคุณค่าทางการศึกษามาก
    แม้จะไม่ค่อยใช้งานได้จริงกับงานเครือข่ายจริง ๆ แต่ผมไม่คิดว่านี่เป็นแค่ของเล่นธรรมดา ในยุคที่พบ backdoor ในชิปเครือข่ายที่ซับซ้อนเกินไป อนาคตอาจมีผู้อ่านที่จริงจังขึ้น หรือมีแรงจูงใจของโปรเจกต์แบบนี้มากขึ้นก็ได้

    • ผมสงสัยว่ามี ช่องโหว่ที่ซ่อนอยู่ภายในซิลิคอนสมัยใหม่ มากแค่ไหน แม้แต่โค้ดไม่กี่พันบรรทัดก็แทบมีช่องโหว่ออกมาให้เห็นทุกวัน แต่ในซิลิคอนที่ hardcode ไว้ ก็เหมือนมีไมโครชิปที่เทียบได้กับโค้ดหลายพันล้านบรรทัดอยู่ข้างใน
  • นี่ทำขึ้นสำหรับคอมพิวเตอร์แบบ custom ล้วน ๆ เลยยิ่งน่าประทับใจกว่าเดิม และไม่ต้องพูดถึงตอนที่บอกว่า “ก็เลยทำ C compiler ขึ้นมา” ถึงอย่างนั้นก็ทำให้อยากรู้ว่า การทำ Ethernet card สำหรับ PC “ทั่วไป” แบบขั้นต่ำสุด จะต้องมีประมาณไหน
    หลายส่วนน่าจะคล้ายกัน และ checksum ก็น่าจะให้ CPU ของ PC จัดการได้ ส่วนการเชื่อมต่อคงต้องเป็น serial ดิบ ๆ หรือถ้าให้ใช้งานได้จริงกว่าก็ต้องเป็น USB และสุดท้ายก็คงต้องใช้ไดรเวอร์ “จริง ๆ” หรือส่งต่อไปจัดการใน user space
    จากที่ดูของคล้าย ๆ กัน ผมเคยคิดว่าถ้าอุปกรณ์ implement https://en.wikipedia.org/wiki/USB_communications_device_clas... ได้ ก็น่าจะทำให้มัน “ใช้ได้เลย” โดยไม่ต้องมีไดรเวอร์ของตัวเอง แต่ดูจะไม่ค่อยเข้ากับการให้ host จัดการ checksum ทั้งหมดเท่าไร
    ระหว่างค้นหาก็เจอ https://en.wikipedia.org/wiki/Ethernet_over_USB ด้วย ซึ่งอาจหมายความว่าสามารถทำอะแดปเตอร์ที่แปลงเฉพาะการเชื่อมต่อทางกายภาพให้เป็น USB แล้วปล่อยให้คอมพิวเตอร์จัดการส่วนที่เหลือเองได้ก็ได้

    • USB ถือว่าซับซ้อนกว่า 10base2 Ethernet ที่ออกมานานแล้วมาก ถ้าจะเชื่อมเข้ากับเครือข่าย 10base2 Ethernet ผ่าน PCIe หรือ USB ทั้งสองแบบจะมีงานมากกว่าฝั่ง Ethernet เองเยอะมาก
      อาจพอเกลี้ยกล่อมให้อุปกรณ์ USB สไตล์ FTDI bit-bang 10base2 Ethernet ได้อยู่ วิธีคือ implement แค่ฝั่ง “PHY” ที่แปลงทราฟฟิกบนสายให้เป็น bitstream สะอาด ๆ และจัดให้ตรงกับจุดเริ่มต้นของเฟรม แล้วให้ PC จัดการส่วนที่เหลือทั้งหมดด้วยซอฟต์แวร์
    • ถ้า PC ทั่วไปยังมี บัส ISA เหมือนเมื่อ 30 ปีก่อน การ์ดเครือข่ายของผมก็สามารถแก้เล็กน้อยแล้วต่อเข้ากับมันได้
    • การ implement NIC ด้วย FPGA พร้อมการเชื่อมต่อ PCIe เป็นเรื่องพบได้ทั่วไปมาก
      ฝั่ง USB นั้น CDC-NCM เอง implement บน MCU ตัวไหนก็ไม่ยาก แต่การ implement USB HS PHY แทบต้องใช้ฮาร์ดแวร์ ASIC
      ถ้าใช้ USB HS ULPI PHY ราคา 0.30 ดอลลาร์ ก็น่าจะ implement USB CDC-NCM บน FPGA ได้ค่อนข้างง่าย
  • ตอนท้ายมีลิงก์ไปยัง C compiler ที่ทำขึ้นสำหรับโปรเจกต์นี้: https://github.com/imihajlow/ccpu-cc
    ดูเหมือนจะมี linker กับ libc ด้วย ผมไม่รู้จริง ๆ ว่าดีไซน์ฮาร์ดแวร์ซับซ้อนแค่ไหน แต่การทำ C compiler แบบเบา ๆ แล้วเอามาประกอบด้วยนั้นสุดยอดมาก

    • เป็น C compiler ที่เขียนด้วย Rust และใช้ crate lang_c สำหรับการ parse ภาษา
  • น่าประทับใจจริง ๆ ผมอยากลองทำโปรเจกต์แบบนี้เอง และนับถือทั้งความทุ่มเทกับเวลานับไม่ถ้วนที่ใช้ไปกับการทำความเข้าใจระบบแล้วสร้างมันขึ้นมา
    ผมไม่ได้อยากเกษียณเป็นพิเศษ แต่บางทีตอนนั้นผมอาจได้ใช้เวลากับ โปรเจกต์ฮาร์ดแวร์·ซอฟต์แวร์ แบบนี้ก็ได้

  • แล้วมันดีกว่า Etherlink 3c501 หรือแย่กว่ากันแน่? :-D
    https://mirror.math.princeton.edu/pub/oldlinux/Linux.old/net...
    ถ้าจำไม่ผิด มันเป็นแบบที่แพ็กเก็ตใหม่ที่เข้ามาจากเครือข่ายจะเขียนทับบัฟเฟอร์ที่ CPU กำลังจะอ่าน ผมเคยใช้บน Linux อยู่ช่วงหนึ่ง ประสิทธิภาพแย่มากจริง ๆ

    • ผมจำได้ว่า 3c590(https://github.com/torvalds/linux/blob/20cb38a7af88dc40095da...) ก็มีพฤติกรรมแย่ ๆ เหมือนกัน ต้องเปลี่ยน ค่า PCI latency จาก 32 เป็น 248 เพื่อหลีกเลี่ยงข้อผิดพลาดร้ายแรง
      น่าทึ่งมากว่าไดรเวอร์กับอัปเดตเฟิร์มแวร์ช่วยซ่อนอะไรจากสายตาเราไว้ได้มากแค่ไหน
    • เจอคำอธิบายของเจ้าสิ่งนี้แล้ว: https://www.os2museum.com/wp/emulating-etherlink/
      ของผมดีกว่าเพราะมีบัฟเฟอร์สองตัว :) ถึงอย่างนั้นก็เก็บเฟรมขาเข้าได้แค่เฟรมเดียว
  • ส่วนที่ว่า “แม้จะกำหนดความยาวเฟรมคงที่ ก็ไม่มีผลต่อโปรโตคอลชั้นบน เพราะโปรโตคอลชั้นบน encode ขนาดแพ็กเก็ตไว้ใน header และไม่ได้พึ่งพาความยาวจริงของ Ethernet frame” น่าสนใจดี
    ผมเพิ่งทำ packet decoder ไปไม่นาน และตรวจสอบอย่างชัดเจนในแต่ละชั้นว่าความยาวของชั้นล่างตรงกันหรือไม่ สำหรับ IP ใน decoder ของผม ความยาวของ IP datagram ต้องตรงพอดีกับความยาว Ethernet frame และความยาว header ของ link layer
    ไม่ใช่ว่าผมตั้งใจจะละเอียดอะไร แค่ต้องการตรวจจับเฟรมที่สั้นเกินไป แล้วหลังจากนั้นก็ตัดสินใจให้เฟรมที่ยาวเกินไปเป็น error ด้วย ผู้เขียนใช้ uIP อยู่ แต่ผมสงสัยว่า Linux หรือ OS สมัยใหม่อื่น ๆ จัดการอย่างไร และอยากรู้ด้วยว่าเขาได้ทดสอบ interoperability หรือเปล่า

    • ผมส่งเฟรมยาวออกไปในเครือข่ายอยู่ และ OS ที่ผมมีไม่มีตัวไหนแสดงปัญหาเลย เคยอ่านจากที่ไหนสักแห่งว่าบาง router ใช้เฟรมที่ยาวเกินจริง ๆ เพื่อเก็บ metadata ไว้ท้ายแพ็กเก็ต
    • timestamp และ in-band network telemetry รูปแบบอื่น ๆ ก็อาจถูกใส่เข้าไปในเฟรมในรูปแบบ trailer ได้ โดยจะมี FCS ใหม่ต่อท้าย
      ถ้าแอปพลิเคชันไม่ได้ดูข้อมูล L2, Linux IP stack ก็จะเพิกเฉยไปเลย
  • เล็กกว่าชุดการ์ด SSI Ethernet รุ่นแรกของ DEC ในเชิงกายภาพมาก: https://i.ebayimg.com/images/g/NEYAAOSw-mZlg0lZ/s-l1600.jpg
    บอร์ด DEC DEUNA ยาวเกิน 1 ฟุต แต่ก็มีฟังก์ชันเยอะกว่ามาก DEUNA เป็น NIC “ของจริง” มีคิวส่งและรับ แล้วจัดการมันได้เอง รวมถึงทำ DMA ด้วย แน่นอนว่าบนการ์ดยังมี PDP-11 ของตัวเองสำหรับรันงานนั้นด้วย

  • เจ๋งจริง ๆ อยากรู้ว่าใช้เวลานานแค่ไหน

    • การทำโมดูลเครือข่ายใช้เวลาประมาณหนึ่งเดือน แต่ การเขียน compiler ใช้เวลามากกว่านั้นเยอะ
  • แสดงให้เห็นว่าการฝัง backdoor ไว้ในชิปที่เชื่อมต่อกับพอร์ตเครือข่ายนั้นง่ายแค่ไหน

  • ในวิชา Communication Systems Engineering ผมเคย implement การประมวลผลสัญญาณ Ethernet แล้วต่อด้วย TCP/IP stack รวมถึง ARP และ switching ด้วย Motorola 68k QUIC assembly
    เป็น 18 เดือนที่ยาวนานที่สุดในชีวิต