Re: [PATCH] lksctp: replace sinfo_timetolive with sinfo_pr_value.

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

 



On Thu, Dec 18, 2008 at 6:24 AM, Vlad Yasevich
<vladislav.yasevich@xxxxxx> wrote:
> Horacio Sanson wrote:
>> From: Horacio Sanson <hsanson@xxxxxxxxxxxxxxxxxx>
>>
>> Modified all relevant structures in all header and source files to
>> replace the deprecated sinfo_timetolive field with the newer
>> sinfo_pr_policy and sinfo_pr_value.
>>
>> Added a new sctp_sinfo_pr_policy enum that contains the different PR policy
>> definitions: SCTP_PR_SCTP_NONE and SCTP_PR_SCTP_TTL. And modified the
>> values of sctp_sinfo_flags so they use the higher byte only and leave the
>> lower byte free for sctp_pr_policy values.
>
> need you sign-off.
>

Done, just added "-s" to the commit command....

>> ---
>>  include/net/sctp/structs.h |   10 ++++++----
>>  include/net/sctp/user.h    |   22 +++++++++++++++++-----
>>  net/sctp/associola.c       |    3 ++-
>>  net/sctp/chunk.c           |   30 +++++++++++++++++++-----------
>>  net/sctp/output.c          |    2 +-
>>  net/sctp/socket.c          |   27 ++++++++++++++-------------
>>  net/sctp/ulpevent.c        |    3 ++-
>>  7 files changed, 61 insertions(+), 36 deletions(-)
>>
>> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
>> index 9661d7b..2a86944 100644
>> --- a/include/net/sctp/structs.h
>> +++ b/include/net/sctp/structs.h
>> @@ -281,8 +281,9 @@ struct sctp_sock {
>>       __u16 default_stream;
>>       __u32 default_ppid;
>>       __u16 default_flags;
>> +     __u16 default_pr_policy;
>>       __u32 default_context;
>> -     __u32 default_timetolive;
>> +     __u32 default_pr_value;
>>       __u32 default_rcv_context;
>>       int max_burst;
>>
>> @@ -626,13 +627,13 @@ struct sctp_datamsg {
>>       struct list_head track;
>>       /* Reference counting. */
>>       atomic_t refcnt;
>> +     /* Policy used to determine how expires_at is interpreted */
>> +     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 *,
>> @@ -1759,9 +1760,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..55ecc4a 100644
>> --- a/include/net/sctp/user.h
>> +++ b/include/net/sctp/user.h
>> @@ -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,23 @@ 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. */
>>  };
>>
>
> Why?

These values, except for SCTP_EOF, are exactly the same values used in
the FreeBSD implementation. This scheme allows the lower byte to be
used for sctp_sinfo_pr_policy values.

I modified all these flags so they coincide with FreeBSD
implementation that is also the same code base used for MacOSX and
Windows implementations to avoid any incompatibilities between
implementations. At least sinfo_pr_policy is transported between peers
in an association and having standard values is a good idea.

>
>> +/*
>> + *  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 */
>> +};
>>
>>  typedef union {
>>       __u8                    raw;
>> 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..d499962 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,17 @@ 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);
>> +                             break;
>> +             }
>
> The one problem with this approach is if the user is still using the older structure that might have
> value uninitialized.  I will most likely be 0, not 1, but also could be something entirely bogus if
> the user didn't zero-out the structure.  So, I think the TTL policy should be a default assumption and
> the sinfo_pr_value (equivalent to the old sinfo_timetoliv) needs to be checked to see if the TTL policy
> applies.
>
> Also, msg->expires_policy needs to be set only if sinfo_pr_policy is truly set correctly.
>

I need the ability to set sinfo_pr_policy to SCTP_PR_SCTP_TTL and
sinfo_pr_value equal to zero as a way to enable a completely
unreliable service (i.e. no retransmissions at all), similar to UDP
but with congestion control (maybe DCCP emulation??).

I believe this functionality added to unordered delivery can be useful
for several applications and allows SCTP to cover all the reliability
spectrum from ordered reliable, ordered unreliable, unordered
reliable, unordered unreliable, ordered partial reliable and unordered
partial reliable.

Another alternative would be to define a new partial reliability
profile, something like SCTP_PR_SCTP_UNR, that forces sinfo_pr_value
to zero and never retransmits.

About validating sinfo_pr_value and sinfo_pr_policy I added validating
code on the sctp_msghdr_parse method. I think this is the best place
to make this validation. This would also make sure that the user gets
an error message if the sinfo_pr_value or sinfo_pr_policy values are
not initialized correctly (me thinks).

>>       }
>>
>>       max = asoc->frag_point;
>> @@ -291,11 +295,15 @@ 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;
>> +                     break;
>> +     }
>>
>>       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..eef5842 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_value.  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;
>>       }
>>
>
> Need to do validation on the pr_policy value to make sure it's valid.

