Only Socket 0 works

Below is the source code I use to send and receive ARP requests.
If I change the g_arpSocket constructor parameter to 1, the code stops working. Why does it only work on socket 0?

I was trying to send ARP packets (on socket 0) after I've called Ethernet.begin(mac) , but that also failed, so I thought that by switching to a different socket I should be able to do it. Any advice?

Thanks!

#include <SPI.h> // needed for Ethernet library communication with the W5100 (Arduino ver>0018)
#include <Ethernet.h>
#include <utility/w5100.h>

SOCKET g_arpSocket(0); // our socket that will be opened in RAW mode
byte rbuf[44]; // send buffer
int rbuflen; // length of data to receive
int sbuflen; // length of data to send

byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

byte IP[] = {
0xAA, 0xBB, 0xCC, 0xDD };

/*
Ethernet II, Src: de:ad:be:ef:fe:ed (de:ad:be:ef:fe:ed), Dst: Broadcast (ff:ff:ff:ff:ff:ff)
Destination: Broadcast (ff:ff:ff:ff:ff:ff)
Source: de:ad:be:ef:fe:ed (de:ad:be:ef:fe:ed)
Type: ARP (0x806)
Padding: 00000.....

Address Resolution Protocol (request)
Hardware type: Ethernet (1)
Protocol type: IP (0x800)
Hardware size: 6
Protocol size: 4
Opcode: request(1)
Sender MAC address: de:ad:be:ef:fe:ed (de:ad:be:ef:fe:ed)
Sender IP address: 223.174.19.240 (223.174.19.240)
Target MAC address: 00:00:00_00:00:00 (00:00:00:00:00:00)
Target IP address: 169:254:12:151 (169:254:12:151)

*/

byte arp_header[] = {
0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01};

byte arp_request[60] = {
0xff,0xff,0xff,0xff,0xff,0xff, //Dst: broadcast
0,0,0,0,0,0, //Src
0x08, 0x06, // ARP,
0x00, 0x01, // Ethernet,
0x08, 0x00, // IP
0x06, // HW size
0x04, // Protocol size,
0x00, 0x01, // Opcode: request
0,0,0,0,0,0, //Src MAC
0,0,0,0, //Src IP
0xff,0xff,0xff,0xff,0xff,0xff, //Dst MAC
0,0,0,0 //Dst IP
};

IPAddress IP_to_resolve(192, 168, 1, 98);

int started = 0;

void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}

Serial.println("start");

// initialize the w5100 chip and open a RAW socket
W5100.init();

W5100.writeSnMR(g_arpSocket, SnMR::MACRAW);
W5100.execCmdSn(g_arpSocket, Sock_OPEN);

// Ethernet.begin(mac);
Serial.print("server is at ");
Serial.println(g_arpSocket);

memcpy (arp_request + 6, mac, sizeof mac);
memcpy (arp_request + 0x16, mac, sizeof mac);
memcpy (arp_request + 0x1C, IP, sizeof IP);

// Serial.println(Ethernet.localIP());
started = 1;
}

byte * getMacAddress(const IPAddress& address_to_resolve) {
memcpy (arp_request + 0x26, IP_to_resolve.raw_address(), sizeof IP_to_resolve);

// sending buffer
W5100.send_data_processing(g_arpSocket, arp_request, 42);
W5100.execCmdSn(g_arpSocket, Sock_SEND_MAC);

// let us try 13 packets
for (int i=0; i < 13; i++) {
// check if we have received something
// rbuflen = W5100.getRXReceivedSize(g_arpSocket);
// if (rbuflen < 42) {
// continue;
// }

//Serial.println("Received something");
//Serial.println(rbuflen);

W5100.recv_data_processing(g_arpSocket, rbuf, 44);
W5100.execCmdSn(g_arpSocket, Sock_RECV);
/*
for (int i = 0; i < 44; i ++) {
Serial.print((int)rbuf*, HEX);*

  • Serial.print(" ");*
  • }*
  • Serial.println(" ");*
    _ */_
  • if (0 == memcmp(rbuf+2, mac, sizeof mac) && // is it sent to our MAC?*
  • 0 == memcmp(rbuf+2+12, arp_request+12, 9) && // 9 is the ARP header size*
  • 2 == rbuf[2+12+9]) // 2 = response*
  • {*
  • // Serial.println("MAC add");*
  • return rbuf + 2 + 0x16;*
  • }*
  • }*
  • return NULL;*
    }
    void loop() {
  • if (!started)*
  • {*
  • delay (1000);*
  • return;*
  • }*
    byte * resolved = getMacAddress(IP_to_resolve);
  • if (resolved) {*
  • for (int i=0; i<6; i++) {*
    _ Serial.print((int)resolved*, HEX);_
    _
    Serial.print(" ");_
    _
    } _
    _
    Serial.println(""); _
    _
    }_
    _
    else {_
    _
    Serial.println("FAILED to resolve ..."); _
    _
    }_
    _
    started = 0;_
    _
    }*_

Next time please use code tags to post your code, otherwise the forum system manipulates the code.

Why does it only work on socket 0?

Quote from the WizNet5100 datasheet, section 5.2.4:

MAC Raw mode(only supported in socket 0) can be utilized.

I was trying to send ARP packets (on socket 0) after I've called Ethernet.begin(mac) , but that also failed

In my opinion the data you send or get with a MAC_RAW socket is starting at byte 20 of an Ethernet frame (Ethernet frame - Wikipedia), where the two length bytes are located. According to the datasheet the data starts with the "header" which is 2 bytes of length information, followed by the payload. So my guess is, the rest of the frame cannot be specified directly.

First of all, thanks to all for your help. I can't believe how responsive you guys are!

Re: frame layout - this code works fine on socket 0. I have checked with WireShark and apart from the frame being padded to length of 60 (useful content is 42), its structure is as expected, both on send and on receive. The receive buffer contains two extra bytes of length in front.

Thanks a lot for all who helped!

Here's what I am trying to do:

  1. Get my IP address(DHCP)
  2. Send some ARP requests
  3. Start a web server

Step 2 would need to use socket 0 (thanks pylon!). So I guess my options are to either make 1 and 3 use a different socket or to switch socket 0 to MAC_RAW for step 2 and then back to some other mode for step 3.
As I have mentioned, if I call

W5100.writeSnMR(g_arpSocket, SnMR::MACRAW);
W5100.execCmdSn(g_arpSocket, Sock_OPEN);

after Ethernet.begin(), my ARP code stops working. Do you have any pointers for solving this?

As I have mentioned, if I call

W5100.writeSnMR(g_arpSocket, SnMR::MACRAW);
W5100.execCmdSn(g_arpSocket, Sock_OPEN);

after Ethernet.begin(), my ARP code stops working. Do you have any pointers for solving this?

In addition to your w5100.init() the call to Ethernet.begin() sets the source MAC address and source IP address. Maybe this changes the behavior of the MAC_RAW mode. I haven't found any specifics in the datasheet.
What does "stops working" mean? What do you see in WireShark?
I would try to insert code that checks if the register SnSR has the value SNSR::MACRAW and if not, close the socket and start again with writing SnMR.