Saturday 25 October 2014

Arista Ethernet Switch Third Party SFP Workaround


I recently had the need to get a third party DWDM SFP+ to work in an Arista 7050T switch. The following work around worked for me. Basically just comment out the vendor checking. I suspect there is a much nicer way to do this.

Step 1 unzip EOS-4.10.6.swi
step 2 unsquashfs rootfs-i386.sqsh (as root)
step 3 make changes to the Python file XcvrAgent.py. See 3.a
step 4 remove original rootfs-i386.sqsh and mksquashfs  squashfs-root/ rootfs-i386.sqsh
step 5 zip up everything without compression
zip -Z store EOS-4.10.6a.swi boot0 initrd-i386 linux-i386 rootfs-i386.sqsh version

Things to change:
/usr/lib/python2.7/site-packages/XcvrAgent.py starts line 172.
3.a) Comment out the 4 lines
assert xcvrStatus.presence == "xcvrPresent"
#Commented out to enable Third Party Optics
# If the xcvr is present, authenticate it.
#t7( "Xcvr", name, "is present. genId status=%d, cfg=%d" % \
 #    ( xcvrStatus.generationId, xcvrConfig.generationId ) )
xcvrConfig.xcvrEnabled = True
 #xcvrConfig.xcvrEnabled = xcvrStatus.xcvrEnabled
#xcvrConfig.configReason = xcvrStatus.configReason

While I would not recommend doing this on a production box it is a handy work around if you are stuck or Arista don't support the SFP+ you need.


Friday 24 October 2014

sfpduino optical power meter vs calibrated optical power meter

According to the data sheet for the third party SFP I am using the optical receive range is from 1200 to 1600nm. While the minimum receive is -13.2dBm for the SFP, the SFP does appear to be capable of measuring accurately down to -28dBm. 

My light source is an Anristu light source 1310 and 1550nm and according to the datasheet has a launch power of -7dBm for both 1310nm and 1550nm. With no attenuation added I was measuring -5.9 at 1550nm and -5.5 at 1310nm.

While SFF-8472 states that the optical power receive accuracy must be better than +/-3dB clearly my third party SFP was remarkable accurate when compared to my nice expensive calibrated power meter. 


Added Attenuation1550Metersfpduino1310Metersfpduino
0dB-5.90dBm-5.81dBm-5.50dBm-5.50dBm
5dB-10.50dBm-10.11dBm-10.10dBm-10.12dBm
8dB-13.50dBm-13.51dBm-13.90dBm-13.59dBm
11dB-17.10dBm-17.21dBm-17.90dBm-17.93dBm
14dB-19.40dBm-19.59dBm-18.9dBm-19.43dBm
15dB-20.20dBm-20.36dBm-19.70dBm-20.04dBm
18dB-22.90dBm-23.77dBm-22.50dBm-23.77dBm
21dB-23.8dBm-24.20dBm-23.60dBm-24.56dBm
25dB-25.60dBm-26.99dBm-26.00dBm-28.86dBm
30dB-31.10dBm-40dBm-33.00dBm-40.00dBm


Saturday 18 October 2014

sfpduino - Arduino SFP optical power meter

I thought it might be interesting to see what I could do with an SFP and an Arduino UNO. My first introduction to Atmel micro-controllers was with the Atmel AVR Butterfly. While the Butterfly is a fantastic piece of hardware it is much quicker to create and test things with the Arduino UNO. 















I have powered the SFP off the 3V power supply on the Arduino UNO and the 16x2 LCD with the 5V supply. I am using the Arduino Liquidcrystal display library hence all the wires! See here for the wiring diagram for the display. http://arduino.cc/en/Tutorial/LiquidCrystal
To connect the SFP to the Arduino UNO I used the Arduino Wire library. http://arduino.cc/en/reference/wire

My SFP is a third party cheap 1310nm transceiver. The SFP is plugged into a Samtec SFP header and is mounted on a piece of  perf board for convenience. The demo code below prints out the temperature and the optical power receive from the SFP using the Arduino UNO as the i2c Master. As most 1310nm SFPs can typically receive light from 1200-1600nm it could be interesting to make a very small plugable coin battery powered optical power meter with a display where all you had to do was add your own SFP with DOM. The sort of thing that you could put on a key ring and give away at trade shows.

While SFF-8472 states that the optical power receive accuracy must be better than +/-3dB. I did a quick test with 1310nm and 1550nm light sources (plus several different attenuators) and compared the measured results between a real calibrated optical power meter and my SFP. I was quite surprised that the SFP power values were typically within 0.2dB of the power meter. 

From SFF-8472
Measured TX output power in mW. Represented as a 16 bit unsigned integer with the power defined as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm).

