ralphjzhang / openpgm

Automatically exported from code.google.com/p/openpgm
0 stars 0 forks source link

NAK-RDATA cycle in PGM #9

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Receiver implementation is like below:

while(true)
{
...
int status = pgm_recvmsgv (m_Sock, msgv, iov_len, MSG_ERRQUEUE, &bytes_read, 
&pgm_err);

switch (status)
{
...
case PGM_IO_STATUS_RESET:
  {
...
//Socket is both sending and receiving data. It's send //options are also set.
int nakStatus = pgm_send(m_Sock, nakPacket.GetBuffer(), 
nakPacket.GetBufferSize(), NULL);
...
  }
...
}
...
}

My question is: What should be the content of this nakPacket(The nak packet 
struct)?. It will be very appreciated if struct or another type is suggested 
and a sample for filling the contents of this struct is provided.

Note: In the PGM specification, it is stated that

   NAKs are transmitted by receivers to request repairs for missing data packets.

   NAKs are unicast (PGM-hop-by-PGM-hop) to the source and contain:

   NAK_TSI        OD_TSI of the ODATA packet for which a repair is
                  requested

   NAK_SQN        OD_SQN of the ODATA packet for which a repair is
                  requested

   NAK_SRC        the unicast NLA of the original source of the missing
                  ODATA.

   NAK_GRP        the multicast group NLA

So I think I must conform to that specification. I didn't find any example for 
that.

Original issue reported on code.google.com by yavuze...@gmail.com on 7 Oct 2011 at 1:21

GoogleCodeExporter commented 9 years ago
pgm_recv and friends automatically generate NAKs based on the internal receive 
state.  The only action required of the application developer is to ensure that 
pgm_recv is called in response to events on the socket handles or file 
descriptors.

Compare with Microsoft's PGM stack:

1:  Call recv() on the PGM socket.
2:  Data is returned or WSAEWOULDBLOCK for no data.
3:  Events are generated for select() when incoming data is available.

OpenPGM stack:

1:  Call pgm_recv() on the PGM socket.
2:  Data is returned or PGM_IO_STATUS_WOULD_BLOCK or 
PGM_IO_STATUS_TIMER_PENDING for no data.
3:  Events are generated for select() when incoming packets or internal state 
changes are available.

So the difference is that OpenPGM generates additional events that would 
normally be received by the Microsoft PGM engine thread pool.  In the Microsoft 
engine the non-data packets, out-of-order packets, or state changes can be 
immediately processed by the thread pool.  In the OpenPGM stack the engine is 
only driven when pgm_recv is called.

Original comment by fnjo...@gmail.com on 7 Oct 2011 at 7:09

GoogleCodeExporter commented 9 years ago
The only action required of the application developer is to ensure that 
pgm_recv is called in response to events on the socket handles or file 
descriptors.

How exactly could that be done? A coded example would probably clarify the 
issue and will be very appreciated.

Thanks.

Original comment by yavuze...@gmail.com on 10 Oct 2011 at 3:59

GoogleCodeExporter commented 9 years ago
A basic example would be found in the pgm_select_info man page:

  int nfds = 0;
  fd_set readfds;
  FD_ZERO(&readfds);
  pgm_select_info (sock, &readfds, NULL, &nfds);
  nfds = select (nfds, &readfds, NULL, NULL, NULL);

http://code.google.com/p/openpgm/wiki/OpenPgm5CReferencePgmSelectInfo

In regard to determining which file descriptors should be checked from the 
return of select().

For RX-only you can get the receiver & pending descriptors:

  int recv_sock, pending_sock;
  socklen_t socklen = sizeof (int);
  pgm_getsockopt (sock, IPPROTO_PGM, PGM_RECV_SOCK, &recv_sock, &socklen);
  pgm_getsockopt (sock, IPPROTO_PGM, PGM_PENDING_SOCK, &pending_sock, &socklen);

For TX-only socket you need the receiver, repair, & pending descriptors:

  int recv_sock, repair_sock, pending_sock;
  socklen_t socklen = sizeof (int);
  pgm_getsockopt (sock, IPPROTO_PGM, PGM_RECV_SOCK, &recv_sock, &socklen);
  pgm_getsockopt (sock, IPPROTO_PGM, PGM_REPAIR_SOCK, &repair_sock, &socklen);
  pgm_getsockopt (sock, IPPROTO_PGM, PGM_PENDING_SOCK, &pending_sock, &socklen);

If you want to testing for blocking sends there is the additional send socket.  
Use this in writefds of select(), it will typically be raised only when you 
have very small kernel socket buffers.

  int send_sock;
  socklen_t socklen = sizeof (int);
  pgm_getsockopt (sock, IPPROTO_PGM, PGM_SEND_SOCK, &send_sock, &socklen);

There is an additional socket for PGM Congestion Control operation but this is 
unsupported.

Original comment by fnjo...@gmail.com on 10 Oct 2011 at 4:21