Skryptowe odpytywanie DDM po I2C: które bajty A2h trzymają wartości bieżące, a które progi
Piszę mały poller, który ściąga temperaturę, napięcie, prąd polaryzacji i moc optyczną wprost z modułów na naszych whiteboksach, żebyśmy mieli linię trendu zamiast kogoś, kto zerka na link okiem dopiero, gdy już zaczął sypać błędami. NOS wypisuje ładne wartości, ale chcę surowe liczby razem z progami vendora obok nich, żeby poziomy alarmów były spójne w mieszanej optyce zamiast ręcznie wpisywane per model.
Stanowisko:
- host Linux, klatki modułów za zwykłym multiplekserem I2C, bus 1
- mieszana optyka SFP, SFP+ i SFP28 od trzech vendorów
- odczyt tylko przez i2c-tools, bez SDK vendora
Stronę diagnostyczną czytam tak:
# i2cdump -y 1 0x51
a to mój roboczy parser, i tu właśnie nie jestem pewien:
temp = s16(a2[96:98]) / 256.0
vcc = u16(a2[98:100]) * 100e-6
bias = u16(a2[100:102]) * 2e-6
Co już zrobiłem:
- porównałem swoje wyliczone wartości z tym, co wypisuje NOS: na części modułów blisko, na innych wyraźnie obok
- przeczytałem SFF-8472, ale wciąż nie umiem pewnie powiedzieć, gdzie kończy się blok progów, a gdzie zaczyna obszar kalibracji
- wykluczyłem multiplekser, zrzucając ten sam moduł na bezpośrednim busie, te same liczby
Czyli: jak naprawdę wygląda mapa A2h, gdzie mieszkają progi, gdzie zaczynają się wartości bieżące, i czy jest gdzieś flaga, która mówi mi, czy moduł oczekuje, że coś zrobię z tymi surowymi słowami, zanim im zaufam?
Comments 7
Które wartości są wyraźnie obok, wszystkie cztery czy tylko bias i moce? To zwykle rozstrzyga całą sprawę. Przy okazji zrzuć też A0h i spójrz na bajt 92: mówi, czy moduł w ogóle raportuje diagnostykę, i czy jest kalibrowany wewnętrznie czy zewnętrznie. Jeśli część twojej floty jest kalibrowana zewnętrznie, a twój parser traktuje wszystkich tak samo, to rozjazd jest oczekiwanym zachowaniem, a nie bugiem w twojej arytmetyce.
Ściągnąłem A0h bajt 92 z całej tacki i nie jest jednolity. Część modułów flaguje kalibrację zewnętrzną, część nie, i te, które nie zgadzają się z wyjściem NOS, to dokładnie te zewnętrzne. Temperatura i napięcie mieszczą się w szumie wszędzie; to bias i obie moce dryfują. Więc wygląda na to, że brakuje mi kroku, a nie że czytam złe offsety. Co właściwie muszę zrobić z surowymi słowami w tej podgrupie?
A2h pod 0x51 dzieli się na cztery fragmenty, które są dla ciebie istotne:
Jednostki w bloku bieżącym: temperatura ze znakiem, 1/256 C na LSB; napięcie 100 uV na LSB; bias 2 uA; moc TX i RX 0,1 uW. Twój fragment kodu już skaluje to poprawnie, więc offsety nie są twoim problemem.
Brakującym elementem jest flaga, którą właśnie znalazłeś. W module kalibrowanym zewnętrznie słowa pod 96-105 to surowe wyjście ADC, i stałe pod 56-95 trzeba nałożyć, zanim będą cokolwiek znaczyć; moduł kalibrowany wewnętrznie już zrobił to za ciebie. Ta gałąź to różnica między twoimi dwiema grupami.
Jeśli chcesz mieć układ do sprawdzenia zamiast wierzyć mi na słowo, nagłówek FreeBSD sff8472.h i py-sfp-eeprom oba rozpisują offsety pole po polu. Ja i tak zweryfikowałbym po jednym module na vendora względem wartości, której ufasz, zanim powiesisz na tym alarmy.
Warto dodać, dlaczego blok progów jest tą ciekawszą połową. Wartości w 0-55 są w tych samych jednostkach co blok bieżący, więc gdy tylko skalowanie masz poprawne, dostajesz za darmo własne punkty alarmowe i ostrzegawcze vendora i nigdy nie musisz wymyślać limitów per model. To samo w sobie uzasadnia czytanie A2h bezpośrednio zamiast parsowania czyjegoś ładnego printera.
Jedna praktyczna uwaga z uruchamiania tego na mieszanej tacce: trzymaj interwał odpytywania skromny. Ta strona to zwykły odczyt I2C, a kontroler modułu nie jest szybki. Walenie w każdy moduł co sekundę na busie, który dodatkowo siedzi za multiplekserem, to dobry sposób na zbieranie krótkich odczytów, które na wykresach wyglądają dokładnie jak migocząca optyka.
Uważaj, jak to formułujesz, bo ludzie czytają to jako „zawsze nakładaj stałe" i potem zastanawiają się, czemu ich liczby się pogorszyły. Stałe pod 56-95 stosuje się tylko wtedy, gdy bajt 92 w A0h mówi, że moduł jest kalibrowany zewnętrznie. Nałóż je na moduł kalibrowany wewnętrznie, a zamienisz całkiem dobre odczyty w bzdury, bo moduł już wykonał tę pracę. Najpierw odczytaj flagę, rozgałęź się na niej, trzymaj obie ścieżki w parserze i loguj, którą ścieżkę wziął dany moduł, żeby później móc odróżnić oba tryby awarii.
Ta sama klasa pułapki z temperaturą: jest ze znakiem. Sparsuj ją jako bez znaku, a wszystko poniżej zera wróci jako dziko wysoka liczba, co jest zabawne pierwszego zimnego poranka, kiedy przez to dostaniesz alarm.
Update z mojej strony. Rozgałęziłem się na bajcie 92 A0h i nakładam stałe tylko tam, gdzie moduł mówi, że jest zewnętrzny. Bias i obie moce teraz zgadzają się z tym, co wypisuje NOS, na każdym module, z jakim mogłem to porównać, a temperatura i napięcie w ogóle nigdy nie były problemem. Dwa moduły wciąż zgłaszają obecność diagnostyki, ale zwracają progi, którym bym nie ufał, więc dla nich wracam do własnych limitów i flaguję moduł w inwentarzu zamiast udawać. Nie nazywam tego zamkniętym tematem, ale powyższa mapa to było dokładnie to, czego mi brakowało.
Jeszcze jedno, zanim to trafi na produkcję. Bajt 110 siedzi na tej samej stronie i to status plus kontrola, a połowa kontrolna obejmuje TX disable. Poller w ogóle nie powinien pisać do A2h, ale jeśli twoja biblioteka gdzieś robi read-modify-write, albo pomylisz się palcem w i2cset, testując na żywym urządzeniu, możesz zdjąć klientowi link z userspace. Otwieraj bus w pollerze tylko do odczytu, a każdą ścieżkę zapisu trzymaj w osobnym narzędziu, które trzeba uruchomić świadomie.
Ten sam bajt daje ci TX fault i RX LOS, i oba warto eksportować obok wartości analogowych. Moduł, który siedzi przy rozsądnej mocy RX z ustawionym LOS, mówi ci zupełnie inną historię niż taki, który po prostu pokazuje niską moc.