Internally measured transceiver temperature. Represented as a 16 bit signed twos complement value in increments of 1/256 degrees Celsius, yielding a total range of -128C to +128C.

The entire sketch is below. 

#include <Wire.h>
#include <math.h>
#include <LiquidCrystal.h>

// LCD interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

const byte EEPROM_ID = 0x51;
int A51[128];

void setup()
{
  Wire.begin();        
  Serial.begin(9600);  
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
}

byte I2CEEPROM_Read (unsigned int address)
{
  byte data;
  Wire.beginTransmission(EEPROM_ID);
  Wire.write(address);
  Wire.endTransmission();
  Wire.requestFrom(EEPROM_ID,(byte)1);
  while(Wire.available() == 0); data = Wire.read();
    return data;
}

void loop()
{
   for (int i = 96; i <106; i++)
  {
    A51[i] = I2CEEPROM_Read(i);
   }
  float temp = A51[96] + (float) A51[97]/256;
  float optical_rx = 10 * log10((float)(A51[104]<<8 | A51[105]) * 0.0001);
  lcd.setCursor(0, 0);
  lcd.print ("Temp = ");
  lcd.print (temp);
  lcd.print ((char)223); //degree symbol
  lcd.print ("C");
  lcd.setCursor (0, 1);
  lcd.print ("RX = ");
  lcd.print (optical_rx);
  lcd.print (" dBm");
    
delay(1000);
}

Sunday 21 September 2014

Barn door


I have seen quite a few different Scotch Mounts on different web pages, These are pretty easy to make.
I used instructions from Stephen Tonkin's. It took me about 2 hours with a trip to my local hardware shop to buy a long M10 nut and bolt. Stephen's instructions are here. http://astunit.com/atm.php?topic=handscotch















One thing I did notice is that several people are using all sorts of dimensions with no explanation of where they got the values. Below is my explanation as to why I used an M10 bolt and placed the bolt at 342mm from the pivot.

The Earth takes 24 hours or 1440 minutes to complete a single rotation. To be really precise, the Earth actually takes 23 hours, 56 minutes and 4.1s (a sidereal day) or 1436.068333 minutes to complete the rotation. So, taking a complete rotation to be 360 degrees; in a minute, the Earth would have rotated only about 0.25 degrees. That means, for every minute, my tracker needs to increase the distance between the upper and lower platform to achieve a 0.25 degrees increase in the angle subtended by the 2 platforms at the hinges.

This equates to 360 degrees(One full revolution of the earth). So in one minute we move 360/1436.068333 = .250684 degrees per minute. The advantage of using one rotation per minute is you can easily use a watch to keep an eye on your timing. A quarter turn every 15 seconds for example.

So now that we know how many degrees we need to move our camera every minute, we still need to work out the dimensions of our triangle to make sure we use the correct thread depth on our bolt and place our bolt at teh correct distance from the hinge.

Example 1: c = a/tan(γ)

Assuming a right angle triangle, we have tan = opposite/adjacent. Tan(γ) = a/c and hence c = a/tan(γ)


 With a = 0.0015m thread depth for an M10 bolt and (γ) = 0.250684 degrees, c works out at: 342mm.

Example 2: c = a/2Sin(γ/2)




For a right angle triangle. Sin(γ)= opposite/hypotenuse. Sin(γ/2) = (a/2)/c. Hence c = a/2Sin(γ/2).

Examples: I used an M10 bolt with a pitch of 1.5mm according to the spec I found.
c = 0.0015/2Sin(.250684/2) = 342mm

This looks like an interesting project:
http://www.garyseronik.com/?q=node/52






Friday 16 May 2014

Raspberry Pi and Programming EEPROMs on SFP/SFP+ modules


Connecting to the I2C pins on an SFP can be difficult, the easiest way I have found is to use old Cisco TwinGig module to house the SFP or SFP+. These can be purchased at a very reasonable price from ebay if you don't have one lying around.

The pins we are interested in on the SFP/SFP+ are:
Pin1: All VeeT or VeeR pins are ground, you only need to connect to one as they are connected internally in the SFP.
Pin 15 and Pin 16 both require +3.3V.
Pin 4: MOD-Def(2) - data line of i2c serial interface
Pin 5: MOD-Def(1) - clock line of i2c serial interface
Pin 6: MOD-Def(0) is connected to ground internally on any of the SFPs I have played with. So no need to connect.





The easiest place I found to make a solder was on the ends of resistors R57 (SDA) and R54(SCL) on the back of the PCB. For the 3.3V and 0V I used the large PCB edge card connectors.











On the Raspberry Pi you just need to connect the 4 wires to the GPIO pins:
GPIO Pin 1: 3.3V
GPIO Pin 6: 0V
GPIO Pin 3: SDA
GPIO Pin 5: SCL

Here is what the final version should look like:
















How to test that everything is working:
1) Install i2c-tools. ie apt-get install i2c-tools
2) Make sure the module is being loaded and not blacklisted.
pi@raspberrypi ~ $ cat /etc/modprobe.d/raspi-blacklist.conf
# blacklist spi and i2c by default (many users don't need them)
blacklist spi-bcm2708
#blacklist i2c-bcm2708

3) Test your wiring. Make sure you can see the SFP address (0x50) on the I2C bus. If you cannot see the address something is wrong with your wiring.


pi@raspberrypi ~ $ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --                      
pi@raspberrypi ~ $

If you also see address 0x51, your SFP supports DOM(Digital Optical Monitoring).

4) Read the EEPROM details from address 0x50 using i2cdump.


pi@raspberrypi ~ $ i2cdump -y 1 0x50
No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 03 04 07 00 00 00 01 00 00 00 00 01 0d 00 00 00    ???...?....??...
10: 37 1b 00 00 52 61 73 70 62 65 72 72 79 20 50 69    7?..Raspberry Pi
20: 20 20 20 20 00 00 30 d3 51 46 42 52 2d 35 37 36        ..0?QFBR-576
30: 36 4c 50 20 20 20 20 20 20 20 20 20 03 52 00 c6    6LP         ?R.?
40: 00 1a 00 00 31 32 33 34 35 36 37 38 39 4a 4b 20    .?..123456789JK
50: 20 20 20 20 30 35 30 33 31 30 20 20 00 00 00 95        050310  ...?
60: 00 00 02 ab 89 12 ea 3e 00 04 1c 5f 6a 0a de 10    ..?????>.??_j???
70: 74 11 3b 00 00 00 00 00 00 00 00 00 ef 19 f8 08    t?;.........????
80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
pi@raspberrypi ~ $

To understand the details of the EEPROM refer to the latest SFP MSA.
ftp://ftp.seagate.com/sff/SFF-8472.PDF
Note the addresses in the SFP MSA are in decimal while the addresses above in the dump are in hex.

5) How to read/write to the EEPROM on your SFP or SFP+

The easiest way I have come across for the Pi is using a library called wiringPi by Gordon Henderson. Check out  http://wiringpi.com/ for details.

To read all the bytes on the EEPROM and store them in an array called A50.

int xio;
int fd1;
unsigned char A50[128];
printf ("Read SFP EEPROM\n");

        xio = wiringPiI2CSetup (0x50);
        if (xio < 0){
                fprintf (stderr, "xio: Unable to initialise I2C: %s\n", strerror (errno));
                return 1;
        }
        /*Read in the first 128 bytes 0 to 127*/
        for(i=0; i <128; i++){
                fd1 = wiringPiI2CReadReg8 (xio,i);
                A50[i] = fd1;
        }

//print vendor id bytes 20 to 35
        memcpy(&vendor, &A50[20],16);
        vendor[16] = '\0';
        printf("\nVendor = %s",vendor);

You can write a byte or an array containing your bytes using a loop for  wiringPiI2CWriteReg8.
unsigned char mybytes[] = {0xff};
   wiringPiI2CWriteReg8(xio, counter, mybytes[0]);

To check to see if your checksum agrees with the value on the EEPROM.
        sum = 0;
        for (counter = 0; counter <0x3f; counter++)
        sum = (A50[counter] + sum);
        sum = sum & 0xff;
        cc_base = A50[0x3f]; //sum stored in address 63.
        printf("value of cc_base = %x and sum= %x\n",cc_base,sum);
        printf ("\n");

To read the transceiver wavelength:
int wave; //3 bytes. 60 high order, 61 low order. 62 is the mantissa             
        wave = ((int) A50[60]<<8) | ((int) A50[61]);
        printf("\nWavelength = %d.%d",wave,A50[62]);


The dump of the EEPROM from the SFP above has a vendor id of Raspberry Pi. It's easy enough to read in and print out more values.
Transceiver is 1000Base SX
Wavelength = 850.0
Vendor = Raspberry Pi  
Serial = 123456789JK
cc_base = c6 and cc_ext = 95

The SFP EEPROM above is Cisco compliant without using service unsupported. To make an SFP Cisco compliant you need to make the two checksums valid(cc_base and cc_ext), you also need to compute the vendor specific bytes 60 to 0x7f. 
Details can be found here: http://forum.nag.ru/

My code can be found here: https://github.com/sonicepk/sfppi