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
1bafb09e
Commit
1bafb09e
authored
Mar 25, 2003
by
Jon Grimm
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[SCTP] Add SEND_FAILED support. (Ardelle Fan)
parent
9850a96f
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
79 additions
and
53 deletions
+79
-53
include/net/sctp/structs.h
include/net/sctp/structs.h
+3
-0
net/sctp/outqueue.c
net/sctp/outqueue.c
+21
-2
net/sctp/sm_sideeffect.c
net/sctp/sm_sideeffect.c
+17
-36
net/sctp/sm_statefuns.c
net/sctp/sm_statefuns.c
+38
-15
No files found.
include/net/sctp/structs.h
View file @
1bafb09e
...
...
@@ -872,6 +872,9 @@ struct sctp_outq {
unsigned
out_qlen
;
/* Total length of queued data chunks. */
/* Error of send failed, may used in SCTP_SEND_FAILED event. */
unsigned
error
;
/* These are control chunks we want to send. */
struct
sk_buff_head
control
;
...
...
net/sctp/outqueue.c
View file @
1bafb09e
...
...
@@ -138,13 +138,13 @@ void sctp_outq_init(sctp_association_t *asoc, struct sctp_outq *q)
}
/* Free the outqueue structure and any related pending chunks.
* FIXME: Add SEND_FAILED support.
*/
void
sctp_outq_teardown
(
struct
sctp_outq
*
q
)
{
struct
sctp_transport
*
transport
;
struct
list_head
*
lchunk
,
*
pos
,
*
temp
;
sctp_chunk_t
*
chunk
;
struct
sctp_ulpevent
*
ev
;
/* Throw away unacknowledged chunks. */
list_for_each
(
pos
,
&
q
->
asoc
->
peer
.
transport_addr_list
)
{
...
...
@@ -152,6 +152,14 @@ void sctp_outq_teardown(struct sctp_outq *q)
while
((
lchunk
=
sctp_list_dequeue
(
&
transport
->
transmitted
)))
{
chunk
=
list_entry
(
lchunk
,
sctp_chunk_t
,
transmitted_list
);
/* Generate a SEND FAILED event. */
ev
=
sctp_ulpevent_make_send_failed
(
q
->
asoc
,
chunk
,
SCTP_DATA_SENT
,
q
->
error
,
GFP_ATOMIC
);
if
(
ev
)
sctp_ulpq_tail_event
(
&
q
->
asoc
->
ulpq
,
ev
);
sctp_free_chunk
(
chunk
);
}
}
...
...
@@ -171,8 +179,19 @@ void sctp_outq_teardown(struct sctp_outq *q)
}
/* Throw away any leftover data chunks. */
while
((
chunk
=
sctp_outq_dequeue_data
(
q
)))
while
((
chunk
=
sctp_outq_dequeue_data
(
q
)))
{
/* Generate a SEND FAILED event. */
ev
=
sctp_ulpevent_make_send_failed
(
q
->
asoc
,
chunk
,
SCTP_DATA_UNSENT
,
q
->
error
,
GFP_ATOMIC
);
if
(
ev
)
sctp_ulpq_tail_event
(
&
q
->
asoc
->
ulpq
,
ev
);
sctp_free_chunk
(
chunk
);
}
q
->
error
=
0
;
/* Throw away any leftover control chunks. */
while
((
chunk
=
(
sctp_chunk_t
*
)
skb_dequeue
(
&
q
->
control
)))
...
...
net/sctp/sm_sideeffect.c
View file @
1bafb09e
...
...
@@ -133,7 +133,7 @@ static void sctp_do_ecn_cwr_work(sctp_association_t *asoc,
}
/* Generate SACK if necessary. We call this at the end of a packet. */
int
sctp_gen_sack
(
struct
sctp_association
*
asoc
,
int
force
,
int
sctp_gen_sack
(
struct
sctp_association
*
asoc
,
int
force
,
sctp_cmd_seq_t
*
commands
)
{
__u32
ctsn
,
max_tsn_seen
;
...
...
@@ -410,7 +410,8 @@ static void sctp_do_8_2_transport_strike(sctp_association_t *asoc,
/* Worker routine to handle INIT command failure. */
static
void
sctp_cmd_init_failed
(
sctp_cmd_seq_t
*
commands
,
sctp_association_t
*
asoc
)
sctp_association_t
*
asoc
,
unsigned
error
)
{
struct
sctp_ulpevent
*
event
;
...
...
@@ -421,46 +422,27 @@ static void sctp_cmd_init_failed(sctp_cmd_seq_t *commands,
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_EVENT_ULP
,
SCTP_ULPEVENT
(
event
));
/* FIXME: We need to handle data possibly either
* sent via COOKIE-ECHO bundling or just waiting in
* the transmit queue, if the user has enabled
* SEND_FAILED notifications.
*/
/* SEND_FAILED sent later when cleaning up the association. */
asoc
->
outqueue
.
error
=
error
;
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_DELETE_TCB
,
SCTP_NULL
());
}
/* Worker routine to handle SCTP_CMD_ASSOC_FAILED. */
static
void
sctp_cmd_assoc_failed
(
sctp_cmd_seq_t
*
commands
,
s
ctp_association_t
*
asoc
,
s
truct
sctp_association
*
asoc
,
sctp_event_t
event_type
,
sctp_subtype_t
subtype
,
sctp_chunk_t
*
chunk
)
struct
sctp_chunk
*
chunk
,
unsigned
error
)
{
struct
sctp_ulpevent
*
event
;
__u16
error
=
0
;
switch
(
event_type
)
{
case
SCTP_EVENT_T_PRIMITIVE
:
if
(
SCTP_PRIMITIVE_ABORT
==
subtype
.
primitive
)
error
=
SCTP_ERROR_USER_ABORT
;
break
;
case
SCTP_EVENT_T_CHUNK
:
if
(
chunk
&&
(
SCTP_CID_ABORT
==
chunk
->
chunk_hdr
->
type
)
&&
(
ntohs
(
chunk
->
chunk_hdr
->
length
)
>=
(
sizeof
(
struct
sctp_chunkhdr
)
+
sizeof
(
struct
sctp_errhdr
))))
{
error
=
((
sctp_errhdr_t
*
)
chunk
->
skb
->
data
)
->
cause
;
}
break
;
default:
break
;
}
/* Cancel any partial delivery in progress. */
sctp_ulpq_abort_pd
(
&
asoc
->
ulpq
,
GFP_ATOMIC
);
event
=
sctp_ulpevent_make_assoc_change
(
asoc
,
0
,
SCTP_COMM_LOST
,
error
,
0
,
0
,
GFP_ATOMIC
);
(
__u16
)
error
,
0
,
0
,
GFP_ATOMIC
);
if
(
event
)
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_EVENT_ULP
,
SCTP_ULPEVENT
(
event
));
...
...
@@ -468,9 +450,8 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands,
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_NEW_STATE
,
SCTP_STATE
(
SCTP_STATE_CLOSED
));
/* FIXME: We need to handle data that could not be sent or was not
* acked, if the user has enabled SEND_FAILED notifications.
*/
/* SEND_FAILED sent later when cleaning up the association. */
asoc
->
outqueue
.
error
=
error
;
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_DELETE_TCB
,
SCTP_NULL
());
}
...
...
@@ -640,9 +621,9 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, sctp_association_t *asoc,
asoc
->
state_timestamp
=
jiffies
;
if
((
SCTP_STATE_ESTABLISHED
==
asoc
->
state
)
||
(
SCTP_STATE_CLOSED
==
asoc
->
state
))
{
(
SCTP_STATE_CLOSED
==
asoc
->
state
))
{
/* Wake up any processes waiting in the asoc's wait queue in
* sctp_wait_for_connect() or sctp_wait_for_sndbuf().
* sctp_wait_for_connect() or sctp_wait_for_sndbuf().
*/
if
(
waitqueue_active
(
&
asoc
->
wait
))
wake_up_interruptible
(
&
asoc
->
wait
);
...
...
@@ -1077,12 +1058,12 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
break
;
case
SCTP_CMD_INIT_FAILED
:
sctp_cmd_init_failed
(
commands
,
asoc
);
sctp_cmd_init_failed
(
commands
,
asoc
,
cmd
->
obj
.
u32
);
break
;
case
SCTP_CMD_ASSOC_FAILED
:
sctp_cmd_assoc_failed
(
commands
,
asoc
,
event_type
,
subtype
,
chunk
);
subtype
,
chunk
,
cmd
->
obj
.
u32
);
break
;
case
SCTP_CMD_COUNTER_INC
:
...
...
@@ -1094,7 +1075,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
break
;
case
SCTP_CMD_REPORT_DUP
:
sctp_tsnmap_mark_dup
(
&
asoc
->
peer
.
tsn_map
,
sctp_tsnmap_mark_dup
(
&
asoc
->
peer
.
tsn_map
,
cmd
->
obj
.
u32
);
break
;
...
...
net/sctp/sm_statefuns.c
View file @
1bafb09e
...
...
@@ -729,7 +729,8 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const sctp_endpoint_t *ep,
if
(
asoc
->
overall_error_count
>=
asoc
->
overall_error_threshold
)
{
/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_NULL
());
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_U32
(
SCTP_ERROR_NO_ERROR
));
SCTP_INC_STATS
(
SctpAborteds
);
SCTP_DEC_STATS
(
SctpCurrEstab
);
return
SCTP_DISPOSITION_DELETE_TCB
;
...
...
@@ -1772,14 +1773,16 @@ sctp_disposition_t sctp_sf_cookie_echoed_err(const sctp_endpoint_t *ep,
sctp_chunk_t
*
chunk
=
arg
;
sctp_errhdr_t
*
err
;
err
=
(
sctp_errhdr_t
*
)(
chunk
->
skb
->
data
);
/* If we have gotten too many failures, give up. */
if
(
1
+
asoc
->
counters
[
SCTP_COUNTER_INIT_ERROR
]
>
asoc
->
max_init_attempts
)
{
/* INIT_FAILED will issue an ulpevent. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_FAILED
,
SCTP_NULL
());
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_FAILED
,
SCTP_U32
(
err
->
cause
));
return
SCTP_DISPOSITION_DELETE_TCB
;
}
err
=
(
sctp_errhdr_t
*
)(
chunk
->
skb
->
data
);
/* Process the error here */
switch
(
err
->
cause
)
{
...
...
@@ -1834,7 +1837,8 @@ sctp_disposition_t sctp_sf_do_5_2_6_stale(const sctp_endpoint_t *ep,
attempts
=
asoc
->
counters
[
SCTP_COUNTER_INIT_ERROR
]
+
1
;
if
(
attempts
>=
asoc
->
max_init_attempts
)
{
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_FAILED
,
SCTP_NULL
());
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_FAILED
,
SCTP_U32
(
SCTP_ERROR_STALE_COOKIE
));
return
SCTP_DISPOSITION_DELETE_TCB
;
}
...
...
@@ -1936,12 +1940,18 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const sctp_endpoint_t *ep,
sctp_cmd_seq_t
*
commands
)
{
sctp_chunk_t
*
chunk
=
arg
;
__u16
error
=
SCTP_ERROR_NO_ERROR
;
if
(
!
sctp_vtag_verify_either
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
if
(
chunk
&&
(
ntohs
(
chunk
->
chunk_hdr
->
length
)
>=
(
sizeof
(
struct
sctp_chunkhdr
)
+
sizeof
(
struct
sctp_errhdr
))))
error
=
((
sctp_errhdr_t
*
)
chunk
->
skb
->
data
)
->
cause
;
/* ASSOC_FAILED will DELETE_TCB. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_
NULL
(
));
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_
U32
(
error
));
SCTP_INC_STATS
(
SctpAborteds
);
SCTP_DEC_STATS
(
SctpCurrEstab
);
...
...
@@ -1961,6 +1971,7 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const sctp_endpoint_t *ep,
sctp_cmd_seq_t
*
commands
)
{
sctp_chunk_t
*
chunk
=
arg
;
__u16
error
=
SCTP_ERROR_NO_ERROR
;
if
(
!
sctp_vtag_verify_either
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
...
...
@@ -1971,10 +1982,14 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const sctp_endpoint_t *ep,
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_TIMER_STOP
,
SCTP_TO
(
SCTP_EVENT_TIMEOUT_T1_INIT
));
if
(
chunk
&&
(
ntohs
(
chunk
->
chunk_hdr
->
length
)
>=
(
sizeof
(
struct
sctp_chunkhdr
)
+
sizeof
(
struct
sctp_errhdr
))))
error
=
((
sctp_errhdr_t
*
)
chunk
->
skb
->
data
)
->
cause
;
/* CMD_INIT_FAILED will DELETE_TCB. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_FAILED
,
SCTP_
NULL
(
));
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_FAILED
,
SCTP_
U32
(
error
));
/* BUG? This does not look complete... */
return
SCTP_DISPOSITION_ABORT
;
}
...
...
@@ -2381,7 +2396,8 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const sctp_endpoint_t *ep,
* processing the rest of the chunks in the packet.
*/
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_DISCARD_PACKET
,
SCTP_NULL
());
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_NULL
());
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_U32
(
SCTP_ERROR_NO_DATA
));
SCTP_INC_STATS
(
SctpAborteds
);
SCTP_DEC_STATS
(
SctpCurrEstab
);
return
SCTP_DISPOSITION_CONSUME
;
...
...
@@ -2596,7 +2612,8 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const sctp_endpoint_t *ep,
* processing the rest of the chunks in the packet.
*/
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_DISCARD_PACKET
,
SCTP_NULL
());
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_NULL
());
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_U32
(
SCTP_ERROR_NO_DATA
));
SCTP_INC_STATS
(
SctpAborteds
);
SCTP_DEC_STATS
(
SctpCurrEstab
);
return
SCTP_DISPOSITION_CONSUME
;
...
...
@@ -3547,7 +3564,8 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(const sctp_endpoint_t *ep,
*/
/* Delete the established association. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_NULL
());
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_U32
(
SCTP_ERROR_USER_ABORT
));
SCTP_INC_STATS
(
SctpAborteds
);
SCTP_DEC_STATS
(
SctpCurrEstab
);
...
...
@@ -3686,7 +3704,8 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(const sctp_endpoint_t *ep,
*/
/* Delete the established association. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_FAILED
,
SCTP_NULL
());
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_FAILED
,
SCTP_U32
(
SCTP_ERROR_USER_ABORT
));
return
retval
;
}
...
...
@@ -4012,7 +4031,8 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const sctp_endpoint_t *ep,
if
(
asoc
->
overall_error_count
>=
asoc
->
overall_error_threshold
)
{
/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_NULL
());
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_U32
(
SCTP_ERROR_NO_ERROR
));
SCTP_INC_STATS
(
SctpAborteds
);
SCTP_DEC_STATS
(
SctpCurrEstab
);
return
SCTP_DISPOSITION_DELETE_TCB
;
...
...
@@ -4147,7 +4167,8 @@ sctp_disposition_t sctp_sf_t1_timer_expire(const sctp_endpoint_t *ep,
SCTP_TO
(
timer
));
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
SCTP_CHUNK
(
repl
));
}
else
{
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_FAILED
,
SCTP_NULL
());
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_FAILED
,
SCTP_U32
(
SCTP_ERROR_NO_ERROR
));
return
SCTP_DISPOSITION_DELETE_TCB
;
}
...
...
@@ -4181,7 +4202,8 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const sctp_endpoint_t *ep,
SCTP_DEBUG_PRINTK
(
"Timer T2 expired.
\n
"
);
if
(
asoc
->
overall_error_count
>=
asoc
->
overall_error_threshold
)
{
/* Note: CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_NULL
());
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_U32
(
SCTP_ERROR_NO_ERROR
));
SCTP_INC_STATS
(
SctpAborteds
);
SCTP_DEC_STATS
(
SctpCurrEstab
);
return
SCTP_DISPOSITION_DELETE_TCB
;
...
...
@@ -4244,7 +4266,8 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const sctp_endpoint_t *ep,
goto
nomem
;
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
SCTP_CHUNK
(
reply
));
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_NULL
());
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_U32
(
SCTP_ERROR_NO_ERROR
));
return
SCTP_DISPOSITION_DELETE_TCB
;
nomem:
...
...
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