Re: [PATCH] Replace timetolive with pr_policy and pr_value

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Please ignore my previous patch set and check these instead...

Testing my own patch I realized that there is no way to set what PR
policy to use when using the sctp_sendmsg() call. Following examples
from FreeBSD SCTP implementation I modified my patch to allow setting
the PR policy as part of the flags passed to the call. For example to
send a message with timed reliability and unordered delivery we can
use:

sctp_sendmsg(sd, msg, len, to, tolen, rand(),
        SCTP_UNORDERED | SCTP_PR_SCTP_TTL, 2000, 0);


The scptsocket api draft says nothing about this but makes sense that
if we can set a pr_value we should be also be able to set the PR
policy too. All tests passed and got a nice "Hoody hoo!" message at
the end of both v4test and v6test tests.

I have some questions regarding my changes as I am new to Kernel development:

Seems to me that values assigned to SCTP_PR_SCTP_TTL, SCTP_PR_SCTP_RTX, etc..
are irrelevant to the receiver so we can assign any values to them that not
necessarily coincide with their values assigned in other
implementations. Still I made my best to make these values coincide
with FreeBSD implementation. What values shall I assign to these
variables??

I had to remove the sinfo_flags validation from the
sctp_msghdr_parse() call in socket.c file. Any tips on how to enable
it again but considering the additional PR policy flags is
appreciated.

Again I am not sure where is the best place to decrement the number of
retransmission when using the experimental SCTP_PR_SCTP_RTX policy.
And some guidance on how to implement a test for this functionality is
welcome.


I used these commands to create the diff files... not sure if it is
the correct way:

cd lksctp-dev
git diff -p origin... include/net/sctp > lksctp-dev-inc-pr.diff
git diff -p origin... net/sctp > lksctp-dev-src-pr.diff

cd lksctp-tools
git diff -p origin... > lksctp-tools-pr.diff


regards,
Horacio

On Wed, Dec 3, 2008 at 10:59 AM, Horacio Sanson <hsanson@xxxxxxxxx> wrote:
> Updated lksctp-dev and lksctp-tools to follow the most recent
> sctpsocket draft 18 by replacing all instances of timetolive from the
> sctp_sndrcvinfo structure with the sinfo_pr_policy and sinfo_pr_value
> fields. I ran the tests in lksctp-tools and to my surprise they all
> pass.
>
> This is the first time I have put my dirty hands on the holy kernel
> source so please expect to find mistakes all over the place. I also
> tried to implement the SCTP_PR_SCTP_RTX policy based on the FreeBSD
> implementation but I am not sure were exactly I should decrement the
> number of retransmission counter. I do it in the
> sctp_retransmit_mark() method but not really sure if is correct and I
> am not good enough to make a test for it. Some help here would be
> greatly appreciated.
>
>
> regards,
> Horacio
>
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;
 	__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;
 
 	__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;
 }
-              
+
 /*
  * 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 *);
 	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;
- 
+
 	/* 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..e98cc5b 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,20 @@ 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)
+		    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/outqueue.c b/net/sctp/outqueue.c
index 247ebc9..cce5bab 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -462,6 +462,13 @@ void sctp_retransmit_mark(struct sctp_outq *q,
 				transport->rto_pending = 0;
 			}
 
+                        /* If the sinfo_pr_policy is SCTP_PR_SCTP_RTX we have
+                         * to decrement the chunk expire_at value
+                         */
+                        if(chunk->msg->expires_policy == SCTP_PR_SCTP_RTX)
+                            chunk->msg->expires_at--;
+             
+
 			/* Move the chunk to the retransmit queue. The chunks
 			 * on the retransmit queue are always kept in order.
 			 */
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/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);

[Index of Archives]     [Linux Networking Development]     [Linux OMAP]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux