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
63c6e5b3
Commit
63c6e5b3
authored
Nov 03, 2002
by
Sridhar Samudrala
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[SCTP] Support for Peer address parameters socket option.
parent
cd722282
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
293 additions
and
80 deletions
+293
-80
include/net/sctp/command.h
include/net/sctp/command.h
+2
-0
include/net/sctp/sctp.h
include/net/sctp/sctp.h
+1
-1
include/net/sctp/sm.h
include/net/sctp/sm.h
+1
-0
include/net/sctp/structs.h
include/net/sctp/structs.h
+8
-6
net/sctp/associola.c
net/sctp/associola.c
+8
-5
net/sctp/outqueue.c
net/sctp/outqueue.c
+3
-3
net/sctp/primitive.c
net/sctp/primitive.c
+23
-0
net/sctp/sm_sideeffect.c
net/sctp/sm_sideeffect.c
+21
-6
net/sctp/sm_statefuns.c
net/sctp/sm_statefuns.c
+78
-29
net/sctp/sm_statetable.c
net/sctp/sm_statetable.c
+16
-8
net/sctp/socket.c
net/sctp/socket.c
+130
-20
net/sctp/transport.c
net/sctp/transport.c
+2
-2
No files found.
include/net/sctp/command.h
View file @
63c6e5b3
...
...
@@ -27,6 +27,7 @@
*
* La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us>
* Ardelle Fan <ardelle.fan@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -72,6 +73,7 @@ typedef enum {
SCTP_CMD_STRIKE
,
/* Mark a strike against a transport. */
SCTP_CMD_TRANSMIT
,
/* Transmit the outqueue. */
SCTP_CMD_HB_TIMERS_START
,
/* Start the heartbeat timers. */
SCTP_CMD_HB_TIMERS_UPDATE
,
/* Update the heartbeat timers. */
SCTP_CMD_TRANSPORT_RESET
,
/* Reset the status of a transport. */
SCTP_CMD_TRANSPORT_ON
,
/* Mark the transport as active. */
SCTP_CMD_REPORT_ERROR
,
/* Pass this error back out of the sm. */
...
...
include/net/sctp/sctp.h
View file @
63c6e5b3
...
...
@@ -142,7 +142,7 @@ extern int sctp_primitive_ASSOCIATE(sctp_association_t *, void *arg);
extern
int
sctp_primitive_SHUTDOWN
(
sctp_association_t
*
,
void
*
arg
);
extern
int
sctp_primitive_ABORT
(
sctp_association_t
*
,
void
*
arg
);
extern
int
sctp_primitive_SEND
(
sctp_association_t
*
,
void
*
arg
);
extern
int
sctp_primitive_REQUESTHEARTBEAT
(
sctp_association_t
*
,
void
*
arg
);
/*
* sctp_crc32c.c
...
...
include/net/sctp/sm.h
View file @
63c6e5b3
...
...
@@ -157,6 +157,7 @@ sctp_state_fn_t sctp_sf_shutdown_ack_sent_prm_abort;
sctp_state_fn_t
sctp_sf_error_closed
;
sctp_state_fn_t
sctp_sf_error_shutdown
;
sctp_state_fn_t
sctp_sf_ignore_primitive
;
sctp_state_fn_t
sctp_sf_do_prm_requestheartbeat
;
/* Prototypes for other event state functions. */
sctp_state_fn_t
sctp_sf_do_9_2_start_shutdown
;
...
...
include/net/sctp/structs.h
View file @
63c6e5b3
...
...
@@ -684,13 +684,15 @@ struct SCTP_transport {
*/
unsigned
long
last_time_ecne_reduced
;
/*
state : The current
state of this destination,
* : i.e. DOWN, UP,
ALLOW-HB, NO-HEARTBEAT,
etc.
/*
active : The current active
state of this destination,
* : i.e. DOWN, UP, etc.
*/
struct
{
int
active
;
int
hb_allowed
;
}
state
;
int
active
;
/* hb_allowed : The current heartbeat state of this destination,
* : i.e. ALLOW-HB, NO-HEARTBEAT, etc.
*/
int
hb_allowed
;
/* These are the error stats for this destination. */
...
...
net/sctp/associola.c
View file @
63c6e5b3
...
...
@@ -461,6 +461,9 @@ sctp_transport_t *sctp_assoc_add_peer(sctp_association_t *asoc,
min
(
asoc
->
overall_error_threshold
+
peer
->
error_threshold
,
asoc
->
max_retrans
);
/* By default, enable heartbeat for peer address. */
peer
->
hb_allowed
=
1
;
/* Initialize the peer's heartbeat interval based on the
* sock configured value.
*/
...
...
@@ -523,12 +526,12 @@ void sctp_assoc_control_transport(sctp_association_t *asoc,
/* Record the transition on the transport. */
switch
(
command
)
{
case
SCTP_TRANSPORT_UP
:
transport
->
state
.
active
=
1
;
transport
->
active
=
1
;
spc_state
=
ADDRESS_AVAILABLE
;
break
;
case
SCTP_TRANSPORT_DOWN
:
transport
->
state
.
active
=
0
;
transport
->
active
=
0
;
spc_state
=
ADDRESS_UNREACHABLE
;
break
;
...
...
@@ -558,7 +561,7 @@ void sctp_assoc_control_transport(sctp_association_t *asoc,
list_for_each
(
pos
,
&
asoc
->
peer
.
transport_addr_list
)
{
t
=
list_entry
(
pos
,
sctp_transport_t
,
transports
);
if
(
!
t
->
state
.
active
)
if
(
!
t
->
active
)
continue
;
if
(
!
first
||
t
->
last_time_heard
>
first
->
last_time_heard
)
{
second
=
first
;
...
...
@@ -578,7 +581,7 @@ void sctp_assoc_control_transport(sctp_association_t *asoc,
* [If the primary is active but not most recent, bump the most
* recently used transport.]
*/
if
(
asoc
->
peer
.
primary_path
->
state
.
active
&&
if
(
asoc
->
peer
.
primary_path
->
active
&&
first
!=
asoc
->
peer
.
primary_path
)
{
second
=
first
;
first
=
asoc
->
peer
.
primary_path
;
...
...
@@ -1018,7 +1021,7 @@ sctp_transport_t *sctp_assoc_choose_shutdown_transport(sctp_association_t *asoc)
/* Try to find an active transport. */
if
(
t
->
state
.
active
)
{
if
(
t
->
active
)
{
break
;
}
else
{
/* Keep track of the next transport in case
...
...
net/sctp/outqueue.c
View file @
63c6e5b3
...
...
@@ -678,7 +678,7 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
if
(
!
new_transport
)
{
new_transport
=
asoc
->
peer
.
active_path
;
}
else
if
(
!
new_transport
->
state
.
active
)
{
}
else
if
(
!
new_transport
->
active
)
{
/* If the chunk is Heartbeat, send it to
* chunk->transport, even it's inactive.
*/
...
...
@@ -835,7 +835,7 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
*/
new_transport
=
chunk
->
transport
;
if
(
new_transport
==
NULL
||
!
new_transport
->
state
.
active
)
!
new_transport
->
active
)
new_transport
=
asoc
->
peer
.
active_path
;
/* Change packets if necessary. */
...
...
@@ -1404,7 +1404,7 @@ static void sctp_check_transmitted(sctp_outqueue_t *q,
/* Mark the destination transport address as
* active if it is not so marked.
*/
if
(
!
transport
->
state
.
active
)
{
if
(
!
transport
->
active
)
{
sctp_assoc_control_transport
(
transport
->
asoc
,
transport
,
...
...
net/sctp/primitive.c
View file @
63c6e5b3
...
...
@@ -38,6 +38,7 @@
* La Monte H.P. Yarroll <piggy@acm.org>
* Narasimha Budihal <narasimha@refcode.org>
* Karl Knutson <karl@athena.chicago.il.us>
* Ardelle Fan <ardelle.fan@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -181,6 +182,28 @@ DECLARE_PRIMITIVE(ABORT);
DECLARE_PRIMITIVE
(
SEND
);
/* 10.1 ULP-to-SCTP
* J) Request Heartbeat
*
* Format: REQUESTHEARTBEAT(association id, destination transport address)
*
* -> result
*
* Instructs the local endpoint to perform a HeartBeat on the specified
* destination transport address of the given association. The returned
* result should indicate whether the transmission of the HEARTBEAT
* chunk to the destination address is successful.
*
* Mandatory attributes:
*
* o association id - local handle to the SCTP association
*
* o destination transport address - the transport address of the
* asociation on which a heartbeat should be issued.
*/
DECLARE_PRIMITIVE
(
REQUESTHEARTBEAT
);
/* COMMENT BUG. Find out where this is mentioned in the spec. */
int
sctp_other_icmp_unreachfrag
(
sctp_association_t
*
asoc
,
void
*
arg
)
{
...
...
net/sctp/sm_sideeffect.c
View file @
63c6e5b3
...
...
@@ -41,6 +41,7 @@
* Dajiang Zhang <dajiang.zhang@nokia.com>
* Daisy Chang <daisyc@us.ibm.com>
* Sridhar Samudrala <sri@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -73,6 +74,8 @@ static void sctp_cmd_process_init(sctp_cmd_seq_t *, sctp_association_t *asoc,
sctp_init_chunk_t
*
peer_init
,
int
priority
);
static
void
sctp_cmd_hb_timers_start
(
sctp_cmd_seq_t
*
,
sctp_association_t
*
);
static
void
sctp_cmd_hb_timers_update
(
sctp_cmd_seq_t
*
,
sctp_association_t
*
,
sctp_transport_t
*
);
static
void
sctp_cmd_set_bind_addrs
(
sctp_cmd_seq_t
*
,
sctp_association_t
*
,
sctp_bind_addr_t
*
);
static
void
sctp_cmd_transport_reset
(
sctp_cmd_seq_t
*
,
sctp_association_t
*
,
...
...
@@ -193,6 +196,7 @@ int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
/* BUG--we should now recover some memory, probably by
* reneging...
*/
error
=
-
ENOMEM
;
break
;
case
SCTP_DISPOSITION_DELETE_TCB
:
...
...
@@ -560,6 +564,11 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
case
SCTP_CMD_HB_TIMERS_START
:
sctp_cmd_hb_timers_start
(
commands
,
asoc
);
break
;
case
SCTP_CMD_HB_TIMERS_UPDATE
:
t
=
command
->
obj
.
transport
;
sctp_cmd_hb_timers_update
(
commands
,
asoc
,
t
);
break
;
case
SCTP_CMD_REPORT_ERROR
:
error
=
command
->
obj
.
error
;
...
...
@@ -978,7 +987,7 @@ static void sctp_do_8_2_transport_strike(sctp_association_t *asoc,
*/
asoc
->
overall_error_count
++
;
if
(
transport
->
state
.
active
&&
if
(
transport
->
active
&&
(
transport
->
error_count
++
>=
transport
->
error_threshold
))
{
SCTP_DEBUG_PRINTK
(
"transport_strike: transport "
"IP:%d.%d.%d.%d failed.
\n
"
,
...
...
@@ -1096,6 +1105,16 @@ static void sctp_cmd_hb_timers_start(sctp_cmd_seq_t *cmds,
}
}
/* Helper function to update the heartbeat timer. */
static
void
sctp_cmd_hb_timers_update
(
sctp_cmd_seq_t
*
cmds
,
sctp_association_t
*
asoc
,
sctp_transport_t
*
t
)
{
/* Update the heartbeat timer. */
if
(
!
mod_timer
(
&
t
->
hb_timer
,
t
->
hb_interval
+
t
->
rto
+
jiffies
))
sctp_transport_hold
(
t
);
}
/* Helper function to break out SCTP_CMD_SET_BIND_ADDR handling. */
void
sctp_cmd_set_bind_addrs
(
sctp_cmd_seq_t
*
cmds
,
sctp_association_t
*
asoc
,
sctp_bind_addr_t
*
bp
)
...
...
@@ -1131,7 +1150,7 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
/* Mark the destination transport address as active if it is not so
* marked.
*/
if
(
!
t
->
state
.
active
)
if
(
!
t
->
active
)
sctp_assoc_control_transport
(
asoc
,
t
,
SCTP_TRANSPORT_UP
,
SCTP_HEARTBEAT_SUCCESS
);
...
...
@@ -1154,10 +1173,6 @@ static void sctp_cmd_transport_reset(sctp_cmd_seq_t *cmds,
/* Mark one strike against a transport. */
sctp_do_8_2_transport_strike
(
asoc
,
t
);
/* Update the heartbeat timer. */
if
(
!
mod_timer
(
&
t
->
hb_timer
,
t
->
hb_interval
+
t
->
rto
+
jiffies
))
sctp_transport_hold
(
t
);
}
/* Helper function to process the process SACK command. */
...
...
net/sctp/sm_statefuns.c
View file @
63c6e5b3
...
...
@@ -664,6 +664,38 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const sctp_endpoint_t *ep,
return
SCTP_DISPOSITION_NOMEM
;
}
/* Generate and sendout a heartbeat packet. */
sctp_disposition_t
sctp_sf_heartbeat
(
const
sctp_endpoint_t
*
ep
,
const
sctp_association_t
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
{
sctp_transport_t
*
transport
=
(
sctp_transport_t
*
)
arg
;
sctp_chunk_t
*
reply
;
sctp_sender_hb_info_t
hbinfo
;
size_t
paylen
=
0
;
hbinfo
.
param_hdr
.
type
=
SCTP_PARAM_HEARTBEAT_INFO
;
hbinfo
.
param_hdr
.
length
=
htons
(
sizeof
(
sctp_sender_hb_info_t
));
hbinfo
.
daddr
=
transport
->
ipaddr
;
hbinfo
.
sent_at
=
jiffies
;
/* Set rto_pending indicating that an RTT measurement
* is started with this heartbeat chunk.
*/
transport
->
rto_pending
=
1
;
/* Send a heartbeat to our peer. */
paylen
=
sizeof
(
sctp_sender_hb_info_t
);
reply
=
sctp_make_heartbeat
(
asoc
,
transport
,
&
hbinfo
,
paylen
);
if
(
!
reply
)
return
SCTP_DISPOSITION_NOMEM
;
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
SCTP_CHUNK
(
reply
));
return
SCTP_DISPOSITION_CONSUME
;
}
/* Generate a HEARTBEAT packet on the given transport. */
sctp_disposition_t
sctp_sf_sendbeat_8_3
(
const
sctp_endpoint_t
*
ep
,
const
sctp_association_t
*
asoc
,
...
...
@@ -672,9 +704,6 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const sctp_endpoint_t *ep,
sctp_cmd_seq_t
*
commands
)
{
sctp_transport_t
*
transport
=
(
sctp_transport_t
*
)
arg
;
sctp_chunk_t
*
reply
;
sctp_sender_hb_info_t
hbinfo
;
size_t
paylen
=
0
;
if
(
asoc
->
overall_error_count
>=
asoc
->
overall_error_threshold
)
{
/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
...
...
@@ -689,34 +718,21 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const sctp_endpoint_t *ep,
* HEARTBEAT is sent (see Section 8.3).
*/
hbinfo
.
param_hdr
.
type
=
SCTP_PARAM_HEARTBEAT_INFO
;
hbinfo
.
param_hdr
.
length
=
htons
(
sizeof
(
sctp_sender_hb_info_t
));
hbinfo
.
daddr
=
transport
->
ipaddr
;
hbinfo
.
sent_at
=
jiffies
;
/* Set rto_pending indicating that an RTT measurement is started
* with this heartbeat chunk.
*/
transport
->
rto_pending
=
1
;
/* Send a heartbeat to our peer. */
paylen
=
sizeof
(
sctp_sender_hb_info_t
);
reply
=
sctp_make_heartbeat
(
asoc
,
transport
,
&
hbinfo
,
paylen
);
if
(
!
reply
)
goto
nomem
;
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
SCTP_CHUNK
(
reply
));
/* Set transport error counter and association error counter
* when sending heartbeat.
*/
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_TRANSPORT_RESET
,
if
(
transport
->
hb_allowed
)
{
if
(
SCTP_DISPOSITION_NOMEM
==
sctp_sf_heartbeat
(
ep
,
asoc
,
type
,
arg
,
commands
))
return
SCTP_DISPOSITION_NOMEM
;
/* Set transport error counter and association error counter
* when sending heartbeat.
*/
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_TRANSPORT_RESET
,
SCTP_TRANSPORT
(
transport
));
}
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_HB_TIMERS_UPDATE
,
SCTP_TRANSPORT
(
transport
));
return
SCTP_DISPOSITION_CONSUME
;
nomem:
return
SCTP_DISPOSITION_NOMEM
;
}
/*
...
...
@@ -3656,6 +3672,39 @@ sctp_disposition_t sctp_sf_shutdown_ack_sent_prm_abort(
return
sctp_sf_shutdown_sent_prm_abort
(
ep
,
asoc
,
type
,
arg
,
commands
);
}
/*
* Process the REQUESTHEARTBEAT primitive
*
* 10.1 ULP-to-SCTP
* J) Request Heartbeat
*
* Format: REQUESTHEARTBEAT(association id, destination transport address)
*
* -> result
*
* Instructs the local endpoint to perform a HeartBeat on the specified
* destination transport address of the given association. The returned
* result should indicate whether the transmission of the HEARTBEAT
* chunk to the destination address is successful.
*
* Mandatory attributes:
*
* o association id - local handle to the SCTP association
*
* o destination transport address - the transport address of the
* asociation on which a heartbeat should be issued.
*/
sctp_disposition_t
sctp_sf_do_prm_requestheartbeat
(
const
sctp_endpoint_t
*
ep
,
const
sctp_association_t
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
{
return
sctp_sf_heartbeat
(
ep
,
asoc
,
type
,
(
sctp_transport_t
*
)
arg
,
commands
);
}
/*
* Ignore the primitive event
*
...
...
net/sctp/sm_statetable.c
View file @
63c6e5b3
...
...
@@ -39,6 +39,7 @@
* Jon Grimm <jgrimm@us.ibm.com>
* Hui Huang <hui.huang@nokia.com>
* Daisy Chang <daisyc@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -706,21 +707,28 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = {
/* SCTP_STATE_EMPTY */
\
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */
\
{.fn = sctp_sf_
not_impl, .name = "sctp_sf_not_impl
"}, \
{.fn = sctp_sf_
bug, .name = "sctp_sf_bug
"}, \
/* SCTP_STATE_COOKIE_WAIT */
\
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
{.fn = sctp_sf_do_prm_requestheartbeat, \
.name = "sctp_sf_do_prm_requestheartbeat"}, \
/* SCTP_STATE_COOKIE_ECHOED */
\
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
{.fn = sctp_sf_do_prm_requestheartbeat, \
.name = "sctp_sf_do_prm_requestheartbeat"}, \
/* SCTP_STATE_ESTABLISHED */
\
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
{.fn = sctp_sf_do_prm_requestheartbeat, \
.name = "sctp_sf_do_prm_requestheartbeat"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */
\
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
{.fn = sctp_sf_do_prm_requestheartbeat, \
.name = "sctp_sf_do_prm_requestheartbeat"}, \
/* SCTP_STATE_SHUTDOWN_SENT */
\
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
{.fn = sctp_sf_do_prm_requestheartbeat, \
.name = "sctp_sf_do_prm_requestheartbeat"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */
\
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
{.fn = sctp_sf_do_prm_requestheartbeat, \
.name = "sctp_sf_do_prm_requestheartbeat"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */
\
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
{.fn = sctp_sf_do_prm_requestheartbeat, \
.name = "sctp_sf_do_prm_requestheartbeat"}, \
}
/* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */
#define TYPE_SCTP_PRIMITIVE_GETSRTTREPORT { \
...
...
net/sctp/socket.c
View file @
63c6e5b3
...
...
@@ -1252,6 +1252,67 @@ static inline int sctp_setsockopt_autoclose(struct sock *sk, char *optval,
return
0
;
}
static
inline
int
sctp_setsockopt_set_peer_addr_params
(
struct
sock
*
sk
,
char
*
optval
,
int
optlen
)
{
struct
sctp_paddrparams
params
;
sctp_association_t
*
asoc
;
sockaddr_storage_t
*
addr
;
sctp_transport_t
*
trans
;
int
error
;
if
(
optlen
!=
sizeof
(
struct
sctp_paddrparams
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
params
,
optval
,
optlen
))
return
-
EFAULT
;
asoc
=
sctp_id2assoc
(
sk
,
params
.
spp_assoc_id
);
if
(
!
asoc
)
return
-
EINVAL
;
addr
=
(
sockaddr_storage_t
*
)
&
(
params
.
spp_address
);
trans
=
sctp_assoc_lookup_paddr
(
asoc
,
addr
);
if
(
!
trans
)
return
-
ENOENT
;
/* Applications can enable or disable heartbeats for any peer address
* of an association, modify an address's heartbeat interval, force a
* heartbeat to be sent immediately, and adjust the address's maximum
* number of retransmissions sent before an address is considered
* unreachable.
*
* The value of the heartbeat interval, in milliseconds. A value of
* UINT32_MAX (4294967295), when modifying the parameter, specifies
* that a heartbeat should be sent immediately to the peer address,
* and the current interval should remain unchanged.
*/
if
(
0xffffffff
==
params
.
spp_hbinterval
)
{
error
=
sctp_primitive_REQUESTHEARTBEAT
(
asoc
,
trans
);
if
(
error
)
return
error
;
}
else
{
/* The value of the heartbeat interval, in milliseconds. A value of 0,
* when modifying the parameter, specifies that the heartbeat on this
* address should be disabled.
*/
if
(
params
.
spp_hbinterval
)
{
trans
->
hb_allowed
=
1
;
trans
->
hb_interval
=
params
.
spp_hbinterval
*
HZ
/
1000
;
}
else
trans
->
hb_allowed
=
0
;
}
/* spp_pathmaxrxt contains the maximum number of retransmissions
* before this address shall be considered unreachable.
*/
trans
->
error_threshold
=
params
.
spp_pathmaxrxt
;
return
0
;
}
/* API 6.2 setsockopt(), getsockopt()
*
* Applications use setsockopt() and getsockopt() to set or retrieve
...
...
@@ -1342,6 +1403,11 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
retval
=
sctp_setsockopt_autoclose
(
sk
,
optval
,
optlen
);
break
;
case
SCTP_SET_PEER_ADDR_PARAMS
:
retval
=
sctp_setsockopt_set_peer_addr_params
(
sk
,
optval
,
optlen
);
break
;
default:
retval
=
-
ENOPROTOOPT
;
break
;
...
...
@@ -1503,28 +1569,26 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
if
(
len
!=
sizeof
(
status
))
{
retval
=
-
EINVAL
;
goto
out
_nounlock
;
goto
out
;
}
if
(
copy_from_user
(
&
status
,
optval
,
sizeof
(
status
)))
{
retval
=
-
EFAULT
;
goto
out
_nounlock
;
goto
out
;
}
sctp_lock_sock
(
sk
);
associd
=
status
.
sstat_assoc_id
;
if
((
SCTP_SOCKET_UDP_HIGH_BANDWIDTH
!=
sctp_sk
(
sk
)
->
type
)
&&
associd
)
{
assoc
=
sctp_id2assoc
(
sk
,
associd
);
if
(
!
assoc
)
{
retval
=
-
EINVAL
;
goto
out
_unlock
;
goto
out
;
}
}
else
{
ep
=
sctp_sk
(
sk
)
->
ep
;
if
(
list_empty
(
&
ep
->
asocs
))
{
retval
=
-
EINVAL
;
goto
out
_unlock
;
goto
out
;
}
assoc
=
list_entry
(
ep
->
asocs
.
next
,
sctp_association_t
,
asocs
);
...
...
@@ -1543,7 +1607,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
status
.
sstat_primary
.
spinfo_assoc_id
=
sctp_assoc2id
(
transport
->
asoc
);
memcpy
(
&
status
.
sstat_primary
.
spinfo_address
,
&
(
transport
->
ipaddr
),
sizeof
(
sockaddr_storage_t
));
status
.
sstat_primary
.
spinfo_state
=
transport
->
state
.
active
;
status
.
sstat_primary
.
spinfo_state
=
transport
->
active
;
status
.
sstat_primary
.
spinfo_cwnd
=
transport
->
cwnd
;
status
.
sstat_primary
.
spinfo_srtt
=
transport
->
srtt
;
status
.
sstat_primary
.
spinfo_rto
=
transport
->
rto
;
...
...
@@ -1551,7 +1615,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
if
(
put_user
(
len
,
optlen
))
{
retval
=
-
EFAULT
;
goto
out
_unlock
;
goto
out
;
}
SCTP_DEBUG_PRINTK
(
"sctp_getsockopt_sctp_status(%d): %d %d %p
\n
"
,
...
...
@@ -1560,13 +1624,10 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
if
(
copy_to_user
(
optval
,
&
status
,
len
))
{
retval
=
-
EFAULT
;
goto
out
_unlock
;
goto
out
;
}
out_unlock:
sctp_release_sock
(
sk
);
out_nounlock:
out:
return
(
retval
);
}
...
...
@@ -1684,25 +1745,23 @@ static inline int sctp_getsockopt_peeloff(struct sock *sk, int len, char *optval
if
(
copy_from_user
(
&
peeloff
,
optval
,
len
))
return
-
EFAULT
;
sctp_lock_sock
(
sk
);
assoc
=
sctp_id2assoc
(
sk
,
peeloff
.
associd
);
if
(
NULL
==
assoc
)
{
retval
=
-
EINVAL
;
goto
out
_unlock
;
goto
out
;
}
SCTP_DEBUG_PRINTK
(
"%s: sk: %p assoc: %p
\n
"
,
__FUNCTION__
,
sk
,
assoc
);
retval
=
sctp_do_peeloff
(
assoc
,
&
newsock
);
if
(
retval
<
0
)
goto
out
_unlock
;
goto
out
;
/* Map the socket to an unused fd that can be returned to the user. */
retval
=
sock_map_fd
(
newsock
);
if
(
retval
<
0
)
{
sock_release
(
newsock
);
goto
out
_unlock
;
goto
out
;
}
SCTP_DEBUG_PRINTK
(
"%s: sk: %p assoc: %p newsk: %p sd: %d
\n
"
,
...
...
@@ -1713,11 +1772,54 @@ static inline int sctp_getsockopt_peeloff(struct sock *sk, int len, char *optval
if
(
copy_to_user
(
optval
,
&
peeloff
,
len
))
retval
=
-
EFAULT
;
out_unlock:
sctp_release_sock
(
sk
);
out:
return
retval
;
}
static
inline
int
sctp_getsockopt_get_peer_addr_params
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
struct
sctp_paddrparams
params
;
sctp_association_t
*
asoc
;
sockaddr_storage_t
*
addr
;
sctp_transport_t
*
trans
;
if
(
len
!=
sizeof
(
struct
sctp_paddrparams
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
params
,
optval
,
*
optlen
))
return
-
EFAULT
;
asoc
=
sctp_id2assoc
(
sk
,
params
.
spp_assoc_id
);
if
(
!
asoc
)
return
-
EINVAL
;
addr
=
(
sockaddr_storage_t
*
)
&
(
params
.
spp_address
);
trans
=
sctp_assoc_lookup_paddr
(
asoc
,
addr
);
if
(
!
trans
)
return
-
ENOENT
;
/* The value of the heartbeat interval, in milliseconds. A value of 0,
* when modifying the parameter, specifies that the heartbeat on this
* address should be disabled.
*/
if
(
!
trans
->
hb_allowed
)
params
.
spp_hbinterval
=
0
;
else
params
.
spp_hbinterval
=
trans
->
hb_interval
*
1000
/
HZ
;
/* spp_pathmaxrxt contains the maximum number of retransmissions
* before this address shall be considered unreachable.
*/
params
.
spp_pathmaxrxt
=
trans
->
error_threshold
;
if
(
copy_to_user
(
optval
,
&
params
,
len
))
return
-
EFAULT
;
*
optlen
=
len
;
return
0
;
}
SCTP_STATIC
int
sctp_getsockopt
(
struct
sock
*
sk
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
)
{
...
...
@@ -1748,6 +1850,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
if
(
get_user
(
len
,
optlen
))
return
-
EFAULT
;
sctp_lock_sock
(
sk
);
switch
(
optname
)
{
case
SCTP_STATUS
:
retval
=
sctp_getsockopt_sctp_status
(
sk
,
len
,
optval
,
optlen
);
...
...
@@ -1770,11 +1874,17 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
retval
=
sctp_getsockopt_peeloff
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_GET_PEER_ADDR_PARAMS
:
retval
=
sctp_getsockopt_get_peer_addr_params
(
sk
,
len
,
optval
,
optlen
);
break
;
default:
retval
=
-
ENOPROTOOPT
;
break
;
};
sctp_release_sock
(
sk
);
return
retval
;
}
...
...
net/sctp/transport.c
View file @
63c6e5b3
...
...
@@ -104,8 +104,8 @@ sctp_transport_t *sctp_transport_init(sctp_transport_t *peer,
peer
->
last_time_used
=
jiffies
;
peer
->
last_time_ecne_reduced
=
jiffies
;
peer
->
state
.
active
=
1
;
peer
->
state
.
hb_allowed
=
0
;
peer
->
active
=
1
;
peer
->
hb_allowed
=
0
;
/* Initialize the default path max_retrans. */
peer
->
max_retrans
=
proto
->
max_retrans_path
;
...
...
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