net: sctp: implement rfc6458, 5.3.5. SCTP_RCVINFO cmsg support
Subsystems (2)
PATCH 3/5 net: sctp: implement rfc6458, 5.3.5. SCTP_RCVINFO cmsg support
From: Geir Ola Vaagland <[email protected]>
This patch implements section 5.3.5. of RFC6458, that is, support for 'SCTP Receive Information Structure' (SCTP_RCVINFO) which is placed into ancillary data cmsghdr structure for each recvmsg() call.
This option can be enabled/disabled via setsockopt(2) on SOL_SCTP level by setting an int value with 1/0 for SCTP_RECVRCVINFO in user space applications as per RFC6458, section 8.1.29.
The sctp_rcvinfo structure is defined as per RFC as below ...
struct sctp_rcvinfo {
uint16_t rcv_sid;
uint16_t rcv_ssn;
uint16_t rcv_flags;
<-- 2 bytes hole -->
uint32_t rcv_ppid;
uint32_t rcv_tsn;
uint32_t rcv_cumtsn;
uint32_t rcv_context;
sctp_assoc_t rcv_assoc_id;
};... and provided under cmsg_level IPPROTO_SCTP, cmsg_type SCTP_RCVINFO, while cmsg_data[] contains struct sctp_rcvinfo. An sctp_rcvinfo item always corresponds to the data in msg_iov.
Joint work with Daniel Borkmann.
--- include/net/sctp/structs.h | 3 +++ include/net/sctp/ulpevent.h | 5 ++++- include/uapi/linux/sctp.h | 32 ++++++++++++++++++++++------- net/sctp/socket.c | 49 ++++++++++++++++++++++++++++++++++++++++++++- net/sctp/ulpevent.c | 25 +++++++++++++++++++++++ 5 files changed, 105 insertions(+), 9 deletions(-)
include/net/sctp/structs.h +3 -0
@@ -207,7 +207,9 @@ struct sctp_sock {struct sctp_paddrparams paddrparam;struct sctp_event_subscribe subscribe;struct sctp_assocparams assocparams; +int user_frag; +__u32 autoclose;__u8 nodelay;__u8 disable_fragments;
@@ -215,6 +217,7 @@ struct sctp_sock {__u8 frag_interleave;__u32 adaptation_ind;__u32 pd_point; +__u8 recvrcvinfo;atomic_t pd_mode;/* Receive to here while partial delivery is in effect. */
include/net/sctp/ulpevent.h +4 -1
@@ -129,7 +129,10 @@ struct sctp_ulpevent *sctp_ulpevent_make_sender_dry_event( const struct sctp_association *asoc, gfp_t gfp);void sctp_ulpevent_read_sndrcvinfo (const struct sctp_ulpevent *event, -struct msghdr *); +struct msghdr *); +void sctp_ulpevent_read_rcvinfo (const struct sctp_ulpevent *event, +struct msghdr *); +__u16 sctp_ulpevent_get_notification_type (const struct sctp_ulpevent *event);/* Is this event type enabled? */
include/uapi/linux/sctp.h +25 -7
@@ -95,6 +95,7 @@ typedef __s32 sctp_assoc_t;#define SCTP_GET_ASSOC_ID_LIST 29/* Read only */ #define SCTP_AUTO_ASCONF 30#define SCTP_PEER_ADDR_THLDS 31 +#define SCTP_RECVRCVINFO 32/* Internal Socket Options. Some of the sctp library functions are * implemented using these socket options.
@@ -110,8 +111,7 @@ typedef __s32 sctp_assoc_t;#define SCTP_SOCKOPT_CONNECTX3 111/* CONNECTX requests (updated) */ #define SCTP_GET_ASSOC_STATS 112/* Read only */ -/* -* 5.2.1 SCTP Initiation Structure (SCTP_INIT) +/* 5.3.1 SCTP Initiation Structure (SCTP_INIT) * * This cmsghdr structure provides information for initializing new * SCTP associations with sendmsg(). The SCTP_INITMSG socket option
@@ -121,7 +121,6 @@ typedef __s32 sctp_assoc_t;* cmsg_level cmsg_type cmsg_data[] * ------------ ------------ ---------------------- * IPPROTO_SCTP SCTP_INIT struct sctp_initmsg -* */ struct sctp_initmsg {__u16 sinit_num_ostreams;
@@ -130,8 +129,7 @@ struct sctp_initmsg {__u16 sinit_max_init_timeo; }; -/* -* 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV) +/* 5.3.2 SCTP Header Information Structure (SCTP_SNDRCV) * * This cmsghdr structure specifies SCTP options for sendmsg() and * describes SCTP header information about a received message through
@@ -140,7 +138,6 @@ struct sctp_initmsg {* cmsg_level cmsg_type cmsg_data[] * ------------ ------------ ---------------------- * IPPROTO_SCTP SCTP_SNDRCV struct sctp_sndrcvinfo -* */ struct sctp_sndrcvinfo {__u16 sinfo_stream;
@@ -170,13 +167,32 @@ struct sctp_sndinfo {sctp_assoc_t snd_assoc_id; }; +/* 5.3.5 SCTP Receive Information Structure (SCTP_RCVINFO) +* +* This cmsghdr structure describes SCTP receive information +* about a received message through recvmsg(). +* +* cmsg_level cmsg_type cmsg_data[] +* ------------ ------------ ------------------- +* IPPROTO_SCTP SCTP_RCVINFO struct sctp_rcvinfo +*/ +struct sctp_rcvinfo { +__u16 rcv_sid; +__u16 rcv_ssn; +__u16 rcv_flags; +__u32 rcv_ppid; +__u32 rcv_tsn; +__u32 rcv_cumtsn; +__u32 rcv_context; +sctp_assoc_t rcv_assoc_id; +}; +/* * sinfo_flags: 16 bits (unsigned integer) * * This field may contain any of the following flags and is composed of * a bitwise OR of these values. */ -enum sctp_sinfo_flags {SCTP_UNORDERED =1 ,/* Send/receive message unordered. */ SCTP_ADDR_OVER =2 ,/* Override the primary destination. */
@@ -199,6 +215,8 @@ typedef enum sctp_cmsg_type {#define SCTP_SNDRCV SCTP_SNDRCV SCTP_SNDINFO, /* 5.3.4 SCTP Send Information Structure */#define SCTP_SNDINFO SCTP_SNDINFO + SCTP_RCVINFO, /* 5.3.5 SCTP Receive Information Structure */ +#define SCTP_RCVINFO SCTP_RCVINFO } sctp_cmsg_t;/*
net/sctp/socket.c +48 -1
94 lines not on this page · raw message
net/sctp/ulpevent.c +25 -0
@@ -886,6 +886,31 @@ void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event, sizeof(sinfo), &sinfo); } +/* RFC6458, Section 5.3.5 SCTP Receive Information Structure +* (SCTP_SNDRCV) +*/ +void sctp_ulpevent_read_rcvinfo (const struct sctp_ulpevent *event, +struct msghdr *msghdr) +{ +struct sctp_rcvinfo rinfo; + +if (sctp_ulpevent_is_notification (event)) +return ; + +memset (&rinfo,0 ,sizeof (struct sctp_rcvinfo )); + rinfo.rcv_sid = event->stream; + rinfo.rcv_ssn = event->ssn; + rinfo.rcv_ppid = event->ppid; + rinfo.rcv_flags = event->flags; + rinfo.rcv_tsn = event->tsn; + rinfo.rcv_cumtsn = event->cumtsn; + rinfo.rcv_assoc_id =sctp_assoc2id (event->asoc); + rinfo.rcv_context = event->asoc->default_rcv_context; + +put_cmsg (msghdr,IPPROTO_SCTP ,SCTP_RCVINFO , +sizeof (rinfo), &rinfo); +} +/* Do accounting for bytes received and hold a reference to the association * for each skb. */
Signature · 1 line
1.7.11.7
From: Daniel Borkmann
Quoted 30 lines
From: Geir Ola Vaagland <[email protected]>
This patch implements section 5.3.5. of RFC6458, that is, support for 'SCTP Receive Information Structure' (
SCTP_RCVINFO) which is placed into ancillary data cmsghdr structure for eachrecvmsg()call.This option can be enabled/disabled via setsockopt(2) on
SOL_SCTPlevel by setting an int value with 1/0 forSCTP_RECVRCVINFOin user space applications as per RFC6458, section 8.1.29.The
sctp_rcvinfostructure is defined as per RFC as below ...struct sctp_rcvinfo { uint16_t rcv_sid; uint16_t rcv_ssn; uint16_t rcv_flags; <-- 2 bytes hole --> uint32_t rcv_ppid; uint32_t rcv_tsn; uint32_t rcv_cumtsn; uint32_t rcv_context; sctp_assoc_t rcv_assoc_id; };... and provided under
cmsg_levelIPPROTO_SCTP,cmsg_typeSCTP_RCVINFO, while cmsg_data[] contains structsctp_rcvinfo. Ansctp_rcvinfoitem always corresponds to the data inmsg_iov.Joint work with Daniel Borkmann.
...
Quoted 14 lines
net/sctp/ulpevent.c +14
-0+/* RFC6458, Section 5.3.5 SCTP Receive Information Structure +* (SCTP_SNDRCV) +*/ +void sctp_ulpevent_read_rcvinfo (const struct sctp_ulpevent *event, +struct msghdr *msghdr) +{ +struct sctp_rcvinfo rinfo; + +if (sctp_ulpevent_is_notification (event)) +return ; + +memset (&rinfo,0 ,sizeof (struct sctp_rcvinfo )); + rinfo.rcv_sid = event->stream; + rinfo.rcv_ssn = event->ssn;
net/sctp/ulpevent.c void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event, · line 912
Quoted 10 lines
net/sctp/ulpevent.c +10
-0+ rinfo.rcv_ppid = event->ppid; + rinfo.rcv_flags = event->flags; + rinfo.rcv_tsn = event->tsn; + rinfo.rcv_cumtsn = event->cumtsn; + rinfo.rcv_assoc_id =sctp_assoc2id (event->asoc); + rinfo.rcv_context = event->asoc->default_rcv_context; + +put_cmsg (msghdr,IPPROTO_SCTP ,SCTP_RCVINFO , +sizeof (rinfo), &rinfo); +}
This gets called for every receive data chunk (since the user needs to verify the ssn and stream).
It really ought to be possible to write the 'cmsg' data with quite so many memory accesses.
Perhaps you should add named fields for the pads so they can be explicitly zeroed.
It also seems that put_cmsg() should be able to return the pointer to where the data should be written - instead on copying the data itself.
David
From: David Laight
...
Quoted 8 lines
Quoted 8 lines
net/sctp/ulpevent.c +8
-0+memset (&rinfo,0 ,sizeof (struct sctp_rcvinfo )); + rinfo.rcv_sid = event->stream; + rinfo.rcv_ssn = event->ssn; + rinfo.rcv_ppid = event->ppid; + rinfo.rcv_flags = event->flags; + rinfo.rcv_tsn = event->tsn; + rinfo.rcv_cumtsn = event->cumtsn; + rinfo.rcv_assoc_id =sctp_assoc2id (event->asoc);
Quoted 8 lines
net/sctp/ulpevent.c void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event, · line 912
Quoted 5 lines
net/sctp/ulpevent.c +5
-0+ rinfo.rcv_context = event->asoc->default_rcv_context; + +put_cmsg (msghdr,IPPROTO_SCTP ,SCTP_RCVINFO , +sizeof (rinfo), &rinfo); +}This gets called for every receive data chunk (since the user needs to verify the ssn and stream).
Clearly I meant ppid and stream :-(
David
Quoted 48 lines · David Laight
From: Daniel Borkmann
Quoted 30 lines
From: Geir Ola Vaagland <[email protected]>
This patch implements section 5.3.5. of RFC6458, that is, support for 'SCTP Receive Information Structure' (
SCTP_RCVINFO) which is placed into ancillary data cmsghdr structure for eachrecvmsg()call.This option can be enabled/disabled via setsockopt(2) on
SOL_SCTPlevel by setting an int value with 1/0 forSCTP_RECVRCVINFOin user space applications as per RFC6458, section 8.1.29.The
sctp_rcvinfostructure is defined as per RFC as below ...struct sctp_rcvinfo { uint16_t rcv_sid; uint16_t rcv_ssn; uint16_t rcv_flags; <-- 2 bytes hole --> uint32_t rcv_ppid; uint32_t rcv_tsn; uint32_t rcv_cumtsn; uint32_t rcv_context; sctp_assoc_t rcv_assoc_id; };... and provided under
cmsg_levelIPPROTO_SCTP,cmsg_typeSCTP_RCVINFO, while cmsg_data[] contains structsctp_rcvinfo. Ansctp_rcvinfoitem always corresponds to the data inmsg_iov.Joint work with Daniel Borkmann.
...
Quoted 16 lines
net/sctp/ulpevent.c +16
-0+/* RFC6458, Section 5.3.5 SCTP Receive Information Structure +* (SCTP_SNDRCV) +*/ +void sctp_ulpevent_read_rcvinfo (const struct sctp_ulpevent *event, +struct msghdr *msghdr) +{ +struct sctp_rcvinfo rinfo; + +if (sctp_ulpevent_is_notification (event)) +return ; + +memset (&rinfo,0 ,sizeof (struct sctp_rcvinfo )); + rinfo.rcv_sid = event->stream; + rinfo.rcv_ssn = event->ssn; + rinfo.rcv_ppid = event->ppid; + rinfo.rcv_flags = event->flags;
Quoted 8 lines
net/sctp/ulpevent.c void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event, · line 912
Quoted 8 lines
net/sctp/ulpevent.c +8
-0+ rinfo.rcv_tsn = event->tsn; + rinfo.rcv_cumtsn = event->cumtsn; + rinfo.rcv_assoc_id =sctp_assoc2id (event->asoc); + rinfo.rcv_context = event->asoc->default_rcv_context; + +put_cmsg (msghdr,IPPROTO_SCTP ,SCTP_RCVINFO , +sizeof (rinfo), &rinfo); +}
Sorry for the late answer, as I'm on travel this week.
Quoted 7 lines
This gets called for every receive data chunk (since the user needs to verify the ssn and stream).
It really ought to be possible to write the 'cmsg' data with quite so many memory accesses.
Perhaps you should add named fields for the pads so they can be explicitly zeroed.
I really dislike the idea to put padding members into a uapi struct, we should stick to the RFC though it specified it with holes in the struct.