Industruino / democode

Arduino sketches with demo code that comes pre-installed on your Industruino product
7 stars 9 forks source link

Byte order of MAC address is extracted incorrectly #2

Closed shanevanj closed 6 years ago

shanevanj commented 6 years ago

The RTC used in the DG21 top board is the MCP79402. This device has a 64bit MAC address stored at location 0xf0 to 0xf8 (see data sheet http://ww1.microchip.com/downloads/en/DeviceDoc/MCP79400-MCP79401-MCP79402-Data-Sheet-20005009G.pdf section 6.3.2) this means the OUI is at 0xf0 (not at 0xF2 as on the MCP79401).

To generate a correct 48bit (6 byte) Mac address. Locations 0xF0,0xF1,0xF2 will contain valid OUI and locations 0xF5,0xF6,0xF7 will contain a unique EI.

modified code snippet to demonstrate:

// the RTC has a MAC address stored in EEPROM - 8 bytes 0xf0 to 0xf7 void readMACfromRTC() { SerialUSB.println("READING MAC from RTC EEPROM"); lcd.setCursor(0, 7); lcd.print("MAC "); for (int i = 0; i < 8; i++) { // get 6 bytes for MAC address from 8 byte version in MCP79402 if (i == 3 || i ==4 ) continue; // skip 1st 2 bytes of EI mac[i] = readByte(0x57, 0xf0 + i); SerialUSB.print(mac[i], HEX); lcd.print(mac[i], HEX); if (i < 7) { SerialUSB.print(":"); lcd.print(":"); } } SerialUSB.println(); }

tomtobback commented 6 years ago

Hi, thanks for the feedback. i have updated the example, slightly different from what you suggest, as you still end up with a 8 byte mac variable, while i prefer to generate a 6-byte one https://github.com/Industruino/democode/blob/master/MACfromRTC/MACfromRTC.ino

tomtobback commented 6 years ago

I tried the updated code, with the correct OUI (Microchip: 0x0, 0x4, 0xA3) plus the 3 last bytes of the EI (0x4D, 0x65, 0x75), and it changed the behaviour of my application as follows:

router with IP 192.168.1.1, subnet mask 255.255.255.0 industruino IP 192.168.1.100 other device X with IP 192.168.1.200 no other devices, no internet connection 1) client.connect() to 192.168.1.200: success 2) client.connect() to 192.168.1.199 (non-existing but inside subnet mask): normal timeout 3) client.connect() to a non-existing IP outside of the router's subnet mask (10.254.1.1) the unit hangs completely, with no timeout kicking in

When i use the previous version of the MAC address generator, skipping the 2 first bytes of the OUI (0xA3, 0xB, 0x0, 0x4D, 0x65, 0x75), i get: 1) success 2) timeout 3) timeout

The reason seems to be the type of MAC address: unicast vs multicast https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast The Microchip OUI's first byte is 0x0; its LSB is 0, that makes it a unicast MAC. In my second version, the first byte is 0xA3; its LSB is 1, making it a multicast MAC(?) - the consequence is that the frame is only sent once(?), so it does a proper timeout, while in the above case, it hangs, which is less desirable, but i'm not sure of the consequences of using a multicast type MAC.

shanevanj commented 6 years ago

Yes you are correct - the mac should start with Microships OUI = 00:04:A3 - this is a universal address and unicast

Here is the code I am currently using and its working perfectly (maybe my posted code was wrong)

// the RTC has a MAC address stored in EEPROM - 8 bytes 0xf0 to 0xf7 // --------------------------------------------------------------------------- void readMACfromRTC(byte* mac) // --------------------------------------------------------------------------- { byte sizeOfMCP79402MAC = 8; // 64 bit mac, we need to extract a 48bit one

for (int i = 0; i < sizeOfMCP79402MAC; i++) { // use 6 bytes for MAC address, skipping first 2 of bytes of 64bit EI if (i == 3 || i ==4 ) continue; // skip 1st 2 bytes of EI mac[i] = readByte(0x57, 0xf0 + i); } }

So in my example I get a MAC of 00:04:A3:00:10:4D

Shane van Jaarsveldt Tel: +27 11 469 4750 Cel: +27 82 601 0499 Fax: +27 11 469 3370

On 19 Oct 2018, at 11:38, tomtobback notifications@github.com wrote:

I tried the updated code, with the correct OUI (Microchip: 0x0, 0x4, 0xA3) plus the 3 last bytes of the EI (0x4D, 0x65, 0x75), and it changed the behaviour of my application as follows:

router with IP 192.168.1.1, subnet mask 255.255.255.0 industruino IP 192.168.1.100 other device X with IP 192.168.1.200 no other devices, no internet connection

client.connect() to 192.168.1.200: success client.connect() to 192.168.1.199 (non-existing but inside subnet mask): normal timeout client.connect() to a non-existing IP outside of the router's subnet mask (10.254.1.1) the unit hangs completely, with no timeout kicking in When i use the previous version of the MAC address generator, skipping the 2 first bytes of the OUI (0xA3, 0xB, 0x0, 0x4D, 0x65, 0x75), i get:

success timeout timeout The reason seems to be the type of MAC address: unicast vs multicast https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast The Microchip OUI's first byte is 0x0; its LSB is 0, that makes it a unicast MAC. In my second version, the first byte is 0xA3; its LSB is 1, making it a multicast MAC(?) - the consequence is that the frame is only sent once(?), so it does a proper timeout, while in the above case, it hangs, which is less desirable, but i'm not sure of the consequences of using a multicast type MAC. — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/Industruino/democode/issues/2#issuecomment-431305924, or mute the thread https://github.com/notifications/unsubscribe-auth/AKhBu9zoCa51zXL6k1cbsHUbzUCWUsRUks5umZ2IgaJpZM4Xstis.

shanevanj commented 6 years ago

Also remember the unicast bit is the LSB of the first Octet - so a MAC starting with A4 works, but A3 (or A5) won’t.

So you should use the Microchip first three (00 04 A3) as it is a globally unique OUI and then the rest should be unique by using the last three bytes of the RCT 0xF5. 0xF6, 0xF7. I am using a MIkroTik router and this is issuing okay and I am connecting to a AWS endpoint using DNS lookup and that seems to work fine.

My IP detail :


Network Configuration NMAC Address:0004A300014D IP:192.168.50.232 Subnet:255.255.255.0 Gateway:192.168.50.1 DNS:8.8.8.8

Shane van Jaarsveldt Tel: +27 11 469 4750 Cel: +27 82 601 0499 Fax: +27 11 469 3370

On 19 Oct 2018, at 12:17, Shane van Jaarsveldt shane@vanjaarsveldt.co.za wrote:

Yes you are correct - the mac should start with Microships OUI = 00:04:A3 - this is a universal address and unicast

Here is the code I am currently using and its working perfectly (maybe my posted code was wrong)

// the RTC has a MAC address stored in EEPROM - 8 bytes 0xf0 to 0xf7 // --------------------------------------------------------------------------- void readMACfromRTC(byte* mac) // --------------------------------------------------------------------------- { byte sizeOfMCP79402MAC = 8; // 64 bit mac, we need to extract a 48bit one

for (int i = 0; i < sizeOfMCP79402MAC; i++) { // use 6 bytes for MAC address, skipping first 2 of bytes of 64bit EI if (i == 3 || i ==4 ) continue; // skip 1st 2 bytes of EI mac[i] = readByte(0x57, 0xf0 + i); } }

So in my example I get a MAC of 00:04:A3:00:10:4D

Shane van Jaarsveldt Tel: +27 11 469 4750 Cel: +27 82 601 0499 Fax: +27 11 469 3370

On 19 Oct 2018, at 11:38, tomtobback <notifications@github.com mailto:notifications@github.com> wrote:

I tried the updated code, with the correct OUI (Microchip: 0x0, 0x4, 0xA3) plus the 3 last bytes of the EI (0x4D, 0x65, 0x75), and it changed the behaviour of my application as follows:

router with IP 192.168.1.1, subnet mask 255.255.255.0 industruino IP 192.168.1.100 other device X with IP 192.168.1.200 no other devices, no internet connection

client.connect() to 192.168.1.200: success client.connect() to 192.168.1.199 (non-existing but inside subnet mask): normal timeout client.connect() to a non-existing IP outside of the router's subnet mask (10.254.1.1) the unit hangs completely, with no timeout kicking in When i use the previous version of the MAC address generator, skipping the 2 first bytes of the OUI (0xA3, 0xB, 0x0, 0x4D, 0x65, 0x75), i get:

success timeout timeout The reason seems to be the type of MAC address: unicast vs multicast https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast The Microchip OUI's first byte is 0x0; its LSB is 0, that makes it a unicast MAC. In my second version, the first byte is 0xA3; its LSB is 1, making it a multicast MAC(?) - the consequence is that the frame is only sent once(?), so it does a proper timeout, while in the above case, it hangs, which is less desirable, but i'm not sure of the consequences of using a multicast type MAC. — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/Industruino/democode/issues/2#issuecomment-431305924, or mute the thread https://github.com/notifications/unsubscribe-auth/AKhBu9zoCa51zXL6k1cbsHUbzUCWUsRUks5umZ2IgaJpZM4Xstis.

tomtobback commented 6 years ago

thanks Shane, all clear now

shanevanj commented 6 years ago

My sample code has errors. I have corrected these in a way that works but is probably not the optimal way to code this.

My code that now extracts the OUI and EI correctly from the RTC :

// the RTC has a 64bit (8 Byte) MAC address stored in EEPROM - from 0xf0 to 0xf7 void readMACfromRTC() {

byte sizeOfMac = 6; byte MCP79402MAC[sizeOfMac];

byte sizeOfMCP79402MAC = 8; // 64 bit mac, we need to extract a 48 bit one byte sizeOfOUI = 3 ; byte offsetEI = 5;

SerialUSB.println("\nREADING MAC from RTC EEPROM"); lcd.setCursor(0, 7); lcd.print("MAC ");

for (int i = 0; i < sizeOfOUI; i++) { // get 1st 3 bytes for OUI MCP79402MAC[i] = readByte(0x57, 0xf0 + i); SerialUSB.print(MCP79402MAC[i] < 0x10 ? "0" : ""); SerialUSB.print(MCP79402MAC[i], HEX); if (i < 3) { SerialUSB.print(":"); } }

for (int i = offsetEI; i < sizeOfOUI + offsetEI; i++) { // get last 3 bytes for EI MCP79402MAC[i] = readByte(0x57, 0xf0 + i); SerialUSB.print(MCP79402MAC[i] < 0x10 ? "0" : ""); SerialUSB.print(MCP79402MAC[i], HEX); if (i < 7) { SerialUSB.print(":"); } } SerialUSB.println(); }

// the RTC has a MAC address stored in EEPROM uint8_t readByte(uint8_t i2cAddr, uint8_t dataAddr) { Wire.beginTransmission(i2cAddr); Wire.write(dataAddr); Wire.endTransmission(false); // don't send stop Wire.requestFrom(i2cAddr, 1); return Wire.read(); }

Shane van Jaarsveldt Tel: +27 11 469 4750 Cel: +27 82 601 0499 Fax: +27 11 469 3370

On 20 Oct 2018, at 03:07, tomtobback notifications@github.com wrote:

Closed #2 https://github.com/Industruino/democode/issues/2.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/Industruino/democode/issues/2#event-1915982546, or mute the thread https://github.com/notifications/unsubscribe-auth/AKhBu196DsEuItO-gfyEbm5O10jiYm6oks5umnc-gaJpZM4Xstis.

shanevanj commented 6 years ago

Poor debugging on my part - this seems to work better - perhaps someone with more C skills can make this a bit more elegant ?

// the RTC has a 64bit (8 Byte) MAC address stored in EEPROM - from 0xf0 to 0xf7 void readMACfromRTC() {

byte sizeOfRtcMac = 8; // 64 bit (8 Byte) Mac byte MCP79402MAC[sizeOfRtcMac];

byte sizeOfMac = 6; // 48 bit (6 byte) mac, byte macAddr[sizeOfMac];

byte sizeOfOUI = 3; byte startOfEI = 5; // to create 48 bit (6byte) Mac byte sizeOfEI = 3;

for (int i = 0; i < sizeOfRtcMac; i++) { MCP79402MAC[i] = readByte(0x57, 0xf0 + i); }

memcpy(macAddr, MCP79402MAC, sizeOfOUI); // copy 3 bytes of OUI into mac byte array memcpy(macAddr + sizeOfOUI++, MCP79402MAC + startOfEI, sizeOfEI); //copy last 3 bytes to form EI

SerialUSB.print("\nMAC:"); for (int i = 0; i < sizeOfMac ; i++) { SerialUSB.print(macAddr[i] < 0x10 ? "0" : ""); SerialUSB.print(macAddr[i], HEX); } }

Shane van Jaarsveldt Tel: +27 11 469 4750 Cel: +27 82 601 0499 Fax: +27 11 469 3370

On 21 Oct 2018, at 21:26, Shane van Jaarsveldt shane@vanjaarsveldt.co.za wrote:

My sample code has errors. I have corrected these in a way that works but is probably not the optimal way to code this.

My code that now extracts the OUI and EI correctly from the RTC :

// the RTC has a 64bit (8 Byte) MAC address stored in EEPROM - from 0xf0 to 0xf7 void readMACfromRTC() {

byte sizeOfMac = 6; byte MCP79402MAC[sizeOfMac];

byte sizeOfMCP79402MAC = 8; // 64 bit mac, we need to extract a 48 bit one byte sizeOfOUI = 3 ; byte offsetEI = 5;

SerialUSB.println("\nREADING MAC from RTC EEPROM"); lcd.setCursor(0, 7); lcd.print("MAC ");

for (int i = 0; i < sizeOfOUI; i++) { // get 1st 3 bytes for OUI MCP79402MAC[i] = readByte(0x57, 0xf0 + i); SerialUSB.print(MCP79402MAC[i] < 0x10 ? "0" : ""); SerialUSB.print(MCP79402MAC[i], HEX); if (i < 3) { SerialUSB.print(":"); } }

for (int i = offsetEI; i < sizeOfOUI + offsetEI; i++) { // get last 3 bytes for EI MCP79402MAC[i] = readByte(0x57, 0xf0 + i); SerialUSB.print(MCP79402MAC[i] < 0x10 ? "0" : ""); SerialUSB.print(MCP79402MAC[i], HEX); if (i < 7) { SerialUSB.print(":"); } } SerialUSB.println(); }

// the RTC has a MAC address stored in EEPROM uint8_t readByte(uint8_t i2cAddr, uint8_t dataAddr) { Wire.beginTransmission(i2cAddr); Wire.write(dataAddr); Wire.endTransmission(false); // don't send stop Wire.requestFrom(i2cAddr, 1); return Wire.read(); }

Shane van Jaarsveldt Tel: +27 11 469 4750 Cel: +27 82 601 0499 Fax: +27 11 469 3370

On 20 Oct 2018, at 03:07, tomtobback <notifications@github.com mailto:notifications@github.com> wrote:

Closed #2 https://github.com/Industruino/democode/issues/2.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/Industruino/democode/issues/2#event-1915982546, or mute the thread https://github.com/notifications/unsubscribe-auth/AKhBu196DsEuItO-gfyEbm5O10jiYm6oks5umnc-gaJpZM4Xstis.