EmbeddedRelated.com
Forums
Memfault Beyond the Launch

How does rabbit know that a packet has arrived ???

Started by rohan_arg January 17, 2005

Hi Everyone,
New Year Greetings!!

When a ethernet packet is received in its entirity, on Rabbit's NIC,
how does rabbit know that a packet has arrived completely and it
needs to process it.

While investigating the same in ip.lib , realtek.lib etc. I found
that pd_recieve() is the routine which is being called in
pkt_received to know that a complete packet is received. I tried to
make the sense out of pd_receive() but looks it will take lot of time
to understand the concept.

My question is: what is the mechanism by which the packet arrival is
known to the reciever in TCP/IP. Does sender puts something like a
end flag in the packet?

Thanking in advance!

With warm Regards,

Rohan A. Gurjar


At 03:41 PM 1/17/2005 +0000, you wrote:
>Hi Everyone,
> New Year Greetings!!
>
>When a ethernet packet is received in its entirity, on Rabbit's NIC,
>how does rabbit know that a packet has arrived completely and it
>needs to process it.
>
>While investigating the same in ip.lib , realtek.lib etc. I found
>that pd_recieve() is the routine which is being called in
>pkt_received to know that a complete packet is received. I tried to
>make the sense out of pd_receive() but looks it will take lot of time
>to understand the concept.
>
>My question is: what is the mechanism by which the packet arrival is
>known to the reciever in TCP/IP. Does sender puts something like a
>end flag in the packet?

Here is the section of my code that talks to a socket. I believe I
pilfered this from an example code on how to do a telnet session in a Rabbit:

if ((EthState != esInit) && !tcp_tick(&socket)) EthState = esInit;

switch (EthState) {
case esInit: // socket is closed, start listening
tcp_listen(&socket,PORT,0,0,NULL,0);
EthState = esListening;
break;
case esListening: // we're listening, nothing connected yet
if (sock_established(&socket)) {
memset(Command,0,sizeof(Command));
EthState = esDownload;
}
break;
case esDownload: // remote is connected, handle incoming commands
memset(buffer,0,sizeof(buffer));
bytes_read=sock_fastread(&socket,buffer,sizeof(buffer)-1);
if(bytes_read>0) {
strcpy(Command,buffer);
if (Command[strlen(Command)-1] == '.') {
HandleCommand(Command);
}
if (strlen(Command) > 10) memset(Command,0,sizeof(Command)); // we
got garbage
}
break;
case esTeardown: // remote requested close, wait till the socket is
gone before listening again
break;
}
bytes_read = 0;
} Hopefully that's enough to give you an idea....

-Mike


At 10:41 AM 1/17/2005, you wrote: >Hi Everyone,
> New Year Greetings!!
>
>When a ethernet packet is received in its entirity, on Rabbit's NIC,
>how does rabbit know that a packet has arrived completely and it
>needs to process it.
>
>While investigating the same in ip.lib , realtek.lib etc. I found
>that pd_recieve() is the routine which is being called in
>pkt_received to know that a complete packet is received. I tried to
>make the sense out of pd_receive() but looks it will take lot of time
>to understand the concept.
>
>My question is: what is the mechanism by which the packet arrival is
>known to the reciever in TCP/IP. Does sender puts something like a
>end flag in the packet?

It is handled by the low-level code and the ethernet interface itself. The
ethernet interface will return data only in a packet. The HW reads the
length in the header to determine the packet length.

If you asking about TCP sockets, there is no packets at the user-level. It
is a stream protocol. If you are assuming that a write at one end comes out
the other as the same size, then you will fail.

I.e:

sock_write(&sock, "Hello ",6)
sock_write(&sock, "World",5)

Will most likely be received as:

sock_read(&sock,buff,sizeof(buff))

buff will likely get "Hello World".

There is no reason that the read would not return "Hello W" and the next
read return "orld". Both are valid as it is a stream protocol.

Like I said, there is no "end of packet" in TCP. Just data arrives as a
stream. It is broken into packets as needed by IP, and the reassembled. In
the example, the driver will combine the two sock_write() calls until a
packet is filled or a TX timeout occurs. This is part of the Nagle
algorithm to optimize data and prevent smaller packets from being used.

You would need to define your own delimiters. I.e HTTP defines the end of
the headers and the start of the content as an empty line.

I often do a protocol in either fixed data sizes or as \n delimited text.
Then write a routine to decode the incoming stream into my own packets.

<Scott ------
| Scott G. Henion| shenion@shen... |
| Consultant | Stone Mountain, GA |
| SHDesigns | PGP Key 0xE98DDC48 |
| http://www.shdesigns.org/rabbit/ |
------



Thanks scott,witt and mike.
Actually, I was looking for low-level implementation of packet
receiption. I found that, IP.LIB in pkt_received() is looping on a
linear array pktbuf[ETH_MAXBUF][ETH_BUFSIZE] which holds the ethernet
packets arrived onto the NIC. It loops on pktbuf for ETH_MAXBUF times.

