Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
acbabcbe
Commit
acbabcbe
authored
Mar 03, 2003
by
Jon Grimm
Browse files
Options
Browse Files
Download
Plain Diff
Merge
http://linux-lksctp.bkbits.net/lksctp-2.5.work
into touki.austin.ibm.com:/home/jgrimm/bk/lksctp-2.5.work
parents
7cd48512
020fec6e
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
267 additions
and
176 deletions
+267
-176
include/net/sctp/command.h
include/net/sctp/command.h
+8
-8
include/net/sctp/constants.h
include/net/sctp/constants.h
+1
-0
include/net/sctp/sctp.h
include/net/sctp/sctp.h
+3
-13
include/net/sctp/sm.h
include/net/sctp/sm.h
+23
-23
include/net/sctp/structs.h
include/net/sctp/structs.h
+12
-14
include/net/sctp/user.h
include/net/sctp/user.h
+2
-0
net/sctp/output.c
net/sctp/output.c
+56
-34
net/sctp/outqueue.c
net/sctp/outqueue.c
+62
-44
net/sctp/protocol.c
net/sctp/protocol.c
+6
-3
net/sctp/sm_sideeffect.c
net/sctp/sm_sideeffect.c
+1
-1
net/sctp/sm_statefuns.c
net/sctp/sm_statefuns.c
+16
-18
net/sctp/socket.c
net/sctp/socket.c
+77
-18
No files found.
include/net/sctp/command.h
View file @
acbabcbe
...
...
@@ -110,13 +110,13 @@ typedef union {
sctp_event_timeout_t
to
;
sctp_counter_t
counter
;
void
*
ptr
;
s
ctp_chunk_t
*
chunk
;
s
ctp_association_t
*
asoc
;
s
truct
sctp_chunk
*
chunk
;
s
truct
sctp_association
*
asoc
;
struct
sctp_transport
*
transport
;
s
ctp_bind_addr_t
*
bp
;
s
truct
sctp_bind_addr
*
bp
;
sctp_init_chunk_t
*
init
;
struct
sctp_ulpevent
*
ulpevent
;
s
ctp_packet_
t
*
packet
;
s
truct
sctp_packe
t
*
packet
;
sctp_sackhdr_t
*
sackh
;
}
sctp_arg_t
;
...
...
@@ -158,13 +158,13 @@ SCTP_ARG_CONSTRUCTOR(STATE, sctp_state_t, state)
SCTP_ARG_CONSTRUCTOR
(
COUNTER
,
sctp_counter_t
,
counter
)
SCTP_ARG_CONSTRUCTOR
(
TO
,
sctp_event_timeout_t
,
to
)
SCTP_ARG_CONSTRUCTOR
(
PTR
,
void
*
,
ptr
)
SCTP_ARG_CONSTRUCTOR
(
CHUNK
,
s
ctp_chunk_t
*
,
chunk
)
SCTP_ARG_CONSTRUCTOR
(
ASOC
,
s
ctp_association_t
*
,
asoc
)
SCTP_ARG_CONSTRUCTOR
(
CHUNK
,
s
truct
sctp_chunk
*
,
chunk
)
SCTP_ARG_CONSTRUCTOR
(
ASOC
,
s
truct
sctp_association
*
,
asoc
)
SCTP_ARG_CONSTRUCTOR
(
TRANSPORT
,
struct
sctp_transport
*
,
transport
)
SCTP_ARG_CONSTRUCTOR
(
BA
,
s
ctp_bind_addr_t
*
,
bp
)
SCTP_ARG_CONSTRUCTOR
(
BA
,
s
truct
sctp_bind_addr
*
,
bp
)
SCTP_ARG_CONSTRUCTOR
(
PEER_INIT
,
sctp_init_chunk_t
*
,
init
)
SCTP_ARG_CONSTRUCTOR
(
ULPEVENT
,
struct
sctp_ulpevent
*
,
ulpevent
)
SCTP_ARG_CONSTRUCTOR
(
PACKET
,
s
ctp_packet_
t
*
,
packet
)
SCTP_ARG_CONSTRUCTOR
(
PACKET
,
s
truct
sctp_packe
t
*
,
packet
)
SCTP_ARG_CONSTRUCTOR
(
SACKH
,
sctp_sackhdr_t
*
,
sackh
)
typedef
struct
{
...
...
include/net/sctp/constants.h
View file @
acbabcbe
...
...
@@ -345,6 +345,7 @@ typedef enum {
SCTP_XMIT_PMTU_FULL
,
SCTP_XMIT_RWND_FULL
,
SCTP_XMIT_MUST_FRAG
,
SCTP_XMIT_NAGLE_DELAY
,
}
sctp_xmit_t
;
/* These are the commands for manipulating transports. */
...
...
include/net/sctp/sctp.h
View file @
acbabcbe
...
...
@@ -313,31 +313,21 @@ static inline void sctp_sysctl_unregister(void) { return; }
#endif
/* Size of Supported Address Parameter for 'x' address types. */
#define SCTP_SAT_LEN(x) (sizeof(struct sctp_paramhdr) + (x) * sizeof(__u16))
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
extern
int
sctp_v6_init
(
void
);
extern
void
sctp_v6_exit
(
void
);
static
inline
int
sctp_ipv6_addr_type
(
const
struct
in6_addr
*
addr
)
{
return
ipv6_addr_type
((
struct
in6_addr
*
)
addr
);
}
/* Size of Supported Address Parameter for 'x' address types. */
#define SCTP_SAT_LEN(x) (sizeof(struct sctp_paramhdr) + (x) * sizeof(__u16))
/* Note: These V6 macros are obsolescent. */
/* Use this macro to enclose code fragments which are V6-dependent. */
#define SCTP_V6(m...) m
#define SCTP_V6_SUPPORT 1
#else
/* #ifdef defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
#define sctp_ipv6_addr_type(a) 0
#define SCTP_SAT_LEN (sizeof(sctp_paramhdr_t) + 1 * sizeof(__u16))
#define SCTP_V6(m...)
/* Do nothing. */
#undef SCTP_V6_SUPPORT
static
inline
int
sctp_v6_init
(
void
)
{
return
0
;
}
static
inline
void
sctp_v6_exit
(
void
)
{
return
;
}
...
...
include/net/sctp/sm.h
View file @
acbabcbe
...
...
@@ -313,18 +313,18 @@ void sctp_generate_t3_rtx_event(unsigned long peer);
void
sctp_generate_heartbeat_event
(
unsigned
long
peer
);
sctp_sackhdr_t
*
sctp_sm_pull_sack
(
sctp_chunk_t
*
);
s
ctp_packet_t
*
sctp_abort_pkt_new
(
const
sctp_endpoint_t
*
ep
,
const
sctp_association_t
*
asoc
,
sctp_chunk_t
*
chunk
,
s
truct
sctp_packet
*
sctp_abort_pkt_new
(
const
struct
sctp_endpoint
*
,
const
struct
sctp_association
*
,
struct
sctp_chunk
*
chunk
,
const
void
*
payload
,
size_t
paylen
);
s
ctp_packet_t
*
sctp_ootb_pkt_new
(
const
sctp_association_t
*
asoc
,
const
sctp_chunk_t
*
chunk
);
void
sctp_ootb_pkt_free
(
s
ctp_packet_t
*
packet
);
s
truct
sctp_packet
*
sctp_ootb_pkt_new
(
const
struct
sctp_association
*
,
const
struct
sctp_chunk
*
);
void
sctp_ootb_pkt_free
(
s
truct
sctp_packet
*
);
sctp_cookie_param_t
*
sctp_pack_cookie
(
const
s
ctp_endpoint_t
*
,
const
sctp_association_t
*
,
const
s
ctp_chunk_t
*
,
int
*
cookie_len
,
sctp_pack_cookie
(
const
s
truct
sctp_endpoint
*
,
const
struct
sctp_association
*
,
const
s
truct
sctp_chunk
*
,
int
*
cookie_len
,
const
__u8
*
,
int
addrs_len
);
sctp_association_t
*
sctp_unpack_cookie
(
const
sctp_endpoint_t
*
,
const
sctp_association_t
*
,
...
...
include/net/sctp/structs.h
View file @
acbabcbe
...
...
@@ -88,7 +88,6 @@ struct sctp_ssnmap;
typedef
struct
sctp_endpoint
sctp_endpoint_t
;
typedef
struct
sctp_association
sctp_association_t
;
typedef
struct
sctp_packet
sctp_packet_t
;
typedef
struct
sctp_chunk
sctp_chunk_t
;
typedef
struct
sctp_bind_addr
sctp_bind_addr_t
;
typedef
struct
sctp_endpoint_common
sctp_endpoint_common_t
;
...
...
@@ -604,26 +603,26 @@ struct sctp_packet {
typedef
int
(
sctp_outq_thandler_t
)(
struct
sctp_outq
*
,
void
*
);
typedef
int
(
sctp_outq_ehandler_t
)(
struct
sctp_outq
*
);
typedef
s
ctp_packet_
t
*
(
sctp_outq_ohandler_init_t
)
(
s
ctp_packet_
t
*
,
typedef
s
truct
sctp_packe
t
*
(
sctp_outq_ohandler_init_t
)
(
s
truct
sctp_packe
t
*
,
struct
sctp_transport
*
,
__u16
sport
,
__u16
dport
);
typedef
s
ctp_packet_
t
*
(
sctp_outq_ohandler_config_t
)
(
s
ctp_packet_
t
*
,
typedef
s
truct
sctp_packe
t
*
(
sctp_outq_ohandler_config_t
)
(
s
truct
sctp_packe
t
*
,
__u32
vtag
,
int
ecn_capable
,
sctp_packet_phandler_t
*
get_prepend_chunk
);
typedef
sctp_xmit_t
(
sctp_outq_ohandler_t
)(
s
ctp_packet_
t
*
,
typedef
sctp_xmit_t
(
sctp_outq_ohandler_t
)(
s
truct
sctp_packe
t
*
,
sctp_chunk_t
*
);
typedef
int
(
sctp_outq_ohandler_force_t
)(
s
ctp_packet_
t
*
);
typedef
int
(
sctp_outq_ohandler_force_t
)(
s
truct
sctp_packe
t
*
);
sctp_outq_ohandler_init_t
sctp_packet_init
;
sctp_outq_ohandler_config_t
sctp_packet_config
;
sctp_outq_ohandler_t
sctp_packet_append_chunk
;
sctp_outq_ohandler_t
sctp_packet_transmit_chunk
;
sctp_outq_ohandler_force_t
sctp_packet_transmit
;
void
sctp_packet_free
(
s
ctp_packet_
t
*
);
void
sctp_packet_free
(
s
truct
sctp_packe
t
*
);
/* This represents a remote transport address.
...
...
@@ -789,7 +788,7 @@ struct sctp_transport {
struct
list_head
transmitted
;
/* We build bundle-able packets for this transport here. */
s
ctp_packet_
t
packet
;
s
truct
sctp_packe
t
packet
;
/* This is the list of transports that have chunks to send. */
struct
list_head
send_ready
;
...
...
@@ -865,12 +864,11 @@ void sctp_inq_set_th_handler(struct sctp_inq *, void (*)(void *), void *);
struct
sctp_outq
{
sctp_association_t
*
asoc
;
/* BUG: This really should be an array of streams.
* This really holds a list of chunks (one stream).
* FIXME: If true, why so?
*/
/* Data pending that has never been transmitted. */
struct
sk_buff_head
out
;
unsigned
out_qlen
;
/* Total length of queued data chunks. */
/* These are control chunks we want to send. */
struct
sk_buff_head
control
;
...
...
@@ -885,7 +883,7 @@ struct sctp_outq {
struct
list_head
retransmit
;
/* Call these functions to send chunks down to the next lower
* layer. This is always
SCTP
_packet, but we separate the two
* layer. This is always
sctp
_packet, but we separate the two
* structures to make testing simpler.
*/
sctp_outq_ohandler_init_t
*
init_output
;
...
...
include/net/sctp/user.h
View file @
acbabcbe
...
...
@@ -108,6 +108,8 @@ enum sctp_optname {
#define SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS_NUM
SCTP_GET_LOCAL_ADDRS
,
/* Get all local addresss. */
#define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS
SCTP_NODELAY
,
/* Get/set nodelay option. */
#define SCTP_NODELAY SCTP_NODELAY
};
...
...
net/sctp/output.c
View file @
acbabcbe
...
...
@@ -62,16 +62,15 @@
#include <net/sctp/sm.h>
/* Forward declarations for private helpers. */
static
void
sctp_packet_reset
(
s
ctp_packet_
t
*
packet
);
static
sctp_xmit_t
sctp_packet_append_data
(
s
ctp_packet_
t
*
packet
,
s
ctp_chunk_t
*
chunk
);
static
void
sctp_packet_reset
(
s
truct
sctp_packe
t
*
packet
);
static
sctp_xmit_t
sctp_packet_append_data
(
s
truct
sctp_packe
t
*
packet
,
s
truct
sctp_chunk
*
chunk
);
/* Config a packet.
* This appears to be a followup set of initializations.)
*/
sctp_packet_t
*
sctp_packet_config
(
sctp_packet_t
*
packet
,
__u32
vtag
,
int
ecn_capable
,
struct
sctp_packet
*
sctp_packet_config
(
struct
sctp_packet
*
packet
,
__u32
vtag
,
int
ecn_capable
,
sctp_packet_phandler_t
*
prepend_handler
)
{
int
packet_empty
=
(
packet
->
size
==
SCTP_IP_OVERHEAD
);
...
...
@@ -89,10 +88,9 @@ sctp_packet_t *sctp_packet_config(sctp_packet_t *packet,
}
/* Initialize the packet structure. */
s
ctp_packet_t
*
sctp_packet_init
(
sctp_packet_
t
*
packet
,
s
truct
sctp_packet
*
sctp_packet_init
(
struct
sctp_packe
t
*
packet
,
struct
sctp_transport
*
transport
,
__u16
sport
,
__u16
dport
)
__u16
sport
,
__u16
dport
)
{
packet
->
transport
=
transport
;
packet
->
source_port
=
sport
;
...
...
@@ -109,14 +107,12 @@ sctp_packet_t *sctp_packet_init(sctp_packet_t *packet,
}
/* Free a packet. */
void
sctp_packet_free
(
s
ctp_packet_
t
*
packet
)
void
sctp_packet_free
(
s
truct
sctp_packe
t
*
packet
)
{
s
ctp_chunk_t
*
chunk
;
s
truct
sctp_chunk
*
chunk
;
while
(
NULL
!=
(
chunk
=
(
sctp_chunk_t
*
)
skb_dequeue
(
&
packet
->
chunks
)))
{
while
((
chunk
=
(
struct
sctp_chunk
*
)
__skb_dequeue
(
&
packet
->
chunks
)))
sctp_free_chunk
(
chunk
);
}
if
(
packet
->
malloced
)
kfree
(
packet
);
...
...
@@ -129,8 +125,8 @@ void sctp_packet_free(sctp_packet_t *packet)
* as it can fit in the packet, but any more data that does not fit in this
* packet can be sent only after receiving the COOKIE_ACK.
*/
sctp_xmit_t
sctp_packet_transmit_chunk
(
s
ctp_packet_
t
*
packet
,
s
ctp_chunk_t
*
chunk
)
sctp_xmit_t
sctp_packet_transmit_chunk
(
s
truct
sctp_packe
t
*
packet
,
s
truct
sctp_chunk
*
chunk
)
{
sctp_xmit_t
retval
;
int
error
=
0
;
...
...
@@ -152,6 +148,7 @@ sctp_xmit_t sctp_packet_transmit_chunk(sctp_packet_t *packet,
case
SCTP_XMIT_MUST_FRAG
:
case
SCTP_XMIT_RWND_FULL
:
case
SCTP_XMIT_OK
:
case
SCTP_XMIT_NAGLE_DELAY
:
break
;
};
...
...
@@ -161,7 +158,8 @@ sctp_xmit_t sctp_packet_transmit_chunk(sctp_packet_t *packet,
/* Append a chunk to the offered packet reporting back any inability to do
* so.
*/
sctp_xmit_t
sctp_packet_append_chunk
(
sctp_packet_t
*
packet
,
sctp_chunk_t
*
chunk
)
sctp_xmit_t
sctp_packet_append_chunk
(
struct
sctp_packet
*
packet
,
struct
sctp_chunk
*
chunk
)
{
sctp_xmit_t
retval
=
SCTP_XMIT_OK
;
__u16
chunk_len
=
WORD_ROUND
(
ntohs
(
chunk
->
chunk_hdr
->
length
));
...
...
@@ -223,7 +221,7 @@ sctp_xmit_t sctp_packet_append_chunk(sctp_packet_t *packet, sctp_chunk_t *chunk)
}
/* It is OK to send this chunk. */
skb_queue_tail
(
&
packet
->
chunks
,
(
struct
sk_buff
*
)
chunk
);
__
skb_queue_tail
(
&
packet
->
chunks
,
(
struct
sk_buff
*
)
chunk
);
packet
->
size
+=
chunk_len
;
finish:
return
retval
;
...
...
@@ -234,18 +232,18 @@ sctp_xmit_t sctp_packet_append_chunk(sctp_packet_t *packet, sctp_chunk_t *chunk)
*
* The return value is a normal kernel error return value.
*/
int
sctp_packet_transmit
(
s
ctp_packet_
t
*
packet
)
int
sctp_packet_transmit
(
s
truct
sctp_packe
t
*
packet
)
{
struct
sctp_transport
*
transport
=
packet
->
transport
;
s
ctp_association_t
*
asoc
=
transport
->
asoc
;
s
truct
sctp_association
*
asoc
=
transport
->
asoc
;
struct
sctphdr
*
sh
;
__u32
crc32
;
struct
sk_buff
*
nskb
;
s
ctp_chunk_t
*
chunk
;
s
truct
sctp_chunk
*
chunk
;
struct
sock
*
sk
;
int
err
=
0
;
int
padding
;
/* How much padding do we need? */
__u8
packet_
has_data
=
0
;
__u8
has_data
=
0
;
struct
dst_entry
*
dst
;
/* Do NOT generate a chunkless packet... */
...
...
@@ -253,7 +251,7 @@ int sctp_packet_transmit(sctp_packet_t *packet)
return
err
;
/* Set up convenience variables... */
chunk
=
(
s
ctp_chunk_t
*
)
(
packet
->
chunks
.
next
);
chunk
=
(
s
truct
sctp_chunk
*
)
(
packet
->
chunks
.
next
);
sk
=
chunk
->
skb
->
sk
;
/* Allocate the new skb. */
...
...
@@ -291,8 +289,7 @@ int sctp_packet_transmit(sctp_packet_t *packet)
* [This whole comment explains WORD_ROUND() below.]
*/
SCTP_DEBUG_PRINTK
(
"***sctp_transmit_packet***
\n
"
);
while
(
NULL
!=
(
chunk
=
(
sctp_chunk_t
*
)
skb_dequeue
(
&
packet
->
chunks
)))
{
while
((
chunk
=
(
struct
sctp_chunk
*
)
__skb_dequeue
(
&
packet
->
chunks
)))
{
chunk
->
num_times_sent
++
;
chunk
->
sent_at
=
jiffies
;
if
(
sctp_chunk_is_data
(
chunk
))
{
...
...
@@ -309,7 +306,7 @@ int sctp_packet_transmit(sctp_packet_t *packet)
chunk
->
rtt_in_progress
=
1
;
transport
->
rto_pending
=
1
;
}
packet_
has_data
=
1
;
has_data
=
1
;
}
memcpy
(
skb_put
(
nskb
,
chunk
->
skb
->
len
),
chunk
->
skb
->
data
,
chunk
->
skb
->
len
);
...
...
@@ -399,7 +396,7 @@ int sctp_packet_transmit(sctp_packet_t *packet)
asoc
->
peer
.
last_sent_to
=
transport
;
}
if
(
packet_
has_data
)
{
if
(
has_data
)
{
struct
timer_list
*
timer
;
unsigned
long
timeout
;
...
...
@@ -456,9 +453,9 @@ int sctp_packet_transmit(sctp_packet_t *packet)
/*
* This private function resets the packet to a fresh state.
*/
static
void
sctp_packet_reset
(
s
ctp_packet_
t
*
packet
)
static
void
sctp_packet_reset
(
s
truct
sctp_packe
t
*
packet
)
{
s
ctp_chunk_t
*
chunk
=
NULL
;
s
truct
sctp_chunk
*
chunk
=
NULL
;
packet
->
size
=
SCTP_IP_OVERHEAD
;
...
...
@@ -473,13 +470,15 @@ static void sctp_packet_reset(sctp_packet_t *packet)
}
/* This private function handles the specifics of appending DATA chunks. */
static
sctp_xmit_t
sctp_packet_append_data
(
s
ctp_packet_
t
*
packet
,
s
ctp_chunk_t
*
chunk
)
static
sctp_xmit_t
sctp_packet_append_data
(
s
truct
sctp_packe
t
*
packet
,
s
truct
sctp_chunk
*
chunk
)
{
sctp_xmit_t
retval
=
SCTP_XMIT_OK
;
size_t
datasize
,
rwnd
,
inflight
;
struct
sctp_transport
*
transport
=
packet
->
transport
;
__u32
max_burst_bytes
;
struct
sctp_opt
*
sp
=
sctp_sk
(
transport
->
asoc
->
base
.
sk
);
struct
sctp_outq
*
q
=
&
transport
->
asoc
->
outqueue
;
/* RFC 2960 6.1 Transmission of DATA Chunks
*
...
...
@@ -543,11 +542,34 @@ static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet,
* When a Fast Retransmit is being performed the sender SHOULD
* ignore the value of cwnd and SHOULD NOT delay retransmission.
*/
if
(
!
chunk
->
fast_retransmit
)
{
if
(
!
chunk
->
fast_retransmit
)
if
(
transport
->
flight_size
>=
transport
->
cwnd
)
{
retval
=
SCTP_XMIT_RWND_FULL
;
goto
finish
;
}
/* Nagle's algorithm to solve small-packet problem:
* inhibit the sending of new chunks when new outgoing data arrives
* if any proeviously transmitted data on the connection remains
* unacknowledged. Unless the connection was previously idle. Check
* whether the connection is idle. No outstanding means idle, flush
* it. If outstanding bytes are less than half cwnd, the connection
* is not in the state of congestion, so also flush it.
*/
if
(
!
sp
->
nodelay
&&
q
->
outstanding_bytes
>=
transport
->
cwnd
>>
1
)
{
/* Check whether this chunk and all the rest of pending
* data will fit or whether we'll choose to delay in
* hopes of bundling a full sized packet.
*/
if
((
datasize
+
q
->
out_qlen
)
<
transport
->
asoc
->
frag_point
)
{
/* If the the chunk should be delay
* for future sending, we could not
* append it.
*/
retval
=
SCTP_XMIT_NAGLE_DELAY
;
goto
finish
;
}
}
/* Keep track of how many bytes are in flight over this transport. */
...
...
net/sctp/outqueue.c
View file @
acbabcbe
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001
-2003
Intel Corp.
* Copyright (c) 2001-2003 International Business Machines Corp.
*
* This file is part of the SCTP kernel reference Implementation
...
...
@@ -62,6 +62,33 @@ static void sctp_check_transmitted(struct sctp_outq *q,
sctp_sackhdr_t
*
sack
,
__u32
highest_new_tsn
);
/* Add data to the front of the queue. */
static
inline
void
sctp_outq_head_data
(
struct
sctp_outq
*
q
,
struct
sctp_chunk
*
ch
)
{
__skb_queue_head
(
&
q
->
out
,
(
struct
sk_buff
*
)
ch
);
q
->
out_qlen
+=
ch
->
skb
->
len
;
return
;
}
/* Take data from the front of the queue. */
static
inline
struct
sctp_chunk
*
sctp_outq_dequeue_data
(
struct
sctp_outq
*
q
)
{
struct
sctp_chunk
*
ch
;
ch
=
(
struct
sctp_chunk
*
)
__skb_dequeue
(
&
q
->
out
);
if
(
ch
)
q
->
out_qlen
-=
ch
->
skb
->
len
;
return
ch
;
}
/* Add data chunk to the end of the queue. */
static
inline
void
sctp_outq_tail_data
(
struct
sctp_outq
*
q
,
struct
sctp_chunk
*
ch
)
{
__skb_queue_tail
(
&
q
->
out
,
(
struct
sk_buff
*
)
ch
);
q
->
out_qlen
+=
ch
->
skb
->
len
;
return
;
}
/* Generate a new outqueue. */
struct
sctp_outq
*
sctp_outq_new
(
sctp_association_t
*
asoc
)
{
...
...
@@ -97,6 +124,7 @@ void sctp_outq_init(sctp_association_t *asoc, struct sctp_outq *q)
q
->
empty
=
1
;
q
->
malloced
=
0
;
q
->
out_qlen
=
0
;
}
/* Free the outqueue structure and any related pending chunks.
...
...
@@ -133,7 +161,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
}
/* Throw away any leftover data chunks. */
while
((
chunk
=
(
sctp_chunk_t
*
)
skb_dequeue
(
&
q
->
out
)))
while
((
chunk
=
sctp_outq_dequeue_data
(
q
)))
sctp_free_chunk
(
chunk
);
/* Throw away any leftover control chunks. */
...
...
@@ -192,7 +220,7 @@ int sctp_outq_tail(struct sctp_outq *q, sctp_chunk_t *chunk)
sctp_cname
(
SCTP_ST_CHUNK
(
chunk
->
chunk_hdr
->
type
))
:
"Illegal Chunk"
);
s
kb_queue_tail
(
&
q
->
out
,
(
struct
sk_buff
*
)
chunk
);
s
ctp_outq_tail_data
(
q
,
chunk
);
if
(
chunk
->
chunk_hdr
->
flags
&
SCTP_DATA_UNORDERED
)
SCTP_INC_STATS
(
SctpOutUnorderChunks
);
else
...
...
@@ -201,7 +229,7 @@ int sctp_outq_tail(struct sctp_outq *q, sctp_chunk_t *chunk)
break
;
};
}
else
{
skb_queue_tail
(
&
q
->
control
,
(
struct
sk_buff
*
)
chunk
);
__
skb_queue_tail
(
&
q
->
control
,
(
struct
sk_buff
*
)
chunk
);
SCTP_INC_STATS
(
SctpOutCtrlChunks
);
}
...
...
@@ -351,7 +379,7 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
*
* The return value is a normal kernel error return value.
*/
static
int
sctp_outq_flush_rtx
(
struct
sctp_outq
*
q
,
s
ctp_packet_
t
*
pkt
,
static
int
sctp_outq_flush_rtx
(
struct
sctp_outq
*
q
,
s
truct
sctp_packe
t
*
pkt
,
int
rtx_timeout
,
int
*
start_timer
)
{
struct
list_head
*
lqueue
;
...
...
@@ -385,17 +413,6 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, sctp_packet_t *pkt,
while
(
lchunk
)
{
chunk
=
list_entry
(
lchunk
,
sctp_chunk_t
,
transmitted_list
);
#if 0
/* If a chunk has been tried for more than SCTP_DEF_MAX_SEND
* times, discard it, and check the empty flag of the outqueue.
*
* --xguo
*/
if (chunk->snd_count > SCTP_DEF_MAX_SEND) {
sctp_free_chunk(chunk);
continue;
}
#endif
/* Make sure that Gap Acked TSNs are not retransmitted. A
* simple approach is just to move such TSNs out of the
...
...
@@ -462,7 +479,7 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, sctp_packet_t *pkt,
* chunk that is currently in the process of fragmentation.
*/
void
sctp_xmit_frag
(
struct
sctp_outq
*
q
,
struct
sk_buff
*
pos
,
s
ctp_packet_
t
*
packet
,
sctp_chunk_t
*
frag
,
__u32
tsn
)
s
truct
sctp_packe
t
*
packet
,
sctp_chunk_t
*
frag
,
__u32
tsn
)
{
struct
sctp_transport
*
transport
=
packet
->
transport
;
struct
sk_buff_head
*
queue
=
&
q
->
out
;
...
...
@@ -480,11 +497,11 @@ void sctp_xmit_frag(struct sctp_outq *q, struct sk_buff *pos,
SCTP_DEBUG_PRINTK
(
"sctp_xmit_frag: q not empty. "
"adding 0x%x to outqueue
\n
"
,
ntohl
(
frag
->
subh
.
data_hdr
->
tsn
));
if
(
pos
)
{
skb_insert
(
pos
,
(
struct
sk_buff
*
)
frag
);
}
else
{
skb_queue_tail
(
queue
,
(
struct
sk_buff
*
)
frag
);
}
if
(
pos
)
__skb_insert
((
struct
sk_buff
*
)
frag
,
pos
->
prev
,
pos
,
pos
->
list
);
else
__skb_queue_tail
(
queue
,
(
struct
sk_buff
*
)
frag
);
return
;
}
...
...
@@ -496,11 +513,11 @@ void sctp_xmit_frag(struct sctp_outq *q, struct sk_buff *pos,
SCTP_DEBUG_PRINTK
(
"sctp_xmit_frag: rwnd full. "
"adding 0x%x to outqueue
\n
"
,
ntohl
(
frag
->
subh
.
data_hdr
->
tsn
));
if
(
pos
)
{
skb_insert
(
pos
,
(
struct
sk_buff
*
)
frag
);
}
else
{
skb_queue_tail
(
queue
,
(
struct
sk_buff
*
)
frag
);
}
if
(
pos
)
__skb_insert
((
struct
sk_buff
*
)
frag
,
pos
->
prev
,
pos
,
pos
->
list
);
else
__skb_queue_tail
(
queue
,
(
struct
sk_buff
*
)
frag
);
break
;
case
SCTP_XMIT_OK
:
...
...
@@ -512,11 +529,11 @@ void sctp_xmit_frag(struct sctp_outq *q, struct sk_buff *pos,
SCTP_DEBUG_PRINTK
(
"sctp_xmit_frag: force output "
"failed. adding 0x%x to outqueue
\n
"
,
ntohl
(
frag
->
subh
.
data_hdr
->
tsn
));
if
(
pos
)
{
skb_insert
(
pos
,
(
struct
sk_buff
*
)
frag
);
}
else
{
skb_queue_tail
(
queue
,
(
struct
sk_buff
*
)
frag
);
}
if
(
pos
)
__skb_insert
((
struct
sk_buff
*
)
frag
,
pos
->
prev
,
pos
,
pos
->
list
);
else
__skb_queue_tail
(
queue
,(
struct
sk_buff
*
)
frag
);
}
else
{
SCTP_DEBUG_PRINTK
(
"sctp_xmit_frag: force output "
"success. 0x%x sent
\n
"
,
...
...
@@ -537,7 +554,7 @@ void sctp_xmit_frag(struct sctp_outq *q, struct sk_buff *pos,
* The argument 'frag' point to the first fragment and it holds the list
* of all the other fragments in the 'frag_list' field.
*/
void
sctp_xmit_fragmented_chunks
(
struct
sctp_outq
*
q
,
s
ctp_packet_t
*
packe
t
,
void
sctp_xmit_fragmented_chunks
(
struct
sctp_outq
*
q
,
s
truct
sctp_packet
*
pk
t
,
sctp_chunk_t
*
frag
)
{
sctp_association_t
*
asoc
=
frag
->
asoc
;
...
...
@@ -557,13 +574,13 @@ void sctp_xmit_fragmented_chunks(struct sctp_outq *q, sctp_packet_t *packet,
pos
=
skb_peek
(
&
q
->
out
);
/* Transmit the first fragment. */
sctp_xmit_frag
(
q
,
pos
,
p
acke
t
,
frag
,
tsn
++
);
sctp_xmit_frag
(
q
,
pos
,
p
k
t
,
frag
,
tsn
++
);
/* Transmit the rest of fragments. */
frag_list
=
&
frag
->
frag_list
;
list_for_each
(
lfrag
,
frag_list
)
{
frag
=
list_entry
(
lfrag
,
sctp_chunk_t
,
frag_list
);
sctp_xmit_frag
(
q
,
pos
,
p
acke
t
,
frag
,
tsn
++
);
sctp_xmit_frag
(
q
,
pos
,
p
k
t
,
frag
,
tsn
++
);
}
}
...
...
@@ -672,15 +689,14 @@ sctp_chunk_t *sctp_fragment_chunk(sctp_chunk_t *chunk,
*
* Description: Send everything in q which we legally can, subject to
* congestion limitations.
*
* Note: This function can be called from multiple contexts so appropriate
* * Note: This function can be called from multiple contexts so appropriate
* locking concerns must be made. Today we use the sock lock to protect
* this function.
*/
int
sctp_outq_flush
(
struct
sctp_outq
*
q
,
int
rtx_timeout
)
{
s
ctp_packet_
t
*
packet
;
s
ctp_packet_
t
singleton
;
s
truct
sctp_packe
t
*
packet
;
s
truct
sctp_packe
t
singleton
;
sctp_association_t
*
asoc
=
q
->
asoc
;
int
ecn_capable
=
asoc
->
peer
.
ecn_capable
;
__u16
sport
=
asoc
->
base
.
bind_addr
.
port
;
...
...
@@ -852,7 +868,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
/* Finally, transmit new packets. */
start_timer
=
0
;
queue
=
&
q
->
out
;
while
(
NULL
!=
(
chunk
=
(
sctp_chunk_t
*
)
skb_dequeue
(
queue
)))
{
while
(
NULL
!=
(
chunk
=
sctp_outq_dequeue_data
(
q
)))
{
/* RFC 2960 6.5 Every DATA chunk MUST carry a valid
* stream identifier.
*/
...
...
@@ -925,6 +942,7 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
switch
(
status
)
{
case
SCTP_XMIT_PMTU_FULL
:
case
SCTP_XMIT_RWND_FULL
:
case
SCTP_XMIT_NAGLE_DELAY
:
/* We could not append this chunk, so put
* the chunk back on the output queue.
*/
...
...
@@ -932,7 +950,7 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
"not transmit TSN: 0x%x, status: %d
\n
"
,
ntohl
(
chunk
->
subh
.
data_hdr
->
tsn
),
status
);
s
kb_queue_head
(
queue
,
(
struct
sk_buff
*
)
chunk
);
s
ctp_outq_head_data
(
q
,
chunk
);
goto
sctp_flush_out
;
break
;
...
...
@@ -994,6 +1012,7 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
}
sctp_flush_out:
/* Before returning, examine all the transports touched in
* this call. Right now, we bluntly force clear all the
* transports. Things might change after we implement Nagle.
...
...
@@ -1163,11 +1182,10 @@ int sctp_outq_sack(struct sctp_outq *q, sctp_sackhdr_t *sack)
sack_a_rwnd
=
ntohl
(
sack
->
a_rwnd
);
outstanding
=
q
->
outstanding_bytes
;
if
(
outstanding
<
sack_a_rwnd
)
{
if
(
outstanding
<
sack_a_rwnd
)
sack_a_rwnd
-=
outstanding
;
}
else
{
else
sack_a_rwnd
=
0
;
}
asoc
->
peer
.
rwnd
=
sack_a_rwnd
;
...
...
net/sctp/protocol.c
View file @
acbabcbe
...
...
@@ -557,10 +557,13 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long event,
*/
int
sctp_ctl_sock_init
(
void
)
{
int
err
=
0
;
int
family
=
PF_INET
;
int
err
;
sa_family_t
family
;
SCTP_V6
(
family
=
PF_INET6
;)
if
(
sctp_get_pf_specific
(
PF_INET6
))
family
=
PF_INET6
;
else
family
=
PF_INET
;
err
=
sock_create
(
family
,
SOCK_SEQPACKET
,
IPPROTO_SCTP
,
&
sctp_ctl_socket
);
...
...
net/sctp/sm_sideeffect.c
View file @
acbabcbe
...
...
@@ -256,7 +256,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
sctp_cmd_t
*
cmd
;
sctp_chunk_t
*
new_obj
;
sctp_chunk_t
*
chunk
=
NULL
;
s
ctp_packet_
t
*
packet
;
s
truct
sctp_packe
t
*
packet
;
struct
list_head
*
pos
;
struct
timer_list
*
timer
;
unsigned
long
timeout
;
...
...
net/sctp/sm_statefuns.c
View file @
acbabcbe
...
...
@@ -189,7 +189,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const sctp_endpoint_t *ep,
sctp_chunk_t
*
repl
;
sctp_association_t
*
new_asoc
;
sctp_chunk_t
*
err_chunk
;
s
ctp_packet_
t
*
packet
;
s
truct
sctp_packe
t
*
packet
;
sctp_unrecognized_param_t
*
unk_param
;
int
len
;
...
...
@@ -354,10 +354,9 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const sctp_endpoint_t *ep,
sctp_init_chunk_t
*
initchunk
;
__u32
init_tag
;
sctp_chunk_t
*
err_chunk
;
s
ctp_packet_
t
*
packet
;
s
truct
sctp_packe
t
*
packet
;
sctp_disposition_t
ret
;
/* 6.10 Bundling
* An endpoint MUST NOT bundle INIT, INIT ACK or
* SHUTDOWN COMPLETE with any other chunks.
...
...
@@ -912,14 +911,14 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa,
sctp_cmd_seq_t
*
commands
)
{
int
len
;
s
ctp_packet_
t
*
pkt
;
s
truct
sctp_packe
t
*
pkt
;
sctp_addr_param_t
*
addrparm
;
sctp_errhdr_t
*
errhdr
;
sctp_endpoint_t
*
ep
;
char
buffer
[
sizeof
(
sctp_errhdr_t
)
+
sizeof
(
sctp_addr_param_t
)];
/* Build the error on the stack. We are way to malloc
*
malloc crazy
throughout the code today.
/* Build the error on the stack. We are way to malloc
crazy
* throughout the code today.
*/
errhdr
=
(
sctp_errhdr_t
*
)
buffer
;
addrparm
=
(
sctp_addr_param_t
*
)
errhdr
->
variable
;
...
...
@@ -1105,11 +1104,10 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
sctp_chunk_t
*
repl
;
sctp_association_t
*
new_asoc
;
sctp_chunk_t
*
err_chunk
;
s
ctp_packet_
t
*
packet
;
s
truct
sctp_packe
t
*
packet
;
sctp_unrecognized_param_t
*
unk_param
;
int
len
;
/* 6.10 Bundling
* An endpoint MUST NOT bundle INIT, INIT ACK or
* SHUTDOWN COMPLETE with any other chunks.
...
...
@@ -2751,7 +2749,7 @@ sctp_disposition_t sctp_sf_tabort_8_4_8(const sctp_endpoint_t *ep,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
{
s
ctp_packet_
t
*
packet
=
NULL
;
s
truct
sctp_packe
t
*
packet
=
NULL
;
sctp_chunk_t
*
chunk
=
arg
;
sctp_chunk_t
*
abort
;
...
...
@@ -2953,7 +2951,7 @@ sctp_disposition_t sctp_sf_shut_8_4_5(const sctp_endpoint_t *ep,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
{
s
ctp_packet_
t
*
packet
=
NULL
;
s
truct
sctp_packe
t
*
packet
=
NULL
;
sctp_chunk_t
*
chunk
=
arg
;
sctp_chunk_t
*
shut
;
...
...
@@ -4377,13 +4375,13 @@ sctp_sackhdr_t *sctp_sm_pull_sack(sctp_chunk_t *chunk)
/* Create an ABORT packet to be sent as a response, with the specified
* error causes.
*/
s
ctp_packet_
t
*
sctp_abort_pkt_new
(
const
sctp_endpoint_t
*
ep
,
s
truct
sctp_packe
t
*
sctp_abort_pkt_new
(
const
sctp_endpoint_t
*
ep
,
const
sctp_association_t
*
asoc
,
sctp_chunk_t
*
chunk
,
const
void
*
payload
,
size_t
paylen
)
{
s
ctp_packet_
t
*
packet
;
s
truct
sctp_packe
t
*
packet
;
sctp_chunk_t
*
abort
;
packet
=
sctp_ootb_pkt_new
(
asoc
,
chunk
);
...
...
@@ -4413,10 +4411,10 @@ sctp_packet_t *sctp_abort_pkt_new(const sctp_endpoint_t *ep,
}
/* Allocate a packet for responding in the OOTB conditions. */
s
ctp_packet_
t
*
sctp_ootb_pkt_new
(
const
sctp_association_t
*
asoc
,
s
truct
sctp_packe
t
*
sctp_ootb_pkt_new
(
const
sctp_association_t
*
asoc
,
const
sctp_chunk_t
*
chunk
)
{
s
ctp_packet_
t
*
packet
;
s
truct
sctp_packe
t
*
packet
;
struct
sctp_transport
*
transport
;
__u16
sport
;
__u16
dport
;
...
...
@@ -4449,7 +4447,7 @@ sctp_packet_t *sctp_ootb_pkt_new(const sctp_association_t *asoc,
goto
nomem
;
/* Allocate a new packet for sending the response. */
packet
=
t_new
(
s
ctp_packet_
t
,
GFP_ATOMIC
);
packet
=
t_new
(
s
truct
sctp_packe
t
,
GFP_ATOMIC
);
if
(
!
packet
)
goto
nomem_packet
;
...
...
@@ -4471,7 +4469,7 @@ sctp_packet_t *sctp_ootb_pkt_new(const sctp_association_t *asoc,
}
/* Free the packet allocated earlier for responding in the OOTB condition. */
void
sctp_ootb_pkt_free
(
s
ctp_packet_
t
*
packet
)
void
sctp_ootb_pkt_free
(
s
truct
sctp_packe
t
*
packet
)
{
sctp_transport_free
(
packet
->
transport
);
sctp_packet_free
(
packet
);
...
...
@@ -4484,7 +4482,7 @@ void sctp_send_stale_cookie_err(const sctp_endpoint_t *ep,
sctp_cmd_seq_t
*
commands
,
sctp_chunk_t
*
err_chunk
)
{
s
ctp_packet_
t
*
packet
;
s
truct
sctp_packe
t
*
packet
;
if
(
err_chunk
)
{
packet
=
sctp_ootb_pkt_new
(
asoc
,
chunk
);
...
...
net/sctp/socket.c
View file @
acbabcbe
...
...
@@ -1231,7 +1231,7 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr
return
err
;
}
static
in
line
in
t
sctp_setsockopt_disable_fragments
(
struct
sock
*
sk
,
static
int
sctp_setsockopt_disable_fragments
(
struct
sock
*
sk
,
char
*
optval
,
int
optlen
)
{
int
val
;
...
...
@@ -1247,7 +1247,7 @@ static inline int sctp_setsockopt_disable_fragments(struct sock *sk,
return
0
;
}
static
in
line
in
t
sctp_setsockopt_events
(
struct
sock
*
sk
,
char
*
optval
,
static
int
sctp_setsockopt_events
(
struct
sock
*
sk
,
char
*
optval
,
int
optlen
)
{
if
(
optlen
!=
sizeof
(
struct
sctp_event_subscribe
))
...
...
@@ -1257,7 +1257,7 @@ static inline int sctp_setsockopt_events(struct sock *sk, char *optval,
return
0
;
}
static
in
line
in
t
sctp_setsockopt_autoclose
(
struct
sock
*
sk
,
char
*
optval
,
static
int
sctp_setsockopt_autoclose
(
struct
sock
*
sk
,
char
*
optval
,
int
optlen
)
{
struct
sctp_opt
*
sp
=
sctp_sk
(
sk
);
...
...
@@ -1274,7 +1274,7 @@ static inline int sctp_setsockopt_autoclose(struct sock *sk, char *optval,
return
0
;
}
static
in
line
in
t
sctp_setsockopt_peer_addr_params
(
struct
sock
*
sk
,
static
int
sctp_setsockopt_peer_addr_params
(
struct
sock
*
sk
,
char
*
optval
,
int
optlen
)
{
struct
sctp_paddrparams
params
;
...
...
@@ -1333,7 +1333,7 @@ static inline int sctp_setsockopt_peer_addr_params(struct sock *sk,
return
0
;
}
static
in
line
in
t
sctp_setsockopt_initmsg
(
struct
sock
*
sk
,
char
*
optval
,
static
int
sctp_setsockopt_initmsg
(
struct
sock
*
sk
,
char
*
optval
,
int
optlen
)
{
if
(
optlen
!=
sizeof
(
struct
sctp_initmsg
))
...
...
@@ -1358,7 +1358,7 @@ static inline int sctp_setsockopt_initmsg(struct sock *sk, char *optval,
* sinfo_timetolive. The user must provide the sinfo_assoc_id field in
* to this call if the caller is using the UDP model.
*/
static
in
line
in
t
sctp_setsockopt_default_send_param
(
struct
sock
*
sk
,
static
int
sctp_setsockopt_default_send_param
(
struct
sock
*
sk
,
char
*
optval
,
int
optlen
)
{
struct
sctp_sndrcvinfo
info
;
...
...
@@ -1416,6 +1416,31 @@ static int sctp_setsockopt_peer_prim(struct sock *sk, char *optval, int optlen)
return
0
;
}
/*
*
* 7.1.5 SCTP_NODELAY
*
* Turn on/off any Nagle-like algorithm. This means that packets are
* generally sent as soon as possible and no unnecessary delays are
* introduced, at the cost of more packets in the network. Expects an
* integer boolean flag.
*/
static
int
sctp_setsockopt_nodelay
(
struct
sock
*
sk
,
char
*
optval
,
int
optlen
)
{
__u8
val
;
if
(
optlen
<
sizeof
(
__u8
))
return
-
EINVAL
;
if
(
get_user
(
val
,
(
__u8
*
)
optval
))
return
-
EFAULT
;
sctp_sk
(
sk
)
->
nodelay
=
(
val
==
0
)
?
0
:
1
;
return
0
;
}
/* API 6.2 setsockopt(), getsockopt()
*
* Applications use setsockopt() and getsockopt() to set or retrieve
...
...
@@ -1515,6 +1540,10 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
retval
=
sctp_setsockopt_peer_prim
(
sk
,
optval
,
optlen
);
break
;
case
SCTP_NODELAY
:
retval
=
sctp_setsockopt_nodelay
(
sk
,
optval
,
optlen
);
break
;
default:
retval
=
-
ENOPROTOOPT
;
break
;
...
...
@@ -1786,7 +1815,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
sp
->
disable_fragments
=
0
;
/* Turn on/off any Nagle-like algorithm. */
sp
->
nodelay
=
0
;
sp
->
nodelay
=
1
;
/* Auto-close idle associations after the configured
* number of seconds. A value of 0 disables this
...
...
@@ -1905,7 +1934,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
return
(
retval
);
}
static
in
line
in
t
sctp_getsockopt_disable_fragments
(
struct
sock
*
sk
,
int
len
,
static
int
sctp_getsockopt_disable_fragments
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
int
val
;
...
...
@@ -1922,7 +1951,7 @@ static inline int sctp_getsockopt_disable_fragments(struct sock *sk, int len,
return
0
;
}
static
in
line
in
t
sctp_getsockopt_set_events
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
static
int
sctp_getsockopt_set_events
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
if
(
len
!=
sizeof
(
struct
sctp_event_subscribe
))
return
-
EINVAL
;
...
...
@@ -1931,7 +1960,7 @@ static inline int sctp_getsockopt_set_events(struct sock *sk, int len, char *opt
return
0
;
}
static
in
line
in
t
sctp_getsockopt_autoclose
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
static
int
sctp_getsockopt_autoclose
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
/* Applicable to UDP-style socket only */
if
(
SCTP_SOCKET_TCP
==
sctp_sk
(
sk
)
->
type
)
...
...
@@ -1975,7 +2004,7 @@ SCTP_STATIC int sctp_do_peeloff(sctp_association_t *assoc, struct socket **newso
return
err
;
}
static
in
line
in
t
sctp_getsockopt_peeloff
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
static
int
sctp_getsockopt_peeloff
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
sctp_peeloff_arg_t
peeloff
;
struct
socket
*
newsock
;
...
...
@@ -2018,7 +2047,7 @@ static inline int sctp_getsockopt_peeloff(struct sock *sk, int len, char *optval
return
retval
;
}
static
in
line
in
t
sctp_getsockopt_peer_addr_params
(
struct
sock
*
sk
,
int
len
,
static
int
sctp_getsockopt_peer_addr_params
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
struct
sctp_paddrparams
params
;
...
...
@@ -2062,7 +2091,7 @@ static inline int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
return
0
;
}
static
in
line
in
t
sctp_getsockopt_initmsg
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
static
int
sctp_getsockopt_initmsg
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
if
(
len
!=
sizeof
(
struct
sctp_initmsg
))
return
-
EINVAL
;
...
...
@@ -2141,7 +2170,7 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
return
0
;
}
static
in
line
in
t
sctp_getsockopt_local_addrs_num
(
struct
sock
*
sk
,
int
len
,
static
int
sctp_getsockopt_local_addrs_num
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
sctp_assoc_t
id
;
...
...
@@ -2180,7 +2209,7 @@ static inline int sctp_getsockopt_local_addrs_num(struct sock *sk, int len,
return
0
;
}
static
in
line
in
t
sctp_getsockopt_local_addrs
(
struct
sock
*
sk
,
int
len
,
static
int
sctp_getsockopt_local_addrs
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
sctp_bind_addr_t
*
bp
;
...
...
@@ -2282,7 +2311,7 @@ static int sctp_getsockopt_peer_prim(struct sock *sk, int len,
*
* For getsockopt, it get the default sctp_sndrcvinfo structure.
*/
static
in
line
in
t
sctp_getsockopt_default_send_param
(
struct
sock
*
sk
,
static
int
sctp_getsockopt_default_send_param
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
struct
sctp_sndrcvinfo
info
;
...
...
@@ -2309,6 +2338,33 @@ static inline int sctp_getsockopt_default_send_param(struct sock *sk,
return
0
;
}
/*
*
* 7.1.5 SCTP_NODELAY
*
* Turn on/off any Nagle-like algorithm. This means that packets are
* generally sent as soon as possible and no unnecessary delays are
* introduced, at the cost of more packets in the network. Expects an
* integer boolean flag.
*/
static
int
sctp_getsockopt_nodelay
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
__u8
val
;
if
(
len
<
sizeof
(
__u8
))
return
-
EINVAL
;
len
=
sizeof
(
__u8
);
val
=
(
sctp_sk
(
sk
)
->
nodelay
==
1
);
if
(
put_user
(
len
,
optlen
))
return
-
EFAULT
;
if
(
copy_to_user
(
optval
,
&
val
,
len
))
return
-
EFAULT
;
return
0
;
}
SCTP_STATIC
int
sctp_getsockopt
(
struct
sock
*
sk
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
)
{
...
...
@@ -2382,6 +2438,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
case
SCTP_SET_PEER_PRIMARY_ADDR
:
retval
=
sctp_getsockopt_peer_prim
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_NODELAY
:
retval
=
sctp_getsockopt_nodelay
(
sk
,
len
,
optval
,
optlen
);
break
;
default:
retval
=
-
ENOPROTOOPT
;
break
;
...
...
@@ -2689,7 +2748,6 @@ int sctp_inet_listen(struct socket *sock, int backlog)
case
SOCK_SEQPACKET
:
err
=
sctp_seqpacket_listen
(
sk
,
backlog
);
break
;
case
SOCK_STREAM
:
err
=
sctp_stream_listen
(
sk
,
backlog
);
break
;
...
...
@@ -3077,7 +3135,8 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, int no
}
/* Verify that this is a valid address. */
static
int
sctp_verify_addr
(
struct
sock
*
sk
,
union
sctp_addr
*
addr
,
int
len
)
static
inline
int
sctp_verify_addr
(
struct
sock
*
sk
,
union
sctp_addr
*
addr
,
int
len
)
{
struct
sctp_af
*
af
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment