|
View:
New views
3 Messages
—
Rating Filter:
Alert me
|
|
|
NutUdpSendTo taking too longHello all.
We have found one weird behaviour of NutUdpSendTo. Basically the problem is the following. If we put our Ethernut3 (with NutOS 4.6.4) to send UDP packets in a network that does NOT have a computer with the IP that the UDP packets are sent to, after some time (about 15 minutes) the Ethernut gets into a state where every single execution of NutUdpSendTo takes about 500ms. We can also see that in this state the microcontroller spends most of the time idling, which suggests that there is a wait process somewhere. To my poor understanding, sending a UDP packet is something like simply dropping the packet into the network, not waiting for anything. After this, if a computer with the target IP "appears" (in linux I configure an ip alias), the situation comes back normal immediately, where it takes usually in the order of milliseconds to execute NutUdpSendTo. This situation seems to be reproducible. A simple while loop sending UPD packets and a bit of patience makes the issue to show up. We measure time by setting pins up and down and with an oscilloscope/logic analyser. The basic code that we use is the following ----------------------- #define MY_MAC "\x00\x06\x98\x30\x00\x35" #define MY_IPADDR "192.168.0.100" #define MY_IPMASK "255.255.255.0" int main(void) { u_long ip_addr = inet_addr(MY_IPADDR); u_long ip_mask = inet_addr(MY_IPMASK); u_char mac[] = MY_MAC; UDPSOCKET *sock=NULL; char buf; DEBUGPINS_INIT; /* Initialize the serial port */ NutRegisterDevice(&DEV_UART0, 0, 0); freopen("uart0", "r+", stdout); _ioctl(_fileno(stdout), UART_SETSPEED, &baud); printf("\n\nNut/OS %s\n", NutVersionString()); /* Register the tracer and start the terminal */ btn_terminal_init(stdout, "[udp]$"); btn_terminal_register_cmd("trace",NutTraceTerminal); btn_terminal_run(BTN_TERMINAL_FORK, 0); /* Register Ethernet controller */ NutRegisterDevice(&DEV_ETHER, 0, 0); NutNetIfConfig("eth0", mac, ip_addr, ip_mask); sock = NutUdpCreateSocket(LOCAL_PORT); if (sock==0) { DEBUGPINS_SETHIGH(2); //Set the debug pin 2 up } ip_addr=inet_addr(REMOTE_IP); while (1) { DEBUGPINS_SETHIGH(0); //Set the debug pin 0 up if (NutUdpSendTo(sock, ip_addr, REMOTE_PORT, &buf, 1) == -1) { DEBUGPINS_SETHIGH(3); NutSleep(200); DEBUGPINS_SETLOW(3); } DEBUGPINS_SETLOW(0); //Set the debug pin 0 low buf++; } } ----------------------- where the DEBUGPINS_SETHIGH(X) is a macro to put the Xth pin of our debug connector to 1, and similar with the rest of macros. The pin 1 is used to indicate when the micro is in the idle thread, and thus cannot be seen in the code here, as it is in the NutOS sources. As you can see we are able to use the tracer also in Ethernut3 (thanks to the modifications of Ernst Stippl) through the btn-terminal for easily getting the traces. If required we can provide sample traces and pictures of the measurements with the scope. We can also provide all the files required to run this code. Regards José _______________________________________________ http://lists.egnite.de/mailman/listinfo/en-nut-discussion |
|
|
Re: NutUdpSendTo taking too longHey José,
When you send a IP packet over ethernet you have to know the MAC address of the recipient. To find this out the ARP (Address Resolution Protocol) cache is examined. If no entry for the destination IP address is in the ARP cache then an ARP request must be sent over the local ethernet and then you have to wait for an ARP reply. If no one is there with that IP address then you just wait until you finally give up. In NutOS the sending thread is blocked until the IP packet is either sent or something goes wrong (in this case no ARP reply). Nathan _______________________________________________ http://lists.egnite.de/mailman/listinfo/en-nut-discussion |
|
|
Re: NutUdpSendTo taking too longHello Nathan, and thanks for the explanation. It was a shortcut to the
code that explains it. My friend was called "arpcache.c" I have still some questions. Nathan Moore escribió: > Hey José, > When you send a IP packet over ethernet you have to know the MAC > address of the recipient. To find this out the ARP (Address Resolution > Protocol) cache is examined. If no entry for the destination IP address > is in the ARP cache then an ARP request must be sent over the > local ethernet and then you have to wait for an ARP reply. If no one > is there with that IP address then you just wait until you finally give up. > In NutOS the sending thread is blocked until the IP packet is either sent > or something goes wrong (in this case no ARP reply). And in that case the no ARP reply is not considered an error, so NutUdpSenTo will peacefully return 0. So it seems to me that for an application there is no straight way to detect when an ARP entry has been deteled. Perhaps calling directly ArpCacheLookup, or even NutArpCacheQuery? Anything against this that I should be aware of? Another way to solve this issue, I guess, could be to mark the ARP entry as permanent, so it will not be flushed. Is this correct? It seems that it would require to manipulate the ARP entry manually, as I couldn't find any function to add/manipulate entries. Anything against this that I should be aware of? In my case it is assumed that the IP of the machine that the Ethernut sends the UDP packets to has always the same private IP Regards! José _______________________________________________ http://lists.egnite.de/mailman/listinfo/en-nut-discussion |
| Free embeddable forum powered by Nabble | Forum Help |