AFBR-89BDDZ QSFP28 báo trường vendor là 0905000000000000 sau khi giao diện SP/FPGA chuyển sang FIFO
Bọn mình phụ trách firmware quản lý switch trên phần cứng tự làm, và kể từ khi giao diện SP/FPGA được đổi từ memory mapped buffer sang FIFO, inventory transceiver trả về toàn rác trên một số cổng.
- Quang QSFP28, toàn bộ là AFBR-89BDDZ cùng một lô
- Việc đọc đi qua đường service processor và FPGA tới EEPROM của module
- Hàm hỗ trợ phía host là get_i2c_status_and_read_buffer: kiểm tra status, đọc toàn bộ buffer, kiểm tra status lần nữa
Thứ bọn mình nhận được thay vì dữ liệu vendor:
one port, vendor field: 0905000000000000
the next port, vendor field: all ones
on another machine: vendor field all zeros, elsewhere repeated digit characters
Những gì bọn mình đã thử:
- đọc lại cùng một cổng nhiều lần liên tiếp, và rác đó ổn định theo từng cổng chứ không phải nhiễu ngẫu nhiên
- power cycle lại module, không khác gì
- xác nhận mọi module trong chassis đều cùng part number, nên đây không phải do bọn mình decode sai một khối vendor lạ nào đó
Trước khi bắt đầu rút quang ra khỏi hệ thống production, khả năng cao hơn là do module, đường I2C, hay chính hàm đọc của bọn mình?
Comments 7
Cái đó chỉ thẳng vào đường đọc, và việc đổi sang FIFO chính là nguyên nhân. Một memory mapped buffer trả về cùng nội dung dù bạn hỏi bao nhiêu lần; một FIFO nhả từng byte đúng một lần rồi thôi, hết. Cái trình tự get_i2c_status_and_read_buffer kế thừa lại, kiểm tra status, đọc toàn bộ buffer, kiểm tra status lần nữa, có lý khi đứng sau bộ nhớ nhưng không còn hợp lý với FIFO: nó rút cạn hàng đợi trong khi việc đọc EEPROM của module vẫn đang trên đường truyền. Bạn nhận được bất cứ thứ gì đang nằm ở đó vào đúng thời điểm ấy, còn các byte đến muộn thì ở lại phía sau và xuất hiện ở lần đọc kế tiếp.
Đó chính xác là dấu vết bạn mô tả. Rác ổn định theo từng cổng, sự hỏng hóc di chuyển theo trình tự, toàn số 0 trên máy này và mẫu chữ số lặp lại trên máy khác tùy theo timing rơi vào đâu. Không có gì trong đó đòi hỏi phải có module hỏng, và kết quả swap của bạn cũng loại quang ra khỏi danh sách nghi phạm rồi.
Cách sửa là ngừng để caller chịu trách nhiệm kiểm tra hoàn tất. Chuyển trách nhiệm đó vào bên trong chính routine đọc của driver transceiver: nó chờ tới khi transaction I2C báo xong rồi mới đụng vào buffer, nên không caller nào có thể rút cạn nó sớm được về mặt cấu trúc. Vá một điểm gọi duy nhất chỉ đẩy cái race sang chỗ khác thôi.
Cảnh báo trước là đây là hình hài đề xuất của bản fix chứ không phải thứ đã có nhiều năm kiểm nghiệm phía sau, nên hãy validate trên platform của bạn trước khi tin tưởng inventory trở lại. Nhưng có một bài học rẻ đáng mang theo: chuỗi vendor bị lỗi đáng được test module-so-với-cổng trước tiên, vì thứ tự đọc hóa ra là thủ phạm nhiều hơn hẳn so với quang.
Phép đo duy nhất chia đôi việc này ra: sự hỏng hóc đi theo module hay đi theo cổng? Rút module ra khỏi cổng đang trả về
0905000000000000, đổi nó với module từ một cổng đọc đúng, rồi đọc lại cả hai. Nếu chuỗi lỗi đi theo module vật lý, hãy quay sang xem xét quang. Nếu nó ở lại với số cổng, hoặc tệ hơn, di chuyển theo bất kỳ module nào được đọc kế tiếp, thì module vô tội và bạn đang có vấn đề đọc ở phía host.Trong lúc đang làm, hãy dump luôn byte EEPROM thô cùng với các trường đã decode. Rác trong chuỗi vendor đã decode mà byte bên dưới vẫn hợp lệ là một bug hoàn toàn khác so với rác nằm ngay trong chính các byte đó.
Đã chạy swap đó trên một cặp cổng. Dữ liệu lỗi không đi theo module: cổng từng trả về
0905000000000000vẫn tiếp tục trả về y vậy dù đã cắm module khác, còn module bọn mình rút ra thì đọc hoàn hảo ở khe mới của nó.Còn hơn thế nữa, khi bọn mình đổi thứ tự đọc các cổng, sự hỏng hóc di chuyển theo trình tự đó. Rác rơi vào bất kỳ module nào được đọc ngay sau module gây lỗi. Vậy là nó bám theo thứ tự đọc, không phải linh kiện vật lý. Byte thô cũng sai luôn, nên đây không phải vấn đề decode ở phía bọn mình.
Nguyên nhân gốc khác, nhưng cùng một cái bẫy, từ phía driver. Trên một con Intel E810-C với bản ice 1.15.4 ngoài cây nguồn chính, mình nhận được các page sai và thiếu từ
ethtool -mtrên quang QSFP28: dữ liệu page 1 và page 3, ngưỡng và các monitor theo từng lane, không khớp với những gì module thực sự chứa. Mình chưa bao giờ có được một phát biểu root cause tử tế cho việc này, thread bị đóng lại coi như đã giải quyết mà không có nhiều chi tiết, nên coi đây là giai thoại chứ đừng coi là chân lý.Cuối cùng mình đã cập nhật driver ice và NVM của E810 bằng
nvmupdate64e, đối chiếu chéo với một lần đọc từ driver ice trong kernel trên máy khác, và kéo các page cụ thể bằngcộng thêm offset và length tường minh, thay vì tin vào output đã decode. Nếu platform của bạn dump thô được, hãy so sánh thô với đã decode trước khi tin cái nào.
Đáng để nói rõ cách phân lớp, vì nó làm kiểu truy tìm này ngắn hơn nhiều. Trên Linux,
ethtool -mdecode EEPROM của module (tên vendor, OUI, part number, serial, date code, và giá trị DDM khi module có),ethtool -edump byte thô, và ở đâu bus I2C được expose ra thìi2cdump -y 1 0x50đọc A0h còni2cdump -y 1 0x51đọc A2h.Trong A0h, tên vendor nằm ở byte 20-35 và PN, rev, SN ở byte 40-59. Nên nếu trường vendor bị lỗi mà part number nằm xa hơn vài chục byte vẫn nguyên vẹn, riêng điều đó đã nói lên việc đọc phụ thuộc vào timing chứ không phải EEPROM hỏng, khớp với những gì bạn đang thấy.
Một kiểu lỗi đừng nhầm với cái này:
ethtool -mtrả về Input/output error thường chỉ đơn giản là module không có DDM. Byte 92 bit 6 của A0h là cờ báo A2h có tồn tại hay không, và test đó đã được đưa vào driver ixgbe và bnx2x trong kernel từ lâu để chúng ngừng với tới 256 byte khác vốn không tồn tại.Cùng dạng vấn đề trên các máy SONiC, dành cho ai đến từ phía đó.
sfputil show eeprombáo Cannot get Module EEPROM data: Invalid argument với một số module nhất định, hoặc âm thầm không khớp vớishow interfaces transceiver eepromtrên cùng một cổng.Từ những gì mình từng gặp thì phần lớn là khoảng trống ở platform và driver chứ không phải do quang: hai lệnh đó dùng tên key không nhất quán ở nhánh 202012 và đã được sửa ở 202205, một số platform mất module QSFP khỏi sfputil sau khi power cycle cho tới khi có bản fix driver, và ở những platform khác thì get_transceiver_info đơn giản là chưa được implement. Khi cần thứ gì đó đáng tin để viết script, mình đi thẳng tới driver kernel optoe và tự đọc thô EEPROM của SFP, QSFP hay CMIS. Nhưng cứ kiểm tra trên platform của bạn, hành vi khác nhau khá nhiều giữa các loại.
Cập nhật từ phía bọn mình. Bọn mình đã chuyển việc kiểm tra hoàn tất vào hàm đọc của driver như được đề xuất, và chuỗi vendor đã đúng trên mọi cổng qua vài trăm lượt inventory, kể cả hai cổng từng đổi rác qua lại cho nhau. Byte thô giờ khớp với các trường đã decode.
Mình tạm gọi đây là một phần chứ chưa đóng hẳn: bọn mình đang mang nó như một patch chưa vào tree chính thức, và còn một platform nữa với bản FPGA khác cần verify trước khi tin tưởng nó ở mọi nơi. Nhưng quang thì đúng là ổn từ đầu tới cuối, đó chính là phần mà tự mình sẽ đoán sai nếu không có mọi người.