i.e. when the control comes into the pkt_received() it checks whether
any packets have arrivee upto ETH_MAXBUF. Looks that packets are
stored on ETH_BUFSIZE (1500) boundary in pktbuf[][] giving way to lot
of memory wastage. Moreover it uses the polling to check the packet
arrival.

Observation: (gUESS??)

AS said by u guys,there is no end flag. Rabbit does not know
immediately that a packet has arrived in entirity. It is only when it
calls pkt_received() periodically,it comes to know that there are
some ethernet packets to be processed.

PLEASE GIVE YOUR COMMENTS ON THIS AND LET ME KNOW IF I AM ASSUMING
SOMETHING WRONG.

warm regards,
Rohan A. Gurjar --- In rabbit-semi@rabb..., Scott Henion <shenion@s...> wrote:
> At 10:41 AM 1/17/2005, you wrote: > >Hi Everyone,
> > New Year Greetings!!
> >
> >When a ethernet packet is received in its entirity, on Rabbit's
NIC,
> >how does rabbit know that a packet has arrived completely and it
> >needs to process it.
> >
> >While investigating the same in ip.lib , realtek.lib etc. I found
> >that pd_recieve() is the routine which is being called in
> >pkt_received to know that a complete packet is received. I tried to
> >make the sense out of pd_receive() but looks it will take lot of
time
> >to understand the concept.
> >
> >My question is: what is the mechanism by which the packet arrival
is
> >known to the reciever in TCP/IP. Does sender puts something like a
> >end flag in the packet?
>
> It is handled by the low-level code and the ethernet interface
itself. The
> ethernet interface will return data only in a packet. The HW reads
the
> length in the header to determine the packet length.
>
> If you asking about TCP sockets, there is no packets at the user-
level. It
> is a stream protocol. If you are assuming that a write at one end
comes out
> the other as the same size, then you will fail.
>
> I.e:
>
> sock_write(&sock, "Hello ",6)
> sock_write(&sock, "World",5)
>
> Will most likely be received as:
>
> sock_read(&sock,buff,sizeof(buff))
>
> buff will likely get "Hello World".
>
> There is no reason that the read would not return "Hello W" and the
next
> read return "orld". Both are valid as it is a stream protocol.
>
> Like I said, there is no "end of packet" in TCP. Just data arrives
as a
> stream. It is broken into packets as needed by IP, and the
reassembled. In
> the example, the driver will combine the two sock_write() calls
until a
> packet is filled or a TX timeout occurs. This is part of the Nagle
> algorithm to optimize data and prevent smaller packets from being
used.
>
> You would need to define your own delimiters. I.e HTTP defines the
end of
> the headers and the start of the content as an empty line.
>
> I often do a protocol in either fixed data sizes or as \n delimited
text.
> Then write a routine to decode the incoming stream into my own
packets.
>
> <Scott > ------
> | Scott G. Henion| shenion@s... |
> | Consultant | Stone Mountain, GA |
> | SHDesigns | PGP Key 0xE98DDC48 |
> | http://www.shdesigns.org/rabbit/ |
> ------



At 06:39 AM 1/19/2005, you wrote:
>Thanks scott,witt and mike.
> Actually, I was looking for low-level implementation of packet
>receiption. I found that, IP.LIB in pkt_received() is looping on a
>linear array pktbuf[ETH_MAXBUF][ETH_BUFSIZE] which holds the ethernet
>packets arrived onto the NIC. It loops on pktbuf for ETH_MAXBUF times.
>
>i.e. when the control comes into the pkt_received() it checks whether
>any packets have arrivee upto ETH_MAXBUF. Looks that packets are
>stored on ETH_BUFSIZE (1500) boundary in pktbuf[][] giving way to lot
>of memory wastage. Moreover it uses the polling to check the packet
>arrival.

That is correct. Apparently the 9.x stack changed this to a far buffer. It
is a memory waste, but the code overhead of implementing a better buffer
speed would effect speed. I did simplify the code considerably in my
minimized stack (circular buffer.)

The pd_received call puts packets in the buffer (allocated by pktentry.)

>Observation: (gUESS??)
>
>AS said by u guys,there is no end flag. Rabbit does not know
>immediately that a packet has arrived in entirity. It is only when it
>calls pkt_received() periodically,it comes to know that there are
>some ethernet packets to be processed.

The ethernet controller knows when a packet has been received. I can
generate an interrupt on this. However, most ZW boards have the interrupt
line unconnected or connected to a useless pin (not one of the external
interrupt pins.)

>PLEASE GIVE YOUR COMMENTS ON THIS AND LET ME KNOW IF I AM ASSUMING
>SOMETHING WRONG.

You are right. The stack is completely polled. You might be able to get it
interrupt driven, but the stack is not reentrant. Add to that, there are
some multi-tasking bugs in the semaphore code.

<Scott



Memfault Beyond the Launch