EmbeddedRelated.com
Forums

Speed of udp_sendto?

Started by terrywnixon December 23, 2010
Hi Guys

I wonder if you can point me the right direction. I am trying to implement a udp protocol which sends about 100MB of data from a PC to the rabbit which spits byte data out of the Aux I/O port to RAM. I send this data as 1024 byte data packets. So that I dont overflow the RX 4K buffer I send 4 packets from the PC and then wait for an Acknowledge byte sent from the Rabbit. It all works except that it takes roughly 6mS to get acknowledge byte out of the rabbit. I have verified this with a logic analyzer and Wireshark which is a packet sniffer. If I measure the time on the analyzer for the udpsento line it is only 208uS so the time must be in the actual function within udp.lib. The program snippet below is based upon one of the upd samples. Any idea how I can speed up the Acknowledge byte?
int ReceivePacket(void) // receive one packet (heartbeat)
{
static int buff[1024];

if (-1 == udp_recv(&sock, buff, sizeof(buff))) // receive the packet
{
return 0; // no packet read. return
}
BitWrPortI(PEFR,&PEFRShadow,1,3); // This is overwritten by //tcp_tick so needs reassurting.
// instead
WrPortI(SPCR,&SPCRShadow,0x9C); // Over written by tcp_tick
TestPulseOn; // Logic Analyzer trigger
OutputArray(buff,NumWords); // Send the packet out Aux I/O bus
TestPulseOff;
return 1;
}
/*****************************************************************************

SYNTAX: void OutputArray(void)
DESCRIPTION: Send Acknoledge Byte (0x7f)
RETURN VALUE: None

Send an acknowlede single byte (0x7f) to remote port 4321 at IP address
192,168,0,127

***************************************************************/
void SendACK(void)
{

udp_sendto(&sock, PackRet, 1,REMOTE_IP,REMOTE_PORT);
}
/****************************************************************************/

