lksctp: replace sinfo_timetolive with sinfo_pr_value.
Subsystems (2)
PATCH 1/1 lksctp: replace sinfo_timetolive with sinfo_pr_value.
From: Horacio Sanson <[email protected]>
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.
--- 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(-)
include/net/sctp/structs.h +6 -4
@@ -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;
include/net/sctp/user.h +17 -5
@@ -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;
net/sctp/associola.c +2 -1
@@ -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 */
net/sctp/chunk.c +19 -11
@@ -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 ; }
net/sctp/output.c +1 -1
@@ -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;
net/sctp/socket.c +14 -13
@@ -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 =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_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 ;break ;default :
net/sctp/ulpevent.c +2 -1
@@ -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);
Signature · 1 line
1.5.6.3
Quoted 10 lines · Horacio Sanson
From: Horacio Sanson <[email protected]>
Modified all relevant structures in all header and source files to replace the deprecated
sinfo_timetolivefield with the newersinfo_pr_policyandsinfo_pr_value.Added a new
sctp_sinfo_pr_policyenum that contains the different PR policy
definitions:SCTP_PR_SCTP_NONEandSCTP_PR_SCTP_TTL. And modified the values ofsctp_sinfo_flagsso they use the higher byte only and leave the lower byte free forsctp_pr_policyvalues.
need you sign-off.
Quoted 73 lines
--- 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(-)include/net/sctp/structs.h +6
-4@@ -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;include/net/sctp/user.h +2
-1@@ -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 {
include/net/sctp/user.h struct sctp_sndrcvinfo { · line 208
Quoted 10 lines
include/net/sctp/user.h +4
-4-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?
Quoted 53 lines
include/net/sctp/user.h +11
-0+/* +* 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;net/sctp/associola.c +2
-1@@ -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 */ net/sctp/chunk.c +2
-8@@ -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); +
net/sctp/chunk.c struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, · line 183
Quoted 10 lines
net/sctp/chunk.c +10
-0+ 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.
Quoted 65 lines
net/sctp/chunk.c +7
-3} 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 ; }net/sctp/output.c +1
-1@@ -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;net/sctp/socket.c +5
-3@@ -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;
net/sctp/socket.c static int sctp_setsockopt_default_send_param(struct sock *sk, · line 2577
Quoted 10 lines
net/sctp/socket.c +2
-1}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.
net/sctp/socket.c SCTP_STATIC int sctp_init_sock(struct sock *sk) · line 3530
Quoted 7 lines
net/sctp/socket.c +1
-1return 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.
Quoted 32 lines
net/sctp/socket.c +6
-3+ 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))
net/sctp/socket.c SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, · line 6112
Quoted 7 lines
net/sctp/socket.c +0
-5@@ -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?
Quoted 8 lines
net/sctp/socket.c +0
-0break ;default :net/sctp/ulpevent.c +0
-0
net/sctp/ulpevent.c void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event, · line 955
Quoted 9 lines
net/sctp/ulpevent.c +2
-1@@ -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
Quoted 7 lines · Vlad Yasevich
Quoted 6 lines · Horacio Sanson
From: Horacio Sanson <[email protected]>
Modified all relevant structures in all header and source files to replace the deprecated
sinfo_timetolivefield with the newersinfo_pr_policyandsinfo_pr_value.
Quoted 7 lines
Quoted 4 lines
Added a new
sctp_sinfo_pr_policyenum that contains the different PR policy
definitions:SCTP_PR_SCTP_NONEandSCTP_PR_SCTP_TTL. And modified the values ofsctp_sinfo_flagsso they use the higher byte only and leave the lower byte free forsctp_pr_policyvalues.need you sign-off.
Done, just added "-s" to the commit command....
Quoted 72 lines
Quoted 72 lines
--- 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(-)include/net/sctp/structs.h +6
-4@@ -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;include/net/sctp/user.h +2
-1@@ -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 {*/
Quoted 13 lines
include/net/sctp/user.h struct sctp_sndrcvinfo { · line 208
Quoted 11 lines
include/net/sctp/user.h +4
-4enum 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.
Quoted 71 lines
Quoted 54 lines
include/net/sctp/user.h +11
-0+/* +* 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;net/sctp/associola.c +2
-1@@ -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 */ net/sctp/chunk.c +2
-8@@ -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); +net/sctp/chunk.c struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, · line 183
Quoted 10 lines
net/sctp/chunk.c +10
-0+ 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 oldsinfo_timetoliv) needs to be checked to see if the TTL policy applies.
Quoted 2 lines
Also,
msg->expires_policyneeds to be set only ifsinfo_pr_policyis 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).
Quoted 69 lines
Quoted 69 lines
net/sctp/chunk.c +7
-3} 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 ; }net/sctp/output.c +1
-1@@ -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;net/sctp/socket.c +5
-3@@ -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;
Quoted 8 lines
net/sctp/socket.c static int sctp_setsockopt_default_send_param(struct sock *sk, · line 2577
Quoted 6 lines
net/sctp/socket.c +2
-1sp->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_policyvalue to make sure it's valid.
As mentioned above I added all this validations in a single place (sctp_msghdr_parse).
Quoted 10 lines
net/sctp/socket.c SCTP_STATIC int sctp_init_sock(struct sock *sk) · line 3530
Quoted 8 lines
net/sctp/socket.c +1
-1return 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
Quoted 36 lines
Quoted 36 lines
net/sctp/socket.c +6
-3+ 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);
Quoted 7 lines
net/sctp/socket.c SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, · line 6113
Quoted 5 lines
net/sctp/socket.c +0
-5-/* 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
Quoted 16 lines
Quoted 16 lines
net/sctp/socket.c +0
-0break ;default :net/sctp/ulpevent.c +2
-1@@ -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 ;
Quoted 6 lines
net/sctp/ulpevent.c void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event, · line 955
Quoted 2 lines
net/sctp/ulpevent.c +0
-0put_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 <[email protected]>
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.
--- 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(-)
include/net/sctp/structs.h +6 -4
@@ -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;
include/net/sctp/user.h +17 -5
@@ -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;
net/sctp/associola.c +2 -1
@@ -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 */
net/sctp/chunk.c +19 -11
@@ -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 ; }
net/sctp/output.c +1 -1
@@ -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;
net/sctp/socket.c +24 -11
@@ -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 :
net/sctp/ulpevent.c +2 -1
@@ -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);
Signature · 1 line
1.5.6.3
Quoted 107 lines · Horacio Sanson
Quoted 7 lines · Vlad Yasevich
Quoted 6 lines · Horacio Sanson
From: Horacio Sanson <[email protected]>
Modified all relevant structures in all header and source files to replace the deprecated
sinfo_timetolivefield with the newersinfo_pr_policyandsinfo_pr_value.Quoted 6 lines
Quoted 4 lines
Added a new
sctp_sinfo_pr_policyenum that contains the different PR policy
definitions:SCTP_PR_SCTP_NONEandSCTP_PR_SCTP_TTL. And modified the values ofsctp_sinfo_flagsso they use the higher byte only and leave the lower byte free forsctp_pr_policyvalues.need you sign-off.
Done, just added "-s" to the commit command....
Quoted 72 lines
Quoted 72 lines
--- 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(-)include/net/sctp/structs.h +6
-4@@ -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;include/net/sctp/user.h +2
-1@@ -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 {*/ Quoted 12 lines
include/net/sctp/user.h struct sctp_sndrcvinfo { · line 208
Quoted 11 lines
include/net/sctp/user.h +4
-4enum 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 forsctp_sinfo_pr_policyvalues.
Quoted 5 lines
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_policyis transported between peers in an association and having standard values is a good idea.
Buy you don't use it as such. You have a separate __u16 defined.to carry pr_policy. So before we had a structure:
struct sctp_sndrcvinfo {
__u16 sinfo_stream;
__u16 sinfo_ssn;
__u16 sinfo_flags;
<---- 16bit memory hole
__u32 sinfo_ppid;
__u32 sinfo_context;
__u32 sinfo_timetolive;
__u32 sinfo_tsn;
__u32 sinfo_cumtsn;
sctp_assoc_t sinfo_assoc_id;
};and now we have a structure
struct sctp_sndrcvinfo {
__u16 sinfo_stream;
__u16 sinfo_ssn;
__u16 sinfo_flags;
__u16 sinfo_pr_policy; <---- hole filled
__u32 sinfo_ppid;
__u32 sinfo_context;
__u32 sinfo_pr_value;
__u32 sinfo_tsn;
__u32 sinfo_cumtsn;
sctp_assoc_t sinfo_assoc_id;
};So, I am trying to find the reason for shifting the flags. Also, this shift would require all the application to recompile since they would suddenly start providing wrong flag values to the kernel (broken ABI).
Quoted 70 lines
Quoted 70 lines
Quoted 54 lines
include/net/sctp/user.h +11
-0+/* +* 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;net/sctp/associola.c +2
-1@@ -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 */ net/sctp/chunk.c +2
-8@@ -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); +net/sctp/chunk.c struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, · line 183
Quoted 10 lines
net/sctp/chunk.c +10
-0+ 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 oldsinfo_timetoliv) needs to be checked to see if the TTL policy applies.
Quoted 7 lines
Quoted 2 lines
Also,
msg->expires_policyneeds to be set only ifsinfo_pr_policyis truly set correctly.I need the ability to set
sinfo_pr_policytoSCTP_PR_SCTP_TTLandsinfo_pr_valueequal 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??).
OK. So you need to have a default case, where the expires_policy is junk and in that case you verify pr_value before setting msg->expires_policy.
In essence, you need to cover the case of user using the new structure as well as using an old structure that had a memory hole.
Quoted 10 lines
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 forcessinfo_pr_valueto zero and never retransmits.
I think what you are looking for a retransmit policy (SCTP_PR_RTX) with the number of retransmits set 0. You don't want to do this as a timer policy with a timeout of 0 milliseconds, because you may end up discarding packets as fast as your app can generate them and never send anything.
Quoted 6 lines
About validating
sinfo_pr_valueandsinfo_pr_policyI added validating code on thesctp_msghdr_parsemethod. I think this is the best place to make this validation. This would also make sure that the user gets an error message if thesinfo_pr_valueorsinfo_pr_policyvalues are not initialized correctly (me thinks).
No, the user may be using an old structure and and old api/abi. We can't break them. This has been my gripe with this draft for a long time... it keeps breaking ABI and requiring these ugly workarounds.
You can log a rate limited warning, but you can't error out since that will break applications.
BTW, why are the constants SCTP_PR_SCTP_*. Having SCTP there once should be enough. We can define BSD compatibility stuff, but having it clean in the kernel.
-vlad
Based on comments from Vlad I have prepared a new patch to replace sinfo_timetolive with the newer sinfo_pr_policy and sinfo_pr_value fields.
Quoted 98 lines · Vlad Yasevich
Quoted 56 lines · Horacio Sanson
Quoted 39 lines
Quoted 9 lines
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 forsctp_sinfo_pr_policyvalues.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_policyis transported between peers in an association and having standard values is a good idea.Buy you don't use it as such. You have a separate
__u16defined.to carrypr_policy. So before we had a structure:struct sctp_sndrcvinfo { __u16 sinfo_stream; __u16 sinfo_ssn; __u16 sinfo_flags; <---- 16bit memory hole __u32 sinfo_ppid; __u32 sinfo_context; __u32 sinfo_timetolive; __u32 sinfo_tsn; __u32 sinfo_cumtsn; sctp_assoc_t sinfo_assoc_id; };and now we have a structure
struct sctp_sndrcvinfo { __u16 sinfo_stream; __u16 sinfo_ssn; __u16 sinfo_flags; __u16 sinfo_pr_policy; <---- hole filled __u32 sinfo_ppid; __u32 sinfo_context; __u32 sinfo_pr_value; __u32 sinfo_tsn; __u32 sinfo_cumtsn; sctp_assoc_t sinfo_assoc_id; };Quoted 4 lines
So, I am trying to find the reason for shifting the flags. Also, this shift would require all the application to recompile since they would suddenly start providing wrong flag values to the kernel (broken ABI).
The idea of the shift, and this is how is done in FreeBSD, is to allow both
sinfo_flagsandsinfo_pr_policyflags to be specified when using thesctp_sendmsg()call. For example this would allow a call like:sctp_sendmsg(sock,
msg, msglen,
toaddr, tolen,
0,
SCTP_UNORDERED|SCTP_PR_SCTP_TTL, // <--sinfo_flags
andsinfo_pr_policy0, 3000, 0);Quoted 9 lines
The latest socket api draft does not mention the
sinfo_pr_policyflags as possible values for the flags argument insctp_sendmsg()but I believe this is a mistake as it makes no sense to allow users to specify apr_valuebut give no way to specify the correspondingpr_policyin the same call. So even if the socket api draft states thatsinfo_flagsandsinfo_pr_policyare separate fields in thesctp_sndrcvinfostruct, there is a reason to have their values shifted so they can be combined in a single integer variable.Ok, so you don't really need to shift this. You simply need to define the partial reliability policy as flags so they can be passed
sctp_sendmsg().This is a problem with retrofitting the existing api that I'll bring up.
Quoted 18 lines
To avoid breaking the ABI what would be a good approach?? I though maybe doing this:
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_PR_NONE = 8, /* Reliable transmission */ SCTP_PR_TTL = 16, /* Timed partial reliability */ SCTP_EOF = MSG_FIN, /* Initiate graceful shutdown process. (0x0200) */};
/* this for draft compatibility */
#defineSCTP_PR_SCTP_NONESCTP_PR_NONE
#defineSCTP_PR_SCTP_TTLSCTP_PR_TTLQuoted 7 lines
But allowing the SCTP_PR_* flags to coexist in the same integer is not a good idea because these flags are exclusive.... if for some reason the user provides both
SCTP_PR_NONEandSCTP_PR_TTLat the same time what should the implementation interpret? this is not addressed in the draft either. The other option would be to reserve the higher 16bits for PR policy flags and the lower 16bits forsinfo_flags:
Quoted 2 lines
The spec doesn't address at all the ability to pass pr policy values to
sctp_sendmsg().
In the end I opted to use this approach of adding the SCTP_PR_SCTP_* constants to the sinfo_flags enum. Using the upper 16 bits causes a lot of trouble when splitting and converting it to a 16bit value needed to fit in the sinfo_pr_policy field.
Quoted 77 lines
Quoted 8 lines
enum
sctp_sinfo_flags{^ISCTP_UNORDERED = 1, /* Send/receive message unordered. */ ^ISCTP_ADDR_OVER = 2, /* Overrde the primary destination. */ ^ISCTP_ABORT = 4, /* Send an ABORT message to the peer. */ ^ISCTP_EOF = MSG_FIN, /* Initiate graceful shutdown process. (0x0200) */ ^ISCTP_PR_NONE = 0x010000, /* Reliable transmission */ ^ISCTP_PR_TTL = 0x020000, /* Timed partial reliability */Quoted 4 lines
};
but this assumes that integers are always 32bits long and I am not sure this is a good assumption to take.
This is safe because the flags argument to
sctp_sendmsg()is defined asuint32_tand you are guaranteed to have 32 bits there.Also, notice that this split will need to be taken care of in libsctp, since that is where
sctp_sendmsg()is defined. That function will have to split the flags intosinfo_flagsandsinfo_pr_policy. This means that we'll need a 2 ways define policy:
as a flag, and as a direct policy.The kernel doesn't need to know anything about the split and can treat the 'flag' policy values as errors.
I think BSD shifted the flags so that it could get way without dual definitions, but they broke the ABI by doing so. I don't know how they could get away with that.
Quoted 38 lines
Quoted 21 lines
Quoted 6 lines
I need the ability to set
sinfo_pr_policytoSCTP_PR_SCTP_TTLandsinfo_pr_valueequal 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??).OK. So you need to have a default case, where the
expires_policyis junk and in that case you verifypr_valuebefore settingmsg->expires_policy.In essence, you need to cover the case of user using the new structure as well as using an old structure that had a memory hole.
Quoted 6 lines
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.
Quoted 8 lines
Quoted 3 lines
Another alternative would be to define a new partial reliability profile, something like
SCTP_PR_SCTP_UNR, that forcessinfo_pr_valueto zero and never retransmits.I think what you are looking for a retransmit policy (
SCTP_PR_RTX) with the number of retransmits set 0. You don't want to do this as a timer policy with a timeout of 0 milliseconds, because you may end up discarding packets as fast as your app can generate them and never send anything.I have this
SCTP_PR_RTXfunctionality already implemented as a separate patch. Once my first
patch gets approval I will submit it for review.If I understand right then something like this would be ok??
switch(sinfo->sinfo_pr_policy){Quoted 11 lines
case SCTP_PR_NONE: msg->expires_policy = SCTP_PR_NONE; msg->expires_at = 0; break; case SCTP_PR_RTX: msg->expires_policy = SCTP_PR_RTX; msg->expires_at = sinfo->sinfo_pr_value; break; case SCTP_PR_TTL: default: if(pr_value <= 0) {
Quoted 1 line
I don't think
pr_valuecan be less then 0 since it's defined a unsigned.
fixed.
Quoted 11 lines
Quoted 10 lines
msg->expires_policy = SCTP_PR_NONE; msg->expires_at = 0; } else { msg->expires_policy = SCTP_PR_TTL; msg->expires_at = jiffies + msecs_to_jiffies(sinfo->sinfo_pr_value); } break; }
Quoted 2 lines
Yes.
great, I use this switch statement now.
Quoted 21 lines
Quoted 13 lines
Quoted 13 lines
Quoted 6 lines
About validating
sinfo_pr_valueandsinfo_pr_policyI added validating code on thesctp_msghdr_parsemethod. I think this is the best place to make this validation. This would also make sure that the user gets an error message if thesinfo_pr_valueorsinfo_pr_policyvalues are not initialized correctly (me thinks).No, the user may be using an old structure and and old api/abi. We can't break them. This has been my gripe with this draft for a long time... it keeps breaking ABI and requiring these ugly workarounds.
You can log a rate limited warning, but you can't error out since that will break applications.
Quoted 7 lines
Quoted 3 lines
BTW, why are the constants SCTP_PR_SCTP_*. Having SCTP there once should be enough. We can define BSD compatibility stuff, but having it clean in the kernel.
Once the values I can use for the SCTP_PR_* flags is established I will think on the validation. And about the constants having SCTP twice in them, well I am just following the draft as it is written.
Quoted 6 lines
Ah... I should have looked.
I think this is getting cleared up. I'll get a comment to the rest of the authors and the wG about specifying policy in
sctp_sendmsg()and let you know the outcome.
hope this time I got it right....
Horacio
Quoted 11 lines
-vlad
Quoted 7 lines
regards
HoracioQuoted 2 lines
-vlad
From 75b5677399dc58d74dc7cfa04b4d6f37ee705ebd Mon Sep 17 00:00:00 2001
From: Horacio Sanson <[email protected]>
Date: Wed, 31 Dec 2008 00:52:41 +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.
--- include/net/sctp/structs.h | 10 ++++++---- include/net/sctp/user.h | 5 ++++- net/sctp/associola.c | 3 ++- net/sctp/chunk.c | 39 ++++++++++++++++++++++++++------------- net/sctp/output.c | 2 +- net/sctp/socket.c | 29 +++++++++++++++++++---------- net/sctp/ulpevent.c | 3 ++- 7 files changed, 60 insertions(+), 31 deletions(-)
include/net/sctp/structs.h +6 -4
@@ -280,9 +280,10 @@ struct sctp_sock {/* Various Socket Options. */ __u16 default_stream;__u32 default_ppid; +__u16 default_pr_policy;__u16 default_flags;__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;
include/net/sctp/user.h +4 -1
@@ -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;
@@ -202,6 +203,8 @@ 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_PR_SCTP_NONE =8 ,/* Reliable transmission */ +SCTP_PR_SCTP_TTL =16 ,/* Timed partial reliability */ SCTP_EOF=MSG_FIN, /* Initiate graceful shutdown process. */ };
net/sctp/associola.c +2 -1
@@ -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 */
net/sctp/chunk.c +26 -13
@@ -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,23 @@ 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); +switch (sinfo->sinfo_pr_policy) { +case SCTP_PR_SCTP_NONE : + msg->expires_policy =SCTP_PR_SCTP_NONE ; + msg->expires_at =0 ; +break ; +case SCTP_PR_SCTP_TTL : +default : +if (!sinfo->sinfo_pr_value) { + msg->expires_policy =SCTP_PR_SCTP_NONE ; + msg->expires_at =0 ; + }else { + msg->expires_policy =SCTP_PR_SCTP_TTL ; + 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 ; } max = asoc->frag_point;
@@ -291,11 +301,14 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk) {struct sctp_datamsg *msg = chunk->msg; -if (!msg->can_abandon) -return 0 ; - -if (time_after (jiffies, msg->expires_at)) -return 1 ; +switch (msg->expires_policy) { +case SCTP_PR_SCTP_NONE : +return 0 ; +case SCTP_PR_SCTP_TTL : +if (time_after (jiffies, msg->expires_at)) +return 1 ; +break ; + }return 0 ; }
net/sctp/output.c +1 -1
@@ -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;
net/sctp/socket.c +19 -10
@@ -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))
@@ -6107,10 +6113,13 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, (struct sctp_sndrcvinfo *)CMSG_DATA (cmsg);/* Minimally, validate the sinfo_flags. */ -if (cmsgs->info->sinfo_flags & +/* +if (cmsgs->info->sinfo_flags & ~(SCTP_UNORDERED | SCTP_ADDR_OVER | -SCTP_ABORT |SCTP_EOF )) +SCTP_ABORT | SCTP_EOF | SCTP_PR_SCTP_NONE | +SCTP_PR_SCTP_TTL)) return -EINVAL; +*/ break ;default :
net/sctp/ulpevent.c +2 -1
@@ -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);
Signature · 1 line
1.5.6.3
Hi Horacio
Few small issues:
Quoted 15 lines
net/sctp/socket.c +2
-2@@ -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;
net/sctp/socket.c static int sctp_setsockopt_default_send_param(struct sock *sk, · line 2576
Quoted 10 lines
net/sctp/socket.c +3
-1+ 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; }
The policy value needs to be verified since we don't want to set to a garbage value.
Quoted 6 lines
(quoted diff) +1
-1@@ -6107,10 +6113,13 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); /* Minimally, validate the sinfo_flags. */ - if (cmsgs->info->sinfo_flags & +/*
Review SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, · line 6125
Quoted 10 lines
(quoted diff) +4
-1+if (cmsgs->info->sinfo_flags & ~(SCTP_UNORDERED | SCTP_ADDR_OVER | - SCTP_ABORT | SCTP_EOF)) + SCTP_ABORT | SCTP_EOF | SCTP_PR_SCTP_NONE | + SCTP_PR_SCTP_TTL)) return -EINVAL; +*/ break; default:
Commented out block above. The sinfo_flags probably shouldn't contain _PR_ flags as it should be filled into the sinfo_pr_policy. Remember that the flags are really needed only for interaction with sctp_sendmsg() library call.
-vlad
Quoted 23 lines · Vlad Yasevich
Hi Horacio
Few small issues:
Quoted 19 lines
net/sctp/socket.c +3
-2@@ -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;
Quoted 9 lines
net/sctp/socket.c static int sctp_setsockopt_default_send_param(struct sock *sk, · line 2576
Quoted 6 lines
net/sctp/socket.c +2
-1sp->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; }The policy value needs to be verified since we don't want to set to a garbage value.
When you say "policy value" here you refer to sinfo_pr_policy value or to sinfo_pr_value? In the former case if the sinfo_pr_policy value is garbage then the behavior would be the same as when sinfo_timetolive was used, see the switch statement on line 150 of the same patch. The default statement checks for sinfo_pr_value and if not zero uses timed reliability and if zero uses reliable transmission independent of the value in sinfo_pr_policy.
If you refer to sinfo_pr_value then I have no idea how to validate this as it can be any 32bit unsigned integer depending on the PR policy used.
Quoted 15 lines
Quoted 15 lines
(quoted diff) +5
-2@@ -6107,10 +6113,13 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); /* Minimally, validate the sinfo_flags. */ - if (cmsgs->info->sinfo_flags & +/* +if (cmsgs->info->sinfo_flags & ~(SCTP_UNORDERED | SCTP_ADDR_OVER | - SCTP_ABORT | SCTP_EOF)) + SCTP_ABORT | SCTP_EOF | SCTP_PR_SCTP_NONE | + SCTP_PR_SCTP_TTL)) return -EINVAL; +*/ break;
Quoted 7 lines
net/sctp/socket.c SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, · line 6116
Quoted 1 line
net/sctp/socket.c +0
-0default :Commented out block above. The
sinfo_flagsprobably shouldn't contain _PR_ flags as it should be filled into thesinfo_pr_policy. Remember that the flags are really needed only for interaction withsctp_sendmsg()library call.
When calling sctp_sendmsg I set sinfo_pr_policy based on the SCTP_PR_* flags (see corresponding sctp-tools patch at line 67) but I do not remove these flags from the sinfo_flags field. For this cause if I do not add the SCTP_PR_* flags in the check all calls to sctp_sendmsg() fail with EINVAL.
Shall I remove the SCTP_PR_* flags from sinfo_flags after I set sinfo_pr_value?? This would require to add a "binary AND" operation per SCTP_PR_* flag that I consider unnecessary. Note the block is commented out due to my lack of git skillz, this block is not commented in my current tree.
regards,
Horacio
Quoted 2 lines
-vlad
Quoted 33 lines · Horacio Sanson
Quoted 22 lines · Vlad Yasevich
Hi Horacio
Few small issues:
Quoted 18 lines
net/sctp/socket.c +3
-2@@ -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;Quoted 9 lines
net/sctp/socket.c static int sctp_setsockopt_default_send_param(struct sock *sk, · line 2576
Quoted 7 lines
net/sctp/socket.c +2
-1sp->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; }The policy value needs to be verified since we don't want to set to a garbage value.
Quoted 4 lines
When you say "policy value" here you refer to
sinfo_pr_policyvalue or tosinfo_pr_value? In the former case if thesinfo_pr_policyvalue is garbage then the behavior would be the same as whensinfo_timetolivewas used, see the switch statement on line 150 of the same patch.
I meant the sinfo_pr_policy. The idea of storing a garbage/non-valid value for pr_policy in either the socket or the association doesn't appeal to me. If, for whatever reason, we need to examine that value, it should be set correctly and not require additional determination elsewhere.
Quoted 38 lines
The
default statement checks forsinfo_pr_valueand if not zero uses timed reliability and if zero uses reliable transmission independent of the value insinfo_pr_policy.If you refer to
sinfo_pr_valuethen I have no idea how to validate this as it can be any 32bit unsigned integer depending on the PR policy used.Quoted 15 lines
Quoted 15 lines
(quoted diff) +5
-2@@ -6107,10 +6113,13 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); /* Minimally, validate the sinfo_flags. */ - if (cmsgs->info->sinfo_flags & +/* +if (cmsgs->info->sinfo_flags & ~(SCTP_UNORDERED | SCTP_ADDR_OVER | - SCTP_ABORT | SCTP_EOF)) + SCTP_ABORT | SCTP_EOF | SCTP_PR_SCTP_NONE | + SCTP_PR_SCTP_TTL)) return -EINVAL; +*/ break;Quoted 6 lines
net/sctp/socket.c SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, · line 6116
Quoted 1 line
net/sctp/socket.c +0
-0default :Commented out block above. The
sinfo_flagsprobably shouldn't contain _PR_ flags as it should be filled into thesinfo_pr_policy. Remember that the flags are really needed only for interaction withsctp_sendmsg()library call.When calling
sctp_sendmsgI setsinfo_pr_policybased on the SCTP_PR_* flags (see corresponding sctp-tools patch at line 67) but I do not remove these flags from thesinfo_flagsfield. For this cause if I do not add the SCTP_PR_* flags in the check all calls tosctp_sendmsg()fail with EINVAL.
Quoted 6 lines
Shall I remove the SCTP_PR_* flags from
sinfo_flagsafter I setsinfo_pr_value?? This would require to add a "binary AND" operation per SCTP_PR_* flag that I consider unnecessary. Note the block is commented out due to my lack of git skillz, this block is not commented in my current tree.
The main problem is that the hunk is commented out. If I were to take and apply this patch, it would introduce a regression. If it looks right on your system check to see if you've committed this change. 'git status' will tell you if you have files still not committed. If you want to update the last commit you did you can do:
# git reset --soft HEAD^ # git update-index <file> <file> ... <- not committed files # git commit -C ORIG_HEAD
As for not removing PR flags from the flags, I currently have an outstanding issue with the ID, but have not heard anything back yet. I will probably recommend that sctp_sendmsg() support only TTL based policy and any other policy needs to be specified with sctp_send() that takes the whole sinfo structure as a parameter. If others agree, we can remove the flags hack. So, I think it would be better to not introduce this particular part of the API and have the library mask off the PR bits from the flags. If the flags interface is adopted, we can remove the mask-off and re-establish this interface.
Can you agree with that reasoning?
Thanks
-vlad
Quoted 10 lines
regards,
HoracioQuoted 2 lines
-vlad
--
To unsubscribe from this list: send the line "unsubscribe linux-sctp" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html