- From: Tuexen Michael <michael.tuexen AT siemens.com>
- To: "'Sumathi.Elangovan'" <Sumathi.Elangovan AT uk.thalesgroup.com>, discussion AT sctp.de, "'Thomas Dreibholz'" <dreibh AT exp-math.uni-essen.de>
- Subject: RE: [SCTP-Discussion] Partial Delivery!!
- Date: Fri Dec 13 13:02:01 2002
- List-id: SCTP Discussions <discussion.sctp.de>
Hi,
sending of large User Data requires the implementation
of a partial delivery API at the receiver. Large User
Data means User Data which is larger than the reciever
window.
The sctplib currently does NOT support the partial
delivery API and will not in pre20, but (hopefully) in
pre21. So it is clear that the association will hang.
The other point is, that you see the FORWARD-TSN chunk
on the wire. This is simply a bug and will be fixed in pre20.
Because the socketapilib is based on the sctplib, you can
also not use the partial delivery API from that library.
However, once the partial delivery API will be available
in the sctplib, it will also be available in the socketapilib.
Best regards
Michael
Michael Tuexen Tel.: +49 89 722 47210
Siemens AG Fax: +49 89 722 48212
ICN CP SE C 7 e-mail:
Michael.Tuexen AT siemens.com
>
-----Original Message-----
>
From: Sumathi.Elangovan
>
[mailto:Sumathi.Elangovan AT uk.thalesgroup.com]
>
Sent: Friday, December 13, 2002 12:12 PM
>
To:
>
discussion AT sctp.de;
>
'Thomas Dreibholz'
>
Subject: [SCTP-Discussion] Partial Delivery!!
>
>
>
> Hi!
>
> I am using the sctp implementation version 1.0.1...I have
>
attached part of my code ("SCTP CODE") which allows
>
association,data transfer and a graceful shutdown. The
>
problem arises when the sender is given a message to send
>
larger than its receiver window where it just hangs. This can
>
be seen in my other attachment ("after the sctp code") with
>
the trace viewed with the Ethereal.
>
> The sender fragments the message and sends the fragments to
>
the receiver.
>
> The receiver is constrained to hold onto the fragments till
>
the whole message has been reconstructed.
>
> Eventually the receiver returns an a_rwnd of 0 which can be
>
seen at frame 63. The association hangs.
>
>
>
> Why I am getting a FORWARD TSN at frame 64...What is the
>
significance of this message? I know that FORWARD TSN means
>
that the message received until this frame (64) is unordered......
>
>
>
> In RFC 2960,section 6.9:
>
> "Note: If the data receiver runs out of buffer space while still
>
> waiting for more fragments to complete the re-assembly of the
>
> message, it should dispatch part of its inbound message through a
>
> partial delivery API (see Section 10), freeing some of
>
its receive
>
> buffer space so that the rest of the message may be received."
>
>
>
> In section 5.3.1 of the sctp socket api - 05 .. ..it
>
mentions the SCTP_PARTIAL_DELIVERY_EVENT to be set....Does
>
the ESSEN implement this feature? How can I overcome the
>
"hang" problem? Am I missing something vital in my code to
>
perform the partial delivery?
>
> Thanks for your help!!!
>
>
>
> ******************** SCTP CODE **************************
>
>
>
#include <arpa/inet.h>
>
#include <bits/time.h>
>
#include <bits/types.h>
>
#include <config.h>
>
#include <ext_socket.h>
>
#include <features.h>
>
#include <gnu_getopt.h>
>
#include <net/route.h>
>
#include <net/if.h>
>
#include <netinet/in.h>
>
#include <sctp.h>
>
#include <stdio.h>
>
#include <stdlib.h>
>
#include <string.h>
>
#include <sys/socket.h>
>
#include <sys/types.h>
>
#include <sys/timeb.h>
>
#include <sys/uio.h>
>
#include <time.h>
>
#include <unistd.h>
>
#include <util.h>
>
>
#define MAX_BUF_LEN (128 *1024)
>
#define PATTERN_LEN 26
>
#define SERVER_PORT_NUM 2960
>
#define LONG_OPTIONS()
>
#define SHORT_OPTIONS()
>
#define DEBUG_PRINT(x) printf(x)
>
#define DEBUG_PRINT_1(x,y) printf(x,y)
>
#define DEBUG_PRINT_2(x,y,z) printf(x,y,z)
>
>
extern int gnu_getopt_long( int argc,char *const *argv,const
>
char *options,const struct option *long_options,int *opt_index );
>
extern double byte_atof( const char *inString );
>
extern const char *inet_ntop(af, src, dst, size);
>
>
struct msghdr msg[1];
>
>
int mBufLen = MAX_BUF_LEN;
>
int mAmount = 10;
>
int isServer = 0;
>
char *mHost;
>
long timeStart = 0;
>
long timeDiff = 0;
>
>
/* to get the time */
>
long getTime()
>
{
>
long longTime;
>
struct timeb thetime;
>
ftime(&thetime);
>
longTime = (thetime.time * 1000) + thetime.millitm;
>
DEBUG_PRINT_1("\nTime = %d ms\n", thetime.millitm);
>
return longTime;
>
}
>
>
/* to calculate the difference between start and end time*/
>
long getTimeDiff(long startTime)
>
{
>
long endTime;
>
endTime = getTime();
>
return (endTime-startTime);
>
}
>
>
/* this function gives the SCTP header information */
>
void printSCTPHeaderInfo(struct sctp_sndrcvinfo *info)
>
{
>
DEBUG_PRINT_1("Send Receive Info for assoc: %x\n", info
>
-> sinfo_assoc_id);
>
DEBUG_PRINT_1("Stream = %d \n", info -> sinfo_stream);
>
DEBUG_PRINT_1("SSN = %d \n", info -> sinfo_ssn);
>
DEBUG_PRINT_1("Flags = %x \n", info -> sinfo_flags);
>
DEBUG_PRINT_1("PPID = %x \n", info -> sinfo_ppid);
>
DEBUG_PRINT_1("Context = %d \n", info -> sinfo_context);
>
DEBUG_PRINT_1("TTL = %d \n", info -> sinfo_timetolive);
>
DEBUG_PRINT_1("TSN = %x \n", info -> sinfo_tsn);
>
}
>
>
/* to handle various events*/
>
void handle_event(void *buf)
>
{
>
struct sctp_assoc_change *sac;
>
struct sctp_send_failed *ssf;
>
struct sctp_paddr_change *spc;
>
struct sctp_remote_error *sre;
>
struct sockaddr_in *sin;
>
struct sctp_rcv_pdapi_event *pdapi;
>
>
union sctp_notification *snp;
>
>
char addrbuf[INET6_ADDRSTRLEN];
>
const char *ap;
>
snp = buf;
>
>
switch(snp -> h.sn_type)
>
{
>
case SCTP_ASSOC_CHANGE:
>
sac = &snp -> sn_assoc_change;
>
printf("*** assoc_change: state = %hu,
>
error = %hu, instr = %hu, outstr = %hu \n",
>
sac ->
>
sac_state, sac -> sac_error, sac -> sac_inbound_streams, sac
>
-> sac_outbound_streams);
>
if(sac -> sac_state == COMMUNICATION_UP)
>
{
>
timeStart = getTime();
>
}
>
if(sac ->sac_state == SHUTDOWN_COMPLETE)
>
{
>
timeDiff = getTimeDiff(timeStart);
>
}
>
break;
>
>
case SCTP_SEND_FAILED:
>
ssf = &snp -> sn_send_failed;
>
DEBUG_PRINT_2("*** send_failed: len =
>
%hu err = %hu\n", ssf -> ssf_length, ssf -> ssf_error);
>
break;
>
>
case SCTP_PEER_ADDR_CHANGE:
>
spc = &snp -> sn_paddr_change;
>
if(((struct sockaddr_in *)&spc ->
>
spc_aaddr)->sin_family == AF_INET)
>
{
>
sin = (struct sockaddr_in
>
*)&spc->spc_aaddr;
>
ap = inet_ntop(AF_INET, &sin ->
>
sin_addr,addrbuf,INET6_ADDRSTRLEN);
>
}
>
printf("*** intf_change: %s state
>
=%d,error =%d\n",ap,spc -> spc_state,spc -> spc_error);
>
break;
>
>
case SCTP_REMOTE_ERROR:
>
sre = &snp -> sn_remote_error;
>
DEBUG_PRINT_1("*** remote_error: err
>
=%hu\n",ntohs(sre -> sre_error));
>
break;
>
>
case SCTP_SHUTDOWN_EVENT:
>
DEBUG_PRINT("*** shutdown event\n");
>
break;
>
>
case SCTP_PARTIAL_DELIVERY_EVENT:
>
pdapi = &snp -> sn_rcv_pdapi_event;
>
printf("*** partial_delivery: length =
>
%hu, indi = %hu\n",pdapi -> pdapi_length,pdapi -> pdapi_indication);
>
break;
>
default:
>
DEBUG_PRINT_1("unknown type: %hu\n",snp
>
-> h.sn_type);
>
break;
>
}
>
>
}
>
>
/* function sctp_recvmsg which uses the ext_recvmsg to obtain
>
the data from the client and a MSG_EOR
>
* flag set for each received message */
>
void *sctp_recvmsg(int fd, struct msghdr *msg, void *buf,
>
size_t *buflen, ssize_t *nrp, size_t cmsglen)
>
{
>
int bytesReceived = 0;
>
int numReads = 0;
>
ssize_t nr = 0;
>
>
for(;;)
>
{
>
struct iovec iov[1];
>
iov -> iov_base = buf;
>
msg -> msg_iov = iov;
>
msg -> msg_iovlen = 1;
>
>
msg -> msg_flags =0;
>
msg -> msg_iov -> iov_len = *buflen;
>
msg -> msg_controllen = cmsglen;
>
>
nr = ext_recvmsg(fd,msg,0);
>
numReads++;
>
>
if(nr <= 0)
>
{
>
bytesReceived = nr;
>
DEBUG_PRINT_1("bytes received = %d\n\n", nr);
>
DEBUG_PRINT_1("sctp_recvmsg: number of reads = %d
>
\n\n", numReads);
>
return(NULL);
>
}
>
>
if((msg -> msg_flags & MSG_EOR) != 0)
>
{
>
*nrp = nr;
>
return(buf);
>
}
>
}
>
}
>
>
/* ext_setsockopt() defined */
>
void setSocketOptions(int sock)
>
{
>
struct sctp_event_subscribe events;
>
DEBUG_PRINT("setting socket option.\n");
>
memset((char*)&events,1,sizeof(events));
>
if(ext_setsockopt(sock, IPPROTO_SCTP, SCTP_SET_EVENTS,
>
&events, sizeof(events)) < 0)
>
{
>
printf("setsocketopt failed\n");
>
exit(1);
>
}
>
DEBUG_PRINT("socket options set\n");
>
}
>
>
/* socket(),bind() and listen() functions called */
>
int setUpSocket(int portNum)
>
{
>
int sock;
>
struct sockaddr_in sockAddr;
>
>
if((sock = ext_socket(AF_INET, SOCK_SEQPACKET,
>
IPPROTO_SCTP)) < 0)
>
{
>
printf("socket() failed");
>
exit(1);
>
}
>
DEBUG_PRINT("socket created()\n");
>
>
memset(&sockAddr, 0 , sizeof(sockAddr));
>
sockAddr.sin_family = AF_INET;
>
sockAddr.sin_addr.s_addr = INADDR_ANY;
>
sockAddr.sin_port = htons(portNum);
>
>
if(ext_bind(sock, (struct sockaddr *) &sockAddr,
>
sizeof(sockAddr)) < 0)
>
{
>
printf("bind() failed");
>
exit(1);
>
}
>
DEBUG_PRINT("address bounded\n");
>
>
setSocketOptions(sock);
>
>
if(ext_listen(sock, 0) < 0)
>
{
>
printf("listen() failed");
>
exit(1);
>
}
>
return sock;
>
>
}
>
>
/*sets up the server side of sctp which calls
>
setUpSocket(),sctp_recvmsg(),handleEvent() and calculates
>
* the Bandwidth */
>
void SctpServer()
>
{
>
int servSock;
>
int numReads = 0;
>
int totalBytesReceived = 0;
>
double throughput;
>
ssize_t bytesReceived = 0;
>
struct sctp_sndrcvinfo *sri;
>
struct cmsghdr *cmsg;
>
>
char cbuf[sizeof(*cmsg) + sizeof(*sri)];
>
char *buf = NULL;
>
size_t bufLen;
>
size_t cmsglen = sizeof(*cmsg) + sizeof(*sri);
>
>
servSock = setUpSocket(SERVER_PORT_NUM);
>
>
for (;;)
>
{
>
>
DEBUG_PRINT("*************************************************
>
**************.\n");
>
bufLen = MAX_BUF_LEN;
>
DEBUG_PRINT_1("Maximum buffer length: %d\n", bufLen);
>
if(!(buf = malloc(bufLen)))
>
{
>
printf("out of memory");
>
exit(1);
>
}
>
DEBUG_PRINT("memory allocated\n");
>
>
memset(msg,0,sizeof(*msg));
>
msg -> msg_control = cbuf;
>
msg -> msg_controllen = cmsglen;
>
msg -> msg_flags = 0;
>
cmsg = (struct cmsghdr *)cbuf;
>
sri = (struct sctp_sndrcvinfo *) (cmsg+1);
>
>
numReads = 0;
>
while((buf = sctp_recvmsg(servSock, msg, buf,
>
&bufLen, &bytesReceived, cmsglen)))
>
{
>
numReads++;
>
totalBytesReceived += bytesReceived;
>
//printSCTPHeaderInfo(sri);
>
if(msg -> msg_flags & MSG_NOTIFICATION)
>
{
>
handle_event(buf);
>
if(timeDiff != 0)
>
{
>
printf("Total bytes received %d
>
in %d msecs\n",totalBytesReceived, timeDiff);
>
throughput =
>
((totalBytesReceived * 8) / timeDiff);
>
printf("Bandwidth: %.2f
>
kbits/sec \n\n",throughput);
>
timeDiff = 0;
>
}
>
continue;
>
}
>
}
>
}
>
}
>
>
/*the client side created which calls up setUpSocket() and
>
ext_sendmsg() */
>
void SctpClient()
>
{
>
int bytesReceived;
>
int clntSock;
>
int bytesSent = 0;
>
int loopIndex;
>
int i;
>
int count;
>
char *buf;
>
int numWrites = 0;
>
int readBufLen = 100;
>
char readBuf[100];
>
struct sockaddr_in servAddr;
>
struct iovec iov[1];
>
struct sctp_sndrcvinfo *sri;
>
struct cmsghdr *cmsg;
>
char cbuf[sizeof(*cmsg) + sizeof(*sri)];
>
size_t cmsglen = sizeof(*cmsg) + sizeof(*sri);
>
>
clntSock = setUpSocket(SERVER_PORT_NUM);
>
>
/* The server address that the client needs to connect */
>
servAddr.sin_family = AF_INET;
>
if(inet_aton(mHost, &servAddr.sin_addr) != 1)
>
{
>
printf("mHost failed.\n\n");
>
exit(1);
>
}
>
servAddr.sin_port = htons(SERVER_PORT_NUM);
>
>
buf = malloc(mBufLen);
>
(&iov[0]) -> iov_base = buf;
>
(&iov[0]) -> iov_len = mBufLen;
>
>
memset(msg,0,sizeof(*msg)); // added by iain
>
msg -> msg_iov = iov;
>
msg -> msg_iovlen = 1;
>
msg -> msg_name = (void *) &servAddr;
>
msg -> msg_namelen = sizeof(servAddr);
>
>
// added by iain
>
cmsg = (struct cmsghdr *) cbuf;
>
sri = (struct sctp_sndrcvinfo *) (cmsg + 1);
>
>
memset(cbuf,0,(sizeof(*cmsg) + sizeof(*sri)));
>
cmsg -> cmsg_level = IPPROTO_SCTP;
>
cmsg -> cmsg_type = SCTP_SNDRCV;
>
cmsg -> cmsg_len = cmsglen;
>
msg -> msg_control = cbuf;
>
msg -> msg_controllen = cmsglen;
>
msg -> msg_flags = 0;
>
>
// end of iain addition
>
>
for(i = 0 ; i < mBufLen; i++)
>
{
>
buf[i] = (char) (i % 256);
>
}
>
>
loopIndex = (mAmount/mBufLen);
>
DEBUG_PRINT_1("\nLoopIndex = %d.\n",loopIndex);
>
>
for(i = 0; i < loopIndex; i++)
>
{
>
if((count = ext_sendmsg(clntSock,msg, 0)) < 0)
>
{
>
printf("send() failed.\n\n");
>
exit(1);
>
}
>
bytesSent += count;
>
numWrites++;
>
}
>
DEBUG_PRINT_1("Number of writes %d \n\n", numWrites);
>
>
msg -> msg_flags = 0;
>
cmsg = (struct cmsghdr *)cbuf;
>
sri = (struct sctp_sndrcvinfo *) (cmsg+1);
>
sri -> sinfo_flags = MSG_EOF;
>
sri -> sinfo_assoc_id = 1;
>
>
/* in order to shutdown the association gracefully ,need to
>
send an empty buffer */
>
>
(&iov[0]) -> iov_base = buf;
>
(&iov[0]) -> iov_len = 0;
>
>
msg -> msg_iov = iov;
>
msg -> msg_iovlen = 1;
>
>
DEBUG_PRINT("For Graceful Shutdown\n");
>
if((count = ext_sendmsg(clntSock,msg,0)) > 0)
>
{
>
printf("buffer greater than 0:failed()");
>
exit(1);
>
}
>
DEBUG_PRINT_1("Empty Buffer:%d\n",count);
>
>
msg -> msg_flags = 0;
>
(&iov[0]) -> iov_base = readBuf;
>
(&iov[0]) -> iov_len = readBufLen;
>
msg -> msg_iov = iov;
>
msg -> msg_iovlen = 1;
>
>
buf = sctp_recvmsg(clntSock, msg, readBuf, &readBufLen,
>
&bytesReceived, cmsglen);
>
>
//{
>
if(msg -> msg_flags & MSG_NOTIFICATION);
>
{
>
handle_event(buf);
>
// continue;
>
}
>
//}
>
printSCTPHeaderInfo(sri);
>
//ext_close(clntSock);
>
DEBUG_PRINT("********** This will timeout
>
soon...inorder to break do Ctrl c ************ \n");
>
sleep(300);
>
exit(1);
>
}
>
>
> *****************************************************
>
TRACE SHOWN BY THE ETHEREAL*****************************************
>
> No. Time Source Destination
>
Protocol Info
>
21 29.147839 Node B Node A SCTP INIT
>
22 29.148184 Node A Node B SCTP INIT_ACK
>
23 29.155720 Node B Node A SCTP COOKIE_ECHO
>
24 29.155933 Node A Node B SCTP COOKIE_ACK
>
25 29.176618 Node B Node A SCTP DATA
>
26 29.176816 Node A Node B SCTP SACK
>
27 29.182558 Node B Node A SCTP DATA
>
28 29.188527 Node B Node A SCTP DATA
>
29 29.188681 Node A Node B SCTP SACK
>
30 29.200215 Node B Node A SCTP DATA
>
31 29.206138 Node B Node A SCTP DATA
>
32 29.206268 Node A Node B SCTP SACK
>
33 29.212063 Node B Node A SCTP DATA
>
34 29.218000 Node B Node A SCTP DATA
>
35 29.218122 Node A Node B SCTP SACK
>
36 29.223930 Node B Node A SCTP DATA
>
37 29.229852 Node B Node A SCTP DATA
>
38 29.229967 Node A Node B SCTP SACK
>
39 29.235775 Node B Node A SCTP DATA
>
40 29.241714 Node B Node A SCTP DATA
>
41 29.241797 Node A Node B SCTP SACK
>
42 29.247734 Node B Node A SCTP DATA
>
43 29.253577 Node B Node A SCTP DATA
>
44 29.253664 Node A Node B SCTP SACK
>
45 29.259504 Node B Node A SCTP DATA
>
46 29.265422 Node B Node A SCTP DATA
>
47 29.265538 Node A Node B SCTP SACK
>
48 29.271355 Node B Node A SCTP DATA
>
49 29.277284 Node B Node A SCTP DATA
>
50 29.277386 Node A Node B SCTP SACK
>
51 29.283222 Node B Node A SCTP DATA
>
52 29.289176 Node B Node A SCTP DATA
>
53 29.289269 Node A Node B SCTP SACK
>
54 29.295083 Node B Node A SCTP DATA
>
55 29.301033 Node B Node A SCTP DATA
>
56 29.301121 Node A Node B SCTP SACK
>
57 29.306941 Node B Node A SCTP DATA
>
58 29.312882 Node B Node A SCTP DATA
>
59 29.312983 Node A Node B SCTP SACK
>
60 29.333917 Node B Node A SCTP DATA
>
61 29.542687 Node A Node B SCTP SACK
>
62 29.564601 Node B Node A SCTP DATA
>
63 29.564718 Node A Node B SCTP SACK
>
64 30.569279 Node B Node A SCTP FORWARD TSN
>
65 30.773141 Node A Node B SCTP SACK
>
>
78 59.903598 Node A Node B SCTP SHUTDOWN
>
83 62.903638 Node A Node B SCTP SHUTDOWN
>
84 68.903799 Node A Node B SCTP SHUTDOWN
>
>
89 80.904099 Node A Node B SCTP SHUTDOWN
>
>
92 104.904727 Node A Node B SCTP SHUTDOWN
>
>
> Regards
>
> Sumathi Elangovan
>
>
>
> Sumathi Elangovan
>
> Design Engineer
>
> Thales Research Limited
>
> Reading
>
> Tel: 0118 923 8272
>
> Email :
>
> Sumathi.Elangovan AT uk.thalesgroup.com
>
>
>
>
>
>
>
**********************************************************************
>
This email and any files transmitted with it are intended solely for
>
the use of the individual or entity to whom they are addressed and may
>
not be divulged to any third party without the express permission of
>
the originator. Any views expressed in this message are those of the
>
individual sender, except where the sender specifically states them to
>
be the views of Thales Research & Technology (UK) Ltd.
>
**********************************************************************
>
_______________________________________________
>
discussion mailing list
>
discussion AT sctp.de
>
http://www.sctp.de/mailman/listinfo/discussion
>
Archive powered by MHonArc 2.6.19+.