void main()
{

int PacketCount;
PacketCount = 0;
/**************** Initialize the Aux I/O Bus *********************/

WrPortI(IB3CR,&IB3CRShadow,0xAC);
WrPortI(PEALR, &PEALRShadow,(PEALRShadow & 0x3F));
BitWrPortI(PEFR,&PEFRShadow,1,3); // Make PE3 a strobe
WrPortI(SPCR,&SPCRShadow,0x9C);
/******************************************************************/

WrPortI (PEDDR, &PEDDRShadow, 0xff); // set E as an output

brdInit();

// Start network and wait for interface to come up (or error exit).
sock_init_or_exit(1);

if(!udp_open(&sock, LOCAL_PORT, REMOTE_IP, 0, NULL)) {
printf("udp_open failed!\n");
exit(0);
}

/* receive heartbeats */
for(;;) {
tcp_tick(NULL);
PacketCount += ReceivePacket(); // Recive packet & increment

if (PacketCount == 4)// Send an Acknowledgement every 4 packets
{
PacketCount = 0;
SendACK();

}

Hi Everyone,

I am trying to develop a TCP/IP packet sniffer using Dynamic C and the
Rabbit RCM3200 processor board module. Does anyone have an example of
Dynamic C code that will show me how to do this? I read in other articles
that the Rabbit processor is not powerful enough to do this. I mentioned
this to my manager and he said that it would be put on a subnet with limited
traffic. Any help in doing this would be greatly appreciated.

Thanks,

Roger Myers
Programmer/Analyst
ComTech Communications Inc.
120 Main Ave. Suite G.
Sacramento CA 95838
(916) 568-7800 x130
r...@comtechcom.net

On 12/23/2010 4:00 PM, Roger Myers wrote:
> Hi Everyone,
>
> I am trying to develop a TCP/IP packet sniffer using Dynamic C and the
> Rabbit RCM3200 processor board module. Does anyone have an example of
> Dynamic C code that will show me how to do this? I read in other articles
> that the Rabbit processor is not powerful enough to do this. I mentioned
> this to my manager and he said that it would be put on a subnet with limited
> traffic. Any help in doing this would be greatly appreciated.
>
> Thanks,

IIRC you would need to call the pkt_recv() funcion after setting up the
link to get packets.

How are you going to route packets to the rabbit? You will need a
managed switch with mirroring capability or find a old hub (non-switch)
to use. Otherwise, all it will see are broadcast packets.

Seems like an exercise in futility though, if you capture anything over
a few packets, the rabbit won;t be able to do much with them.

--
------
Scott G. Henion, Consultant
Web site: http://SHDesigns.org
Rabbit libs: http://shdesigns.org/rabbit/
------

Hi Scott,

Thank you for the quick response. The idea is to sniff the network and when
one or more packets are seen going to a specific IP address (in this case it
is the printer IP address) to signal an alert to other devices.

Best regards,

Roger Myers

Programmer/Analyst

ComTech Communications Inc.

120 Main Ave. Suite G.

Sacramento CA 95838

(916) 568-7800 x130

r...@comtechcom.net

_____

From: r... [mailto:r...] On
Behalf Of Scott Henion
Sent: Thursday, December 23, 2010 1:39 PM
To: r...
Subject: Re: [rabbit-semi] Speed of udp_sendto?

On 12/23/2010 4:00 PM, Roger Myers wrote:
> Hi Everyone,
>
> I am trying to develop a TCP/IP packet sniffer using Dynamic C and the
> Rabbit RCM3200 processor board module. Does anyone have an example of
> Dynamic C code that will show me how to do this? I read in other articles
> that the Rabbit processor is not powerful enough to do this. I mentioned
> this to my manager and he said that it would be put on a subnet with
limited
> traffic. Any help in doing this would be greatly appreciated.
>
> Thanks,

IIRC you would need to call the pkt_recv() funcion after setting up the
link to get packets.

How are you going to route packets to the rabbit? You will need a
managed switch with mirroring capability or find a old hub (non-switch)
to use. Otherwise, all it will see are broadcast packets.

Seems like an exercise in futility though, if you capture anything over
a few packets, the rabbit won;t be able to do much with them.

--
------
Scott G. Henion, Consultant
Web site: http://SHDesigns.org
Rabbit libs: http://shdesigns.org/rabbit/
------
Hi Roger,

Unless it is a broadcast message or you are using a hub or a managed switch,
there is no other way for this to work. If you are on a standard switch you
will only see the packets that are addressed to the Rabbit.

If this is being designed to work on many different networks you are likely
to find it won't work.

Just try running Wireshark on your PC and you want see any of the TCP/IP
traffic from any other devices even if you put it in promiscuous mode.

Dave...
---
Very funny Scotty, now beam down my clothes!!!
---

From: r... [mailto:r...] On
Behalf Of Roger Myers
Sent: 24 December 2010 05:18
To: r...
Subject: RE: [rabbit-semi] Speed of udp_sendto?

Hi Scott,

Thank you for the quick response. The idea is to sniff the network and when
one or more packets are seen going to a specific IP address (in this case it
is the printer IP address) to signal an alert to other devices.

Best regards,

Roger Myers
e Date: 12/22/10
Guys

Back to the original topic. A bit more information. I am using a RCM 4300 and DC 10.64. Any ideas will be much appreciated

Regards

--- In r..., "terrywnixon" wrote:
>
> Hi Guys
>
> I wonder if you can point me the right direction. I am trying to implement a udp protocol which sends about 100MB of data from a PC to the rabbit which spits byte data out of the Aux I/O port to RAM. I send this data as 1024 byte data packets. So that I dont overflow the RX 4K buffer I send 4 packets from the PC and then wait for an Acknowledge byte sent from the Rabbit. It all works except that it takes roughly 6mS to get acknowledge byte out of the rabbit. I have verified this with a logic analyzer and Wireshark which is a packet sniffer. If I measure the time on the analyzer for the udpsento line it is only 208uS so the time must be in the actual function within udp.lib. The program snippet below is based upon one of the upd samples. Any idea how I can speed up the Acknowledge byte?
> int ReceivePacket(void) // receive one packet (heartbeat)
> {
> static int buff[1024];
>
> if (-1 == udp_recv(&sock, buff, sizeof(buff))) // receive the packet
> {
> return 0; // no packet read. return
> }
> BitWrPortI(PEFR,&PEFRShadow,1,3); // This is overwritten by //tcp_tick so needs reassurting.
> // instead
> WrPortI(SPCR,&SPCRShadow,0x9C); // Over written by tcp_tick
> TestPulseOn; // Logic Analyzer trigger
> OutputArray(buff,NumWords); // Send the packet out Aux I/O bus
> TestPulseOff;
> return 1;
> }
> /*****************************************************************************
>
> SYNTAX: void OutputArray(void)
> DESCRIPTION: Send Acknoledge Byte (0x7f)
> RETURN VALUE: None
>
> Send an acknowlede single byte (0x7f) to remote port 4321 at IP address
> 192,168,0,127
>
> ***************************************************************/
> void SendACK(void)
> {
>
> udp_sendto(&sock, PackRet, 1,REMOTE_IP,REMOTE_PORT);
> }
> /****************************************************************************/
>
> void main()
> {
>
> int PacketCount;
> PacketCount = 0;
> /**************** Initialize the Aux I/O Bus *********************/
>
> WrPortI(IB3CR,&IB3CRShadow,0xAC);
> WrPortI(PEALR, &PEALRShadow,(PEALRShadow & 0x3F));
> BitWrPortI(PEFR,&PEFRShadow,1,3); // Make PE3 a strobe
> WrPortI(SPCR,&SPCRShadow,0x9C);
> /******************************************************************/
>
> WrPortI (PEDDR, &PEDDRShadow, 0xff); // set E as an output
>
> brdInit();
>
> // Start network and wait for interface to come up (or error exit).
> sock_init_or_exit(1);
>
> if(!udp_open(&sock, LOCAL_PORT, REMOTE_IP, 0, NULL)) {
> printf("udp_open failed!\n");
> exit(0);
> }
>
> /* receive heartbeats */
> for(;;) {
> tcp_tick(NULL);
> PacketCount += ReceivePacket(); // Recive packet & increment
>
> if (PacketCount == 4)// Send an Acknowledgement every 4 packets
> {
> PacketCount = 0;
> SendACK();
>
> }
>

Terry,

I'm not sure how to decrease the 6ms time it takes to receive the ACK, but you might want to consider a protocol with block numbers in each UDP packet, and the Rabbit can send an ACK with a block number to indicate it's received everything up to a certain block, or a NAK with a block number to request missing blocks.

The sending end could just keep streaming bytes, perhaps at a predetermined "optimal" rate; backing off when lots of NAKs are coming in or trying to go faster when things seem to be going well.

You'll end up with an asynchronous protocol that won't be affected as much by the latency of the link.

-Tom
On Dec 23, 2010, at 10:34 AM, terrywnixon wrote:
> Hi Guys
>
> I wonder if you can point me the right direction. I am trying to implement a udp protocol which sends about 100MB of data from a PC to the rabbit which spits byte data out of the Aux I/O port to RAM. I send this data as 1024 byte data packets. So that I dont overflow the RX 4K buffer I send 4 packets from the PC and then wait for an Acknowledge byte sent from the Rabbit. It all works except that it takes roughly 6mS to get acknowledge byte out of the rabbit. I have verified this with a logic analyzer and Wireshark which is a packet sniffer. If I measure the time on the analyzer for the udpsento line it is only 208uS so the time must be in the actual function within udp.lib. The program snippet below is based upon one of the upd samples. Any idea how I can speed up the Acknowledge byte?
>
> int ReceivePacket(void) // receive one packet (heartbeat)
> {
> static int buff[1024];
>
> if (-1 == udp_recv(&sock, buff, sizeof(buff))) // receive the packet
> {
> return 0; // no packet read. return
> }
> BitWrPortI(PEFR,&PEFRShadow,1,3); // This is overwritten by //tcp_tick so needs reassurting.
> // instead
> WrPortI(SPCR,&SPCRShadow,0x9C); // Over written by tcp_tick
> TestPulseOn; // Logic Analyzer trigger
> OutputArray(buff,NumWords); // Send the packet out Aux I/O bus
> TestPulseOff;
> return 1;
> }
> /*****************************************************************************
>
> SYNTAX: void OutputArray(void)
> DESCRIPTION: Send Acknoledge Byte (0x7f)
> RETURN VALUE: None
>
> Send an acknowlede single byte (0x7f) to remote port 4321 at IP address
> 192,168,0,127
>
> ***************************************************************/
> void SendACK(void)
> {
>
> udp_sendto(&sock, PackRet, 1,REMOTE_IP,REMOTE_PORT);
> }
> /****************************************************************************/
>
> void main()
> {
>
> int PacketCount;
> PacketCount = 0;
> /**************** Initialize the Aux I/O Bus *********************/
>
> WrPortI(IB3CR,&IB3CRShadow,0xAC);
> WrPortI(PEALR, &PEALRShadow,(PEALRShadow & 0x3F));
> BitWrPortI(PEFR,&PEFRShadow,1,3); // Make PE3 a strobe
> WrPortI(SPCR,&SPCRShadow,0x9C);
> /******************************************************************/
>
> WrPortI (PEDDR, &PEDDRShadow, 0xff); // set E as an output
>
> brdInit();
>
> // Start network and wait for interface to come up (or error exit).
> sock_init_or_exit(1);
>
> if(!udp_open(&sock, LOCAL_PORT, REMOTE_IP, 0, NULL)) {
> printf("udp_open failed!\n");
> exit(0);
> }
>
> /* receive heartbeats */
> for(;;) {
> tcp_tick(NULL);
> PacketCount += ReceivePacket(); // Recive packet & increment
>
> if (PacketCount == 4)// Send an Acknowledgement every 4 packets
> {
> PacketCount = 0;
> SendACK();
>
> }
Tom,

Thanks for the reply and the advice. I know you have a lot of experience with this sort of thing so I will probably have to accept that it really does take 6mS to get a byte out the rabbit.

Enjoy the holidays

--- In r..., Tom Collins wrote:
>
> Terry,
>
> I'm not sure how to decrease the 6ms time it takes to receive the ACK, but you might want to consider a protocol with block numbers in each UDP packet, and the Rabbit can send an ACK with a block number to indicate it's received everything up to a certain block, or a NAK with a block number to request missing blocks.
>
> The sending end could just keep streaming bytes, perhaps at a predetermined "optimal" rate; backing off when lots of NAKs are coming in or trying to go faster when things seem to be going well.
>
> You'll end up with an asynchronous protocol that won't be affected as much by the latency of the link.
>
> -Tom
> On Dec 23, 2010, at 10:34 AM, terrywnixon wrote:
> > Hi Guys
> >
> > I wonder if you can point me the right direction. I am trying to implement a udp protocol which sends about 100MB of data from a PC to the rabbit which spits byte data out of the Aux I/O port to RAM. I send this data as 1024 byte data packets. So that I dont overflow the RX 4K buffer I send 4 packets from the PC and then wait for an Acknowledge byte sent from the Rabbit. It all works except that it takes roughly 6mS to get acknowledge byte out of the rabbit. I have verified this with a logic analyzer and Wireshark which is a packet sniffer. If I measure the time on the analyzer for the udpsento line it is only 208uS so the time must be in the actual function within udp.lib. The program snippet below is based upon one of the upd samples. Any idea how I can speed up the Acknowledge byte?
> >
> > int ReceivePacket(void) // receive one packet (heartbeat)
> > {
> > static int buff[1024];
> >
> > if (-1 == udp_recv(&sock, buff, sizeof(buff))) // receive the packet
> > {
> > return 0; // no packet read. return
> > }
> > BitWrPortI(PEFR,&PEFRShadow,1,3); // This is overwritten by //tcp_tick so needs reassurting.
> > // instead
> > WrPortI(SPCR,&SPCRShadow,0x9C); // Over written by tcp_tick
> > TestPulseOn; // Logic Analyzer trigger
> > OutputArray(buff,NumWords); // Send the packet out Aux I/O bus
> > TestPulseOff;
> > return 1;
> > }
> > /*****************************************************************************
> >
> > SYNTAX: void OutputArray(void)
> > DESCRIPTION: Send Acknoledge Byte (0x7f)
> > RETURN VALUE: None
> >
> > Send an acknowlede single byte (0x7f) to remote port 4321 at IP address
> > 192,168,0,127
> >
> > ***************************************************************/
> > void SendACK(void)
> > {
> >
> > udp_sendto(&sock, PackRet, 1,REMOTE_IP,REMOTE_PORT);
> > }
> > /****************************************************************************/
> >
> > void main()
> > {
> >
> > int PacketCount;
> > PacketCount = 0;
> > /**************** Initialize the Aux I/O Bus *********************/
> >
> > WrPortI(IB3CR,&IB3CRShadow,0xAC);
> > WrPortI(PEALR, &PEALRShadow,(PEALRShadow & 0x3F));
> > BitWrPortI(PEFR,&PEFRShadow,1,3); // Make PE3 a strobe
> > WrPortI(SPCR,&SPCRShadow,0x9C);
> > /******************************************************************/
> >
> > WrPortI (PEDDR, &PEDDRShadow, 0xff); // set E as an output
> >
> > brdInit();
> >
> > // Start network and wait for interface to come up (or error exit).
> > sock_init_or_exit(1);
> >
> > if(!udp_open(&sock, LOCAL_PORT, REMOTE_IP, 0, NULL)) {
> > printf("udp_open failed!\n");
> > exit(0);
> > }
> >
> > /* receive heartbeats */
> > for(;;) {
> > tcp_tick(NULL);
> > PacketCount += ReceivePacket(); // Recive packet & increment
> >
> > if (PacketCount == 4)// Send an Acknowledgement every 4 packets
> > {
> > PacketCount = 0;
> > SendACK();
> >
> > }
> >
>

Terry,

I wouldn't say for certain that you can't speed up the ACK. I don't have access to my work files over the holiday, so I can't really dig into udp_sendto() to see what it's doing.

The first ACK could be slow if the target's MAC address isn't in the ARP cache. I know you can bypass ARP when you send -- I think there's code in ADDP.LIB that sends UDP responses using the MAC address from a UDP request that you could use for guidance.

You may have to instrument the code path in udp_sendto() in order to determine which aspect(s) take the majority of that 6ms, including measuring how much of it is used before you even get to the udp_sendto().

-Tom
On Dec 24, 2010, at 11:50 AM, terrywnixon wrote:
> Thanks for the reply and the advice. I know you have a lot of experience with this sort of thing so I will probably have to accept that it really does take 6mS to get a byte out the rabbit.
Tom,

Thanks for the advice. I know it must be possible to send that ACK byte quicker because I tried an experiment using basically the same code which sends an ACK after each received packet (1024bytes). I can get a new packet every 2.7mS doing this. This means 1MByte takes 2.82sec. Using an ACK byte every 4 received packets gives me a 1MB time of 2.18sec so if I could get the ACK byte out in 3mS rather than 6mS I could shave off 750mS from the 1MB time

--- In r..., Tom Collins wrote:
>
> Terry,
>
> I wouldn't say for certain that you can't speed up the ACK. I don't have access to my work files over the holiday, so I can't really dig into udp_sendto() to see what it's doing.
>
> The first ACK could be slow if the target's MAC address isn't in the ARP cache. I know you can bypass ARP when you send -- I think there's code in ADDP.LIB that sends UDP responses using the MAC address from a UDP request that you could use for guidance.
>
> You may have to instrument the code path in udp_sendto() in order to determine which aspect(s) take the majority of that 6ms, including measuring how much of it is used before you even get to the udp_sendto().
>
> -Tom
> On Dec 24, 2010, at 11:50 AM, terrywnixon wrote:
> > Thanks for the reply and the advice. I know you have a lot of experience with this sort of thing so I will probably have to accept that it really does take 6mS to get a byte out the rabbit.
>