Horacio Sanson wrote: > On Tue, Dec 16, 2008 at 12:55 AM, Vlad Yasevich > <vladislav.yasevich@xxxxxx> wrote: >>> I created a new patch set that fixes the SCTP_PR_SCTP_RTX partial >>> reliability that was not working and added a test program to test it. >>> Again all v4tests and v6tests pass including my own tests. >>> >>> This includes the previous patches so the previous ones should be >>> ignored. But no one seems to be looking at my patches so I think there >>> should be no problems anyway :( . >>> >>> >> I am looking, I am just busy with other things as well. Please be patient. >> > > Thanks, I really appreciate the feedback. > >> As a first step that will make review much easier, please get rid of the whitespace >> changes that show up. That will improve the readability of the patches. >> > > I tried my best here but seems I did it all wrong. I though that using > a command like "git apply --check --whitespaces=error-all" was enough > to make sure no trailing spaces or spaces before tabs were present. > Seems this is not the case as the command gives no errors even though > there are in fact white spaces all over the place. Will check again. Look at the git-diff generated patch and look for lines like this: > - union sctp_addr_param *); > + union sctp_addr_param *); Note, they have the same text but they show up in diff. This means that there is a difference in the whitespace used in those lines. --whitespace doesn't catch everything. Vim and emacs diff options typically show where the change occurred. You can save the new file, then do git-checkout <filename> and bring up both in one of the graphic diff tools to see where the change was. > >> Also, please separate the patches into separate e-mails. Look at git-send-email >> and git-format-patch for more information. >> > > Will rewrite my patches again trying to split the changes in smaller > and more concise steps. I thing you patches were already split, however, they were in one email. It's easier to review when each patch is by itself. > >> Thanks >> -vlad >> >>> >>> >>> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h >>> index 9661d7b..ffda4c5 100644 >>> --- a/include/net/sctp/structs.h >>> +++ b/include/net/sctp/structs.h >>> @@ -208,7 +208,7 @@ extern struct sctp_globals { >>> >>> /* Lock that protects the local_addr_list writers */ >>> spinlock_t addr_list_lock; >>> - >>> + >>> /* Flag to indicate if addip is enabled. */ >>> int addip_enable; >>> int addip_noauth_enable; >>> @@ -282,7 +282,8 @@ struct sctp_sock { >>> __u32 default_ppid; >>> __u16 default_flags; >>> __u32 default_context; >>> - __u32 default_timetolive; >>> + __u16 default_pr_policy; >>> + __u32 default_pr_value; >> Please don't add any memory holes when adding new entries to the structure. > > Could you please elaborate in this comment?? Has this something to do > with memory alignment issues of some sort? How can I avoid this memory > hole you mention?? sctp_sock is already huge and adding memory holes just makes it even bigger. when possible, try to find a hole to fill. If not possible, try to create a smallest hole possible. Use pahole to see the alignment and memory holes (git://git.kernel.org/pub/scm/linux/kernel/git/acme/pahole.git) For the above bit, there is already a 16 bit memory hole between default_flags and default-context. If the default_* elements fall into the same cache line, then it's better to fill that 16 bit memory hole with pr_policy element. It doesn't matter that the elements are not together. By being in the same cache line you get free access to all of them. -vlad > > thanks, > Horacio > > >>> __u32 default_rcv_context; >>> int max_burst; >>> >>> @@ -390,7 +391,7 @@ struct sctp_cookie { >>> /* This holds the originating address of the INIT packet. */ >>> union sctp_addr peer_addr; >>> >>> - /* IG Section 2.35.3 >>> + /* IG Section 2.35.3 >>> * Include the source port of the INIT-ACK >>> */ >>> __u16 my_port; >>> @@ -398,7 +399,7 @@ struct sctp_cookie { >>> __u8 prsctp_capable; >>> >>> /* Padding for future use */ >>> - __u8 padding; >>> + __u8 padding; >> White space? Please limit the scope of your patches. >> >>> __u32 adaptation_ind; >>> >>> @@ -512,12 +513,12 @@ static inline __u16 sctp_ssn_next(struct sctp_stream *stream, __u16 id) >>> } >>> >>> /* Skip over this ssn and all below. */ >>> -static inline void sctp_ssn_skip(struct sctp_stream *stream, __u16 id, >>> +static inline void sctp_ssn_skip(struct sctp_stream *stream, __u16 id, >>> __u16 ssn) >>> { >>> stream->ssn[id] = ssn+1; >>> } >>> - >>> + >> More whitespace? >> >>> /* >>> * Pointers to address related SCTP functions. >>> * (i.e. things that depend on the address family.) >>> @@ -575,7 +576,7 @@ struct sctp_af { >>> union sctp_addr_param *, >>> __be16 port, int iif); >>> int (*to_addr_param) (const union sctp_addr *, >>> - union sctp_addr_param *); >>> + union sctp_addr_param *); >> Again? >> >>> int (*addr_valid) (union sctp_addr *, >>> struct sctp_sock *, >>> const struct sk_buff *); >>> @@ -626,13 +627,15 @@ struct sctp_datamsg { >>> struct list_head track; >>> /* Reference counting. */ >>> atomic_t refcnt; >>> + >>> + /* Policy used to determine expired messages */ >>> + unsigned long expires_policy; >>> /* When is this message no longer interesting to the peer? */ >>> unsigned long expires_at; >>> /* Did the messenge fail to send? */ >>> int send_error; >>> char send_failed; >>> /* Control whether chunks from this message can be abandoned. */ >>> - char can_abandon; >>> }; >>> >>> struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *, >>> @@ -1339,7 +1342,7 @@ struct sctp_endpoint { >>> * on every receive. >>> */ >>> __u8 *digest; >>> - >>> + >> Again? I am done at this point!!! >> >>> /* sendbuf acct. policy. */ >>> __u32 sndbuf_policy; >>> >>> @@ -1759,9 +1762,10 @@ struct sctp_association { >>> /* Default send parameters. */ >>> __u16 default_stream; >>> __u16 default_flags; >>> + __u16 default_pr_policy; >>> __u32 default_ppid; >>> __u32 default_context; >>> - __u32 default_timetolive; >>> + __u32 default_pr_value; >>> >>> /* Default receive parameters */ >>> __u32 default_rcv_context; >>> diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h >>> index f205b10..74c0aba 100644 >>> --- a/include/net/sctp/user.h >>> +++ b/include/net/sctp/user.h >>> @@ -71,7 +71,7 @@ enum sctp_optname { >>> #define SCTP_NODELAY SCTP_NODELAY >>> SCTP_AUTOCLOSE, >>> #define SCTP_AUTOCLOSE SCTP_AUTOCLOSE >>> - SCTP_SET_PEER_PRIMARY_ADDR, >>> + SCTP_SET_PEER_PRIMARY_ADDR, >>> #define SCTP_SET_PEER_PRIMARY_ADDR SCTP_SET_PEER_PRIMARY_ADDR >>> SCTP_PRIMARY_ADDR, >>> #define SCTP_PRIMARY_ADDR SCTP_PRIMARY_ADDR >>> @@ -120,7 +120,7 @@ enum sctp_optname { >>> #define SCTP_LOCAL_AUTH_CHUNKS SCTP_LOCAL_AUTH_CHUNKS >>> >>> >>> - /* Internal Socket Options. Some of the sctp library functions are >>> + /* Internal Socket Options. Some of the sctp library functions are >>> * implemented using these socket options. >>> */ >>> SCTP_SOCKOPT_BINDX_ADD = 100,/* BINDX requests for adding addresses. */ >>> @@ -183,9 +183,10 @@ struct sctp_sndrcvinfo { >>> __u16 sinfo_stream; >>> __u16 sinfo_ssn; >>> __u16 sinfo_flags; >>> + __u16 sinfo_pr_policy; >>> __u32 sinfo_ppid; >>> __u32 sinfo_context; >>> - __u32 sinfo_timetolive; >>> + __u32 sinfo_pr_value; >>> __u32 sinfo_tsn; >>> __u32 sinfo_cumtsn; >>> sctp_assoc_t sinfo_assoc_id; >>> @@ -199,12 +200,25 @@ struct sctp_sndrcvinfo { >>> */ >>> >>> enum sctp_sinfo_flags { >>> - SCTP_UNORDERED = 1, /* Send/receive message unordered. */ >>> - SCTP_ADDR_OVER = 2, /* Override the primary destination. */ >>> - SCTP_ABORT=4, /* Send an ABORT message to the peer. */ >>> - SCTP_EOF=MSG_FIN, /* Initiate graceful shutdown process. */ >>> + SCTP_EOF = MSG_FIN, /* Initiate graceful shutdown process. (0x0200) */ >>> + SCTP_UNORDERED = 0x0400, /* Send/receive message unordered. */ >>> + SCTP_ADDR_OVER = 0x0800, /* Override the primary destination. */ >>> + SCTP_ABORT = 0x1000, /* Send an ABORT message to the peer. */ >>> }; >>> >>> +/* >>> + * sinfo_pr_policy: 16 bits (unsigned integer) >>> + * >>> + * This field may contain the partial reliability used to >>> + * send the message. >>> + */ >>> + >>> +enum sctp_sinfo_pr_policy { >>> + SCTP_PR_SCTP_NONE = 0x0000, /* Reliable transmission */ >>> + SCTP_PR_SCTP_TTL = 0x0001, /* Timed partial reliability */ >>> + SCTP_PR_SCTP_BUF = 0x0002, /* Buffer parital reliability (EXPERIMENTAL) */ >>> + SCTP_PR_SCTP_RTX = 0x0003, /* Retransmis partial reliability (EXPERIMENTAL) */ >>> +}; >>> >>> typedef union { >>> __u8 raw; >>> @@ -479,7 +493,7 @@ typedef enum sctp_sn_error { >>> * >>> * The protocol parameters used to initialize and bound retransmission >>> * timeout (RTO) are tunable. See [SCTP] for more information on how >>> - * these parameters are used in RTO calculation. >>> + * these parameters are used in RTO calculation. >>> */ >>> struct sctp_rtoinfo { >>> sctp_assoc_t srto_assoc_id; >>> @@ -717,9 +731,9 @@ struct sctp_authchunks { >>> >>> /* >>> * 8.3, 8.5 get all peer/local addresses in an association. >>> - * This parameter struct is used by SCTP_GET_PEER_ADDRS and >>> + * This parameter struct is used by SCTP_GET_PEER_ADDRS and >>> * SCTP_GET_LOCAL_ADDRS socket options used internally to implement >>> - * sctp_getpaddrs() and sctp_getladdrs() API. >>> + * sctp_getpaddrs() and sctp_getladdrs() API. >>> */ >>> struct sctp_getaddrs_old { >>> sctp_assoc_t assoc_id; >>> >>> >>> >>> diff --git a/net/sctp/associola.c b/net/sctp/associola.c >>> index f4b2304..c178139 100644 >>> --- a/net/sctp/associola.c >>> +++ b/net/sctp/associola.c >>> @@ -302,7 +302,8 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a >>> asoc->default_ppid = sp->default_ppid; >>> asoc->default_flags = sp->default_flags; >>> asoc->default_context = sp->default_context; >>> - asoc->default_timetolive = sp->default_timetolive; >>> + asoc->default_pr_policy = sp->default_pr_policy; >>> + asoc->default_pr_value = sp->default_pr_value; >>> asoc->default_rcv_context = sp->default_rcv_context; >>> >>> /* AUTH related initializations */ >>> diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c >>> index 1748ef9..4cdfe49 100644 >>> --- a/net/sctp/chunk.c >>> +++ b/net/sctp/chunk.c >>> @@ -56,7 +56,7 @@ static void sctp_datamsg_init(struct sctp_datamsg *msg) >>> atomic_set(&msg->refcnt, 1); >>> msg->send_failed = 0; >>> msg->send_error = 0; >>> - msg->can_abandon = 0; >>> + msg->expires_policy = SCTP_PR_SCTP_NONE; >>> msg->expires_at = 0; >>> INIT_LIST_HEAD(&msg->chunks); >>> } >>> @@ -170,13 +170,26 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, >>> /* Note: Calculate this outside of the loop, so that all fragments >>> * have the same expiration. >>> */ >>> - if (sinfo->sinfo_timetolive) { >>> - /* sinfo_timetolive is in milliseconds */ >>> - msg->expires_at = jiffies + >>> - msecs_to_jiffies(sinfo->sinfo_timetolive); >>> - msg->can_abandon = 1; >>> - SCTP_DEBUG_PRINTK("%s: msg:%p expires_at: %ld jiffies:%ld\n", >>> - __func__, msg, msg->expires_at, jiffies); >>> + >>> + msg->expires_policy = sinfo->sinfo_pr_policy; >>> + >>> + if(msg->expires_policy) { >>> + switch(msg->expires_policy) { >>> + case SCTP_PR_SCTP_TTL: >>> + /* sinfo_timetolive is in milliseconds */ >>> + msg->expires_at = jiffies + >>> + msecs_to_jiffies(sinfo->sinfo_pr_value); >>> + SCTP_DEBUG_PRINTK("%s: msg:%p expires_at: %ld jiffies:%ld\n", >>> + __func__, msg, msg->expires_at, jiffies); >>> + break; >>> + case SCTP_PR_SCTP_BUF: >>> + break; >>> + case SCTP_PR_SCTP_RTX: >>> + msg->expires_at = sinfo->sinfo_pr_value; >>> + SCTP_DEBUG_PRINTK("%s: msg:%p expires_after: %ld retransmissions \n", >>> + __func__, msg, msg->expires_at); >>> + break; >>> + } >>> } >>> >>> max = asoc->frag_point; >>> @@ -291,11 +304,23 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk) >>> { >>> struct sctp_datamsg *msg = chunk->msg; >>> >>> - if (!msg->can_abandon) >>> + if (!msg->expires_policy) >>> return 0; >>> >>> - if (time_after(jiffies, msg->expires_at)) >>> - return 1; >>> + switch(msg->expires_policy) { >>> + case SCTP_PR_SCTP_TTL: >>> + if (time_after(jiffies, msg->expires_at)) >>> + return 1; >>> + case SCTP_PR_SCTP_BUF: >>> + /* TODO: Implement this */ >>> + return 0; >>> + case SCTP_PR_SCTP_RTX: >>> + if(--msg->expires_at <= 0) { >>> + SCTP_DEBUG_PRINTK("%s: msg:%p expires_at: %ld EXPIRED!!\n", >>> + __func__, msg, msg->expires_at); >>> + return 1; >>> + } >>> + } >>> >>> return 0; >>> } >>> diff --git a/net/sctp/output.c b/net/sctp/output.c >>> index c3f417f..b344a9d 100644 >>> --- a/net/sctp/output.c >>> +++ b/net/sctp/output.c >>> @@ -745,7 +745,7 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet, >>> asoc->peer.rwnd = rwnd; >>> /* Has been accepted for transmission. */ >>> if (!asoc->peer.prsctp_capable) >>> - chunk->msg->can_abandon = 0; >>> + chunk->msg->expires_policy = SCTP_PR_SCTP_NONE; >>> >>> finish: >>> return retval; >>> diff --git a/net/sctp/socket.c b/net/sctp/socket.c >>> index a1b9045..0dfc137 100644 >>> --- a/net/sctp/socket.c >>> +++ b/net/sctp/socket.c >>> @@ -1698,7 +1698,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, >>> default_sinfo.sinfo_flags = asoc->default_flags; >>> default_sinfo.sinfo_ppid = asoc->default_ppid; >>> default_sinfo.sinfo_context = asoc->default_context; >>> - default_sinfo.sinfo_timetolive = asoc->default_timetolive; >>> + default_sinfo.sinfo_pr_policy = asoc->default_pr_policy; >>> + default_sinfo.sinfo_pr_value = asoc->default_pr_value; >>> default_sinfo.sinfo_assoc_id = sctp_assoc2id(asoc); >>> sinfo = &default_sinfo; >>> } >>> @@ -2539,7 +2540,7 @@ static int sctp_setsockopt_initmsg(struct sock *sk, char __user *optval, int opt >>> * in to this call the sctp_sndrcvinfo structure defined in Section >>> * 5.2.2) The input parameters accepted by this call include >>> * sinfo_stream, sinfo_flags, sinfo_ppid, sinfo_context, >>> - * sinfo_timetolive. The user must provide the sinfo_assoc_id field in >>> + * sinfo_pr_policy. The user must provide the sinfo_assoc_id field in >>> * to this call if the caller is using the UDP model. >>> */ >>> static int sctp_setsockopt_default_send_param(struct sock *sk, >>> @@ -2563,13 +2564,15 @@ static int sctp_setsockopt_default_send_param(struct sock *sk, >>> asoc->default_flags = info.sinfo_flags; >>> asoc->default_ppid = info.sinfo_ppid; >>> asoc->default_context = info.sinfo_context; >>> - asoc->default_timetolive = info.sinfo_timetolive; >>> + asoc->default_pr_policy = info.sinfo_pr_policy; >>> + asoc->default_pr_value = info.sinfo_pr_value; >>> } else { >>> sp->default_stream = info.sinfo_stream; >>> sp->default_flags = info.sinfo_flags; >>> sp->default_ppid = info.sinfo_ppid; >>> sp->default_context = info.sinfo_context; >>> - sp->default_timetolive = info.sinfo_timetolive; >>> + sp->default_pr_policy = info.sinfo_pr_policy; >>> + sp->default_pr_value = info.sinfo_pr_value; >>> } >>> >>> return 0; >>> @@ -3524,7 +3527,8 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) >>> sp->default_ppid = 0; >>> sp->default_flags = 0; >>> sp->default_context = 0; >>> - sp->default_timetolive = 0; >>> + sp->default_pr_policy = 0; >>> + sp->default_pr_value = 0; >>> >>> sp->default_rcv_context = 0; >>> sp->max_burst = sctp_max_burst; >>> @@ -4824,7 +4828,7 @@ static int sctp_getsockopt_adaptation_layer(struct sock *sk, int len, >>> * in to this call the sctp_sndrcvinfo structure defined in Section >>> * 5.2.2) The input parameters accepted by this call include >>> * sinfo_stream, sinfo_flags, sinfo_ppid, sinfo_context, >>> - * sinfo_timetolive. The user must provide the sinfo_assoc_id field in >>> + * sinfo_pr_policy. The user must provide the sinfo_assoc_id field in >>> * to this call if the caller is using the UDP model. >>> * >>> * For getsockopt, it get the default sctp_sndrcvinfo structure. >>> @@ -4854,13 +4858,15 @@ static int sctp_getsockopt_default_send_param(struct sock *sk, >>> info.sinfo_flags = asoc->default_flags; >>> info.sinfo_ppid = asoc->default_ppid; >>> info.sinfo_context = asoc->default_context; >>> - info.sinfo_timetolive = asoc->default_timetolive; >>> + info.sinfo_pr_policy = asoc->default_pr_policy; >>> + info.sinfo_pr_value = asoc->default_pr_value; >>> } else { >>> info.sinfo_stream = sp->default_stream; >>> info.sinfo_flags = sp->default_flags; >>> info.sinfo_ppid = sp->default_ppid; >>> info.sinfo_context = sp->default_context; >>> - info.sinfo_timetolive = sp->default_timetolive; >>> + info.sinfo_pr_policy = sp->default_pr_policy; >>> + info.sinfo_pr_value = sp->default_pr_value; >>> } >>> >>> if (put_user(len, optlen)) >>> @@ -6107,10 +6113,17 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, >>> (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); >>> >>> /* Minimally, validate the sinfo_flags. */ >>> + >>> + /* TODO this validation does not work with the new >>> + * SCTP_PR_SCTP_XXX flags >>> + */ >>> + >>> + /* >>> if (cmsgs->info->sinfo_flags & >>> ~(SCTP_UNORDERED | SCTP_ADDR_OVER | >>> SCTP_ABORT | SCTP_EOF)) >>> return -EINVAL; >>> + */ >>> break; >>> >>> default: >>> diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c >>> index 5f186ca..2c6f111 100644 >>> --- a/net/sctp/ulpevent.c >>> +++ b/net/sctp/ulpevent.c >>> @@ -948,7 +948,8 @@ void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event, >>> sinfo.sinfo_context = event->asoc->default_rcv_context; >>> >>> /* These fields are not used while receiving. */ >>> - sinfo.sinfo_timetolive = 0; >>> + sinfo.sinfo_pr_policy = 0; >>> + sinfo.sinfo_pr_value = 0; >>> >>> put_cmsg(msghdr, IPPROTO_SCTP, SCTP_SNDRCV, >>> sizeof(struct sctp_sndrcvinfo), (void *)&sinfo); >>> >>> >>> >>> diff --git a/src/func_tests/Makefile.am b/src/func_tests/Makefile.am >>> index b985685..a7167d5 100644 >>> --- a/src/func_tests/Makefile.am >>> +++ b/src/func_tests/Makefile.am >>> @@ -5,7 +5,7 @@ include $(top_srcdir)/Makefile.rules >>> include $(top_srcdir)/Makefile.dirs >>> >>> # General compilation flags >>> -INCLUDES = -I. -I$(top_srcdir)/src/include -I$(top_srcdir)/src/testlib >>> +INCLUDES = -I. -I$(top_srcdir)/src/include -I$(top_srcdir)/src/testlib >>> AM_CFLAGS = -g -Wall -Wstrict-prototypes -Wimplicit-function-declaration >>> AM_LDFLAGS = -lpthread >>> LDADD = $(top_builddir)/src/lib/libsctp.la \ >>> @@ -27,6 +27,7 @@ PASSING_KERN_TESTS = \ >>> test_connectx \ >>> test_recvmsg \ >>> test_timetolive \ >>> + test_rtxtolive \ >>> test_sctp_sendrecvmsg \ >>> test_getname \ >>> test_tcp_style\ >>> @@ -55,6 +56,7 @@ PASSING_V6_KERN_TESTS = \ >>> test_inaddr_any_v6 \ >>> test_peeloff_v6 \ >>> test_timetolive_v6 \ >>> + test_rtxtolive_v6 \ >>> test_sctp_sendrecvmsg_v6 \ >>> test_getname_v6 \ >>> test_tcp_style_v6 >>> @@ -102,21 +104,22 @@ v6test: ${PASSING_V6_KERN_TESTS} >>> @echo "Hoody hoo!" >>> >>> # Specifying the sources >>> -test_assoc_abort_SOURCES = test_assoc_abort.c >>> -test_assoc_shutdown_SOURCES = test_assoc_shutdown.c >>> -test_autoclose_SOURCES = test_autoclose.c >>> -test_basic_SOURCES = test_basic.c >>> -test_fragments_SOURCES = test_fragments.c >>> -test_inaddr_any_SOURCES = test_inaddr_any.c >>> -test_peeloff_SOURCES = test_peeloff.c >>> -test_sockopt_SOURCES = test_sockopt.c >>> -test_connect_SOURCES = test_connect.c >>> -test_connectx_SOURCES = test_connectx.c >>> -test_recvmsg_SOURCES = test_recvmsg.c >>> +test_assoc_abort_SOURCES = test_assoc_abort.c >>> +test_assoc_shutdown_SOURCES = test_assoc_shutdown.c >>> +test_autoclose_SOURCES = test_autoclose.c >>> +test_basic_SOURCES = test_basic.c >>> +test_fragments_SOURCES = test_fragments.c >>> +test_inaddr_any_SOURCES = test_inaddr_any.c >>> +test_peeloff_SOURCES = test_peeloff.c >>> +test_sockopt_SOURCES = test_sockopt.c >>> +test_connect_SOURCES = test_connect.c >>> +test_connectx_SOURCES = test_connectx.c >>> +test_recvmsg_SOURCES = test_recvmsg.c >>> test_timetolive_SOURCES = test_timetolive.c >>> +test_rtxtolive_SOURCES = test_rtxtolive.c >>> test_sctp_sendrecvmsg_SOURCES = test_sctp_sendrecvmsg.c >>> -test_getname_SOURCES = test_getname.c >>> -test_tcp_style_SOURCES = test_tcp_style.c >>> +test_getname_SOURCES = test_getname.c >>> +test_tcp_style_SOURCES = test_tcp_style.c >>> >>> test_1_to_1_socket_bind_listen_SOURCES = test_1_to_1_socket_bind_listen.c >>> test_1_to_1_accept_close_SOURCES = test_1_to_1_accept_close.c >>> @@ -157,6 +160,9 @@ test_peeloff_v6_CFLAGS = ${V6FLAGS} >>> test_timetolive_v6_SOURCES = test_timetolive.c >>> test_timetolive_v6_CFLAGS = ${V6FLAGS} >>> >>> +test_rtxtolive_v6_SOURCES = test_rtxtolive.c >>> +test_rtxtolive_v6_CFLAGS = ${V6FLAGS} >>> + >>> test_sctp_sendrecvmsg_v6_SOURCES = test_sctp_sendrecvmsg.c >>> test_sctp_sendrecvmsg_v6_CFLAGS = ${V6FLAGS} >>> >>> diff --git a/src/func_tests/test_rtxtolive.c b/src/func_tests/test_rtxtolive.c >>> new file mode 100644 >>> index 0000000..9aa03ad >>> --- /dev/null >>> +++ b/src/func_tests/test_rtxtolive.c >>> @@ -0,0 +1,410 @@ >>> +/* SCTP kernel Implementation >>> + * (C) Copyright IBM Corp. 2001, 2003 >>> + * Copyright (c) 1999-2000 Cisco, Inc. >>> + * Copyright (c) 1999-2001 Motorola, Inc. >>> + * Copyright (c) 2001 Intel Corp. >>> + * Copyright (c) 2001 Nokia, Inc. >>> + * >>> + * The SCTP implementation is free software; >>> + * you can redistribute it and/or modify it under the terms of >>> + * the GNU General Public License as published by >>> + * the Free Software Foundation; either version 2, or (at your option) >>> + * any later version. >>> + * >>> + * The SCTP implementation is distributed in the hope that it >>> + * will be useful, but WITHOUT ANY WARRANTY; without even the implied >>> + * ************************ >>> + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. >>> + * See the GNU General Public License for more details. >>> + * >>> + * You should have received a copy of the GNU General Public License >>> + * along with GNU CC; see the file COPYING. If not, write to >>> + * the Free Software Foundation, 59 Temple Place - Suite 330, >>> + * Boston, MA 02111-1307, USA. >>> + * >>> + * Please send any bug reports or fixes you make to the >>> + * email address(es): >>> + * lksctp developers <lksctp-developers@xxxxxxxxxxxxxxxxxxxxx> >>> + * >>> + * Or submit a bug report through the following website: >>> + * http://www.sf.net/projects/lksctp >>> + * >>> + * Any bugs reported to us we will try to fix... any fixes shared will >>> + * be incorporated into the next SCTP release. >>> + * >>> + * Written or modified by: >>> + * Jon Grimm <jgrimm@xxxxxxxxxx> >>> + * Sridhar Samudrala <sri@xxxxxxxxxx> >>> + */ >>> + >>> +/* >>> + * This is a basic functional test for the SCTP kernel >>> + * implementation of sndrcvinfo.sinfo_pr_value. >>> + * >>> + * 1) Create two sockets, the listening socket sets its RECVBUF small >>> + * 2) Create a connection. Send enough data to the non-reading listener >>> + * to fill the RCVBUF. >>> + * 5) Set sinfo_pr_value with SCTP_PR_SCTP_TTL policy on a message and send. >>> + * 6) Disable sinfo_pr_value on a message and send. >>> + * 7) Wait sinfo_pr_value time. >>> + * 8) Read out all the data at the receiver. >>> + * 9) Make sure timed out message did not make it. >>> + * 10) Make sure that the message with no timeout makes it to the receiver. >>> + * >>> + * Also test with SEND_FAILED notifications. Also, use a fragmented >>> + * message so as to also exercise the SEND_FAILED of fragmentation >>> + * code. >>> + */ >>> + >>> +#include <stdio.h> >>> +#include <unistd.h> >>> +#include <stdlib.h> >>> +#include <string.h> >>> +#include <sys/types.h> >>> +#include <sys/socket.h> >>> +#include <sys/uio.h> >>> +#include <netinet/in.h> >>> +#include <sys/errno.h> >>> +#include <errno.h> >>> +#include <netinet/sctp.h> >>> +#include <sctputil.h> >>> + >>> +char *TCID = __FILE__; >>> +int TST_TOTAL = 6; >>> +int TST_CNT = 0; >>> + >>> +/* This is the size of our RCVBUF */ >>> +#define SMALL_RCVBUF 3000 >>> + >>> +/* MAX segment size */ >>> +#define SMALL_MAXSEG 100 >>> + >>> +/* RWND_SLOP is the extra data that fills up the rwnd */ >>> +#define RWND_SLOP 100 >>> +static char *fillmsg = NULL; >>> +static char *ttlmsg = "This should time out!\n"; >>> +static char *nottlmsg = "This should NOT time out!\n"; >>> +static char ttlfrag[SMALL_MAXSEG*3] = {0}; >>> +static char *message = "Hello world\n"; >>> + >>> +int main(int argc, char *argv[]) >>> +{ >>> + int sk1, sk2; >>> + sockaddr_storage_t loop1; >>> + sockaddr_storage_t loop2; >>> + struct iovec iov; >>> + struct msghdr inmessage; >>> + struct msghdr outmessage; >>> + char incmsg[CMSG_SPACE(sizeof(sctp_cmsg_data_t))]; >>> + char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; >>> + struct cmsghdr *cmsg; >>> + struct sctp_sndrcvinfo *sinfo; >>> + struct iovec out_iov; >>> + int error; >>> + int pf_class, af_family; >>> + uint32_t ppid; >>> + uint32_t stream; >>> + sctp_assoc_t associd1, associd2; >>> + struct sctp_assoc_change *sac; >>> + struct sctp_event_subscribe subscribe; >>> + char *big_buffer; >>> + int offset; >>> + struct sctp_send_failed *ssf; >>> + int len; /* Really becomes 2xlen when set. */ >>> + int orig_len; >>> + struct sctp_status gstatus; >>> + >>> + /* Rather than fflush() throughout the code, set stdout to >>> + * be unbuffered. >>> + */ >>> + setvbuf(stdout, NULL, _IONBF, 0); >>> + >>> + /* Set some basic values which depend on the address family. */ >>> +#if TEST_V6 >>> + pf_class = PF_INET6; >>> + af_family = AF_INET6; >>> + >>> + loop1.v6.sin6_family = AF_INET6; >>> + loop1.v6.sin6_addr = in6addr_loopback; >>> + loop1.v6.sin6_port = htons(SCTP_TESTPORT_1); >>> + >>> + loop2.v6.sin6_family = AF_INET6; >>> + loop2.v6.sin6_addr = in6addr_loopback; >>> + loop2.v6.sin6_port = htons(SCTP_TESTPORT_2); >>> +#else >>> + pf_class = PF_INET; >>> + af_family = AF_INET; >>> + >>> + loop1.v4.sin_family = AF_INET; >>> + loop1.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; >>> + loop1.v4.sin_port = htons(SCTP_TESTPORT_1); >>> + >>> + loop2.v4.sin_family = AF_INET; >>> + loop2.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; >>> + loop2.v4.sin_port = htons(SCTP_TESTPORT_2); >>> +#endif /* TEST_V6 */ >>> + >>> + /* Create the two endpoints which will talk to each other. */ >>> + sk1 = test_socket(pf_class, SOCK_SEQPACKET, IPPROTO_SCTP); >>> + sk2 = test_socket(pf_class, SOCK_SEQPACKET, IPPROTO_SCTP); >>> + >>> + len = sizeof(int); >>> + error = getsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &orig_len, >>> + &len); >>> + if (error) >>> + tst_brkm(TBROK, tst_exit, "can't get rcvbuf size: %s", >>> + strerror(errno)); >>> + /* Set the MAXSEG to something smallish. */ >>> + { >>> + int val = SMALL_MAXSEG; >>> + test_setsockopt(sk1, SCTP_MAXSEG, &val, sizeof(val)); >>> + } >>> + >>> + memset(&subscribe, 0, sizeof(subscribe)); >>> + subscribe.sctp_data_io_event = 1; >>> + subscribe.sctp_association_event = 1; >>> + subscribe.sctp_send_failure_event = 1; >>> + test_setsockopt(sk1, SCTP_EVENTS, &subscribe, sizeof(subscribe)); >>> + test_setsockopt(sk2, SCTP_EVENTS, &subscribe, sizeof(subscribe)); >>> + >>> + /* Bind these sockets to the test ports. */ >>> + test_bind(sk1, &loop1.sa, sizeof(loop1)); >>> + test_bind(sk2, &loop2.sa, sizeof(loop2)); >>> + >>> + /* >>> + * This code sets the associations RWND very small so we can >>> + * fill it. It does this by manipulating the rcvbuf as follows: >>> + * 1) Reduce the rcvbuf size on the socket >>> + * 2) create an association so that we advertize rcvbuf/2 as >>> + * our initial rwnd >>> + * 3) raise the rcvbuf value so that we don't drop data wile >>> + * receiving later data >>> + */ >>> + len = SMALL_RCVBUF; >>> + error = setsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &len, >>> + sizeof(len)); >>> + if (error) >>> + tst_brkm(TBROK, tst_exit, "setsockopt(SO_RCVBUF): %s", >>> + strerror(errno)); >>> + >>> + /* Mark sk2 as being able to accept new associations. */ >>> + test_listen(sk2, 1); >>> + >>> + /* Send the first message. This will create the association. */ >>> + outmessage.msg_name = &loop2; >>> + outmessage.msg_namelen = sizeof(loop2); >>> + outmessage.msg_iov = &out_iov; >>> + outmessage.msg_iovlen = 1; >>> + outmessage.msg_control = outcmsg; >>> + outmessage.msg_controllen = sizeof(outcmsg); >>> + outmessage.msg_flags = 0; >>> + cmsg = CMSG_FIRSTHDR(&outmessage); >>> + cmsg->cmsg_level = IPPROTO_SCTP; >>> + cmsg->cmsg_type = SCTP_SNDRCV; >>> + cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); >>> + outmessage.msg_controllen = cmsg->cmsg_len; >>> + sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); >>> + memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo)); >>> + ppid = rand(); /* Choose an arbitrary value. */ >>> + stream = 1; >>> + sinfo->sinfo_ppid = ppid; >>> + sinfo->sinfo_stream = stream; >>> + outmessage.msg_iov->iov_base = message; >>> + outmessage.msg_iov->iov_len = strlen(message) + 1; >>> + test_sendmsg(sk1, &outmessage, 0, strlen(message)+1); >>> + >>> + /* Initialize inmessage for all receives. */ >>> + big_buffer = test_malloc(REALLY_BIG); >>> + memset(&inmessage, 0, sizeof(inmessage)); >>> + iov.iov_base = big_buffer; >>> + iov.iov_len = REALLY_BIG; >>> + inmessage.msg_iov = &iov; >>> + inmessage.msg_iovlen = 1; >>> + inmessage.msg_control = incmsg; >>> + >>> + /* Get the communication up message on sk2. */ >>> + inmessage.msg_controllen = sizeof(incmsg); >>> + error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); >>> + test_check_msg_notification(&inmessage, error, >>> + sizeof(struct sctp_assoc_change), >>> + SCTP_ASSOC_CHANGE, SCTP_COMM_UP); >>> + sac = (struct sctp_assoc_change *)iov.iov_base; >>> + associd2 = sac->sac_assoc_id; >>> + >>> + /* Get the communication up message on sk1. */ >>> + inmessage.msg_controllen = sizeof(incmsg); >>> + error = test_recvmsg(sk1, &inmessage, MSG_WAITALL); >>> + test_check_msg_notification(&inmessage, error, >>> + sizeof(struct sctp_assoc_change), >>> + SCTP_ASSOC_CHANGE, SCTP_COMM_UP); >>> + sac = (struct sctp_assoc_change *)iov.iov_base; >>> + associd1 = sac->sac_assoc_id; >>> + >>> + /* restore the rcvbuffer size for the receiving socket */ >>> + error = setsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &orig_len, >>> + sizeof(orig_len)); >>> + >>> + if (error) >>> + tst_brkm(TBROK, tst_exit, "setsockopt(SO_RCVBUF): %s", >>> + strerror(errno)); >>> + >>> + /* Get the first data message which was sent. */ >>> + inmessage.msg_controllen = sizeof(incmsg); >>> + error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); >>> + test_check_msg_data(&inmessage, error, strlen(message) + 1, >>> + MSG_EOR, stream, ppid); >>> + >>> + /* Figure out how big to make our fillmsg */ >>> + len = sizeof(struct sctp_status); >>> + memset(&gstatus,0,sizeof(struct sctp_status)); >>> + gstatus.sstat_assoc_id = associd1; >>> + error = getsockopt(sk1, IPPROTO_SCTP, SCTP_STATUS, &gstatus, &len); >>> + >>> + if (error) >>> + tst_brkm(TBROK, tst_exit, "can't get rwnd size: %s", >>> + strerror(errno)); >>> + tst_resm(TINFO, "Creating fillmsg of size %d", >>> + gstatus.sstat_rwnd+RWND_SLOP); >>> + fillmsg = malloc(gstatus.sstat_rwnd+RWND_SLOP); >>> + >>> + /* Send a fillmsg */ >>> + outmessage.msg_controllen = sizeof(outcmsg); >>> + outmessage.msg_flags = 0; >>> + cmsg = CMSG_FIRSTHDR(&outmessage); >>> + cmsg->cmsg_level = IPPROTO_SCTP; >>> + cmsg->cmsg_type = SCTP_SNDRCV; >>> + cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); >>> + outmessage.msg_controllen = cmsg->cmsg_len; >>> + sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); >>> + memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo)); >>> + ppid++; >>> + stream++; >>> + sinfo->sinfo_ppid = ppid; >>> + sinfo->sinfo_stream = stream; >>> + memset(fillmsg, 'X', gstatus.sstat_rwnd+RWND_SLOP); >>> + fillmsg[gstatus.sstat_rwnd+RWND_SLOP-1] = '\0'; >>> + outmessage.msg_iov->iov_base = fillmsg; >>> + outmessage.msg_iov->iov_len = gstatus.sstat_rwnd+RWND_SLOP; >>> + outmessage.msg_name = NULL; >>> + outmessage.msg_namelen = 0; >>> + sinfo->sinfo_assoc_id = associd1; >>> + sinfo->sinfo_pr_policy = SCTP_PR_SCTP_NONE; >>> + sinfo->sinfo_pr_value = 0; >>> + test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, >>> + gstatus.sstat_rwnd+RWND_SLOP); >>> + >>> + /* Now send the message with timeout. */ >>> + sinfo->sinfo_ppid = ppid; >>> + sinfo->sinfo_stream = stream; >>> + outmessage.msg_iov->iov_base = ttlmsg; >>> + outmessage.msg_iov->iov_len = strlen(ttlmsg) + 1; >>> + outmessage.msg_name = NULL; >>> + outmessage.msg_namelen = 0; >>> + sinfo->sinfo_assoc_id = associd1; >>> + sinfo->sinfo_pr_policy = SCTP_PR_SCTP_RTX; >>> + sinfo->sinfo_pr_value = 2; >>> + test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, strlen(ttlmsg) + 1); >>> + >>> + tst_resm(TPASS, "Send a message with timeout"); >>> + >>> + /* Next send a message with no timeout. */ >>> + sinfo->sinfo_ppid = ppid; >>> + sinfo->sinfo_stream = stream; >>> + outmessage.msg_iov->iov_base = nottlmsg; >>> + outmessage.msg_iov->iov_len = strlen(nottlmsg) + 1; >>> + outmessage.msg_name = NULL; >>> + outmessage.msg_namelen = 0; >>> + sinfo->sinfo_assoc_id = associd1; >>> + sinfo->sinfo_pr_policy = SCTP_PR_SCTP_NONE; >>> + sinfo->sinfo_pr_value = 0; >>> + test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, strlen(nottlmsg)+1); >>> + >>> + tst_resm(TPASS, "Send a message with no timeout"); >>> + >>> + /* And finally a fragmented message that will time out. */ >>> + sinfo->sinfo_ppid = ppid; >>> + sinfo->sinfo_stream = stream; >>> + memset(ttlfrag, '0', sizeof(ttlfrag)); >>> + ttlfrag[sizeof(ttlfrag)-1] = '\0'; >>> + outmessage.msg_iov->iov_base = ttlfrag; >>> + outmessage.msg_iov->iov_len = sizeof(ttlfrag); >>> + outmessage.msg_name = NULL; >>> + outmessage.msg_namelen = 0; >>> + sinfo->sinfo_assoc_id = associd1; >>> + sinfo->sinfo_pr_policy = SCTP_PR_SCTP_RTX; >>> + sinfo->sinfo_pr_value = 2; >>> + test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, sizeof(ttlfrag)); >>> + >>> + tst_resm(TPASS, "Send a fragmented message with timeout"); >>> + >>> + /* Sleep waiting for the message to time out. */ >>> + tst_resm(TINFO, " ** SLEEPING for 3 seconds **"); >>> + sleep(3); >>> + >>> + /* Read the fillmsg snuck in between the ttl'd messages. */ >>> + do { >>> + inmessage.msg_controllen = sizeof(incmsg); >>> + error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); >>> + } while (!(inmessage.msg_flags & MSG_EOR)); >>> + >>> + /* Now get the message that did NOT time out. */ >>> + inmessage.msg_controllen = sizeof(incmsg); >>> + error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); >>> + test_check_msg_data(&inmessage, error, strlen(nottlmsg) + 1, >>> + MSG_EOR, stream, ppid); >>> + if (0 != strncmp(iov.iov_base, nottlmsg, strlen(nottlmsg)+1)) >>> + tst_brkm(TBROK, tst_exit, "Received Wrong Message !!!"); >>> + >>> + tst_resm(TPASS, "Receive message with no timeout"); >>> + >>> + /* Get the SEND_FAILED notification for the message that DID >>> + * time out. >>> + */ >>> + inmessage.msg_controllen = sizeof(incmsg); >>> + error = test_recvmsg(sk1, &inmessage, MSG_WAITALL); >>> + test_check_msg_notification(&inmessage, error, >>> + sizeof(struct sctp_send_failed) + >>> + strlen(ttlmsg) + 1, >>> + SCTP_SEND_FAILED, 0); >>> + ssf = (struct sctp_send_failed *)iov.iov_base; >>> + if (0 != strncmp(ttlmsg, (char *)ssf->ssf_data, strlen(ttlmsg) + 1)) >>> + tst_brkm(TBROK, tst_exit, "SEND_FAILED data mismatch"); >>> + >>> + tst_resm(TPASS, "Receive SEND_FAILED for message with timeout"); >>> + >>> + /* Get the SEND_FAILED notification for the fragmented message that >>> + * DID time out. >>> + */ >>> + offset = 0; >>> + do { >>> + inmessage.msg_controllen = sizeof(incmsg); >>> + error = test_recvmsg(sk1, &inmessage, MSG_WAITALL); >>> + test_check_msg_notification(&inmessage, error, >>> + sizeof(struct sctp_send_failed) + >>> + SMALL_MAXSEG, >>> + SCTP_SEND_FAILED, 0); >>> + ssf = (struct sctp_send_failed *)iov.iov_base; >>> + if (0 != strncmp(&ttlfrag[offset], (char *)ssf->ssf_data, >>> + SMALL_MAXSEG)) >>> + tst_brkm(TBROK, tst_exit, "SEND_FAILED data mismatch"); >>> + offset += SMALL_MAXSEG; >>> + } while (!(ssf->ssf_info.sinfo_flags & 0x01)); /* LAST_FRAG */ >>> + >>> + tst_resm(TPASS, "Receive SEND_FAILED for fragmented message with " >>> + "timeout"); >>> + >>> + /* Shut down the link. */ >>> + close(sk1); >>> + >>> + /* Get the shutdown complete notification. */ >>> + inmessage.msg_controllen = sizeof(incmsg); >>> + error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); >>> + test_check_msg_notification(&inmessage, error, >>> + sizeof(struct sctp_assoc_change), >>> + SCTP_ASSOC_CHANGE, SCTP_SHUTDOWN_COMP); >>> + >>> + close(sk2); >>> + >>> + /* Indicate successful completion. */ >>> + return 0; >>> +} >>> diff --git a/src/func_tests/test_sctp_sendrecvmsg.c b/src/func_tests/test_sctp_sendrecvmsg.c >>> index c275e45..aaa56e9 100644 >>> --- a/src/func_tests/test_sctp_sendrecvmsg.c >>> +++ b/src/func_tests/test_sctp_sendrecvmsg.c >>> @@ -243,7 +243,7 @@ int main(int argc, char *argv[]) >>> /* Now send a message that will timeout. */ >>> test_sctp_sendmsg(sk1, ttlmsg, strlen(ttlmsg) + 1, >>> (struct sockaddr *)&loop2, sizeof(loop2), >>> - ppid, 0, stream, 2000, 0); >>> + ppid, SCTP_PR_SCTP_TTL, stream, 2000, 0); >>> >>> tst_resm(TPASS, "sctp_sendmsg with ttl"); >>> >>> @@ -259,7 +259,7 @@ int main(int argc, char *argv[]) >>> ttlfrag[sizeof(ttlfrag)-1] = '\0'; >>> test_sctp_sendmsg(sk1, ttlfrag, sizeof(ttlfrag), >>> (struct sockaddr *)&loop2, sizeof(loop2), >>> - ppid, 0, stream, 2000, 0); >>> + ppid, SCTP_PR_SCTP_TTL, stream, 2000, 0); >>> >>> tst_resm(TPASS, "sctp_sendmsg fragmented msg with ttl"); >>> >>> @@ -335,7 +335,8 @@ int main(int argc, char *argv[]) >>> snd_sinfo.sinfo_ppid = rand(); >>> snd_sinfo.sinfo_flags = 0; >>> snd_sinfo.sinfo_stream = 2; >>> - snd_sinfo.sinfo_timetolive = 0; >>> + snd_sinfo.sinfo_pr_policy = SCTP_PR_SCTP_NONE; >>> + snd_sinfo.sinfo_pr_value = 0; >>> snd_sinfo.sinfo_assoc_id = associd1; >>> test_sctp_send(sk1, message, strlen(message) + 1, &snd_sinfo, >>> MSG_NOSIGNAL); >>> diff --git a/src/func_tests/test_timetolive.c b/src/func_tests/test_timetolive.c >>> index d9bdf1b..dc66722 100644 >>> --- a/src/func_tests/test_timetolive.c >>> +++ b/src/func_tests/test_timetolive.c >>> @@ -39,14 +39,14 @@ >>> >>> /* >>> * This is a basic functional test for the SCTP kernel >>> - * implementation of sndrcvinfo.sinfo_timetolive. >>> + * implementation of sndrcvinfo.sinfo_pr_value. >>> * >>> * 1) Create two sockets, the listening socket sets its RECVBUF small >>> * 2) Create a connection. Send enough data to the non-reading listener >>> * to fill the RCVBUF. >>> - * 5) Set sinfo_timetolive on a message and send. >>> - * 6) Disable sinfo_timetolive on a message and send. >>> - * 7) Wait sinfo_timetolive. >>> + * 5) Set sinfo_pr_value with SCTP_PR_SCTP_TTL policy on a message and send. >>> + * 6) Disable sinfo_pr_value on a message and send. >>> + * 7) Wait sinfo_pr_value time. >>> * 8) Read out all the data at the receiver. >>> * 9) Make sure timed out message did not make it. >>> * 10) Make sure that the message with no timeout makes it to the receiver. >>> @@ -288,7 +288,8 @@ int main(int argc, char *argv[]) >>> outmessage.msg_name = NULL; >>> outmessage.msg_namelen = 0; >>> sinfo->sinfo_assoc_id = associd1; >>> - sinfo->sinfo_timetolive = 0; >>> + sinfo->sinfo_pr_policy = SCTP_PR_SCTP_NONE; >>> + sinfo->sinfo_pr_value = 0; >>> test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, >>> gstatus.sstat_rwnd+RWND_SLOP); >>> >>> @@ -300,7 +301,8 @@ int main(int argc, char *argv[]) >>> outmessage.msg_name = NULL; >>> outmessage.msg_namelen = 0; >>> sinfo->sinfo_assoc_id = associd1; >>> - sinfo->sinfo_timetolive = 2000; >>> + sinfo->sinfo_pr_policy = SCTP_PR_SCTP_TTL; >>> + sinfo->sinfo_pr_value = 2000; >>> test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, strlen(ttlmsg) + 1); >>> >>> tst_resm(TPASS, "Send a message with timeout"); >>> @@ -313,7 +315,8 @@ int main(int argc, char *argv[]) >>> outmessage.msg_name = NULL; >>> outmessage.msg_namelen = 0; >>> sinfo->sinfo_assoc_id = associd1; >>> - sinfo->sinfo_timetolive = 0; >>> + sinfo->sinfo_pr_policy = SCTP_PR_SCTP_NONE; >>> + sinfo->sinfo_pr_value = 0; >>> test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, strlen(nottlmsg)+1); >>> >>> tst_resm(TPASS, "Send a message with no timeout"); >>> @@ -328,7 +331,8 @@ int main(int argc, char *argv[]) >>> outmessage.msg_name = NULL; >>> outmessage.msg_namelen = 0; >>> sinfo->sinfo_assoc_id = associd1; >>> - sinfo->sinfo_timetolive = 2000; >>> + sinfo->sinfo_pr_policy = SCTP_PR_SCTP_TTL; >>> + sinfo->sinfo_pr_value = 2000; >>> test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, sizeof(ttlfrag)); >>> >>> tst_resm(TPASS, "Send a fragmented message with timeout"); >>> diff --git a/src/include/netinet/sctp.h b/src/include/netinet/sctp.h >>> index ae557a5..5a6cea2 100644 >>> --- a/src/include/netinet/sctp.h >>> +++ b/src/include/netinet/sctp.h >>> @@ -184,9 +184,10 @@ struct sctp_sndrcvinfo { >>> __u16 sinfo_stream; >>> __u16 sinfo_ssn; >>> __u16 sinfo_flags; >>> + __u16 sinfo_pr_policy; >>> __u32 sinfo_ppid; >>> __u32 sinfo_context; >>> - __u32 sinfo_timetolive; >>> + __u32 sinfo_pr_value; >>> __u32 sinfo_tsn; >>> __u32 sinfo_cumtsn; >>> sctp_assoc_t sinfo_assoc_id; >>> @@ -200,12 +201,25 @@ struct sctp_sndrcvinfo { >>> */ >>> >>> enum sctp_sinfo_flags { >>> - SCTP_UNORDERED = 1, /* Send/receive message unordered. */ >>> - SCTP_ADDR_OVER = 2, /* Override the primary destination. */ >>> - SCTP_ABORT=4, /* Send an ABORT message to the peer. */ >>> - SCTP_EOF=MSG_FIN, /* Initiate graceful shutdown process. */ >>> + SCTP_EOF = MSG_FIN, /* Initiate graceful shutdown process. */ >>> + SCTP_UNORDERED = 0x0400, /* Send/receive message unordered. */ >>> + SCTP_ADDR_OVER = 0x0800, /* Override the primary destination. */ >>> + SCTP_ABORT = 0x1000, /* Send an ABORT message to the peer. */ >>> }; >>> >>> +/* >>> + * sinfo_pr_policy: 16 bits (unsigned integer) >>> + * >>> + * This field may contain the partial reliability used to >>> + * send the message. >>> + */ >>> + >>> +enum sctp_sinfo_pr_policy { >>> + SCTP_PR_SCTP_NONE = 0x0000, /* Reliable transmission */ >>> + SCTP_PR_SCTP_TTL = 0x0001, /* Timed partial reliable */ >>> + SCTP_PR_SCTP_BUF = 0x0002, /* Buffer parital reliable */ >>> + SCTP_PR_SCTP_RTX = 0x0003, /* Retransmist partial reliable */ >>> +}; >>> >>> typedef union { >>> __u8 raw; >>> @@ -816,7 +830,7 @@ int sctp_freeladdrs(struct sockaddr *addrs); >>> */ >>> int sctp_sendmsg(int s, const void *msg, size_t len, struct sockaddr *to, >>> socklen_t tolen, uint32_t ppid, uint32_t flags, >>> - uint16_t stream_no, uint32_t timetolive, uint32_t context); >>> + uint16_t stream_no, uint32_t pr_value, uint32_t context); >>> >>> /* This library function assist the user with sending a message without >>> * dealing directly with the CMSG header. >>> diff --git a/src/lib/sendmsg.c b/src/lib/sendmsg.c >>> index 1de592d..a674646 100644 >>> --- a/src/lib/sendmsg.c >>> +++ b/src/lib/sendmsg.c >>> @@ -31,7 +31,7 @@ >>> int >>> sctp_sendmsg(int s, const void *msg, size_t len, struct sockaddr *to, >>> socklen_t tolen, uint32_t ppid, uint32_t flags, >>> - uint16_t stream_no, uint32_t timetolive, uint32_t context) >>> + uint16_t stream_no, uint32_t pr_value, uint32_t context) >>> { >>> struct msghdr outmsg; >>> struct iovec iov; >>> @@ -61,9 +61,22 @@ sctp_sendmsg(int s, const void *msg, size_t len, struct sockaddr *to, >>> sinfo->sinfo_ppid = ppid; >>> sinfo->sinfo_flags = flags; >>> sinfo->sinfo_stream = stream_no; >>> - sinfo->sinfo_timetolive = timetolive; >>> sinfo->sinfo_context = context; >>> >>> + sinfo->sinfo_pr_policy = sinfo->sinfo_flags & 0xff; >>> + sinfo->sinfo_pr_value = pr_value; >>> + >>> + printf("sinfo_flags: %x sinfo_pr_policy: %d sinfo_pr_value: %d\n", >>> + sinfo->sinfo_flags, sinfo->sinfo_pr_policy, sinfo->sinfo_pr_value); >>> + >>> + /* If we get an invalid sinfo_pr_policy force it to >>> + * SCTP_PR_SCTP_NONE or shall we better fail and set a >>> + * EINVAL error?? >>> + */ >>> + >>> + if(sinfo->sinfo_pr_policy > SCTP_PR_SCTP_RTX) >>> + sinfo->sinfo_pr_policy = SCTP_PR_SCTP_NONE; >>> + >>> return sendmsg(s, &outmsg, 0); >>> } >>> >>> diff --git a/src/testlib/sctputil.h b/src/testlib/sctputil.h >>> index 347c91b..0afbc36 100644 >>> --- a/src/testlib/sctputil.h >>> +++ b/src/testlib/sctputil.h >>> @@ -270,11 +270,11 @@ static inline int test_sctp_peeloff(int sk, sctp_assoc_t assoc_id) >>> static inline int test_sctp_sendmsg(int s, const void *msg, size_t len, >>> struct sockaddr *to, socklen_t tolen, >>> uint32_t ppid, uint32_t flags, >>> - uint16_t stream_no, uint32_t timetolive, >>> + uint16_t stream_no, uint32_t pr_value, >>> uint32_t context) >>> { >>> int error = sctp_sendmsg(s, msg, len, to, tolen, ppid, flags, stream_no, >>> - timetolive, context); >>> + pr_value, context); >>> if (len != error) >>> tst_brkm(TBROK, tst_exit, "sctp_sendmsg: error:%d errno:%d", >>> error, errno); >> > -- > To unsubscribe from this list: send the line "unsubscribe linux-sctp" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-sctp" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html