As mentioned above I added all this validations in a single place
(sctp_msghdr_parse).

>
>>       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;
>
> Initialize policy to the enum you defined.

done

>
>> +     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_value.  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))
>> @@ -6106,11 +6112,6 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg,
>>                       cmsgs->info =
>>                               (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
>>
>> -                     /* Minimally, validate the sinfo_flags. */
>> -                     if (cmsgs->info->sinfo_flags &
>> -                         ~(SCTP_UNORDERED | SCTP_ADDR_OVER |
>> -                           SCTP_ABORT | SCTP_EOF))
>> -                             return -EINVAL;
>
> Why?

The new sinfo_pr_policy flags caused this to fail. I have added a new
validation check and additionally added validation for sinfo_pr_policy
and sinfo_pr_value. See attached new patch.


regrads
Horacio

>
>>                       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);
>
>
> -vlad
>
From 43b17b6c73a0d72dd421b200fd3e8d4845cdf885 Mon Sep 17 00:00:00 2001
From: Horacio Sanson <hsanson@xxxxxxxxxxxxxxxxxx>
Date: Thu, 18 Dec 2008 18:57:51 +0900
Subject: [PATCH] lksctp: replace sinfo_timetolive with sinfo_pr_value.

Modified all relevant structures in all header and source files to
replace the deprecated sinfo_timetolive field with the newer
sinfo_pr_policy and sinfo_pr_value.

Added a new sctp_sinfo_pr_policy enum that contains the different PR policy
definitions: SCTP_PR_SCTP_NONE and SCTP_PR_SCTP_TTL. And modified the
values of sctp_sinfo_flags so they use the higher byte only and leave the
lower byte free for sctp_pr_policy values.
Signed-off-by: Horacio Sanson <horacio@xxxxxxxxxxxxxxxxxx>
---
 include/net/sctp/structs.h |   10 ++++++----
 include/net/sctp/user.h    |   22 +++++++++++++++++-----
 net/sctp/associola.c       |    3 ++-
 net/sctp/chunk.c           |   30 +++++++++++++++++++-----------
 net/sctp/output.c          |    2 +-
 net/sctp/socket.c          |   35 ++++++++++++++++++++++++-----------
 net/sctp/ulpevent.c        |    3 ++-
 7 files changed, 71 insertions(+), 34 deletions(-)

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 9661d7b..2a86944 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -281,8 +281,9 @@ struct sctp_sock {
 	__u16 default_stream;
 	__u32 default_ppid;
 	__u16 default_flags;
+	__u16 default_pr_policy;
 	__u32 default_context;
-	__u32 default_timetolive;
+	__u32 default_pr_value;
 	__u32 default_rcv_context;
 	int max_burst;
 
@@ -626,13 +627,13 @@ struct sctp_datamsg {
 	struct list_head track;
 	/* Reference counting. */
 	atomic_t refcnt;
+	/* Policy used to determine how expires_at is interpreted */
+	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 *,
@@ -1759,9 +1760,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..55ecc4a 100644
--- a/include/net/sctp/user.h
+++ b/include/net/sctp/user.h
@@ -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,23 @@ 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 */
+};
 
 typedef union {
 	__u8   			raw;
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..d499962 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,17 @@ 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);
+				break;
+		}
 	}
 
 	max = asoc->frag_point;
@@ -291,11 +295,15 @@ 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;
+			break;
+	}
 
 	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..a741c82 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_value.  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 = SCTP_PR_SCTP_NONE;
+	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_value.  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))
@@ -6106,11 +6112,18 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg,
 			cmsgs->info =
 				(struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
 
-			/* Minimally, validate the sinfo_flags. */
-			if (cmsgs->info->sinfo_flags &
+			if ((cmsgs->info->sinfo_flags & 0xff00) &
 			    ~(SCTP_UNORDERED | SCTP_ADDR_OVER |
-			      SCTP_ABORT | SCTP_EOF))
+			    SCTP_ABORT | SCTP_EOF))
 				return -EINVAL;
+
+			if(cmsgs->info->sinfo_pr_policy != SCTP_PR_SCTP_NONE &&
+			    cmsgs->info->sinfo_pr_policy != SCTP_PR_SCTP_TTL)
+				return -EINVAL;
+
+			if(cmsgs->info->sinfo_pr_value < 0)
+				return -EINVAL;
+
 			break;
 
 		default:
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 5f186ca..9517e47 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 = SCTP_PR_SCTP_NONE;
+	sinfo.sinfo_pr_value = 0;
 
 	put_cmsg(msghdr, IPPROTO_SCTP, SCTP_SNDRCV,
 		 sizeof(struct sctp_sndrcvinfo), (void *)&sinfo);
-- 
1.5.6.3


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

  Powered by Linux