Advertise W5500-EVB-Pico as network gateway using ARP (GARP?)

Hi there, I’m using the W5500-EVB-Pico board with Arduino IDE to do some testing and I just want to send a packet with the packet structure that is in the code that I’m posting below, however, it seems W5500 libraries are handling ARP, and thus I can’t send custom raw packets.

Is there something I’m doing wrong? In wireshark the operation code always shows (1) so it’s not announcing itself.

#include <Ethernet.h>

byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };  // MAC address of the Ethernet shield
IPAddress ipAddress(192, 168, 1, 1);  // IP address of the Ethernet shield
IPAddress destIpAddress(255, 255, 255, 255);  // Destination IP address

EthernetUDP udpClient;

void setup() {
    while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Ethernet.init(17);
  Ethernet.begin(mac, ipAddress);
  Serial.begin(9600);
  delay(1000);
  udpClient.begin(0);  // Open a random local port
  sendArpRequest(destIpAddress);
  //udpClient.begin(0);  // Open a random local port

  //sendArpRequest(destIpAddress);

}
void sendArpRequest(const IPAddress& targetIp) {
  // Create the ARP request packet
  uint8_t arpRequestPacket[] = {
    0x08, 0x06,
    0x00, 0x01,   // Hardware type: Ethernet (1)
    0x08, 0x00,   // Protocol type: IPv4 (0x0800)
    0x06,         // Hardware address length: 6
    0x04,         // Protocol address length: 4
    0x00, 0x02,   // ARP operation: Request (2)
    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],   // Sender MAC address
    ipAddress[0], ipAddress[1], ipAddress[2], ipAddress[3],   // Sender IP address
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // Target MAC address (zeroed out)
    targetIp[0], targetIp[1], targetIp[2], targetIp[3]  // Target IP address
  };

  // Send the ARP request packet
  udpClient.beginPacket(targetIp, 0);
  udpClient.write(arpRequestPacket, sizeof(arpRequestPacket));
  udpClient.endPacket();
}

ARP/GARP is datalink layer, to get its functionality you must switch socket 0 into MACRAW mode. You seem to use UDP mode.

1 Like

Right! Thank you for the reply, I’m using the default UDP mode, I guess I’ll have to rewrite this whole code and start opening sockets directly using Sn_MR, right? Or would I be able to set the socket like so below, and still use the code I already have?

uint8_t socketNum = 0;
uint8_t socketMode = 0b00001000; // P3 = 0, P2 = 1, P1 = 0, P0 = 0 (MACRAW mode)

// Write the socket mode to Sn_MR register
uint16_t regValue = socketMode << 8;
regValue |= Sn_MR(socketNum);
Write(Sn_MR(socketNum), regValue);

Look into the libraries you use, hopefully there’re calls for MACRAW mode, or universal calls (eg. data I/O) which can be reused for MACRAW mode.

Is Sn_MR 8-bit?

I’ll have to look deeper into the libraries then, thank you, I can’t test with the board until tomorrow, so I’ll revert back here then, in the meantime, here’s the Sn_MR register in the datasheet, it’s 8-bit, no?

Yes, then it is not clear for me how you can

write 16-bit value into 8-bit register unless there’s some hidden logic in this function :slight_smile:

1 Like

Heh, great catch, still a lot for me to learn, thank you, absolute mistake by me!
I’ll update on progress in around 14 hours! :slight_smile:

1 Like

So I managed to make progress, however I’m not managing to get packets sent out, it seems to always fail. I basically always get “failed to send”. Using the RP2040 Ethernet/ Ethernet2 library, it seems like I am setting the correct modes and registers through this code, I’d definitely appreciate some more guidance if possible :pray:

#include <SPI.h>
#include <Ethernet2.h>
#include <utility\socket.h>
#include <string.h>


// Initialize the Ethernet library
byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };  // MAC address of the Ethernet shield
IPAddress destIpAddress(255,255,255,255);
IPAddress ipAddress(192, 168, 51, 1);  // IP address of the Ethernet shield
uint8_t ipAddr[4] = {255, 255, 255, 255};

void setup() {
      while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  // Initialize the SPI bus
  SPI.begin();
    // Initialize the Ethernet library and the W5500 module
  Ethernet.init(17);// init 17
      Serial.begin(9600);
  delay(1000);

  
  Ethernet.begin(mac);


    Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());


}
void sendArpRequest(const IPAddress& targetIp) {
  // Create the ARP request packet
  uint8_t arpRequestPacket[] = {
    0x08, 0x06,
    0x00, 0x01,   // Hardware type: Ethernet (1)
    0x08, 0x00,   // Protocol type: IPv4 (0x0800)
    0x06,         // Hardware address length: 6
    0x04,         // Protocol address length: 4
    0x00, 0x02,   // ARP operation: Request (2)
    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],   // Sender MAC address
    ipAddress[0], ipAddress[1], ipAddress[2], ipAddress[3],   // Sender IP address
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // Target MAC address (zeroed out)
    targetIp[0], targetIp[1], targetIp[2], targetIp[3]  // Target IP address
  };
  int packetSize = sizeof(arpRequestPacket);


  SOCKET macrawSocket = socket(0,SnMR::MACRAW, 0, 0);
  if (sendto(macrawSocket, arpRequestPacket, packetSize,ipAddr, 0) == 0) {
 Serial.println("failed to send");
  }

  close(macrawSocket);


}
void loop() {
  
 sendArpRequest(destIpAddress);
 delay(5000);



}



Solved this by using a different Library :+1:

1 Like